Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,6 @@ export const ReduxActionTypes = {
FETCH_API_KEYS_SUCCESS: "FETCH_API_KEYS_SUCCESS",
MOVE_TO_FOLDER2_SUCCESS: "MOVE_TO_FOLDER2_SUCCESS",

/* workspace RELATED */
FETCH_WORKSPACES_INIT: "FETCH_WORKSPACES_INIT",
FETCH_WORKSPACES_SUCCESS: "FETCH_WORKSPACES_SUCCESS",



/* plugin RELATED */
FETCH_DATA_SOURCE_TYPES: "FETCH_DATA_SOURCE_TYPES",
FETCH_DATA_SOURCE_TYPES_SUCCESS: "FETCH_DATA_SOURCE_TYPES_SUCCESS",
Expand Down
13 changes: 12 additions & 1 deletion client/packages/lowcoder/src/pages/common/WorkspaceSection.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React, { useEffect, useRef } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import styled from 'styled-components';
import { Input, Pagination, Spin } from 'antd';
Expand Down Expand Up @@ -198,8 +198,19 @@ export default function WorkspaceSectionComponent({
handleSearchChange,
handlePageChange,
pageSize,
refetch,
} = useWorkspaceManager({});

// Refetch list when orgs change (create/delete)
const orgsCount = user.orgs.length;
const prevOrgsCount = useRef(orgsCount);
useEffect(() => {
if (prevOrgsCount.current !== orgsCount) {
prevOrgsCount.current = orgsCount;
refetch();
}
}, [orgsCount, refetch]);

// Early returns for better performance
if (!showSwitchOrg(user, sysConfig)) return null;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { getUser } from "redux/selectors/usersSelectors";
import { getOrgCreateStatus } from "redux/selectors/orgSelectors";
import { useWorkspaceManager } from "util/useWorkspaceManager";
import { Org } from "constants/orgConstants";
import { useState } from "react";
import { useState, useEffect, useRef } from "react";
import { SwapOutlined } from "@ant-design/icons";
import dayjs from "dayjs";

Expand Down Expand Up @@ -195,10 +195,21 @@ function OrganizationSetting() {
handleSearchChange,
handlePageChange,
pageSize,
refetch,
} = useWorkspaceManager({
pageSize: 10
});

// Refetch list when orgs change (create/delete)
const orgsCount = user.orgs.length;
const prevOrgsCount = useRef(orgsCount);
useEffect(() => {
if (prevOrgsCount.current !== orgsCount) {
prevOrgsCount.current = orgsCount;
refetch();
}
}, [orgsCount, refetch]);



// Show all organizations with role information
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
UpdateAppMetaPayload,
UpdateAppPermissionPayload,
} from "redux/reduxActions/applicationActions";
import { UpdateOrgPayload } from "redux/reduxActions/orgActions";
import { createReducer } from "util/reducerUtils";
import {
ApplicationDetail,
Expand Down Expand Up @@ -70,6 +71,15 @@ const usersReducer = createReducer(initialState, {
},
},
}),
[ReduxActionTypes.UPDATE_ORG_SUCCESS]: (
state: ApplicationReduxState,
action: ReduxAction<UpdateOrgPayload>
): ApplicationReduxState => ({
...state,
homeOrg: state.homeOrg && state.homeOrg.id === action.payload.id
? { ...state.homeOrg, ...(action.payload.orgName && { name: action.payload.orgName }) }
: state.homeOrg,
}),
[ReduxActionTypes.FETCH_HOME_DATA_SUCCESS]: (
state: ApplicationReduxState,
action: ReduxAction<HomeData>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { Org } from "@lowcoder-ee/constants/orgConstants";
import {
ReduxAction,
ReduxActionErrorTypes,
Expand All @@ -22,14 +21,6 @@ const initialState: UsersReduxState = {
rawCurrentUser: defaultCurrentUser,
profileSettingModalVisible: false,
apiKeys: [],
workspaces: {
items: [],
totalCount: 0,
currentOrg: null,
loading: false,
isFetched: false,

}
};

const usersReducer = createReducer(initialState, {
Expand Down Expand Up @@ -199,31 +190,6 @@ const usersReducer = createReducer(initialState, {
...state,
apiKeys: action.payload,
}),

[ReduxActionTypes.FETCH_WORKSPACES_INIT]: (state: UsersReduxState) => ({
...state,
workspaces: {
...state.workspaces,
loading: true,
},
}),


[ReduxActionTypes.FETCH_WORKSPACES_SUCCESS]: (
state: UsersReduxState,
action: ReduxAction<{ items: Org[], totalCount: number, isLoadMore?: boolean }>
) => ({
...state,
workspaces: {
items: action.payload.isLoadMore
? [...state.workspaces.items, ...action.payload.items] // Append for load more
: action.payload.items, // Replace for new search/initial load
totalCount: action.payload.totalCount,
isFetched: true,
loading: false,
}
}),

});

export interface UsersReduxState {
Expand All @@ -239,16 +205,6 @@ export interface UsersReduxState {
error: string;
profileSettingModalVisible: boolean;
apiKeys: Array<ApiKey>;

// NEW state for workspaces
// NEW: Separate workspace state
workspaces: {
items: Org[]; // Current page of workspaces
totalCount: number; // Total workspaces available
currentOrg: Org | null;
loading: boolean;
isFetched: boolean;
};
}

export default usersReducer;
14 changes: 1 addition & 13 deletions client/packages/lowcoder/src/redux/reduxActions/orgActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,6 @@ export const updateOrgSuccess = (payload: UpdateOrgPayload) => {
};


// till now
export type OrgAPIUsagePayload = {
apiUsage: number,
};
Expand All @@ -181,7 +180,6 @@ export const fetchAPIUsageActionSuccess = (payload: OrgAPIUsagePayload) => {
};
};

// last month
export type OrgLastMonthAPIUsagePayload = {
lastMonthApiUsage: number,
};
Expand All @@ -199,14 +197,4 @@ export const fetchLastMonthAPIUsageActionSuccess = (payload: OrgLastMonthAPIUsag
type: ReduxActionTypes.FETCH_ORG_LAST_MONTH_API_USAGE_SUCCESS,
payload: payload,
};
};

export const fetchWorkspacesAction = (page: number = 1,pageSize: number = 20, search?: string, isLoadMore?: boolean) => ({
type: ReduxActionTypes.FETCH_WORKSPACES_INIT,
payload: { page, pageSize, search, isLoadMore }
});

export const loadMoreWorkspacesAction = (page: number, search?: string) => ({
type: ReduxActionTypes.FETCH_WORKSPACES_INIT,
payload: { page, search, isLoadMore: true }
});
};
63 changes: 4 additions & 59 deletions client/packages/lowcoder/src/redux/sagas/orgSagas.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { messageInstance } from "lowcoder-design/src/components/GlobalInstances";

import { ApiResponse, FetchGroupApiResponse, GenericApiResponse } from "api/apiResponses";
import { ApiResponse, FetchGroupApiResponse } from "api/apiResponses";
import OrgApi, { CreateOrgResponse, GroupUsersResponse, OrgAPIUsageResponse, OrgUsersResponse } from "api/orgApi";
import { AxiosResponse } from "axios";
import { OrgGroup } from "constants/orgConstants";
Expand All @@ -25,14 +25,11 @@ import {
fetchLastMonthAPIUsageActionSuccess,
UpdateUserGroupRolePayload,
UpdateUserOrgRolePayload,
fetchWorkspacesAction,
} from "redux/reduxActions/orgActions";
import { getUser } from "redux/selectors/usersSelectors";
import { validateResponse } from "api/apiUtils";
import { User } from "constants/userConstants";
import { getUserSaga } from "redux/sagas/userSagas";
import { GetMyOrgsResponse } from "@lowcoder-ee/api/userApi";
import UserApi from "@lowcoder-ee/api/userApi";

export function* updateGroupSaga(action: ReduxAction<UpdateGroupActionPayload>) {
try {
Expand Down Expand Up @@ -264,14 +261,10 @@ export function* createOrgSaga(action: ReduxAction<{ orgName: string }>) {
);
const isValidResponse: boolean = validateResponse(response);
if (isValidResponse) {
// update org list
yield call(getUserSaga);
// Refetch workspaces to update the profile dropdown
yield put(fetchWorkspacesAction(1, 10));
yield put({
type: ReduxActionTypes.CREATE_ORG_SUCCESS,
});

yield put({
type: ReduxActionTypes.CREATE_ORG_SUCCESS,
});
}
} catch (error: any) {
yield put({
Expand All @@ -293,8 +286,6 @@ export function* deleteOrgSaga(action: ReduxAction<{ orgId: string }>) {
orgId: action.payload.orgId,
},
});
// Refetch workspaces to update the profile dropdown
yield put(fetchWorkspacesAction(1, 10));
}
} catch (error: any) {
messageInstance.error(error.message);
Expand All @@ -308,8 +299,6 @@ export function* updateOrgSaga(action: ReduxAction<UpdateOrgPayload>) {
const isValidResponse: boolean = validateResponse(response);
if (isValidResponse) {
yield put(updateOrgSuccess(action.payload));
// Refetch workspaces to update the profile dropdown
yield put(fetchWorkspacesAction(1, 10));
}
} catch (error: any) {
messageInstance.error(error.message);
Expand Down Expand Up @@ -353,47 +342,6 @@ export function* fetchLastMonthAPIUsageSaga(action: ReduxAction<{
}
}

// fetch my orgs
// In userSagas.ts
export function* fetchWorkspacesSaga(action: ReduxAction<{page: number, pageSize: number, search?: string, isLoadMore?: boolean}>) {
try {
const { page, pageSize, search, isLoadMore } = action.payload;

const response: AxiosResponse<GetMyOrgsResponse> = yield call(
UserApi.getMyOrgs,
page, // pageNum
pageSize, // pageSize (changed to 5 for testing)
search // orgName
);

if (validateResponse(response)) {
const apiData = response.data.data;

// Transform orgId/orgName to match Org interface
const transformedItems = apiData.data
.filter(item => item.orgView && item.orgView.orgId)
.map(item => ({
id: item.orgView.orgId,
name: item.orgView.orgName,
createdAt: item.orgView.createdAt,
updatedAt: item.orgView.updatedAt,
isCurrentOrg: item.isCurrentOrg,
}));

yield put({
type: ReduxActionTypes.FETCH_WORKSPACES_SUCCESS,
payload: {
items: transformedItems,
totalCount: apiData.total,
isLoadMore: isLoadMore || false
}
});
}
} catch (error: any) {
console.error('Error fetching workspaces:', error);
}
}

export default function* orgSagas() {
yield all([
takeLatest(ReduxActionTypes.UPDATE_GROUP_INFO, updateGroupSaga),
Expand All @@ -414,8 +362,5 @@ export default function* orgSagas() {
takeLatest(ReduxActionTypes.UPDATE_ORG, updateOrgSaga),
takeLatest(ReduxActionTypes.FETCH_ORG_API_USAGE, fetchAPIUsageSaga),
takeLatest(ReduxActionTypes.FETCH_ORG_LAST_MONTH_API_USAGE, fetchLastMonthAPIUsageSaga),
takeLatest(ReduxActionTypes.FETCH_WORKSPACES_INIT, fetchWorkspacesSaga),


]);
}
1 change: 0 additions & 1 deletion client/packages/lowcoder/src/redux/sagas/userSagas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import { messageInstance } from "lowcoder-design/src/components/GlobalInstances"
import { AuthSearchParams } from "constants/authConstants";
import { saveAuthSearchParams } from "pages/userAuth/authUtils";
import { initTranslator } from "i18n";
import { fetchWorkspacesAction } from "../reduxActions/orgActions";

function validResponseData(response: AxiosResponse<ApiResponse>) {
return response && response.data && response.data.data;
Expand Down
4 changes: 0 additions & 4 deletions client/packages/lowcoder/src/redux/selectors/orgSelectors.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { Org } from "@lowcoder-ee/constants/orgConstants";
import { getUser } from "./usersSelectors";
import { AppState } from "redux/reducers";
import { getHomeOrg } from "./applicationSelector";

Expand Down Expand Up @@ -31,9 +30,6 @@ export const getOrgLastMonthApiUsage = (state: AppState) => {
return state.ui.org.lastMonthApiUsage;
}

// Add to usersSelectors.ts
export const getWorkspaces = (state: AppState) => state.ui.users.workspaces;

export const getCurrentOrg = (state: AppState): Pick<Org, 'id' | 'name'> | undefined => {
const homeOrg = getHomeOrg(state);
if (!homeOrg) {
Expand Down
Loading
Loading