feat: 중첩 구조 지원을 위한 컴포넌트 선택 및 기본값 적용 기능 추가

- ScreenManagementService에서 company_code 저장 로직을 개선하여 SUPER_ADMIN의 경우 화면 정의에 따라 company_code를 저장하도록 수정하였습니다.
- ScreenDesigner에서 중첩 구조를 지원하는 탭 내부 컴포넌트 선택 상태 및 핸들러를 추가하였습니다.
- SplitPanelLayoutComponent에서 분할 패널 내부 컴포넌트의 기본값을 재귀적으로 적용하는 헬퍼 함수를 구현하였습니다.
- TimelineSchedulerConfigPanel에서 필드 매핑 업데이트 로직을 개선하여 이전 형식과 새 형식을 모두 지원하도록 하였습니다.
- useTimelineData 훅에서 필드 매핑을 JSON 문자열로 안정화하여 객체 참조 변경 방지를 위한 메모이제이션을 적용하였습니다.
This commit is contained in:
kjs
2026-02-02 17:11:00 +09:00
parent 4e7aa0c3b9
commit 7043f26ac8
9 changed files with 1079 additions and 231 deletions

View File

@@ -56,6 +56,13 @@ export function TimelineSchedulerConfigPanel({
config,
onChange,
}: TimelineSchedulerConfigPanelProps) {
// 🐛 디버깅: 받은 config 출력
console.log("🐛 [TimelineSchedulerConfigPanel] config:", {
selectedTable: config.selectedTable,
fieldMapping: config.fieldMapping,
fieldMappingKeys: config.fieldMapping ? Object.keys(config.fieldMapping) : [],
});
const [tables, setTables] = useState<TableInfo[]>([]);
const [tableColumns, setTableColumns] = useState<ColumnInfo[]>([]);
const [resourceColumns, setResourceColumns] = useState<ColumnInfo[]>([]);
@@ -141,13 +148,40 @@ export function TimelineSchedulerConfigPanel({
onChange({ ...config, ...updates });
};
// 필드 매핑 업데이트
// 🆕 이전 형식(idField)과 새 형식(id) 모두 지원하는 헬퍼 함수
const getFieldMappingValue = (newKey: string, oldKey: string): string => {
const mapping = config.fieldMapping as Record<string, any> | undefined;
if (!mapping) return "";
return mapping[newKey] || mapping[oldKey] || "";
};
// 필드 매핑 업데이트 (새 형식으로 저장하고, 이전 형식 키 삭제)
const updateFieldMapping = (field: string, value: string) => {
const currentMapping = { ...config.fieldMapping } as Record<string, any>;
// 이전 형식 키 매핑
const oldKeyMap: Record<string, string> = {
id: "idField",
resourceId: "resourceIdField",
title: "titleField",
startDate: "startDateField",
endDate: "endDateField",
status: "statusField",
progress: "progressField",
color: "colorField",
};
// 새 형식으로 저장
currentMapping[field] = value;
// 이전 형식 키가 있으면 삭제
const oldKey = oldKeyMap[field];
if (oldKey && currentMapping[oldKey]) {
delete currentMapping[oldKey];
}
updateConfig({
fieldMapping: {
...config.fieldMapping,
[field]: value,
},
fieldMapping: currentMapping,
});
};
@@ -345,7 +379,7 @@ export function TimelineSchedulerConfigPanel({
<div className="space-y-1">
<Label className="text-[10px]">ID</Label>
<Select
value={config.fieldMapping?.id || ""}
value={getFieldMappingValue("id", "idField")}
onValueChange={(v) => updateFieldMapping("id", v)}
>
<SelectTrigger className="h-7 text-xs">
@@ -365,7 +399,7 @@ export function TimelineSchedulerConfigPanel({
<div className="space-y-1">
<Label className="text-[10px]"> ID</Label>
<Select
value={config.fieldMapping?.resourceId || ""}
value={getFieldMappingValue("resourceId", "resourceIdField")}
onValueChange={(v) => updateFieldMapping("resourceId", v)}
>
<SelectTrigger className="h-7 text-xs">
@@ -385,7 +419,7 @@ export function TimelineSchedulerConfigPanel({
<div className="space-y-1">
<Label className="text-[10px]"></Label>
<Select
value={config.fieldMapping?.title || ""}
value={getFieldMappingValue("title", "titleField")}
onValueChange={(v) => updateFieldMapping("title", v)}
>
<SelectTrigger className="h-7 text-xs">
@@ -405,7 +439,7 @@ export function TimelineSchedulerConfigPanel({
<div className="space-y-1">
<Label className="text-[10px]"></Label>
<Select
value={config.fieldMapping?.startDate || ""}
value={getFieldMappingValue("startDate", "startDateField")}
onValueChange={(v) => updateFieldMapping("startDate", v)}
>
<SelectTrigger className="h-7 text-xs">
@@ -425,7 +459,7 @@ export function TimelineSchedulerConfigPanel({
<div className="space-y-1">
<Label className="text-[10px]"></Label>
<Select
value={config.fieldMapping?.endDate || ""}
value={getFieldMappingValue("endDate", "endDateField")}
onValueChange={(v) => updateFieldMapping("endDate", v)}
>
<SelectTrigger className="h-7 text-xs">
@@ -445,7 +479,7 @@ export function TimelineSchedulerConfigPanel({
<div className="space-y-1">
<Label className="text-[10px]"> ()</Label>
<Select
value={config.fieldMapping?.status || "__none__"}
value={getFieldMappingValue("status", "statusField") || "__none__"}
onValueChange={(v) => updateFieldMapping("status", v === "__none__" ? "" : v)}
>
<SelectTrigger className="h-7 text-xs">