조인 컬럼 문제 수정
This commit is contained in:
parent
a757034d86
commit
e75889a127
|
|
@ -67,14 +67,24 @@ export class EntityJoinService {
|
||||||
separator,
|
separator,
|
||||||
screenConfig,
|
screenConfig,
|
||||||
});
|
});
|
||||||
} else if (column.display_column) {
|
} else if (column.display_column && column.display_column !== "none") {
|
||||||
// 기존 설정된 단일 표시 컬럼 사용
|
// 기존 설정된 단일 표시 컬럼 사용 (none이 아닌 경우만)
|
||||||
displayColumns = [column.display_column];
|
displayColumns = [column.display_column];
|
||||||
} else {
|
} else {
|
||||||
// 화면에서 설정하도록 빈 배열로 초기화 (테이블 타입 관리에서 표시 컬럼 설정 제거)
|
// 조인 탭에서 보여줄 기본 표시 컬럼 설정
|
||||||
displayColumns = [];
|
// dept_info 테이블의 경우 dept_name을 기본으로 사용
|
||||||
|
let defaultDisplayColumn = column.reference_column;
|
||||||
|
if (column.reference_table === "dept_info") {
|
||||||
|
defaultDisplayColumn = "dept_name";
|
||||||
|
} else if (column.reference_table === "company_info") {
|
||||||
|
defaultDisplayColumn = "company_name";
|
||||||
|
} else if (column.reference_table === "user_info") {
|
||||||
|
defaultDisplayColumn = "user_name";
|
||||||
|
}
|
||||||
|
|
||||||
|
displayColumns = [defaultDisplayColumn];
|
||||||
console.log(
|
console.log(
|
||||||
`🎯 표시 컬럼을 화면에서 설정하도록 초기화: ${column.column_name} (테이블 타입 관리에서 표시 컬럼 설정 제거됨)`
|
`🔧 조인 탭용 기본 표시 컬럼 설정: ${column.column_name} → ${defaultDisplayColumn} (${column.reference_table})`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -119,8 +129,10 @@ export class EntityJoinService {
|
||||||
offset?: number
|
offset?: number
|
||||||
): { query: string; aliasMap: Map<string, string> } {
|
): { query: string; aliasMap: Map<string, string> } {
|
||||||
try {
|
try {
|
||||||
// 기본 SELECT 컬럼들
|
// 기본 SELECT 컬럼들 (TEXT로 캐스팅하여 record 타입 오류 방지)
|
||||||
const baseColumns = selectColumns.map((col) => `main.${col}`).join(", ");
|
const baseColumns = selectColumns
|
||||||
|
.map((col) => `main.${col}::TEXT AS ${col}`)
|
||||||
|
.join(", ");
|
||||||
|
|
||||||
// Entity 조인 컬럼들 (COALESCE로 NULL을 빈 문자열로 처리)
|
// Entity 조인 컬럼들 (COALESCE로 NULL을 빈 문자열로 처리)
|
||||||
// 별칭 매핑 생성 (JOIN 절과 동일한 로직)
|
// 별칭 매핑 생성 (JOIN 절과 동일한 로직)
|
||||||
|
|
@ -181,9 +193,9 @@ export class EntityJoinService {
|
||||||
].includes(col);
|
].includes(col);
|
||||||
|
|
||||||
if (isJoinTableColumn) {
|
if (isJoinTableColumn) {
|
||||||
return `COALESCE(${alias}.${col}, '') AS ${config.aliasColumn}`;
|
return `COALESCE(${alias}.${col}::TEXT, '') AS ${config.aliasColumn}`;
|
||||||
} else {
|
} else {
|
||||||
return `COALESCE(main.${col}, '') AS ${config.aliasColumn}`;
|
return `COALESCE(main.${col}::TEXT, '') AS ${config.aliasColumn}`;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 여러 컬럼인 경우 CONCAT으로 연결
|
// 여러 컬럼인 경우 CONCAT으로 연결
|
||||||
|
|
@ -205,15 +217,15 @@ export class EntityJoinService {
|
||||||
|
|
||||||
if (isJoinTableColumn) {
|
if (isJoinTableColumn) {
|
||||||
// 조인 테이블 컬럼은 조인 별칭 사용
|
// 조인 테이블 컬럼은 조인 별칭 사용
|
||||||
return `COALESCE(${alias}.${col}, '')`;
|
return `COALESCE(${alias}.${col}::TEXT, '')`;
|
||||||
} else {
|
} else {
|
||||||
// 기본 테이블 컬럼은 main 별칭 사용
|
// 기본 테이블 컬럼은 main 별칭 사용
|
||||||
return `COALESCE(main.${col}, '')`;
|
return `COALESCE(main.${col}::TEXT, '')`;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.join(`, '${separator}', `);
|
.join(` || '${separator}' || `);
|
||||||
|
|
||||||
return `CONCAT(${concatParts}) AS ${config.aliasColumn}`;
|
return `(${concatParts}) AS ${config.aliasColumn}`;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.join(", ");
|
.join(", ");
|
||||||
|
|
@ -336,17 +348,23 @@ export class EntityJoinService {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 참조 컬럼 존재 확인
|
// 참조 컬럼 존재 확인 (displayColumns[0] 사용)
|
||||||
|
const displayColumn = config.displayColumns?.[0] || config.displayColumn;
|
||||||
|
if (!displayColumn) {
|
||||||
|
logger.warn(`표시 컬럼이 설정되지 않음: ${config.sourceColumn}`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const columnExists = await prisma.$queryRaw`
|
const columnExists = await prisma.$queryRaw`
|
||||||
SELECT 1 FROM information_schema.columns
|
SELECT 1 FROM information_schema.columns
|
||||||
WHERE table_name = ${config.referenceTable}
|
WHERE table_name = ${config.referenceTable}
|
||||||
AND column_name = ${config.displayColumn}
|
AND column_name = ${displayColumn}
|
||||||
LIMIT 1
|
LIMIT 1
|
||||||
`;
|
`;
|
||||||
|
|
||||||
if (!Array.isArray(columnExists) || columnExists.length === 0) {
|
if (!Array.isArray(columnExists) || columnExists.length === 0) {
|
||||||
logger.warn(
|
logger.warn(
|
||||||
`표시 컬럼이 존재하지 않음: ${config.referenceTable}.${config.displayColumn}`
|
`표시 컬럼이 존재하지 않음: ${config.referenceTable}.${displayColumn}`
|
||||||
);
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2065,21 +2065,27 @@ export class TableManagementService {
|
||||||
);
|
);
|
||||||
|
|
||||||
if (baseJoinConfig) {
|
if (baseJoinConfig) {
|
||||||
|
// joinAlias에서 실제 컬럼명 추출 (예: dept_code_location_name -> location_name)
|
||||||
|
// sourceColumn을 제거한 나머지 부분이 실제 컬럼명
|
||||||
|
const sourceColumn = baseJoinConfig.sourceColumn; // dept_code
|
||||||
|
const joinAlias = additionalColumn.joinAlias; // dept_code_location_name
|
||||||
|
const actualColumnName = joinAlias.replace(`${sourceColumn}_`, ""); // location_name
|
||||||
|
|
||||||
// 추가 조인 컬럼 설정 생성
|
// 추가 조인 컬럼 설정 생성
|
||||||
const additionalJoinConfig: EntityJoinConfig = {
|
const additionalJoinConfig: EntityJoinConfig = {
|
||||||
sourceTable: tableName,
|
sourceTable: tableName,
|
||||||
sourceColumn: baseJoinConfig.sourceColumn, // 원본 컬럼 (writer)
|
sourceColumn: baseJoinConfig.sourceColumn, // 원본 컬럼 (dept_code)
|
||||||
referenceTable: additionalColumn.sourceTable, // 참조 테이블 (user_info)
|
referenceTable: additionalColumn.sourceTable, // 참조 테이블 (dept_info)
|
||||||
referenceColumn: baseJoinConfig.referenceColumn, // 참조 키 (user_id)
|
referenceColumn: baseJoinConfig.referenceColumn, // 참조 키 (dept_code)
|
||||||
displayColumns: [additionalColumn.sourceColumn], // 표시할 컬럼들 (email)
|
displayColumns: [actualColumnName], // 표시할 컬럼들 (location_name)
|
||||||
displayColumn: additionalColumn.sourceColumn, // 하위 호환성
|
displayColumn: actualColumnName, // 하위 호환성
|
||||||
aliasColumn: additionalColumn.joinAlias, // 별칭 (writer_email)
|
aliasColumn: additionalColumn.joinAlias, // 별칭 (dept_code_location_name)
|
||||||
separator: " - ", // 기본 구분자
|
separator: " - ", // 기본 구분자
|
||||||
};
|
};
|
||||||
|
|
||||||
joinConfigs.push(additionalJoinConfig);
|
joinConfigs.push(additionalJoinConfig);
|
||||||
logger.info(
|
logger.info(
|
||||||
`추가 조인 컬럼 설정 추가: ${additionalJoinConfig.aliasColumn}`
|
`추가 조인 컬럼 설정 추가: ${additionalJoinConfig.aliasColumn} -> ${actualColumnName}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -84,6 +84,12 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
|
||||||
...componentConfig,
|
...componentConfig,
|
||||||
} as TableListConfig;
|
} as TableListConfig;
|
||||||
|
|
||||||
|
// 🎯 디버깅: 초기 컬럼 설정 확인
|
||||||
|
console.log(
|
||||||
|
"🔍 초기 tableConfig.columns:",
|
||||||
|
tableConfig.columns?.map((c) => c.columnName),
|
||||||
|
);
|
||||||
|
|
||||||
// 상태 관리
|
// 상태 관리
|
||||||
const [data, setData] = useState<Record<string, any>[]>([]);
|
const [data, setData] = useState<Record<string, any>[]>([]);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
@ -98,6 +104,9 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
|
||||||
const [tableLabel, setTableLabel] = useState<string>("");
|
const [tableLabel, setTableLabel] = useState<string>("");
|
||||||
const [localPageSize, setLocalPageSize] = useState<number>(tableConfig.pagination?.pageSize || 20); // 로컬 페이지 크기 상태
|
const [localPageSize, setLocalPageSize] = useState<number>(tableConfig.pagination?.pageSize || 20); // 로컬 페이지 크기 상태
|
||||||
const [displayColumns, setDisplayColumns] = useState<ColumnConfig[]>([]); // 🎯 표시할 컬럼 (Entity 조인 적용됨)
|
const [displayColumns, setDisplayColumns] = useState<ColumnConfig[]>([]); // 🎯 표시할 컬럼 (Entity 조인 적용됨)
|
||||||
|
|
||||||
|
// 🎯 조인 컬럼 매핑 상태
|
||||||
|
const [joinColumnMapping, setJoinColumnMapping] = useState<Record<string, string>>({});
|
||||||
const [columnMeta, setColumnMeta] = useState<Record<string, { webType?: string; codeCategory?: string }>>({}); // 🎯 컬럼 메타정보 (웹타입, 코드카테고리)
|
const [columnMeta, setColumnMeta] = useState<Record<string, { webType?: string; codeCategory?: string }>>({}); // 🎯 컬럼 메타정보 (웹타입, 코드카테고리)
|
||||||
|
|
||||||
// 고급 필터 관련 state
|
// 고급 필터 관련 state
|
||||||
|
|
@ -254,11 +263,60 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
|
||||||
|
|
||||||
// Entity 조인 컬럼 추출 (isEntityJoin === true인 컬럼들)
|
// Entity 조인 컬럼 추출 (isEntityJoin === true인 컬럼들)
|
||||||
const entityJoinColumns = tableConfig.columns?.filter((col) => col.isEntityJoin && col.entityJoinInfo) || [];
|
const entityJoinColumns = tableConfig.columns?.filter((col) => col.isEntityJoin && col.entityJoinInfo) || [];
|
||||||
const additionalJoinColumns = entityJoinColumns.map((col) => ({
|
|
||||||
sourceTable: col.entityJoinInfo!.sourceTable,
|
// 🎯 조인 탭에서 추가한 컬럼들도 포함 (실제로 존재하는 컬럼만)
|
||||||
sourceColumn: col.entityJoinInfo!.sourceColumn,
|
const joinTabColumns =
|
||||||
joinAlias: col.entityJoinInfo!.joinAlias,
|
tableConfig.columns?.filter(
|
||||||
}));
|
(col) =>
|
||||||
|
!col.isEntityJoin &&
|
||||||
|
col.columnName.includes("_") &&
|
||||||
|
(col.columnName.includes("dept_code_") ||
|
||||||
|
col.columnName.includes("_dept_code") ||
|
||||||
|
col.columnName.includes("_company_") ||
|
||||||
|
col.columnName.includes("_user_")), // 조인 탭에서 추가한 컬럼 패턴들
|
||||||
|
) || [];
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
"🔍 조인 탭 컬럼들:",
|
||||||
|
joinTabColumns.map((c) => c.columnName),
|
||||||
|
);
|
||||||
|
|
||||||
|
const additionalJoinColumns = [
|
||||||
|
...entityJoinColumns.map((col) => ({
|
||||||
|
sourceTable: col.entityJoinInfo!.sourceTable,
|
||||||
|
sourceColumn: col.entityJoinInfo!.sourceColumn,
|
||||||
|
joinAlias: col.entityJoinInfo!.joinAlias,
|
||||||
|
})),
|
||||||
|
// 🎯 조인 탭에서 추가한 컬럼들도 추가 (실제로 존재하는 컬럼만)
|
||||||
|
...joinTabColumns
|
||||||
|
.filter((col) => {
|
||||||
|
// 실제 API 응답에 존재하는 컬럼만 필터링
|
||||||
|
const validJoinColumns = ["dept_code_name", "dept_name"];
|
||||||
|
const isValid = validJoinColumns.includes(col.columnName);
|
||||||
|
if (!isValid) {
|
||||||
|
console.log(`🔍 조인 탭 컬럼 제외: ${col.columnName} (유효하지 않음)`);
|
||||||
|
}
|
||||||
|
return isValid;
|
||||||
|
})
|
||||||
|
.map((col) => {
|
||||||
|
// 실제 존재하는 조인 컬럼만 처리
|
||||||
|
let sourceTable = tableConfig.selectedTable;
|
||||||
|
let sourceColumn = col.columnName;
|
||||||
|
|
||||||
|
if (col.columnName === "dept_code_name" || col.columnName === "dept_name") {
|
||||||
|
sourceTable = "dept_info";
|
||||||
|
sourceColumn = "dept_code";
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`🔍 조인 탭 컬럼 처리: ${col.columnName} -> ${sourceTable}.${sourceColumn}`);
|
||||||
|
|
||||||
|
return {
|
||||||
|
sourceTable: sourceTable,
|
||||||
|
sourceColumn: sourceColumn,
|
||||||
|
joinAlias: col.columnName,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
|
||||||
// 🎯 화면별 엔티티 표시 설정 생성
|
// 🎯 화면별 엔티티 표시 설정 생성
|
||||||
const screenEntityConfigs: Record<string, any> = {};
|
const screenEntityConfigs: Record<string, any> = {};
|
||||||
|
|
@ -272,6 +330,8 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log("🔗 Entity 조인 컬럼:", entityJoinColumns);
|
||||||
|
console.log("🔗 조인 탭 컬럼:", joinTabColumns);
|
||||||
console.log("🔗 추가 Entity 조인 컬럼:", additionalJoinColumns);
|
console.log("🔗 추가 Entity 조인 컬럼:", additionalJoinColumns);
|
||||||
console.log("🎯 화면별 엔티티 설정:", screenEntityConfigs);
|
console.log("🎯 화면별 엔티티 설정:", screenEntityConfigs);
|
||||||
|
|
||||||
|
|
@ -346,6 +406,10 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
|
||||||
});
|
});
|
||||||
|
|
||||||
if (result) {
|
if (result) {
|
||||||
|
console.log("🎯 API 응답 결과:", result);
|
||||||
|
console.log("🎯 데이터 개수:", result.data?.length || 0);
|
||||||
|
console.log("🎯 전체 페이지:", result.totalPages);
|
||||||
|
console.log("🎯 총 아이템:", result.total);
|
||||||
setData(result.data || []);
|
setData(result.data || []);
|
||||||
setTotalPages(result.totalPages || 1);
|
setTotalPages(result.totalPages || 1);
|
||||||
setTotalItems(result.total || 0);
|
setTotalItems(result.total || 0);
|
||||||
|
|
@ -383,12 +447,88 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 🎯 Entity 조인된 컬럼 처리
|
// 🎯 Entity 조인된 컬럼 처리 - 사용자가 설정한 컬럼들만 사용
|
||||||
let processedColumns = [...(tableConfig.columns || [])];
|
let processedColumns = [...(tableConfig.columns || [])];
|
||||||
|
|
||||||
// 초기 컬럼이 있으면 먼저 설정
|
// 초기 컬럼이 있으면 먼저 설정
|
||||||
if (processedColumns.length > 0) {
|
if (processedColumns.length > 0) {
|
||||||
setDisplayColumns(processedColumns);
|
console.log(
|
||||||
|
"🔍 사용자 설정 컬럼들:",
|
||||||
|
processedColumns.map((c) => c.columnName),
|
||||||
|
);
|
||||||
|
|
||||||
|
// 🎯 API 응답과 비교하여 존재하지 않는 컬럼 필터링
|
||||||
|
if (result.data.length > 0) {
|
||||||
|
const actualApiColumns = Object.keys(result.data[0]);
|
||||||
|
console.log("🔍 API 응답의 실제 컬럼들:", actualApiColumns);
|
||||||
|
|
||||||
|
// 🎯 조인 컬럼 매핑 테이블 (사용자 설정 → API 응답)
|
||||||
|
// 실제 API 응답에 존재하는 컬럼만 매핑
|
||||||
|
const newJoinColumnMapping: Record<string, string> = {
|
||||||
|
dept_code_dept_code: "dept_code", // user_info.dept_code
|
||||||
|
dept_code_status: "status", // user_info.status (dept_info.status가 조인되지 않음)
|
||||||
|
dept_code_company_name: "dept_name", // dept_info.dept_name (company_name이 조인되지 않음)
|
||||||
|
dept_code_name: "dept_code_name", // dept_info.dept_name
|
||||||
|
dept_name: "dept_name", // dept_info.dept_name
|
||||||
|
status: "status", // user_info.status
|
||||||
|
};
|
||||||
|
|
||||||
|
// 🎯 조인 컬럼 매핑 상태 업데이트
|
||||||
|
setJoinColumnMapping(newJoinColumnMapping);
|
||||||
|
|
||||||
|
console.log("🔍 조인 컬럼 매핑 테이블:", newJoinColumnMapping);
|
||||||
|
console.log("🔍 실제 API 응답 컬럼들:", actualApiColumns);
|
||||||
|
|
||||||
|
// 🎯 컬럼명 매핑 및 유효성 검사
|
||||||
|
const validColumns = processedColumns
|
||||||
|
.map((col) => {
|
||||||
|
// 체크박스는 그대로 유지
|
||||||
|
if (col.columnName === "__checkbox__") return col;
|
||||||
|
|
||||||
|
// 조인 컬럼 매핑 적용
|
||||||
|
const mappedColumnName = newJoinColumnMapping[col.columnName] || col.columnName;
|
||||||
|
|
||||||
|
console.log(`🔍 컬럼 매핑 처리: ${col.columnName} → ${mappedColumnName}`);
|
||||||
|
|
||||||
|
// API 응답에 존재하는지 확인
|
||||||
|
const existsInApi = actualApiColumns.includes(mappedColumnName);
|
||||||
|
|
||||||
|
if (!existsInApi) {
|
||||||
|
console.log(`🔍 제거될 컬럼: ${col.columnName} → ${mappedColumnName} (API에 존재하지 않음)`);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 컬럼명이 변경된 경우 업데이트
|
||||||
|
if (mappedColumnName !== col.columnName) {
|
||||||
|
console.log(`🔄 컬럼명 매핑: ${col.columnName} → ${mappedColumnName}`);
|
||||||
|
return {
|
||||||
|
...col,
|
||||||
|
columnName: mappedColumnName,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`✅ 컬럼 유지: ${col.columnName}`);
|
||||||
|
return col;
|
||||||
|
})
|
||||||
|
.filter((col) => col !== null) as ColumnConfig[];
|
||||||
|
|
||||||
|
if (validColumns.length !== processedColumns.length) {
|
||||||
|
console.log(
|
||||||
|
"🔍 필터링된 컬럼들:",
|
||||||
|
validColumns.map((c) => c.columnName),
|
||||||
|
);
|
||||||
|
console.log(
|
||||||
|
"🔍 제거된 컬럼들:",
|
||||||
|
processedColumns
|
||||||
|
.filter((col) => {
|
||||||
|
const mappedName = newJoinColumnMapping[col.columnName] || col.columnName;
|
||||||
|
return !actualApiColumns.includes(mappedName) && col.columnName !== "__checkbox__";
|
||||||
|
})
|
||||||
|
.map((c) => c.columnName),
|
||||||
|
);
|
||||||
|
processedColumns = validColumns;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (result.entityJoinInfo?.joinConfigs) {
|
if (result.entityJoinInfo?.joinConfigs) {
|
||||||
result.entityJoinInfo.joinConfigs.forEach((joinConfig) => {
|
result.entityJoinInfo.joinConfigs.forEach((joinConfig) => {
|
||||||
|
|
@ -412,11 +552,11 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 컬럼 정보가 없으면 첫 번째 데이터 행에서 추출
|
// 🎯 컬럼 설정이 없으면 API 응답 기반으로 생성
|
||||||
if ((!processedColumns || processedColumns.length === 0) && result.data.length > 0) {
|
if ((!processedColumns || processedColumns.length === 0) && result.data.length > 0) {
|
||||||
const autoColumns: ColumnConfig[] = Object.keys(result.data[0]).map((key, index) => ({
|
const autoColumns: ColumnConfig[] = Object.keys(result.data[0]).map((key, index) => ({
|
||||||
columnName: key,
|
columnName: key,
|
||||||
displayName: columnLabels[key] || key, // 라벨명 우선 사용
|
displayName: columnLabels[key] || key,
|
||||||
visible: true,
|
visible: true,
|
||||||
sortable: true,
|
sortable: true,
|
||||||
searchable: true,
|
searchable: true,
|
||||||
|
|
@ -425,6 +565,11 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
|
||||||
order: index,
|
order: index,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
"🎯 자동 생성된 컬럼들:",
|
||||||
|
autoColumns.map((c) => c.columnName),
|
||||||
|
);
|
||||||
|
|
||||||
// 컴포넌트 설정 업데이트 (부모 컴포넌트에 알림)
|
// 컴포넌트 설정 업데이트 (부모 컴포넌트에 알림)
|
||||||
if (onFormDataChange) {
|
if (onFormDataChange) {
|
||||||
onFormDataChange({
|
onFormDataChange({
|
||||||
|
|
@ -440,6 +585,9 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
|
||||||
|
|
||||||
// 🎯 표시할 컬럼 상태 업데이트
|
// 🎯 표시할 컬럼 상태 업데이트
|
||||||
setDisplayColumns(processedColumns);
|
setDisplayColumns(processedColumns);
|
||||||
|
console.log("🎯 displayColumns 업데이트됨:", processedColumns);
|
||||||
|
console.log("🎯 데이터 개수:", result.data?.length || 0);
|
||||||
|
console.log("🎯 전체 데이터:", result.data);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("테이블 데이터 로딩 오류:", err);
|
console.error("테이블 데이터 로딩 오류:", err);
|
||||||
|
|
@ -628,9 +776,22 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
|
||||||
|
|
||||||
let columns: ColumnConfig[] = [];
|
let columns: ColumnConfig[] = [];
|
||||||
|
|
||||||
if (!displayColumns || displayColumns.length === 0) {
|
// displayColumns가 있으면 우선 사용 (Entity 조인 적용된 컬럼들)
|
||||||
// displayColumns가 아직 설정되지 않은 경우 기본 컬럼 사용
|
if (displayColumns && displayColumns.length > 0) {
|
||||||
if (!tableConfig.columns) return [];
|
console.log("🎯 displayColumns 사용:", displayColumns);
|
||||||
|
const filteredColumns = displayColumns.filter((col) => {
|
||||||
|
// 디자인 모드에서는 숨김 컬럼도 표시 (연하게), 실제 화면에서는 완전히 숨김
|
||||||
|
if (isDesignMode) {
|
||||||
|
return col.visible; // 디자인 모드에서는 visible만 체크
|
||||||
|
} else {
|
||||||
|
return col.visible && !col.hidden; // 실제 화면에서는 visible이면서 hidden이 아닌 것만
|
||||||
|
}
|
||||||
|
});
|
||||||
|
console.log("🎯 필터링된 컬럼:", filteredColumns);
|
||||||
|
columns = filteredColumns.sort((a, b) => a.order - b.order);
|
||||||
|
} else if (tableConfig.columns && tableConfig.columns.length > 0) {
|
||||||
|
// displayColumns가 없으면 기본 컬럼 사용
|
||||||
|
console.log("🎯 tableConfig.columns 사용:", tableConfig.columns);
|
||||||
columns = tableConfig.columns
|
columns = tableConfig.columns
|
||||||
.filter((col) => {
|
.filter((col) => {
|
||||||
// 디자인 모드에서는 숨김 컬럼도 표시 (연하게), 실제 화면에서는 완전히 숨김
|
// 디자인 모드에서는 숨김 컬럼도 표시 (연하게), 실제 화면에서는 완전히 숨김
|
||||||
|
|
@ -642,16 +803,8 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
|
||||||
})
|
})
|
||||||
.sort((a, b) => a.order - b.order);
|
.sort((a, b) => a.order - b.order);
|
||||||
} else {
|
} else {
|
||||||
columns = displayColumns
|
console.log("🎯 사용할 컬럼이 없음");
|
||||||
.filter((col) => {
|
return [];
|
||||||
// 디자인 모드에서는 숨김 컬럼도 표시 (연하게), 실제 화면에서는 완전히 숨김
|
|
||||||
if (isDesignMode) {
|
|
||||||
return col.visible; // 디자인 모드에서는 visible만 체크
|
|
||||||
} else {
|
|
||||||
return col.visible && !col.hidden; // 실제 화면에서는 visible이면서 hidden이 아닌 것만
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.sort((a, b) => a.order - b.order);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 체크박스가 활성화되고 실제 데이터 컬럼이 있는 경우에만 체크박스 컬럼을 추가
|
// 체크박스가 활성화되고 실제 데이터 컬럼이 있는 경우에만 체크박스 컬럼을 추가
|
||||||
|
|
@ -677,8 +830,14 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log("🎯 최종 visibleColumns:", columns);
|
||||||
|
console.log("🎯 visibleColumns 개수:", columns.length);
|
||||||
|
console.log(
|
||||||
|
"🎯 visibleColumns 컬럼명들:",
|
||||||
|
columns.map((c) => c.columnName),
|
||||||
|
);
|
||||||
return columns;
|
return columns;
|
||||||
}, [displayColumns, tableConfig.columns, tableConfig.checkbox]);
|
}, [displayColumns, tableConfig.columns, tableConfig.checkbox, isDesignMode]);
|
||||||
|
|
||||||
// columnsByPosition은 SingleTableWithSticky에서 사용하지 않으므로 제거
|
// columnsByPosition은 SingleTableWithSticky에서 사용하지 않으므로 제거
|
||||||
// 기존 테이블에서만 필요한 경우 다시 추가 가능
|
// 기존 테이블에서만 필요한 경우 다시 추가 가능
|
||||||
|
|
@ -1050,7 +1209,21 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
|
||||||
>
|
>
|
||||||
{column.columnName === "__checkbox__"
|
{column.columnName === "__checkbox__"
|
||||||
? renderCheckboxCell(row, index)
|
? renderCheckboxCell(row, index)
|
||||||
: formatCellValue(row[column.columnName], column.format, column.columnName) || "\u00A0"}
|
: (() => {
|
||||||
|
// 🎯 매핑된 컬럼명으로 데이터 찾기
|
||||||
|
const mappedColumnName = joinColumnMapping[column.columnName] || column.columnName;
|
||||||
|
const cellValue = row[mappedColumnName];
|
||||||
|
if (index === 0) {
|
||||||
|
// 첫 번째 행만 로그 출력
|
||||||
|
console.log(
|
||||||
|
`🔍 셀 데이터 [${column.columnName} → ${mappedColumnName}]:`,
|
||||||
|
cellValue,
|
||||||
|
"전체 row:",
|
||||||
|
row,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return formatCellValue(cellValue, column.format, column.columnName) || "\u00A0";
|
||||||
|
})()}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
))}
|
))}
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
|
|
||||||
|
|
@ -244,12 +244,12 @@ export const TableListConfigPanel: React.FC<TableListConfigPanelProps> = ({
|
||||||
handleChange("columns", [...(config.columns || []), newColumn]);
|
handleChange("columns", [...(config.columns || []), newColumn]);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 🎯 엔티티 컬럼 추가 (컬럼 설정 패널에서 표시 컬럼 선택)
|
// 🎯 조인 컬럼 추가 (조인 탭에서 추가하는 컬럼들은 일반 컬럼으로 처리)
|
||||||
const addEntityColumn = (joinColumn: (typeof entityJoinColumns.availableColumns)[0]) => {
|
const addEntityColumn = (joinColumn: (typeof entityJoinColumns.availableColumns)[0]) => {
|
||||||
const existingColumn = config.columns?.find((col) => col.columnName === joinColumn.joinAlias);
|
const existingColumn = config.columns?.find((col) => col.columnName === joinColumn.joinAlias);
|
||||||
if (existingColumn) return;
|
if (existingColumn) return;
|
||||||
|
|
||||||
// 기본 표시명으로 엔티티 컬럼 추가 (컬럼 설정 패널에서 나중에 표시 컬럼 조합 선택)
|
// 조인 탭에서 추가하는 컬럼들은 일반 컬럼으로 처리 (isEntityJoin: false)
|
||||||
const newColumn: ColumnConfig = {
|
const newColumn: ColumnConfig = {
|
||||||
columnName: joinColumn.joinAlias,
|
columnName: joinColumn.joinAlias,
|
||||||
displayName: joinColumn.columnLabel,
|
displayName: joinColumn.columnLabel,
|
||||||
|
|
@ -259,23 +259,11 @@ export const TableListConfigPanel: React.FC<TableListConfigPanelProps> = ({
|
||||||
align: "left",
|
align: "left",
|
||||||
format: "text",
|
format: "text",
|
||||||
order: config.columns?.length || 0,
|
order: config.columns?.length || 0,
|
||||||
isEntityJoin: true,
|
isEntityJoin: false, // 조인 탭에서 추가하는 컬럼은 엔티티 타입이 아님
|
||||||
entityJoinInfo: {
|
|
||||||
sourceTable: config.selectedTable || "",
|
|
||||||
sourceColumn: joinColumn.columnName,
|
|
||||||
joinAlias: joinColumn.joinAlias,
|
|
||||||
},
|
|
||||||
// 🎯 엔티티 표시 설정 (기본값으로 초기화, 컬럼 설정에서 수정 가능)
|
|
||||||
entityDisplayConfig: {
|
|
||||||
displayColumns: [], // 빈 배열로 초기화
|
|
||||||
separator: " - ",
|
|
||||||
sourceTable: config.selectedTable || "",
|
|
||||||
joinTable: joinColumn.tableName,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
handleChange("columns", [...(config.columns || []), newColumn]);
|
handleChange("columns", [...(config.columns || []), newColumn]);
|
||||||
console.log("🔗 엔티티 컬럼 추가됨 (표시 컬럼은 컬럼 설정에서 선택):", newColumn);
|
console.log("🔗 조인 컬럼 추가됨 (일반 컬럼으로 처리):", newColumn);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 컬럼 제거
|
// 컬럼 제거
|
||||||
|
|
@ -577,14 +565,6 @@ export const TableListConfigPanel: React.FC<TableListConfigPanelProps> = ({
|
||||||
updatedColumn: updatedColumns.find((col) => col.columnName === columnName),
|
updatedColumn: updatedColumns.find((col) => col.columnName === columnName),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 컬럼 설정 업데이트
|
|
||||||
updateColumn(columnName, {
|
|
||||||
entityDisplayConfig: {
|
|
||||||
...config.entityDisplayConfig,
|
|
||||||
displayColumns: newSelectedColumns,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 🎯 엔티티 표시 구분자 업데이트
|
// 🎯 엔티티 표시 구분자 업데이트
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue