1
- import { TacoButton } from "lowcoder-design/src/components/button "
2
- import { ReactNode , useState } from "react" ;
1
+ import { TacoButton , CustomModal , Alert } from "lowcoder-design"
2
+ import { useState , useEffect } from "react" ;
3
3
import { useDispatch } from "react-redux" ;
4
4
import { updateAppMetaAction } from "redux/reduxActions/applicationActions" ;
5
5
import styled from "styled-components" ;
@@ -25,6 +25,11 @@ import { useParams } from "react-router-dom";
25
25
import { messageInstance } from "lowcoder-design/src/components/GlobalInstances" ;
26
26
import { FolderIcon } from "icons" ;
27
27
import { BrandedIcon } from "@lowcoder-ee/components/BrandedIcon" ;
28
+ import { Typography } from "antd" ;
29
+ import { default as Form } from "antd/es/form" ;
30
+ import { default as Input } from "antd/es/input" ;
31
+ import { MultiIconDisplay } from "@lowcoder-ee/comps/comps/multiIconDisplay" ;
32
+ import { FormStyled } from "../setting/idSource/styledComponents" ;
28
33
29
34
const ExecButton = styled ( TacoButton ) `
30
35
width: 52px;
@@ -50,14 +55,16 @@ const ExecButton = styled(TacoButton)`
50
55
` ;
51
56
52
57
const Wrapper = styled . div `
53
- height: 67px;
54
58
padding: 0 6px;
55
59
border-radius: 8px;
56
- margin-bottom: -1px;
57
- margin-top: 1px;
58
-
60
+ margin-bottom: 2px;
61
+ margin-top: 2px;
62
+ padding-top: 10px;
63
+ padding-bottom: 10px;
64
+ background-color: #fcfcfc;
65
+ min-height: 100px;
59
66
&:hover {
60
- background-color: #f5f7fa;
67
+ background-color: #f5f5f6
61
68
}
62
69
` ;
63
70
@@ -98,7 +105,6 @@ const CardInfo = styled.div`
98
105
height: 100%;
99
106
flex-grow: 1;
100
107
cursor: pointer;
101
- overflow: hidden;
102
108
padding-right: 12px;
103
109
104
110
&:hover {
@@ -124,6 +130,7 @@ const AppTimeOwnerInfoLabel = styled.div`
124
130
const OperationWrapper = styled . div `
125
131
display: flex;
126
132
align-items: center;
133
+ padding-right: 10px;
127
134
@media screen and (max-width: 500px) {
128
135
> svg {
129
136
display: none;
@@ -133,9 +140,75 @@ const OperationWrapper = styled.div`
133
140
134
141
const MONTH_MILLIS = 30 * 24 * 60 * 60 * 1000 ;
135
142
143
+ interface UpdateAppModalProps {
144
+ visible : boolean ;
145
+ onCancel : ( ) => void ;
146
+ onOk : ( values : any ) => void ;
147
+ res : HomeRes ;
148
+ folderId ?: string ;
149
+ }
150
+
151
+ export function UpdateAppModal ( { visible, onCancel, onOk, res, folderId } : UpdateAppModalProps ) {
152
+ const [ detailsForm ] = Form . useForm ( ) ;
153
+
154
+ // Reset form values when res changes
155
+ useEffect ( ( ) => {
156
+ if ( res && visible ) {
157
+ detailsForm . setFieldsValue ( {
158
+ appName : res . name ,
159
+ title : res . title
160
+ } ) ;
161
+ }
162
+ } , [ res , visible , detailsForm ] ) ;
163
+
164
+ return (
165
+ < CustomModal
166
+ title = { trans ( "home.updateAppName" ) }
167
+ open = { visible }
168
+ destroyOnHidden
169
+ onCancel = { onCancel }
170
+ showCancelButton = { false }
171
+ showOkButton
172
+ width = "440px"
173
+ okText = { trans ( "finish" ) }
174
+ onOk = { ( ) => {
175
+ detailsForm . validateFields ( ) . then ( ( values ) => {
176
+ onOk ( values ) ;
177
+ } ) . catch ( ( errorInfo ) => {
178
+ console . error ( 'Validation failed:' , errorInfo ) ;
179
+ } ) ;
180
+ } }
181
+ >
182
+ < FormStyled
183
+ form = { detailsForm }
184
+ name = "general"
185
+ layout = "vertical"
186
+ style = { { maxWidth : '100%' } }
187
+ autoComplete = "off"
188
+ >
189
+ { res . title &&
190
+ < Alert label = { trans ( "home.titleUpdateWarning" ) } type = "warning" /> }
191
+ < br />
192
+
193
+ < Form . Item label = { trans ( "home.name" ) } name = "appName" >
194
+ < Input />
195
+ </ Form . Item >
196
+
197
+ { res . title && (
198
+ < Form . Item label = { trans ( "title" ) } name = "title" >
199
+ < Input disabled />
200
+ </ Form . Item >
201
+ ) }
202
+
203
+ </ FormStyled >
204
+ </ CustomModal >
205
+ ) ;
206
+ }
207
+
136
208
export function HomeResCard ( props : { res : HomeRes ; onMove : ( res : HomeRes ) => void ; setModify :any ; modify : boolean } ) {
137
209
const { res, onMove, setModify, modify } = props ;
138
210
const [ appNameEditing , setAppNameEditing ] = useState ( false ) ;
211
+ const [ dialogVisible , setDialogVisible ] = useState ( false )
139
212
const dispatch = useDispatch ( ) ;
140
213
141
214
const { folderId } = useParams < { folderId : string } > ( ) ;
@@ -161,96 +234,137 @@ export function HomeResCard(props: { res: HomeRes; onMove: (res: HomeRes) => voi
161
234
else if ( res . type === HomeResTypeEnum . NavLayout || res . type === HomeResTypeEnum . MobileTabLayout ) {
162
235
iconColor = "#af41ff" ;
163
236
}
164
-
165
237
const Icon = resInfo . icon ;
166
238
239
+ const handleModalOk = ( values : any ) => {
240
+ dispatch (
241
+ updateAppMetaAction ( { applicationId : res . id , name : values . appName || res . name , folderId : folderId } )
242
+ ) ;
243
+
244
+ setDialogVisible ( false ) ;
245
+ setTimeout ( ( ) => {
246
+ setModify ( ! modify ) ;
247
+ } , 200 ) ;
248
+ } ;
249
+
167
250
return (
168
- < Wrapper >
169
- < Card >
170
- { Icon && (
171
- < BrandedIcon >
172
- < Icon width = { "42px" } height = { "42px" } style = {
173
- {
174
- color : iconColor ,
175
- marginRight : "10px" ,
176
- flexShrink : 0
177
- }
178
- } />
179
- </ BrandedIcon >
180
- ) }
181
- < CardInfo
182
- onClick = { ( e ) => {
183
- if ( appNameEditing ) {
184
- return ;
185
- }
186
- if ( res . type === HomeResTypeEnum . Folder ) {
187
- handleFolderViewClick ( res . id ) ;
188
- } else {
189
- if ( checkIsMobile ( window . innerWidth ) ) {
190
- history . push ( APPLICATION_VIEW_URL ( res . id , "view" ) ) ;
191
- return ;
192
- }
193
- if ( res . isMarketplace ) {
194
- handleMarketplaceAppViewClick ( res . id ) ;
195
- return ;
196
- }
197
- res . isEditable ? handleAppEditClick ( e , res . id ) : handleAppViewClick ( res . id ) ;
198
- }
199
- } }
200
- >
201
- < TypographyText
202
- value = { res . name }
203
- editing = { appNameEditing }
204
- onChange = { ( value ) => {
205
- if ( ! value . trim ( ) ) {
206
- messageInstance . warning ( trans ( "home.nameCheckMessage" ) ) ;
251
+ < >
252
+ < UpdateAppModal
253
+ visible = { dialogVisible }
254
+ onCancel = { ( ) => setDialogVisible ( false ) }
255
+ onOk = { handleModalOk }
256
+ res = { res }
257
+ folderId = { folderId }
258
+ />
259
+
260
+ < Wrapper >
261
+ < Card >
262
+ { res . icon ?
263
+ < MultiIconDisplay
264
+ identifier = { res . icon && typeof res . icon === 'string' ? res . icon : '/icon:antd/appstoreoutlined' }
265
+ width = "30px"
266
+ height = "30px"
267
+ style = { {
268
+ marginRight : "6px" ,
269
+ flexShrink : 0 ,
270
+ color : "#b766db"
271
+ } }
272
+ /> :
273
+ Icon && (
274
+ < BrandedIcon >
275
+ < Icon width = { "42px" } height = { "42px" } style = {
276
+ {
277
+ color : iconColor ,
278
+ marginRight : "10px" ,
279
+ flexShrink : 0
280
+ }
281
+ } />
282
+ </ BrandedIcon >
283
+ )
284
+ }
285
+ < CardInfo
286
+ onClick = { ( e ) => {
287
+ if ( appNameEditing ) {
207
288
return ;
208
289
}
209
290
if ( res . type === HomeResTypeEnum . Folder ) {
210
- dispatch ( updateFolder ( { id : res . id , name : value } ) ) ;
211
- setTimeout ( ( ) => {
212
- setModify ( ! modify ) ;
213
- } , 200 ) ;
291
+ handleFolderViewClick ( res . id ) ;
214
292
} else {
215
- dispatch (
216
- updateAppMetaAction ( { applicationId : res . id , name : value , folderId : folderId } )
217
- ) ;
218
- setTimeout ( ( ) => {
219
- setModify ( ! modify ) ;
220
- } , 200 ) ;
293
+ if ( checkIsMobile ( window . innerWidth ) ) {
294
+ history . push ( APPLICATION_VIEW_URL ( res . id , "view" ) ) ;
295
+ return ;
296
+ }
297
+ if ( res . isMarketplace ) {
298
+ handleMarketplaceAppViewClick ( res . id ) ;
299
+ return ;
300
+ }
301
+ res . isEditable ? handleAppEditClick ( e , res . id ) : handleAppViewClick ( res . id ) ;
221
302
}
222
- setAppNameEditing ( false ) ;
223
303
} }
224
- />
225
- < AppTimeOwnerInfoLabel title = { subTitle } > { subTitle } </ AppTimeOwnerInfoLabel >
226
- </ CardInfo >
227
- < OperationWrapper >
228
- { /* {res.isEditable && (
229
- <EditButton onClick={(e) => handleAppEditClick(e, res.id)} buttonType="primary">
230
- {trans("edit")}
231
- </EditButton>
232
- )} */ }
233
- < ExecButton
234
- onClick = { ( ) =>
235
- res . type === HomeResTypeEnum . Folder
236
- ? handleFolderViewClick ( res . id )
237
- : res . isMarketplace
238
- ? handleMarketplaceAppViewClick ( res . id )
239
- : handleAppViewClick ( res . id )
240
- }
241
304
>
242
- { trans ( "view" ) }
243
- </ ExecButton >
244
- < HomeResOptions
245
- res = { res }
246
- onRename = { ( ) => setAppNameEditing ( true ) }
247
- onMove = { ( res ) => onMove ( res ) }
248
- setModify = { setModify }
249
- modify = { modify }
250
- />
251
- </ OperationWrapper >
252
- </ Card >
253
- </ Wrapper >
305
+ < TypographyText
306
+ value = { res . title || res . name }
307
+ editing = { false }
308
+ onChange = { ( value ) => {
309
+ if ( ! value . trim ( ) ) {
310
+ messageInstance . warning ( trans ( "home.nameCheckMessage" ) ) ;
311
+ return ;
312
+ }
313
+ if ( res . type === HomeResTypeEnum . Folder ) {
314
+ dispatch ( updateFolder ( { id : res . id , name : value } ) ) ;
315
+ setTimeout ( ( ) => {
316
+ setModify ( ! modify ) ;
317
+ } , 200 ) ;
318
+ } else {
319
+ dispatch (
320
+ updateAppMetaAction ( { applicationId : res . id , name : value , folderId : folderId } )
321
+ ) ;
322
+ setTimeout ( ( ) => {
323
+ setModify ( ! modify ) ;
324
+ } , 200 ) ;
325
+ }
326
+ setAppNameEditing ( false ) ;
327
+ } }
328
+ />
329
+
330
+ { res ?. description
331
+ && < Typography . Text
332
+ type = "secondary"
333
+ style = { { fontSize : 12 , textWrap : "wrap" } }
334
+ >
335
+ { res ?. description }
336
+ </ Typography . Text > }
337
+
338
+ < AppTimeOwnerInfoLabel title = { subTitle } > { subTitle } </ AppTimeOwnerInfoLabel >
339
+ </ CardInfo >
340
+ < OperationWrapper >
341
+ { /* {res.isEditable && (
342
+ <EditButton onClick={(e) => handleAppEditClick(e, res.id)} buttonType="primary">
343
+ {trans("edit")}
344
+ </EditButton>
345
+ )} */ }
346
+ < ExecButton
347
+ onClick = { ( ) =>
348
+ res . type === HomeResTypeEnum . Folder
349
+ ? handleFolderViewClick ( res . id )
350
+ : res . isMarketplace
351
+ ? handleMarketplaceAppViewClick ( res . id )
352
+ : handleAppViewClick ( res . id )
353
+ }
354
+ >
355
+ { trans ( "view" ) }
356
+ </ ExecButton >
357
+ < HomeResOptions
358
+ res = { res }
359
+ onRename = { ( ) => setDialogVisible ( true ) }
360
+ onMove = { ( res ) => onMove ( res ) }
361
+ setModify = { setModify }
362
+ modify = { modify }
363
+ />
364
+ </ OperationWrapper >
365
+ </ Card >
366
+ </ Wrapper >
367
+ </ >
254
368
) ;
255
369
}
256
370
0 commit comments