Skip to content

Commit c82279e

Browse files
committed
refactor columnToAntd function
1 parent 38c8653 commit c82279e

File tree

1 file changed

+221
-115
lines changed

1 file changed

+221
-115
lines changed

client/packages/lowcoder/src/comps/comps/tableLiteComp/tableUtils.tsx

Lines changed: 221 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,195 @@ export type CustomColumnType<RecordType> = ColumnType<RecordType> & {
288288
cellColorFn: CellColorViewType;
289289
};
290290

291+
/**
292+
* Helper: build a mapping of column -> sort order
293+
*/
294+
function computeSortMap(sort: SortValue[]): Map<string | undefined, SortOrder> {
295+
return new Map(sort.map((s) => [s.column, s.desc ? "descend" : "ascend"]));
296+
}
297+
298+
/**
299+
* Helper: sort columns by fixed position and dynamic config order
300+
*/
301+
function orderColumns(
302+
columns: Array<RawColumnType>,
303+
dynamicColumn: boolean,
304+
dynamicColumnConfig: string[],
305+
): Array<RawColumnType> {
306+
const dynamicPositions: Record<string, number> = {};
307+
if (dynamicColumn && dynamicColumnConfig.length > 0) {
308+
dynamicColumnConfig.forEach((name, idx) => {
309+
dynamicPositions[name] = idx;
310+
});
311+
}
312+
return _.sortBy(columns, (c) => {
313+
if (c.fixed === "left") return -1;
314+
if (c.fixed === "right") return Number.MAX_SAFE_INTEGER;
315+
if (dynamicColumn && dynamicColumnConfig.length > 0) {
316+
const key = c.isCustom ? c.title : c.dataIndex;
317+
const pos = dynamicPositions[key];
318+
if (typeof pos === "number") return pos;
319+
}
320+
return 0;
321+
});
322+
}
323+
324+
/**
325+
* Helper: should include a column based on hide and dynamic config gating
326+
*/
327+
function shouldIncludeColumn(
328+
column: RawColumnType,
329+
enableColumnSetting: boolean,
330+
dynamicColumn: boolean,
331+
dynamicColumnConfig: string[],
332+
): boolean {
333+
if (
334+
columnHide({
335+
hide: column.hide,
336+
tempHide: column.tempHide,
337+
enableColumnSetting,
338+
})
339+
) {
340+
return false;
341+
}
342+
if (
343+
dynamicColumn &&
344+
dynamicColumnConfig.length > 0 &&
345+
!dynamicColumnConfig.includes(column.isCustom ? column.title : column.dataIndex)
346+
) {
347+
return false;
348+
}
349+
return true;
350+
}
351+
352+
/**
353+
* Helper: aggregate data for a specific column
354+
*/
355+
function extractAggrForColumn(
356+
dataIndex: string,
357+
columnsAggrData: ColumnsAggrData,
358+
) {
359+
const aggr = columnsAggrData[dataIndex] as any;
360+
const candidateTags: string[] = Array.isArray(aggr?.uniqueTags) ? aggr.uniqueTags : [];
361+
const candidateStatus: { text: string; status: StatusType }[] = Array.isArray(aggr?.uniqueStatus)
362+
? aggr.uniqueStatus
363+
: [];
364+
const uniqueValues: any[] = Array.isArray(aggr?.uniqueValues) ? aggr.uniqueValues : [];
365+
return { candidateTags, candidateStatus, uniqueValues };
366+
}
367+
368+
/**
369+
* Helper: build filter props for antd Table column
370+
*/
371+
function buildFilterProps(
372+
dataIndex: string,
373+
filterable: boolean,
374+
candidateTags: any[],
375+
uniqueValues: any[],
376+
) {
377+
if (!filterable) return {};
378+
const candidates = (Array.isArray(candidateTags) && candidateTags.length > 0
379+
? candidateTags
380+
: Array.isArray(uniqueValues) && uniqueValues.length > 0
381+
? uniqueValues
382+
: [])
383+
.slice(0, 100);
384+
return {
385+
filters: candidates.map((v) => ({ text: String(v), value: v })),
386+
onFilter: (value: any, record: any) => String(record[dataIndex] ?? "") === String(value ?? ""),
387+
} as const;
388+
}
389+
390+
/**
391+
* Helper: build sorter props
392+
*/
393+
function buildSorterProps(
394+
column: RawColumnType,
395+
sortOrder: SortOrder | undefined,
396+
multiplePriority: number,
397+
) {
398+
if (!column.sortable) return {};
399+
const sorter = {
400+
multiple: multiplePriority,
401+
compare:
402+
column.columnType === 'date' || column.columnType === 'dateTime'
403+
? (a: any, b: any) => {
404+
return dayjs(a[column.dataIndex] as string).unix() - dayjs(b[column.dataIndex] as string).unix();
405+
}
406+
: undefined,
407+
} as const;
408+
return {
409+
sorter,
410+
sortOrder,
411+
showSorterTooltip: false,
412+
} as const;
413+
}
414+
415+
/**
416+
* Helper: build static style props
417+
*/
418+
function buildStyleProps(column: RawColumnType) {
419+
const style = {
420+
background: column.background,
421+
margin: column.margin,
422+
text: column.text,
423+
border: column.border,
424+
radius: column.radius,
425+
textSize: column.textSize,
426+
textWeight: column.textWeight,
427+
fontStyle: column.fontStyle,
428+
fontFamily: column.fontFamily,
429+
borderWidth: column.borderWidth,
430+
} as TableColumnStyleType;
431+
const linkStyle = {
432+
text: column.linkColor,
433+
hoverText: column.linkHoverColor,
434+
activeText: column.linkActiveColor,
435+
} as TableColumnLinkStyleType;
436+
return { style, linkStyle };
437+
}
438+
439+
/**
440+
* Helper: build render function with minimal closure
441+
*/
442+
function buildRenderFn(
443+
column: RawColumnType,
444+
size: string,
445+
candidateTags: string[],
446+
candidateStatus: { text: string; status: StatusType }[],
447+
onTableEvent: (eventName: any) => void,
448+
initialColumns: { label: string; value: string }[],
449+
) {
450+
return (value: any, record: RecordType, index: number) => {
451+
const row = _.omit(record, OB_ROW_ORI_INDEX);
452+
return column
453+
.render(
454+
{
455+
currentCell: value,
456+
currentRow: row,
457+
currentIndex: index,
458+
currentOriginalIndex: tryToNumber(record[OB_ROW_ORI_INDEX]),
459+
initialColumns,
460+
},
461+
String(record[OB_ROW_ORI_INDEX])
462+
)
463+
.getView()
464+
.view({
465+
tableSize: size,
466+
candidateTags,
467+
candidateStatus,
468+
textOverflow: column.textOverflow,
469+
cellTooltip: column.cellTooltip({
470+
currentCell: value,
471+
currentRow: row,
472+
currentIndex: index,
473+
}),
474+
onTableEvent,
475+
cellIndex: `${column.dataIndex}-${index}`,
476+
});
477+
};
478+
}
479+
291480
/**
292481
* convert column in raw format into antd format
293482
*/
@@ -303,134 +492,51 @@ export function columnsToAntdFormat(
303492
): Array<CustomColumnType<RecordType>> {
304493
const customColumns = columns.filter(col => col.isCustom).map(col => col.dataIndex);
305494
const initialColumns = getInitialColumns(columnsAggrData, customColumns);
306-
const sortMap: Map<string | undefined, SortOrder> = new Map(
307-
sort.map((s) => [s.column, s.desc ? "descend" : "ascend"])
308-
);
309-
const sortedColumns = _.sortBy(columns, (c) => {
310-
if (c.fixed === "left") {
311-
return -1;
312-
} else if (c.fixed === "right") {
313-
return Number.MAX_SAFE_INTEGER;
314-
} else if (dynamicColumnConfig.length > 0) {
315-
// sort by dynamic config array
316-
const index = dynamicColumnConfig.indexOf(c.isCustom ? c.title : c.dataIndex);
317-
if (index >= 0) {
318-
return index;
319-
}
320-
}
321-
return 0;
322-
});
323-
return sortedColumns.flatMap((column, mIndex) => {
324-
if (
325-
columnHide({
326-
hide: column.hide,
327-
tempHide: column.tempHide,
328-
enableColumnSetting: enableColumnSetting,
329-
})
330-
) {
331-
return [];
332-
}
333-
if (
334-
dynamicColumn &&
335-
dynamicColumnConfig.length > 0 &&
336-
!dynamicColumnConfig.includes(column.isCustom ? column.title : column.dataIndex)
337-
) {
338-
return [];
495+
const sortMap = computeSortMap(sort);
496+
const sortedColumns = orderColumns(columns, dynamicColumn, dynamicColumnConfig);
497+
498+
const result: Array<CustomColumnType<RecordType>> = [];
499+
500+
sortedColumns.forEach((column, mIndex) => {
501+
if (!shouldIncludeColumn(column, enableColumnSetting, dynamicColumn, dynamicColumnConfig)) {
502+
return;
339503
}
340-
const tags = ((columnsAggrData[column.dataIndex] ?? {}).uniqueTags ?? []) as string[];
341-
const status = ((columnsAggrData[column.dataIndex] ?? {}).uniqueStatus ?? []) as {
342-
text: string;
343-
status: StatusType;
344-
}[];
345-
const uniqueValues = (columnsAggrData[column.dataIndex] as any)?.uniqueValues as any[] ?? [];
346-
const title = renderTitle({ title: column.title, tooltip: column.titleTooltip });
347504

348-
const filterProps = column.filterable
349-
? {
350-
filters: (Array.isArray(tags) && tags.length > 0
351-
? tags
352-
: Array.isArray(uniqueValues) && uniqueValues.length > 0
353-
? uniqueValues
354-
: [])
355-
.slice(0, 100)
356-
.map((v) => ({ text: String(v), value: v })),
357-
358-
onFilter: (value: any, record: any) => String(record[column.dataIndex] ?? "") === String(value ?? ""),
359-
}
360-
: {};
505+
const { candidateTags, candidateStatus, uniqueValues } = extractAggrForColumn(column.dataIndex, columnsAggrData);
506+
const title = renderTitle({ title: column.title, tooltip: column.titleTooltip });
507+
const filterProps = buildFilterProps(column.dataIndex, column.filterable, candidateTags, uniqueValues);
508+
const { style, linkStyle } = buildStyleProps(column);
509+
const multiplePriority = (sortedColumns.length - mIndex) + 1;
510+
const sorterProps = buildSorterProps(column, sortMap.get(column.dataIndex), multiplePriority);
361511

362-
return {
363-
key: `${column.dataIndex}-${mIndex}`,
512+
const antdColumn: CustomColumnType<RecordType> = {
513+
key: `${column.dataIndex}`,
364514
title: column.showTitle ? title : '',
365515
titleText: column.title,
366516
dataIndex: column.dataIndex,
367517
align: column.align,
368518
width: column.autoWidth === "auto" ? 0 : column.width,
369519
fixed: column.fixed === "close" ? false : column.fixed,
370-
style: {
371-
background: column.background,
372-
margin: column.margin,
373-
text: column.text,
374-
border: column.border,
375-
radius: column.radius,
376-
textSize: column.textSize,
377-
textWeight: column.textWeight,
378-
fontStyle:column.fontStyle,
379-
fontFamily: column.fontFamily,
380-
borderWidth: column.borderWidth,
381-
},
382-
linkStyle: {
383-
text: column.linkColor,
384-
hoverText: column.linkHoverColor,
385-
activeText: column.linkActiveColor,
386-
},
520+
style,
521+
linkStyle,
387522
cellColorFn: column.cellColor,
388523
onWidthResize: column.onWidthResize,
389-
render: (value: any, record: RecordType, index: number) => {
390-
const row = _.omit(record, OB_ROW_ORI_INDEX);
391-
return column
392-
.render(
393-
{
394-
currentCell: value,
395-
currentRow: row,
396-
currentIndex: index,
397-
currentOriginalIndex: tryToNumber(record[OB_ROW_ORI_INDEX]),
398-
initialColumns,
399-
},
400-
String(record[OB_ROW_ORI_INDEX])
401-
)
402-
.getView()
403-
.view({
404-
tableSize: size,
405-
candidateTags: tags,
406-
candidateStatus: status,
407-
textOverflow: column.textOverflow,
408-
cellTooltip: column.cellTooltip({
409-
currentCell: value,
410-
currentRow: row,
411-
currentIndex: index,
412-
}),
413-
onTableEvent,
414-
cellIndex: `${column.dataIndex}-${index}`,
415-
});
416-
},
417-
...(column.sortable
418-
? {
419-
sorter: {
420-
multiple: (sortedColumns.length - mIndex) + 1,
421-
compare: column.columnType === 'date' || column.columnType === 'dateTime'
422-
? (a: any, b: any) => {
423-
return dayjs(a[column.dataIndex] as string).unix() - dayjs(b[column.dataIndex] as string).unix();
424-
}
425-
: undefined
426-
},
427-
sortOrder: sortMap.get(column.dataIndex),
428-
showSorterTooltip: false,
429-
}
430-
: {}),
431-
...filterProps,
524+
render: buildRenderFn(
525+
column,
526+
size,
527+
candidateTags,
528+
candidateStatus,
529+
onTableEvent,
530+
initialColumns,
531+
),
532+
...(sorterProps as any),
533+
...(filterProps as any),
432534
} as any;
535+
536+
result.push(antdColumn);
433537
});
538+
539+
return result;
434540
}
435541

436542
function getSortValue(sortResult: SorterResult<RecordType>) {

0 commit comments

Comments
 (0)