feat: 중첩 구조 지원을 위한 컴포넌트 선택 및 기본값 적용 기능 추가
- ScreenManagementService에서 company_code 저장 로직을 개선하여 SUPER_ADMIN의 경우 화면 정의에 따라 company_code를 저장하도록 수정하였습니다. - ScreenDesigner에서 중첩 구조를 지원하는 탭 내부 컴포넌트 선택 상태 및 핸들러를 추가하였습니다. - SplitPanelLayoutComponent에서 분할 패널 내부 컴포넌트의 기본값을 재귀적으로 적용하는 헬퍼 함수를 구현하였습니다. - TimelineSchedulerConfigPanel에서 필드 매핑 업데이트 로직을 개선하여 이전 형식과 새 형식을 모두 지원하도록 하였습니다. - useTimelineData 훅에서 필드 매핑을 JSON 문자열로 안정화하여 객체 참조 변경 방지를 위한 메모이제이션을 적용하였습니다.
This commit is contained in:
@@ -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">
|
||||
|
||||
Reference in New Issue
Block a user