[agent-pipeline] pipe-20260311052455-y968 round-1
This commit is contained in:
parent
afd936ff67
commit
b329b52036
|
|
@ -8,7 +8,6 @@ import { Badge } from "@/components/ui/badge";
|
|||
import { Separator } from "@/components/ui/separator";
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
||||
import { Checkbox } from "@/components/ui/checkbox";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible";
|
||||
import { ChevronDown, Settings, Info, Database, Trash2, Copy, Palette } from "lucide-react";
|
||||
import {
|
||||
|
|
@ -44,20 +43,11 @@ import {
|
|||
DetailTypeOption,
|
||||
} from "@/types/input-type-mapping";
|
||||
|
||||
// 새로운 컴포넌트 설정 패널들
|
||||
import { ButtonConfigPanel } from "../config-panels/ButtonConfigPanel";
|
||||
import { CardConfigPanel } from "../config-panels/CardConfigPanel";
|
||||
import { DashboardConfigPanel } from "../config-panels/DashboardConfigPanel";
|
||||
import { ColorPickerWithTransparent } from "../common/ColorPickerWithTransparent";
|
||||
import { StatsCardConfigPanel } from "../config-panels/StatsCardConfigPanel";
|
||||
|
||||
// ComponentRegistry import (동적 ConfigPanel 가져오기용)
|
||||
import { ComponentRegistry } from "@/lib/registry/ComponentRegistry";
|
||||
import { ProgressBarConfigPanel } from "../config-panels/ProgressBarConfigPanel";
|
||||
import { ChartConfigPanel } from "../config-panels/ChartConfigPanel";
|
||||
import { AlertConfigPanel } from "../config-panels/AlertConfigPanel";
|
||||
import { BadgeConfigPanel } from "../config-panels/BadgeConfigPanel";
|
||||
import { DynamicComponentConfigPanel } from "@/lib/utils/getComponentConfigPanel";
|
||||
import { DynamicComponentConfigPanel, hasComponentConfigPanel } from "@/lib/utils/getComponentConfigPanel";
|
||||
import StyleEditor from "../StyleEditor";
|
||||
import { Slider } from "@/components/ui/slider";
|
||||
import { Zap } from "lucide-react";
|
||||
|
|
@ -186,17 +176,6 @@ export const V2PropertiesPanel: React.FC<V2PropertiesPanelProps> = ({
|
|||
selectedComponent.componentConfig?.id ||
|
||||
selectedComponent.type;
|
||||
|
||||
const handleUpdateProperty = (path: string, value: any) => {
|
||||
onUpdateProperty(selectedComponent.id, path, value);
|
||||
};
|
||||
|
||||
const handleConfigChange = (newConfig: any) => {
|
||||
// 기존 config와 병합하여 다른 속성 유지
|
||||
const currentConfig = selectedComponent.componentConfig?.config || {};
|
||||
const mergedConfig = { ...currentConfig, ...newConfig };
|
||||
onUpdateProperty(selectedComponent.id, "componentConfig.config", mergedConfig);
|
||||
};
|
||||
|
||||
// 🆕 ComponentRegistry에서 ConfigPanel 가져오기 시도
|
||||
const componentId =
|
||||
selectedComponent.componentType || // ⭐ section-card 등
|
||||
|
|
@ -204,58 +183,6 @@ export const V2PropertiesPanel: React.FC<V2PropertiesPanelProps> = ({
|
|||
selectedComponent.componentConfig?.id ||
|
||||
(selectedComponent.type === "component" ? selectedComponent.id : null); // 🆕 독립 컴포넌트 (table-search-widget 등)
|
||||
|
||||
// 🆕 V2 컴포넌트 직접 감지 및 설정 패널 렌더링
|
||||
if (componentId?.startsWith("v2-")) {
|
||||
const v2ConfigPanels: Record<string, React.FC<{ config: any; onChange: (config: any) => void }>> = {
|
||||
"v2-input": require("@/components/v2/config-panels/V2InputConfigPanel").V2InputConfigPanel,
|
||||
"v2-select": require("@/components/v2/config-panels/V2SelectConfigPanel").V2SelectConfigPanel,
|
||||
"v2-date": require("@/components/v2/config-panels/V2DateConfigPanel").V2DateConfigPanel,
|
||||
"v2-list": require("@/components/v2/config-panels/V2ListConfigPanel").V2ListConfigPanel,
|
||||
"v2-layout": require("@/components/v2/config-panels/V2LayoutConfigPanel").V2LayoutConfigPanel,
|
||||
"v2-group": require("@/components/v2/config-panels/V2GroupConfigPanel").V2GroupConfigPanel,
|
||||
"v2-media": require("@/components/v2/config-panels/V2MediaConfigPanel").V2MediaConfigPanel,
|
||||
"v2-biz": require("@/components/v2/config-panels/V2BizConfigPanel").V2BizConfigPanel,
|
||||
"v2-hierarchy": require("@/components/v2/config-panels/V2HierarchyConfigPanel").V2HierarchyConfigPanel,
|
||||
"v2-bom-item-editor": require("@/components/v2/config-panels/V2BomItemEditorConfigPanel").V2BomItemEditorConfigPanel,
|
||||
"v2-bom-tree": require("@/components/v2/config-panels/V2BomTreeConfigPanel").V2BomTreeConfigPanel,
|
||||
};
|
||||
|
||||
const V2ConfigPanel = v2ConfigPanels[componentId];
|
||||
if (V2ConfigPanel) {
|
||||
const currentConfig = selectedComponent.componentConfig || {};
|
||||
const handleV2ConfigChange = (newConfig: any) => {
|
||||
onUpdateProperty(selectedComponent.id, "componentConfig", { ...currentConfig, ...newConfig });
|
||||
};
|
||||
|
||||
// 컬럼의 inputType 가져오기 (entity 타입인지 확인용)
|
||||
const inputType = currentConfig.inputType || currentConfig.webType || (selectedComponent as any).inputType;
|
||||
|
||||
// 현재 화면의 테이블명 가져오기
|
||||
const currentTableName = tables?.[0]?.tableName;
|
||||
|
||||
// 컴포넌트별 추가 props
|
||||
const extraProps: Record<string, any> = {};
|
||||
if (componentId === "v2-select") {
|
||||
extraProps.inputType = inputType;
|
||||
extraProps.tableName = selectedComponent.tableName || currentTable?.tableName || currentTableName;
|
||||
extraProps.columnName = selectedComponent.columnName || currentConfig.fieldKey || currentConfig.columnName;
|
||||
}
|
||||
if (componentId === "v2-list") {
|
||||
extraProps.currentTableName = currentTableName;
|
||||
}
|
||||
if (componentId === "v2-bom-item-editor" || componentId === "v2-bom-tree") {
|
||||
extraProps.currentTableName = currentTableName;
|
||||
extraProps.screenTableName = selectedComponent.tableName || currentTable?.tableName || currentTableName;
|
||||
}
|
||||
|
||||
return (
|
||||
<div key={selectedComponent.id} className="space-y-4">
|
||||
<V2ConfigPanel config={currentConfig} onChange={handleV2ConfigChange} {...extraProps} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (componentId) {
|
||||
const definition = ComponentRegistry.getComponent(componentId);
|
||||
|
||||
|
|
@ -322,335 +249,42 @@ export const V2PropertiesPanel: React.FC<V2PropertiesPanelProps> = ({
|
|||
</div>
|
||||
);
|
||||
}
|
||||
// ConfigPanel이 없으면 아래 switch case로 넘어감
|
||||
// ConfigPanel이 없으면 DynamicComponentConfigPanel fallback으로 처리
|
||||
}
|
||||
|
||||
// 기존 하드코딩된 설정 패널들 (레거시)
|
||||
switch (componentType) {
|
||||
case "button":
|
||||
case "button-primary":
|
||||
case "button-secondary":
|
||||
case "v2-button-primary":
|
||||
// 🔧 component.id만 key로 사용 (unmount 방지)
|
||||
return (
|
||||
<ButtonConfigPanel
|
||||
key={selectedComponent.id}
|
||||
component={selectedComponent}
|
||||
onUpdateProperty={handleUpdateProperty}
|
||||
allComponents={allComponents}
|
||||
currentTableName={currentTableName}
|
||||
currentScreenCompanyCode={currentScreenCompanyCode}
|
||||
/>
|
||||
);
|
||||
// DynamicComponentConfigPanel을 통한 동적 로드 (CONFIG_PANEL_MAP 기반)
|
||||
const fallbackId = componentId || componentType;
|
||||
if (fallbackId && hasComponentConfigPanel(fallbackId)) {
|
||||
const handleDynamicConfigChange = (newConfig: any) => {
|
||||
const currentConfig = selectedComponent.componentConfig || {};
|
||||
const mergedConfig = { ...currentConfig, ...newConfig };
|
||||
onUpdateProperty(selectedComponent.id, "componentConfig", mergedConfig);
|
||||
};
|
||||
|
||||
case "card":
|
||||
return <CardConfigPanel component={selectedComponent} onUpdateProperty={handleUpdateProperty} />;
|
||||
|
||||
case "dashboard":
|
||||
return <DashboardConfigPanel component={selectedComponent} onUpdateProperty={handleUpdateProperty} />;
|
||||
|
||||
case "stats":
|
||||
case "stats-card":
|
||||
return <StatsCardConfigPanel component={selectedComponent} onUpdateProperty={handleUpdateProperty} />;
|
||||
|
||||
case "progress":
|
||||
case "progress-bar":
|
||||
return <ProgressBarConfigPanel component={selectedComponent} onUpdateProperty={handleUpdateProperty} />;
|
||||
|
||||
case "chart":
|
||||
case "chart-basic":
|
||||
return <ChartConfigPanel component={selectedComponent} onUpdateProperty={handleUpdateProperty} />;
|
||||
|
||||
case "alert":
|
||||
case "alert-info":
|
||||
return <AlertConfigPanel component={selectedComponent} onUpdateProperty={handleUpdateProperty} />;
|
||||
|
||||
case "badge":
|
||||
case "badge-status":
|
||||
return <BadgeConfigPanel component={selectedComponent} onUpdateProperty={handleUpdateProperty} />;
|
||||
|
||||
case "section-card":
|
||||
return (
|
||||
<div className="space-y-4 p-4">
|
||||
<div className="space-y-2">
|
||||
<h3 className="text-sm font-semibold">Section Card 설정</h3>
|
||||
<p className="text-muted-foreground text-xs">제목과 테두리가 있는 명확한 그룹화 컨테이너</p>
|
||||
</div>
|
||||
|
||||
{/* 헤더 표시 */}
|
||||
<div className="flex items-center space-x-2">
|
||||
<Checkbox
|
||||
id="showHeader"
|
||||
checked={selectedComponent.componentConfig?.showHeader !== false}
|
||||
onCheckedChange={(checked) => {
|
||||
handleUpdateProperty(selectedComponent.id, "componentConfig.showHeader", checked);
|
||||
}}
|
||||
/>
|
||||
<Label htmlFor="showHeader" className="cursor-pointer text-xs">
|
||||
헤더 표시
|
||||
</Label>
|
||||
</div>
|
||||
|
||||
{/* 제목 */}
|
||||
{selectedComponent.componentConfig?.showHeader !== false && (
|
||||
<div className="space-y-2">
|
||||
<Label className="text-xs">제목</Label>
|
||||
<Input
|
||||
value={selectedComponent.componentConfig?.title || ""}
|
||||
onChange={(e) => {
|
||||
handleUpdateProperty(selectedComponent.id, "componentConfig.title", e.target.value);
|
||||
}}
|
||||
placeholder="섹션 제목 입력"
|
||||
className="h-9 text-xs"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 설명 */}
|
||||
{selectedComponent.componentConfig?.showHeader !== false && (
|
||||
<div className="space-y-2">
|
||||
<Label className="text-xs">설명 (선택)</Label>
|
||||
<Textarea
|
||||
value={selectedComponent.componentConfig?.description || ""}
|
||||
onChange={(e) => {
|
||||
handleUpdateProperty(selectedComponent.id, "componentConfig.description", e.target.value);
|
||||
}}
|
||||
placeholder="섹션 설명 입력"
|
||||
className="resize-none text-xs"
|
||||
rows={2}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 패딩 */}
|
||||
<div className="space-y-2">
|
||||
<Label className="text-xs">내부 여백</Label>
|
||||
<Select
|
||||
value={selectedComponent.componentConfig?.padding || "md"}
|
||||
onValueChange={(value) => {
|
||||
handleUpdateProperty(selectedComponent.id, "componentConfig.padding", value);
|
||||
}}
|
||||
>
|
||||
<SelectTrigger className="h-9 text-xs">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="none">없음</SelectItem>
|
||||
<SelectItem value="sm">작게 (12px)</SelectItem>
|
||||
<SelectItem value="md">중간 (24px)</SelectItem>
|
||||
<SelectItem value="lg">크게 (32px)</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
{/* 배경색 */}
|
||||
<div className="space-y-2">
|
||||
<Label className="text-xs">배경색</Label>
|
||||
<Select
|
||||
value={selectedComponent.componentConfig?.backgroundColor || "default"}
|
||||
onValueChange={(value) => {
|
||||
handleUpdateProperty(selectedComponent.id, "componentConfig.backgroundColor", value);
|
||||
}}
|
||||
>
|
||||
<SelectTrigger className="h-9 text-xs">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="default">기본 (카드)</SelectItem>
|
||||
<SelectItem value="muted">회색</SelectItem>
|
||||
<SelectItem value="transparent">투명</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
{/* 테두리 스타일 */}
|
||||
<div className="space-y-2">
|
||||
<Label className="text-xs">테두리 스타일</Label>
|
||||
<Select
|
||||
value={selectedComponent.componentConfig?.borderStyle || "solid"}
|
||||
onValueChange={(value) => {
|
||||
handleUpdateProperty(selectedComponent.id, "componentConfig.borderStyle", value);
|
||||
}}
|
||||
>
|
||||
<SelectTrigger className="h-9 text-xs">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="solid">실선</SelectItem>
|
||||
<SelectItem value="dashed">점선</SelectItem>
|
||||
<SelectItem value="none">없음</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
{/* 접기/펼치기 기능 */}
|
||||
<div className="space-y-2 border-t pt-2">
|
||||
<div className="flex items-center space-x-2">
|
||||
<Checkbox
|
||||
id="collapsible"
|
||||
checked={selectedComponent.componentConfig?.collapsible || false}
|
||||
onCheckedChange={(checked) => {
|
||||
handleUpdateProperty(selectedComponent.id, "componentConfig.collapsible", checked);
|
||||
}}
|
||||
/>
|
||||
<Label htmlFor="collapsible" className="cursor-pointer text-xs">
|
||||
접기/펼치기 가능
|
||||
</Label>
|
||||
</div>
|
||||
|
||||
{selectedComponent.componentConfig?.collapsible && (
|
||||
<div className="ml-6 flex items-center space-x-2">
|
||||
<Checkbox
|
||||
id="defaultOpen"
|
||||
checked={selectedComponent.componentConfig?.defaultOpen !== false}
|
||||
onCheckedChange={(checked) => {
|
||||
handleUpdateProperty(selectedComponent.id, "componentConfig.defaultOpen", checked);
|
||||
}}
|
||||
/>
|
||||
<Label htmlFor="defaultOpen" className="cursor-pointer text-xs">
|
||||
기본으로 펼치기
|
||||
</Label>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
case "section-paper":
|
||||
return (
|
||||
<div className="space-y-4 p-4">
|
||||
<div className="space-y-2">
|
||||
<h3 className="text-sm font-semibold">Section Paper 설정</h3>
|
||||
<p className="text-muted-foreground text-xs">배경색 기반의 미니멀한 그룹화 컨테이너</p>
|
||||
</div>
|
||||
|
||||
{/* 배경색 */}
|
||||
<div className="space-y-2">
|
||||
<Label className="text-xs">배경색</Label>
|
||||
<Select
|
||||
value={selectedComponent.componentConfig?.backgroundColor || "default"}
|
||||
onValueChange={(value) => {
|
||||
handleUpdateProperty(selectedComponent.id, "componentConfig.backgroundColor", value);
|
||||
}}
|
||||
>
|
||||
<SelectTrigger className="h-9 text-xs">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="default">기본 (연한 회색)</SelectItem>
|
||||
<SelectItem value="muted">회색</SelectItem>
|
||||
<SelectItem value="accent">강조 (연한 파랑)</SelectItem>
|
||||
<SelectItem value="primary">브랜드 컬러</SelectItem>
|
||||
<SelectItem value="custom">커스텀</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
{/* 커스텀 색상 */}
|
||||
{selectedComponent.componentConfig?.backgroundColor === "custom" && (
|
||||
<div className="space-y-2">
|
||||
<Label className="text-xs">커스텀 색상</Label>
|
||||
<ColorPickerWithTransparent
|
||||
value={selectedComponent.componentConfig?.customColor}
|
||||
onChange={(value) => {
|
||||
handleUpdateProperty(selectedComponent.id, "componentConfig.customColor", value);
|
||||
}}
|
||||
defaultColor="#f0f0f0"
|
||||
placeholder="#f0f0f0"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 패딩 */}
|
||||
<div className="space-y-2">
|
||||
<Label className="text-xs">내부 여백</Label>
|
||||
<Select
|
||||
value={selectedComponent.componentConfig?.padding || "md"}
|
||||
onValueChange={(value) => {
|
||||
handleUpdateProperty(selectedComponent.id, "componentConfig.padding", value);
|
||||
}}
|
||||
>
|
||||
<SelectTrigger className="h-9 text-xs">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="none">없음</SelectItem>
|
||||
<SelectItem value="sm">작게 (12px)</SelectItem>
|
||||
<SelectItem value="md">중간 (16px)</SelectItem>
|
||||
<SelectItem value="lg">크게 (24px)</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
{/* 둥근 모서리 */}
|
||||
<div className="space-y-2">
|
||||
<Label className="text-xs">둥근 모서리</Label>
|
||||
<Select
|
||||
value={selectedComponent.componentConfig?.roundedCorners || "md"}
|
||||
onValueChange={(value) => {
|
||||
handleUpdateProperty(selectedComponent.id, "componentConfig.roundedCorners", value);
|
||||
}}
|
||||
>
|
||||
<SelectTrigger className="h-9 text-xs">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="none">없음</SelectItem>
|
||||
<SelectItem value="sm">작게 (2px)</SelectItem>
|
||||
<SelectItem value="md">중간 (6px)</SelectItem>
|
||||
<SelectItem value="lg">크게 (8px)</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
{/* 그림자 */}
|
||||
<div className="space-y-2">
|
||||
<Label className="text-xs">그림자</Label>
|
||||
<Select
|
||||
value={selectedComponent.componentConfig?.shadow || "none"}
|
||||
onValueChange={(value) => {
|
||||
handleUpdateProperty(selectedComponent.id, "componentConfig.shadow", value);
|
||||
}}
|
||||
>
|
||||
<SelectTrigger className="h-9 text-xs">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="none">없음</SelectItem>
|
||||
<SelectItem value="sm">작게</SelectItem>
|
||||
<SelectItem value="md">중간</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
{/* 테두리 표시 */}
|
||||
<div className="flex items-center space-x-2">
|
||||
<Checkbox
|
||||
id="showBorder"
|
||||
checked={selectedComponent.componentConfig?.showBorder || false}
|
||||
onCheckedChange={(checked) => {
|
||||
handleUpdateProperty(selectedComponent.id, "componentConfig.showBorder", checked);
|
||||
}}
|
||||
/>
|
||||
<Label htmlFor="showBorder" className="cursor-pointer text-xs">
|
||||
미묘한 테두리 표시
|
||||
</Label>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
default:
|
||||
// ConfigPanel이 없는 경우 경고 표시
|
||||
return (
|
||||
<div className="flex h-full flex-col items-center justify-center p-6 text-center">
|
||||
<Settings className="text-muted-foreground mb-4 h-12 w-12" />
|
||||
<h3 className="mb-2 text-base font-medium">⚠️ 설정 패널 없음</h3>
|
||||
<p className="text-muted-foreground text-sm">
|
||||
컴포넌트 "{componentId || componentType}"에 대한 설정 패널이 없습니다.
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<DynamicComponentConfigPanel
|
||||
componentId={fallbackId}
|
||||
config={selectedComponent.componentConfig || {}}
|
||||
onChange={handleDynamicConfigChange}
|
||||
screenTableName={selectedComponent.tableName || currentTable?.tableName || currentTableName}
|
||||
tableColumns={currentTable?.columns || []}
|
||||
tables={tables}
|
||||
menuObjid={menuObjid}
|
||||
allComponents={allComponents}
|
||||
currentComponent={selectedComponent}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex h-full flex-col items-center justify-center p-6 text-center">
|
||||
<Settings className="text-muted-foreground mb-4 h-12 w-12" />
|
||||
<h3 className="mb-2 text-base font-medium">설정 패널 없음</h3>
|
||||
<p className="text-muted-foreground text-sm">
|
||||
컴포넌트 "{fallbackId || componentType}"에 대한 설정 패널이 없습니다.
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
// 기본 정보 탭
|
||||
|
|
|
|||
|
|
@ -73,7 +73,6 @@ const CONFIG_PANEL_MAP: Record<string, () => Promise<any>> = {
|
|||
"v2-repeat-container": () => import("@/lib/registry/components/v2-repeat-container/RepeatContainerConfigPanel"),
|
||||
"repeater-field-group": () => import("@/components/webtypes/config/RepeaterConfigPanel"),
|
||||
"v2-repeater": () => import("@/components/v2/config-panels/V2RepeaterConfigPanel"),
|
||||
"v2-repeater": () => import("@/components/v2/config-panels/V2RepeaterConfigPanel"),
|
||||
"simple-repeater-table": () => import("@/lib/registry/components/simple-repeater-table/SimpleRepeaterTableConfigPanel"),
|
||||
"modal-repeater-table": () => import("@/lib/registry/components/modal-repeater-table/ModalRepeaterTableConfigPanel"),
|
||||
"repeat-screen-modal": () => import("@/lib/registry/components/repeat-screen-modal/RepeatScreenModalConfigPanel"),
|
||||
|
|
@ -104,6 +103,24 @@ const CONFIG_PANEL_MAP: Record<string, () => Promise<any>> = {
|
|||
"category-manager": () => import("@/lib/registry/components/category-manager/CategoryManagerConfigPanel"),
|
||||
"universal-form-modal": () => import("@/lib/registry/components/universal-form-modal/UniversalFormModalConfigPanel"),
|
||||
"v2-process-work-standard": () => import("@/lib/registry/components/v2-process-work-standard/ProcessWorkStandardConfigPanel"),
|
||||
|
||||
// ========== V2 BOM 컴포넌트 ==========
|
||||
"v2-bom-item-editor": () => import("@/components/v2/config-panels/V2BomItemEditorConfigPanel"),
|
||||
"v2-bom-tree": () => import("@/components/v2/config-panels/V2BomTreeConfigPanel"),
|
||||
|
||||
// ========== 레거시 위젯 (component/onUpdateProperty props 사용) ==========
|
||||
"card": () => import("@/components/screen/config-panels/CardConfigPanel"),
|
||||
"dashboard": () => import("@/components/screen/config-panels/DashboardConfigPanel"),
|
||||
"stats": () => import("@/components/screen/config-panels/StatsCardConfigPanel"),
|
||||
"stats-card": () => import("@/components/screen/config-panels/StatsCardConfigPanel"),
|
||||
"progress": () => import("@/components/screen/config-panels/ProgressBarConfigPanel"),
|
||||
"progress-bar": () => import("@/components/screen/config-panels/ProgressBarConfigPanel"),
|
||||
"chart": () => import("@/components/screen/config-panels/ChartConfigPanel"),
|
||||
"chart-basic": () => import("@/components/screen/config-panels/ChartConfigPanel"),
|
||||
"alert": () => import("@/components/screen/config-panels/AlertConfigPanel"),
|
||||
"alert-info": () => import("@/components/screen/config-panels/AlertConfigPanel"),
|
||||
"badge": () => import("@/components/screen/config-panels/BadgeConfigPanel"),
|
||||
"badge-status": () => import("@/components/screen/config-panels/BadgeConfigPanel"),
|
||||
};
|
||||
|
||||
// ConfigPanel 컴포넌트 캐시
|
||||
|
|
@ -128,60 +145,30 @@ export async function getComponentConfigPanel(componentId: string): Promise<Reac
|
|||
try {
|
||||
const module = await importFn();
|
||||
|
||||
// 모듈에서 ConfigPanel 컴포넌트 추출
|
||||
// 1차: PascalCase 변환된 이름으로 찾기 (예: text-input -> TextInputConfigPanel)
|
||||
// 2차: v2- 접두사 제거 후 PascalCase 이름으로 찾기 (예: v2-table-list -> TableListConfigPanel)
|
||||
// 3차: 특수 export명들 fallback
|
||||
// 모듈에서 ConfigPanel 컴포넌트 추출 (우선순위):
|
||||
// 1차: PascalCase 변환된 이름 (예: text-input -> TextInputConfigPanel)
|
||||
// 2차: v2- 접두사 제거 후 PascalCase (예: v2-table-list -> TableListConfigPanel)
|
||||
// 3차: *ConfigPanel로 끝나는 첫 번째 named export
|
||||
// 4차: default export
|
||||
const pascalCaseName = `${toPascalCase(componentId)}ConfigPanel`;
|
||||
// v2- 접두사가 있는 경우 접두사를 제거한 이름도 시도
|
||||
const baseComponentId = componentId.startsWith("v2-") ? componentId.slice(3) : componentId;
|
||||
const basePascalCaseName = `${toPascalCase(baseComponentId)}ConfigPanel`;
|
||||
|
||||
// 모듈에서 ConfigPanel로 끝나는 첫 번째 named export를 찾는 fallback
|
||||
const findConfigPanelExport = () => {
|
||||
for (const key of Object.keys(module)) {
|
||||
if (key.endsWith("ConfigPanel") && typeof module[key] === "function") {
|
||||
return module[key];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const ConfigPanelComponent =
|
||||
module[pascalCaseName] ||
|
||||
module[basePascalCaseName] ||
|
||||
// 특수 export명들
|
||||
module.RepeaterConfigPanel ||
|
||||
module.FlowWidgetConfigPanel ||
|
||||
module.CustomerItemMappingConfigPanel ||
|
||||
module.SelectedItemsDetailInputConfigPanel ||
|
||||
module.ButtonConfigPanel ||
|
||||
module.TableListConfigPanel ||
|
||||
module.SectionCardConfigPanel ||
|
||||
module.SectionPaperConfigPanel ||
|
||||
module.TabsConfigPanel ||
|
||||
module.V2RepeaterConfigPanel ||
|
||||
module.V2InputConfigPanel ||
|
||||
module.V2SelectConfigPanel ||
|
||||
module.V2DateConfigPanel ||
|
||||
module.V2ListConfigPanel ||
|
||||
module.V2MediaConfigPanel ||
|
||||
module.V2BizConfigPanel ||
|
||||
module.V2GroupConfigPanel ||
|
||||
module.V2HierarchyConfigPanel ||
|
||||
module.V2LayoutConfigPanel ||
|
||||
module.RepeatContainerConfigPanel ||
|
||||
module.ScreenSplitPanelConfigPanel ||
|
||||
module.SimpleRepeaterTableConfigPanel ||
|
||||
module.ModalRepeaterTableConfigPanel ||
|
||||
module.RepeatScreenModalConfigPanel ||
|
||||
module.RelatedDataButtonsConfigPanel ||
|
||||
module.AutocompleteSearchInputConfigPanel ||
|
||||
module.EntitySearchInputConfigPanel ||
|
||||
module.MailRecipientSelectorConfigPanel ||
|
||||
module.LocationSwapSelectorConfigPanel ||
|
||||
module.MapConfigPanel ||
|
||||
module.RackStructureConfigPanel ||
|
||||
module.AggregationWidgetConfigPanel ||
|
||||
module.NumberingRuleConfigPanel ||
|
||||
module.CategoryManagerConfigPanel ||
|
||||
module.UniversalFormModalConfigPanel ||
|
||||
module.PivotGridConfigPanel ||
|
||||
module.TableSearchWidgetConfigPanel ||
|
||||
module.TaxInvoiceListConfigPanel ||
|
||||
module.ImageWidgetConfigPanel ||
|
||||
module.TestInputConfigPanel ||
|
||||
findConfigPanelExport() ||
|
||||
module.default;
|
||||
|
||||
if (!ConfigPanelComponent) {
|
||||
|
|
@ -522,6 +509,33 @@ export const DynamicComponentConfigPanel: React.FC<ComponentConfigPanelProps> =
|
|||
}
|
||||
};
|
||||
|
||||
// 레거시 위젯 패널 (component/onUpdateProperty props 사용)
|
||||
const LEGACY_PANELS = new Set([
|
||||
"card", "dashboard", "stats", "stats-card",
|
||||
"progress", "progress-bar", "chart", "chart-basic",
|
||||
"alert", "alert-info", "badge", "badge-status",
|
||||
]);
|
||||
|
||||
if (LEGACY_PANELS.has(componentId)) {
|
||||
const pseudoComponent = {
|
||||
id: currentComponent?.id || "temp",
|
||||
type: "component",
|
||||
componentConfig: config,
|
||||
...currentComponent,
|
||||
};
|
||||
return (
|
||||
<ConfigPanelComponent
|
||||
component={pseudoComponent}
|
||||
onUpdateProperty={(path: string, value: any) => {
|
||||
if (path.startsWith("componentConfig.")) {
|
||||
const key = path.replace("componentConfig.", "");
|
||||
onChange({ ...config, [key]: value });
|
||||
}
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// 🆕 수주 등록 관련 컴포넌트들은 간단한 인터페이스 사용
|
||||
const isSimpleConfigPanel = [
|
||||
"autocomplete-search-input",
|
||||
|
|
|
|||
Loading…
Reference in New Issue