Skip to content

Commit cc015e6

Browse files
committed
Add routing structure for Environments
1 parent 349fdf1 commit cc015e6

File tree

3 files changed

+154
-128
lines changed

3 files changed

+154
-128
lines changed

client/packages/lowcoder/src/constants/routesURL.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ export const AUDIT_LOG_DETAIL = "/setting/audit/:eventId/detail";
2424
export const APP_USAGE_DASHBOARD = "/setting/app-usage";
2525
export const APP_USAGE_DETAIL = "/setting/app-usage/:eventId/detail";
2626

27+
export const ENVIRONMENT_SETTING = "/setting/environments";
28+
export const ENVIRONMENT_DETAIL = `${ENVIRONMENT_SETTING}/:environmentId`;
29+
export const ENVIRONMENT_WORKSPACE_DETAIL = `${ENVIRONMENT_DETAIL}/workspaces/:workspaceId`;
30+
2731
export const OAUTH_PROVIDER_SETTING = "/setting/oauth-provider";
2832
export const OAUTH_PROVIDER_DETAIL = "/setting/oauth-provider/detail";
2933

@@ -120,3 +124,7 @@ export const buildSubscriptionSettingsLink = (subscriptionId: string, productId
120124
export const buildSubscriptionInfoLink = (productId: string) => `${SUBSCRIPTION_SETTING}/info/${productId}`;
121125

122126
export const buildSupportTicketLink = (ticketId: string) => `${SUPPORT_URL}/details/${ticketId}`;
127+
128+
export const buildEnvironmentId = (environmentId: string) => `${ENVIRONMENT_SETTING}/${environmentId}`;
129+
export const buildEnvironmentWorkspaceId = (environmentId: string, workspaceId: string) =>
130+
`${ENVIRONMENT_SETTING}/${environmentId}/workspaces/${workspaceId}`;

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

Lines changed: 10 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -1,135 +1,17 @@
1-
import React, { useState } from 'react';
2-
import { Table, Typography, Alert, Input, Button, Space, Empty } from 'antd';
3-
import { SearchOutlined, ReloadOutlined } from '@ant-design/icons';
4-
import { useHistory } from 'react-router-dom';
5-
import { useEnvironments } from './hooks/useEnvironments';
6-
import { Environment } from './types/environment.types';
1+
// environments/Environments.tsx
2+
import React from "react";
3+
import { Switch, Route, useRouteMatch } from "react-router-dom";
4+
import EnvironmentsList from "./EnvironmentsList"; // Rename your current component
75

8-
const { Title } = Typography;
6+
import { ENVIRONMENT_SETTING } from "@lowcoder-ee/constants/routesURL";
97

10-
/**
11-
* Environment Listing Page Component
12-
* Displays a basic table of environments
13-
*/
148
const Environments: React.FC = () => {
15-
// Use our custom hook to get environments data and states
16-
const { environments, loading, error, refresh } = useEnvironments();
17-
18-
// State for search input
19-
const [searchText, setSearchText] = useState('');
20-
21-
// Hook for navigation (using history instead of navigate)
22-
const history = useHistory();
23-
24-
// Filter environments based on search text
25-
const filteredEnvironments = environments.filter(env => {
26-
const searchLower = searchText.toLowerCase();
27-
return (
28-
(env.environmentName || '').toLowerCase().includes(searchLower) ||
29-
(env.environmentFrontendUrl || '').toLowerCase().includes(searchLower) ||
30-
env.environmentId.toLowerCase().includes(searchLower) ||
31-
env.environmentType.toLowerCase().includes(searchLower)
32-
);
33-
});
34-
35-
// Define table columns - updated to match the actual data structure
36-
const columns = [
37-
{
38-
title: 'Name',
39-
dataIndex: 'environmentName',
40-
key: 'environmentName',
41-
render: (name: string) => name || 'Unnamed Environment',
42-
},
43-
{
44-
title: 'Domain',
45-
dataIndex: 'environmentFrontendUrl',
46-
key: 'environmentFrontendUrl',
47-
render: (url: string) => url || 'No URL',
48-
},
49-
{
50-
title: 'ID',
51-
dataIndex: 'environmentId',
52-
key: 'environmentId',
53-
},
54-
{
55-
title: 'Stage',
56-
dataIndex: 'environmentType',
57-
key: 'environmentType',
58-
},
59-
{
60-
title: 'Master',
61-
dataIndex: 'isMaster',
62-
key: 'isMaster',
63-
render: (isMaster: boolean) => isMaster ? 'Yes' : 'No',
64-
},
65-
];
66-
67-
// Handle row click to navigate to environment detail
68-
const handleRowClick = (record: Environment) => {
69-
history.push(`/home/settings/environments/${record.environmentId}`);
70-
};
71-
729
return (
73-
<div className="environments-container" style={{ padding: '24px' }}>
74-
{/* Header section with title and controls */}
75-
<div className="environments-header" style={{
76-
marginBottom: '24px',
77-
display: 'flex',
78-
justifyContent: 'space-between',
79-
alignItems: 'center'
80-
}}>
81-
<Title level={3}>Environments</Title>
82-
<Space>
83-
<Input
84-
placeholder="Search environments"
85-
value={searchText}
86-
onChange={e => setSearchText(e.target.value)}
87-
style={{ width: 250 }}
88-
prefix={<SearchOutlined />}
89-
allowClear
90-
/>
91-
<Button
92-
icon={<ReloadOutlined />}
93-
onClick={refresh}
94-
loading={loading}
95-
>
96-
Refresh
97-
</Button>
98-
</Space>
99-
</div>
100-
101-
{/* Error handling */}
102-
{error && (
103-
<Alert
104-
message="Error loading environments"
105-
description={error}
106-
type="error"
107-
showIcon
108-
style={{ marginBottom: '24px' }}
109-
/>
110-
)}
111-
112-
{/* Empty state handling */}
113-
{!loading && environments.length === 0 && !error ? (
114-
<Empty
115-
description="No environments found"
116-
image={Empty.PRESENTED_IMAGE_SIMPLE}
117-
/>
118-
) : (
119-
/* Table component */
120-
<Table
121-
dataSource={filteredEnvironments}
122-
columns={columns}
123-
rowKey="environmentId"
124-
loading={loading}
125-
pagination={{ pageSize: 10 }}
126-
onRow={(record) => ({
127-
onClick: () => handleRowClick(record),
128-
style: { cursor: 'pointer' }
129-
})}
130-
/>
131-
)}
132-
</div>
10+
<Switch>
11+
<Route exact path={ENVIRONMENT_SETTING}>
12+
<EnvironmentsList />
13+
</Route>
14+
</Switch>
13315
);
13416
};
13517

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
import React, { useState } from 'react';
2+
import { Table, Typography, Alert, Input, Button, Space, Empty } from 'antd';
3+
import { SearchOutlined, ReloadOutlined } from '@ant-design/icons';
4+
import { useHistory } from 'react-router-dom';
5+
import { useEnvironments } from './hooks/useEnvironments';
6+
import { Environment } from './types/environment.types';
7+
8+
const { Title } = Typography;
9+
10+
/**
11+
* Environment Listing Page Component
12+
* Displays a basic table of environments
13+
*/
14+
const EnvironmentsList: React.FC = () => {
15+
// Use our custom hook to get environments data and states
16+
const { environments, loading, error, refresh } = useEnvironments();
17+
18+
// State for search input
19+
const [searchText, setSearchText] = useState('');
20+
21+
// Hook for navigation (using history instead of navigate)
22+
const history = useHistory();
23+
24+
// Filter environments based on search text
25+
const filteredEnvironments = environments.filter(env => {
26+
const searchLower = searchText.toLowerCase();
27+
return (
28+
(env.environmentName || '').toLowerCase().includes(searchLower) ||
29+
(env.environmentFrontendUrl || '').toLowerCase().includes(searchLower) ||
30+
env.environmentId.toLowerCase().includes(searchLower) ||
31+
env.environmentType.toLowerCase().includes(searchLower)
32+
);
33+
});
34+
35+
// Define table columns - updated to match the actual data structure
36+
const columns = [
37+
{
38+
title: 'Name',
39+
dataIndex: 'environmentName',
40+
key: 'environmentName',
41+
render: (name: string) => name || 'Unnamed Environment',
42+
},
43+
{
44+
title: 'Domain',
45+
dataIndex: 'environmentFrontendUrl',
46+
key: 'environmentFrontendUrl',
47+
render: (url: string) => url || 'No URL',
48+
},
49+
{
50+
title: 'ID',
51+
dataIndex: 'environmentId',
52+
key: 'environmentId',
53+
},
54+
{
55+
title: 'Stage',
56+
dataIndex: 'environmentType',
57+
key: 'environmentType',
58+
},
59+
{
60+
title: 'Master',
61+
dataIndex: 'isMaster',
62+
key: 'isMaster',
63+
render: (isMaster: boolean) => isMaster ? 'Yes' : 'No',
64+
},
65+
];
66+
67+
// Handle row click to navigate to environment detail
68+
const handleRowClick = (record: Environment) => {
69+
history.push(`/home/settings/environments/${record.environmentId}`);
70+
};
71+
72+
return (
73+
<div className="environments-container" style={{ padding: '24px' }}>
74+
{/* Header section with title and controls */}
75+
<div className="environments-header" style={{
76+
marginBottom: '24px',
77+
display: 'flex',
78+
justifyContent: 'space-between',
79+
alignItems: 'center'
80+
}}>
81+
<Title level={3}>Environments</Title>
82+
<Space>
83+
<Input
84+
placeholder="Search environments"
85+
value={searchText}
86+
onChange={e => setSearchText(e.target.value)}
87+
style={{ width: 250 }}
88+
prefix={<SearchOutlined />}
89+
allowClear
90+
/>
91+
<Button
92+
icon={<ReloadOutlined />}
93+
onClick={refresh}
94+
loading={loading}
95+
>
96+
Refresh
97+
</Button>
98+
</Space>
99+
</div>
100+
101+
{/* Error handling */}
102+
{error && (
103+
<Alert
104+
message="Error loading environments"
105+
description={error}
106+
type="error"
107+
showIcon
108+
style={{ marginBottom: '24px' }}
109+
/>
110+
)}
111+
112+
{/* Empty state handling */}
113+
{!loading && environments.length === 0 && !error ? (
114+
<Empty
115+
description="No environments found"
116+
image={Empty.PRESENTED_IMAGE_SIMPLE}
117+
/>
118+
) : (
119+
/* Table component */
120+
<Table
121+
dataSource={filteredEnvironments}
122+
columns={columns}
123+
rowKey="environmentId"
124+
loading={loading}
125+
pagination={{ pageSize: 10 }}
126+
onRow={(record) => ({
127+
onClick: () => handleRowClick(record),
128+
style: { cursor: 'pointer' }
129+
})}
130+
/>
131+
)}
132+
</div>
133+
);
134+
};
135+
136+
export default EnvironmentsList;

0 commit comments

Comments
 (0)