feat: 중첩 구조 지원을 위한 컴포넌트 선택 및 기본값 적용 기능 추가
- ScreenManagementService에서 company_code 저장 로직을 개선하여 SUPER_ADMIN의 경우 화면 정의에 따라 company_code를 저장하도록 수정하였습니다. - ScreenDesigner에서 중첩 구조를 지원하는 탭 내부 컴포넌트 선택 상태 및 핸들러를 추가하였습니다. - SplitPanelLayoutComponent에서 분할 패널 내부 컴포넌트의 기본값을 재귀적으로 적용하는 헬퍼 함수를 구현하였습니다. - TimelineSchedulerConfigPanel에서 필드 매핑 업데이트 로직을 개선하여 이전 형식과 새 형식을 모두 지원하도록 하였습니다. - useTimelineData 훅에서 필드 매핑을 JSON 문자열로 안정화하여 객체 참조 변경 방지를 위한 메모이제이션을 적용하였습니다.
This commit is contained in:
@@ -67,6 +67,20 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||
...props
|
||||
}) => {
|
||||
const componentConfig = (component.componentConfig || {}) as SplitPanelLayoutConfig;
|
||||
|
||||
// 🐛 디버깅: 로드 시 rightPanel.components 확인
|
||||
const rightComps = componentConfig.rightPanel?.components || [];
|
||||
const finishedTimeline = rightComps.find((c: any) => c.id === "finished_timeline");
|
||||
if (finishedTimeline) {
|
||||
const fm = finishedTimeline.componentConfig?.fieldMapping;
|
||||
console.log("🔍 [SplitPanelLayout] finished_timeline fieldMapping:", {
|
||||
componentId: finishedTimeline.id,
|
||||
fieldMapping: fm ? JSON.stringify(fm) : "undefined",
|
||||
fieldMappingKeys: fm ? Object.keys(fm) : [],
|
||||
fieldMappingId: fm?.id,
|
||||
fullComponentConfig: JSON.stringify(finishedTimeline.componentConfig || {}, null, 2),
|
||||
});
|
||||
}
|
||||
// 🆕 프리뷰용 회사 코드 오버라이드 (최고 관리자만 사용 가능)
|
||||
const companyCode = (props as any).companyCode as string | undefined;
|
||||
|
||||
@@ -231,6 +245,33 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||
[component, componentConfig, onUpdateComponent]
|
||||
);
|
||||
|
||||
// 🆕 중첩된 컴포넌트 업데이트 핸들러 (탭 컴포넌트 내부 위치 변경 등)
|
||||
const handleNestedComponentUpdate = useCallback(
|
||||
(panelSide: "left" | "right", compId: string, updatedNestedComponent: any) => {
|
||||
if (!onUpdateComponent) return;
|
||||
|
||||
const panelKey = panelSide === "left" ? "leftPanel" : "rightPanel";
|
||||
const panelConfig = componentConfig[panelKey] || {};
|
||||
const panelComponents = panelConfig.components || [];
|
||||
|
||||
const updatedComponents = panelComponents.map((c: PanelInlineComponent) =>
|
||||
c.id === compId ? { ...c, ...updatedNestedComponent, id: c.id } : c
|
||||
);
|
||||
|
||||
onUpdateComponent({
|
||||
...component,
|
||||
componentConfig: {
|
||||
...componentConfig,
|
||||
[panelKey]: {
|
||||
...panelConfig,
|
||||
components: updatedComponents,
|
||||
},
|
||||
},
|
||||
});
|
||||
},
|
||||
[component, componentConfig, onUpdateComponent]
|
||||
);
|
||||
|
||||
// 🆕 커스텀 모드: 드래그 시작 핸들러
|
||||
const handlePanelDragStart = useCallback(
|
||||
(e: React.MouseEvent, panelSide: "left" | "right", comp: PanelInlineComponent) => {
|
||||
@@ -2293,6 +2334,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||
)}
|
||||
<CardContent className="flex-1 overflow-auto p-4">
|
||||
{/* 좌측 데이터 목록/테이블/커스텀 */}
|
||||
{console.log("🔍 [SplitPanel] 왼쪽 패널 displayMode:", componentConfig.leftPanel?.displayMode, "isDesignMode:", isDesignMode)}
|
||||
{componentConfig.leftPanel?.displayMode === "custom" ? (
|
||||
// 🆕 커스텀 모드: 패널 안에 자유롭게 컴포넌트 배치
|
||||
<div
|
||||
@@ -2398,11 +2440,42 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||
height: displayHeight,
|
||||
}}
|
||||
>
|
||||
<div className="pointer-events-none h-full w-full">
|
||||
{/* 🆕 컨테이너 컴포넌트(탭, 분할 패널)는 드롭 이벤트를 받을 수 있어야 함 */}
|
||||
<div className={cn(
|
||||
"h-full w-full",
|
||||
// 탭/분할 패널 같은 컨테이너 컴포넌트는 pointer-events 활성화
|
||||
(comp.componentType === "v2-tabs-widget" ||
|
||||
comp.componentType === "tabs-widget" ||
|
||||
comp.componentType === "v2-split-panel-layout" ||
|
||||
comp.componentType === "split-panel-layout")
|
||||
? ""
|
||||
: "pointer-events-none"
|
||||
)}>
|
||||
<DynamicComponentRenderer
|
||||
component={componentData as any}
|
||||
isDesignMode={true}
|
||||
formData={{}}
|
||||
// 🆕 중첩된 컴포넌트 업데이트 핸들러 전달
|
||||
onUpdateComponent={(updatedComp: any) => {
|
||||
handleNestedComponentUpdate("left", comp.id, updatedComp);
|
||||
}}
|
||||
// 🆕 중첩된 탭 내부 컴포넌트 선택 핸들러 - 부모 분할 패널 정보 포함
|
||||
onSelectTabComponent={(tabId: string, compId: string, tabComp: any) => {
|
||||
console.log("🔍 [SplitPanel-Left] onSelectTabComponent 호출:", { tabId, compId, tabComp, parentSplitPanelId: component.id });
|
||||
// 부모 분할 패널 정보와 함께 전역 이벤트 발생
|
||||
const event = new CustomEvent("nested-tab-component-select", {
|
||||
detail: {
|
||||
tabsComponentId: comp.id,
|
||||
tabId,
|
||||
componentId: compId,
|
||||
component: tabComp,
|
||||
parentSplitPanelId: component.id,
|
||||
parentPanelSide: "left",
|
||||
},
|
||||
});
|
||||
window.dispatchEvent(event);
|
||||
}}
|
||||
selectedTabComponentId={undefined}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -3079,11 +3152,42 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||
height: displayHeight,
|
||||
}}
|
||||
>
|
||||
<div className="pointer-events-none h-full w-full">
|
||||
{/* 🆕 컨테이너 컴포넌트(탭, 분할 패널)는 드롭 이벤트를 받을 수 있어야 함 */}
|
||||
<div className={cn(
|
||||
"h-full w-full",
|
||||
// 탭/분할 패널 같은 컨테이너 컴포넌트는 pointer-events 활성화
|
||||
(comp.componentType === "v2-tabs-widget" ||
|
||||
comp.componentType === "tabs-widget" ||
|
||||
comp.componentType === "v2-split-panel-layout" ||
|
||||
comp.componentType === "split-panel-layout")
|
||||
? ""
|
||||
: "pointer-events-none"
|
||||
)}>
|
||||
<DynamicComponentRenderer
|
||||
component={componentData as any}
|
||||
isDesignMode={true}
|
||||
formData={{}}
|
||||
// 🆕 중첩된 컴포넌트 업데이트 핸들러 전달
|
||||
onUpdateComponent={(updatedComp: any) => {
|
||||
handleNestedComponentUpdate("right", comp.id, updatedComp);
|
||||
}}
|
||||
// 🆕 중첩된 탭 내부 컴포넌트 선택 핸들러 - 부모 분할 패널 정보 포함
|
||||
onSelectTabComponent={(tabId: string, compId: string, tabComp: any) => {
|
||||
console.log("🔍 [SplitPanel-Right] onSelectTabComponent 호출:", { tabId, compId, tabComp, parentSplitPanelId: component.id });
|
||||
// 부모 분할 패널 정보와 함께 전역 이벤트 발생
|
||||
const event = new CustomEvent("nested-tab-component-select", {
|
||||
detail: {
|
||||
tabsComponentId: comp.id,
|
||||
tabId,
|
||||
componentId: compId,
|
||||
component: tabComp,
|
||||
parentSplitPanelId: component.id,
|
||||
parentPanelSide: "right",
|
||||
},
|
||||
});
|
||||
window.dispatchEvent(event);
|
||||
}}
|
||||
selectedTabComponentId={undefined}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user