Skip to content

Commit eb401ee

Browse files
committed
add workspaces list
1 parent 2e88e9f commit eb401ee

File tree

6 files changed

+524
-141
lines changed

6 files changed

+524
-141
lines changed

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

Lines changed: 199 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,29 @@
11
import React from "react";
22
import { useParams } from "react-router-dom";
3-
import {
4-
Spin,
5-
Typography,
6-
Card,
7-
Row,
8-
Col,
9-
Tag,
10-
Tabs,
11-
Alert,
12-
Descriptions,
3+
import {
4+
Spin,
5+
Typography,
6+
Card,
7+
Row,
8+
Col,
9+
Tag,
10+
Tabs,
11+
Alert,
12+
Descriptions,
1313
Button,
14-
Statistic
14+
Statistic,
15+
Divider,
1516
} from "antd";
16-
import {
17-
ReloadOutlined,
18-
LinkOutlined,
19-
ClusterOutlined,
20-
TeamOutlined,
21-
UserOutlined
17+
import {
18+
ReloadOutlined,
19+
LinkOutlined,
20+
ClusterOutlined,
21+
TeamOutlined,
22+
UserOutlined,
23+
SyncOutlined,
2224
} from "@ant-design/icons";
23-
import { useEnvironmentDetail } from './hooks/useEnvironmentDetail';
25+
import { useEnvironmentDetail } from "./hooks/useEnvironmentDetail";
26+
import WorkspacesList from "./components/WorkspacesList";
2427

2528
const { Title, Text } = Typography;
2629
const { TabPane } = Tabs;
@@ -32,19 +35,37 @@ const { TabPane } = Tabs;
3235
const EnvironmentDetail: React.FC = () => {
3336
// Get environment ID from URL params
3437
const { environmentId: id } = useParams<{ environmentId: string }>();
35-
38+
39+
// Use the custom hook to handle data fetching and state management
3640
// Use the custom hook to handle data fetching and state management
37-
const { environment, loading, error, refresh } = useEnvironmentDetail(id);
38-
41+
const {
42+
environment,
43+
loading,
44+
error,
45+
refresh,
46+
workspaces,
47+
workspacesLoading,
48+
workspacesError,
49+
refreshWorkspaces,
50+
workspaceStats,
51+
} = useEnvironmentDetail(id);
3952
// If loading, show spinner
4053
if (loading) {
4154
return (
42-
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100%', padding: '50px' }}>
55+
<div
56+
style={{
57+
display: "flex",
58+
justifyContent: "center",
59+
alignItems: "center",
60+
height: "100%",
61+
padding: "50px",
62+
}}
63+
>
4364
<Spin size="large" tip="Loading environment details..." />
4465
</div>
4566
);
4667
}
47-
68+
4869
// If error, show error message
4970
if (error) {
5071
return (
@@ -53,7 +74,7 @@ const EnvironmentDetail: React.FC = () => {
5374
description={error}
5475
type="error"
5576
showIcon
56-
style={{ margin: '24px' }}
77+
style={{ margin: "24px" }}
5778
action={
5879
<Button type="primary" icon={<ReloadOutlined />} onClick={refresh}>
5980
Try Again
@@ -62,7 +83,7 @@ const EnvironmentDetail: React.FC = () => {
6283
/>
6384
);
6485
}
65-
86+
6687
// If no environment data, show message
6788
if (!environment) {
6889
return (
@@ -71,122 +92,219 @@ const EnvironmentDetail: React.FC = () => {
7192
description="The requested environment could not be found"
7293
type="warning"
7394
showIcon
74-
style={{ margin: '24px' }}
95+
style={{ margin: "24px" }}
7596
/>
7697
);
7798
}
78-
99+
79100
return (
80-
<div className="environment-detail-container" style={{ padding: '24px' }}>
101+
<div className="environment-detail-container" style={{ padding: "24px" }}>
81102
{/* Header with environment name and controls */}
82-
<div className="environment-header" style={{ marginBottom: '24px', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
103+
<div
104+
className="environment-header"
105+
style={{
106+
marginBottom: "24px",
107+
display: "flex",
108+
justifyContent: "space-between",
109+
alignItems: "center",
110+
}}
111+
>
83112
<div>
84-
<Title level={3}>{environment.environmentName || 'Unnamed Environment'}</Title>
113+
<Title level={3}>
114+
{environment.environmentName || "Unnamed Environment"}
115+
</Title>
85116
<Text type="secondary">ID: {environment.environmentId}</Text>
86117
</div>
87-
<Button
88-
icon={<ReloadOutlined />}
89-
onClick={refresh}
90-
>
118+
<Button icon={<ReloadOutlined />} onClick={refresh}>
91119
Refresh
92120
</Button>
93121
</div>
94-
122+
95123
{/* Basic Environment Information Card */}
96-
<Card
97-
title="Environment Overview"
98-
style={{ marginBottom: '24px' }}
124+
<Card
125+
title="Environment Overview"
126+
style={{ marginBottom: "24px" }}
99127
extra={environment.isMaster && <Tag color="green">Master</Tag>}
100128
>
101-
<Descriptions bordered column={{ xxl: 4, xl: 3, lg: 3, md: 2, sm: 1, xs: 1 }}>
129+
<Descriptions
130+
bordered
131+
column={{ xxl: 4, xl: 3, lg: 3, md: 2, sm: 1, xs: 1 }}
132+
>
102133
<Descriptions.Item label="Domain">
103134
{environment.environmentFrontendUrl ? (
104-
<a href={environment.environmentFrontendUrl} target="_blank" rel="noopener noreferrer">
135+
<a
136+
href={environment.environmentFrontendUrl}
137+
target="_blank"
138+
rel="noopener noreferrer"
139+
>
105140
{environment.environmentFrontendUrl} <LinkOutlined />
106141
</a>
107142
) : (
108-
'No domain set'
143+
"No domain set"
109144
)}
110145
</Descriptions.Item>
111146
<Descriptions.Item label="Environment Type">
112-
<Tag color={environment.environmentType === 'production' ? 'red' : environment.environmentType === 'testing' ? 'orange' : 'blue'}>
147+
<Tag
148+
color={
149+
environment.environmentType === "production"
150+
? "red"
151+
: environment.environmentType === "testing"
152+
? "orange"
153+
: "blue"
154+
}
155+
>
113156
{environment.environmentType}
114157
</Tag>
115158
</Descriptions.Item>
116159
<Descriptions.Item label="API Key Status">
117-
{environment.environmentApikey ? <Tag color="green">Configured</Tag> : <Tag color="red">Not Configured</Tag>}
160+
{environment.environmentApikey ? (
161+
<Tag color="green">Configured</Tag>
162+
) : (
163+
<Tag color="red">Not Configured</Tag>
164+
)}
118165
</Descriptions.Item>
119166
<Descriptions.Item label="Master Environment">
120-
{environment.isMaster ? 'Yes' : 'No'}
167+
{environment.isMaster ? "Yes" : "No"}
121168
</Descriptions.Item>
122169
</Descriptions>
123170
</Card>
124-
171+
125172
{/* Tabs for Workspaces and User Groups */}
126173
<Tabs defaultActiveKey="workspaces">
127-
<TabPane
128-
tab={<span><ClusterOutlined /> Workspaces</span>}
174+
<TabPane
175+
tab={
176+
<span>
177+
<ClusterOutlined /> Workspaces
178+
</span>
179+
}
129180
key="workspaces"
130181
>
131182
<Card>
132-
{/* Placeholder for workspace statistics */}
133-
<Row gutter={16} style={{ marginBottom: '24px' }}>
183+
{/* Header with refresh button */}
184+
<div
185+
style={{
186+
display: "flex",
187+
justifyContent: "space-between",
188+
alignItems: "center",
189+
marginBottom: "16px",
190+
}}
191+
>
192+
<Title level={5}>Workspaces in this Environment</Title>
193+
<Button
194+
icon={<SyncOutlined />}
195+
onClick={refreshWorkspaces}
196+
size="small"
197+
loading={workspacesLoading}
198+
>
199+
Refresh Workspaces
200+
</Button>
201+
</div>
202+
203+
{/* Workspace Statistics */}
204+
<Row gutter={16} style={{ marginBottom: "24px" }}>
134205
<Col span={8}>
135-
<Statistic
136-
title="Total Workspaces"
137-
value={0}
138-
prefix={<ClusterOutlined />}
206+
<Statistic
207+
title="Total Workspaces"
208+
value={workspaceStats.total}
209+
prefix={<ClusterOutlined />}
139210
/>
140211
</Col>
141212
<Col span={8}>
142-
<Statistic
143-
title="Managed Workspaces"
144-
value={0}
145-
prefix={<ClusterOutlined />}
213+
<Statistic
214+
title="Managed Workspaces"
215+
value={workspaceStats.managed}
216+
prefix={<ClusterOutlined />}
146217
/>
147218
</Col>
148219
<Col span={8}>
149-
<Statistic
150-
title="Unmanaged Workspaces"
151-
value={0}
152-
prefix={<ClusterOutlined />}
220+
<Statistic
221+
title="Unmanaged Workspaces"
222+
value={workspaceStats.unmanaged}
223+
prefix={<ClusterOutlined />}
153224
/>
154225
</Col>
155226
</Row>
156-
157-
{/* Placeholder for workspace list */}
158-
<Alert
159-
message="Workspace Information"
160-
description="Workspace data will be implemented in the next phase. This section will display workspace details and management options."
161-
type="info"
162-
showIcon
227+
228+
<Divider style={{ margin: "16px 0" }} />
229+
230+
{/* Show error if workspace loading failed */}
231+
{workspacesError && (
232+
<Alert
233+
message="Error loading workspaces"
234+
description={workspacesError}
235+
type="error"
236+
showIcon
237+
style={{ marginBottom: "16px" }}
238+
action={
239+
workspacesError.includes("No API key configured") ? (
240+
<Button size="small" type="primary" disabled>
241+
API Key Required
242+
</Button>
243+
) : (
244+
<Button
245+
size="small"
246+
type="primary"
247+
onClick={refreshWorkspaces}
248+
>
249+
Try Again
250+
</Button>
251+
)
252+
}
253+
/>
254+
)}
255+
256+
{(!environment.environmentApikey ||
257+
!environment.environmentApiServiceUrl) &&
258+
!workspacesError && (
259+
<Alert
260+
message="Configuration Issue"
261+
description={
262+
!environment.environmentApikey
263+
? "An API key is required to fetch workspaces for this environment."
264+
: "An API service URL is required to fetch workspaces for this environment."
265+
}
266+
type="warning"
267+
showIcon
268+
style={{ marginBottom: "16px" }}
269+
/>
270+
)}
271+
272+
{/* Workspaces List */}
273+
<WorkspacesList
274+
workspaces={workspaces}
275+
loading={workspacesLoading && !workspacesError}
276+
error={workspacesError}
163277
/>
164278
</Card>
165279
</TabPane>
166-
167-
<TabPane
168-
tab={<span><TeamOutlined /> User Groups</span>}
280+
281+
<TabPane
282+
tab={
283+
<span>
284+
<TeamOutlined /> User Groups
285+
</span>
286+
}
169287
key="userGroups"
170288
>
171289
<Card>
172290
{/* Placeholder for user group statistics */}
173-
<Row gutter={16} style={{ marginBottom: '24px' }}>
291+
<Row gutter={16} style={{ marginBottom: "24px" }}>
174292
<Col span={8}>
175-
<Statistic
176-
title="Total User Groups"
177-
value={0}
178-
prefix={<TeamOutlined />}
293+
<Statistic
294+
title="Total User Groups"
295+
value={0}
296+
prefix={<TeamOutlined />}
179297
/>
180298
</Col>
181299
<Col span={8}>
182-
<Statistic
183-
title="Total Users"
184-
value={0}
185-
prefix={<UserOutlined />}
300+
<Statistic
301+
title="Total Users"
302+
value={0}
303+
prefix={<UserOutlined />}
186304
/>
187305
</Col>
188306
</Row>
189-
307+
190308
{/* Placeholder for user group list */}
191309
<Alert
192310
message="User Group Information"

0 commit comments

Comments
 (0)