diff --git a/frontend/components/screen/InteractiveScreenViewerDynamic.tsx b/frontend/components/screen/InteractiveScreenViewerDynamic.tsx index 1dfdba14..d906a404 100644 --- a/frontend/components/screen/InteractiveScreenViewerDynamic.tsx +++ b/frontend/components/screen/InteractiveScreenViewerDynamic.tsx @@ -365,7 +365,7 @@ export const InteractiveScreenViewerDynamic: React.FC 0) ? originalData : formData} // ๐Ÿ†• originalData๊ฐ€ ์žˆ์œผ๋ฉด ์‚ฌ์šฉ, ์—†์œผ๋ฉด formData ์‚ฌ์šฉ (์ƒ์„ฑ ๋ชจ๋“œ์—์„œ ๋ถ€๋ชจ ๋ฐ์ดํ„ฐ ์ „๋‹ฌ) onFormDataChange={handleFormDataChange} screenId={screenInfo?.id} tableName={screenInfo?.tableName} diff --git a/frontend/lib/registry/components/split-panel-layout2/SplitPanelLayout2Component.tsx b/frontend/lib/registry/components/split-panel-layout2/SplitPanelLayout2Component.tsx index 6e38e86e..a06c046f 100644 --- a/frontend/lib/registry/components/split-panel-layout2/SplitPanelLayout2Component.tsx +++ b/frontend/lib/registry/components/split-panel-layout2/SplitPanelLayout2Component.tsx @@ -654,7 +654,6 @@ export const SplitPanelLayout2Component: React.FC DynamicComponentRenderer์—์„œ ์ „๋‹ฌ๋œ prop const initialData = propInitialData || _initialData; + // ์„ค์ • ๋ณ‘ํ•ฉ const config: UniversalFormModalConfig = useMemo(() => { const componentConfig = component?.config || {}; @@ -155,11 +156,6 @@ export function UniversalFormModalComponent({ ...defaultConfig.saveConfig, ...propConfig?.saveConfig, ...componentConfig.saveConfig, - multiRowSave: { - ...defaultConfig.saveConfig.multiRowSave, - ...propConfig?.saveConfig?.multiRowSave, - ...componentConfig.saveConfig?.multiRowSave, - }, afterSave: { ...defaultConfig.saveConfig.afterSave, ...propConfig?.saveConfig?.afterSave, @@ -194,9 +190,6 @@ export function UniversalFormModalComponent({ [tableKey: string]: Record[]; }>({}); - // ๋กœ๋”ฉ ์ƒํƒœ - const [saving, setSaving] = useState(false); - // ์ฑ„๋ฒˆ๊ทœ์น™ ์›๋ณธ ๊ฐ’ ์ถ”์  (์ˆ˜๋™ ๋ชจ๋“œ ๊ฐ์ง€์šฉ) // key: columnName, value: ์ž๋™ ์ƒ์„ฑ๋œ ์›๋ณธ ๊ฐ’ const [numberingOriginalValues, setNumberingOriginalValues] = useState>({}); @@ -614,7 +607,8 @@ export function UniversalFormModalComponent({ } const tableConfig = section.tableConfig; - const editConfig = tableConfig.editConfig; + // editConfig๋Š” ํƒ€์ž…์— ์ •์˜๋˜์ง€ ์•Š์•˜์ง€๋งŒ ๋Ÿฐํƒ€์ž„์— ์กด์žฌํ•  ์ˆ˜ ์žˆ์Œ + const editConfig = (tableConfig as any).editConfig; const saveConfig = tableConfig.saveConfig; console.log(`[initializeForm] ํ…Œ์ด๋ธ” ์„น์…˜ ${section.id} ๊ฒ€์‚ฌ:`, { @@ -1244,378 +1238,6 @@ export function UniversalFormModalComponent({ return { valid: missingFields.length === 0, missingFields }; }, [config.sections, formData]); - // ๋‹จ์ผ ํ–‰ ์ €์žฅ - const saveSingleRow = useCallback(async () => { - const dataToSave = { ...formData }; - - // ํ…Œ์ด๋ธ” ์„น์…˜ ๋ฐ์ดํ„ฐ ์ถ”์ถœ (๋ณ„๋„ ์ €์žฅ์šฉ) - const tableSectionData: Record = {}; - - // ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ํ•„๋“œ ์ œ๊ฑฐ (์ฑ„๋ฒˆ ๊ทœ์น™ ID๋Š” ์œ ์ง€ - buttonActions.ts์—์„œ ์‚ฌ์šฉ) - Object.keys(dataToSave).forEach((key) => { - if (key.startsWith("_tableSection_")) { - // ํ…Œ์ด๋ธ” ์„น์…˜ ๋ฐ์ดํ„ฐ๋Š” ๋ณ„๋„๋กœ ์ €์žฅ - const sectionId = key.replace("_tableSection_", ""); - tableSectionData[sectionId] = dataToSave[key] || []; - delete dataToSave[key]; - } else if (key.startsWith("_") && !key.includes("_numberingRuleId")) { - delete dataToSave[key]; - } - }); - - // ์ €์žฅ ์‹œ์  ์ฑ„๋ฒˆ๊ทœ์น™ ์ฒ˜๋ฆฌ - for (const section of config.sections) { - // ํ…Œ์ด๋ธ” ํƒ€์ž… ์„น์…˜์€ ๊ฑด๋„ˆ๋›ฐ๊ธฐ - if (section.type === "table") continue; - - for (const field of section.fields || []) { - if (field.numberingRule?.enabled && field.numberingRule?.ruleId) { - const ruleIdKey = `${field.columnName}_numberingRuleId`; - const hasRuleId = dataToSave[ruleIdKey]; // ์‚ฌ์šฉ์ž๊ฐ€ ์ˆ˜์ •ํ•˜์ง€ ์•Š์•˜์œผ๋ฉด ruleId ์œ ์ง€๋จ - - // ์ฑ„๋ฒˆ ๊ทœ์น™ ํ• ๋‹น ์กฐ๊ฑด - const shouldAllocate = - // 1. generateOnSave๊ฐ€ ON์ธ ๊ฒฝ์šฐ: ํ•ญ์ƒ ์ €์žฅ ์‹œ์ ์— ํ• ๋‹น - field.numberingRule.generateOnSave || - // 2. editable์ด OFF์ธ ๊ฒฝ์šฐ: ์‚ฌ์šฉ์ž ์ž…๋ ฅ ๋ฌด์‹œํ•˜๊ณ  ์ฑ„๋ฒˆ ๊ทœ์น™์œผ๋กœ ๋ฎ์–ด์”Œ์›€ - !field.numberingRule.editable || - // 3. editable์ด ON์ด๊ณ  ์‚ฌ์šฉ์ž๊ฐ€ ์ˆ˜์ •ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ (ruleId ์œ ์ง€๋จ): ์‹ค์ œ ๋ฒˆํ˜ธ ํ• ๋‹น - (field.numberingRule.editable && hasRuleId); - - if (shouldAllocate) { - const response = await allocateNumberingCode(field.numberingRule.ruleId); - if (response.success && response.data?.generatedCode) { - dataToSave[field.columnName] = response.data.generatedCode; - let reason = "(์•Œ ์ˆ˜ ์—†์Œ)"; - if (field.numberingRule.generateOnSave) { - reason = "(generateOnSave)"; - } else if (!field.numberingRule.editable) { - reason = "(editable=OFF, ๊ฐ•์ œ ๋ฎ์–ด์”Œ์›€)"; - } else if (hasRuleId) { - reason = "(editable=ON, ์‚ฌ์šฉ์ž ๋ฏธ์ˆ˜์ •)"; - } - console.log(`[์ฑ„๋ฒˆ ํ• ๋‹น] ${field.columnName} = ${response.data.generatedCode} ${reason}`); - } else { - console.error(`[์ฑ„๋ฒˆ ์‹คํŒจ] ${field.columnName}:`, response.error); - } - } else { - console.log( - `[์ฑ„๋ฒˆ ์Šคํ‚ต] ${field.columnName}: ์‚ฌ์šฉ์ž๊ฐ€ ์ง์ ‘ ์ž…๋ ฅํ•œ ๊ฐ’ ์œ ์ง€ = ${dataToSave[field.columnName]}`, - ); - } - } - } - } - - // ๋ณ„๋„ ํ…Œ์ด๋ธ”์— ์ €์žฅํ•ด์•ผ ํ•˜๋Š” ํ…Œ์ด๋ธ” ์„น์…˜ ๋ชฉ๋ก - const tableSectionsForSeparateTable = config.sections.filter( - (s) => - s.type === "table" && - s.tableConfig?.saveConfig?.targetTable && - s.tableConfig.saveConfig.targetTable !== config.saveConfig.tableName, - ); - - // ํ…Œ์ด๋ธ” ์„น์…˜์ด ์žˆ๊ณ  ๋ฉ”์ธ ํ…Œ์ด๋ธ”์— ํ’ˆ๋ชฉ๋ณ„๋กœ ์ €์žฅํ•˜๋Š” ๊ฒฝ์šฐ (๊ณตํ†ต + ๊ฐœ๋ณ„ ๋ณ‘ํ•ฉ ์ €์žฅ) - // targetTable์ด ์—†๊ฑฐ๋‚˜ ๋ฉ”์ธ ํ…Œ์ด๋ธ”๊ณผ ๊ฐ™์€ ๊ฒฝ์šฐ - const tableSectionsForMainTable = config.sections.filter( - (s) => - s.type === "table" && - (!s.tableConfig?.saveConfig?.targetTable || - s.tableConfig.saveConfig.targetTable === config.saveConfig.tableName), - ); - - console.log("[saveSingleRow] ๋ฉ”์ธ ํ…Œ์ด๋ธ”:", config.saveConfig.tableName); - console.log( - "[saveSingleRow] ๋ฉ”์ธ ํ…Œ์ด๋ธ”์— ์ €์žฅํ•  ํ…Œ์ด๋ธ” ์„น์…˜:", - tableSectionsForMainTable.map((s) => s.id), - ); - console.log( - "[saveSingleRow] ๋ณ„๋„ ํ…Œ์ด๋ธ”์— ์ €์žฅํ•  ํ…Œ์ด๋ธ” ์„น์…˜:", - tableSectionsForSeparateTable.map((s) => s.id), - ); - console.log("[saveSingleRow] ํ…Œ์ด๋ธ” ์„น์…˜ ๋ฐ์ดํ„ฐ ํ‚ค:", Object.keys(tableSectionData)); - console.log("[saveSingleRow] dataToSave ํ‚ค:", Object.keys(dataToSave)); - - if (tableSectionsForMainTable.length > 0) { - // ๊ณตํ†ต ์ €์žฅ ํ•„๋“œ ์ˆ˜์ง‘ (sectionSaveModes ์„ค์ •์— ๋”ฐ๋ผ) - const commonFieldsData: Record = {}; - const { sectionSaveModes } = config.saveConfig; - - // ํ•„๋“œ ํƒ€์ž… ์„น์…˜์—์„œ ๊ณตํ†ต ์ €์žฅ ํ•„๋“œ ์ˆ˜์ง‘ - for (const section of config.sections) { - if (section.type === "table") continue; - - const sectionMode = sectionSaveModes?.find((s) => s.sectionId === section.id); - const defaultMode = "common"; // ํ•„๋“œ ํƒ€์ž… ์„น์…˜์˜ ๊ธฐ๋ณธ๊ฐ’์€ ๊ณตํ†ต ์ €์žฅ - const sectionSaveMode = sectionMode?.saveMode || defaultMode; - - if (section.fields) { - for (const field of section.fields) { - const fieldOverride = sectionMode?.fieldOverrides?.find((f) => f.fieldName === field.columnName); - const fieldSaveMode = fieldOverride?.saveMode || sectionSaveMode; - - if (fieldSaveMode === "common" && dataToSave[field.columnName] !== undefined) { - commonFieldsData[field.columnName] = dataToSave[field.columnName]; - } - } - } - } - - // ๊ฐ ํ…Œ์ด๋ธ” ์„น์…˜์˜ ํ’ˆ๋ชฉ ๋ฐ์ดํ„ฐ์— ๊ณตํ†ต ํ•„๋“œ ๋ณ‘ํ•ฉํ•˜์—ฌ ์ €์žฅ - for (const tableSection of tableSectionsForMainTable) { - const sectionData = tableSectionData[tableSection.id] || []; - - if (sectionData.length > 0) { - // ํ’ˆ๋ชฉ๋ณ„๋กœ ํ–‰ ์ €์žฅ - for (const item of sectionData) { - const rowToSave = { ...commonFieldsData, ...item }; - - // _sourceData ๋“ฑ ๋‚ด๋ถ€ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์ œ๊ฑฐ - Object.keys(rowToSave).forEach((key) => { - if (key.startsWith("_")) { - delete rowToSave[key]; - } - }); - - const response = await apiClient.post( - `/table-management/tables/${config.saveConfig.tableName}/add`, - rowToSave, - ); - - if (!response.data?.success) { - throw new Error(response.data?.message || "ํ’ˆ๋ชฉ ์ €์žฅ ์‹คํŒจ"); - } - } - - // ์ด๋ฏธ ์ €์žฅํ–ˆ์œผ๋ฏ€๋กœ ์•„๋ž˜ ๋กœ์ง์—์„œ ๋‹ค์‹œ ์ €์žฅํ•˜์ง€ ์•Š๋„๋ก ์ œ๊ฑฐ - delete tableSectionData[tableSection.id]; - } - } - - // ํ’ˆ๋ชฉ์ด ์—†์œผ๋ฉด ๊ณตํ†ต ๋ฐ์ดํ„ฐ๋งŒ ์ €์žฅํ•˜์ง€ ์•Š์Œ (ํ’ˆ๋ชฉ์ด ํ•„์š”ํ•œ ํ™”๋ฉด์ด๋ฏ€๋กœ) - // ๋‹ค๋ฅธ ํ…Œ์ด๋ธ” ์„น์…˜์ด ์žˆ๋Š” ๊ฒฝ์šฐ์—๋งŒ ๋ฉ”์ธ ๋ฐ์ดํ„ฐ ์ €์žฅ - const hasOtherTableSections = Object.keys(tableSectionData).length > 0; - if (!hasOtherTableSections) { - return; // ๋ฉ”์ธ ํ…Œ์ด๋ธ”์— ์ €์žฅํ•  ํ’ˆ๋ชฉ์ด ์—†์œผ๋ฉด ์ข…๋ฃŒ - } - } - - // ๋ฉ”์ธ ๋ฐ์ดํ„ฐ ์ €์žฅ (ํ…Œ์ด๋ธ” ์„น์…˜์ด ์—†๊ฑฐ๋‚˜ ๋ณ„๋„ ํ…Œ์ด๋ธ”์— ์ €์žฅํ•˜๋Š” ๊ฒฝ์šฐ) - const response = await apiClient.post(`/table-management/tables/${config.saveConfig.tableName}/add`, dataToSave); - - if (!response.data?.success) { - throw new Error(response.data?.message || "์ €์žฅ ์‹คํŒจ"); - } - - // ํ…Œ์ด๋ธ” ์„น์…˜ ๋ฐ์ดํ„ฐ ์ €์žฅ (๋ณ„๋„ ํ…Œ์ด๋ธ”์—) - for (const section of config.sections) { - if (section.type === "table" && section.tableConfig?.saveConfig?.targetTable) { - const sectionData = tableSectionData[section.id]; - if (sectionData && sectionData.length > 0) { - // ๋ฉ”์ธ ๋ ˆ์ฝ”๋“œ ID๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ (response.data์—์„œ ๊ฐ€์ ธ์˜ค๊ธฐ) - const mainRecordId = response.data?.data?.id; - - // ๊ณตํ†ต ์ €์žฅ ํ•„๋“œ ์ˆ˜์ง‘: ๋‹ค๋ฅธ ์„น์…˜(ํ•„๋“œ ํƒ€์ž…)์—์„œ ๊ณตํ†ต ์ €์žฅ์œผ๋กœ ์„ค์ •๋œ ํ•„๋“œ ๊ฐ’ - // ๊ธฐ๋ณธ๊ฐ’: ํ•„๋“œ ํƒ€์ž… ์„น์…˜์€ 'common', ํ…Œ์ด๋ธ” ํƒ€์ž… ์„น์…˜์€ 'individual' - const commonFieldsData: Record = {}; - const { sectionSaveModes } = config.saveConfig; - - // ๋‹ค๋ฅธ ์„น์…˜์—์„œ ๊ณตํ†ต ์ €์žฅ์œผ๋กœ ์„ค์ •๋œ ํ•„๋“œ ๊ฐ’ ์ˆ˜์ง‘ - for (const otherSection of config.sections) { - if (otherSection.id === section.id) continue; // ํ˜„์žฌ ํ…Œ์ด๋ธ” ์„น์…˜์€ ๊ฑด๋„ˆ๋›ฐ๊ธฐ - - const sectionMode = sectionSaveModes?.find((s) => s.sectionId === otherSection.id); - // ๊ธฐ๋ณธ๊ฐ’: ํ•„๋“œ ํƒ€์ž… ์„น์…˜์€ 'common', ํ…Œ์ด๋ธ” ํƒ€์ž… ์„น์…˜์€ 'individual' - const defaultMode = otherSection.type === "table" ? "individual" : "common"; - const sectionSaveMode = sectionMode?.saveMode || defaultMode; - - // ํ•„๋“œ ํƒ€์ž… ์„น์…˜์˜ ํ•„๋“œ๋“ค ์ฒ˜๋ฆฌ - if (otherSection.type !== "table" && otherSection.fields) { - for (const field of otherSection.fields) { - // ํ•„๋“œ๋ณ„ ์˜ค๋ฒ„๋ผ์ด๋“œ ํ™•์ธ - const fieldOverride = sectionMode?.fieldOverrides?.find((f) => f.fieldName === field.columnName); - const fieldSaveMode = fieldOverride?.saveMode || sectionSaveMode; - - // ๊ณตํ†ต ์ €์žฅ์ด๋ฉด formData์—์„œ ๊ฐ’์„ ๊ฐ€์ ธ์™€ ๋ชจ๋“  ํ’ˆ๋ชฉ์— ์ ์šฉ - if (fieldSaveMode === "common" && formData[field.columnName] !== undefined) { - commonFieldsData[field.columnName] = formData[field.columnName]; - } - } - } - - // ๐Ÿ†• ์„ ํƒ์  ํ•„๋“œ ๊ทธ๋ฃน (optionalFieldGroups)๋„ ์ฒ˜๋ฆฌ - if (otherSection.optionalFieldGroups && otherSection.optionalFieldGroups.length > 0) { - for (const optGroup of otherSection.optionalFieldGroups) { - if (optGroup.fields) { - for (const field of optGroup.fields) { - // ์„ ํƒ์  ํ•„๋“œ ๊ทธ๋ฃน์€ ๊ธฐ๋ณธ์ ์œผ๋กœ common ์ €์žฅ - if (formData[field.columnName] !== undefined) { - commonFieldsData[field.columnName] = formData[field.columnName]; - } - } - } - } - } - } - - console.log("[saveSingleRow] ๋ณ„๋„ ํ…Œ์ด๋ธ” ์ €์žฅ - ๊ณตํ†ต ํ•„๋“œ:", Object.keys(commonFieldsData)); - - for (const item of sectionData) { - // ๊ณตํ†ต ํ•„๋“œ ๋ณ‘ํ•ฉ + ๊ฐœ๋ณ„ ํ’ˆ๋ชฉ ๋ฐ์ดํ„ฐ - const itemToSave = { ...commonFieldsData, ...item }; - - // saveToTarget: false์ธ ์ปฌ๋Ÿผ์€ ์ €์žฅ์—์„œ ์ œ์™ธ - const columns = section.tableConfig?.columns || []; - for (const col of columns) { - if (col.saveConfig?.saveToTarget === false && col.field in itemToSave) { - delete itemToSave[col.field]; - } - } - - // _sourceData ๋“ฑ ๋‚ด๋ถ€ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์ œ๊ฑฐ - Object.keys(itemToSave).forEach((key) => { - if (key.startsWith("_")) { - delete itemToSave[key]; - } - }); - - // ๋ฉ”์ธ ๋ ˆ์ฝ”๋“œ์™€ ์—ฐ๊ฒฐ์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ - if (mainRecordId && config.saveConfig.primaryKeyColumn) { - itemToSave[config.saveConfig.primaryKeyColumn] = mainRecordId; - } - - const saveResponse = await apiClient.post( - `/table-management/tables/${section.tableConfig.saveConfig.targetTable}/add`, - itemToSave, - ); - - if (!saveResponse.data?.success) { - throw new Error(saveResponse.data?.message || `${section.title || "ํ…Œ์ด๋ธ” ์„น์…˜"} ์ €์žฅ ์‹คํŒจ`); - } - } - } - } - } - }, [ - config.sections, - config.saveConfig.tableName, - config.saveConfig.primaryKeyColumn, - config.saveConfig.sectionSaveModes, - formData, - ]); - - // ๋‹ค์ค‘ ํ–‰ ์ €์žฅ (๊ฒธ์ง ๋“ฑ) - const saveMultipleRows = useCallback(async () => { - const { multiRowSave } = config.saveConfig; - if (!multiRowSave) return; - - let { commonFields = [], repeatSectionId = "" } = multiRowSave; - const { typeColumn, mainTypeValue, subTypeValue, mainSectionFields = [] } = multiRowSave; - - // ๊ณตํ†ต ํ•„๋“œ๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ, ๊ธฐ๋ณธ์ •๋ณด ์„น์…˜์˜ ๋ชจ๋“  ํ•„๋“œ๋ฅผ ๊ณตํ†ต ํ•„๋“œ๋กœ ์‚ฌ์šฉ - if (commonFields.length === 0) { - const nonRepeatableSections = config.sections.filter((s) => !s.repeatable); - commonFields = nonRepeatableSections.flatMap((s) => (s.fields || []).map((f) => f.columnName)); - } - - // ๋ฐ˜๋ณต ์„น์…˜ ID๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ, ์ฒซ ๋ฒˆ์งธ ๋ฐ˜๋ณต ์„น์…˜ ์‚ฌ์šฉ - if (!repeatSectionId) { - const repeatableSection = config.sections.find((s) => s.repeatable); - if (repeatableSection) { - repeatSectionId = repeatableSection.id; - } - } - - // ๋ฐ˜๋ณต ์„น์…˜ ๋ฐ์ดํ„ฐ - const repeatItems = repeatSections[repeatSectionId] || []; - - // ์ €์žฅํ•  ํ–‰๋“ค ์ƒ์„ฑ - const rowsToSave: any[] = []; - - // ๊ณตํ†ต ๋ฐ์ดํ„ฐ (๋ชจ๋“  ํ–‰์— ์ ์šฉ) - const commonData: any = {}; - commonFields.forEach((fieldName) => { - if (formData[fieldName] !== undefined) { - commonData[fieldName] = formData[fieldName]; - } - }); - - // ๋ฉ”์ธ ์„น์…˜ ํ•„๋“œ ๋ฐ์ดํ„ฐ (๋ฉ”์ธ ํ–‰์—๋งŒ ์ ์šฉ๋˜๋Š” ๋ถ€์„œ/์ง๊ธ‰ ๋“ฑ) - const mainSectionData: any = {}; - mainSectionFields.forEach((fieldName) => { - if (formData[fieldName] !== undefined) { - mainSectionData[fieldName] = formData[fieldName]; - } - }); - - // ๋ฉ”์ธ ํ–‰ (๊ณตํ†ต ๋ฐ์ดํ„ฐ + ๋ฉ”์ธ ์„น์…˜ ํ•„๋“œ) - const mainRow: any = { ...commonData, ...mainSectionData }; - if (typeColumn) { - mainRow[typeColumn] = mainTypeValue || "main"; - } - rowsToSave.push(mainRow); - - // ๋ฐ˜๋ณต ์„น์…˜ ํ–‰๋“ค (๊ณตํ†ต ๋ฐ์ดํ„ฐ + ๋ฐ˜๋ณต ์„น์…˜ ํ•„๋“œ) - for (const item of repeatItems) { - const subRow: any = { ...commonData }; - - // ๋ฐ˜๋ณต ์„น์…˜์˜ ํ•„๋“œ ๊ฐ’ ์ถ”๊ฐ€ - const repeatSection = config.sections.find((s) => s.id === repeatSectionId); - (repeatSection?.fields || []).forEach((field) => { - if (item[field.columnName] !== undefined) { - subRow[field.columnName] = item[field.columnName]; - } - }); - - if (typeColumn) { - subRow[typeColumn] = subTypeValue || "concurrent"; - } - - rowsToSave.push(subRow); - } - - // ์ €์žฅ ์‹œ์  ์ฑ„๋ฒˆ๊ทœ์น™ ์ฒ˜๋ฆฌ (๋ฉ”์ธ ํ–‰๋งŒ) - for (const section of config.sections) { - if (section.repeatable || section.type === "table") continue; - - for (const field of section.fields || []) { - if (field.numberingRule?.enabled && field.numberingRule?.ruleId) { - // generateOnSave ๋˜๋Š” generateOnOpen ๋ชจ๋‘ ์ €์žฅ ์‹œ ์‹ค์ œ ์ˆœ๋ฒˆ ํ• ๋‹น - const shouldAllocate = field.numberingRule.generateOnSave || field.numberingRule.generateOnOpen; - if (shouldAllocate) { - const response = await allocateNumberingCode(field.numberingRule.ruleId); - if (response.success && response.data?.generatedCode) { - // ๋ชจ๋“  ํ–‰์— ๋™์ผํ•œ ์ฑ„๋ฒˆ ๊ฐ’ ์ ์šฉ (๊ณตํ†ต ํ•„๋“œ์ธ ๊ฒฝ์šฐ) - if (commonFields.includes(field.columnName)) { - rowsToSave.forEach((row) => { - row[field.columnName] = response.data?.generatedCode; - }); - } else { - rowsToSave[0][field.columnName] = response.data?.generatedCode; - } - } - } - } - } - } - - // ๋ชจ๋“  ํ–‰ ์ €์žฅ - for (let i = 0; i < rowsToSave.length; i++) { - const row = rowsToSave[i]; - - // ๋นˆ ๊ฐ์ฒด ์ฒดํฌ - if (Object.keys(row).length === 0) { - continue; - } - - const response = await apiClient.post(`/table-management/tables/${config.saveConfig.tableName}/add`, row); - - if (!response.data?.success) { - throw new Error(response.data?.message || `${i + 1}๋ฒˆ์งธ ํ–‰ ์ €์žฅ ์‹คํŒจ`); - } - } - }, [config.sections, config.saveConfig, formData, repeatSections]); - // ๋‹ค์ค‘ ํ…Œ์ด๋ธ” ์ €์žฅ (๋ฒ”์šฉ) const saveWithMultiTable = useCallback(async () => { const { customApiSave } = config.saveConfig; @@ -1798,134 +1420,6 @@ export function UniversalFormModalComponent({ } }, [config.sections, config.saveConfig, formData, repeatSections, initialData]); - // ์ปค์Šคํ…€ API ์ €์žฅ - const saveWithCustomApi = useCallback(async () => { - const { customApiSave } = config.saveConfig; - if (!customApiSave) return; - - const saveWithGenericCustomApi = async () => { - if (!customApiSave.customEndpoint) { - throw new Error("์ปค์Šคํ…€ API ์—”๋“œํฌ์ธํŠธ๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค."); - } - - const dataToSave = { ...formData }; - - // ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ํ•„๋“œ ์ œ๊ฑฐ - Object.keys(dataToSave).forEach((key) => { - if (key.startsWith("_")) { - delete dataToSave[key]; - } - }); - - // ๋ฐ˜๋ณต ์„น์…˜ ๋ฐ์ดํ„ฐ ํฌํ•จ - if (Object.keys(repeatSections).length > 0) { - dataToSave._repeatSections = repeatSections; - } - - const method = customApiSave.customMethod || "POST"; - const response = - method === "PUT" - ? await apiClient.put(customApiSave.customEndpoint, dataToSave) - : await apiClient.post(customApiSave.customEndpoint, dataToSave); - - if (!response.data?.success) { - throw new Error(response.data?.message || "์ €์žฅ ์‹คํŒจ"); - } - }; - - switch (customApiSave.apiType) { - case "multi-table": - await saveWithMultiTable(); - break; - case "custom": - await saveWithGenericCustomApi(); - break; - default: - throw new Error(`์ง€์›ํ•˜์ง€ ์•Š๋Š” API ํƒ€์ž…: ${customApiSave.apiType}`); - } - }, [config.saveConfig, formData, repeatSections, saveWithMultiTable]); - - // ์ €์žฅ ์ฒ˜๋ฆฌ - const handleSave = useCallback(async () => { - // ์ปค์Šคํ…€ API ์ €์žฅ ๋ชจ๋“œ๊ฐ€ ์•„๋‹Œ ๊ฒฝ์šฐ์—๋งŒ ํ…Œ์ด๋ธ”๋ช… ์ฒดํฌ - if (!config.saveConfig.customApiSave?.enabled && !config.saveConfig.tableName) { - toast.error("์ €์žฅํ•  ํ…Œ์ด๋ธ”์ด ์„ค์ •๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค."); - return; - } - - // ํ•„์ˆ˜ ํ•„๋“œ ๊ฒ€์ฆ - const { valid, missingFields } = validateRequiredFields(); - if (!valid) { - toast.error(`ํ•„์ˆ˜ ํ•ญ๋ชฉ์„ ์ž…๋ ฅํ•ด์ฃผ์„ธ์š”: ${missingFields.join(", ")}`); - return; - } - - setSaving(true); - - try { - const { multiRowSave, customApiSave } = config.saveConfig; - - // ์ปค์Šคํ…€ API ์ €์žฅ ๋ชจ๋“œ - if (customApiSave?.enabled) { - await saveWithCustomApi(); - } else if (multiRowSave?.enabled) { - // ๋‹ค์ค‘ ํ–‰ ์ €์žฅ - await saveMultipleRows(); - } else { - // ๋‹จ์ผ ํ–‰ ์ €์žฅ - await saveSingleRow(); - } - - // ์ €์žฅ ํ›„ ๋™์ž‘ - if (config.saveConfig.afterSave?.showToast) { - toast.success("์ €์žฅ๋˜์—ˆ์Šต๋‹ˆ๋‹ค."); - } - - if (config.saveConfig.afterSave?.refreshParent) { - window.dispatchEvent(new CustomEvent("refreshParentData")); - } - - // onSave ์ฝœ๋ฐฑ์€ ์ €์žฅ ์™„๋ฃŒ ์•Œ๋ฆผ์šฉ์œผ๋กœ๋งŒ ์‚ฌ์šฉ - // ์‹ค์ œ ์ €์žฅ์€ ์ด๋ฏธ ์œ„์—์„œ ์™„๋ฃŒ๋จ (saveSingleRow ๋˜๋Š” saveMultipleRows) - // EditModal ๋“ฑ ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ์˜ ์ €์žฅ ๋กœ์ง์ด ๋‹ค์‹œ ์‹คํ–‰๋˜์ง€ ์•Š๋„๋ก - // _saveCompleted ํ”Œ๋ž˜๊ทธ๋ฅผ ํฌํ•จํ•˜์—ฌ ์ „๋‹ฌ - if (onSave) { - onSave({ ...formData, _saveCompleted: true }); - } - - // ์ €์žฅ ์™„๋ฃŒ ํ›„ ๋ชจ๋‹ฌ ๋‹ซ๊ธฐ ์ด๋ฒคํŠธ ๋ฐœ์ƒ - if (config.saveConfig.afterSave?.closeModal !== false) { - window.dispatchEvent(new CustomEvent("closeEditModal")); - } - } catch (error: any) { - console.error("์ €์žฅ ์‹คํŒจ:", error); - // axios ์—๋Ÿฌ์˜ ๊ฒฝ์šฐ ์„œ๋ฒ„ ์‘๋‹ต ๋ฉ”์‹œ์ง€ ์ถ”์ถœ - const errorMessage = - error.response?.data?.message || - error.response?.data?.error?.details || - error.message || - "์ €์žฅ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค."; - toast.error(errorMessage); - } finally { - setSaving(false); - } - }, [ - config, - formData, - repeatSections, - onSave, - validateRequiredFields, - saveSingleRow, - saveMultipleRows, - saveWithCustomApi, - ]); - - // ํผ ์ดˆ๊ธฐํ™” - const handleReset = useCallback(() => { - initializeForm(); - toast.info("ํผ์ด ์ดˆ๊ธฐํ™”๋˜์—ˆ์Šต๋‹ˆ๋‹ค."); - }, [initializeForm]); - // ํ•„๋“œ ์š”์†Œ ๋ Œ๋”๋ง (์ž…๋ ฅ ์ปดํฌ๋„ŒํŠธ๋งŒ) // repeatContext: ๋ฐ˜๋ณต ์„น์…˜์ธ ๊ฒฝ์šฐ { sectionId, itemId }๋ฅผ ์ „๋‹ฌ const renderFieldElement = ( @@ -2664,38 +2158,6 @@ export function UniversalFormModalComponent({ {/* ์„น์…˜๋“ค */}
{config.sections.map((section) => renderSection(section))}
- {/* ๋ฒ„ํŠผ ์˜์—ญ - ์ €์žฅ ๋ฒ„ํŠผ์ด ํ‘œ์‹œ๋  ๋•Œ๋งŒ ๋ Œ๋”๋ง */} - {config.modal.showSaveButton !== false && ( -
- {config.modal.showResetButton && ( - - )} - -
- )} - {/* ์‚ญ์ œ ํ™•์ธ ๋‹ค์ด์–ผ๋กœ๊ทธ */} ๋ชจ๋‹ฌ ์ฐฝ์˜ ํฌ๊ธฐ๋ฅผ ์„ ํƒํ•˜์„ธ์š” - - {/* ์ €์žฅ ๋ฒ„ํŠผ ํ‘œ์‹œ ์„ค์ • */} -
-
- updateModalConfig({ showSaveButton: checked === true })} - /> - -
- ์ฒดํฌ ํ•ด์ œ ์‹œ ๋ชจ๋‹ฌ ํ•˜๋‹จ์˜ ์ €์žฅ ๋ฒ„ํŠผ์ด ์ˆจ๊ฒจ์ง‘๋‹ˆ๋‹ค -
- -
-
- - updateModalConfig({ saveButtonText: e.target.value })} - className="h-9 w-full max-w-full text-sm" - /> -
-
- - updateModalConfig({ cancelButtonText: e.target.value })} - className="h-9 w-full max-w-full text-sm" - /> -
-
@@ -885,7 +851,6 @@ export function UniversalFormModalConfigPanel({ tableColumns={tableColumns} numberingRules={numberingRules} onLoadTableColumns={loadTableColumns} - availableParentFields={availableParentFields} targetTableName={config.saveConfig?.tableName} targetTableColumns={config.saveConfig?.tableName ? tableColumns[config.saveConfig.tableName] || [] : []} /> diff --git a/frontend/lib/registry/components/universal-form-modal/config.ts b/frontend/lib/registry/components/universal-form-modal/config.ts index 41c18043..08baf766 100644 --- a/frontend/lib/registry/components/universal-form-modal/config.ts +++ b/frontend/lib/registry/components/universal-form-modal/config.ts @@ -23,11 +23,6 @@ export const defaultConfig: UniversalFormModalConfig = { size: "lg", closeOnOutsideClick: false, showCloseButton: true, - showSaveButton: true, - saveButtonText: "์ €์žฅ", - cancelButtonText: "์ทจ์†Œ", - showResetButton: false, - resetButtonText: "์ดˆ๊ธฐํ™”", }, sections: [ { @@ -45,15 +40,6 @@ export const defaultConfig: UniversalFormModalConfig = { saveConfig: { tableName: "", primaryKeyColumn: "id", - multiRowSave: { - enabled: false, - commonFields: [], - repeatSectionId: "", - typeColumn: "", - mainTypeValue: "main", - subTypeValue: "concurrent", - mainSectionFields: [], - }, afterSave: { closeModal: true, refreshParent: true, diff --git a/frontend/lib/registry/components/universal-form-modal/index.ts b/frontend/lib/registry/components/universal-form-modal/index.ts index f98bf438..40af1dfc 100644 --- a/frontend/lib/registry/components/universal-form-modal/index.ts +++ b/frontend/lib/registry/components/universal-form-modal/index.ts @@ -9,14 +9,14 @@ import { defaultConfig } from "./config"; /** * ๋ฒ”์šฉ ํผ ๋ชจ๋‹ฌ ์ปดํฌ๋„ŒํŠธ ์ •์˜ * - * ์„น์…˜ ๊ธฐ๋ฐ˜ ํผ ๋ ˆ์ด์•„์›ƒ, ์ฑ„๋ฒˆ๊ทœ์น™, ๋‹ค์ค‘ ํ–‰ ์ €์žฅ์„ ์ง€์›ํ•˜๋Š” + * ์„น์…˜ ๊ธฐ๋ฐ˜ ํผ ๋ ˆ์ด์•„์›ƒ, ์ฑ„๋ฒˆ๊ทœ์น™์„ ์ง€์›ํ•˜๋Š” * ๋ฒ”์šฉ ๋ชจ๋‹ฌ ์ปดํฌ๋„ŒํŠธ์ž…๋‹ˆ๋‹ค. */ export const UniversalFormModalDefinition = createComponentDefinition({ id: "universal-form-modal", name: "๋ฒ”์šฉ ํผ ๋ชจ๋‹ฌ", nameEng: "Universal Form Modal", - description: "์„น์…˜ ๊ธฐ๋ฐ˜ ํผ ๋ ˆ์ด์•„์›ƒ, ์ฑ„๋ฒˆ๊ทœ์น™, ๋‹ค์ค‘ ํ–‰ ์ €์žฅ์„ ์ง€์›ํ•˜๋Š” ๋ฒ”์šฉ ๋ชจ๋‹ฌ ์ปดํฌ๋„ŒํŠธ", + description: "์„น์…˜ ๊ธฐ๋ฐ˜ ํผ ๋ ˆ์ด์•„์›ƒ, ์ฑ„๋ฒˆ๊ทœ์น™์„ ์ง€์›ํ•˜๋Š” ๋ฒ”์šฉ ๋ชจ๋‹ฌ ์ปดํฌ๋„ŒํŠธ", category: ComponentCategory.INPUT, webType: "form", component: UniversalFormModalComponent, @@ -28,7 +28,7 @@ export const UniversalFormModalDefinition = createComponentDefinition({ }, configPanel: UniversalFormModalConfigPanel, icon: "FormInput", - tags: ["ํผ", "๋ชจ๋‹ฌ", "์ž…๋ ฅ", "์ €์žฅ", "์ฑ„๋ฒˆ", "๊ฒธ์ง", "๋‹ค์ค‘ํ–‰"], + tags: ["ํผ", "๋ชจ๋‹ฌ", "์ž…๋ ฅ", "์ €์žฅ", "์ฑ„๋ฒˆ"], version: "1.0.0", author: "๊ฐœ๋ฐœํŒ€", documentation: ` @@ -36,22 +36,22 @@ export const UniversalFormModalDefinition = createComponentDefinition({ ### ์ฃผ์š” ๊ธฐ๋Šฅ - **์„น์…˜ ๊ธฐ๋ฐ˜ ๋ ˆ์ด์•„์›ƒ**: ๊ธฐ๋ณธ ์ •๋ณด, ์ถ”๊ฐ€ ์ •๋ณด ๋“ฑ ์„น์…˜๋ณ„๋กœ ํผ ๊ตฌ์„ฑ -- **๋ฐ˜๋ณต ์„น์…˜**: ๊ฒธ์ง์ฒ˜๋Ÿผ ๋™์ผํ•œ ํ•„๋“œ ๊ทธ๋ฃน์„ ์—ฌ๋Ÿฌ ๊ฐœ ์ถ”๊ฐ€ ๊ฐ€๋Šฅ +- **๋ฐ˜๋ณต ์„น์…˜**: ๋™์ผํ•œ ํ•„๋“œ ๊ทธ๋ฃน์„ ์—ฌ๋Ÿฌ ๊ฐœ ์ถ”๊ฐ€ ๊ฐ€๋Šฅ - **์ฑ„๋ฒˆ๊ทœ์น™ ์—ฐ๋™**: ์ž๋™ ์ฝ”๋“œ ์ƒ์„ฑ (๋ชจ๋‹ฌ ์—ด๋ฆด ๋•Œ ๋˜๋Š” ์ €์žฅ ์‹œ์ ) -- **๋‹ค์ค‘ ํ–‰ ์ €์žฅ**: ๊ณตํ†ต ํ•„๋“œ + ๊ฐœ๋ณ„ ํ•„๋“œ ์กฐํ•ฉ์œผ๋กœ ์—ฌ๋Ÿฌ ํ–‰ ๋™์‹œ ์ €์žฅ +- **๋‹จ์ผ/๋‹ค์ค‘ ํ…Œ์ด๋ธ” ์ €์žฅ**: ๋‹จ์ผ ํ…Œ์ด๋ธ” ๋˜๋Š” ๋ฉ”์ธ+์„œ๋ธŒ ํ…Œ์ด๋ธ”์— ์ €์žฅ - **์™ธ๋ถ€ ๋ฐ์ดํ„ฐ ์ˆ˜์‹ **: ๋ถ€๋ชจ ํ™”๋ฉด์—์„œ ์ „๋‹ฌ๋ฐ›์€ ๊ฐ’ ์ž๋™ ์ฑ„์›€ ### ์‚ฌ์šฉ ์˜ˆ์‹œ -1. ๋ถ€์„œ๊ด€๋ฆฌ ์‚ฌ์› ์ถ”๊ฐ€ + ๊ฒธ์ง ๋“ฑ๋ก -2. ํ’ˆ๋ชฉ ๋“ฑ๋ก + ๊ทœ๊ฒฉ ์˜ต์…˜ ์ถ”๊ฐ€ -3. ๊ฑฐ๋ž˜์ฒ˜ ๋“ฑ๋ก + ๋‹ด๋‹น์ž ์ •๋ณด ์ถ”๊ฐ€ +1. ์‚ฌ์› ๋“ฑ๋ก, ๋ถ€์„œ ๋“ฑ๋ก, ๊ฑฐ๋ž˜์ฒ˜ ๋“ฑ๋ก (๋‹จ์ผ ํ…Œ์ด๋ธ”) +2. ์ฃผ๋ฌธ ๋“ฑ๋ก + ์ฃผ๋ฌธ ์ƒ์„ธ (๋‹ค์ค‘ ํ…Œ์ด๋ธ”) +3. ํ’ˆ๋ชฉ ๋“ฑ๋ก + ๊ทœ๊ฒฉ ์˜ต์…˜ ์ถ”๊ฐ€ ### ์„ค์ • ๋ฐฉ๋ฒ• 1. ์ €์žฅ ํ…Œ์ด๋ธ” ์„ ํƒ -2. ์„น์…˜ ์ถ”๊ฐ€ (๊ธฐ๋ณธ ์ •๋ณด, ๊ฒธ์ง ์ •๋ณด ๋“ฑ) +2. ์„น์…˜ ์ถ”๊ฐ€ (๊ธฐ๋ณธ ์ •๋ณด ๋“ฑ) 3. ๊ฐ ์„น์…˜์— ํ•„๋“œ ์ถ”๊ฐ€ 4. ๋ฐ˜๋ณต ์„น์…˜ ์„ค์ • (ํ•„์š” ์‹œ) -5. ๋‹ค์ค‘ ํ–‰ ์ €์žฅ ์„ค์ • (ํ•„์š” ์‹œ) +5. ๋‹ค์ค‘ ํ…Œ์ด๋ธ” ์ €์žฅ ์„ค์ • (ํ•„์š” ์‹œ) 6. ์ฑ„๋ฒˆ๊ทœ์น™ ์—ฐ๋™ (ํ•„์š” ์‹œ) `, }); @@ -69,7 +69,6 @@ export type { FormSectionConfig, FormFieldConfig, SaveConfig, - MultiRowSaveConfig, NumberingRuleConfig, SelectOptionConfig, FormDataState, diff --git a/frontend/lib/registry/components/universal-form-modal/modals/FieldDetailSettingsModal.tsx b/frontend/lib/registry/components/universal-form-modal/modals/FieldDetailSettingsModal.tsx index 8882d9bc..453429e7 100644 --- a/frontend/lib/registry/components/universal-form-modal/modals/FieldDetailSettingsModal.tsx +++ b/frontend/lib/registry/components/universal-form-modal/modals/FieldDetailSettingsModal.tsx @@ -65,8 +65,6 @@ interface FieldDetailSettingsModalProps { tableColumns: { [tableName: string]: { name: string; type: string; label: string }[] }; numberingRules: { id: string; name: string }[]; onLoadTableColumns: (tableName: string) => void; - // ๋ถ€๋ชจ ํ™”๋ฉด์—์„œ ์ „๋‹ฌ ๊ฐ€๋Šฅํ•œ ํ•„๋“œ ๋ชฉ๋ก (์„ ํƒ์‚ฌํ•ญ) - availableParentFields?: AvailableParentField[]; // ์ €์žฅ ํ…Œ์ด๋ธ” ์ •๋ณด (ํƒ€๊ฒŸ ์ปฌ๋Ÿผ ์„ ํƒ์šฉ) targetTableName?: string; targetTableColumns?: { name: string; type: string; label: string }[]; @@ -81,7 +79,6 @@ export function FieldDetailSettingsModal({ tableColumns, numberingRules, onLoadTableColumns, - availableParentFields = [], // targetTableName์€ ํƒ€๊ฒŸ ์ปฌ๋Ÿผ ์„ ํƒ ์‹œ ์ฐธ๊ณ ์šฉ์œผ๋กœ ์ „๋‹ฌ๋จ (ํ˜„์žฌ targetTableColumns๋งŒ ์‚ฌ์šฉ) targetTableName: _targetTableName, targetTableColumns = [], @@ -330,60 +327,6 @@ export function FieldDetailSettingsModal({ /> ํ™”๋ฉด์— ํ‘œ์‹œํ•˜์ง€ ์•Š์ง€๋งŒ ๊ฐ’์€ ์ €์žฅ๋ฉ๋‹ˆ๋‹ค - - - -
- ๋ถ€๋ชจ์—์„œ ๊ฐ’ ๋ฐ›๊ธฐ - updateField({ receiveFromParent: checked })} - /> -
- ๋ถ€๋ชจ ํ™”๋ฉด์—์„œ ์ „๋‹ฌ๋ฐ›์€ ๊ฐ’์œผ๋กœ ์ž๋™ ์ฑ„์›Œ์ง‘๋‹ˆ๋‹ค - - {/* ๋ถ€๋ชจ์—์„œ ๊ฐ’ ๋ฐ›๊ธฐ ํ™œ์„ฑํ™” ์‹œ ํ•„๋“œ ์„ ํƒ */} - {localField.receiveFromParent && ( -
- - {availableParentFields.length > 0 ? ( - - ) : ( -
- updateField({ parentFieldName: e.target.value })} - placeholder={`์˜ˆ: ${localField.columnName || "parent_field_name"}`} - className="h-8 text-xs" - /> -

- ๋ถ€๋ชจ ํ™”๋ฉด์—์„œ ์ „๋‹ฌ๋ฐ›์„ ํ•„๋“œ๋ช…์„ ์ž…๋ ฅํ•˜์„ธ์š”. ๋น„์›Œ๋‘๋ฉด "{localField.columnName}"์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. -

-
- )} -
- )} {/* Accordion์œผ๋กœ ๊ณ ๊ธ‰ ์„ค์ • */} diff --git a/frontend/lib/registry/components/universal-form-modal/modals/SaveSettingsModal.tsx b/frontend/lib/registry/components/universal-form-modal/modals/SaveSettingsModal.tsx index 11b3a8ae..01c87fcb 100644 --- a/frontend/lib/registry/components/universal-form-modal/modals/SaveSettingsModal.tsx +++ b/frontend/lib/registry/components/universal-form-modal/modals/SaveSettingsModal.tsx @@ -378,7 +378,11 @@ export function SaveSettingsModal({ ๋‹จ์ผ ํ…Œ์ด๋ธ” ์ €์žฅ - ๋ชจ๋“  ํ•„๋“œ๋ฅผ ํ•˜๋‚˜์˜ ํ…Œ์ด๋ธ”์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค (๊ธฐ๋ณธ ๋ฐฉ์‹) + + ํผ ๋ฐ์ดํ„ฐ๋ฅผ ํ•˜๋‚˜์˜ ํ…Œ์ด๋ธ”์— 1๊ฐœ ํ–‰์œผ๋กœ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. +
+ ์˜ˆ: ์‚ฌ์› ๋“ฑ๋ก, ๋ถ€์„œ ๋“ฑ๋ก, ๊ฑฐ๋ž˜์ฒ˜ ๋“ฑ๋ก ๋“ฑ ๋‹จ์ˆœ ๋“ฑ๋ก ํ™”๋ฉด +
@@ -387,9 +391,13 @@ export function SaveSettingsModal({
- ๋ฉ”์ธ ํ…Œ์ด๋ธ” + ์„œ๋ธŒ ํ…Œ์ด๋ธ”์— ํŠธ๋žœ์žญ์…˜์œผ๋กœ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค + ํ•˜๋‚˜์˜ ํผ์œผ๋กœ ์—ฌ๋Ÿฌ ํ…Œ์ด๋ธ”์— ๋™์‹œ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. (ํŠธ๋žœ์žญ์…˜์œผ๋กœ ๋ฌถ์ž„)
- ์˜ˆ: ์ฃผ๋ฌธ(orders) + ์ฃผ๋ฌธ์ƒ์„ธ(order_items), ์‚ฌ์›(user_info) + ๋ถ€์„œ(user_dept) + ๋ฉ”์ธ ํ…Œ์ด๋ธ”: ํผ์˜ ๋ชจ๋“  ํ•„๋“œ ์ค‘ ํ•ด๋‹น ํ…Œ์ด๋ธ” ์ปฌ๋Ÿผ๊ณผ ์ผ์น˜ํ•˜๋Š” ๊ฒƒ ์ž๋™ ์ €์žฅ +
+ ์„œ๋ธŒ ํ…Œ์ด๋ธ”: ํ•„๋“œ ๋งคํ•‘์—์„œ ์ง€์ •ํ•œ ํ•„๋“œ๋งŒ ์ €์žฅ (๋ฉ”์ธ ํ…Œ์ด๋ธ”์˜ ํ‚ค ๊ฐ’์ด ์ž๋™ ์—ฐ๊ฒฐ๋จ) +
+ ์˜ˆ: ์‚ฌ์›+๋ถ€์„œ๋ฐฐ์ •(user_info+user_dept), ์ฃผ๋ฌธ+์ฃผ๋ฌธ์ƒ์„ธ(orders+order_items)
@@ -691,9 +699,11 @@ export function SaveSettingsModal({ - ๋ฐ˜๋ณต ์„น์…˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ„๋„ ํ…Œ์ด๋ธ”์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. + ํผ์—์„œ ์ž…๋ ฅํ•œ ํ•„๋“œ๋ฅผ ์„œ๋ธŒ ํ…Œ์ด๋ธ”์— ๋‚˜๋ˆ ์„œ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.
- ์˜ˆ: ์ฃผ๋ฌธ์ƒ์„ธ(order_items), ๊ฒธ์ง๋ถ€์„œ(user_dept) + ๋ฉ”์ธ ํ…Œ์ด๋ธ”์˜ ํ‚ค ๊ฐ’(์˜ˆ: user_id)์ด ์„œ๋ธŒ ํ…Œ์ด๋ธ”์— ์ž๋™์œผ๋กœ ์—ฐ๊ฒฐ๋ฉ๋‹ˆ๋‹ค. +
+ ํ•„๋“œ ๋งคํ•‘์—์„œ ์ง€์ •ํ•œ ํ•„๋“œ๋งŒ ์„œ๋ธŒ ํ…Œ์ด๋ธ”์— ์ €์žฅ๋ฉ๋‹ˆ๋‹ค.
{(localSaveConfig.customApiSave?.multiTable?.subTables || []).length === 0 ? ( @@ -802,13 +812,13 @@ export function SaveSettingsModal({
- + - ์ด ์„œ๋ธŒ ํ…Œ์ด๋ธ”์— ์ €์žฅํ•  ๋ฐ˜๋ณต ์„น์…˜์„ ์„ ํƒํ•˜์„ธ์š” + + ๋ฐ˜๋ณต ์„น์…˜: ํผ ์•ˆ์—์„œ ๋™์ ์œผ๋กœ ํ•ญ๋ชฉ์„ ์ถ”๊ฐ€/์‚ญ์ œํ•  ์ˆ˜ ์žˆ๋Š” ์„น์…˜ (์˜ˆ: ์ฃผ๋ฌธ ํ’ˆ๋ชฉ ๋ชฉ๋ก) +
+ ๋ฐ˜๋ณต ์„น์…˜์ด ์žˆ์œผ๋ฉด ํ•ด๋‹น ์„น์…˜์˜ ๊ฐ ํ•ญ๋ชฉ์ด ์„œ๋ธŒ ํ…Œ์ด๋ธ”์— ์—ฌ๋Ÿฌ ํ–‰์œผ๋กœ ์ €์žฅ๋ฉ๋‹ˆ๋‹ค. +
+ ๋ฐ˜๋ณต ์„น์…˜ ์—†์ด ํ•„๋“œ ๋งคํ•‘๋งŒ ์‚ฌ์šฉํ•˜๋ฉด 1๊ฐœ ํ–‰๋งŒ ์ €์žฅ๋ฉ๋‹ˆ๋‹ค. +
diff --git a/frontend/lib/registry/components/universal-form-modal/types.ts b/frontend/lib/registry/components/universal-form-modal/types.ts index 303705b6..25d04ea8 100644 --- a/frontend/lib/registry/components/universal-form-modal/types.ts +++ b/frontend/lib/registry/components/universal-form-modal/types.ts @@ -648,19 +648,6 @@ export interface TableCalculationRule { conditionalCalculation?: ConditionalCalculationConfig; } -// ๋‹ค์ค‘ ํ–‰ ์ €์žฅ ์„ค์ • -export interface MultiRowSaveConfig { - enabled?: boolean; // ์‚ฌ์šฉ ์—ฌ๋ถ€ (๊ธฐ๋ณธ: false) - commonFields?: string[]; // ๋ชจ๋“  ํ–‰์— ๊ณตํ†ต ์ €์žฅํ•  ํ•„๋“œ (columnName ๊ธฐ์ค€) - repeatSectionId?: string; // ๋ฐ˜๋ณต ์„น์…˜ ID - typeColumn?: string; // ๊ตฌ๋ถ„ ์ปฌ๋Ÿผ๋ช… (์˜ˆ: "employment_type") - mainTypeValue?: string; // ๋ฉ”์ธ ํ–‰ ๊ฐ’ (์˜ˆ: "main") - subTypeValue?: string; // ์„œ๋ธŒ ํ–‰ ๊ฐ’ (์˜ˆ: "concurrent") - - // ๋ฉ”์ธ ์„น์…˜ ํ•„๋“œ (๋ฐ˜๋ณต ์„น์…˜์ด ์•„๋‹Œ ๊ณณ์˜ ๋ถ€์„œ/์ง๊ธ‰ ๋“ฑ) - mainSectionFields?: string[]; // ๋ฉ”์ธ ํ–‰์—๋งŒ ์ €์žฅํ•  ํ•„๋“œ -} - /** * ์„น์…˜๋ณ„ ์ €์žฅ ๋ฐฉ์‹ ์„ค์ • * ๊ณตํ†ต ์ €์žฅ: ํ•ด๋‹น ์„น์…˜์˜ ํ•„๋“œ ๊ฐ’์ด ๋ชจ๋“  ํ’ˆ๋ชฉ ํ–‰์— ๋™์ผํ•˜๊ฒŒ ์ €์žฅ๋ฉ๋‹ˆ๋‹ค (์˜ˆ: ์ˆ˜์ฃผ๋ฒˆํ˜ธ, ๊ฑฐ๋ž˜์ฒ˜) @@ -681,9 +668,6 @@ export interface SaveConfig { tableName: string; primaryKeyColumn?: string; // PK ์ปฌ๋Ÿผ (์ˆ˜์ • ์‹œ ์‚ฌ์šฉ) - // ๋‹ค์ค‘ ํ–‰ ์ €์žฅ ์„ค์ • - multiRowSave?: MultiRowSaveConfig; - // ์ปค์Šคํ…€ API ์ €์žฅ ์„ค์ • (ํ…Œ์ด๋ธ” ์ง์ ‘ ์ €์žฅ ๋Œ€์‹  ์ „์šฉ API ์‚ฌ์šฉ) customApiSave?: CustomApiSaveConfig; @@ -802,13 +786,6 @@ export interface ModalConfig { size: "sm" | "md" | "lg" | "xl" | "full"; closeOnOutsideClick?: boolean; showCloseButton?: boolean; - - // ๋ฒ„ํŠผ ์„ค์ • - showSaveButton?: boolean; // ์ €์žฅ ๋ฒ„ํŠผ ํ‘œ์‹œ (๊ธฐ๋ณธ: true) - saveButtonText?: string; // ์ €์žฅ ๋ฒ„ํŠผ ํ…์ŠคํŠธ (๊ธฐ๋ณธ: "์ €์žฅ") - cancelButtonText?: string; // ์ทจ์†Œ ๋ฒ„ํŠผ ํ…์ŠคํŠธ (๊ธฐ๋ณธ: "์ทจ์†Œ") - showResetButton?: boolean; // ์ดˆ๊ธฐํ™” ๋ฒ„ํŠผ ํ‘œ์‹œ - resetButtonText?: string; // ์ดˆ๊ธฐํ™” ๋ฒ„ํŠผ ํ…์ŠคํŠธ } // ์ „์ฒด ์„ค์ •