Skip to content

Commit 4be0dad

Browse files
committed
Add Env Detail Page
1 parent 27451ab commit 4be0dad

File tree

4 files changed

+243
-3
lines changed

4 files changed

+243
-3
lines changed
Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
import React, { useEffect, useState } from "react";
2+
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,
13+
Button,
14+
Statistic
15+
} from "antd";
16+
import {
17+
ReloadOutlined,
18+
LinkOutlined,
19+
ClusterOutlined,
20+
TeamOutlined,
21+
UserOutlined
22+
} from "@ant-design/icons";
23+
import { getEnvironmentById } from "./services/environments.service";
24+
import { Environment } from "./types/environment.types";
25+
26+
const { Title, Text } = Typography;
27+
const { TabPane } = Tabs;
28+
29+
/**
30+
* Environment Detail Page Component
31+
* Shows detailed information about a specific environment
32+
*/
33+
const EnvironmentDetail: React.FC = () => {
34+
// Get environment ID from URL params
35+
const { environmentId: id } = useParams<{ environmentId: string }>();
36+
console.log(id);
37+
38+
// State for environment data and loading state
39+
const [environment, setEnvironment] = useState<Environment | null>(null);
40+
const [loading, setLoading] = useState<boolean>(true);
41+
const [error, setError] = useState<string | null>(null);
42+
43+
// Fetch environment data on mount and when ID changes
44+
useEffect(() => {
45+
fetchEnvironmentData();
46+
}, [id]);
47+
48+
// Function to fetch environment data
49+
const fetchEnvironmentData = async () => {
50+
setLoading(true);
51+
setError(null);
52+
53+
try {
54+
const data = await getEnvironmentById(id);
55+
setEnvironment(data);
56+
} catch (err) {
57+
setError(err instanceof Error ? err.message : 'Failed to fetch environment details');
58+
} finally {
59+
setLoading(false);
60+
}
61+
};
62+
63+
// Handle refresh button click
64+
const handleRefresh = () => {
65+
fetchEnvironmentData();
66+
};
67+
68+
// If loading, show spinner
69+
if (loading) {
70+
return (
71+
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100%', padding: '50px' }}>
72+
<Spin size="large" tip="Loading environment details..." />
73+
</div>
74+
);
75+
}
76+
77+
// If error, show error message
78+
if (error) {
79+
return (
80+
<Alert
81+
message="Error loading environment details"
82+
description={error}
83+
type="error"
84+
showIcon
85+
style={{ margin: '24px' }}
86+
action={
87+
<Button type="primary" icon={<ReloadOutlined />} onClick={handleRefresh}>
88+
Try Again
89+
</Button>
90+
}
91+
/>
92+
);
93+
}
94+
95+
// If no environment data, show message
96+
if (!environment) {
97+
return (
98+
<Alert
99+
message="Environment not found"
100+
description="The requested environment could not be found"
101+
type="warning"
102+
showIcon
103+
style={{ margin: '24px' }}
104+
/>
105+
);
106+
}
107+
108+
return (
109+
<div className="environment-detail-container" style={{ padding: '24px' }}>
110+
{/* Header with environment name and controls */}
111+
<div className="environment-header" style={{ marginBottom: '24px', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
112+
<div>
113+
<Title level={3}>{environment.environmentName || 'Unnamed Environment'}</Title>
114+
<Text type="secondary">ID: {environment.environmentId}</Text>
115+
</div>
116+
<Button
117+
icon={<ReloadOutlined />}
118+
onClick={handleRefresh}
119+
>
120+
Refresh
121+
</Button>
122+
</div>
123+
124+
{/* Basic Environment Information Card */}
125+
<Card
126+
title="Environment Overview"
127+
style={{ marginBottom: '24px' }}
128+
extra={environment.isMaster && <Tag color="green">Master</Tag>}
129+
>
130+
<Descriptions bordered column={{ xxl: 4, xl: 3, lg: 3, md: 2, sm: 1, xs: 1 }}>
131+
<Descriptions.Item label="Domain">
132+
{environment.environmentFrontendUrl ? (
133+
<a href={environment.environmentFrontendUrl} target="_blank" rel="noopener noreferrer">
134+
{environment.environmentFrontendUrl} <LinkOutlined />
135+
</a>
136+
) : (
137+
'No domain set'
138+
)}
139+
</Descriptions.Item>
140+
<Descriptions.Item label="Environment Type">
141+
<Tag color={environment.environmentType === 'production' ? 'red' : environment.environmentType === 'testing' ? 'orange' : 'blue'}>
142+
{environment.environmentType}
143+
</Tag>
144+
</Descriptions.Item>
145+
<Descriptions.Item label="API Key Status">
146+
{environment.environmentApikey ? <Tag color="green">Configured</Tag> : <Tag color="red">Not Configured</Tag>}
147+
</Descriptions.Item>
148+
<Descriptions.Item label="Master Environment">
149+
{environment.isMaster ? 'Yes' : 'No'}
150+
</Descriptions.Item>
151+
</Descriptions>
152+
</Card>
153+
154+
{/* Tabs for Workspaces and User Groups */}
155+
<Tabs defaultActiveKey="workspaces">
156+
<TabPane
157+
tab={<span><ClusterOutlined /> Workspaces</span>}
158+
key="workspaces"
159+
>
160+
<Card>
161+
{/* Placeholder for workspace statistics */}
162+
<Row gutter={16} style={{ marginBottom: '24px' }}>
163+
<Col span={8}>
164+
<Statistic
165+
title="Total Workspaces"
166+
value={0}
167+
prefix={<ClusterOutlined />}
168+
/>
169+
</Col>
170+
<Col span={8}>
171+
<Statistic
172+
title="Managed Workspaces"
173+
value={0}
174+
prefix={<ClusterOutlined />}
175+
/>
176+
</Col>
177+
<Col span={8}>
178+
<Statistic
179+
title="Unmanaged Workspaces"
180+
value={0}
181+
prefix={<ClusterOutlined />}
182+
/>
183+
</Col>
184+
</Row>
185+
186+
{/* Placeholder for workspace list */}
187+
<Alert
188+
message="Workspace Information"
189+
description="Workspace data will be implemented in the next phase. This section will display workspace details and management options."
190+
type="info"
191+
showIcon
192+
/>
193+
</Card>
194+
</TabPane>
195+
196+
<TabPane
197+
tab={<span><TeamOutlined /> User Groups</span>}
198+
key="userGroups"
199+
>
200+
<Card>
201+
{/* Placeholder for user group statistics */}
202+
<Row gutter={16} style={{ marginBottom: '24px' }}>
203+
<Col span={8}>
204+
<Statistic
205+
title="Total User Groups"
206+
value={0}
207+
prefix={<TeamOutlined />}
208+
/>
209+
</Col>
210+
<Col span={8}>
211+
<Statistic
212+
title="Total Users"
213+
value={0}
214+
prefix={<UserOutlined />}
215+
/>
216+
</Col>
217+
</Row>
218+
219+
{/* Placeholder for user group list */}
220+
<Alert
221+
message="User Group Information"
222+
description="User group data will be implemented in the next phase. This section will display user group details and membership information."
223+
type="info"
224+
showIcon
225+
/>
226+
</Card>
227+
</TabPane>
228+
</Tabs>
229+
</div>
230+
);
231+
};
232+
233+
export default EnvironmentDetail;

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,21 @@
22
import React from "react";
33
import { Switch, Route, useRouteMatch } from "react-router-dom";
44
import EnvironmentsList from "./EnvironmentsList"; // Rename your current component
5+
import EnvironmentDetail from "./EnvironmentDetail";
6+
7+
import { ENVIRONMENT_SETTING, ENVIRONMENT_DETAIL } from "@lowcoder-ee/constants/routesURL";
58

6-
import { ENVIRONMENT_SETTING } from "@lowcoder-ee/constants/routesURL";
79

810
const Environments: React.FC = () => {
911
return (
1012
<Switch>
1113
<Route exact path={ENVIRONMENT_SETTING}>
1214
<EnvironmentsList />
1315
</Route>
16+
<Route path={ENVIRONMENT_DETAIL}>
17+
<EnvironmentDetail />
18+
</Route>
19+
1420
</Switch>
1521
);
1622
};

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { useHistory } from "react-router-dom";
55
import { useEnvironments } from "./hooks/useEnvironments";
66
import { Environment } from "./types/environment.types";
77
import EnvironmentsTable from "./components/EnvironmentsTable";
8+
import { buildEnvironmentId } from "@lowcoder-ee/constants/routesURL";
89

910
const { Title } = Typography;
1011

@@ -67,7 +68,7 @@ const EnvironmentsList: React.FC = () => {
6768

6869
// Handle row click to navigate to environment detail
6970
const handleRowClick = (record: Environment) => {
70-
history.push(`/home/settings/environments/${record.environmentId}`);
71+
history.push(buildEnvironmentId(record.environmentId));
7172
};
7273

7374
return (

client/packages/lowcoder/src/pages/setting/environments/services/environments.service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export async function getEnvironments(): Promise<Environment[]> {
2727
*/
2828
export async function getEnvironmentById(id: string): Promise<Environment> {
2929
try {
30-
const response = await axios.get(`/api/plugins/enterprise/environments/${id}`);
30+
const response = await axios.get(`/api/plugins/enterprise/environments?environmentId=${id}`);
3131

3232
if (!response.data) {
3333
throw new Error('Failed to fetch environment');

0 commit comments

Comments
 (0)