fix: 분할 패널 필터링 수정 및 디버깅 로그 제거
문제:
- 분할 패널에서 필터 입력 시 검색이 제대로 작동하지 않음
- 백엔드가 {value: '전자', operator: 'contains'} 형태를 처리하지 못함
원인:
- buildAdvancedSearchCondition이 필터 객체의 value 속성을 추출하지 않음
- 객체를 직접 문자열로 변환하여 '[object Object]'로 검색됨
해결:
1. tableManagementService.buildAdvancedSearchCondition 수정:
- {value, operator} 형태의 필터 객체 감지
- actualValue 추출 및 operator 처리
- 모든 웹타입 케이스에 actualValue 전달
2. 프론트엔드 디버깅 로그 제거:
- SplitPanelLayoutComponent의 console.log 제거
- 필터, 컬럼 가시성, API 호출 로그 정리
테스트 필요:
- 분할 패널에서 필터 입력 → 정상 검색 확인
- 텍스트, 날짜, 숫자, 코드 타입 필터 동작 확인
This commit is contained in:
parent
7b84a81a96
commit
77faba7e77
|
|
@ -1069,12 +1069,28 @@ export class TableManagementService {
|
|||
paramCount: number;
|
||||
} | null> {
|
||||
try {
|
||||
// 🔧 {value, operator} 형태의 필터 객체 처리
|
||||
let actualValue = value;
|
||||
let operator = "contains"; // 기본값
|
||||
|
||||
if (typeof value === "object" && value !== null && "value" in value) {
|
||||
actualValue = value.value;
|
||||
operator = value.operator || "contains";
|
||||
|
||||
logger.info("🔍 필터 객체 처리:", {
|
||||
columnName,
|
||||
originalValue: value,
|
||||
actualValue,
|
||||
operator,
|
||||
});
|
||||
}
|
||||
|
||||
// "__ALL__" 값이거나 빈 값이면 필터 조건을 적용하지 않음
|
||||
if (
|
||||
value === "__ALL__" ||
|
||||
value === "" ||
|
||||
value === null ||
|
||||
value === undefined
|
||||
actualValue === "__ALL__" ||
|
||||
actualValue === "" ||
|
||||
actualValue === null ||
|
||||
actualValue === undefined
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
|
@ -1083,12 +1099,22 @@ export class TableManagementService {
|
|||
const columnInfo = await this.getColumnWebTypeInfo(tableName, columnName);
|
||||
|
||||
if (!columnInfo) {
|
||||
// 컬럼 정보가 없으면 기본 문자열 검색
|
||||
return {
|
||||
whereClause: `${columnName}::text ILIKE $${paramIndex}`,
|
||||
values: [`%${value}%`],
|
||||
paramCount: 1,
|
||||
};
|
||||
// 컬럼 정보가 없으면 operator에 따른 기본 검색
|
||||
switch (operator) {
|
||||
case "equals":
|
||||
return {
|
||||
whereClause: `${columnName}::text = $${paramIndex}`,
|
||||
values: [actualValue],
|
||||
paramCount: 1,
|
||||
};
|
||||
case "contains":
|
||||
default:
|
||||
return {
|
||||
whereClause: `${columnName}::text ILIKE $${paramIndex}`,
|
||||
values: [`%${actualValue}%`],
|
||||
paramCount: 1,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const webType = columnInfo.webType;
|
||||
|
|
@ -1097,17 +1123,17 @@ export class TableManagementService {
|
|||
switch (webType) {
|
||||
case "date":
|
||||
case "datetime":
|
||||
return this.buildDateRangeCondition(columnName, value, paramIndex);
|
||||
return this.buildDateRangeCondition(columnName, actualValue, paramIndex);
|
||||
|
||||
case "number":
|
||||
case "decimal":
|
||||
return this.buildNumberRangeCondition(columnName, value, paramIndex);
|
||||
return this.buildNumberRangeCondition(columnName, actualValue, paramIndex);
|
||||
|
||||
case "code":
|
||||
return await this.buildCodeSearchCondition(
|
||||
tableName,
|
||||
columnName,
|
||||
value,
|
||||
actualValue,
|
||||
paramIndex
|
||||
);
|
||||
|
||||
|
|
@ -1115,15 +1141,15 @@ export class TableManagementService {
|
|||
return await this.buildEntitySearchCondition(
|
||||
tableName,
|
||||
columnName,
|
||||
value,
|
||||
actualValue,
|
||||
paramIndex
|
||||
);
|
||||
|
||||
default:
|
||||
// 기본 문자열 검색
|
||||
// 기본 문자열 검색 (actualValue 사용)
|
||||
return {
|
||||
whereClause: `${columnName}::text ILIKE $${paramIndex}`,
|
||||
values: [`%${value}%`],
|
||||
values: [`%${actualValue}%`],
|
||||
paramCount: 1,
|
||||
};
|
||||
}
|
||||
|
|
@ -1133,9 +1159,14 @@ export class TableManagementService {
|
|||
error
|
||||
);
|
||||
// 오류 시 기본 검색으로 폴백
|
||||
let fallbackValue = value;
|
||||
if (typeof value === "object" && value !== null && "value" in value) {
|
||||
fallbackValue = value.value;
|
||||
}
|
||||
|
||||
return {
|
||||
whereClause: `${columnName}::text ILIKE $${paramIndex}`,
|
||||
values: [`%${value}%`],
|
||||
values: [`%${fallbackValue}%`],
|
||||
paramCount: 1,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -185,11 +185,6 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
|||
// 🔄 컬럼 가시성 및 순서 처리
|
||||
const visibleLeftColumns = useMemo(() => {
|
||||
const displayColumns = componentConfig.leftPanel?.columns || [];
|
||||
console.log("🔍 [분할패널] visibleLeftColumns 계산:", {
|
||||
displayColumns: displayColumns.length,
|
||||
leftColumnVisibility: leftColumnVisibility.length,
|
||||
leftColumnOrder: leftColumnOrder.length,
|
||||
});
|
||||
|
||||
if (displayColumns.length === 0) return [];
|
||||
|
||||
|
|
@ -202,7 +197,6 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
|||
const colName = typeof col === 'string' ? col : (col.name || col.columnName);
|
||||
return visibilityMap.get(colName) !== false;
|
||||
});
|
||||
console.log("✅ [분할패널] 가시성 적용 후:", columns.length);
|
||||
}
|
||||
|
||||
// 🔧 컬럼 순서 적용
|
||||
|
|
@ -215,7 +209,6 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
|||
const bIndex = orderMap.get(bName) ?? 999;
|
||||
return aIndex - bIndex;
|
||||
});
|
||||
console.log("✅ [분할패널] 순서 적용 후:", columns.map((c: any) => typeof c === 'string' ? c : (c.name || c.columnName)));
|
||||
}
|
||||
|
||||
return columns;
|
||||
|
|
@ -258,11 +251,6 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
|||
// 🎯 필터 조건을 API에 전달 (entityJoinApi 사용)
|
||||
const filters = Object.keys(searchValues).length > 0 ? searchValues : undefined;
|
||||
|
||||
console.log("📡 [분할패널] API 호출 시작:", {
|
||||
tableName: leftTableName,
|
||||
filters,
|
||||
searchValues,
|
||||
});
|
||||
|
||||
const result = await entityJoinApi.getTableDataWithJoins(leftTableName, {
|
||||
page: 1,
|
||||
|
|
@ -271,11 +259,6 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
|||
enableEntityJoin: true, // 엔티티 조인 활성화
|
||||
});
|
||||
|
||||
console.log("📡 [분할패널] API 응답:", {
|
||||
success: result.success,
|
||||
dataLength: result.data?.length || 0,
|
||||
totalItems: result.totalItems,
|
||||
});
|
||||
|
||||
// 가나다순 정렬 (좌측 패널의 표시 컬럼 기준)
|
||||
const leftColumn = componentConfig.rightPanel?.relation?.leftColumn;
|
||||
|
|
@ -946,12 +929,6 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
|||
// 🔧 컬럼 가시성 변경 시 localStorage에 저장 및 순서 업데이트
|
||||
useEffect(() => {
|
||||
const leftTableName = componentConfig.leftPanel?.tableName;
|
||||
console.log("🔍 [분할패널] 컬럼 가시성 변경 감지:", {
|
||||
leftColumnVisibility: leftColumnVisibility.length,
|
||||
leftTableName,
|
||||
currentUserId,
|
||||
visibility: leftColumnVisibility,
|
||||
});
|
||||
|
||||
if (leftColumnVisibility.length > 0 && leftTableName && currentUserId) {
|
||||
// 순서 업데이트
|
||||
|
|
@ -959,13 +936,11 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
|||
.map((cv) => cv.columnName)
|
||||
.filter((name) => name !== "__checkbox__"); // 체크박스 제외
|
||||
|
||||
console.log("✅ [분할패널] 컬럼 순서 업데이트:", newOrder);
|
||||
setLeftColumnOrder(newOrder);
|
||||
|
||||
// localStorage에 저장
|
||||
const storageKey = `table_column_visibility_${leftTableName}_${currentUserId}`;
|
||||
localStorage.setItem(storageKey, JSON.stringify(leftColumnVisibility));
|
||||
console.log("💾 [분할패널] localStorage 저장:", storageKey);
|
||||
}
|
||||
}, [leftColumnVisibility, componentConfig.leftPanel?.tableName, currentUserId]);
|
||||
|
||||
|
|
@ -979,16 +954,7 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
|
|||
|
||||
// 🔄 필터 변경 시 데이터 다시 로드
|
||||
useEffect(() => {
|
||||
console.log("🔍 [분할패널] 필터 변경 감지:", {
|
||||
leftFilters: leftFilters.length,
|
||||
filters: leftFilters,
|
||||
isDesignMode,
|
||||
autoLoad: componentConfig.autoLoad,
|
||||
searchValues,
|
||||
});
|
||||
|
||||
if (!isDesignMode && componentConfig.autoLoad !== false) {
|
||||
console.log("✅ [분할패널] loadLeftData 호출 (필터 변경)");
|
||||
loadLeftData();
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
|
|
|
|||
Loading…
Reference in New Issue