Skip to content

Commit 0204bf3

Browse files
committed
Add unlicensed environemnt component for Detail page
1 parent d8b761a commit 0204bf3

File tree

2 files changed

+223
-34
lines changed

2 files changed

+223
-34
lines changed

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

Lines changed: 8 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import {
2525

2626
import { useSingleEnvironmentContext } from "./context/SingleEnvironmentContext";
2727
import EditEnvironmentModal from "./components/EditEnvironmentModal";
28+
import UnlicensedEnvironmentView from "./components/UnlicensedEnvironmentView";
2829
import { Environment } from "./types/environment.types";
2930
import history from "@lowcoder-ee/util/history";
3031
import WorkspacesTab from "./components/WorkspacesTab";
@@ -100,43 +101,16 @@ const EnvironmentDetail: React.FC = () => {
100101
);
101102
}
102103

103-
// Check if environment is not licensed and show restriction message
104+
// Check if environment is not licensed and show modern UI
104105
if (environment.isLicensed === false) {
105-
const getLicenseIcon = () => {
106-
switch (environment.licenseStatus) {
107-
case 'unlicensed':
108-
return <CloseCircleOutlined style={{ color: '#ff4d4f' }} />;
109-
case 'error':
110-
return <ExclamationCircleOutlined style={{ color: '#faad14' }} />;
111-
default:
112-
return <CloseCircleOutlined style={{ color: '#ff4d4f' }} />;
113-
}
114-
};
115-
116106
return (
117-
<div style={{ padding: "24px", flex: 1 }}>
118-
<Result
119-
icon={getLicenseIcon()}
120-
title="Environment Access Restricted"
121-
subTitle={`This environment is not licensed. ${environment.licenseError || 'Please check the license configuration.'}`}
122-
extra={[
123-
<Button
124-
type="primary"
125-
key="back"
126-
onClick={() => history.push("/setting/environments")}
127-
>
128-
Back to Environments
129-
</Button>,
130-
<Button
131-
key="edit"
132-
onClick={handleEditClick}
133-
>
134-
Edit Environment
135-
</Button>
136-
]}
107+
<>
108+
<UnlicensedEnvironmentView
109+
environment={environment}
110+
onEditClick={handleEditClick}
137111
/>
138112

139-
{/* Still allow editing the environment to fix license issues */}
113+
{/* Edit Environment Modal */}
140114
{environment && (
141115
<EditEnvironmentModal
142116
visible={isEditModalVisible}
@@ -146,7 +120,7 @@ const EnvironmentDetail: React.FC = () => {
146120
loading={isUpdating}
147121
/>
148122
)}
149-
</div>
123+
</>
150124
);
151125
}
152126

Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
import React from 'react';
2+
import { Button, Card, Space, Typography, Row, Col } from 'antd';
3+
import {
4+
CustomerServiceOutlined,
5+
EditOutlined,
6+
ArrowLeftOutlined,
7+
CloseCircleOutlined,
8+
ExclamationCircleOutlined,
9+
WarningOutlined
10+
} from '@ant-design/icons';
11+
import { Environment } from '../types/environment.types';
12+
import history from "@lowcoder-ee/util/history";
13+
14+
const { Title, Text } = Typography;
15+
16+
interface UnlicensedEnvironmentViewProps {
17+
environment: Environment;
18+
onEditClick: () => void;
19+
}
20+
21+
/**
22+
* Modern UI for unlicensed environments
23+
*/
24+
const UnlicensedEnvironmentView: React.FC<UnlicensedEnvironmentViewProps> = ({
25+
environment,
26+
onEditClick
27+
}) => {
28+
const getLicenseIcon = () => {
29+
switch (environment.licenseStatus) {
30+
case 'unlicensed':
31+
return <CloseCircleOutlined style={{ fontSize: '48px', color: '#ff4d4f' }} />;
32+
case 'error':
33+
return <ExclamationCircleOutlined style={{ fontSize: '48px', color: '#faad14' }} />;
34+
default:
35+
return <WarningOutlined style={{ fontSize: '48px', color: '#ff4d4f' }} />;
36+
}
37+
};
38+
39+
const getLicenseTitle = () => {
40+
switch (environment.licenseStatus) {
41+
case 'unlicensed':
42+
return 'Environment Not Licensed';
43+
case 'error':
44+
return 'License Configuration Error';
45+
default:
46+
return 'License Issue';
47+
}
48+
};
49+
50+
const getLicenseDescription = () => {
51+
if (environment.licenseError) {
52+
return environment.licenseError;
53+
}
54+
55+
switch (environment.licenseStatus) {
56+
case 'unlicensed':
57+
return 'This environment requires a valid license to access its features and functionality.';
58+
case 'error':
59+
return 'There was an error validating the license for this environment. Please check the configuration.';
60+
default:
61+
return 'This environment has license-related issues that need to be resolved.';
62+
}
63+
};
64+
65+
return (
66+
<div style={{
67+
padding: "24px",
68+
flex: 1,
69+
minHeight: '100vh',
70+
background: 'linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%)'
71+
}}>
72+
<Row justify="center" style={{ minHeight: '80vh' }}>
73+
<Col xs={24} sm={20} md={16} lg={14} xl={12}>
74+
<div style={{
75+
display: 'flex',
76+
flexDirection: 'column',
77+
justifyContent: 'center',
78+
alignItems: 'center',
79+
minHeight: '70vh',
80+
textAlign: 'center'
81+
}}>
82+
{/* Main Status Card */}
83+
<Card
84+
style={{
85+
width: '100%',
86+
borderRadius: '16px',
87+
boxShadow: '0 20px 40px rgba(0,0,0,0.1)',
88+
border: 'none',
89+
background: 'white',
90+
overflow: 'hidden'
91+
}}
92+
bodyStyle={{ padding: '48px 32px' }}
93+
>
94+
{/* Status Icon */}
95+
<div style={{ marginBottom: '24px' }}>
96+
{getLicenseIcon()}
97+
</div>
98+
99+
{/* Environment Info */}
100+
<div style={{ marginBottom: '32px' }}>
101+
<Title level={2} style={{ marginBottom: '8px', color: '#262626' }}>
102+
{getLicenseTitle()}
103+
</Title>
104+
<Text style={{
105+
fontSize: '16px',
106+
color: '#595959',
107+
display: 'block',
108+
marginBottom: '16px',
109+
lineHeight: '1.6'
110+
}}>
111+
{getLicenseDescription()}
112+
</Text>
113+
114+
{/* Environment Details */}
115+
<div style={{
116+
background: '#fafafa',
117+
padding: '16px',
118+
borderRadius: '8px',
119+
marginTop: '24px',
120+
border: '1px solid #f0f0f0'
121+
}}>
122+
<Text strong style={{ color: '#8c8c8c', fontSize: '14px' }}>Environment:</Text>
123+
<Text style={{
124+
display: 'block',
125+
fontSize: '16px',
126+
color: '#262626',
127+
marginTop: '4px'
128+
}}>
129+
{environment.environmentName || 'Unnamed Environment'}
130+
</Text>
131+
<Text style={{
132+
fontSize: '13px',
133+
color: '#8c8c8c',
134+
fontFamily: 'monospace'
135+
}}>
136+
ID: {environment.environmentId}
137+
</Text>
138+
</div>
139+
</div>
140+
141+
{/* Action Buttons */}
142+
<Space size="large" direction="vertical" style={{ width: '100%' }}>
143+
<Button
144+
type="primary"
145+
size="large"
146+
icon={<CustomerServiceOutlined />}
147+
style={{
148+
width: '100%',
149+
height: '48px',
150+
borderRadius: '8px',
151+
fontSize: '16px',
152+
fontWeight: 500,
153+
background: 'linear-gradient(135deg, #1890ff 0%, #0050b3 100%)',
154+
border: 'none',
155+
boxShadow: '0 4px 12px rgba(24, 144, 255, 0.3)'
156+
}}
157+
// onClick will be handled later when modal is ready
158+
>
159+
Contact Lowcoder Team
160+
</Button>
161+
162+
<Button
163+
size="large"
164+
icon={<EditOutlined />}
165+
onClick={onEditClick}
166+
style={{
167+
width: '100%',
168+
height: '48px',
169+
borderRadius: '8px',
170+
fontSize: '16px',
171+
fontWeight: 500,
172+
borderColor: '#d9d9d9',
173+
color: '#595959'
174+
}}
175+
>
176+
Edit Environment
177+
</Button>
178+
179+
<Button
180+
size="large"
181+
icon={<ArrowLeftOutlined />}
182+
onClick={() => history.push("/setting/environments")}
183+
style={{
184+
width: '100%',
185+
height: '48px',
186+
borderRadius: '8px',
187+
fontSize: '16px',
188+
fontWeight: 500,
189+
borderColor: '#d9d9d9',
190+
color: '#8c8c8c'
191+
}}
192+
>
193+
Back to Environments
194+
</Button>
195+
</Space>
196+
</Card>
197+
198+
{/* Footer Help Text */}
199+
<Text style={{
200+
marginTop: '24px',
201+
color: '#8c8c8c',
202+
fontSize: '14px',
203+
maxWidth: '400px',
204+
lineHeight: '1.5'
205+
}}>
206+
Need assistance? Contact our team for licensing support or edit the environment configuration to resolve this issue.
207+
</Text>
208+
</div>
209+
</Col>
210+
</Row>
211+
</div>
212+
);
213+
};
214+
215+
export default UnlicensedEnvironmentView;

0 commit comments

Comments
 (0)