diff --git a/backend-node/src/services/dataService.ts b/backend-node/src/services/dataService.ts index 241bc9e3..2150a4af 100644 --- a/backend-node/src/services/dataService.ts +++ b/backend-node/src/services/dataService.ts @@ -18,45 +18,6 @@ import { pool } from "../database/db"; // ๐Ÿ†• Entity ์กฐ์ธ์„ ์œ„ํ•œ pool impo import { buildDataFilterWhereClause } from "../utils/dataFilterUtil"; // ๐Ÿ†• ๋ฐ์ดํ„ฐ ํ•„ํ„ฐ ์œ ํ‹ธ import { v4 as uuidv4 } from "uuid"; // ๐Ÿ†• UUID ์ƒ์„ฑ -/** - * ๋น„๋ฐ€๋ฒˆํ˜ธ(password) ํƒ€์ž… ์ปฌ๋Ÿผ์˜ ๊ฐ’์„ ๋นˆ ๋ฌธ์ž์—ด๋กœ ๋งˆ์Šคํ‚น - * - table_type_columns์—์„œ input_type = 'password'์ธ ์ปฌ๋Ÿผ์„ ์กฐํšŒ - * - ๋ฐ์ดํ„ฐ ์‘๋‹ต์—์„œ ํ•ด๋‹น ์ปฌ๋Ÿผ ๊ฐ’์„ ๋น„์›Œ์„œ ํ•ด์‹œ๊ฐ’ ๋…ธ์ถœ ๋ฐฉ์ง€ - */ -async function maskPasswordColumns(tableName: string, data: any): Promise { - try { - const passwordCols = await query<{ column_name: string }>( - `SELECT DISTINCT column_name FROM table_type_columns - WHERE table_name = $1 AND input_type = 'password'`, - [tableName] - ); - if (passwordCols.length === 0) return data; - - const passwordColumnNames = new Set(passwordCols.map(c => c.column_name)); - - // ๋‹จ์ผ ๊ฐ์ฒด ์ฒ˜๋ฆฌ - const maskRow = (row: any) => { - if (!row || typeof row !== "object") return row; - const masked = { ...row }; - for (const col of passwordColumnNames) { - if (col in masked) { - masked[col] = ""; // ํ•ด์‹œ๊ฐ’ ๋Œ€์‹  ๋นˆ ๋ฌธ์ž์—ด - } - } - return masked; - }; - - if (Array.isArray(data)) { - return data.map(maskRow); - } - return maskRow(data); - } catch (error) { - // ๋งˆ์Šคํ‚น ์‹คํŒจํ•ด๋„ ์›๋ณธ ๋ฐ์ดํ„ฐ ๋ฐ˜ํ™˜ (์„œ๋น„์Šค ์ค‘๋‹จ ๋ฐฉ์ง€) - console.warn("โš ๏ธ password ์ปฌ๋Ÿผ ๋งˆ์Šคํ‚น ์‹คํŒจ:", error); - return data; - } -} - interface GetTableDataParams { tableName: string; limit?: number; @@ -661,14 +622,14 @@ class DataService { return { success: true, - data: await maskPasswordColumns(tableName, normalizedGroupRows), // ๐Ÿ”ง ๋ฐฐ์—ด๋กœ ๋ฐ˜ํ™˜! + password ๋งˆ์Šคํ‚น + data: normalizedGroupRows, // ๐Ÿ”ง ๋ฐฐ์—ด๋กœ ๋ฐ˜ํ™˜! }; } } return { success: true, - data: await maskPasswordColumns(tableName, normalizedRows[0]), // ๊ทธ๋ฃนํ•‘ ์—†์œผ๋ฉด ๋‹จ์ผ ๋ ˆ์ฝ”๋“œ + password ๋งˆ์Šคํ‚น + data: normalizedRows[0], // ๊ทธ๋ฃนํ•‘ ์—†์œผ๋ฉด ๋‹จ์ผ ๋ ˆ์ฝ”๋“œ }; } } @@ -687,7 +648,7 @@ class DataService { return { success: true, - data: await maskPasswordColumns(tableName, result[0]), // password ๋งˆ์Šคํ‚น + data: result[0], }; } catch (error) { console.error(`๋ ˆ์ฝ”๋“œ ์ƒ์„ธ ์กฐํšŒ ์˜ค๋ฅ˜ (${tableName}/${id}):`, error); diff --git a/backend-node/src/services/dynamicFormService.ts b/backend-node/src/services/dynamicFormService.ts index 28ea6cc9..9e0915ee 100644 --- a/backend-node/src/services/dynamicFormService.ts +++ b/backend-node/src/services/dynamicFormService.ts @@ -2,7 +2,6 @@ import { query, queryOne, transaction, getPool } from "../database/db"; import { EventTriggerService } from "./eventTriggerService"; import { DataflowControlService } from "./dataflowControlService"; import tableCategoryValueService from "./tableCategoryValueService"; -import { PasswordUtils } from "../utils/passwordUtils"; export interface FormDataResult { id: number; @@ -860,33 +859,6 @@ export class DynamicFormService { } } - // ๋น„๋ฐ€๋ฒˆํ˜ธ(password) ํƒ€์ž… ์ปฌ๋Ÿผ ์ฒ˜๋ฆฌ - // - ๋นˆ ๊ฐ’์ด๋ฉด ๋ณ€๊ฒฝ ๋ชฉ๋ก์—์„œ ์ œ๊ฑฐ (๊ธฐ์กด ๋น„๋ฐ€๋ฒˆํ˜ธ ์œ ์ง€) - // - ๊ฐ’์ด ์žˆ์œผ๋ฉด ์•”ํ˜ธํ™” ํ›„ ์ €์žฅ - try { - const passwordCols = await query<{ column_name: string }>( - `SELECT DISTINCT column_name FROM table_type_columns - WHERE table_name = $1 AND input_type = 'password'`, - [tableName] - ); - for (const { column_name } of passwordCols) { - if (column_name in changedFields) { - const pwValue = changedFields[column_name]; - if (!pwValue || pwValue === "") { - // ๋นˆ ๊ฐ’ โ†’ ๊ธฐ์กด ๋น„๋ฐ€๋ฒˆํ˜ธ ์œ ์ง€ (๋ณ€๊ฒฝ ๋ชฉ๋ก์—์„œ ์ œ๊ฑฐ) - delete changedFields[column_name]; - console.log(`๐Ÿ” ๋น„๋ฐ€๋ฒˆํ˜ธ ํ•„๋“œ ${column_name}: ๋นˆ ๊ฐ’์ด๋ฏ€๋กœ ์—…๋ฐ์ดํŠธ ์Šคํ‚ต (๊ธฐ์กด ์œ ์ง€)`); - } else { - // ๊ฐ’ ์žˆ์Œ โ†’ ์•”ํ˜ธํ™”ํ•˜์—ฌ ์ €์žฅ - changedFields[column_name] = PasswordUtils.encrypt(pwValue); - console.log(`๐Ÿ” ๋น„๋ฐ€๋ฒˆํ˜ธ ํ•„๋“œ ${column_name}: ์ƒˆ ๋น„๋ฐ€๋ฒˆํ˜ธ ์•”ํ˜ธํ™” ์™„๋ฃŒ`); - } - } - } - } catch (pwError) { - console.warn("โš ๏ธ ๋น„๋ฐ€๋ฒˆํ˜ธ ์ปฌ๋Ÿผ ์ฒ˜๋ฆฌ ์ค‘ ์˜ค๋ฅ˜:", pwError); - } - // ๋ณ€๊ฒฝ๋œ ํ•„๋“œ๊ฐ€ ์—†์œผ๋ฉด ์—…๋ฐ์ดํŠธ ๊ฑด๋„ˆ๋›ฐ๊ธฐ if (Object.keys(changedFields).length === 0) { console.log("๐Ÿ“‹ ๋ณ€๊ฒฝ๋œ ํ•„๋“œ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์—…๋ฐ์ดํŠธ๋ฅผ ๊ฑด๋„ˆ๋œ๋‹ˆ๋‹ค."); diff --git a/frontend/components/screen/InteractiveScreenViewer.tsx b/frontend/components/screen/InteractiveScreenViewer.tsx index 05d8bdc9..c4b2ad0a 100644 --- a/frontend/components/screen/InteractiveScreenViewer.tsx +++ b/frontend/components/screen/InteractiveScreenViewer.tsx @@ -2231,11 +2231,20 @@ export const InteractiveScreenViewer: React.FC = ( } : component; - // ๐Ÿ†• ๋ชจ๋“  ๋ ˆ์ด์–ด์˜ ์ปดํฌ๋„ŒํŠธ๋ฅผ ํ†ตํ•ฉ (์กฐ๊ฑด๋ถ€ ๋ ˆ์ด์–ด ๋‚ด ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๊ธฐ๋ณธ ๋ ˆ์ด์–ด formData ์ฐธ์กฐ ๊ฐ€๋Šฅํ•˜๋„๋ก) + // ๋ชจ๋“  ๋ ˆ์ด์–ด์˜ ์ปดํฌ๋„ŒํŠธ ํ†ตํ•ฉ (์กฐ๊ฑด ํ‰๊ฐ€์šฉ - ํŠธ๋ฆฌ๊ฑฐ ์ปดํฌ๋„ŒํŠธ ๊ฒ€์ƒ‰์— ํ•„์š”) const allLayerComponents = useMemo(() => { return layers.flatMap((layer) => layer.components); }, [layers]); + // ๐Ÿ”ง ํ™œ์„ฑ ๋ ˆ์ด์–ด ์ปดํฌ๋„ŒํŠธ๋งŒ ํ†ตํ•ฉ (์ €์žฅ/๋ฐ์ดํ„ฐ ์ˆ˜์ง‘์šฉ) + // ๊ธฐ๋ณธ ๋ ˆ์ด์–ด(base) + ํ˜„์žฌ ํ™œ์„ฑํ™”๋œ ์กฐ๊ฑด๋ถ€ ๋ ˆ์ด์–ด๋งŒ ํฌํ•จ + // ๋น„ํ™œ์„ฑ ๋ ˆ์ด์–ด์˜ ์ค‘๋ณต columnName ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ €์žฅ ๋ฐ์ดํ„ฐ๋ฅผ ์˜ค์—ผ์‹œํ‚ค๋Š” ๋ฌธ์ œ ํ•ด๊ฒฐ + const visibleLayerComponents = useMemo(() => { + return layers + .filter((layer) => layer.type === "base" || activeLayerIds.includes(layer.id)) + .flatMap((layer) => layer.components); + }, [layers, activeLayerIds]); + // ๐Ÿ†• ๋ ˆ์ด์–ด๋ณ„ ์ปดํฌ๋„ŒํŠธ ๋ Œ๋”๋ง ํ•จ์ˆ˜ const renderLayerComponents = useCallback((layer: LayerDefinition) => { // ํ™œ์„ฑํ™”๋˜์ง€ ์•Š์€ ๋ ˆ์ด์–ด๋Š” ๋ Œ๋”๋งํ•˜์ง€ ์•Š์Œ @@ -2272,7 +2281,7 @@ export const InteractiveScreenViewer: React.FC = ( > = ( > = ( > = ( > = ( })} ); - }, [activeLayerIds, handleLayerAction, externalFormData, onFormDataChange, screenInfo, calculateYOffset, allLayerComponents, layers]); + }, [activeLayerIds, handleLayerAction, externalFormData, onFormDataChange, screenInfo, calculateYOffset, visibleLayerComponents, layers]); return ( diff --git a/frontend/lib/registry/components/selected-items-detail-input/SelectedItemsDetailInputComponent.tsx b/frontend/lib/registry/components/selected-items-detail-input/SelectedItemsDetailInputComponent.tsx index 6af5a88f..c2bb436d 100644 --- a/frontend/lib/registry/components/selected-items-detail-input/SelectedItemsDetailInputComponent.tsx +++ b/frontend/lib/registry/components/selected-items-detail-input/SelectedItemsDetailInputComponent.tsx @@ -67,6 +67,10 @@ export const SelectedItemsDetailInputComponent: React.FC ์ปดํฌ๋„ŒํŠธ ์„ค์ • > component.id const dataSourceId = useMemo( () => urlDataSourceId || componentConfig.dataSourceId || component.id || "default", @@ -228,7 +232,21 @@ export const SelectedItemsDetailInputComponent: React.FC[]> = {}; - if (firstRecord.customer_id && firstRecord.item_id) { + // ๋™์  ํ•„ํ„ฐ ๊ตฌ์„ฑ: parentDataMapping์˜ targetField + sourceKeyField + const editFilters: Record = {}; + const parentMappings = componentConfig.parentDataMapping || []; + parentMappings.forEach((mapping: any) => { + if (mapping.targetField && firstRecord[mapping.targetField]) { + editFilters[mapping.targetField] = firstRecord[mapping.targetField]; + } + }); + if (firstRecord[sourceKeyField]) { + editFilters[sourceKeyField] = firstRecord[sourceKeyField]; + } + + const hasRequiredKeys = Object.keys(editFilters).length >= 2; + + if (hasRequiredKeys) { try { const { dataApi } = await import("@/lib/api/data"); // ๋ชจ๋“  sourceTable์˜ ๋ฐ์ดํ„ฐ๋ฅผ API๋กœ ์ „์ฒด ๋กœ๋“œ (์ค‘๋ณต ํ…Œ์ด๋ธ” ์ œ๊ฑฐ) @@ -238,10 +256,7 @@ export const SelectedItemsDetailInputComponent: React.FC { const groupFields = additionalFields.filter((f) => f.groupId === group.id); groupFields.forEach((field) => { - if (field.name === "item_id" && field.autoFillFrom && item.originalData) { - itemId = item.originalData[field.autoFillFrom] || null; + if (field.name === sourceKeyField && field.autoFillFrom && item.originalData) { + sourceKeyValue = item.originalData[field.autoFillFrom] || null; } }); }); } // 3์ˆœ์œ„: fallback (์ตœํ›„์˜ ์ˆ˜๋‹จ) - if (!itemId && item.originalData) { - itemId = item.originalData.id || null; + if (!sourceKeyValue && item.originalData) { + sourceKeyValue = item.originalData.id || null; } - if (!itemId) { - console.error("โŒ [2๋‹จ๊ณ„ ์ €์žฅ] item_id๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Œ:", item); + if (!sourceKeyValue) { + console.error(`โŒ [2๋‹จ๊ณ„ ์ €์žฅ] ${sourceKeyField}๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Œ:`, item); continue; } - // upsert ๊ณตํ†ต parentKeys: customer_id + item_id (์ •ํ™•ํ•œ ๋งค์นญ) - const itemParentKeys = { ...parentKeys, item_id: itemId }; + // upsert ๊ณตํ†ต parentKeys: parentMapping ํ‚ค + sourceKeyField (์ •ํ™•ํ•œ ๋งค์นญ) + const itemParentKeys = { ...parentKeys, [sourceKeyField]: sourceKeyValue }; // === Step 1: ๋ฉ”์ธ ํ…Œ์ด๋ธ”(customer_item_mapping) ์ €์žฅ === // ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๋งคํ•‘ ๋ ˆ์ฝ”๋“œ ์ง€์› (๊ฑฐ๋ž˜์ฒ˜ ํ’ˆ๋ฒˆ/ํ’ˆ๋ช…์ด ๋‹ค์ค‘์ผ ์ˆ˜ ์žˆ์Œ) @@ -688,11 +703,11 @@ export const SelectedItemsDetailInputComponent: React.FC { - if (field.name !== "item_id" && field.autoFillFrom && item.originalData) { + if (field.name !== sourceKeyField && field.autoFillFrom && item.originalData) { const value = item.originalData[field.autoFillFrom]; if (value !== undefined && value !== null && !record[field.name]) { record[field.name] = value; @@ -1700,7 +1715,7 @@ export const SelectedItemsDetailInputComponent: React.FC f.name !== "item_id" && f.width !== "0px"); + const sampleFields = (componentConfig.additionalFields || []).filter(f => f.name !== sourceKeyField && f.width !== "0px"); const sampleGroups = componentConfig.fieldGroups || [{ id: "default", title: "์ž…๋ ฅ ์ •๋ณด", order: 0 }]; const gridCols = sampleGroups.length === 1 ? "grid-cols-1" : "grid-cols-2"; diff --git a/frontend/lib/registry/components/v2-split-panel-layout/SplitPanelLayoutComponent.tsx b/frontend/lib/registry/components/v2-split-panel-layout/SplitPanelLayoutComponent.tsx index bb9306c8..ebecedb3 100644 --- a/frontend/lib/registry/components/v2-split-panel-layout/SplitPanelLayoutComponent.tsx +++ b/frontend/lib/registry/components/v2-split-panel-layout/SplitPanelLayoutComponent.tsx @@ -1183,31 +1183,15 @@ export const SplitPanelLayoutComponent: React.FC } // leftItem์ด null์ด๋ฉด join ๋ชจ๋“œ ์ด์™ธ์—๋Š” ๋ฐ์ดํ„ฐ ๋กœ๋“œ ๋ถˆ๊ฐ€ + // detail ๋ชจ๋“œ: ์„ ํƒ ์•ˆ ํ•˜๋ฉด ์•„๋ฌด๊ฒƒ๋„ ์•ˆ ๋œธ, ์„ ํƒํ•˜๋ฉด ํ•„ํ„ฐ๋ง + // join ๋ชจ๋“œ: ์„ ํƒ ์•ˆ ํ•˜๋ฉด ์ „์ฒด, ์„ ํƒํ•˜๋ฉด ํ•„ํ„ฐ๋ง if (!leftItem) return; setIsLoadingRight(true); try { - if (relationshipType === "detail") { - // ์ƒ์„ธ ๋ชจ๋“œ: ๋™์ผ ํ…Œ์ด๋ธ”์˜ ์ƒ์„ธ ์ •๋ณด (์—”ํ‹ฐํ‹ฐ ์กฐ์ธ ํ™œ์„ฑํ™”) - const primaryKey = leftItem.id || leftItem.ID || Object.values(leftItem)[0]; - - // ๐Ÿ†• ์—”ํ‹ฐํ‹ฐ ์กฐ์ธ API ์‚ฌ์šฉ - const { entityJoinApi } = await import("@/lib/api/entityJoin"); - const rightDetailJoinColumns = extractAdditionalJoinColumns( - componentConfig.rightPanel?.columns, - rightTableName, - ); - const result = await entityJoinApi.getTableDataWithJoins(rightTableName, { - search: { id: primaryKey }, - enableEntityJoin: true, - size: 1, - companyCodeOverride: companyCode, - additionalJoinColumns: rightDetailJoinColumns, // ๐Ÿ†• Entity ์กฐ์ธ ์ปฌ๋Ÿผ ์ „๋‹ฌ - }); - - const detail = result.items && result.items.length > 0 ? result.items[0] : null; - setRightData(detail); - } else if (relationshipType === "join") { + // detail / join ๋ชจ๋‘ ๋™์ผํ•œ ํ•„ํ„ฐ๋ง ๋กœ์ง ์‚ฌ์šฉ + // (์ฐจ์ด์ : ์ดˆ๊ธฐ ๋กœ๋“œ ์—ฌ๋ถ€๋งŒ ๋‹ค๋ฆ„ - detail์€ ์ดˆ๊ธฐ ๋กœ๋“œ ์•ˆ ํ•จ) + { // ์กฐ์ธ ๋ชจ๋“œ: ๋‹ค๋ฅธ ํ…Œ์ด๋ธ”์˜ ๊ด€๋ จ ๋ฐ์ดํ„ฐ (์—ฌ๋Ÿฌ ๊ฐœ) const keys = componentConfig.rightPanel?.relation?.keys; const leftTable = componentConfig.leftPanel?.tableName; @@ -1443,16 +1427,24 @@ export const SplitPanelLayoutComponent: React.FC // ํƒญ์˜ dataFilter (API ์ „๋‹ฌ์šฉ) const tabDataFilterForApi = (tabConfig as any).dataFilter; + // ํƒญ์˜ relation type ํ™•์ธ (detail์ด๋ฉด ์ดˆ๊ธฐ ์ „์ฒด ๋กœ๋“œ ์•ˆ ํ•จ) + const tabRelationType = tabConfig.relation?.type || "join"; + if (!leftItem) { - // ์ขŒ์ธก ๋ฏธ์„ ํƒ: ์ „์ฒด ๋ฐ์ดํ„ฐ ๋กœ๋“œ (dataFilter๋Š” API์— ์ „๋‹ฌ) - const result = await entityJoinApi.getTableDataWithJoins(tabTableName, { - enableEntityJoin: true, - size: 1000, - companyCodeOverride: companyCode, - additionalJoinColumns: tabJoinColumns, - dataFilter: tabDataFilterForApi, - }); - resultData = result.data || []; + if (tabRelationType === "detail") { + // detail ๋ชจ๋“œ: ์„ ํƒ ์•ˆ ํ•˜๋ฉด ์•„๋ฌด๊ฒƒ๋„ ์•ˆ ๋œธ + resultData = []; + } else { + // join ๋ชจ๋“œ: ์ขŒ์ธก ๋ฏธ์„ ํƒ ์‹œ ์ „์ฒด ๋ฐ์ดํ„ฐ ๋กœ๋“œ (dataFilter๋Š” API์— ์ „๋‹ฌ) + const result = await entityJoinApi.getTableDataWithJoins(tabTableName, { + enableEntityJoin: true, + size: 1000, + companyCodeOverride: companyCode, + additionalJoinColumns: tabJoinColumns, + dataFilter: tabDataFilterForApi, + }); + resultData = result.data || []; + } } else if (leftColumn && rightColumn) { const searchConditions: Record = {}; @@ -2781,16 +2773,20 @@ export const SplitPanelLayoutComponent: React.FC if (!isDesignMode && componentConfig.autoLoad !== false) { loadLeftData(); // ์ขŒ์ธก ๋ฏธ์„ ํƒ ์ƒํƒœ์—์„œ ์šฐ์ธก ์ „์ฒด ๋ฐ์ดํ„ฐ ๊ธฐ๋ณธ ๋กœ๋“œ + // join ๋ชจ๋“œ: ์ดˆ๊ธฐ ์ „์ฒด ๋กœ๋“œ / detail ๋ชจ๋“œ: ์ดˆ๊ธฐ ๋กœ๋“œ ์•ˆ ํ•จ const relationshipType = componentConfig.rightPanel?.relation?.type || "detail"; if (relationshipType === "join") { loadRightData(null); - // ์ถ”๊ฐ€ ํƒญ๋„ ์ „์ฒด ๋ฐ์ดํ„ฐ ๋กœ๋“œ - const tabs = componentConfig.rightPanel?.additionalTabs; - if (tabs && tabs.length > 0) { - tabs.forEach((_: any, idx: number) => { + } + // ์ถ”๊ฐ€ ํƒญ: ๊ฐ ํƒญ์˜ relation.type์— ๋”ฐ๋ผ ์ดˆ๊ธฐ ๋กœ๋“œ ๊ฒฐ์ • + const tabs = componentConfig.rightPanel?.additionalTabs; + if (tabs && tabs.length > 0) { + tabs.forEach((tab: any, idx: number) => { + const tabRelType = tab.relation?.type || "join"; + if (tabRelType === "join") { loadTabData(idx + 1, null); - }); - } + } + }); } } // eslint-disable-next-line react-hooks/exhaustive-deps @@ -4645,7 +4641,7 @@ export const SplitPanelLayoutComponent: React.FC ) : ( <>

