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

Commit4e5e0b1

Browse files
author
FalkWolsky
committed
Copy-Able Data from Components in State Display
1 parent2e38751 commit4e5e0b1

File tree

1 file changed

+127
-87
lines changed

1 file changed

+127
-87
lines changed

‎client/packages/lowcoder/src/pages/editor/LeftContent.tsx‎

Lines changed: 127 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -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";
1818
importReact,{ReactNode,useCallback,useContext,useMemo,useState}from"react";
1919
import{hookCompCategory}from"comps/hooks/hookCompTypes";
@@ -32,13 +32,33 @@ import type { UICompType } from "comps/uiCompRegistry";
3232
import{CollapseWrapper,DirectoryTreeStyle,Node}from"./styledComponents";
3333
import{DataNode,EventDataNode}from"antd/es/tree";
3434
import{isAggregationApp}from"util/appUtils";
35+
importModalfrom"antd/es/modal/Modal";
36+
importcopyToClipboardfrom"copy-to-clipboard";
3537

3638
constCollapseTitleWrapper=styled.div`
3739
display: flex;
3840
width: fit-content;
3941
max-width: calc(100% - 8px);
4042
`;
4143

44+
constPadDiv=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+
constCopyIcon=styled(CopyTextButton)`
56+
visibility: hidden;
57+
margin-left: 8px;
58+
color: #1890ff;
59+
cursor: pointer;
60+
`;
61+
4262
functiongetLen(config:string|boolean|number){
4363
if(typeofconfig==="number"){
4464
return(config+"").toString().length;
@@ -49,47 +69,48 @@ function getLen(config: string | boolean | number) {
4969
return0;
5070
}
5171

52-
functiontoDataView(value:any,name:string,desc?:ReactNode){
72+
functiontoDataView(value:any,name:string,desc?:ReactNode,modal?:boolean){
5373
conststr=typeofvalue==="function" ?"Function" :safeJSONStringify(value);
5474
constdescRecord:Record<string,ReactNode>={};
75+
constshortenedString=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
constdataChild:Record<string,any>={};
5879
value.forEach((valueChild,index)=>{
5980
dataChild[index]=valueChild;
6081
});
6182
return(
62-
<CollapseViewname={name}desc={descRecord}data={dataChild}isArray={true}key={name}/>
83+
<CollapseViewname={name}desc={descRecord}data={dataChild}isArray={true}key={name}modal={modal}/>
6384
);
6485
}elseif(_.isPlainObject(value)){
65-
return<CollapseViewname={name}desc={descRecord}data={value}key={name}/>;
66-
}
67-
68-
return(
69-
<PadDivkey={name}>
70-
<Tooltiptitle={desc}placement={"right"}>
71-
<Labellabel={name}/>
72-
&#8203;
73-
</Tooltip>
74-
75-
<Tooltip
76-
title={
77-
getLen(str)>50 ?(
78-
<divstyle={{display:"flex",wordBreak:"break-all"}}>
79-
{getLen(str)>300 ?str.slice(0,300)+"..." :str}
80-
<CopyTextButtontext={value}style={{color:"#fff",margin:"4px 0 0 6px"}}/>
81-
</div>
82-
) :null
83-
}
84-
placement={"right"}
86+
return(
87+
<CollapseViewname={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-
&#8203;
87-
<Labelcolor="#FF9816"label={getLen(str)>50 ?str.slice(0,50)+"..." :str}/>
88-
</Tooltip>
89-
</PadDiv>
90-
);
95+
<Tooltiptitle={desc}placement={"right"}>
96+
<Labellabel={name}/> &#8203;
97+
</Tooltip>
98+
99+
<divstyle={{display:"flex",wordBreak:"break-all",textAlign:"right"}}>
100+
<spanstyle={{marginRight:"10px"}}>{shortenedString}</span>
101+
{getLen(str)>0&&
102+
<CopyTextButtontext={value}style={{color:"#ccc",marginRight:"0px",marginTop:"4px"}}/>
103+
}
104+
</div>
105+
106+
</PadDiv>
107+
);
108+
}
91109
}
92110

111+
112+
exportdefaulttoDataView;
113+
93114
functionsliceArr(arr:string[]){
94115
letpreArr:string[]=[];
95116
letafterArr:string[]=[];
@@ -104,23 +125,23 @@ function sliceArr(arr: string[]) {
104125
return{ preArr, afterArr}asconst;
105126
}
106127

107-
functiontoData(props:{data:Record<string,any>;desc?:Record<string,ReactNode>}){
128+
functiontoData(props:{data:Record<string,any>;desc?:Record<string,ReactNode>,modal?:boolean}){
108129
consttotalArr=Object.keys(props.data);
109130
constsliceFn=sliceArr;
110131
return(
111132
<div>
112133
{totalArr.length<30 ?(
113134
totalArr.map((name)=>{
114-
returntoDataView(props.data[name],name,props.desc?.[name]);
135+
returntoDataView(props.data[name],name,props.desc?.[name],props.modal);
115136
})
116137
) :(
117138
<>
118139
{sliceFn(totalArr).preArr.map((name)=>{
119-
returntoDataView(props.data[name],name,props.desc?.[name]);
140+
returntoDataView(props.data[name],name,props.desc?.[name],props.modal);
120141
})}
121142
<UnShownum={totalArr.length-6}/>
122143
{sliceFn(totalArr).afterArr.map((name)=>{
123-
returntoDataView(props.data[name],name,props.desc?.[name]);
144+
returntoDataView(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
constonlyOne=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-
<CollapseTitleWrapperonClick={()=>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+
<divstyle={{display:'flex',justifyContent:'space-between',alignItems:'center'}}>
175+
<Tooltip
176+
title={props.desc?.[props.name]}
177+
placement={"right"}
178+
>
179+
<CollapseTitleWrapperonClick={()=>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+
<CopyTextButtontext={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+
192221
interfaceLeftContentProps{
193222
uiComp:InstanceType<typeofUIComp>;
194223
}
@@ -324,13 +353,23 @@ export const LeftContent = (props: LeftContentProps) => {
324353
constgetTreeNode=(node:NodeItem,uiCompInfos:CompInfo[])=>{
325354
constinfo=showData.find((item)=>item.key===node.key);
326355
constdata=uiCompInfos.find((item)=>item.name===node.title);
356+
357+
constprepareData=(data:Record<string,any>,desc?:Record<string,ReactNode>)=>{
358+
return(
359+
<div>
360+
{Object.keys(data).map((name)=>{
361+
returntoDataView(data[name],name,desc?.[name],true);
362+
})}
363+
</div>
364+
);
365+
};
366+
327367
return(
328-
<Node>
368+
<Nodekey={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-
<CollapseWrappertitle=""$clientX={info?.clientX}onClick={(e)=>e.stopPropagation()}>
396-
<ScrollBarstyle={{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
constgetTreeUI=(type:TreeUIKey)=>{
412456
constuiCompInfos=_.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
<divstyle={{margin:'16px 4px 0 -4px'}}>
440483
{CompStateIcon[props.typeasUICompType]||<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

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp