fix: 엔티티 컬럼 표시 설정 문제 해결
- TableListComponent에서 엔티티 컬럼 라벨을 기준 테이블 라벨로 표시 - TableListConfigPanel에서 input_type 필드로 엔티티 컬럼 감지 - ScreenDesigner에서 컬럼 정보 로드 시 input_type 필드 포함 - UnifiedColumnInfo 타입에 input_type 필드 추가 - 엔티티 컬럼 감지 로직에 디버깅 로그 추가 이제 화면 편집기에서 엔티티 컬럼의 표시 컬럼 설정이 정상적으로 보여야 함
This commit is contained in:
@@ -194,10 +194,10 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
|
||||
|
||||
// Entity 타입인 경우
|
||||
if (column.webType === "entity") {
|
||||
// 백엔드에서 받은 displayColumnLabel을 사용하거나, 없으면 기본값 사용
|
||||
displayLabel = column.displayColumnLabel || column.displayColumn || `${column.columnName}_name`;
|
||||
// 우선 기준 테이블의 컬럼 라벨을 사용
|
||||
displayLabel = column.displayName || column.columnName;
|
||||
console.log(
|
||||
`🎯 Entity 조인 컬럼 라벨 설정: ${column.columnName} → "${displayLabel}" (${column.displayColumn || "기본값"})`,
|
||||
`🎯 Entity 조인 컬럼 라벨 설정: ${column.columnName} → "${displayLabel}" (기준 테이블 라벨 사용)`,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -62,12 +62,17 @@ export const TableListConfigPanel: React.FC<TableListConfigPanelProps> = ({
|
||||
const [loadingEntityJoins, setLoadingEntityJoins] = useState(false);
|
||||
|
||||
// 🎯 엔티티 컬럼 표시 설정을 위한 상태
|
||||
const [entityDisplayConfigs, setEntityDisplayConfigs] = useState<Record<string, {
|
||||
sourceColumns: Array<{ columnName: string; displayName: string; dataType: string }>;
|
||||
joinColumns: Array<{ columnName: string; displayName: string; dataType: string }>;
|
||||
selectedColumns: string[];
|
||||
separator: string;
|
||||
}>>({});
|
||||
const [entityDisplayConfigs, setEntityDisplayConfigs] = useState<
|
||||
Record<
|
||||
string,
|
||||
{
|
||||
sourceColumns: Array<{ columnName: string; displayName: string; dataType: string }>;
|
||||
joinColumns: Array<{ columnName: string; displayName: string; dataType: string }>;
|
||||
selectedColumns: string[];
|
||||
separator: string;
|
||||
}
|
||||
>
|
||||
>({});
|
||||
|
||||
// 화면 테이블명이 있으면 자동으로 설정
|
||||
useEffect(() => {
|
||||
@@ -284,6 +289,72 @@ export const TableListConfigPanel: React.FC<TableListConfigPanelProps> = ({
|
||||
handleChange("columns", updatedColumns);
|
||||
};
|
||||
|
||||
// 🎯 기존 컬럼들을 체크하여 엔티티 타입인 경우 isEntityJoin 플래그 설정
|
||||
useEffect(() => {
|
||||
console.log("🔍 엔티티 컬럼 감지 useEffect 실행:", {
|
||||
hasColumns: !!config.columns,
|
||||
columnsCount: config.columns?.length || 0,
|
||||
hasTableColumns: !!tableColumns,
|
||||
tableColumnsCount: tableColumns?.length || 0,
|
||||
selectedTable: config.selectedTable
|
||||
});
|
||||
|
||||
if (!config.columns || !tableColumns) {
|
||||
console.log("⚠️ 컬럼 또는 테이블 컬럼 정보가 없어서 엔티티 감지 스킵");
|
||||
return;
|
||||
}
|
||||
|
||||
const updatedColumns = config.columns.map((column) => {
|
||||
// 이미 isEntityJoin이 설정된 경우 스킵
|
||||
if (column.isEntityJoin) {
|
||||
console.log("✅ 이미 엔티티 플래그 설정됨:", column.columnName);
|
||||
return column;
|
||||
}
|
||||
|
||||
// 테이블 컬럼 정보에서 해당 컬럼 찾기
|
||||
const tableColumn = tableColumns.find((tc) => tc.column_name === column.columnName);
|
||||
console.log("🔍 컬럼 검색:", {
|
||||
columnName: column.columnName,
|
||||
found: !!tableColumn,
|
||||
inputType: tableColumn?.input_type,
|
||||
webType: tableColumn?.web_type
|
||||
});
|
||||
|
||||
// 엔티티 타입인 경우 isEntityJoin 플래그 설정 (input_type 또는 web_type 확인)
|
||||
if (tableColumn && (tableColumn.input_type === "entity" || tableColumn.web_type === "entity")) {
|
||||
console.log("🎯 엔티티 컬럼 감지 및 플래그 설정:", column.columnName);
|
||||
|
||||
return {
|
||||
...column,
|
||||
isEntityJoin: true,
|
||||
entityJoinInfo: {
|
||||
sourceTable: config.selectedTable || "",
|
||||
sourceColumn: column.columnName,
|
||||
joinAlias: column.columnName,
|
||||
},
|
||||
entityDisplayConfig: {
|
||||
displayColumns: [], // 빈 배열로 초기화
|
||||
separator: " - ",
|
||||
sourceTable: config.selectedTable || "",
|
||||
joinTable: tableColumn.reference_table || "",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
return column;
|
||||
});
|
||||
|
||||
// 변경사항이 있는 경우에만 업데이트
|
||||
const hasChanges = updatedColumns.some((col, index) => col.isEntityJoin !== config.columns![index].isEntityJoin);
|
||||
|
||||
if (hasChanges) {
|
||||
console.log("🎯 엔티티 컬럼 플래그 업데이트:", updatedColumns);
|
||||
handleChange("columns", updatedColumns);
|
||||
} else {
|
||||
console.log("ℹ️ 엔티티 컬럼 변경사항 없음");
|
||||
}
|
||||
}, [config.columns, tableColumns, config.selectedTable]);
|
||||
|
||||
// 🎯 엔티티 컬럼의 표시 컬럼 정보 로드
|
||||
const loadEntityDisplayConfig = async (column: ColumnConfig) => {
|
||||
if (!column.isEntityJoin || !column.entityJoinInfo || !column.entityDisplayConfig) return;
|
||||
@@ -304,7 +375,7 @@ export const TableListConfigPanel: React.FC<TableListConfigPanelProps> = ({
|
||||
const sourceColumns = sourceResult.columns || [];
|
||||
const joinColumns = joinResult.columns || [];
|
||||
|
||||
setEntityDisplayConfigs(prev => ({
|
||||
setEntityDisplayConfigs((prev) => ({
|
||||
...prev,
|
||||
[configKey]: {
|
||||
sourceColumns,
|
||||
@@ -325,10 +396,10 @@ export const TableListConfigPanel: React.FC<TableListConfigPanelProps> = ({
|
||||
if (!config) return;
|
||||
|
||||
const newSelectedColumns = config.selectedColumns.includes(selectedColumn)
|
||||
? config.selectedColumns.filter(col => col !== selectedColumn)
|
||||
? config.selectedColumns.filter((col) => col !== selectedColumn)
|
||||
: [...config.selectedColumns, selectedColumn];
|
||||
|
||||
setEntityDisplayConfigs(prev => ({
|
||||
setEntityDisplayConfigs((prev) => ({
|
||||
...prev,
|
||||
[configKey]: {
|
||||
...prev[configKey],
|
||||
@@ -351,7 +422,7 @@ export const TableListConfigPanel: React.FC<TableListConfigPanelProps> = ({
|
||||
const config = entityDisplayConfigs[configKey];
|
||||
if (!config) return;
|
||||
|
||||
setEntityDisplayConfigs(prev => ({
|
||||
setEntityDisplayConfigs((prev) => ({
|
||||
...prev,
|
||||
[configKey]: {
|
||||
...prev[configKey],
|
||||
@@ -791,6 +862,135 @@ export const TableListConfigPanel: React.FC<TableListConfigPanelProps> = ({
|
||||
{/* 컬럼 설정 탭 */}
|
||||
<TabsContent value="columns" className="space-y-4">
|
||||
<ScrollArea className="h-[600px] pr-4">
|
||||
{/* 🎯 엔티티 컬럼 표시 설정 섹션 - 컬럼 설정 패널 바깥으로 분리 */}
|
||||
{config.columns?.some((col) => col.isEntityJoin) && (
|
||||
<Card className="border-l-4 border-l-orange-500">
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2 text-base">🎯 엔티티 컬럼 표시 설정</CardTitle>
|
||||
<CardDescription>엔티티 타입 컬럼의 표시할 컬럼들을 조합하여 설정하세요</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
{config.columns
|
||||
?.filter((col) => col.isEntityJoin && col.entityDisplayConfig)
|
||||
.map((column) => (
|
||||
<div key={column.columnName} className="space-y-3 rounded-lg border bg-orange-50 p-3">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center gap-2">
|
||||
<Badge variant="outline" className="border-orange-300 text-orange-600">
|
||||
{column.columnName}
|
||||
</Badge>
|
||||
<span className="text-sm font-medium">{column.displayName}</span>
|
||||
</div>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => loadEntityDisplayConfig(column)}
|
||||
className="h-6 text-xs"
|
||||
>
|
||||
<Plus className="mr-1 h-3 w-3" />
|
||||
컬럼 로드
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{entityDisplayConfigs[column.columnName] && (
|
||||
<div className="space-y-3">
|
||||
{/* 구분자 설정 */}
|
||||
<div className="space-y-1">
|
||||
<Label className="text-xs">구분자</Label>
|
||||
<Input
|
||||
value={entityDisplayConfigs[column.columnName].separator}
|
||||
onChange={(e) => updateEntityDisplaySeparator(column.columnName, e.target.value)}
|
||||
className="h-7 text-xs"
|
||||
placeholder=" - "
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* 기본 테이블 컬럼 */}
|
||||
<div className="space-y-1">
|
||||
<Label className="text-xs text-blue-600">
|
||||
기본 테이블: {column.entityDisplayConfig?.sourceTable}
|
||||
</Label>
|
||||
<div className="grid max-h-20 grid-cols-2 gap-1 overflow-y-auto">
|
||||
{entityDisplayConfigs[column.columnName].sourceColumns.map((col) => (
|
||||
<div key={col.columnName} className="flex items-center space-x-1">
|
||||
<Checkbox
|
||||
id={`source-${column.columnName}-${col.columnName}`}
|
||||
checked={entityDisplayConfigs[column.columnName].selectedColumns.includes(
|
||||
col.columnName,
|
||||
)}
|
||||
onCheckedChange={() =>
|
||||
toggleEntityDisplayColumn(column.columnName, col.columnName)
|
||||
}
|
||||
className="h-3 w-3"
|
||||
/>
|
||||
<Label
|
||||
htmlFor={`source-${column.columnName}-${col.columnName}`}
|
||||
className="flex-1 cursor-pointer text-xs"
|
||||
>
|
||||
{col.displayName}
|
||||
</Label>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 조인 테이블 컬럼 */}
|
||||
<div className="space-y-1">
|
||||
<Label className="text-xs text-green-600">
|
||||
조인 테이블: {column.entityDisplayConfig?.joinTable}
|
||||
</Label>
|
||||
<div className="grid max-h-20 grid-cols-2 gap-1 overflow-y-auto">
|
||||
{entityDisplayConfigs[column.columnName].joinColumns.map((col) => (
|
||||
<div key={col.columnName} className="flex items-center space-x-1">
|
||||
<Checkbox
|
||||
id={`join-${column.columnName}-${col.columnName}`}
|
||||
checked={entityDisplayConfigs[column.columnName].selectedColumns.includes(
|
||||
col.columnName,
|
||||
)}
|
||||
onCheckedChange={() =>
|
||||
toggleEntityDisplayColumn(column.columnName, col.columnName)
|
||||
}
|
||||
className="h-3 w-3"
|
||||
/>
|
||||
<Label
|
||||
htmlFor={`join-${column.columnName}-${col.columnName}`}
|
||||
className="flex-1 cursor-pointer text-xs"
|
||||
>
|
||||
{col.displayName}
|
||||
</Label>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 선택된 컬럼 미리보기 */}
|
||||
{entityDisplayConfigs[column.columnName].selectedColumns.length > 0 && (
|
||||
<div className="space-y-1">
|
||||
<Label className="text-xs">미리보기</Label>
|
||||
<div className="flex flex-wrap gap-1 rounded bg-gray-50 p-2 text-xs">
|
||||
{entityDisplayConfigs[column.columnName].selectedColumns.map((colName, idx) => (
|
||||
<React.Fragment key={colName}>
|
||||
<Badge variant="secondary" className="text-xs">
|
||||
{colName}
|
||||
</Badge>
|
||||
{idx < entityDisplayConfigs[column.columnName].selectedColumns.length - 1 && (
|
||||
<span className="text-gray-400">
|
||||
{entityDisplayConfigs[column.columnName].separator}
|
||||
</span>
|
||||
)}
|
||||
</React.Fragment>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
{!screenTableName ? (
|
||||
<Card>
|
||||
<CardContent className="pt-6">
|
||||
@@ -921,105 +1121,17 @@ export const TableListConfigPanel: React.FC<TableListConfigPanelProps> = ({
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* 🎯 엔티티 타입 컬럼일 때 표시 컬럼 선택 UI */}
|
||||
{column.isEntityJoin && column.entityDisplayConfig && (
|
||||
<div className="col-span-2 space-y-2">
|
||||
<div className="flex items-center justify-between">
|
||||
<Label className="text-xs font-medium">표시 컬럼 조합</Label>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => loadEntityDisplayConfig(column)}
|
||||
className="h-6 text-xs"
|
||||
>
|
||||
<Plus className="h-3 w-3 mr-1" />
|
||||
컬럼 로드
|
||||
</Button>
|
||||
{/* 엔티티 타입 컬럼 표시 */}
|
||||
{column.isEntityJoin && (
|
||||
<div className="col-span-2">
|
||||
<div className="flex items-center gap-2 rounded bg-orange-50 p-2">
|
||||
<Badge variant="outline" className="border-orange-300 text-orange-600">
|
||||
엔티티 타입
|
||||
</Badge>
|
||||
<span className="text-xs text-orange-600">
|
||||
표시 컬럼 설정은 상단의 "🎯 엔티티 컬럼 표시 설정" 섹션에서 하세요
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{entityDisplayConfigs[column.columnName] && (
|
||||
<div className="space-y-3">
|
||||
{/* 구분자 설정 */}
|
||||
<div className="space-y-1">
|
||||
<Label className="text-xs">구분자</Label>
|
||||
<Input
|
||||
value={entityDisplayConfigs[column.columnName].separator}
|
||||
onChange={(e) => updateEntityDisplaySeparator(column.columnName, e.target.value)}
|
||||
className="h-7 text-xs"
|
||||
placeholder=" - "
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* 기본 테이블 컬럼 */}
|
||||
<div className="space-y-1">
|
||||
<Label className="text-xs text-blue-600">
|
||||
기본 테이블: {column.entityDisplayConfig.sourceTable}
|
||||
</Label>
|
||||
<div className="grid grid-cols-2 gap-1 max-h-20 overflow-y-auto">
|
||||
{entityDisplayConfigs[column.columnName].sourceColumns.map((col) => (
|
||||
<div key={col.columnName} className="flex items-center space-x-1">
|
||||
<Checkbox
|
||||
id={`source-${column.columnName}-${col.columnName}`}
|
||||
checked={entityDisplayConfigs[column.columnName].selectedColumns.includes(col.columnName)}
|
||||
onCheckedChange={() => toggleEntityDisplayColumn(column.columnName, col.columnName)}
|
||||
className="h-3 w-3"
|
||||
/>
|
||||
<Label
|
||||
htmlFor={`source-${column.columnName}-${col.columnName}`}
|
||||
className="text-xs cursor-pointer flex-1"
|
||||
>
|
||||
{col.displayName}
|
||||
</Label>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 조인 테이블 컬럼 */}
|
||||
<div className="space-y-1">
|
||||
<Label className="text-xs text-green-600">
|
||||
조인 테이블: {column.entityDisplayConfig.joinTable}
|
||||
</Label>
|
||||
<div className="grid grid-cols-2 gap-1 max-h-20 overflow-y-auto">
|
||||
{entityDisplayConfigs[column.columnName].joinColumns.map((col) => (
|
||||
<div key={col.columnName} className="flex items-center space-x-1">
|
||||
<Checkbox
|
||||
id={`join-${column.columnName}-${col.columnName}`}
|
||||
checked={entityDisplayConfigs[column.columnName].selectedColumns.includes(col.columnName)}
|
||||
onCheckedChange={() => toggleEntityDisplayColumn(column.columnName, col.columnName)}
|
||||
className="h-3 w-3"
|
||||
/>
|
||||
<Label
|
||||
htmlFor={`join-${column.columnName}-${col.columnName}`}
|
||||
className="text-xs cursor-pointer flex-1"
|
||||
>
|
||||
{col.displayName}
|
||||
</Label>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 선택된 컬럼 미리보기 */}
|
||||
{entityDisplayConfigs[column.columnName].selectedColumns.length > 0 && (
|
||||
<div className="space-y-1">
|
||||
<Label className="text-xs">미리보기</Label>
|
||||
<div className="flex flex-wrap gap-1 rounded bg-gray-50 p-2 text-xs">
|
||||
{entityDisplayConfigs[column.columnName].selectedColumns.map((colName, idx) => (
|
||||
<React.Fragment key={colName}>
|
||||
<Badge variant="secondary" className="text-xs">
|
||||
{colName}
|
||||
</Badge>
|
||||
{idx < entityDisplayConfigs[column.columnName].selectedColumns.length - 1 && (
|
||||
<span className="text-gray-400">{entityDisplayConfigs[column.columnName].separator}</span>
|
||||
)}
|
||||
</React.Fragment>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -1528,7 +1640,6 @@ export const TableListConfigPanel: React.FC<TableListConfigPanelProps> = ({
|
||||
</ScrollArea>
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user