์ขŒ์ธก์—์„œ ํ•ญ๋ชฉ์„ ์„ ํƒํ•˜์„ธ์š”

-

์„ ํƒํ•œ ํ•ญ๋ชฉ์˜ ์ƒ์„ธ ์ •๋ณด๊ฐ€ ์—ฌ๊ธฐ์— ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค

+

์„ ํƒํ•œ ํ•ญ๋ชฉ์˜ ๊ด€๋ จ ๋ฐ์ดํ„ฐ๊ฐ€ ์—ฌ๊ธฐ์— ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค

)} diff --git a/frontend/lib/registry/components/v2-split-panel-layout/SplitPanelLayoutConfigPanel.tsx b/frontend/lib/registry/components/v2-split-panel-layout/SplitPanelLayoutConfigPanel.tsx index 52fd30a1..d77cb88d 100644 --- a/frontend/lib/registry/components/v2-split-panel-layout/SplitPanelLayoutConfigPanel.tsx +++ b/frontend/lib/registry/components/v2-split-panel-layout/SplitPanelLayoutConfigPanel.tsx @@ -1542,13 +1542,10 @@ export const SplitPanelLayoutConfigPanel: React.FC { - if (relationshipType === "detail") { - return leftTableName; // ์ƒ์„ธ ๋ชจ๋“œ์—์„œ๋Š” ์ขŒ์ธก๊ณผ ๋™์ผ - } return config.rightPanel?.tableName || ""; - }, [relationshipType, leftTableName, config.rightPanel?.tableName]); + }, [config.rightPanel?.tableName]); // ์šฐ์ธก ํ…Œ์ด๋ธ” ์ปฌ๋Ÿผ (๋กœ๋“œ๋œ ์ปฌ๋Ÿผ ์‚ฌ์šฉ) const rightTableColumns = useMemo(() => { @@ -1567,8 +1564,8 @@ export const SplitPanelLayoutConfigPanel: React.FC { - // ์ƒ์„ธ ๋ชจ๋“œ๋กœ ๋ณ€๊ฒฝ ์‹œ ์šฐ์ธก ํ…Œ์ด๋ธ”์„ ํ˜„์žฌ ํ™”๋ฉด ํ…Œ์ด๋ธ”๋กœ ์„ค์ • - if (value === "detail" && screenTableName) { - updateRightPanel({ - relation: { ...config.rightPanel?.relation, type: value }, - tableName: screenTableName, - }); - } else { - updateRightPanel({ - relation: { ...config.rightPanel?.relation, type: value }, - }); - } + updateRightPanel({ + relation: { ...config.rightPanel?.relation, type: value }, + }); }} > - {relationshipType === "detail" ? "1๊ฑด ์ƒ์„ธ๋ณด๊ธฐ" : "์—ฐ๊ด€ ๋ชฉ๋ก"} + {relationshipType === "detail" ? "์„ ํƒ ์‹œ ํ‘œ์‹œ" : "์—ฐ๊ด€ ๋ชฉ๋ก"}
- 1๊ฑด ์ƒ์„ธ๋ณด๊ธฐ - ์ขŒ์ธก ํด๋ฆญ ์‹œ ํ•ด๋‹น ํ•ญ๋ชฉ์˜ ์ƒ์„ธ ์ •๋ณด ํ‘œ์‹œ (๊ฐ™์€ ํ…Œ์ด๋ธ”) + ์„ ํƒ ์‹œ ํ‘œ์‹œ + ์ขŒ์ธก ์„ ํƒ ์‹œ์—๋งŒ ์šฐ์ธก ๋ฐ์ดํ„ฐ ํ‘œ์‹œ / ๋ฏธ์„ ํƒ ์‹œ ๋นˆ ํ™”๋ฉด
์—ฐ๊ด€ ๋ชฉ๋ก - ์ขŒ์ธก ํด๋ฆญ ์‹œ ์—ฐ๊ด€๋œ ๋ฐ์ดํ„ฐ ๋ชฉ๋ก ํ‘œ์‹œ / ๋ฏธ์„ ํƒ ์‹œ ์ „์ฒด ํ‘œ์‹œ + ๋ฏธ์„ ํƒ ์‹œ ์ „์ฒด ํ‘œ์‹œ / ์ขŒ์ธก ์„ ํƒ ์‹œ ํ•„ํ„ฐ๋ง
@@ -2305,7 +2294,7 @@ export const SplitPanelLayoutConfigPanel: React.FC {/* ์šฐ์ธก ํŒจ๋„ ์„ค์ • */}
-

์šฐ์ธก ํŒจ๋„ ์„ค์ • ({relationshipType === "detail" ? "1๊ฑด ์ƒ์„ธ๋ณด๊ธฐ" : "์—ฐ๊ด€ ๋ชฉ๋ก"})

+

์šฐ์ธก ํŒจ๋„ ์„ค์ • ({relationshipType === "detail" ? "์„ ํƒ ์‹œ ํ‘œ์‹œ" : "์—ฐ๊ด€ ๋ชฉ๋ก"})

@@ -2338,63 +2327,49 @@ export const SplitPanelLayoutConfigPanel: React.FC */} {/* ๊ด€๊ณ„ ํƒ€์ž…์— ๋”ฐ๋ผ ํ…Œ์ด๋ธ” ์„ ํƒ UI ๋ณ€๊ฒฝ */} - {relationshipType === "detail" ? ( - // ์ƒ์„ธ ๋ชจ๋“œ: ์ขŒ์ธก๊ณผ ๋™์ผํ•œ ํ…Œ์ด๋ธ” (์ž๋™ ์„ค์ •) -
- -
-

- {config.leftPanel?.tableName || screenTableName || "ํ…Œ์ด๋ธ”์ด ์ง€์ •๋˜์ง€ ์•Š์Œ"} -

-

์ƒ์„ธ ๋ชจ๋“œ์—์„œ๋Š” ์ขŒ์ธก๊ณผ ๋™์ผํ•œ ํ…Œ์ด๋ธ”์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค

-
-
- ) : ( - // ์กฐ๊ฑด ํ•„ํ„ฐ ๋ชจ๋“œ: ์ „์ฒด ํ…Œ์ด๋ธ”์—์„œ ์„ ํƒ ๊ฐ€๋Šฅ -
- - - - - - - - - ํ…Œ์ด๋ธ”์„ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. - - {availableRightTables.map((table) => ( - { - updateRightPanel({ tableName: table.tableName }); - setRightTableOpen(false); - }} - > - - {table.displayName || table.tableName} - {table.displayName && ({table.tableName})} - - ))} - - - - -
- )} +
+ + + + + + + + + ํ…Œ์ด๋ธ”์„ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. + + {availableRightTables.map((table) => ( + { + updateRightPanel({ tableName: table.tableName }); + setRightTableOpen(false); + }} + > + + {table.displayName || table.tableName} + {table.displayName && ({table.tableName})} + + ))} + + + + +