Files
vexplor/frontend/lib/utils/layoutV2Converter.ts
DDD1542 192b678bce fix: 화면 복제 기능 개선 및 관련 버그 수정
- 화면 복제 기능을 개선하여 DB 구조 개편 후의 효율적인 화면 관리를 지원합니다.
- 그룹 복제 시 버튼의 `targetScreenId`가 새 화면으로 매핑되지 않는 버그를 수정하였습니다.
- 관련된 서비스 및 쿼리에서 `table_type_columns`를 사용하여 라벨 정보를 조회하도록 변경하였습니다.
- 여러 컨트롤러 및 서비스에서 `column_labels` 대신 `table_type_columns`를 참조하도록 업데이트하였습니다.
2026-01-28 11:24:25 +09:00

141 lines
3.6 KiB
TypeScript

/**
* V2 레이아웃 변환 유틸리티
*
* 기존 LayoutData ↔ V2 LayoutData 변환
*/
import {
ComponentV2,
LayoutV2,
getComponentUrl,
getComponentTypeFromUrl,
getDefaultsByUrl,
mergeComponentConfig,
extractCustomConfig
} from "@/lib/schemas/componentConfig";
// 기존 ComponentData 타입 (간략화)
interface LegacyComponentData {
id: string;
componentType?: string;
widgetType?: string;
type?: string;
position?: { x: number; y: number };
size?: { width: number; height: number };
componentConfig?: Record<string, any>;
[key: string]: any;
}
interface LegacyLayoutData {
components: LegacyComponentData[];
gridSettings?: any;
screenResolution?: any;
metadata?: any;
}
// ============================================
// V2 → Legacy 변환 (로드 시)
// ============================================
export function convertV2ToLegacy(v2Layout: LayoutV2 | null): LegacyLayoutData | null {
if (!v2Layout || !v2Layout.components) {
return null;
}
const components: LegacyComponentData[] = v2Layout.components.map((comp) => {
const componentType = getComponentTypeFromUrl(comp.url);
const defaults = getDefaultsByUrl(comp.url);
const mergedConfig = mergeComponentConfig(defaults, comp.overrides);
return {
id: comp.id,
componentType: componentType,
widgetType: componentType,
type: "component",
position: comp.position,
size: comp.size,
componentConfig: mergedConfig,
// 기존 구조 호환을 위한 추가 필드
label: mergedConfig.label || componentType,
style: {},
parentId: null,
gridColumns: 12,
gridRowIndex: 0,
};
});
return {
components,
gridSettings: {
enabled: true,
size: 20,
color: "#d1d5db",
opacity: 0.5,
snapToGrid: true,
columns: 12,
gap: 16,
padding: 16,
},
screenResolution: {
width: 1920,
height: 1080,
},
};
}
// ============================================
// Legacy → V2 변환 (저장 시)
// ============================================
export function convertLegacyToV2(legacyLayout: LegacyLayoutData): LayoutV2 {
const components: ComponentV2[] = legacyLayout.components.map((comp, index) => {
// 컴포넌트 타입 결정
const componentType = comp.componentType || comp.widgetType || comp.type || "unknown";
const url = getComponentUrl(componentType);
// 기본값 가져오기
const defaults = getDefaultsByUrl(url);
// 현재 설정에서 차이값만 추출
const fullConfig = comp.componentConfig || {};
const overrides = extractCustomConfig(fullConfig, defaults);
return {
id: comp.id,
url: url,
position: comp.position || { x: 0, y: 0 },
size: comp.size || { width: 100, height: 100 },
displayOrder: index,
overrides: overrides,
};
});
return {
version: "2.0",
components,
updatedAt: new Date().toISOString(),
};
}
// ============================================
// V2 레이아웃 유효성 검사
// ============================================
export function isValidV2Layout(data: any): data is LayoutV2 {
return (
data &&
typeof data === "object" &&
data.version === "2.0" &&
Array.isArray(data.components)
);
}
// ============================================
// 기존 레이아웃인지 확인
// ============================================
export function isLegacyLayout(data: any): boolean {
return (
data &&
typeof data === "object" &&
Array.isArray(data.components) &&
data.version !== "2.0"
);
}