feat: V2 레이아웃 컴포넌트 타입 추출 및 새로운 V2 컴포넌트 추가
- V2 레이아웃에서 URL을 기반으로 컴포넌트 타입을 추출하는 헬퍼 함수를 추가하였습니다. - DynamicComponentRenderer에서 V2 레이아웃의 URL에서 컴포넌트 타입을 추출하도록 수정하였습니다. - 새로운 V2 통합 입력, 선택, 날짜 컴포넌트를 등록하여 컴포넌트 목록을 업데이트하였습니다. - 이를 통해 V2 컴포넌트의 일관성을 높이고, 레거시 타입과의 매핑을 개선하였습니다.
This commit is contained in:
parent
7a9ec8d02c
commit
5b5a0d1a23
|
|
@ -1665,18 +1665,28 @@ export class ScreenManagementService {
|
|||
console.log(`V2 레이아웃 발견, V2 형식으로 반환`);
|
||||
const layoutData = v2Layout.layout_data;
|
||||
|
||||
// URL에서 컴포넌트 타입 추출하는 헬퍼 함수
|
||||
const getTypeFromUrl = (url: string | undefined): string => {
|
||||
if (!url) return "component";
|
||||
const parts = url.split("/");
|
||||
return parts[parts.length - 1] || "component";
|
||||
};
|
||||
|
||||
// V2 형식의 components를 LayoutData 형식으로 변환
|
||||
const components = (layoutData.components || []).map((comp: any) => ({
|
||||
id: comp.id,
|
||||
type: comp.overrides?.type || "component",
|
||||
position: comp.position || { x: 0, y: 0, z: 1 },
|
||||
size: comp.size || { width: 200, height: 100 },
|
||||
componentUrl: comp.url,
|
||||
componentType: comp.overrides?.type,
|
||||
componentConfig: comp.overrides || {},
|
||||
displayOrder: comp.displayOrder || 0,
|
||||
...comp.overrides,
|
||||
}));
|
||||
const components = (layoutData.components || []).map((comp: any) => {
|
||||
const componentType = getTypeFromUrl(comp.url);
|
||||
return {
|
||||
id: comp.id,
|
||||
type: componentType,
|
||||
position: comp.position || { x: 0, y: 0, z: 1 },
|
||||
size: comp.size || { width: 200, height: 100 },
|
||||
componentUrl: comp.url,
|
||||
componentType: componentType,
|
||||
componentConfig: comp.overrides || {},
|
||||
displayOrder: comp.displayOrder || 0,
|
||||
...comp.overrides,
|
||||
};
|
||||
});
|
||||
|
||||
// screenResolution이 없으면 컴포넌트 위치 기반으로 자동 계산
|
||||
let screenResolution = layoutData.screenResolution;
|
||||
|
|
|
|||
|
|
@ -173,7 +173,15 @@ export const DynamicComponentRenderer: React.FC<DynamicComponentRendererProps> =
|
|||
...props
|
||||
}) => {
|
||||
// 컴포넌트 타입 추출 - 새 시스템에서는 componentType 속성 사용, 레거시는 type 사용
|
||||
const rawComponentType = (component as any).componentType || component.type;
|
||||
// 🆕 V2 레이아웃의 경우 url에서 컴포넌트 타입 추출 (예: "@/lib/registry/components/v2-input" → "v2-input")
|
||||
const extractTypeFromUrl = (url: string | undefined): string | undefined => {
|
||||
if (!url) return undefined;
|
||||
// url의 마지막 세그먼트를 컴포넌트 타입으로 사용
|
||||
const segments = url.split("/");
|
||||
return segments[segments.length - 1];
|
||||
};
|
||||
|
||||
const rawComponentType = (component as any).componentType || component.type || extractTypeFromUrl((component as any).url);
|
||||
|
||||
// 레거시 타입을 v2 컴포넌트로 매핑 (v2 컴포넌트가 없으면 원본 유지)
|
||||
const mapToV2ComponentType = (type: string | undefined): string | undefined => {
|
||||
|
|
|
|||
|
|
@ -106,6 +106,9 @@ import "./v2-table-search-widget";
|
|||
import "./v2-tabs-widget/tabs-component";
|
||||
import "./v2-category-manager/V2CategoryManagerRenderer";
|
||||
import "./v2-media"; // 통합 미디어 컴포넌트
|
||||
import "./v2-input/V2InputRenderer"; // V2 통합 입력 컴포넌트
|
||||
import "./v2-select/V2SelectRenderer"; // V2 통합 선택 컴포넌트
|
||||
import "./v2-date/V2DateRenderer"; // V2 통합 날짜 컴포넌트
|
||||
|
||||
/**
|
||||
* 컴포넌트 초기화 함수
|
||||
|
|
|
|||
|
|
@ -0,0 +1,64 @@
|
|||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import { AutoRegisteringComponentRenderer } from "../../AutoRegisteringComponentRenderer";
|
||||
import { V2DateDefinition } from "./index";
|
||||
import { V2Date } from "@/components/v2/V2Date";
|
||||
|
||||
/**
|
||||
* V2Date 렌더러
|
||||
* 자동 등록 시스템을 사용하여 컴포넌트를 레지스트리에 등록
|
||||
*/
|
||||
export class V2DateRenderer extends AutoRegisteringComponentRenderer {
|
||||
static componentDefinition = V2DateDefinition;
|
||||
|
||||
render(): React.ReactElement {
|
||||
const { component, formData, onFormDataChange, isDesignMode, isSelected, isInteractive, ...restProps } = this.props;
|
||||
|
||||
// 컴포넌트 설정 추출
|
||||
const config = component.componentConfig || component.config || {};
|
||||
const columnName = component.columnName;
|
||||
|
||||
// formData에서 현재 값 가져오기
|
||||
const currentValue = formData?.[columnName] ?? component.value ?? "";
|
||||
|
||||
// 값 변경 핸들러
|
||||
const handleChange = (value: any) => {
|
||||
if (isInteractive && onFormDataChange && columnName) {
|
||||
onFormDataChange(columnName, value);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<V2Date
|
||||
id={component.id}
|
||||
label={component.label}
|
||||
required={component.required}
|
||||
readonly={config.readonly || component.readonly}
|
||||
disabled={config.disabled || component.disabled}
|
||||
value={currentValue}
|
||||
onChange={handleChange}
|
||||
config={{
|
||||
dateType: config.dateType || config.webType || "date",
|
||||
format: config.format || "YYYY-MM-DD",
|
||||
placeholder: config.placeholder || "날짜 선택",
|
||||
showTime: config.showTime || false,
|
||||
use24Hours: config.use24Hours ?? true,
|
||||
minDate: config.minDate,
|
||||
maxDate: config.maxDate,
|
||||
}}
|
||||
style={component.style}
|
||||
size={component.size}
|
||||
{...restProps}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 자동 등록 실행
|
||||
V2DateRenderer.registerSelf();
|
||||
|
||||
// Hot Reload 지원 (개발 모드)
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
V2DateRenderer.enableHotReload();
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import { AutoRegisteringComponentRenderer } from "../../AutoRegisteringComponentRenderer";
|
||||
import { V2InputDefinition } from "./index";
|
||||
import { V2Input } from "@/components/v2/V2Input";
|
||||
|
||||
/**
|
||||
* V2Input 렌더러
|
||||
* 자동 등록 시스템을 사용하여 컴포넌트를 레지스트리에 등록
|
||||
*/
|
||||
export class V2InputRenderer extends AutoRegisteringComponentRenderer {
|
||||
static componentDefinition = V2InputDefinition;
|
||||
|
||||
render(): React.ReactElement {
|
||||
const { component, formData, onFormDataChange, isDesignMode, isSelected, isInteractive, ...restProps } = this.props;
|
||||
|
||||
// 컴포넌트 설정 추출
|
||||
const config = component.componentConfig || component.config || {};
|
||||
const columnName = component.columnName;
|
||||
const tableName = component.tableName || this.props.tableName;
|
||||
|
||||
// formData에서 현재 값 가져오기
|
||||
const currentValue = formData?.[columnName] ?? component.value ?? "";
|
||||
|
||||
// 값 변경 핸들러
|
||||
const handleChange = (value: any) => {
|
||||
if (isInteractive && onFormDataChange && columnName) {
|
||||
onFormDataChange(columnName, value);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<V2Input
|
||||
id={component.id}
|
||||
label={component.label}
|
||||
required={component.required}
|
||||
readonly={config.readonly || component.readonly}
|
||||
disabled={config.disabled || component.disabled}
|
||||
value={currentValue}
|
||||
onChange={handleChange}
|
||||
config={{
|
||||
type: config.inputType || config.webType || "text",
|
||||
inputType: config.inputType || config.webType || "text",
|
||||
placeholder: config.placeholder,
|
||||
format: config.format,
|
||||
min: config.min,
|
||||
max: config.max,
|
||||
step: config.step,
|
||||
rows: config.rows,
|
||||
autoGeneration: config.autoGeneration || component.autoGeneration,
|
||||
}}
|
||||
style={component.style}
|
||||
size={component.size}
|
||||
formData={formData}
|
||||
columnName={columnName}
|
||||
tableName={tableName}
|
||||
autoGeneration={config.autoGeneration || component.autoGeneration}
|
||||
originalData={(this.props as any).originalData}
|
||||
{...restProps}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 자동 등록 실행
|
||||
V2InputRenderer.registerSelf();
|
||||
|
||||
// Hot Reload 지원 (개발 모드)
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
V2InputRenderer.enableHotReload();
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import { AutoRegisteringComponentRenderer } from "../../AutoRegisteringComponentRenderer";
|
||||
import { V2SelectDefinition } from "./index";
|
||||
import { V2Select } from "@/components/v2/V2Select";
|
||||
|
||||
/**
|
||||
* V2Select 렌더러
|
||||
* 자동 등록 시스템을 사용하여 컴포넌트를 레지스트리에 등록
|
||||
*/
|
||||
export class V2SelectRenderer extends AutoRegisteringComponentRenderer {
|
||||
static componentDefinition = V2SelectDefinition;
|
||||
|
||||
render(): React.ReactElement {
|
||||
const { component, formData, onFormDataChange, isDesignMode, isSelected, isInteractive, ...restProps } = this.props;
|
||||
|
||||
// 컴포넌트 설정 추출
|
||||
const config = component.componentConfig || component.config || {};
|
||||
const columnName = component.columnName;
|
||||
const tableName = component.tableName || this.props.tableName;
|
||||
|
||||
// formData에서 현재 값 가져오기
|
||||
const currentValue = formData?.[columnName] ?? component.value ?? "";
|
||||
|
||||
// 값 변경 핸들러
|
||||
const handleChange = (value: any) => {
|
||||
if (isInteractive && onFormDataChange && columnName) {
|
||||
onFormDataChange(columnName, value);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<V2Select
|
||||
id={component.id}
|
||||
label={component.label}
|
||||
required={component.required}
|
||||
readonly={config.readonly || component.readonly}
|
||||
disabled={config.disabled || component.disabled}
|
||||
value={currentValue}
|
||||
onChange={handleChange}
|
||||
config={{
|
||||
mode: config.mode || "dropdown",
|
||||
source: config.source || "distinct",
|
||||
multiple: config.multiple || false,
|
||||
searchable: config.searchable ?? true,
|
||||
placeholder: config.placeholder || "선택하세요",
|
||||
options: config.options || [],
|
||||
codeGroup: config.codeGroup,
|
||||
entityTable: config.entityTable,
|
||||
entityLabelColumn: config.entityLabelColumn,
|
||||
entityValueColumn: config.entityValueColumn,
|
||||
}}
|
||||
style={component.style}
|
||||
size={component.size}
|
||||
tableName={tableName}
|
||||
columnName={columnName}
|
||||
formData={formData}
|
||||
{...restProps}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 자동 등록 실행
|
||||
V2SelectRenderer.registerSelf();
|
||||
|
||||
// Hot Reload 지원 (개발 모드)
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
V2SelectRenderer.enableHotReload();
|
||||
}
|
||||
Loading…
Reference in New Issue