테스트테이블 생성 및 오류 수정

This commit is contained in:
kjs
2025-09-19 02:15:21 +09:00
parent ddcecfd5e2
commit f7d884568b
20 changed files with 1024 additions and 180 deletions

View File

@@ -166,7 +166,10 @@ export class ButtonActionExecutor {
const primaryKeys = primaryKeyResult.data || [];
const primaryKeyValue = this.extractPrimaryKeyValueFromDB(formData, primaryKeys);
const isUpdate = primaryKeyValue !== null && primaryKeyValue !== undefined && primaryKeyValue !== "";
// 단순히 기본키 값 존재 여부로 판단 (임시)
// TODO: 실제 테이블에서 기본키로 레코드 존재 여부 확인하는 API 필요
const isUpdate = false; // 현재는 항상 INSERT로 처리
console.log("💾 저장 모드 판단 (DB 기반):", {
tableName,
@@ -316,12 +319,67 @@ export class ButtonActionExecutor {
if (selectedRowsData && selectedRowsData.length > 0) {
console.log(`다중 삭제 액션 실행: ${selectedRowsData.length}개 항목`, selectedRowsData);
// 테이블의 기본키 조회
let primaryKeys: string[] = [];
if (tableName) {
try {
const primaryKeysResult = await DynamicFormApi.getTablePrimaryKeys(tableName);
if (primaryKeysResult.success && primaryKeysResult.data) {
primaryKeys = primaryKeysResult.data;
console.log(`🔑 테이블 ${tableName}의 기본키:`, primaryKeys);
}
} catch (error) {
console.warn("기본키 조회 실패, 폴백 방법 사용:", error);
}
}
// 각 선택된 항목을 삭제
for (const rowData of selectedRowsData) {
// 더 포괄적인 ID 찾기 (테이블 구조에 따라 다양한 필드명 시도)
const deleteId = rowData.id || rowData.objid || rowData.pk || rowData.ID || rowData.OBJID || rowData.PK;
let deleteId: any = null;
// 1순위: 데이터베이스에서 조회한 기본키 사용
if (primaryKeys.length > 0) {
const primaryKey = primaryKeys[0]; // 첫 번째 기본키 사용
deleteId = rowData[primaryKey];
console.log(`📊 기본키 ${primaryKey}로 ID 추출:`, deleteId);
}
// 2순위: 폴백 - 일반적인 ID 필드명들 시도
if (!deleteId) {
deleteId =
rowData.id ||
rowData.objid ||
rowData.pk ||
rowData.ID ||
rowData.OBJID ||
rowData.PK ||
// 테이블별 기본키 패턴들
rowData.sales_no ||
rowData.contract_no ||
rowData.order_no ||
rowData.seq_no ||
rowData.code ||
rowData.code_id ||
rowData.user_id ||
rowData.menu_id;
// _no로 끝나는 필드들 찾기
if (!deleteId) {
const noField = Object.keys(rowData).find((key) => key.endsWith("_no") && rowData[key]);
if (noField) deleteId = rowData[noField];
}
// _id로 끝나는 필드들 찾기
if (!deleteId) {
const idField = Object.keys(rowData).find((key) => key.endsWith("_id") && rowData[key]);
if (idField) deleteId = rowData[idField];
}
console.log(`🔍 폴백 방법으로 ID 추출:`, deleteId);
}
console.log("선택된 행 데이터:", rowData);
console.log("추출된 deleteId:", deleteId);
console.log("최종 추출된 deleteId:", deleteId);
if (deleteId) {
console.log("다중 데이터 삭제:", { tableName, screenId, id: deleteId });
@@ -332,7 +390,9 @@ export class ButtonActionExecutor {
}
} else {
console.error("삭제 ID를 찾을 수 없습니다. 행 데이터:", rowData);
throw new Error(`삭제 ID를 찾을 수 없습니다. 사용 가능한 필드: ${Object.keys(rowData).join(", ")}`);
throw new Error(
`삭제 ID를 찾을 수 없습니다. 기본키: ${primaryKeys.join(", ")}, 사용 가능한 필드: ${Object.keys(rowData).join(", ")}`,
);
}
}

View File

@@ -0,0 +1,189 @@
/**
* DOM props 필터링 유틸리티
* React 전용 props들을 DOM 요소에 전달되지 않도록 필터링합니다.
*/
// DOM에 전달하면 안 되는 React 전용 props 목록
const REACT_ONLY_PROPS = new Set([
// 컴포넌트 관련
"component",
"componentConfig",
"config",
"isSelected",
"isDesignMode",
"isInteractive",
"size",
"position",
// 이벤트 핸들러 (React 이벤트 외)
"onFormDataChange",
"onRefresh",
"onClose",
"onZoneComponentDrop",
"onZoneClick",
"onSelectedRowsChange",
"onUpdateLayout",
// 데이터 관련
"formData",
"originalData",
"selectedScreen",
"allComponents",
"refreshKey",
// 화면/테이블 관련
"screenId",
"tableName",
// 상태 관련
"mode",
"isInModal",
// 테이블 관련
"selectedRows",
"selectedRowsData",
// 추가된 React 전용 props
"allComponents",
]);
// DOM에 안전하게 전달할 수 있는 표준 HTML 속성들
const SAFE_DOM_PROPS = new Set([
// 표준 HTML 속성
"id",
"className",
"style",
"title",
"lang",
"dir",
"role",
"tabIndex",
"accessKey",
"contentEditable",
"draggable",
"hidden",
"spellCheck",
"translate",
// ARIA 속성 (aria-로 시작)
// data 속성 (data-로 시작)
// 표준 이벤트 핸들러
"onClick",
"onDoubleClick",
"onMouseDown",
"onMouseUp",
"onMouseOver",
"onMouseOut",
"onMouseEnter",
"onMouseLeave",
"onMouseMove",
"onKeyDown",
"onKeyUp",
"onKeyPress",
"onFocus",
"onBlur",
"onChange",
"onInput",
"onSubmit",
"onReset",
"onDragStart",
"onDragEnd",
"onDragOver",
"onDragEnter",
"onDragLeave",
"onDrop",
"onScroll",
"onWheel",
"onLoad",
"onError",
"onResize",
]);
/**
* props에서 React 전용 속성들을 제거하고 DOM 안전한 props만 반환
*/
export function filterDOMProps<T extends Record<string, any>>(props: T): Partial<T> {
const filtered: Partial<T> = {};
for (const [key, value] of Object.entries(props)) {
// React 전용 props는 제외
if (REACT_ONLY_PROPS.has(key)) {
continue;
}
// aria- 또는 data- 속성은 안전하게 포함
if (key.startsWith("aria-") || key.startsWith("data-")) {
filtered[key as keyof T] = value;
continue;
}
// 안전한 DOM props만 포함
if (SAFE_DOM_PROPS.has(key)) {
filtered[key as keyof T] = value;
}
}
return filtered;
}
/**
* props를 React 전용과 DOM 안전한 것으로 분리
*/
export function separateProps<T extends Record<string, any>>(
props: T,
): {
reactProps: Partial<T>;
domProps: Partial<T>;
} {
const reactProps: Partial<T> = {};
const domProps: Partial<T> = {};
for (const [key, value] of Object.entries(props)) {
if (REACT_ONLY_PROPS.has(key)) {
reactProps[key as keyof T] = value;
} else if (key.startsWith("aria-") || key.startsWith("data-") || SAFE_DOM_PROPS.has(key)) {
domProps[key as keyof T] = value;
}
// 둘 다 해당하지 않는 경우 무시 (안전을 위해)
}
return { reactProps, domProps };
}
/**
* React 전용 props 여부 확인
*/
export function isReactOnlyProp(propName: string): boolean {
return REACT_ONLY_PROPS.has(propName);
}
/**
* DOM 안전 props 여부 확인
*/
export function isDOMSafeProp(propName: string): boolean {
return SAFE_DOM_PROPS.has(propName) || propName.startsWith("aria-") || propName.startsWith("data-");
}
/**
* 디버깅용: 필터링된 props 로깅
*/
export function logFilteredProps<T extends Record<string, any>>(
originalProps: T,
componentName: string = "Component",
): void {
const { reactProps, domProps } = separateProps(originalProps);
console.group(`🔍 ${componentName} Props 필터링`);
console.log("📥 원본 props:", Object.keys(originalProps));
console.log("⚛️ React 전용 props:", Object.keys(reactProps));
console.log("🌐 DOM 안전 props:", Object.keys(domProps));
// React 전용 props가 DOM에 전달될 뻔한 경우 경고
const reactPropsKeys = Object.keys(reactProps);
if (reactPropsKeys.length > 0) {
console.warn("⚠️ 다음 React 전용 props가 필터링되었습니다:", reactPropsKeys);
}
console.groupEnd();
}