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

Commit147cf4c

Browse files
optimise table comp, toolbar, filters, summary rows and different column types
1 parent12f2485 commit147cf4c

28 files changed

+2526
-1439
lines changed

‎client/packages/lowcoder/src/comps/comps/tableComp/column/columnTypeCompBuilder.tsx‎

Lines changed: 75 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ export class ColumnTypeCompBuilder<
5454
RecordConstructorToComp<NewChildrenCtorMap<ChildrenCtorMap,T>>
5555
>;
5656
privateeditViewFn?:EditViewFn<T>;
57+
privatecleanupFunctions:(()=>void)[]=[];
5758

5859
constructor(
5960
childrenMap:ChildrenCtorMap,
@@ -93,22 +94,57 @@ export class ColumnTypeCompBuilder<
9394
if(!this.propertyViewFn){
9495
thrownewError("need property view fn");
9596
}
97+
98+
// Memoize the props processing
99+
constmemoizedViewFn=_.memoize(
100+
(props:any,dispatch:any)=>{
101+
constbaseValue=this.baseValueFn?.(props,dispatch);
102+
constnormalView=this.viewFn(props,dispatch);
103+
return(
104+
<EditableCell<T>
105+
{...props}
106+
normalView={normalView}
107+
dispatch={dispatch}
108+
baseValue={baseValue}
109+
changeValue={props.changeValueasany}
110+
editViewFn={this.editViewFn}
111+
/>
112+
);
113+
},
114+
(props)=>{
115+
letsafeOptions=[];
116+
letsafeAvatars=[];
117+
if(props.options){
118+
safeOptions=props.options.map((option:Record<string,any>)=>{
119+
const{prefixIcon, suffixIcon, ...safeOption}=option;
120+
returnsafeOption;
121+
})
122+
}
123+
if(props.avatars){
124+
safeAvatars=props.avatars.map((avatar:Record<string,any>)=>{
125+
const{AvatarIcon, ...safeAvatar}=avatar;
126+
returnsafeAvatar;
127+
})
128+
}
129+
const{
130+
prefixIcon,
131+
suffixIcon,
132+
iconFalse,
133+
iconTrue,
134+
iconNull,
135+
tagColors,
136+
options,
137+
avatars,
138+
...safeProps
139+
}=props;
140+
returnsafeProps;
141+
}
142+
);
143+
96144
constviewFn:ColumnTypeViewFn<ChildrenCtorMap,T,CellViewReturn>=
97145
(props,dispatch):CellViewReturn=>
98-
(cellProps)=>{
99-
constbaseValue=this.baseValueFn?.(props,dispatch);
100-
constnormalView=this.viewFn(props,dispatch);
101-
return(
102-
<EditableCell<T>
103-
{...cellProps}
104-
normalView={normalView}
105-
dispatch={dispatch}
106-
baseValue={baseValue}
107-
changeValue={props.changeValueasany}
108-
editViewFn={this.editViewFn}
109-
/>
110-
);
111-
};
146+
(cellProps)=>memoizedViewFn({ ...props, ...cellProps}asany,dispatch);
147+
112148
constColumnTypeCompTmp=newMultiCompBuilder(
113149
this.childrenMapasToConstructor<
114150
RecordConstructorToComp<NewChildrenCtorMap<ChildrenCtorMap,T>>
@@ -117,12 +153,21 @@ export class ColumnTypeCompBuilder<
117153
)
118154
.setPropertyViewFn(this.propertyViewFn)
119155
.build();
156+
120157
constdisplayValueFn=this.displayValueFn;
121158
consteditViewFn=this.editViewFn;
122159

123160
returnclassextendsColumnTypeCompTmp{
124161
// table cell data
125-
readonlydisplayValue:JSONValue=null;
162+
private_displayValue:JSONValue=null;
163+
privatecleanupFunctions:(()=>void)[]=[];
164+
constructor(props:any){
165+
super(props);
166+
this.cleanupFunctions.push(()=>{
167+
this._displayValue=null;
168+
memoizedViewFn.cache.clear?.();
169+
});
170+
}
126171

127172
overrideextraNode(){
128173
return{
@@ -134,7 +179,8 @@ export class ColumnTypeCompBuilder<
134179
},
135180
updateNodeFields:(value:any)=>{
136181
constdisplayValueFunc=value[__COLUMN_DISPLAY_VALUE_FN];
137-
return{displayValue:displayValueFunc(value)};
182+
this._displayValue=displayValueFunc(value);
183+
return{displayValue:this._displayValue};
138184
},
139185
};
140186
}
@@ -143,12 +189,24 @@ export class ColumnTypeCompBuilder<
143189
* Get the data actually displayed by the table cell
144190
*/
145191
getDisplayValue(){
146-
returnthis.displayValue;
192+
returnthis._displayValue;
147193
}
148194

149195
staticcanBeEditable(){
150196
return!_.isNil(editViewFn);
151197
}
198+
199+
componentWillUnmount(){
200+
// Cleanup all registered cleanup functions
201+
this.cleanupFunctions.forEach(cleanup=>cleanup());
202+
this.cleanupFunctions=[];
203+
}
152204
};
153205
}
206+
207+
// Cleanup method to be called when the builder is no longer needed
208+
cleanup(){
209+
this.cleanupFunctions.forEach(cleanup=>cleanup());
210+
this.cleanupFunctions=[];
211+
}
154212
}

