@@ -9,11 +9,11 @@ import {
99 LeftClose ,
1010 LeftCommon ,
1111 LeftOpen ,
12- PadDiv ,
1312 ScrollBar ,
1413 Tooltip ,
1514 UnfoldIcon ,
1615 UnShow ,
16+ TacoButton ,
1717} from "lowcoder-design" ;
1818import React , { ReactNode , useCallback , useContext , useMemo , useState } from "react" ;
1919import { hookCompCategory } from "comps/hooks/hookCompTypes" ;
@@ -32,13 +32,33 @@ import type { UICompType } from "comps/uiCompRegistry";
3232import { CollapseWrapper , DirectoryTreeStyle , Node } from "./styledComponents" ;
3333import { DataNode , EventDataNode } from "antd/es/tree" ;
3434import { isAggregationApp } from "util/appUtils" ;
35+ import Modal from "antd/es/modal/Modal" ;
36+ import copyToClipboard from "copy-to-clipboard" ;
3537
3638const CollapseTitleWrapper = styled . div `
3739 display: flex;
3840 width: fit-content;
3941 max-width: calc(100% - 8px);
4042` ;
4143
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+
4262function getLen ( config : string | boolean | number ) {
4363 if ( typeof config === "number" ) {
4464 return ( config + "" ) . toString ( ) . length ;
@@ -49,47 +69,48 @@ function getLen(config: string | boolean | number) {
4969 return 0 ;
5070}
5171
52- function toDataView ( value : any , name : string , desc ?: ReactNode ) {
72+ function toDataView ( value : any , name : string , desc ?: ReactNode , modal ?: boolean ) {
5373 const str = typeof value === "function" ? "Function" : safeJSONStringify ( value ) ;
5474 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 ) ;
5576 descRecord [ name ] = desc ;
5677 if ( Array . isArray ( value ) ) {
5778 const dataChild : Record < string , any > = { } ;
5879 value . forEach ( ( valueChild , index ) => {
5980 dataChild [ index ] = valueChild ;
6081 } ) ;
6182 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 } />
6384 ) ;
6485 } 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 }
8594 >
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+ }
91109}
92110
111+
112+ export default toDataView ;
113+
93114function sliceArr ( arr : string [ ] ) {
94115 let preArr : string [ ] = [ ] ;
95116 let afterArr : string [ ] = [ ] ;
@@ -104,23 +125,23 @@ function sliceArr(arr: string[]) {
104125 return { preArr, afterArr } as const ;
105126}
106127
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 } ) {
108129 const totalArr = Object . keys ( props . data ) ;
109130 const sliceFn = sliceArr ;
110131 return (
111132 < div >
112133 { totalArr . length < 30 ? (
113134 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 ) ;
115136 } )
116137 ) : (
117138 < >
118139 { 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 ) ;
120141 } ) }
121142 < UnShow num = { totalArr . length - 6 } />
122143 { 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 ) ;
124145 } ) }
125146 </ >
126147 ) }
@@ -137,6 +158,8 @@ const CollapseView = React.memo(
137158 onClick ?: ( compName : string ) => void ;
138159 isSelected ?: boolean ;
139160 isOpen ?: boolean ;
161+ children ?: React . ReactNode ; // Accept children
162+ modal ?: boolean ;
140163 } ) => {
141164 const { data = { } } = props ;
142165 const onlyOne = Object . keys ( data ) . length === 1 ;
@@ -148,47 +171,53 @@ const CollapseView = React.memo(
148171 {
149172 key : props . name ,
150173 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 >
183211 ) ,
184- data : toData ( { data, desc : props . desc } ) ,
212+ data : toData ( { data, desc : props . desc , modal : props . modal } ) ,
185213 } ,
186214 ] }
187215 />
188216 ) ;
189217 }
190218) ;
191219
220+
192221interface LeftContentProps {
193222 uiComp : InstanceType < typeof UIComp > ;
194223}
@@ -324,13 +353,23 @@ export const LeftContent = (props: LeftContentProps) => {
324353 const getTreeNode = ( node : NodeItem , uiCompInfos : CompInfo [ ] ) => {
325354 const info = showData . find ( ( item ) => item . key === node . key ) ;
326355 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+
327367 return (
328- < Node >
368+ < Node key = { node . key } >
329369 < 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 ? (
334373 < Tooltip
335374 placement = "right"
336375 title = { trans ( "leftPanel.collapseTip" , { component : node . title } ) }
@@ -353,7 +392,7 @@ export const LeftContent = (props: LeftContentProps) => {
353392 setShowData ( newData ) ;
354393 } }
355394 >
356- < LeftOpen />
395+
357396 </ div >
358397 </ Tooltip >
359398 ) : (
@@ -389,24 +428,29 @@ export const LeftContent = (props: LeftContentProps) => {
389428 < LeftClose />
390429 </ div >
391430 </ Tooltip >
392- ) ) }
431+ )
432+ ) }
393433 </ span >
394434 { 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 >
406449 ) }
407450 </ Node >
408451 ) ;
409452 } ;
453+
410454
411455 const getTreeUI = ( type : TreeUIKey ) => {
412456 const uiCompInfos = _ . sortBy ( editorState . uiCompInfoList ( ) , [ ( x ) => x . name ] ) ;
@@ -434,15 +478,11 @@ export const LeftContent = (props: LeftContentProps) => {
434478 return (
435479 < DirectoryTreeStyle
436480 treeData = { explorerData }
437- // icon={(props: NodeItem) => props.type && (CompStateIcon[props.type] || <LeftCommon />)}
438481 icon = { ( props : any ) => props . type && (
439482 < div style = { { margin : '16px 4px 0 -4px' } } >
440483 { CompStateIcon [ props . type as UICompType ] || < LeftCommon /> }
441484 </ div >
442485 ) }
443- // switcherIcon={({ expanded }: { expanded: boolean }) =>
444- // expanded ? <FoldedIcon /> : <UnfoldIcon />
445- // }
446486 switcherIcon = { ( props : any ) =>
447487 props . expanded ? < FoldedIcon /> : < UnfoldIcon />
448488 }
0 commit comments