Skip to content

Commit d2d7ede

Browse files
committed
Update Environments UI
1 parent 0abe597 commit d2d7ede

File tree

10 files changed

+316
-308
lines changed

10 files changed

+316
-308
lines changed

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

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,8 @@ const EnvironmentDetail: React.FC = () => {
8585

8686
if (isLoading) {
8787
return (
88-
<div style={{ display: 'flex', justifyContent: 'center', padding: '50px' }}>
89-
<Spin size="large" tip="Loading environment..." style={{ display: 'block', textAlign: 'center' }} />
88+
<div style={{ display: 'flex', justifyContent: 'center', padding: '60px 0' }}>
89+
<Spin size="large" />
9090
</div>
9191
);
9292
}
@@ -151,19 +151,21 @@ const EnvironmentDetail: React.FC = () => {
151151
onEditClick={handleEditClick}
152152
/>
153153

154-
155-
156-
{/* Basic Environment Information Card - improved responsiveness */}
154+
{/* Basic Environment Information Card */}
157155
<Card
158156
title="Environment Overview"
159-
style={{ marginBottom: "24px", borderRadius: '8px', boxShadow: '0 2px 8px rgba(0,0,0,0.05)' }}
157+
style={{
158+
marginBottom: "24px",
159+
borderRadius: '4px',
160+
border: '1px solid #f0f0f0'
161+
}}
160162
className="environment-overview-card"
161163
>
162164
<Descriptions
163165
bordered
164-
layout="vertical" // Change to vertical layout on smaller screens
166+
layout="vertical"
165167
column={{ xxl: 4, xl: 3, lg: 3, md: 2, sm: 1, xs: 1 }}
166-
size="small" // Use smaller size on mobile
168+
size="small"
167169
>
168170
<Descriptions.Item label="Domain">
169171
{environment.environmentFrontendUrl ? (
@@ -181,7 +183,7 @@ const EnvironmentDetail: React.FC = () => {
181183
<Descriptions.Item label="Environment Type">
182184
<Tag
183185
color={getEnvironmentTagColor(environment.environmentType)}
184-
style={{ borderRadius: '12px' }}
186+
style={{ borderRadius: '4px' }}
185187
>
186188
{environment.environmentType}
187189
</Tag>
@@ -190,23 +192,23 @@ const EnvironmentDetail: React.FC = () => {
190192
{(() => {
191193
switch (environment.licenseStatus) {
192194
case 'checking':
193-
return <Tag icon={<SyncOutlined spin />} color="blue" style={{ borderRadius: '12px' }}>Checking...</Tag>;
195+
return <Tag icon={<SyncOutlined spin />} color="blue" style={{ borderRadius: '4px' }}>Checking...</Tag>;
194196
case 'licensed':
195-
return <Tag icon={<CheckCircleOutlined />} color="green" style={{ borderRadius: '12px' }}>Licensed</Tag>;
197+
return <Tag icon={<CheckCircleOutlined />} color="green" style={{ borderRadius: '4px' }}>Licensed</Tag>;
196198
case 'unlicensed':
197-
return <Tag icon={<CloseCircleOutlined />} color="red" style={{ borderRadius: '12px' }}>Not Licensed</Tag>;
199+
return <Tag icon={<CloseCircleOutlined />} color="red" style={{ borderRadius: '4px' }}>Not Licensed</Tag>;
198200
case 'error':
199-
return <Tag icon={<ExclamationCircleOutlined />} color="orange" style={{ borderRadius: '12px' }}>License Error</Tag>;
201+
return <Tag icon={<ExclamationCircleOutlined />} color="orange" style={{ borderRadius: '4px' }}>License Error</Tag>;
200202
default:
201-
return <Tag color="default" style={{ borderRadius: '12px' }}>Unknown</Tag>;
203+
return <Tag color="default" style={{ borderRadius: '4px' }}>Unknown</Tag>;
202204
}
203205
})()}
204206
</Descriptions.Item>
205207
<Descriptions.Item label="API Key Status">
206208
{environment.environmentApikey ? (
207-
<Tag color="green" style={{ borderRadius: '12px' }}>Configured</Tag>
209+
<Tag color="green" style={{ borderRadius: '4px' }}>Configured</Tag>
208210
) : (
209-
<Tag color="red" style={{ borderRadius: '12px' }}>Not Configured</Tag>
211+
<Tag color="red" style={{ borderRadius: '4px' }}>Not Configured</Tag>
210212
)}
211213
</Descriptions.Item>
212214
<Descriptions.Item label="Master Environment">
@@ -217,13 +219,20 @@ const EnvironmentDetail: React.FC = () => {
217219

218220
{/* Modern Breadcrumbs navigation */}
219221
<ModernBreadcrumbs items={breadcrumbItems} />
222+
220223
{/* Tabs for Workspaces and User Groups */}
221224
<Tabs
222225
defaultActiveKey="workspaces"
223226
activeKey={activeTab}
224227
onChange={setActiveTab}
225228
className="modern-tabs"
226-
type="card"
229+
type="line"
230+
style={{
231+
background: '#fff',
232+
borderRadius: '4px',
233+
border: '1px solid #f0f0f0',
234+
padding: '0'
235+
}}
227236
>
228237
<TabPane
229238
tab={
@@ -233,7 +242,6 @@ const EnvironmentDetail: React.FC = () => {
233242
}
234243
key="workspaces"
235244
>
236-
{/* Using our new standalone WorkspacesTab component */}
237245
<WorkspacesTab environment={environment} />
238246
</TabPane>
239247

@@ -245,7 +253,6 @@ const EnvironmentDetail: React.FC = () => {
245253
}
246254
key="userGroups"
247255
>
248-
{/* Now using our standalone UserGroupsTab component */}
249256
<UserGroupsTab environment={environment} />
250257
</TabPane>
251258
</Tabs>

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

Lines changed: 83 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React, { useState, useEffect } from "react";
2-
import { Alert, Empty, Spin } from "antd";
3-
import { SyncOutlined } from "@ant-design/icons";
2+
import { Alert, Empty, Spin, Row, Col, Card } from "antd";
3+
import { SyncOutlined, CloudServerOutlined } from "@ant-design/icons";
44
import { AddIcon, Search, TacoButton } from "lowcoder-design";
55
import { useHistory } from "react-router-dom";
66
import { useSelector, useDispatch } from "react-redux";
@@ -11,6 +11,7 @@ import EnvironmentsTable from "./components/EnvironmentsTable";
1111
import CreateEnvironmentModal from "./components/CreateEnvironmentModal";
1212
import { buildEnvironmentId } from "@lowcoder-ee/constants/routesURL";
1313
import { createEnvironment } from "./services/environments.service";
14+
import { getEnvironmentTagColor } from "./utils/environmentUtils";
1415
import styled from "styled-components";
1516

1617
const EnvironmentsWrapper = styled.div`
@@ -54,6 +55,10 @@ const BodyWrapper = styled.div`
5455
padding: 0 24px;
5556
`;
5657

58+
const StatsWrapper = styled.div`
59+
margin-bottom: 20px;
60+
`;
61+
5762
/**
5863
* Environment Listing Page Component
5964
* Displays a table of environments
@@ -73,6 +78,65 @@ const EnvironmentsList: React.FC = () => {
7378
// Hook for navigation
7479
const history = useHistory();
7580

81+
// Calculate environment type statistics
82+
const environmentStats = React.useMemo(() => {
83+
const stats = environments.reduce((acc, env) => {
84+
const type = env.environmentType.toUpperCase();
85+
acc[type] = (acc[type] || 0) + 1;
86+
return acc;
87+
}, {} as Record<string, number>);
88+
89+
// Sort by common environment types first
90+
const typeOrder = ['PROD', 'PREPROD', 'TEST', 'DEV'];
91+
const sortedStats = Object.entries(stats).sort(([a], [b]) => {
92+
const aIndex = typeOrder.indexOf(a);
93+
const bIndex = typeOrder.indexOf(b);
94+
95+
if (aIndex !== -1 && bIndex !== -1) return aIndex - bIndex;
96+
if (aIndex !== -1) return -1;
97+
if (bIndex !== -1) return 1;
98+
return a.localeCompare(b);
99+
});
100+
101+
return sortedStats;
102+
}, [environments]);
103+
104+
// Get icon for environment type
105+
const getEnvironmentIcon = (type: string) => {
106+
return <CloudServerOutlined />;
107+
};
108+
109+
// Stat card component
110+
const StatCard = ({ title, value, color }: { title: string; value: number; color: string }) => (
111+
<Card
112+
style={{
113+
height: '100%',
114+
borderRadius: '4px',
115+
border: '1px solid #f0f0f0'
116+
}}
117+
>
118+
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
119+
<div>
120+
<div style={{ fontSize: '13px', color: '#8c8c8c', marginBottom: '8px' }}>{title}</div>
121+
<div style={{ fontSize: '20px', fontWeight: 500 }}>{value}</div>
122+
</div>
123+
<div style={{
124+
fontSize: '24px',
125+
opacity: 0.8,
126+
color: color,
127+
padding: '8px',
128+
backgroundColor: `${color}15`,
129+
borderRadius: '4px',
130+
display: 'flex',
131+
alignItems: 'center',
132+
justifyContent: 'center'
133+
}}>
134+
{getEnvironmentIcon(title)}
135+
</div>
136+
</div>
137+
</Card>
138+
);
139+
76140
// Filter environments based on search text
77141
const filteredEnvironments = environments.filter((env) => {
78142
const searchLower = searchText.toLowerCase();
@@ -133,7 +197,6 @@ const EnvironmentsList: React.FC = () => {
133197
buttonType="normal"
134198
icon={<SyncOutlined spin={isLoading} />}
135199
onClick={handleRefresh}
136-
loading={isLoading}
137200
>
138201
Refresh
139202
</RefreshBtn>
@@ -143,6 +206,23 @@ const EnvironmentsList: React.FC = () => {
143206
</HeaderWrapper>
144207

145208
<BodyWrapper>
209+
{/* Environment Type Statistics */}
210+
{!isLoading && environments.length > 0 && (
211+
<StatsWrapper>
212+
<Row gutter={[16, 16]} style={{ marginBottom: '20px' }}>
213+
{environmentStats.map(([type, count]) => (
214+
<Col xs={24} sm={12} md={8} lg={6} key={type}>
215+
<StatCard
216+
title={type}
217+
value={count}
218+
color={getEnvironmentTagColor(type.toLowerCase())}
219+
/>
220+
</Col>
221+
))}
222+
</Row>
223+
</StatsWrapper>
224+
)}
225+
146226
{/* Error handling */}
147227
{error && (
148228
<Alert

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,17 @@ const WorkspaceDetail: React.FC = () => {
118118
<ModernBreadcrumbs items={breadcrumbItems} />
119119

120120
{/* Tabs for Apps, Data Sources, and Queries */}
121-
<Tabs defaultActiveKey="apps" className="modern-tabs" type="card">
121+
<Tabs
122+
defaultActiveKey="apps"
123+
className="modern-tabs"
124+
type="line"
125+
style={{
126+
background: '#fff',
127+
borderRadius: '4px',
128+
border: '1px solid #f0f0f0',
129+
padding: '0'
130+
}}
131+
>
122132
<TabPane tab={<span><AppstoreOutlined /> Apps</span>} key="apps">
123133
<AppsTab
124134
environment={environment}

0 commit comments

Comments
 (0)