Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit536e7bb

Browse files
committed
Add Manually create env functionality
1 parent482b802 commit536e7bb

File tree

3 files changed

+251
-15
lines changed

3 files changed

+251
-15
lines changed

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

Lines changed: 54 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
importReact,{useState}from"react";
22
import{Typography,Alert,Input,Button,Space,Empty,Card,Spin,Row,Col,Tooltip,Badge}from"antd";
3-
import{SearchOutlined,CloudServerOutlined,SyncOutlined}from"@ant-design/icons";
3+
import{SearchOutlined,CloudServerOutlined,SyncOutlined,PlusOutlined}from"@ant-design/icons";
44
import{useHistory}from"react-router-dom";
55
import{useEnvironmentContext}from"./context/EnvironmentContext";
66
import{Environment}from"./types/environment.types";
77
importEnvironmentsTablefrom"./components/EnvironmentsTable";
8+
importCreateEnvironmentModalfrom"./components/CreateEnvironmentModal";
89
import{buildEnvironmentId}from"@lowcoder-ee/constants/routesURL";
910
import{getEnvironmentTagColor}from"./utils/environmentUtils";
11+
import{createEnvironment}from"./services/environments.service";
1012

1113
const{ Title, Text}=Typography;
1214

@@ -26,6 +28,8 @@ const EnvironmentsList: React.FC = () => {
2628
// State for search input
2729
const[searchText,setSearchText]=useState("");
2830
const[isRefreshing,setIsRefreshing]=useState(false);
31+
const[isCreateModalVisible,setIsCreateModalVisible]=useState(false);
32+
const[isCreating,setIsCreating]=useState(false);
2933

3034
// Hook for navigation
3135
consthistory=useHistory();
@@ -53,6 +57,20 @@ const EnvironmentsList: React.FC = () => {
5357
setIsRefreshing(false);
5458
};
5559

60+
// Handle create environment
61+
consthandleCreateEnvironment=async(environmentData:Partial<Environment>)=>{
62+
setIsCreating(true);
63+
try{
64+
awaitcreateEnvironment(environmentData);
65+
awaitrefreshEnvironments();// Refresh the list after creation
66+
}catch(error){
67+
console.error("Failed to create environment:",error);
68+
throwerror;// Re-throw to let the modal handle the error display
69+
}finally{
70+
setIsCreating(false);
71+
}
72+
};
73+
5674
// Count environment types
5775
constenvironmentCounts=environments.reduce((counts,env)=>{
5876
consttype=env.environmentType.toUpperCase();
@@ -110,20 +128,33 @@ const EnvironmentsList: React.FC = () => {
110128
</Col>
111129
<Colxs={24}sm={8}style={{textAlign:'right'}}>
112130
<Spacesize="middle">
113-
<Button
114-
icon={<SyncOutlinedspin={isRefreshing}/>}
115-
onClick={handleRefresh}
116-
loading={isLoading}
117-
type="default"
118-
style={{
119-
backgroundColor:'rgba(255, 255, 255, 0.2)',
120-
borderColor:'rgba(255, 255, 255, 0.4)',
121-
color:'white',
122-
fontWeight:500
123-
}}
124-
>
125-
Refresh
126-
</Button>
131+
<Button
132+
icon={<PlusOutlined/>}
133+
onClick={()=>setIsCreateModalVisible(true)}
134+
type="primary"
135+
style={{
136+
backgroundColor:'rgba(255, 255, 255, 0.15)',
137+
borderColor:'rgba(255, 255, 255, 0.4)',
138+
color:'white',
139+
fontWeight:500
140+
}}
141+
>
142+
Create Environment
143+
</Button>
144+
<Button
145+
icon={<SyncOutlinedspin={isRefreshing}/>}
146+
onClick={handleRefresh}
147+
loading={isLoading}
148+
type="default"
149+
style={{
150+
backgroundColor:'rgba(255, 255, 255, 0.2)',
151+
borderColor:'rgba(255, 255, 255, 0.4)',
152+
color:'white',
153+
fontWeight:500
154+
}}
155+
>
156+
Refresh
157+
</Button>
127158
</Space>
128159
</Col>
129160
</Row>
@@ -245,6 +276,14 @@ const EnvironmentsList: React.FC = () => {
245276
</div>
246277
)}
247278
</Card>
279+
280+
{/* Create Environment Modal */}
281+
<CreateEnvironmentModal
282+
visible={isCreateModalVisible}
283+
onClose={()=>setIsCreateModalVisible(false)}
284+
onSave={handleCreateEnvironment}
285+
loading={isCreating}
286+
/>
248287
</div>
249288
);
250289
};
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
importReact,{useState}from'react';
2+
import{Modal,Form,Input,Select,Switch,Button}from'antd';
3+
import{Environment}from'../types/environment.types';
4+
5+
const{ Option}=Select;
6+
7+
interfaceCreateEnvironmentModalProps{
8+
visible:boolean;
9+
onClose:()=>void;
10+
onSave:(data:Partial<Environment>)=>Promise<void>;
11+
loading?:boolean;
12+
}
13+
14+
constCreateEnvironmentModal:React.FC<CreateEnvironmentModalProps>=({
15+
visible,
16+
onClose,
17+
onSave,
18+
loading=false
19+
})=>{
20+
const[form]=Form.useForm();
21+
const[submitLoading,setSubmitLoading]=useState(false);
22+
23+
consthandleSubmit=async()=>{
24+
try{
25+
constvalues=awaitform.validateFields();
26+
setSubmitLoading(true);
27+
28+
awaitonSave(values);
29+
form.resetFields();// Reset form after successful creation
30+
onClose();
31+
}catch(error){
32+
if(errorinstanceofError){
33+
console.error("Form validation or submission error:",error);
34+
}
35+
}finally{
36+
setSubmitLoading(false);
37+
}
38+
};
39+
40+
consthandleCancel=()=>{
41+
form.resetFields();// Reset form when canceling
42+
onClose();
43+
};
44+
45+
return(
46+
<Modal
47+
title="Create New Environment"
48+
open={visible}
49+
onCancel={handleCancel}
50+
maskClosable={true}
51+
destroyOnClose={true}
52+
footer={[
53+
<Buttonkey="back"onClick={handleCancel}>
54+
Cancel
55+
</Button>,
56+
<Button
57+
key="submit"
58+
type="primary"
59+
loading={loading||submitLoading}
60+
onClick={handleSubmit}
61+
>
62+
Create Environment
63+
</Button>
64+
]}
65+
>
66+
<Form
67+
form={form}
68+
layout="vertical"
69+
name="create_environment_form"
70+
initialValues={{
71+
environmentType:"DEV",
72+
isMaster:false
73+
}}
74+
>
75+
<Form.Item
76+
name="environmentName"
77+
label="Environment Name"
78+
rules={[
79+
{required:true,message:'Please enter a name'},
80+
{min:2,message:'Name must be at least 2 characters'}
81+
]}
82+
>
83+
<Inputplaceholder="Enter environment name"/>
84+
</Form.Item>
85+
86+
<Form.Item
87+
name="environmentDescription"
88+
label="Description"
89+
>
90+
<Input.TextArea
91+
placeholder="Enter description"
92+
rows={3}
93+
/>
94+
</Form.Item>
95+
96+
<Form.Item
97+
name="environmentType"
98+
label="Stage"
99+
rules={[{required:true,message:'Please select a stage'}]}
100+
>
101+
<Selectplaceholder="Select stage">
102+
<Optionvalue="DEV">Development (DEV)</Option>
103+
<Optionvalue="TEST">Testing (TEST)</Option>
104+
<Optionvalue="PREPROD">Pre-Production (PREPROD)</Option>
105+
<Optionvalue="PROD">Production (PROD)</Option>
106+
</Select>
107+
</Form.Item>
108+
109+
<Form.Item
110+
name="environmentFrontendUrl"
111+
label="Frontend URL"
112+
rules={[
113+
{type:'url',message:'Please enter a valid URL'}
114+
]}
115+
>
116+
<Inputplaceholder="https://example.com"/>
117+
</Form.Item>
118+
119+
<Form.Item
120+
name="environmentApiServiceUrl"
121+
label="API Service URL"
122+
rules={[
123+
{type:'url',message:'Please enter a valid URL'}
124+
]}
125+
>
126+
<Inputplaceholder="https://api.example.com"/>
127+
</Form.Item>
128+
129+
<Form.Item
130+
name="environmentNodeServiceUrl"
131+
label="Node Service URL"
132+
rules={[
133+
{type:'url',message:'Please enter a valid URL'}
134+
]}
135+
>
136+
<Inputplaceholder="https://node.example.com"/>
137+
</Form.Item>
138+
139+
<Form.Item
140+
name="environmentApikey"
141+
label="API Key"
142+
>
143+
<Input.TextArea
144+
placeholder="Enter API key"
145+
rows={2}
146+
/>
147+
</Form.Item>
148+
149+
<Form.Item
150+
name="isMaster"
151+
label="Master Environment"
152+
valuePropName="checked"
153+
>
154+
<Switch/>
155+
</Form.Item>
156+
</Form>
157+
</Modal>
158+
);
159+
};
160+
161+
exportdefaultCreateEnvironmentModal;

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

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,42 @@ export async function updateEnvironment(
4444
}
4545
}
4646

47+
/**
48+
* Create a new environment manually
49+
*@param environmentData - Environment data to create
50+
*@returns Promise with created environment data
51+
*/
52+
exportasyncfunctioncreateEnvironment(
53+
environmentData:Partial<Environment>
54+
):Promise<Environment>{
55+
try{
56+
// Convert frontend model to API model
57+
constpayload={
58+
environment_description:environmentData.environmentDescription||"",
59+
environment_icon:environmentData.environmentIcon||"",
60+
environment_name:environmentData.environmentName||"",
61+
environment_apikey:environmentData.environmentApikey||"",
62+
environment_type:environmentData.environmentType||"",
63+
environment_api_service_url:environmentData.environmentApiServiceUrl||"",
64+
environment_frontend_url:environmentData.environmentFrontendUrl||"",
65+
environment_node_service_url:environmentData.environmentNodeServiceUrl||"",
66+
isMaster:environmentData.isMaster||false
67+
};
4768

69+
constres=awaitaxios.post(`/api/plugins/enterprise/environments`,payload);
70+
71+
if(res.data){
72+
messageInstance.success("Environment created successfully");
73+
returnres.data;
74+
}else{
75+
thrownewError("Failed to create environment");
76+
}
77+
}catch(err){
78+
consterrorMsg=errinstanceofError ?err.message :"Failed to create environment";
79+
messageInstance.error(errorMsg);
80+
throwerr;
81+
}
82+
}
4883

4984
/**
5085
* Fetch all environments
@@ -100,6 +135,7 @@ export async function getEnvironmentById(id: string): Promise<Environment> {
100135
* Fetch workspaces for a specific environment
101136
*@param environmentId - ID of the environment
102137
*@param apiKey - API key for the environment
138+
*@param apiServiceUrl - API service URL for the environment
103139
*@returns Promise with an array of workspaces
104140
*/
105141
exportasyncfunctiongetEnvironmentWorkspaces(

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp