diff --git a/frontend/lib/registry/components/table-list/TableListComponent.tsx b/frontend/lib/registry/components/table-list/TableListComponent.tsx index b722e31c..651675b8 100644 --- a/frontend/lib/registry/components/table-list/TableListComponent.tsx +++ b/frontend/lib/registry/components/table-list/TableListComponent.tsx @@ -1506,6 +1506,7 @@ export const TableListComponent: React.FC = ({ tableName: tableConfig.selectedTable, selectedLeftData: splitPanelContext?.selectedLeftData, linkedFilters: splitPanelContext?.linkedFilters, + splitPanelPosition: splitPanelPosition, }); if (splitPanelContext) { @@ -1537,6 +1538,39 @@ export const TableListComponent: React.FC = ({ linkedFilterValues[key] = value; } } + + // ๐Ÿ†• ์ž๋™ ์ปฌ๋Ÿผ ๋งค์นญ: linkedFilters๊ฐ€ ์„ค์ •๋˜์–ด ์žˆ์ง€ ์•Š์•„๋„ + // ์šฐ์ธก ํ™”๋ฉด(splitPanelPosition === "right")์ด๊ณ  ์ขŒ์ธก ๋ฐ์ดํ„ฐ๊ฐ€ ์„ ํƒ๋˜์–ด ์žˆ์œผ๋ฉด + // ๋™์ผํ•œ ์ปฌ๋Ÿผ๋ช…์ด ์žˆ๋Š” ๊ฒฝ์šฐ ์ž๋™์œผ๋กœ ํ•„ํ„ฐ๋ง ์ ์šฉ + if ( + splitPanelPosition === "right" && + hasSelectedLeftData && + Object.keys(linkedFilterValues).length === 0 && + !hasLinkedFiltersConfigured + ) { + const leftData = splitPanelContext.selectedLeftData!; + const tableColumns = (tableConfig.columns || []).map((col) => col.columnName); + + // ์ขŒ์ธก ๋ฐ์ดํ„ฐ์˜ ์ปฌ๋Ÿผ ์ค‘ ํ˜„์žฌ ํ…Œ์ด๋ธ”์— ๋™์ผํ•œ ์ปฌ๋Ÿผ์ด ์žˆ๋Š”์ง€ ํ™•์ธ + for (const [colName, colValue] of Object.entries(leftData)) { + // null, undefined, ๋นˆ ๋ฌธ์ž์—ด ์ œ์™ธ + if (colValue === null || colValue === undefined || colValue === "") continue; + // id, objid ๋“ฑ ๊ธฐ๋ณธ ํ‚ค๋Š” ์ œ์™ธ (๋„ˆ๋ฌด ์ผ๋ฐ˜์ ์ธ ์ปฌ๋Ÿผ๋ช…) + if (colName === "id" || colName === "objid" || colName === "company_code") continue; + + // ํ˜„์žฌ ํ…Œ์ด๋ธ”์— ๋™์ผํ•œ ์ปฌ๋Ÿผ์ด ์žˆ๋Š”์ง€ ํ™•์ธ + if (tableColumns.includes(colName)) { + linkedFilterValues[colName] = colValue; + hasLinkedFiltersConfigured = true; + console.log(`๐Ÿ”— [TableList] ์ž๋™ ์ปฌ๋Ÿผ ๋งค์นญ: ${colName} = ${colValue}`); + } + } + + if (Object.keys(linkedFilterValues).length > 0) { + console.log("๐Ÿ”— [TableList] ์ž๋™ ์ปฌ๋Ÿผ ๋งค์นญ ํ•„ํ„ฐ ์ ์šฉ:", linkedFilterValues); + } + } + if (Object.keys(linkedFilterValues).length > 0) { console.log("๐Ÿ”— [TableList] ์—ฐ๊ฒฐ ํ•„ํ„ฐ ์ ์šฉ:", linkedFilterValues); } @@ -1749,7 +1783,10 @@ export const TableListComponent: React.FC = ({ searchTerm, searchValues, isDesignMode, - splitPanelContext?.selectedLeftData, // ๐Ÿ†• ์—ฐ๊ฒฐ ํ•„ํ„ฐ ๋ณ€๊ฒฝ ์‹œ ์žฌ์กฐํšŒ + // ๐Ÿ†• ์šฐ์ธก ํ™”๋ฉด์ผ ๋•Œ๋งŒ selectedLeftData ๋ณ€๊ฒฝ์— ๋ฐ˜์‘ (์ขŒ์ธก ํ…Œ์ด๋ธ”์€ ์žฌ์กฐํšŒ ๋ถˆํ•„์š”) + splitPanelPosition, + currentSplitPosition, + splitPanelContext?.selectedLeftData, ]); const fetchTableDataDebounced = useCallback( @@ -2059,7 +2096,18 @@ export const TableListComponent: React.FC = ({ // ๐Ÿ†• ๋ถ„ํ•  ํŒจ๋„ ์ปจํ…์ŠคํŠธ์— ์„ ํƒ๋œ ๋ฐ์ดํ„ฐ ์ €์žฅ (์ขŒ์ธก ํ™”๋ฉด์ธ ๊ฒฝ์šฐ) // disableAutoDataTransfer๊ฐ€ true์ด๋ฉด ์ž๋™ ์ „๋‹ฌ ๋น„ํ™œ์„ฑํ™” (๋ฒ„ํŠผ ํด๋ฆญ์œผ๋กœ๋งŒ ์ „๋‹ฌ) - if (splitPanelContext && splitPanelPosition === "left" && !splitPanelContext.disableAutoDataTransfer) { + // currentSplitPosition์„ ์‚ฌ์šฉํ•˜์—ฌ ์ •ํ™•ํ•œ ์œ„์น˜ ํ™•์ธ (splitPanelPosition์ด ์—†์„ ์ˆ˜ ์žˆ์Œ) + const effectiveSplitPosition = splitPanelPosition || currentSplitPosition; + + console.log("๐Ÿ”— [TableList] ํ–‰ ํด๋ฆญ - ๋ถ„ํ•  ํŒจ๋„ ์œ„์น˜ ํ™•์ธ:", { + splitPanelPosition, + currentSplitPosition, + effectiveSplitPosition, + hasSplitPanelContext: !!splitPanelContext, + disableAutoDataTransfer: splitPanelContext?.disableAutoDataTransfer, + }); + + if (splitPanelContext && effectiveSplitPosition === "left" && !splitPanelContext.disableAutoDataTransfer) { if (!isCurrentlySelected) { // ์„ ํƒ๋œ ๊ฒฝ์šฐ: ๋ฐ์ดํ„ฐ ์ €์žฅ splitPanelContext.setSelectedLeftData(row); @@ -2077,12 +2125,57 @@ export const TableListComponent: React.FC = ({ console.log("ํ–‰ ํด๋ฆญ:", { row, index, isSelected: !isCurrentlySelected }); }; - // ๐Ÿ†• ์…€ ํด๋ฆญ ํ•ธ๋“ค๋Ÿฌ (ํฌ์ปค์Šค ์„ค์ •) + // ๐Ÿ†• ์…€ ํด๋ฆญ ํ•ธ๋“ค๋Ÿฌ (ํฌ์ปค์Šค ์„ค์ • + ํ–‰ ์„ ํƒ) const handleCellClick = (rowIndex: number, colIndex: number, e: React.MouseEvent) => { e.stopPropagation(); setFocusedCell({ rowIndex, colIndex }); // ํ…Œ์ด๋ธ” ์ปจํ…Œ์ด๋„ˆ์— ํฌ์ปค์Šค ์„ค์ • (ํ‚ค๋ณด๋“œ ์ด๋ฒคํŠธ ์ˆ˜์‹ ์šฉ) tableContainerRef.current?.focus(); + + // ๐Ÿ†• ๋ถ„ํ•  ํŒจ๋„ ๋‚ด์—์„œ ์…€ ํด๋ฆญ ์‹œ์—๋„ ํ•ด๋‹น ํ–‰ ์„ ํƒ ์ฒ˜๋ฆฌ + // filteredData์—์„œ ํ•ด๋‹น ํ–‰์˜ ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ + const row = filteredData[rowIndex]; + if (!row) return; + + const rowKey = getRowKey(row, rowIndex); + const isCurrentlySelected = selectedRows.has(rowKey); + + // ๋ถ„ํ•  ํŒจ๋„ ์ปจํ…์ŠคํŠธ๊ฐ€ ์žˆ๊ณ , ์ขŒ์ธก ํ™”๋ฉด์ธ ๊ฒฝ์šฐ์—๋งŒ ํ–‰ ์„ ํƒ ๋ฐ ๋ฐ์ดํ„ฐ ์ „๋‹ฌ + const effectiveSplitPosition = splitPanelPosition || currentSplitPosition; + + console.log("๐Ÿ”— [TableList] ์…€ ํด๋ฆญ - ๋ถ„ํ•  ํŒจ๋„ ์œ„์น˜ ํ™•์ธ:", { + rowIndex, + colIndex, + splitPanelPosition, + currentSplitPosition, + effectiveSplitPosition, + hasSplitPanelContext: !!splitPanelContext, + isCurrentlySelected, + }); + + if (splitPanelContext && effectiveSplitPosition === "left" && !splitPanelContext.disableAutoDataTransfer) { + // ์ด๋ฏธ ์„ ํƒ๋œ ํ–‰๊ณผ ๋‹ค๋ฅธ ํ–‰์„ ํด๋ฆญํ•œ ๊ฒฝ์šฐ์—๋งŒ ์ฒ˜๋ฆฌ + if (!isCurrentlySelected) { + // ๊ธฐ์กด ์„ ํƒ ํ•ด์ œํ•˜๊ณ  ์ƒˆ ํ–‰ ์„ ํƒ + setSelectedRows(new Set([rowKey])); + setIsAllSelected(false); + + // ๋ถ„ํ•  ํŒจ๋„ ์ปจํ…์ŠคํŠธ์— ๋ฐ์ดํ„ฐ ์ €์žฅ + splitPanelContext.setSelectedLeftData(row); + console.log("๐Ÿ”— [TableList] ์…€ ํด๋ฆญ์œผ๋กœ ๋ถ„ํ•  ํŒจ๋„ ์ขŒ์ธก ๋ฐ์ดํ„ฐ ์ €์žฅ:", { + row, + parentDataMapping: splitPanelContext.parentDataMapping, + }); + + // onSelectedRowsChange ์ฝœ๋ฐฑ ํ˜ธ์ถœ + if (onSelectedRowsChange) { + onSelectedRowsChange([rowKey], [row], sortColumn || undefined, sortDirection); + } + if (onFormDataChange) { + onFormDataChange({ selectedRows: [rowKey], selectedRowsData: [row] }); + } + } + } }; // ๐Ÿ†• ์…€ ๋”๋ธ”ํด๋ฆญ ํ•ธ๋“ค๋Ÿฌ (ํŽธ์ง‘ ๋ชจ๋“œ ์ง„์ž…) - visibleColumns ์ •์˜ ํ›„ ์‚ฌ์šฉ @@ -4066,13 +4159,13 @@ export const TableListComponent: React.FC = ({ // ๐Ÿ“Ž ์ฒจ๋ถ€ํŒŒ์ผ ํƒ€์ž…: ํŒŒ์ผ ์•„์ด์ฝ˜๊ณผ ๊ฐœ์ˆ˜ ํ‘œ์‹œ // ์ปฌ๋Ÿผ๋ช…์ด 'attachments'๋ฅผ ํฌํ•จํ•˜๊ฑฐ๋‚˜, inputType์ด file/attachment์ธ ๊ฒฝ์šฐ - const isAttachmentColumn = - inputType === "file" || - inputType === "attachment" || + const isAttachmentColumn = + inputType === "file" || + inputType === "attachment" || column.columnName === "attachments" || column.columnName?.toLowerCase().includes("attachment") || column.columnName?.toLowerCase().includes("file"); - + if (isAttachmentColumn) { // JSONB ๋ฐฐ์—ด ๋˜๋Š” JSON ๋ฌธ์ž์—ด ํŒŒ์‹ฑ let files: any[] = []; @@ -4098,21 +4191,14 @@ export const TableListComponent: React.FC = ({ // ํŒŒ์ผ ์ด๋ฆ„ ํ‘œ์‹œ (์—ฌ๋Ÿฌ ๊ฐœ๋ฉด ์‰ผํ‘œ๋กœ ๊ตฌ๋ถ„) const { Paperclip } = require("lucide-react"); const fileNames = files.map((f: any) => f.realFileName || f.real_file_name || f.name || "ํŒŒ์ผ").join(", "); - + return ( -
- - +
+ + {fileNames} - {files.length > 1 && ( - - ({files.length}) - - )} + {files.length > 1 && ({files.length})}
); } @@ -4677,6 +4763,10 @@ export const TableListComponent: React.FC = ({ fetchTableLabel(); }, [tableConfig.selectedTable, fetchColumnLabels, fetchTableLabel]); + // ๐Ÿ†• ์šฐ์ธก ํ™”๋ฉด์ผ ๋•Œ๋งŒ selectedLeftData ๋ณ€๊ฒฝ์— ๋ฐ˜์‘ํ•˜๋„๋ก ๋ณ€์ˆ˜ ์ƒ์„ฑ + const isRightPanel = splitPanelPosition === "right" || currentSplitPosition === "right"; + const selectedLeftDataForRightPanel = isRightPanel ? splitPanelContext?.selectedLeftData : null; + useEffect(() => { // console.log("๐Ÿ” [TableList] useEffect ์‹คํ–‰ - ๋ฐ์ดํ„ฐ ์กฐํšŒ ํŠธ๋ฆฌ๊ฑฐ", { // isDesignMode, @@ -4700,7 +4790,7 @@ export const TableListComponent: React.FC = ({ refreshKey, refreshTrigger, // ๊ฐ•์ œ ์ƒˆ๋กœ๊ณ ์นจ ํŠธ๋ฆฌ๊ฑฐ isDesignMode, - splitPanelContext?.selectedLeftData, // ๐Ÿ†• ์ขŒ์ธก ๋ฐ์ดํ„ฐ ์„ ํƒ ๋ณ€๊ฒฝ ์‹œ ๋ฐ์ดํ„ฐ ์ƒˆ๋กœ๊ณ ์นจ + selectedLeftDataForRightPanel, // ๐Ÿ†• ์šฐ์ธก ํ™”๋ฉด์ผ ๋•Œ๋งŒ ์ขŒ์ธก ๋ฐ์ดํ„ฐ ์„ ํƒ ๋ณ€๊ฒฝ ์‹œ ๋ฐ์ดํ„ฐ ์ƒˆ๋กœ๊ณ ์นจ // fetchTableDataDebounced ์ œ๊ฑฐ: useCallback ์žฌ์ƒ์„ฑ์œผ๋กœ ์ธํ•œ ๋ฌดํ•œ ๋ฃจํ”„ ๋ฐฉ์ง€ ]);