Skip to content

Commit 3208128

Browse files
memoize kanban comp view
1 parent 88fd633 commit 3208128

File tree

2 files changed

+147
-106
lines changed

2 files changed

+147
-106
lines changed

lowcoder-comp-kanban/src/cardViewControl.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ type JSONValue = typeof JSONValue;
2929
const ContextSlotControl = withSelectedMultiContext(SlotControl);
3030

3131
const ContainerView = React.memo((props: ContainerBaseProps) => {
32-
console.log('card grid -> ', props);
3332
return <InnerGrid {...props} emptyRows={8} autoHeight />;
3433
});
3534

lowcoder-comp-kanban/src/kanbanCompView.tsx

Lines changed: 147 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
styled,
77
ScrollBar,
88
SlotConfigContext,
9+
getPanelStatus,
910
} from "lowcoder-sdk";
1011
import { extend, addClass, registerLicense } from "@syncfusion/ej2-base";
1112
import {
@@ -50,6 +51,7 @@ const LayoutContainer = styled.div<{
5051
`;
5152

5253
const getString = (assignee: string): string => {
54+
if (!Boolean(assignee)) return '';
5355
return (assignee.match(/\b(\w)/g) as string[]).join("").toUpperCase();
5456
};
5557

@@ -78,6 +80,7 @@ const cardRendered = (props: {
7880
cardContentStyles: Record<string, string>,
7981
}): void => {
8082
let val: string = (props.args.data as { [key: string]: Object }).priority as string;
83+
if (!Boolean(val)) return;
8184
let cardElement = props.args.element as HTMLElement;
8285
cardElement.style.backgroundColor = props.cardContentStyles.backgroundColor;
8386
cardElement.style.borderRadius = props.cardContentStyles.radius;
@@ -88,23 +91,27 @@ const cardRendered = (props: {
8891
};
8992

9093
const CardTemplate = React.memo((props: {
94+
isEditorStateAvailable: boolean;
95+
cardViewOption: string;
9196
data: { [key: string]: string },
9297
cardIndex: number;
9398
cardView: any;
9499
cardHeaderStyles: Record<string, string>;
95100
cardContentStyles: Record<string, string>;
96101
tagStyles: Record<string, string>;
97102
}) => {
98-
const editorState = useContext(EditorContext);
99-
100103
const template = useMemo(() => {
101104
return props.cardView.cardTemplate(
102105
props.data,
103106
props.cardIndex,
104107
)
105-
}, [JSON.stringify(props.data), props.cardIndex]);
108+
}, [
109+
JSON.stringify(props.data),
110+
props.cardIndex,
111+
// props.cardView.cardTemplate,
112+
]);
106113

107-
if (editorState) {
114+
if (props.isEditorStateAvailable && props.cardViewOption === 'custom') {
108115
return template;
109116
}
110117

@@ -164,6 +171,8 @@ const CardTemplate = React.memo((props: {
164171
</div>
165172
</Wrapper>
166173
);
174+
}, (prev, next) => {
175+
return JSON.stringify(prev) === JSON.stringify(next)
167176
});
168177

169178
type Props = {
@@ -177,27 +186,28 @@ export const KanbanCompView = React.memo((props: Props) => {
177186
// [childrenToProps, comp.children],
178187
// );
179188
const childrenProps = childrenToProps(comp.children);
189+
const panelStatus = getPanelStatus();
180190

191+
const editorState = useContext(EditorContext);
181192
const [dataMap, setDataMap] = useState<Record<string, number>>({});
182193
const [isModalOpen, setIsModalOpen] = useState(false);
183194
const [dialogData, setDialogData] = useState<Record<string,string>>({});
184195

196+
const isEditorStateAvailable = useMemo(() => Boolean(editorState), [ editorState ]);
197+
const cardView = useMemo(() => comp.children.cardView.children.cardView.toJsonValue(), [comp.children.cardView]);
198+
const cardModal = useMemo(() => childrenProps.cardView.cardModalView, [childrenProps.cardView.cardModalView] )
185199
const updateDataMap = useCallback(() => {
186200
const mapData: Record<string, number> = {};
187201
childrenProps.data?.forEach((item: any, index: number) => {
188-
mapData[item.id] = index;
202+
mapData[`${item.id}`] = index;
189203
})
190204
setDataMap(mapData);
191-
}, [ setDataMap]);
205+
}, [ JSON.stringify(childrenProps.data), setDataMap]);
192206

193207
useEffect(() => {
194208
updateDataMap();
195209
}, [updateDataMap]);
196210

197-
useEffect(() => {
198-
updateDataMap();
199-
}, [JSON.stringify(childrenProps.data), updateDataMap]);
200-
201211
const kanbanData: Object[] = useMemo(() => extend(
202212
[],
203213
childrenProps.data as { [key: string]: Object },
@@ -221,7 +231,11 @@ export const KanbanCompView = React.memo((props: Props) => {
221231
}, [setDialogData, showModal]);
222232

223233
const assigneeOptions = useMemo(() => {
224-
let assignees: any = [];
234+
let assignees: any = [{
235+
label: 'Unassigned',
236+
value: '',
237+
key: 'unassigned',
238+
}];
225239
childrenProps.assigneeOptions.forEach((item: any) => {
226240
let assignee = {
227241
label: item.name,
@@ -256,7 +270,7 @@ export const KanbanCompView = React.memo((props: Props) => {
256270
return uniqueObjectsArray;
257271
}, [JSON.stringify(childrenProps.statusOptions)]);
258272

259-
const handleDataChange = (kanbanData: Array<Record<string,any>>) => {
273+
const handleDataChange = useCallback((kanbanData: Array<Record<string,any>>) => {
260274
comp.children?.data.children.manual.children.manual.dispatch(
261275
comp.children?.data.children.manual.children.manual.setChildrensAction(
262276
kanbanData
@@ -267,25 +281,25 @@ export const KanbanCompView = React.memo((props: Props) => {
267281
);
268282

269283
childrenProps.onEvent("change");
270-
};
284+
}, [comp, childrenProps.onEvent]);
271285

272-
const handleActionComplete = ({
286+
const handleActionComplete = useCallback(({
273287
changedRecords,
274288
}: {
275289
changedRecords : Array<Record<string,any>>
276290
}) => {
277291
const updatedData = [ ...kanbanData ] as Array<Record<string,any>>;
278-
changedRecords.forEach((record) => {
292+
changedRecords?.forEach((record) => {
279293
const { id } = record;
280294
const index = updatedData.findIndex((item: any) => item.id === id);
281295
if (index > -1) {
282296
updatedData[index] = record;
283297
}
284298
});
285299
handleDataChange(updatedData);
286-
}
300+
}, [kanbanData, handleDataChange]);
287301

288-
const handleOk = (dialogData: Record<string, string>) => {
302+
const handleOk = useCallback((dialogData: Record<string, string>) => {
289303
const { id } = dialogData;
290304
const updatedData = [ ...kanbanData ];
291305
const index = updatedData.findIndex((item: any) => item.id === id);
@@ -294,101 +308,129 @@ export const KanbanCompView = React.memo((props: Props) => {
294308
handleDataChange(updatedData);
295309
}
296310
setIsModalOpen(false);
297-
}
311+
}, [kanbanData, setIsModalOpen, handleDataChange])
298312

299-
const handleCancel = () => {
313+
const handleCancel = useCallback(() => {
300314
setIsModalOpen(false);
301-
}
315+
}, [setIsModalOpen])
302316

303-
const cardSettings = useMemo(() => ({
304-
headerField: 'label',
305-
template: (data: Record<string, string>) => {
306-
const cardIndex = dataMap[data.id] || 0;
307-
return (
308-
<CardTemplate
309-
data={{...data}}
310-
cardIndex={cardIndex}
311-
cardView={childrenProps.cardView}
312-
cardHeaderStyles={childrenProps.cardHeaderStyles}
313-
cardContentStyles={childrenProps.cardContentStyles}
314-
tagStyles={childrenProps.tagStyles}
315-
/>
316-
);
317-
},
318-
}), [
319-
dataMap,
320-
childrenProps.cardView,
321-
childrenProps.cardHeaderStyles,
322-
childrenProps.cardContentStyles,
323-
childrenProps.tagStyles,
317+
const cardTemplate = useCallback((data: Record<string, string>) => {
318+
const cardIndex = dataMap[data.id] || 0;
319+
return (
320+
<CardTemplate
321+
key={data.id}
322+
isEditorStateAvailable={isEditorStateAvailable}
323+
cardViewOption={childrenProps.cardViewOption}
324+
data={data}
325+
cardIndex={cardIndex}
326+
cardView={childrenProps.cardView}
327+
cardHeaderStyles={childrenProps.cardHeaderStyles}
328+
cardContentStyles={childrenProps.cardContentStyles}
329+
tagStyles={childrenProps.tagStyles}
330+
/>
331+
);
332+
}, [
333+
cardView,
334+
childrenProps.cardViewOption,
335+
isEditorStateAvailable,
336+
JSON.stringify(panelStatus),
337+
JSON.stringify(dataMap),
338+
JSON.stringify(childrenProps.cardHeaderStyles),
339+
JSON.stringify(childrenProps.cardContentStyles),
340+
JSON.stringify(childrenProps.tagStyles),
324341
]);
325342

326-
return (
327-
<>
328-
<div
329-
className="schedule-control-section"
330-
style={{height: `100%`, width: `100%`}}
343+
const renderKanbanComp = useMemo(() => {
344+
return (
345+
<ScrollBar
346+
style={{
347+
height: childrenProps.autoHeight ? 'auto' : '100%',
348+
margin: '0px',
349+
padding: '0px',
350+
}}
351+
hideScrollbar={!childrenProps.scrollbars}
331352
>
332-
<div
333-
className="col-lg-12 control-section"
334-
style={{height: `100%`, width: `100%`}}
335-
>
336-
<ScrollBar
337-
style={{
338-
height: childrenProps.autoHeight ? 'auto' : '100%',
339-
margin: '0px',
340-
padding: '0px',
341-
}}
342-
hideScrollbar={!childrenProps.scrollbars}
343-
>
344-
<LayoutContainer>
345-
<KanbanComponent
346-
id="kanban"
347-
cssClass="kanban-overview"
348-
keyField="status"
349-
dataSource={[...kanbanData]}
350-
cardDoubleClick={OnCardDoubleClick}
351-
cardClick={(args: CardClickEventArgs) => args.event?.stopPropagation()}
352-
swimlaneSettings={{keyField: 'assignee'}}
353-
actionComplete={handleActionComplete}
354-
cardSettings={cardSettings}
355-
cardRendered={(args: CardRenderedEventArgs) => {
356-
return cardRendered({
357-
args,
358-
cardContentStyles: childrenProps.cardContentStyles,
359-
})
360-
}}
361-
>
362-
<ColumnsDirective>
363-
{childrenProps.statusOptions.map((statusOption: any) => (
364-
<ColumnDirective
365-
key={statusOption.value}
366-
headerText={statusOption.label}
367-
keyField={statusOption.value}
368-
allowToggle={true}
369-
template={(data: Record<string, string>) => (
370-
<ColumnTemplate data={data} boardStyles={childrenProps.boardStyles} />
371-
)}
372-
/>
373-
))}
374-
</ColumnsDirective>
375-
</KanbanComponent>
376-
</LayoutContainer>
377-
</ScrollBar>
378-
<SlotConfigContext.Provider value={{ modalWidth: 600 }}>
379-
{childrenProps.cardView.cardModalView}
380-
</SlotConfigContext.Provider>
381-
</div>
382-
</div>
353+
<LayoutContainer>
354+
{Boolean(Object.keys(dataMap).length) && (
355+
<KanbanComponent
356+
id="kanban"
357+
cssClass="kanban-overview"
358+
keyField="status"
359+
dataSource={[...kanbanData]}
360+
cardDoubleClick={OnCardDoubleClick}
361+
cardClick={(args: CardClickEventArgs) => args.event?.stopPropagation()}
362+
swimlaneSettings={
363+
{keyField: childrenProps.separateAssigneeSections ? 'assignee' : ''}
364+
}
365+
actionComplete={handleActionComplete}
366+
cardSettings={{
367+
headerField: 'label',
368+
template: cardTemplate,
369+
}}
370+
cardRendered={(args: CardRenderedEventArgs) => {
371+
return cardRendered({
372+
args,
373+
cardContentStyles: childrenProps.cardContentStyles,
374+
})
375+
}}
376+
>
377+
<ColumnsDirective>
378+
{childrenProps.statusOptions.map((statusOption: any) => (
379+
<ColumnDirective
380+
key={statusOption.value}
381+
headerText={statusOption.label}
382+
keyField={statusOption.value}
383+
allowToggle={true}
384+
template={(data: Record<string, string>) => (
385+
<ColumnTemplate data={data} boardStyles={childrenProps.boardStyles} />
386+
)}
387+
/>
388+
))}
389+
</ColumnsDirective>
390+
</KanbanComponent>
391+
)}
392+
</LayoutContainer>
393+
</ScrollBar>
394+
)}, [
395+
cardTemplate,
396+
JSON.stringify(dataMap),
397+
JSON.stringify(kanbanData),
398+
JSON.stringify(childrenProps.statusOptions),
399+
JSON.stringify(childrenProps.cardContentStyles),
400+
JSON.stringify(childrenProps.boardStyles),
401+
childrenProps.autoHeight,
402+
childrenProps.separateAssigneeSections,
403+
OnCardDoubleClick,
404+
handleActionComplete,
405+
]);
383406

384-
<KanbanCardModal
385-
open={isModalOpen}
386-
data={dialogData}
387-
statusOptions={statusOptions}
388-
assigneeOptions={assigneeOptions}
389-
onOk={(data) => handleOk(data)}
390-
onCancel={handleCancel}
391-
/>
407+
const renderKanbanModal = useMemo(() => (
408+
<KanbanCardModal
409+
open={isModalOpen}
410+
data={dialogData}
411+
statusOptions={statusOptions}
412+
assigneeOptions={assigneeOptions}
413+
onOk={(data) => handleOk(data)}
414+
onCancel={handleCancel}
415+
/>
416+
), [
417+
isModalOpen,
418+
dialogData,
419+
JSON.stringify(statusOptions),
420+
JSON.stringify(assigneeOptions),
421+
handleOk,
422+
handleCancel,
423+
]);
424+
425+
return (
426+
<>
427+
{ renderKanbanComp }
428+
<SlotConfigContext.Provider value={{ modalWidth: 600 }}>
429+
{cardModal}
430+
</SlotConfigContext.Provider>
431+
{ renderKanbanModal}
392432
</>
393433
);
434+
}, (prev, next) => {
435+
return prev.comp.toJsonValue() === next.comp.toJsonValue();
394436
});

0 commit comments

Comments
 (0)