@@ -9,11 +9,11 @@ import {
9
9
LeftClose ,
10
10
LeftCommon ,
11
11
LeftOpen ,
12
- PadDiv ,
13
12
ScrollBar ,
14
13
Tooltip ,
15
14
UnfoldIcon ,
16
15
UnShow ,
16
+ TacoButton ,
17
17
} from "lowcoder-design" ;
18
18
import React , { ReactNode , useCallback , useContext , useMemo , useState } from "react" ;
19
19
import { hookCompCategory } from "comps/hooks/hookCompTypes" ;
@@ -32,13 +32,33 @@ import type { UICompType } from "comps/uiCompRegistry";
32
32
import { CollapseWrapper , DirectoryTreeStyle , Node } from "./styledComponents" ;
33
33
import { DataNode , EventDataNode } from "antd/es/tree" ;
34
34
import { isAggregationApp } from "util/appUtils" ;
35
+ import Modal from "antd/es/modal/Modal" ;
36
+ import copyToClipboard from "copy-to-clipboard" ;
35
37
36
38
const CollapseTitleWrapper = styled . div `
37
39
display: flex;
38
40
width: fit-content;
39
41
max-width: calc(100% - 8px);
40
42
` ;
41
43
44
+ const PadDiv = styled . div `
45
+ padding: 8px;
46
+ display: flex;
47
+ justify-content: space-between;
48
+ align-items: center;
49
+
50
+ &:hover .copy-icon {
51
+ visibility: visible;
52
+ }
53
+ ` ;
54
+
55
+ const CopyIcon = styled ( CopyTextButton ) `
56
+ visibility: hidden;
57
+ margin-left: 8px;
58
+ color: #1890ff;
59
+ cursor: pointer;
60
+ ` ;
61
+
42
62
function getLen ( config : string | boolean | number ) {
43
63
if ( typeof config === "number" ) {
44
64
return ( config + "" ) . toString ( ) . length ;
@@ -49,47 +69,48 @@ function getLen(config: string | boolean | number) {
49
69
return 0 ;
50
70
}
51
71
52
- function toDataView ( value : any , name : string , desc ?: ReactNode ) {
72
+ function toDataView ( value : any , name : string , desc ?: ReactNode , modal ?: boolean ) {
53
73
const str = typeof value === "function" ? "Function" : safeJSONStringify ( value ) ;
54
74
const descRecord : Record < string , ReactNode > = { } ;
75
+ const shortenedString = modal === true ? ( getLen ( str ) > 42 ? str . slice ( 0 , 42 ) + "..." : str ) : ( getLen ( str ) > 20 ? str . slice ( 0 , 20 ) + "..." : str ) ;
55
76
descRecord [ name ] = desc ;
56
77
if ( Array . isArray ( value ) ) {
57
78
const dataChild : Record < string , any > = { } ;
58
79
value . forEach ( ( valueChild , index ) => {
59
80
dataChild [ index ] = valueChild ;
60
81
} ) ;
61
82
return (
62
- < CollapseView name = { name } desc = { descRecord } data = { dataChild } isArray = { true } key = { name } />
83
+ < CollapseView name = { name } desc = { descRecord } data = { dataChild } isArray = { true } key = { name } modal = { modal } />
63
84
) ;
64
85
} else if ( _ . isPlainObject ( value ) ) {
65
- return < CollapseView name = { name } desc = { descRecord } data = { value } key = { name } /> ;
66
- }
67
-
68
- return (
69
- < PadDiv key = { name } >
70
- < Tooltip title = { desc } placement = { "right" } >
71
- < Label label = { name } />
72
- ​
73
- </ Tooltip >
74
-
75
- < Tooltip
76
- title = {
77
- getLen ( str ) > 50 ? (
78
- < div style = { { display : "flex" , wordBreak : "break-all" } } >
79
- { getLen ( str ) > 300 ? str . slice ( 0 , 300 ) + "..." : str }
80
- < CopyTextButton text = { value } style = { { color : "#fff" , margin : "4px 0 0 6px" } } />
81
- </ div >
82
- ) : null
83
- }
84
- placement = { "right" }
86
+ return (
87
+ < CollapseView name = { name } desc = { descRecord } data = { value } key = { name } modal = { modal } />
88
+ ) ;
89
+ } else {
90
+ return (
91
+ < PadDiv
92
+ style = { { marginLeft : "20px" , borderBottom : "1px solid #f0f0f0" , height : "32px" , display : 'flex' , justifyContent : 'space-between' , alignItems : 'center' } }
93
+ key = { name }
85
94
>
86
- ​
87
- < Label color = "#FF9816" label = { getLen ( str ) > 50 ? str . slice ( 0 , 50 ) + "..." : str } />
88
- </ Tooltip >
89
- </ PadDiv >
90
- ) ;
95
+ < Tooltip title = { desc } placement = { "right" } >
96
+ < Label label = { name } /> ​
97
+ </ Tooltip >
98
+
99
+ < div style = { { display : "flex" , wordBreak : "break-all" , textAlign : "right" } } >
100
+ < span style = { { marginRight : "10px" } } > { shortenedString } </ span >
101
+ { getLen ( str ) > 0 &&
102
+ < CopyTextButton text = { value } style = { { color : "#ccc" , marginRight : "0px" , marginTop : "4px" } } />
103
+ }
104
+ </ div >
105
+
106
+ </ PadDiv >
107
+ ) ;
108
+ }
91
109
}
92
110
111
+
112
+ export default toDataView ;
113
+
93
114
function sliceArr ( arr : string [ ] ) {
94
115
let preArr : string [ ] = [ ] ;
95
116
let afterArr : string [ ] = [ ] ;
@@ -104,23 +125,23 @@ function sliceArr(arr: string[]) {
104
125
return { preArr, afterArr } as const ;
105
126
}
106
127
107
- function toData ( props : { data : Record < string , any > ; desc ?: Record < string , ReactNode > } ) {
128
+ function toData ( props : { data : Record < string , any > ; desc ?: Record < string , ReactNode > , modal ?: boolean } ) {
108
129
const totalArr = Object . keys ( props . data ) ;
109
130
const sliceFn = sliceArr ;
110
131
return (
111
132
< div >
112
133
{ totalArr . length < 30 ? (
113
134
totalArr . map ( ( name ) => {
114
- return toDataView ( props . data [ name ] , name , props . desc ?. [ name ] ) ;
135
+ return toDataView ( props . data [ name ] , name , props . desc ?. [ name ] , props . modal ) ;
115
136
} )
116
137
) : (
117
138
< >
118
139
{ sliceFn ( totalArr ) . preArr . map ( ( name ) => {
119
- return toDataView ( props . data [ name ] , name , props . desc ?. [ name ] ) ;
140
+ return toDataView ( props . data [ name ] , name , props . desc ?. [ name ] , props . modal ) ;
120
141
} ) }
121
142
< UnShow num = { totalArr . length - 6 } />
122
143
{ sliceFn ( totalArr ) . afterArr . map ( ( name ) => {
123
- return toDataView ( props . data [ name ] , name , props . desc ?. [ name ] ) ;
144
+ return toDataView ( props . data [ name ] , name , props . desc ?. [ name ] , props . modal ) ;
124
145
} ) }
125
146
</ >
126
147
) }
@@ -137,6 +158,8 @@ const CollapseView = React.memo(
137
158
onClick ?: ( compName : string ) => void ;
138
159
isSelected ?: boolean ;
139
160
isOpen ?: boolean ;
161
+ children ?: React . ReactNode ; // Accept children
162
+ modal ?: boolean ;
140
163
} ) => {
141
164
const { data = { } } = props ;
142
165
const onlyOne = Object . keys ( data ) . length === 1 ;
@@ -148,47 +171,53 @@ const CollapseView = React.memo(
148
171
{
149
172
key : props . name ,
150
173
title : (
151
- < Tooltip
152
- title = { props . desc ?. [ props . name ] }
153
- placement = { "right" }
154
- >
155
- < CollapseTitleWrapper onClick = { ( ) => props . onClick && props . onClick ( props . name ) } >
156
- < Title
157
- style = { {
158
- whiteSpace : "nowrap" ,
159
- textOverflow : "ellipsis" ,
160
- overflow : "hidden" ,
161
- } }
162
- label = { props . name }
163
- hasChild = { Object . keys ( data ) . length > 0 }
164
- />
165
- < Title
166
- style = { { flexShrink : 0 } }
167
- color = "#8B8FA3"
168
- label = { `${ props . isArray ? "[]" : "{}" } ${ trans (
169
- props . isArray
170
- ? onlyOne
171
- ? "leftPanel.propTipArr"
172
- : "leftPanel.propTipsArr"
173
- : onlyOne
174
- ? "leftPanel.propTip"
175
- : "leftPanel.propTips" ,
176
- {
177
- num : Object . keys ( data ) . length ,
178
- }
179
- ) } `}
180
- />
181
- </ CollapseTitleWrapper >
182
- </ Tooltip >
174
+ < div style = { { display : 'flex' , justifyContent : 'space-between' , alignItems : 'center' } } >
175
+ < Tooltip
176
+ title = { props . desc ?. [ props . name ] }
177
+ placement = { "right" }
178
+ >
179
+ < CollapseTitleWrapper onClick = { ( ) => props . onClick && props . onClick ( props . name ) } >
180
+ < Title
181
+ style = { {
182
+ whiteSpace : "nowrap" ,
183
+ textOverflow : "ellipsis" ,
184
+ overflow : "hidden" ,
185
+ } }
186
+ label = { props . name }
187
+ hasChild = { Object . keys ( data ) . length > 0 }
188
+ />
189
+ < Title
190
+ style = { { flexShrink : 0 } }
191
+ color = "#8B8FA3"
192
+ label = { `${ props . isArray ? "[]" : "{}" } ${ trans (
193
+ props . isArray
194
+ ? onlyOne
195
+ ? "leftPanel.propTipArr"
196
+ : "leftPanel.propTipsArr"
197
+ : onlyOne
198
+ ? "leftPanel.propTip"
199
+ : "leftPanel.propTips" ,
200
+ {
201
+ num : Object . keys ( data ) . length ,
202
+ }
203
+ ) } `}
204
+ />
205
+ </ CollapseTitleWrapper >
206
+ </ Tooltip >
207
+ { Object . keys ( data ) . length > 0 &&
208
+ < CopyTextButton text = { JSON . stringify ( data ) } style = { { color : "#aaa" , marginRight : "8px" } } />
209
+ }
210
+ </ div >
183
211
) ,
184
- data : toData ( { data, desc : props . desc } ) ,
212
+ data : toData ( { data, desc : props . desc , modal : props . modal } ) ,
185
213
} ,
186
214
] }
187
215
/>
188
216
) ;
189
217
}
190
218
) ;
191
219
220
+
192
221
interface LeftContentProps {
193
222
uiComp : InstanceType < typeof UIComp > ;
194
223
}
@@ -324,13 +353,23 @@ export const LeftContent = (props: LeftContentProps) => {
324
353
const getTreeNode = ( node : NodeItem , uiCompInfos : CompInfo [ ] ) => {
325
354
const info = showData . find ( ( item ) => item . key === node . key ) ;
326
355
const data = uiCompInfos . find ( ( item ) => item . name === node . title ) ;
356
+
357
+ const prepareData = ( data : Record < string , any > , desc ?: Record < string , ReactNode > ) => {
358
+ return (
359
+ < div >
360
+ { Object . keys ( data ) . map ( ( name ) => {
361
+ return toDataView ( data [ name ] , name , desc ?. [ name ] , true ) ;
362
+ } ) }
363
+ </ div >
364
+ ) ;
365
+ } ;
366
+
327
367
return (
328
- < Node >
368
+ < Node key = { node . key } >
329
369
< span >
330
- < span > { node . title } </ span >
331
- { data &&
332
- ! ! Object . keys ( data . data ) ?. length &&
333
- ( info ?. show ? (
370
+ < span > { node . title } </ span >
371
+ { data && ! ! Object . keys ( data . data ) ?. length && (
372
+ info ?. show ? (
334
373
< Tooltip
335
374
placement = "right"
336
375
title = { trans ( "leftPanel.collapseTip" , { component : node . title } ) }
@@ -353,7 +392,7 @@ export const LeftContent = (props: LeftContentProps) => {
353
392
setShowData ( newData ) ;
354
393
} }
355
394
>
356
- < LeftOpen />
395
+
357
396
</ div >
358
397
</ Tooltip >
359
398
) : (
@@ -389,24 +428,29 @@ export const LeftContent = (props: LeftContentProps) => {
389
428
< LeftClose />
390
429
</ div >
391
430
</ Tooltip >
392
- ) ) }
431
+ )
432
+ ) }
393
433
</ span >
394
434
{ info ?. show && data && (
395
- < CollapseWrapper title = "" $clientX = { info ?. clientX } onClick = { ( e ) => e . stopPropagation ( ) } >
396
- < ScrollBar style = { { maxHeight : "400px" } } >
397
- < CollapseView
398
- key = { data . name }
399
- name = { data . name }
400
- desc = { data . dataDesc }
401
- data = { data . data }
402
- isOpen = { true }
403
- />
404
- </ ScrollBar >
405
- </ CollapseWrapper >
435
+ < Modal
436
+ title = { data . name }
437
+ open = { info . show }
438
+ onOk = { ( ) => setShowData ( [ ] ) }
439
+ cancelButtonProps = { { style : { display : 'none' } } }
440
+ maskClosable = { true } // Prevent closing on background click
441
+ >
442
+ < div
443
+ style = { { whiteSpace : 'pre-wrap' , wordWrap : 'break-word' , maxHeight : "calc(100vh - 400px)" , overflow : "scroll" } }
444
+ onClick = { ( e ) => e . stopPropagation ( ) } // Prevent closing on clicking inside the modal
445
+ >
446
+ { prepareData ( data . data , data . dataDesc ) }
447
+ </ div >
448
+ </ Modal >
406
449
) }
407
450
</ Node >
408
451
) ;
409
452
} ;
453
+
410
454
411
455
const getTreeUI = ( type : TreeUIKey ) => {
412
456
const uiCompInfos = _ . sortBy ( editorState . uiCompInfoList ( ) , [ ( x ) => x . name ] ) ;
@@ -434,15 +478,11 @@ export const LeftContent = (props: LeftContentProps) => {
434
478
return (
435
479
< DirectoryTreeStyle
436
480
treeData = { explorerData }
437
- // icon={(props: NodeItem) => props.type && (CompStateIcon[props.type] || <LeftCommon />)}
438
481
icon = { ( props : any ) => props . type && (
439
482
< div style = { { margin : '16px 4px 0 -4px' } } >
440
483
{ CompStateIcon [ props . type as UICompType ] || < LeftCommon /> }
441
484
</ div >
442
485
) }
443
- // switcherIcon={({ expanded }: { expanded: boolean }) =>
444
- // expanded ? <FoldedIcon /> : <UnfoldIcon />
445
- // }
446
486
switcherIcon = { ( props : any ) =>
447
487
props . expanded ? < FoldedIcon /> : < UnfoldIcon />
448
488
}
0 commit comments