Merge branch 'main' of http://39.117.244.52:3000/kjs/ERP-node into feature/v2-unified-renewal
This commit is contained in:
@@ -951,23 +951,43 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||
// 추가 dataFilter 적용
|
||||
let filteredData = result.data || [];
|
||||
const dataFilter = componentConfig.rightPanel?.dataFilter;
|
||||
if (dataFilter?.enabled && dataFilter.conditions?.length > 0) {
|
||||
// 🔧 filters 또는 conditions 배열 모두 지원
|
||||
const filterConditions = dataFilter?.filters || dataFilter?.conditions || [];
|
||||
if (dataFilter?.enabled && filterConditions.length > 0) {
|
||||
console.log(`🔍 [기본탭] dataFilter 설정:`, JSON.stringify(dataFilter, null, 2));
|
||||
console.log(`🔍 [기본탭] 필터 전 데이터 수:`, filteredData.length);
|
||||
filteredData = filteredData.filter((item: any) => {
|
||||
return dataFilter.conditions.every((cond: any) => {
|
||||
const value = item[cond.column];
|
||||
return filterConditions.every((cond: any) => {
|
||||
// 🔧 columnName 또는 column 필드 모두 지원
|
||||
const columnName = cond.columnName || cond.column;
|
||||
const value = item[columnName];
|
||||
const condValue = cond.value;
|
||||
let result = true;
|
||||
switch (cond.operator) {
|
||||
case "equals":
|
||||
return value === condValue;
|
||||
result = value === condValue;
|
||||
break;
|
||||
case "notEquals":
|
||||
return value !== condValue;
|
||||
result = value !== condValue;
|
||||
break;
|
||||
case "contains":
|
||||
return String(value).includes(String(condValue));
|
||||
result = String(value).includes(String(condValue));
|
||||
break;
|
||||
case "is_null":
|
||||
case "NULL":
|
||||
result = value === null || value === undefined || value === "";
|
||||
break;
|
||||
case "is_not_null":
|
||||
case "NOT NULL":
|
||||
result = value !== null && value !== undefined && value !== "";
|
||||
break;
|
||||
default:
|
||||
return true;
|
||||
result = true;
|
||||
}
|
||||
return result;
|
||||
});
|
||||
});
|
||||
console.log(`🔍 [기본탭] 필터 후 데이터 수:`, filteredData.length);
|
||||
}
|
||||
|
||||
setRightData(filteredData);
|
||||
@@ -1080,23 +1100,48 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||
|
||||
// 데이터 필터 적용
|
||||
const dataFilter = tabConfig.dataFilter;
|
||||
if (dataFilter?.enabled && dataFilter.conditions?.length > 0) {
|
||||
console.log(`🔍 [추가탭 ${tabIndex}] dataFilter 설정:`, JSON.stringify(dataFilter, null, 2));
|
||||
// 🔧 filters 또는 conditions 배열 모두 지원 (DataFilterConfigPanel은 filters 사용)
|
||||
const filterConditions = dataFilter?.filters || dataFilter?.conditions || [];
|
||||
console.log(`🔍 [추가탭 ${tabIndex}] filterConditions:`, filterConditions);
|
||||
console.log(`🔍 [추가탭 ${tabIndex}] 필터 전 데이터 수:`, resultData.length);
|
||||
if (dataFilter?.enabled && filterConditions.length > 0) {
|
||||
const beforeCount = resultData.length;
|
||||
resultData = resultData.filter((item: any) => {
|
||||
return dataFilter.conditions.every((cond: any) => {
|
||||
const value = item[cond.column];
|
||||
return filterConditions.every((cond: any) => {
|
||||
// 🔧 columnName 또는 column 필드 모두 지원
|
||||
const columnName = cond.columnName || cond.column;
|
||||
const value = item[columnName];
|
||||
const condValue = cond.value;
|
||||
let result = true;
|
||||
switch (cond.operator) {
|
||||
case "equals":
|
||||
return value === condValue;
|
||||
result = value === condValue;
|
||||
break;
|
||||
case "notEquals":
|
||||
return value !== condValue;
|
||||
result = value !== condValue;
|
||||
break;
|
||||
case "contains":
|
||||
return String(value).includes(String(condValue));
|
||||
result = String(value).includes(String(condValue));
|
||||
break;
|
||||
case "is_null":
|
||||
case "NULL":
|
||||
result = value === null || value === undefined || value === "";
|
||||
break;
|
||||
case "is_not_null":
|
||||
case "NOT NULL":
|
||||
result = value !== null && value !== undefined && value !== "";
|
||||
break;
|
||||
default:
|
||||
return true;
|
||||
result = true;
|
||||
}
|
||||
console.log(`🔍 [필터 체크] ${columnName}=${JSON.stringify(value)}, operator=${cond.operator}, result=${result}`);
|
||||
return result;
|
||||
});
|
||||
});
|
||||
console.log(`🔍 [추가탭 ${tabIndex}] 필터 후 데이터 수: ${beforeCount} → ${resultData.length}`);
|
||||
} else {
|
||||
console.log(`🔍 [추가탭 ${tabIndex}] 필터 비활성화 또는 조건 없음 (enabled=${dataFilter?.enabled}, conditions=${filterConditions.length})`);
|
||||
}
|
||||
|
||||
// 중복 제거 적용
|
||||
@@ -1557,6 +1602,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||
// 추가 버튼 핸들러
|
||||
const handleAddClick = useCallback(
|
||||
(panel: "left" | "right") => {
|
||||
console.log("🆕 [추가모달] handleAddClick 호출:", { panel, activeTabIndex });
|
||||
setAddModalPanel(panel);
|
||||
|
||||
// 우측 패널 추가 시, 좌측에서 선택된 항목의 조인 컬럼 값을 자동으로 채움
|
||||
@@ -1567,124 +1613,183 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
||||
componentConfig.rightPanel?.rightColumn
|
||||
) {
|
||||
const leftColumnValue = selectedLeftItem[componentConfig.leftPanel.leftColumn];
|
||||
setAddModalFormData({
|
||||
const initialData = {
|
||||
[componentConfig.rightPanel.rightColumn]: leftColumnValue,
|
||||
});
|
||||
};
|
||||
console.log("🆕 [추가모달] 초기 데이터 설정:", initialData);
|
||||
setAddModalFormData(initialData);
|
||||
} else {
|
||||
console.log("🆕 [추가모달] 빈 데이터로 초기화");
|
||||
setAddModalFormData({});
|
||||
}
|
||||
|
||||
setShowAddModal(true);
|
||||
},
|
||||
[selectedLeftItem, componentConfig],
|
||||
[selectedLeftItem, componentConfig, activeTabIndex],
|
||||
);
|
||||
|
||||
// 수정 버튼 핸들러
|
||||
const handleEditClick = useCallback(
|
||||
(panel: "left" | "right", item: any) => {
|
||||
// 🆕 우측 패널 수정 버튼 설정 확인
|
||||
if (panel === "right" && componentConfig.rightPanel?.editButton?.mode === "modal") {
|
||||
const modalScreenId = componentConfig.rightPanel?.editButton?.modalScreenId;
|
||||
// 🔧 현재 활성 탭에 따라 해당 탭의 editButton 설정 사용
|
||||
if (panel === "right") {
|
||||
// 기본 탭(0)이면 rightPanel.editButton, 추가 탭이면 additionalTabs의 editButton 사용
|
||||
const editButtonConfig =
|
||||
activeTabIndex === 0
|
||||
? componentConfig.rightPanel?.editButton
|
||||
: componentConfig.rightPanel?.additionalTabs?.[activeTabIndex - 1]?.editButton;
|
||||
|
||||
if (modalScreenId) {
|
||||
// 커스텀 모달 화면 열기
|
||||
const rightTableName = componentConfig.rightPanel?.tableName || "";
|
||||
// 해당 탭의 테이블명 가져오기
|
||||
const currentTableName =
|
||||
activeTabIndex === 0
|
||||
? componentConfig.rightPanel?.tableName || ""
|
||||
: componentConfig.rightPanel?.additionalTabs?.[activeTabIndex - 1]?.tableName || "";
|
||||
|
||||
// Primary Key 찾기 (우선순위: 설정값 > id > ID > non-null 필드)
|
||||
// 🔧 설정에서 primaryKeyColumn 지정 가능
|
||||
const configuredPrimaryKey = componentConfig.rightPanel?.editButton?.primaryKeyColumn;
|
||||
console.log("🔧 [SplitPanel] 수정 버튼 클릭 - 현재 탭 설정 확인:", {
|
||||
activeTabIndex,
|
||||
editButtonConfig,
|
||||
currentTableName,
|
||||
isModalMode: editButtonConfig?.mode === "modal",
|
||||
});
|
||||
|
||||
let primaryKeyName = "id";
|
||||
let primaryKeyValue: any;
|
||||
if (editButtonConfig?.mode === "modal") {
|
||||
const modalScreenId = editButtonConfig.modalScreenId;
|
||||
|
||||
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";
|
||||
primaryKeyValue = item.id;
|
||||
} else if (item.ID !== undefined && item.ID !== null) {
|
||||
primaryKeyName = "ID";
|
||||
primaryKeyValue = item.ID;
|
||||
} else {
|
||||
// 🔧 첫 번째 non-null 필드를 Primary Key로 간주
|
||||
const keys = Object.keys(item);
|
||||
let found = false;
|
||||
for (const key of keys) {
|
||||
if (item[key] !== undefined && item[key] !== null) {
|
||||
primaryKeyName = key;
|
||||
primaryKeyValue = item[key];
|
||||
found = true;
|
||||
break;
|
||||
if (modalScreenId) {
|
||||
// 커스텀 모달 화면 열기
|
||||
|
||||
// Primary Key 찾기 (우선순위: 설정값 > id > ID > non-null 필드)
|
||||
// 🔧 설정에서 primaryKeyColumn 지정 가능
|
||||
const configuredPrimaryKey = editButtonConfig.primaryKeyColumn;
|
||||
|
||||
let primaryKeyName = "id";
|
||||
let primaryKeyValue: any;
|
||||
|
||||
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";
|
||||
primaryKeyValue = item.id;
|
||||
} else if (item.ID !== undefined && item.ID !== null) {
|
||||
primaryKeyName = "ID";
|
||||
primaryKeyValue = item.ID;
|
||||
} else {
|
||||
// 🔧 첫 번째 non-null 필드를 Primary Key로 간주
|
||||
const keys = Object.keys(item);
|
||||
let found = false;
|
||||
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]];
|
||||
}
|
||||
}
|
||||
// 모든 필드가 null이면 첫 번째 필드 사용
|
||||
if (!found && keys.length > 0) {
|
||||
primaryKeyName = keys[0];
|
||||
primaryKeyValue = item[keys[0]];
|
||||
}
|
||||
}
|
||||
|
||||
console.log("✅ 수정 모달 열기:", {
|
||||
tableName: rightTableName,
|
||||
primaryKeyName,
|
||||
primaryKeyValue,
|
||||
screenId: modalScreenId,
|
||||
fullItem: item,
|
||||
});
|
||||
console.log("✅ 수정 모달 열기:", {
|
||||
activeTabIndex,
|
||||
tableName: currentTableName,
|
||||
primaryKeyName,
|
||||
primaryKeyValue,
|
||||
screenId: modalScreenId,
|
||||
fullItem: item,
|
||||
});
|
||||
|
||||
// modalDataStore에도 저장 (호환성 유지)
|
||||
import("@/stores/modalDataStore").then(({ useModalDataStore }) => {
|
||||
useModalDataStore.getState().setData(rightTableName, [item]);
|
||||
});
|
||||
// modalDataStore에도 저장 (호환성 유지)
|
||||
import("@/stores/modalDataStore").then(({ useModalDataStore }) => {
|
||||
useModalDataStore.getState().setData(currentTableName, [item]);
|
||||
});
|
||||
|
||||
// 🆕 groupByColumns 추출
|
||||
const groupByColumns = componentConfig.rightPanel?.editButton?.groupByColumns || [];
|
||||
// 🆕 groupByColumns 추출
|
||||
const groupByColumns = editButtonConfig.groupByColumns || [];
|
||||
|
||||
console.log("🔧 [SplitPanel] 수정 버튼 클릭 - groupByColumns 확인:", {
|
||||
groupByColumns,
|
||||
editButtonConfig: componentConfig.rightPanel?.editButton,
|
||||
hasGroupByColumns: groupByColumns.length > 0,
|
||||
});
|
||||
console.log("🔧 [SplitPanel] 수정 버튼 클릭 - groupByColumns 확인:", {
|
||||
groupByColumns,
|
||||
editButtonConfig,
|
||||
hasGroupByColumns: groupByColumns.length > 0,
|
||||
});
|
||||
|
||||
// ScreenModal 열기 이벤트 발생 (URL 파라미터로 ID + groupByColumns + primaryKeyColumn 전달)
|
||||
window.dispatchEvent(
|
||||
new CustomEvent("openScreenModal", {
|
||||
detail: {
|
||||
screenId: modalScreenId,
|
||||
urlParams: {
|
||||
mode: "edit",
|
||||
editId: primaryKeyValue,
|
||||
tableName: rightTableName,
|
||||
primaryKeyColumn: primaryKeyName, // 🆕 Primary Key 컬럼명 전달
|
||||
...(groupByColumns.length > 0 && {
|
||||
groupByColumns: JSON.stringify(groupByColumns),
|
||||
}),
|
||||
// ScreenModal 열기 이벤트 발생 (URL 파라미터로 ID + groupByColumns + primaryKeyColumn 전달)
|
||||
window.dispatchEvent(
|
||||
new CustomEvent("openScreenModal", {
|
||||
detail: {
|
||||
screenId: modalScreenId,
|
||||
urlParams: {
|
||||
mode: "edit",
|
||||
editId: primaryKeyValue,
|
||||
tableName: currentTableName,
|
||||
primaryKeyColumn: primaryKeyName, // 🆕 Primary Key 컬럼명 전달
|
||||
...(groupByColumns.length > 0 && {
|
||||
groupByColumns: JSON.stringify(groupByColumns),
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
);
|
||||
}),
|
||||
);
|
||||
|
||||
console.log("✅ [SplitPanel] openScreenModal 이벤트 발생:", {
|
||||
screenId: modalScreenId,
|
||||
editId: primaryKeyValue,
|
||||
tableName: rightTableName,
|
||||
primaryKeyColumn: primaryKeyName,
|
||||
groupByColumns: groupByColumns.length > 0 ? JSON.stringify(groupByColumns) : "없음",
|
||||
});
|
||||
console.log("✅ [SplitPanel] openScreenModal 이벤트 발생:", {
|
||||
screenId: modalScreenId,
|
||||
editId: primaryKeyValue,
|
||||
tableName: currentTableName,
|
||||
primaryKeyColumn: primaryKeyName,
|
||||
groupByColumns: groupByColumns.length > 0 ? JSON.stringify(groupByColumns) : "없음",
|
||||
});
|
||||
|
||||
return;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 기존 자동 편집 모드 (인라인 편집 모달)
|
||||
setEditModalPanel(panel);
|
||||
setEditModalItem(item);
|
||||
setEditModalFormData({ ...item });
|
||||
|
||||
// 🔧 우측 패널(추가탭 포함) 수정 시 selectedLeftItem의 FK 값 병합
|
||||
let mergedItem = { ...item };
|
||||
if (panel === "right" && selectedLeftItem) {
|
||||
// 현재 활성 탭의 relation 설정 가져오기
|
||||
const currentTabConfig =
|
||||
activeTabIndex === 0
|
||||
? componentConfig.rightPanel
|
||||
: componentConfig.rightPanel?.additionalTabs?.[activeTabIndex - 1];
|
||||
|
||||
const relationKeys = currentTabConfig?.relation?.keys;
|
||||
const leftColumn = currentTabConfig?.relation?.leftColumn;
|
||||
const rightColumn = currentTabConfig?.relation?.foreignKey || currentTabConfig?.relation?.rightColumn;
|
||||
|
||||
if (relationKeys && relationKeys.length > 0) {
|
||||
// 복합키인 경우
|
||||
relationKeys.forEach((key: any) => {
|
||||
if (key.leftColumn && key.rightColumn && selectedLeftItem[key.leftColumn] !== undefined) {
|
||||
// item에 해당 FK 값이 없거나 빈 값이면 selectedLeftItem에서 가져옴
|
||||
if (mergedItem[key.rightColumn] === undefined || mergedItem[key.rightColumn] === null || mergedItem[key.rightColumn] === "") {
|
||||
mergedItem[key.rightColumn] = selectedLeftItem[key.leftColumn];
|
||||
}
|
||||
}
|
||||
});
|
||||
} else if (leftColumn && rightColumn) {
|
||||
// 단일키인 경우
|
||||
if (selectedLeftItem[leftColumn] !== undefined) {
|
||||
if (mergedItem[rightColumn] === undefined || mergedItem[rightColumn] === null || mergedItem[rightColumn] === "") {
|
||||
mergedItem[rightColumn] = selectedLeftItem[leftColumn];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setEditModalFormData(mergedItem);
|
||||
setShowEditModal(true);
|
||||
},
|
||||
[componentConfig],
|
||||
[componentConfig, selectedLeftItem, activeTabIndex],
|
||||
);
|
||||
|
||||
// 수정 모달 저장
|
||||
|
||||
Reference in New Issue
Block a user