‎client/packages/lowcoder/src/comps/comps/tableComp/column/columnTypeComps/ColumnNumberComp.tsx‎

Lines changed: 107 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import{defaultasInputNumber}from"antd/es/input-number";
1+
importReact,{useState,useRef,useEffect,useCallback,useMemo,ReactNode}from"react";
2+
import{defaultasInputNumber}from"antd/es/input-number";
23
import{NumberControl,RangeControl,StringControl}from"comps/controls/codeControl";
34
import{BoolControl}from"comps/controls/boolControl";
45
import{trans}from"i18n";
@@ -35,59 +36,123 @@ const childrenMap = {
3536
suffix:StringControl,
3637
};
3738

38-
letfloat=false;
39-
letstep=1;
40-
letprecision=0;
39+
constgetBaseValue:ColumnTypeViewFn<typeofchildrenMap,number,number>=(props)=>props.text;
4140

42-
constgetBaseValue:ColumnTypeViewFn<typeofchildrenMap,number,number>=(
43-
props
44-
)=>{
45-
returnprops.text
41+
typeNumberViewProps={
42+
value:number;
43+
prefix:string;
44+
suffix:string;
45+
prefixIcon:ReactNode;
46+
suffixIcon:ReactNode;
47+
float:boolean;
48+
precision:number;
4649
};
4750

51+
typeNumberEditProps={
52+
value:number;
53+
onChange:(value:number)=>void;
54+
onChangeEnd:()=>void;
55+
step:number;
56+
precision:number;
57+
float:boolean;
58+
};
59+
60+
constColumnNumberView=React.memo((props:NumberViewProps)=>{
61+
constformattedValue=useMemo(()=>{
62+
letresult=!props.float ?Math.floor(props.value) :props.value;
63+
if(props.float){
64+
result=Number(result.toFixed(props.precision+1));
65+
}
66+
returnresult;
67+
},[props.value,props.float,props.precision]);
68+
69+
return(
70+
<>
71+
{hasIcon(props.prefixIcon)&&(
72+
<span>{props.prefixIcon}</span>
73+
)}
74+
<span>{props.prefix+formattedValue+props.suffix}</span>
75+
{hasIcon(props.suffixIcon)&&(
76+
<span>{props.suffixIcon}</span>
77+
)}
78+
</>
79+
);
80+
});
81+
82+
ColumnNumberView.displayName='ColumnNumberView';
83+
84+
85+
constColumnNumberEdit=React.memo((props:NumberEditProps)=>{
86+
const[currentValue,setCurrentValue]=useState(props.value);
87+
constmountedRef=useRef(true);
88+
89+
// Cleanup on unmount
90+
useEffect(()=>{
91+
return()=>{
92+
mountedRef.current=false;
93+
setCurrentValue(0);
94+
};
95+
},[]);
96+
97+
consthandleChange=useCallback((value:string|number|null)=>{
98+
if(!mountedRef.current)return;
99+
constnewValue=typeofvalue==='number' ?value :0;
100+
constfinalValue=!props.float ?Math.floor(newValue) :newValue;
101+
props.onChange(finalValue);
102+
setCurrentValue(finalValue);
103+
},[props.onChange,props.float]);
104+
105+
consthandleBlur=useCallback(()=>{
106+
if(!mountedRef.current)return;
107+
props.onChangeEnd();
108+
},[props.onChangeEnd]);
109+
110+
consthandlePressEnter=useCallback(()=>{
111+
if(!mountedRef.current)return;
112+
props.onChangeEnd();
113+
},[props.onChangeEnd]);
114+
115+
return(
116+
<InputNumberWrapper>
117+
<InputNumber
118+
step={props.step}
119+
value={currentValue}
120+
autoFocus
121+
variant="borderless"
122+
onChange={handleChange}
123+
precision={props.float ?props.precision :0}
124+
onBlur={handleBlur}
125+
onPressEnter={handlePressEnter}
126+
/>
127+
</InputNumberWrapper>
128+
);
129+
});
130+
131+
ColumnNumberEdit.displayName='NumberEdit';
132+
48133
exportconstColumnNumberComp=(function(){
49134
returnnewColumnTypeCompBuilder(
50135
childrenMap,
51136
(props,dispatch)=>{
52-
float=props.float;
53-
step=props.step;
54-
precision=props.precision;
55137
constvalue=props.changeValue??getBaseValue(props,dispatch);
56-
letformattedValue:string|number=!float ?Math.floor(value) :value;
57-
if(float){
58-
formattedValue=formattedValue.toFixed(precision+1);
59-
}
60-
return(
61-
<>{hasIcon(props.prefixIcon)&&(
62-
<span>{props.prefixIcon}</span>
63-
)}
64-
<span>{props.prefix+formattedValue+props.suffix}</span>
65-
{hasIcon(props.suffixIcon)&&(
66-
<span>{props.suffixIcon}</span>
67-
)}</>
68-
);
138+
return<ColumnNumberViewvalue={value}{...props}/>;
69139
},
70140
(nodeValue)=>nodeValue.text.value,
71-
getBaseValue,
141+
getBaseValue
72142
)
73143
.setEditViewFn((props)=>{
144+
const{ value, onChange, onChangeEnd, otherProps}=props;
74145
return(
75-
<InputNumberWrapper>
76-
<InputNumber
77-
step={step}
78-
defaultValue={props.value}
79-
autoFocus
80-
variant="borderless"
81-
onChange={(value)=>{
82-
value=value??0;
83-
props.onChange(!float ?Math.floor(value) :value);
84-
}}
85-
precision={float ?precision :0}
86-
onBlur={props.onChangeEnd}
87-
onPressEnter={props.onChangeEnd}
146+
<ColumnNumberEdit
147+
value={value}
148+
onChange={onChange}
149+
onChangeEnd={onChangeEnd}
150+
step={otherProps?.step??1}
151+
precision={otherProps?.precision??0}
152+
float={otherProps?.float??false}
88153
/>
89-
</InputNumberWrapper>
90-
)})
154+
);
155+
})
91156
.setPropertyViewFn((children)=>{
92157
return(
93158
<>
@@ -99,15 +164,15 @@ export const ColumnNumberComp = (function () {
99164
label:trans("table.numberStep"),
100165
tooltip:trans("table.numberStepTooltip"),
101166
onFocus:(focused)=>{
102-
if(!focused){
167+
if(!focused){
103168
constvalue=children.step.getView();
104169
constisFloat=children.float.getView();
105170
constnewValue=!isFloat ?Math.floor(value) :value;
106171
children.step.dispatchChangeValueAction(String(newValue));
107172
}
108173
}
109174
})}
110-
{float&&(
175+
{children.float.getView()&&(
111176
children.precision.propertyView({
112177
label:trans("table.precision"),
113178
})

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp