Skip to content

Commit 0d87a21

Browse files
committed
Make a seperate AppsTab components and unified managed/unmanged apps
1 parent aafb5f5 commit 0d87a21

File tree

4 files changed

+299
-130
lines changed

4 files changed

+299
-130
lines changed

client/packages/lowcoder/src/pages/setting/environments/WorkspaceDetail.tsx

Lines changed: 2 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import { useManagedApps } from "./hooks/enterprise/useManagedApps";
3434
import { App } from "./types/app.types";
3535
import { getMergedApps } from "./utils/getMergedApps";
3636
import { connectManagedApp, unconnectManagedApp } from "./services/enterprise.service";
37+
import AppsTab from "./components/AppsTab";
3738

3839
const { Title, Text } = Typography;
3940
const { TabPane } = Tabs;
@@ -60,14 +61,6 @@ const WorkspaceDetail: React.FC = () => {
6061
refresh: refreshWorkspace
6162
} = useWorkspace(environment, workspaceId);
6263

63-
const {
64-
apps,
65-
loading: appsLoading,
66-
error: appsError,
67-
refresh: refreshApps,
68-
appStats,
69-
} = useWorkspaceApps(environment, workspaceId);
70-
7164
const {
7265
dataSources,
7366
loading: dataSourcesLoading,
@@ -76,35 +69,6 @@ const WorkspaceDetail: React.FC = () => {
7669
dataSourceStats,
7770
} = useWorkspaceDataSources(environment, workspaceId);
7871

79-
const { managedApps } = useManagedApps(environmentId);
80-
const [mergedApps, setMergedApps] = useState<App[]>([]);
81-
82-
useEffect(() => {
83-
setMergedApps(getMergedApps(apps, managedApps));
84-
}, [apps, managedApps]);
85-
86-
87-
88-
89-
const handleToggleManagedApp = async (app: App, checked: boolean) => {
90-
try {
91-
if (checked) {
92-
await connectManagedApp(environmentId, app.name, app.applicationGid!);
93-
} else {
94-
await unconnectManagedApp(app.applicationGid!);
95-
}
96-
97-
setMergedApps((currentApps) =>
98-
currentApps.map((a) =>
99-
a.applicationId === app.applicationId ? { ...a, managed: checked } : a
100-
)
101-
);
102-
103-
message.success(`${app.name} is now ${checked ? "Managed" : "Unmanaged"}`);
104-
} catch {
105-
message.error(`Failed to toggle ${app.name}`);
106-
}
107-
};
10872
if (envLoading || workspaceLoading) {
10973
return (
11074
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100%', padding: '50px' }}>
@@ -167,64 +131,7 @@ const WorkspaceDetail: React.FC = () => {
167131
tab={<span><AppstoreOutlined /> Apps</span>}
168132
key="apps"
169133
>
170-
<Card>
171-
{/* Header with refresh button */}
172-
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '16px' }}>
173-
<Title level={5}>Apps in this Workspace</Title>
174-
<Button
175-
icon={<SyncOutlined />}
176-
onClick={refreshApps}
177-
size="small"
178-
loading={appsLoading}
179-
>
180-
Refresh Apps
181-
</Button>
182-
</div>
183-
184-
{/* App Statistics */}
185-
<Row gutter={16} style={{ marginBottom: '24px' }}>
186-
<Col span={8}>
187-
<Statistic
188-
title="Total Apps"
189-
value={appStats.total}
190-
prefix={<AppstoreOutlined />}
191-
/>
192-
</Col>
193-
<Col span={8}>
194-
<Statistic
195-
title="Published Apps"
196-
value={appStats.published}
197-
prefix={<AppstoreOutlined />}
198-
/>
199-
</Col>
200-
</Row>
201-
202-
<Divider style={{ margin: '16px 0' }} />
203-
204-
{/* Show error if apps loading failed */}
205-
{appsError && (
206-
<Alert
207-
message="Error loading apps"
208-
description={appsError}
209-
type="error"
210-
showIcon
211-
style={{ marginBottom: '16px' }}
212-
action={
213-
<Button size="small" type="primary" onClick={refreshApps}>
214-
Try Again
215-
</Button>
216-
}
217-
/>
218-
)}
219-
220-
{/* Apps List */}
221-
<AppsList
222-
apps={mergedApps}
223-
loading={appsLoading}
224-
error={appsError}
225-
onToggleManaged={handleToggleManagedApp}
226-
/>
227-
</Card>
134+
<AppsTab environment={environment} workspaceId={workspaceId} />
228135
</TabPane>
229136

230137
{/* Update the TabPane in WorkspaceDetail.tsx */}
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
// components/AppsTab.tsx
2+
import React from 'react';
3+
import { Card, Button, Row, Col, Statistic, Divider, Alert, message } from 'antd';
4+
import { AppstoreOutlined, SyncOutlined } from '@ant-design/icons';
5+
import Title from 'antd/lib/typography/Title';
6+
import { Environment } from '../types/environment.types';
7+
import { useWorkspaceApps } from '../hooks/useWorkspaceApps';
8+
import AppsList from './AppsList';
9+
import { App } from '../types/app.types';
10+
11+
interface AppsTabProps {
12+
environment: Environment;
13+
workspaceId: string;
14+
}
15+
16+
const AppsTab: React.FC<AppsTabProps> = ({ environment, workspaceId }) => {
17+
const {
18+
apps,
19+
stats,
20+
loading,
21+
error,
22+
toggleManagedStatus
23+
} = useWorkspaceApps(environment, workspaceId);
24+
25+
const handleToggleManagedApp = async (app: App, checked: boolean) => {
26+
const success = await toggleManagedStatus(app, checked);
27+
28+
if (success) {
29+
message.success(`${app.name} is now ${checked ? "Managed" : "Unmanaged"}`);
30+
} else {
31+
message.error(`Failed to toggle ${app.name}`);
32+
}
33+
};
34+
35+
return (
36+
<Card>
37+
{/* Header with refresh button */}
38+
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '16px' }}>
39+
<Title level={5}>Apps in this Workspace</Title>
40+
</div>
41+
42+
{/* App Statistics */}
43+
<Row gutter={16} style={{ marginBottom: '24px' }}>
44+
<Col span={6}>
45+
<Statistic
46+
title="Total Apps"
47+
value={stats.total}
48+
prefix={<AppstoreOutlined />}
49+
/>
50+
</Col>
51+
<Col span={6}>
52+
<Statistic
53+
title="Published Apps"
54+
value={stats.published}
55+
prefix={<AppstoreOutlined />}
56+
/>
57+
</Col>
58+
<Col span={6}>
59+
<Statistic
60+
title="Managed Apps"
61+
value={stats.managed}
62+
prefix={<AppstoreOutlined />}
63+
/>
64+
</Col>
65+
<Col span={6}>
66+
<Statistic
67+
title="Unmanaged Apps"
68+
value={stats.unmanaged}
69+
prefix={<AppstoreOutlined />}
70+
/>
71+
</Col>
72+
</Row>
73+
74+
<Divider style={{ margin: '16px 0' }} />
75+
76+
{/* Show error if apps loading failed */}
77+
{error && (
78+
<Alert
79+
message="Error loading apps"
80+
description={error}
81+
type="error"
82+
showIcon
83+
style={{ marginBottom: '16px' }}
84+
/>
85+
)}
86+
87+
{/* Configuration warning */}
88+
{(!environment.environmentApikey ||
89+
!environment.environmentApiServiceUrl) &&
90+
!error && (
91+
<Alert
92+
message="Configuration Issue"
93+
description={
94+
!environment.environmentApikey
95+
? "An API key is required to fetch apps for this workspace."
96+
: "An API service URL is required to fetch apps for this workspace."
97+
}
98+
type="warning"
99+
showIcon
100+
style={{ marginBottom: '16px' }}
101+
/>
102+
)}
103+
104+
{/* Apps List */}
105+
<AppsList
106+
apps={apps}
107+
loading={loading && !error}
108+
error={error}
109+
onToggleManaged={handleToggleManagedApp}
110+
/>
111+
</Card>
112+
);
113+
};
114+
115+
export default AppsTab;

0 commit comments

Comments
 (0)