8f92fb2368
- input-type-mapping.ts: BaseInputType 10개 → UserSelectableInputType 8개 (박창현 image 2). vexplor_rps INPUT_TYPE_DETAIL_TYPES 포팅, select/checkbox/radio variant 를 code base 로 흡수 - input-types.ts: USER_SELECTABLE_INPUT_TYPE_ORDER/LABELS re-export (InputType 12개는 그대로) - getDetailType.ts (신규): getWidgetVariants / getDefaultWidgetVariant helper - 드롭다운 호출처 7개 8개 제한: ColumnDetailPanel, AddColumnModal, ColumnDefinitionTable, tableMngList/page.tsx, TableSettingModal, TypeOverviewStrip, types.ts - ColumnDetailPanel: Legacy row 드롭다운 disabled + v5-glow-sm Alert 배너 - backward shim: BaseInputType / BASE_INPUT_TYPE_OPTIONS / getBaseInputType 등 V2/Properties/DetailSettingsPanel 호환 운영 DB 96.6% 가 이미 8개 안 (V0, 35,316 row). DB zero touch, mapper 5곳 보호. spec: .omc/specs/deep-dive-table-type-storage-ui-separation.md (v3.2) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
187 lines
9.7 KiB
TypeScript
187 lines
9.7 KiB
TypeScript
/** 박창현 image 2 의 8개 — 사용자가 테이블 타입 관리에서 직접 고를 수 있는 base */
|
|
export type UserSelectableInputType =
|
|
| "text" | "number" | "date"
|
|
| "code" | "entity"
|
|
| "numbering" | "file" | "image";
|
|
|
|
/** 화면관리 widget 의 세부 variant */
|
|
export interface WidgetVariantOption {
|
|
value: string;
|
|
label: string;
|
|
description: string;
|
|
}
|
|
|
|
/**
|
|
* 8개 base 별 widget variant 매핑.
|
|
* vexplor_rps `input-type-mapping.ts:37-102` 의 variant 그대로 포팅.
|
|
* 박창현 결정 (Q3): select/checkbox/radio base 의 variant 는 모두 code base 로 흡수.
|
|
*/
|
|
export const INPUT_TYPE_DETAIL_TYPES: Record<UserSelectableInputType, WidgetVariantOption[]> = {
|
|
text: [
|
|
{ value: "text", label: "일반 텍스트", description: "기본 텍스트 입력" },
|
|
{ value: "email", label: "이메일", description: "이메일 주소 입력" },
|
|
{ value: "tel", label: "전화번호", description: "전화번호 입력" },
|
|
{ value: "url", label: "URL", description: "웹사이트 주소 입력" },
|
|
{ value: "password", label: "비밀번호", description: "마스킹 입력" },
|
|
{ value: "textarea", label: "여러 줄 텍스트", description: "긴 텍스트 영역" },
|
|
],
|
|
number: [
|
|
{ value: "number", label: "정수", description: "정수 숫자 입력" },
|
|
{ value: "decimal", label: "소수", description: "소수점 포함" },
|
|
{ value: "currency", label: "통화", description: "₩ 1,000 형식" },
|
|
{ value: "percentage", label: "퍼센트", description: "50% 형식" },
|
|
],
|
|
date: [
|
|
{ value: "date", label: "날짜", description: "YYYY-MM-DD" },
|
|
{ value: "datetime", label: "날짜+시간", description: "날짜와 시간" },
|
|
{ value: "time", label: "시간", description: "HH:mm" },
|
|
{ value: "daterange", label: "기간", description: "시작일 ~ 종료일" },
|
|
{ value: "month", label: "월", description: "YYYY-MM" },
|
|
{ value: "year", label: "년", description: "YYYY" },
|
|
],
|
|
code: [
|
|
{ value: "code", label: "코드 선택박스", description: "드롭다운으로 코드 선택" },
|
|
{ value: "code-autocomplete", label: "코드 자동완성", description: "코드/코드명 검색" },
|
|
{ value: "code-radio", label: "코드 라디오", description: "라디오 버튼 그룹" },
|
|
{ value: "code-radio-horizontal", label: "가로 라디오", description: "가로 배치 라디오" },
|
|
{ value: "code-radio-vertical", label: "세로 라디오", description: "세로 배치 라디오" },
|
|
{ value: "dropdown", label: "검색 선택박스", description: "검색 기능 포함 (vexplor_rps select base)" },
|
|
{ value: "multiselect", label: "다중 선택", description: "여러 항목 선택 (vexplor_rps select base)" },
|
|
{ value: "autocomplete", label: "자동완성", description: "입력하면 자동완성 제안 (vexplor_rps select base)" },
|
|
{ value: "checkbox", label: "체크박스", description: "단일 체크박스 (vexplor_rps checkbox base)" },
|
|
{ value: "checkbox-group", label: "체크박스 그룹", description: "여러 체크박스 (vexplor_rps checkbox base)" },
|
|
{ value: "boolean", label: "On/Off 스위치", description: "boolean 스위치 (vexplor_rps checkbox base)" },
|
|
],
|
|
entity: [
|
|
{ value: "entity", label: "엔티티 참조", description: "다른 테이블 데이터 참조" },
|
|
{ value: "entity-autocomplete", label: "엔티티 자동완성", description: "검색 결과 inline 표시" },
|
|
{ value: "entity-popup", label: "엔티티 팝업", description: "별도 검색 팝업" },
|
|
],
|
|
file: [
|
|
{ value: "file", label: "단일 파일", description: "파일 1개 첨부" },
|
|
{ value: "file-list", label: "다중 파일", description: "여러 파일 첨부" },
|
|
{ value: "file-drop", label: "드래그 앤 드롭", description: "drop zone 형태" },
|
|
],
|
|
image: [
|
|
{ value: "image", label: "이미지", description: "이미지 1장 표시/업로드" },
|
|
{ value: "image-gallery", label: "이미지 갤러리", description: "여러 장 grid 표시" },
|
|
{ value: "image-upload", label: "이미지 업로드", description: "크롭/리사이즈 포함" },
|
|
],
|
|
numbering: [
|
|
{ value: "numbering", label: "자동 채번", description: "옵션설정의 채번 규칙으로 자동 생성" },
|
|
],
|
|
};
|
|
|
|
/** 8개 base 의 한글 라벨 */
|
|
export const USER_SELECTABLE_INPUT_TYPE_LABELS: Record<UserSelectableInputType, string> = {
|
|
text: "텍스트",
|
|
number: "숫자",
|
|
date: "날짜",
|
|
code: "코드",
|
|
entity: "테이블참조",
|
|
numbering: "채번",
|
|
file: "파일",
|
|
image: "이미지",
|
|
};
|
|
|
|
/** 8개 base 의 순서 (드롭다운/카드 표시 순서) */
|
|
export const USER_SELECTABLE_INPUT_TYPE_ORDER: UserSelectableInputType[] = [
|
|
"text", "number", "date",
|
|
"code", "entity",
|
|
"numbering", "file", "image",
|
|
];
|
|
|
|
export function isUserSelectableInputType(value: string): value is UserSelectableInputType {
|
|
return USER_SELECTABLE_INPUT_TYPE_ORDER.includes(value as UserSelectableInputType);
|
|
}
|
|
|
|
// ─────────────────────────────────────────────────────────────────────────
|
|
// Backward Shim — 사용처 3곳 (V2PropertiesPanel/PropertiesPanel/DetailSettingsPanel) 임시 호환
|
|
// ─────────────────────────────────────────────────────────────────────────
|
|
|
|
/**
|
|
* @deprecated v3.2: BaseInputType 은 UserSelectableInputType (8개) 로 대체.
|
|
* 이 export 는 backward shim — 사용처 3곳 임시 호환. 후속 PR 에서 strangle.
|
|
*/
|
|
export type BaseInputType =
|
|
| UserSelectableInputType
|
|
| "textarea"
|
|
| "select"
|
|
| "checkbox"
|
|
| "radio";
|
|
|
|
/**
|
|
* @deprecated v3.2: WidgetVariantOption 로 대체.
|
|
* 사용처 3곳의 DetailTypeOption import 호환용.
|
|
*/
|
|
export type DetailTypeOption = WidgetVariantOption;
|
|
|
|
/**
|
|
* @deprecated v3.2: UserSelectableInputType 의 8개로 사용 권장.
|
|
* 사용처 3곳의 BASE_INPUT_TYPE_OPTIONS import 호환용.
|
|
*/
|
|
export const BASE_INPUT_TYPE_OPTIONS: Array<{ value: BaseInputType; label: string; description: string }> = [
|
|
{ value: "text", label: "텍스트", description: "텍스트 입력 필드" },
|
|
{ value: "textarea", label: "텍스트 에리어", description: "여러 줄 텍스트 입력 (legacy — text base 의 variant)" },
|
|
{ value: "number", label: "숫자", description: "숫자 입력 필드" },
|
|
{ value: "date", label: "날짜", description: "날짜/시간 선택" },
|
|
{ value: "code", label: "코드", description: "공통 코드 선택" },
|
|
{ value: "entity", label: "엔티티", description: "다른 테이블 참조" },
|
|
{ value: "select", label: "선택박스", description: "드롭다운 선택 (legacy — code base 의 variant)" },
|
|
{ value: "checkbox", label: "체크박스", description: "체크박스/스위치 (legacy — code base 의 variant)" },
|
|
{ value: "radio", label: "라디오버튼", description: "라디오 버튼 그룹 (legacy — code base 의 variant)" },
|
|
{ value: "image", label: "이미지", description: "이미지 표시" },
|
|
{ value: "numbering", label: "자동 채번", description: "옵션설정 기반 자동 번호" },
|
|
{ value: "file", label: "파일", description: "파일 업로드" },
|
|
];
|
|
|
|
/**
|
|
* @deprecated v3.2: webType → UserSelectableInputType 로 매핑 권장 (`getUserSelectableInputType`).
|
|
* 사용처 3곳의 getBaseInputType 호환용.
|
|
*/
|
|
export function getBaseInputType(webType: string): BaseInputType {
|
|
if (["text", "email", "tel", "url", "password"].includes(webType)) return "text";
|
|
if (webType === "textarea") return "textarea";
|
|
if (["number", "decimal", "currency", "percentage"].includes(webType)) return "number";
|
|
if (["date", "datetime", "time", "daterange", "month", "year"].includes(webType)) return "date";
|
|
if (["code", "code-autocomplete", "code-radio", "code-radio-horizontal", "code-radio-vertical"].includes(webType)) return "code";
|
|
if (["select", "dropdown", "multiselect", "autocomplete"].includes(webType)) return "select";
|
|
if (["checkbox", "boolean", "checkbox-group"].includes(webType)) return "checkbox";
|
|
if (["radio", "radio-horizontal", "radio-vertical"].includes(webType)) return "radio";
|
|
if (webType === "entity" || webType.startsWith("entity-")) return "entity";
|
|
if (webType === "image" || webType.startsWith("image-")) return "image";
|
|
if (webType === "file" || webType.startsWith("file-")) return "file";
|
|
if (webType === "numbering") return "numbering";
|
|
return "text";
|
|
}
|
|
|
|
/** 신규 권장 함수 — UserSelectableInputType 직접 반환 */
|
|
export function getUserSelectableInputType(webType: string): UserSelectableInputType {
|
|
const base = getBaseInputType(webType);
|
|
if (base === "textarea") return "text";
|
|
if (base === "select" || base === "checkbox" || base === "radio") return "code";
|
|
return base as UserSelectableInputType;
|
|
}
|
|
|
|
/**
|
|
* @deprecated v3.2: getWidgetVariants (lib/utils/getDetailType.ts) 권장.
|
|
* 사용처의 getDetailTypes import 호환용.
|
|
*/
|
|
export function getDetailTypes(baseInputType: BaseInputType): DetailTypeOption[] {
|
|
// legacy base → UserSelectableInputType 매핑 후 variant 조회
|
|
let key: UserSelectableInputType;
|
|
if (baseInputType === "textarea") key = "text";
|
|
else if (baseInputType === "select" || baseInputType === "checkbox" || baseInputType === "radio") key = "code";
|
|
else key = baseInputType;
|
|
return INPUT_TYPE_DETAIL_TYPES[key] ?? [];
|
|
}
|
|
|
|
/**
|
|
* @deprecated v3.2: getDefaultWidgetVariant (lib/utils/getDetailType.ts) 권장.
|
|
* 사용처의 getDefaultDetailType import 호환용.
|
|
*/
|
|
export function getDefaultDetailType(baseInputType: BaseInputType): string {
|
|
const variants = getDetailTypes(baseInputType);
|
|
return variants[0]?.value ?? baseInputType;
|
|
}
|