컴포넌트 리뉴얼 1.0

This commit is contained in:
kjs
2025-12-19 15:44:38 +09:00
parent 2487c79a61
commit 91d00aa784
61 changed files with 11678 additions and 175 deletions
+76 -41
View File
@@ -17,7 +17,7 @@ import {
SCREEN_RESOLUTIONS,
} from "@/types/screen";
import { generateComponentId } from "@/lib/utils/generateId";
import { getComponentIdFromWebType } from "@/lib/utils/webTypeMapping";
import { getComponentIdFromWebType, createUnifiedConfigFromColumn, getUnifiedConfigFromWebType } from "@/lib/utils/webTypeMapping";
import {
createGroupComponent,
calculateBoundingBox,
@@ -938,11 +938,35 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD
: null;
const tableLabel = currentTable?.displayName || tableName;
// 현재 화면의 테이블 컬럼 정보 조회
const columnsResponse = await tableTypeApi.getColumns(tableName);
// 현재 화면의 테이블 컬럼 정보 조회 (캐시 버스팅으로 최신 데이터 가져오기)
const columnsResponse = await tableTypeApi.getColumns(tableName, true);
const columns: ColumnInfo[] = (columnsResponse || []).map((col: any) => {
const widgetType = col.widgetType || col.widget_type || col.webType || col.web_type;
// widgetType 결정: inputType(entity 등) > webType > widget_type
const inputType = col.inputType || col.input_type;
const widgetType = inputType || col.widgetType || col.widget_type || col.webType || col.web_type;
// detailSettings 파싱 (문자열이면 JSON 파싱)
let detailSettings = col.detailSettings || col.detail_settings;
if (typeof detailSettings === "string") {
try {
detailSettings = JSON.parse(detailSettings);
} catch (e) {
console.warn("detailSettings 파싱 실패:", e);
detailSettings = {};
}
}
// 엔티티 타입 디버깅
if (inputType === "entity" || widgetType === "entity") {
console.log("🔍 엔티티 컬럼 감지:", {
columnName: col.columnName || col.column_name,
inputType,
widgetType,
detailSettings,
referenceTable: detailSettings?.referenceTable || col.referenceTable || col.reference_table,
});
}
return {
tableName: col.tableName || tableName,
@@ -950,7 +974,8 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD
columnLabel: col.displayName || col.columnLabel || col.column_label || col.columnName || col.column_name,
dataType: col.dataType || col.data_type || col.dbType,
webType: col.webType || col.web_type,
input_type: col.inputType || col.input_type,
input_type: inputType,
inputType: inputType,
widgetType,
isNullable: col.isNullable || col.is_nullable,
required: col.required !== undefined ? col.required : col.isNullable === "NO" || col.is_nullable === "NO",
@@ -958,10 +983,12 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD
characterMaximumLength: col.characterMaximumLength || col.character_maximum_length,
codeCategory: col.codeCategory || col.code_category,
codeValue: col.codeValue || col.code_value,
// 엔티티 타입용 참조 테이블 정보
referenceTable: col.referenceTable || col.reference_table,
referenceColumn: col.referenceColumn || col.reference_column,
displayColumn: col.displayColumn || col.display_column,
// 엔티티 타입용 참조 테이블 정보 (detailSettings에서 추출)
referenceTable: detailSettings?.referenceTable || col.referenceTable || col.reference_table,
referenceColumn: detailSettings?.referenceColumn || col.referenceColumn || col.reference_column,
displayColumn: detailSettings?.displayColumn || col.displayColumn || col.display_column,
// detailSettings 전체 보존 (Unified 컴포넌트용)
detailSettings,
};
});
@@ -2578,28 +2605,40 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD
const relativeX = e.clientX - containerRect.left;
const relativeY = e.clientY - containerRect.top;
// 웹타입을 새로운 컴포넌트 ID로 매핑
const componentId = getComponentIdFromWebType(column.widgetType);
// console.log(`🔄 폼 컨테이너 드롭: ${column.widgetType} → ${componentId}`);
// 🆕 Unified 컴포넌트 매핑 사용
const unifiedMapping = createUnifiedConfigFromColumn({
widgetType: column.widgetType,
columnName: column.columnName,
columnLabel: column.columnLabel,
codeCategory: column.codeCategory,
inputType: column.inputType,
required: column.required,
detailSettings: column.detailSettings, // 엔티티 참조 정보 전달
// column_labels 직접 필드도 전달
referenceTable: column.referenceTable,
referenceColumn: column.referenceColumn,
displayColumn: column.displayColumn,
});
// 웹타입별 기본 너비 계산 (10px 단위 고정)
const componentWidth = getDefaultWidth(column.widgetType);
console.log("🎯 폼 컨테이너 컴포넌트 생성:", {
console.log("🎯 폼 컨테이너 Unified 컴포넌트 생성:", {
widgetType: column.widgetType,
unifiedType: unifiedMapping.componentType,
componentWidth,
});
newComponent = {
id: generateComponentId(),
type: "component", // ✅ 새로운 컴포넌트 시스템 사용
type: "component", // ✅ Unified 컴포넌트 시스템 사용
label: column.columnLabel || column.columnName,
tableName: table.tableName,
columnName: column.columnName,
required: column.required,
readonly: false,
parentId: formContainerId, // 폼 컨테이너의 자식으로 설정
componentType: componentId, // DynamicComponentRenderer용 컴포넌트 타입
componentType: unifiedMapping.componentType, // unified-input, unified-select 등
position: { x: relativeX, y: relativeY, z: 1 } as Position,
size: { width: componentWidth, height: getDefaultHeight(column.widgetType) },
// 코드 타입인 경우 코드 카테고리 정보 추가
@@ -2615,43 +2654,47 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD
labelMarginBottom: "6px",
},
componentConfig: {
type: componentId, // text-input, number-input 등
webType: column.widgetType, // 원본 웹타입 보존
inputType: column.inputType, // ✅ input_type 추가 (category 등)
...getDefaultWebTypeConfig(column.widgetType),
placeholder: column.columnLabel || column.columnName, // placeholder에 라벨명 표시
// 코드 타입인 경우 코드 카테고리 정보 추가
...(column.widgetType === "code" &&
column.codeCategory && {
codeCategory: column.codeCategory,
}),
type: unifiedMapping.componentType, // unified-input, unified-select 등
...unifiedMapping.componentConfig, // Unified 컴포넌트 기본 설정
},
};
} else {
return; // 폼 컨테이너를 찾을 수 없으면 드롭 취소
}
} else {
// 일반 캔버스에 드롭한 경우 - 새로운 컴포넌트 시스템 사용
const componentId = getComponentIdFromWebType(column.widgetType);
// console.log(`🔄 캔버스 드롭: ${column.widgetType} → ${componentId}`);
// 일반 캔버스에 드롭한 경우 - 🆕 Unified 컴포넌트 시스템 사용
const unifiedMapping = createUnifiedConfigFromColumn({
widgetType: column.widgetType,
columnName: column.columnName,
columnLabel: column.columnLabel,
codeCategory: column.codeCategory,
inputType: column.inputType,
required: column.required,
detailSettings: column.detailSettings, // 엔티티 참조 정보 전달
// column_labels 직접 필드도 전달
referenceTable: column.referenceTable,
referenceColumn: column.referenceColumn,
displayColumn: column.displayColumn,
});
// 웹타입별 기본 너비 계산 (10px 단위 고정)
const componentWidth = getDefaultWidth(column.widgetType);
console.log("🎯 캔버스 컴포넌트 생성:", {
console.log("🎯 캔버스 Unified 컴포넌트 생성:", {
widgetType: column.widgetType,
unifiedType: unifiedMapping.componentType,
componentWidth,
});
newComponent = {
id: generateComponentId(),
type: "component", // ✅ 새로운 컴포넌트 시스템 사용
type: "component", // ✅ Unified 컴포넌트 시스템 사용
label: column.columnLabel || column.columnName, // 컬럼 라벨 우선, 없으면 컬럼명
tableName: table.tableName,
columnName: column.columnName,
required: column.required,
readonly: false,
componentType: componentId, // DynamicComponentRenderer용 컴포넌트 타입
componentType: unifiedMapping.componentType, // unified-input, unified-select 등
position: { x, y, z: 1 } as Position,
size: { width: componentWidth, height: getDefaultHeight(column.widgetType) },
// 코드 타입인 경우 코드 카테고리 정보 추가
@@ -2667,16 +2710,8 @@ export default function ScreenDesigner({ selectedScreen, onBackToList }: ScreenD
labelMarginBottom: "8px",
},
componentConfig: {
type: componentId, // text-input, number-input 등
webType: column.widgetType, // 원본 웹타입 보존
inputType: column.inputType, // ✅ input_type 추가 (category 등)
...getDefaultWebTypeConfig(column.widgetType),
placeholder: column.columnLabel || column.columnName, // placeholder에 라벨명 표시
// 코드 타입인 경우 코드 카테고리 정보 추가
...(column.widgetType === "code" &&
column.codeCategory && {
codeCategory: column.codeCategory,
}),
type: unifiedMapping.componentType, // unified-input, unified-select 등
...unifiedMapping.componentConfig, // Unified 컴포넌트 기본 설정
},
};
}