fix: 분할패널 수정 버튼 클릭 시 데이터 불러오기 오류 수정
- Primary Key 컬럼명을 프론트엔드에서 백엔드로 전달하도록 개선 - 백엔드 자동 감지 실패 시에도 클라이언트 제공 값 우선 사용 - Primary Key 찾기 로직 개선 (설정값 > id > ID > non-null 필드)
This commit is contained in:
parent
6a0aa87d3b
commit
e8fc664352
|
|
@ -606,7 +606,7 @@ router.get(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const { enableEntityJoin, groupByColumns } = req.query;
|
const { enableEntityJoin, groupByColumns, primaryKeyColumn } = req.query;
|
||||||
const enableEntityJoinFlag =
|
const enableEntityJoinFlag =
|
||||||
enableEntityJoin === "true" ||
|
enableEntityJoin === "true" ||
|
||||||
(typeof enableEntityJoin === "boolean" && enableEntityJoin);
|
(typeof enableEntityJoin === "boolean" && enableEntityJoin);
|
||||||
|
|
@ -626,17 +626,22 @@ router.get(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 🆕 primaryKeyColumn 파싱
|
||||||
|
const primaryKeyColumnStr = typeof primaryKeyColumn === "string" ? primaryKeyColumn : undefined;
|
||||||
|
|
||||||
console.log(`🔍 레코드 상세 조회: ${tableName}/${id}`, {
|
console.log(`🔍 레코드 상세 조회: ${tableName}/${id}`, {
|
||||||
enableEntityJoin: enableEntityJoinFlag,
|
enableEntityJoin: enableEntityJoinFlag,
|
||||||
groupByColumns: groupByColumnsArray,
|
groupByColumns: groupByColumnsArray,
|
||||||
|
primaryKeyColumn: primaryKeyColumnStr,
|
||||||
});
|
});
|
||||||
|
|
||||||
// 레코드 상세 조회 (Entity Join 옵션 + 그룹핑 옵션 포함)
|
// 레코드 상세 조회 (Entity Join 옵션 + 그룹핑 옵션 + Primary Key 컬럼 포함)
|
||||||
const result = await dataService.getRecordDetail(
|
const result = await dataService.getRecordDetail(
|
||||||
tableName,
|
tableName,
|
||||||
id,
|
id,
|
||||||
enableEntityJoinFlag,
|
enableEntityJoinFlag,
|
||||||
groupByColumnsArray
|
groupByColumnsArray,
|
||||||
|
primaryKeyColumnStr // 🆕 Primary Key 컬럼명 전달
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!result.success) {
|
if (!result.success) {
|
||||||
|
|
|
||||||
|
|
@ -490,7 +490,8 @@ class DataService {
|
||||||
tableName: string,
|
tableName: string,
|
||||||
id: string | number,
|
id: string | number,
|
||||||
enableEntityJoin: boolean = false,
|
enableEntityJoin: boolean = false,
|
||||||
groupByColumns: string[] = []
|
groupByColumns: string[] = [],
|
||||||
|
primaryKeyColumn?: string // 🆕 클라이언트에서 전달한 Primary Key 컬럼명
|
||||||
): Promise<ServiceResponse<any>> {
|
): Promise<ServiceResponse<any>> {
|
||||||
try {
|
try {
|
||||||
// 테이블 접근 검증
|
// 테이블 접근 검증
|
||||||
|
|
@ -499,20 +500,30 @@ class DataService {
|
||||||
return validation.error!;
|
return validation.error!;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Primary Key 컬럼 찾기
|
// 🆕 클라이언트에서 전달한 Primary Key 컬럼이 있으면 우선 사용
|
||||||
const pkResult = await query<{ attname: string }>(
|
let pkColumn = primaryKeyColumn || "";
|
||||||
`SELECT a.attname
|
|
||||||
FROM pg_index i
|
// Primary Key 컬럼이 없으면 자동 감지
|
||||||
JOIN pg_attribute a ON a.attrelid = i.indrelid AND a.attnum = ANY(i.indkey)
|
if (!pkColumn) {
|
||||||
WHERE i.indrelid = $1::regclass AND i.indisprimary`,
|
const pkResult = await query<{ attname: string }>(
|
||||||
[tableName]
|
`SELECT a.attname
|
||||||
);
|
FROM pg_index i
|
||||||
|
JOIN pg_attribute a ON a.attrelid = i.indrelid AND a.attnum = ANY(i.indkey)
|
||||||
|
WHERE i.indrelid = $1::regclass AND i.indisprimary`,
|
||||||
|
[tableName]
|
||||||
|
);
|
||||||
|
|
||||||
let pkColumn = "id"; // 기본값
|
pkColumn = "id"; // 기본값
|
||||||
if (pkResult.length > 0) {
|
if (pkResult.length > 0) {
|
||||||
pkColumn = pkResult[0].attname;
|
pkColumn = pkResult[0].attname;
|
||||||
|
}
|
||||||
|
console.log(`🔑 [getRecordDetail] 자동 감지된 Primary Key:`, pkResult);
|
||||||
|
} else {
|
||||||
|
console.log(`🔑 [getRecordDetail] 클라이언트 제공 Primary Key: ${pkColumn}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log(`🔑 [getRecordDetail] 테이블: ${tableName}, Primary Key 컬럼: ${pkColumn}, 조회 ID: ${id}`);
|
||||||
|
|
||||||
// 🆕 Entity Join이 활성화된 경우
|
// 🆕 Entity Join이 활성화된 경우
|
||||||
if (enableEntityJoin) {
|
if (enableEntityJoin) {
|
||||||
const { EntityJoinService } = await import("./entityJoinService");
|
const { EntityJoinService } = await import("./entityJoinService");
|
||||||
|
|
|
||||||
|
|
@ -374,8 +374,9 @@ export const ScreenModal: React.FC<ScreenModalProps> = ({ className }) => {
|
||||||
const editId = urlParams.get("editId");
|
const editId = urlParams.get("editId");
|
||||||
const tableName = urlParams.get("tableName") || screenInfo.tableName;
|
const tableName = urlParams.get("tableName") || screenInfo.tableName;
|
||||||
const groupByColumnsParam = urlParams.get("groupByColumns");
|
const groupByColumnsParam = urlParams.get("groupByColumns");
|
||||||
|
const primaryKeyColumn = urlParams.get("primaryKeyColumn"); // 🆕 Primary Key 컬럼명
|
||||||
|
|
||||||
console.log("📋 URL 파라미터 확인:", { mode, editId, tableName, groupByColumnsParam });
|
console.log("📋 URL 파라미터 확인:", { mode, editId, tableName, groupByColumnsParam, primaryKeyColumn });
|
||||||
|
|
||||||
// 수정 모드이고 editId가 있으면 해당 레코드 조회
|
// 수정 모드이고 editId가 있으면 해당 레코드 조회
|
||||||
if (mode === "edit" && editId && tableName) {
|
if (mode === "edit" && editId && tableName) {
|
||||||
|
|
@ -414,6 +415,11 @@ export const ScreenModal: React.FC<ScreenModalProps> = ({ className }) => {
|
||||||
params.groupByColumns = JSON.stringify(groupByColumns);
|
params.groupByColumns = JSON.stringify(groupByColumns);
|
||||||
console.log("✅ [ScreenModal] groupByColumns를 params에 추가:", params.groupByColumns);
|
console.log("✅ [ScreenModal] groupByColumns를 params에 추가:", params.groupByColumns);
|
||||||
}
|
}
|
||||||
|
// 🆕 Primary Key 컬럼명 전달 (백엔드 자동 감지 실패 시 사용)
|
||||||
|
if (primaryKeyColumn) {
|
||||||
|
params.primaryKeyColumn = primaryKeyColumn;
|
||||||
|
console.log("✅ [ScreenModal] primaryKeyColumn을 params에 추가:", primaryKeyColumn);
|
||||||
|
}
|
||||||
|
|
||||||
console.log("📡 [ScreenModal] 실제 API 요청:", {
|
console.log("📡 [ScreenModal] 실제 API 요청:", {
|
||||||
url: `/data/${tableName}/${editId}`,
|
url: `/data/${tableName}/${editId}`,
|
||||||
|
|
|
||||||
|
|
@ -1590,21 +1590,40 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||||
// 커스텀 모달 화면 열기
|
// 커스텀 모달 화면 열기
|
||||||
const rightTableName = componentConfig.rightPanel?.tableName || "";
|
const rightTableName = componentConfig.rightPanel?.tableName || "";
|
||||||
|
|
||||||
// Primary Key 찾기 (우선순위: id > ID > 첫 번째 필드)
|
// Primary Key 찾기 (우선순위: 설정값 > id > ID > non-null 필드)
|
||||||
|
// 🔧 설정에서 primaryKeyColumn 지정 가능
|
||||||
|
const configuredPrimaryKey = componentConfig.rightPanel?.editButton?.primaryKeyColumn;
|
||||||
|
|
||||||
let primaryKeyName = "id";
|
let primaryKeyName = "id";
|
||||||
let primaryKeyValue: any;
|
let primaryKeyValue: any;
|
||||||
|
|
||||||
if (item.id !== undefined && item.id !== null) {
|
if (configuredPrimaryKey && item[configuredPrimaryKey] !== undefined && item[configuredPrimaryKey] !== null) {
|
||||||
|
// 설정된 Primary Key 사용
|
||||||
|
primaryKeyName = configuredPrimaryKey;
|
||||||
|
primaryKeyValue = item[configuredPrimaryKey];
|
||||||
|
} else if (item.id !== undefined && item.id !== null) {
|
||||||
primaryKeyName = "id";
|
primaryKeyName = "id";
|
||||||
primaryKeyValue = item.id;
|
primaryKeyValue = item.id;
|
||||||
} else if (item.ID !== undefined && item.ID !== null) {
|
} else if (item.ID !== undefined && item.ID !== null) {
|
||||||
primaryKeyName = "ID";
|
primaryKeyName = "ID";
|
||||||
primaryKeyValue = item.ID;
|
primaryKeyValue = item.ID;
|
||||||
} else {
|
} else {
|
||||||
// 첫 번째 필드를 Primary Key로 간주
|
// 🔧 첫 번째 non-null 필드를 Primary Key로 간주
|
||||||
const firstKey = Object.keys(item)[0];
|
const keys = Object.keys(item);
|
||||||
primaryKeyName = firstKey;
|
let found = false;
|
||||||
primaryKeyValue = item[firstKey];
|
for (const key of keys) {
|
||||||
|
if (item[key] !== undefined && item[key] !== null) {
|
||||||
|
primaryKeyName = key;
|
||||||
|
primaryKeyValue = item[key];
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 모든 필드가 null이면 첫 번째 필드 사용
|
||||||
|
if (!found && keys.length > 0) {
|
||||||
|
primaryKeyName = keys[0];
|
||||||
|
primaryKeyValue = item[keys[0]];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("✅ 수정 모달 열기:", {
|
console.log("✅ 수정 모달 열기:", {
|
||||||
|
|
@ -1629,7 +1648,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||||
hasGroupByColumns: groupByColumns.length > 0,
|
hasGroupByColumns: groupByColumns.length > 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
// ScreenModal 열기 이벤트 발생 (URL 파라미터로 ID + groupByColumns 전달)
|
// ScreenModal 열기 이벤트 발생 (URL 파라미터로 ID + groupByColumns + primaryKeyColumn 전달)
|
||||||
window.dispatchEvent(
|
window.dispatchEvent(
|
||||||
new CustomEvent("openScreenModal", {
|
new CustomEvent("openScreenModal", {
|
||||||
detail: {
|
detail: {
|
||||||
|
|
@ -1638,6 +1657,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||||
mode: "edit",
|
mode: "edit",
|
||||||
editId: primaryKeyValue,
|
editId: primaryKeyValue,
|
||||||
tableName: rightTableName,
|
tableName: rightTableName,
|
||||||
|
primaryKeyColumn: primaryKeyName, // 🆕 Primary Key 컬럼명 전달
|
||||||
...(groupByColumns.length > 0 && {
|
...(groupByColumns.length > 0 && {
|
||||||
groupByColumns: JSON.stringify(groupByColumns),
|
groupByColumns: JSON.stringify(groupByColumns),
|
||||||
}),
|
}),
|
||||||
|
|
@ -1650,6 +1670,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||||
screenId: modalScreenId,
|
screenId: modalScreenId,
|
||||||
editId: primaryKeyValue,
|
editId: primaryKeyValue,
|
||||||
tableName: rightTableName,
|
tableName: rightTableName,
|
||||||
|
primaryKeyColumn: primaryKeyName,
|
||||||
groupByColumns: groupByColumns.length > 0 ? JSON.stringify(groupByColumns) : "없음",
|
groupByColumns: groupByColumns.length > 0 ? JSON.stringify(groupByColumns) : "없음",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue