다국어 지원 및 테이블 설정 현황 문서를 업데이트하고, SplitPanelLayoutConfigPanel에서 좌측 패널 테이블 선택 기능을 추가했습니다. 또한, 조인 키를 연결 키로 변경하고, 조건 필터 모드에 대한 설명을 수정하여 사용자 경험을 개선했습니다.

This commit is contained in:
kjs
2026-01-15 17:35:04 +09:00
parent 7181822832
commit ce85528ddf
3 changed files with 154 additions and 55 deletions

View File

@@ -388,9 +388,9 @@ const AdditionalTabConfigPanel: React.FC<AdditionalTabConfigPanelProps> = ({
)}
</div>
{/* ===== 4. 컬럼 매핑 (조인 키) ===== */}
{/* ===== 4. 컬럼 매핑 (연결 키) ===== */}
<div className="space-y-3 rounded-lg border bg-white p-3">
<Label className="text-xs font-semibold text-blue-600"> ( )</Label>
<Label className="text-xs font-semibold text-blue-600"> ( )</Label>
<p className="text-[10px] text-gray-500">
</p>
@@ -1067,10 +1067,11 @@ export const SplitPanelLayoutConfigPanel: React.FC<SplitPanelLayoutConfigPanelPr
screenTableName, // 현재 화면의 테이블명
menuObjid, // 🆕 메뉴 OBJID
}) => {
const [leftTableOpen, setLeftTableOpen] = useState(false); // 🆕 좌측 테이블 Combobox 상태
const [rightTableOpen, setRightTableOpen] = useState(false);
const [loadedTableColumns, setLoadedTableColumns] = useState<Record<string, ColumnInfo[]>>({});
const [loadingColumns, setLoadingColumns] = useState<Record<string, boolean>>({});
const [allTables, setAllTables] = useState<any[]>([]); // 조인 모드용 전체 테이블 목록
const [allTables, setAllTables] = useState<any[]>([]); // 테이블 목록
// 엔티티 참조 테이블 컬럼
type EntityRefTable = { tableName: string; columns: ColumnInfo[] };
const [entityReferenceTables, setEntityReferenceTables] = useState<Record<string, EntityRefTable[]>>({});
@@ -1095,35 +1096,27 @@ export const SplitPanelLayoutConfigPanel: React.FC<SplitPanelLayoutConfigPanelPr
}
}, [config.leftPanel?.title, config.rightPanel?.title, isUserEditing]);
// 조인 모드일 때만 전체 테이블 목록 로드
// 전체 테이블 목록 항상 로드 (좌측/우측 모두 사용)
useEffect(() => {
if (relationshipType === "join") {
const loadAllTables = async () => {
try {
const { tableManagementApi } = await import("@/lib/api/tableManagement");
const response = await tableManagementApi.getTableList();
if (response.success && response.data) {
console.log("✅ 분할패널 조인 모드: 전체 테이블 목록 로드", response.data.length, "개");
setAllTables(response.data);
}
} catch (error) {
console.error("❌ 전체 테이블 목록 로드 실패:", error);
const loadAllTables = async () => {
try {
const { tableManagementApi } = await import("@/lib/api/tableManagement");
const response = await tableManagementApi.getTableList();
if (response.success && response.data) {
console.log("✅ 분할패널: 전체 테이블 목록 로드", response.data.length, "개");
setAllTables(response.data);
}
};
loadAllTables();
} else {
// 상세 모드일 때는 기본 테이블만 사용
setAllTables([]);
}
}, [relationshipType]);
// screenTableName이 변경되면 좌측 패널 테이블을 항상 화면 테이블로 설정
useEffect(() => {
if (screenTableName) {
// 좌측 패널은 항상 현재 화면의 테이블 사용
if (config.leftPanel?.tableName !== screenTableName) {
updateLeftPanel({ tableName: screenTableName });
} catch (error) {
console.error("❌ 전체 테이블 목록 로드 실패:", error);
}
};
loadAllTables();
}, []);
// 초기 로드 시 좌측 패널 테이블이 없으면 화면 테이블로 설정
useEffect(() => {
if (screenTableName && !config.leftPanel?.tableName) {
updateLeftPanel({ tableName: screenTableName });
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [screenTableName]);
@@ -1345,8 +1338,13 @@ export const SplitPanelLayoutConfigPanel: React.FC<SplitPanelLayoutConfigPanelPr
return leftTableName ? loadedTableColumns[leftTableName] || [] : [];
}, [loadedTableColumns, leftTableName]);
// 우측 테이블명
const rightTableName = config.rightPanel?.tableName || "";
// 우측 테이블명 (상세 모드에서는 좌측과 동일)
const rightTableName = useMemo(() => {
if (relationshipType === "detail") {
return leftTableName; // 상세 모드에서는 좌측과 동일
}
return config.rightPanel?.tableName || "";
}, [relationshipType, leftTableName, config.rightPanel?.tableName]);
// 우측 테이블 컬럼 (로드된 컬럼 사용)
const rightTableColumns = useMemo(() => {
@@ -1406,8 +1404,8 @@ export const SplitPanelLayoutConfigPanel: React.FC<SplitPanelLayoutConfigPanelPr
</SelectItem>
<SelectItem value="join">
<div className="flex flex-col">
<span className="font-medium"> (JOIN)</span>
<span className="text-xs text-gray-500"> ( )</span>
<span className="font-medium"> (FILTERED)</span>
<span className="text-xs text-gray-500"> </span>
</div>
</SelectItem>
</SelectContent>
@@ -1418,6 +1416,103 @@ export const SplitPanelLayoutConfigPanel: React.FC<SplitPanelLayoutConfigPanelPr
<div className="mt-4 space-y-4 border-t pt-4">
<h3 className="text-sm font-semibold"> ()</h3>
{/* 🆕 좌측 패널 테이블 선택 */}
<div className="space-y-2">
<Label className="text-xs font-medium"> </Label>
<Popover open={leftTableOpen} onOpenChange={setLeftTableOpen}>
<PopoverTrigger asChild>
<Button
variant="outline"
role="combobox"
aria-expanded={leftTableOpen}
className="h-9 w-full justify-between text-xs"
>
<div className="flex items-center gap-2 truncate">
<Database className="h-3.5 w-3.5 shrink-0 text-muted-foreground" />
<span className="truncate">
{config.leftPanel?.tableName
? allTables.find((t) => (t.tableName || t.table_name) === config.leftPanel?.tableName)?.tableLabel ||
allTables.find((t) => (t.tableName || t.table_name) === config.leftPanel?.tableName)?.displayName ||
config.leftPanel?.tableName
: "테이블을 선택하세요"}
</span>
</div>
<ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
</Button>
</PopoverTrigger>
<PopoverContent className="w-[300px] p-0" align="start">
<Command>
<CommandInput placeholder="테이블 검색..." className="text-xs" />
<CommandList>
<CommandEmpty className="py-3 text-center text-xs text-muted-foreground">
.
</CommandEmpty>
{/* 화면 기본 테이블 */}
{screenTableName && (
<CommandGroup heading="기본 (화면 테이블)">
<CommandItem
value={screenTableName}
onSelect={() => {
updateLeftPanel({ tableName: screenTableName, columns: [] });
setLeftTableOpen(false);
}}
className="text-xs"
>
<Check
className={cn(
"mr-2 h-4 w-4",
config.leftPanel?.tableName === screenTableName ? "opacity-100" : "opacity-0"
)}
/>
<Database className="mr-2 h-3.5 w-3.5 text-blue-500" />
{allTables.find((t) => (t.tableName || t.table_name) === screenTableName)?.tableLabel ||
allTables.find((t) => (t.tableName || t.table_name) === screenTableName)?.displayName ||
screenTableName}
</CommandItem>
</CommandGroup>
)}
{/* 전체 테이블 */}
<CommandGroup heading="전체 테이블">
{allTables
.filter((t) => (t.tableName || t.table_name) !== screenTableName)
.map((table) => {
const tableName = table.tableName || table.table_name;
const displayName = table.tableLabel || table.displayName || tableName;
return (
<CommandItem
key={tableName}
value={tableName}
onSelect={() => {
updateLeftPanel({ tableName, columns: [] });
setLeftTableOpen(false);
}}
className="text-xs"
>
<Check
className={cn(
"mr-2 h-4 w-4",
config.leftPanel?.tableName === tableName ? "opacity-100" : "opacity-0"
)}
/>
<Database className="mr-2 h-3.5 w-3.5 text-muted-foreground" />
<span className="truncate">{displayName}</span>
</CommandItem>
);
})}
</CommandGroup>
</CommandList>
</Command>
</PopoverContent>
</Popover>
{config.leftPanel?.tableName && config.leftPanel?.tableName !== screenTableName && (
<p className="text-[10px] text-muted-foreground">
.
</p>
)}
</div>
<div className="space-y-2">
<Label> </Label>
<Input
@@ -1661,7 +1756,7 @@ export const SplitPanelLayoutConfigPanel: React.FC<SplitPanelLayoutConfigPanelPr
{/* 우측 패널 설정 */}
<div className="mt-4 space-y-4 border-t pt-4">
<h3 className="text-sm font-semibold"> ({relationshipType === "detail" ? "상세" : "조"})</h3>
<h3 className="text-sm font-semibold"> ({relationshipType === "detail" ? "상세" : "조건 필터"})</h3>
<div className="space-y-2">
<Label> </Label>
@@ -1706,9 +1801,9 @@ export const SplitPanelLayoutConfigPanel: React.FC<SplitPanelLayoutConfigPanelPr
</div>
</div>
) : (
// 조 모드: 전체 테이블에서 선택 가능
// 조건 필터 모드: 전체 테이블에서 선택 가능
<div className="space-y-2">
<Label> ( )</Label>
<Label> </Label>
<Popover open={rightTableOpen} onOpenChange={setRightTableOpen}>
<PopoverTrigger asChild>
<Button
@@ -1814,12 +1909,12 @@ export const SplitPanelLayoutConfigPanel: React.FC<SplitPanelLayoutConfigPanelPr
</div>
)}
{/* 엔티티 설정 선택 - 조 모드에서만 표시 */}
{/* 엔티티 설정 선택 - 조건 필터 모드에서만 표시 */}
{relationshipType !== "detail" && (
<div className="space-y-2">
<Label className="text-xs font-medium"> ( )</Label>
<Label className="text-xs font-medium"> </Label>
<p className="text-muted-foreground text-[10px]">
</p>
<Select
value={config.rightPanel?.relation?.foreignKey || ""}