계층 구조 트리 뷰
This commit is contained in:
@@ -90,6 +90,29 @@ export const SplitPanelLayoutConfigPanel: React.FC<SplitPanelLayoutConfigPanelPr
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [config.leftPanel?.tableName, screenTableName, loadedTableColumns, config.leftPanel?.showAdd]);
|
||||
|
||||
// 좌측 패널 하위 항목 추가 모달 PK 자동 추가
|
||||
useEffect(() => {
|
||||
const leftTableName = config.leftPanel?.tableName || screenTableName;
|
||||
if (leftTableName && loadedTableColumns[leftTableName] && config.leftPanel?.showItemAddButton) {
|
||||
const currentAddModalColumns = config.leftPanel?.itemAddConfig?.addModalColumns || [];
|
||||
const updatedColumns = ensurePrimaryKeysInAddModal(leftTableName, currentAddModalColumns);
|
||||
|
||||
// PK가 추가되었으면 업데이트
|
||||
if (updatedColumns.length !== currentAddModalColumns.length) {
|
||||
console.log(`🔄 좌측 패널 하위 항목 추가: PK 컬럼 자동 추가 (${leftTableName})`);
|
||||
updateLeftPanel({
|
||||
itemAddConfig: {
|
||||
...config.leftPanel?.itemAddConfig,
|
||||
addModalColumns: updatedColumns,
|
||||
parentColumn: config.leftPanel?.itemAddConfig?.parentColumn || "",
|
||||
sourceColumn: config.leftPanel?.itemAddConfig?.sourceColumn || "",
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [config.leftPanel?.tableName, screenTableName, loadedTableColumns, config.leftPanel?.showItemAddButton]);
|
||||
|
||||
// 우측 패널 테이블 컬럼 로드 완료 시 PK 자동 추가
|
||||
useEffect(() => {
|
||||
const rightTableName = config.rightPanel?.tableName;
|
||||
@@ -340,6 +363,307 @@ export const SplitPanelLayoutConfigPanel: React.FC<SplitPanelLayoutConfigPanelPr
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-between">
|
||||
<Label>각 항목에 + 버튼</Label>
|
||||
<Switch
|
||||
checked={config.leftPanel?.showItemAddButton ?? false}
|
||||
onCheckedChange={(checked) => updateLeftPanel({ showItemAddButton: checked })}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* 항목별 + 버튼 설정 (하위 항목 추가) */}
|
||||
{config.leftPanel?.showItemAddButton && (
|
||||
<div className="space-y-3 rounded-lg border border-blue-200 bg-blue-50 p-3">
|
||||
<Label className="text-sm font-semibold">하위 항목 추가 설정</Label>
|
||||
<p className="text-xs text-gray-600">
|
||||
+ 버튼 클릭 시 선택된 항목의 하위 항목을 추가합니다 (예: 부서 → 하위 부서)
|
||||
</p>
|
||||
|
||||
{/* 현재 항목의 값을 가져올 컬럼 (sourceColumn) */}
|
||||
<div>
|
||||
<Label className="text-xs">현재 항목 ID 컬럼</Label>
|
||||
<p className="mb-2 text-[10px] text-gray-500">
|
||||
선택된 항목의 어떤 컬럼 값을 사용할지 (예: dept_code)
|
||||
</p>
|
||||
<Popover>
|
||||
<PopoverTrigger asChild>
|
||||
<Button
|
||||
variant="outline"
|
||||
role="combobox"
|
||||
className="h-8 w-full justify-between text-xs"
|
||||
>
|
||||
{config.leftPanel?.itemAddConfig?.sourceColumn || "컬럼 선택"}
|
||||
<ChevronsUpDown className="ml-2 h-3 w-3 shrink-0 opacity-50" />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-full p-0">
|
||||
<Command>
|
||||
<CommandInput placeholder="컬럼 검색..." className="text-xs" />
|
||||
<CommandEmpty className="text-xs">컬럼을 찾을 수 없습니다.</CommandEmpty>
|
||||
<CommandGroup className="max-h-[200px] overflow-auto">
|
||||
{leftTableColumns
|
||||
.filter((column) => !['company_code', 'company_name'].includes(column.columnName))
|
||||
.map((column) => (
|
||||
<CommandItem
|
||||
key={column.columnName}
|
||||
value={column.columnName}
|
||||
onSelect={(value) => {
|
||||
updateLeftPanel({
|
||||
itemAddConfig: {
|
||||
...config.leftPanel?.itemAddConfig,
|
||||
sourceColumn: value,
|
||||
parentColumn: config.leftPanel?.itemAddConfig?.parentColumn || "",
|
||||
}
|
||||
});
|
||||
}}
|
||||
className="text-xs"
|
||||
>
|
||||
<Check
|
||||
className={cn(
|
||||
"mr-2 h-3 w-3",
|
||||
config.leftPanel?.itemAddConfig?.sourceColumn === column.columnName ? "opacity-100" : "opacity-0"
|
||||
)}
|
||||
/>
|
||||
{column.columnLabel || column.columnName}
|
||||
<span className="ml-2 text-[10px] text-gray-500">
|
||||
({column.columnName})
|
||||
</span>
|
||||
</CommandItem>
|
||||
))}
|
||||
</CommandGroup>
|
||||
</Command>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
</div>
|
||||
|
||||
{/* 상위 항목 ID를 저장할 컬럼 (parentColumn) */}
|
||||
<div>
|
||||
<Label className="text-xs">상위 항목 저장 컬럼</Label>
|
||||
<p className="mb-2 text-[10px] text-gray-500">
|
||||
하위 항목에서 상위 항목 ID를 저장할 컬럼 (예: parent_dept_code)
|
||||
</p>
|
||||
<Popover>
|
||||
<PopoverTrigger asChild>
|
||||
<Button
|
||||
variant="outline"
|
||||
role="combobox"
|
||||
className="h-8 w-full justify-between text-xs"
|
||||
>
|
||||
{config.leftPanel?.itemAddConfig?.parentColumn || "컬럼 선택"}
|
||||
<ChevronsUpDown className="ml-2 h-3 w-3 shrink-0 opacity-50" />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-full p-0">
|
||||
<Command>
|
||||
<CommandInput placeholder="컬럼 검색..." className="text-xs" />
|
||||
<CommandEmpty className="text-xs">컬럼을 찾을 수 없습니다.</CommandEmpty>
|
||||
<CommandGroup className="max-h-[200px] overflow-auto">
|
||||
{leftTableColumns
|
||||
.filter((column) => !['company_code', 'company_name'].includes(column.columnName))
|
||||
.map((column) => (
|
||||
<CommandItem
|
||||
key={column.columnName}
|
||||
value={column.columnName}
|
||||
onSelect={(value) => {
|
||||
updateLeftPanel({
|
||||
itemAddConfig: {
|
||||
...config.leftPanel?.itemAddConfig,
|
||||
parentColumn: value,
|
||||
sourceColumn: config.leftPanel?.itemAddConfig?.sourceColumn || "",
|
||||
}
|
||||
});
|
||||
}}
|
||||
className="text-xs"
|
||||
>
|
||||
<Check
|
||||
className={cn(
|
||||
"mr-2 h-3 w-3",
|
||||
config.leftPanel?.itemAddConfig?.parentColumn === column.columnName ? "opacity-100" : "opacity-0"
|
||||
)}
|
||||
/>
|
||||
{column.columnLabel || column.columnName}
|
||||
<span className="ml-2 text-[10px] text-gray-500">
|
||||
({column.columnName})
|
||||
</span>
|
||||
</CommandItem>
|
||||
))}
|
||||
</CommandGroup>
|
||||
</Command>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
</div>
|
||||
|
||||
{/* 하위 항목 추가 모달 컬럼 설정 */}
|
||||
<div className="space-y-2 rounded border border-blue-300 bg-white p-2">
|
||||
<div className="flex items-center justify-between">
|
||||
<Label className="text-xs font-semibold">추가 모달 입력 컬럼</Label>
|
||||
<Button
|
||||
size="sm"
|
||||
variant="outline"
|
||||
onClick={() => {
|
||||
const currentColumns = config.leftPanel?.itemAddConfig?.addModalColumns || [];
|
||||
const newColumns = [
|
||||
...currentColumns,
|
||||
{ name: "", label: "", required: false },
|
||||
];
|
||||
updateLeftPanel({
|
||||
itemAddConfig: {
|
||||
...config.leftPanel?.itemAddConfig,
|
||||
addModalColumns: newColumns,
|
||||
parentColumn: config.leftPanel?.itemAddConfig?.parentColumn || "",
|
||||
sourceColumn: config.leftPanel?.itemAddConfig?.sourceColumn || "",
|
||||
}
|
||||
});
|
||||
}}
|
||||
className="h-6 text-[10px]"
|
||||
>
|
||||
<Plus className="mr-1 h-3 w-3" />
|
||||
컬럼 추가
|
||||
</Button>
|
||||
</div>
|
||||
<p className="text-[10px] text-gray-600">
|
||||
하위 항목 추가 시 입력받을 필드를 선택하세요
|
||||
</p>
|
||||
|
||||
<div className="space-y-2">
|
||||
{(config.leftPanel?.itemAddConfig?.addModalColumns || []).length === 0 ? (
|
||||
<div className="rounded-md border border-dashed border-gray-300 bg-gray-50 p-2 text-center">
|
||||
<p className="text-[10px] text-gray-500">설정된 컬럼이 없습니다</p>
|
||||
</div>
|
||||
) : (
|
||||
(config.leftPanel?.itemAddConfig?.addModalColumns || []).map((col, index) => {
|
||||
const column = leftTableColumns.find(c => c.columnName === col.name);
|
||||
const isPK = column?.isPrimaryKey || false;
|
||||
|
||||
return (
|
||||
<div
|
||||
key={index}
|
||||
className={cn(
|
||||
"flex items-center gap-2 rounded-md border p-2",
|
||||
isPK ? "border-yellow-300 bg-yellow-50" : "bg-white"
|
||||
)}
|
||||
>
|
||||
{isPK && (
|
||||
<span className="rounded bg-yellow-200 px-1.5 py-0.5 text-[10px] font-semibold text-yellow-700">
|
||||
PK
|
||||
</span>
|
||||
)}
|
||||
<div className="flex-1">
|
||||
<Popover>
|
||||
<PopoverTrigger asChild>
|
||||
<Button
|
||||
variant="outline"
|
||||
role="combobox"
|
||||
disabled={isPK}
|
||||
className="h-7 w-full justify-between text-[10px]"
|
||||
>
|
||||
{col.name || "컬럼 선택"}
|
||||
<ChevronsUpDown className="ml-2 h-3 w-3 shrink-0 opacity-50" />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-full p-0">
|
||||
<Command>
|
||||
<CommandInput placeholder="컬럼 검색..." className="text-xs" />
|
||||
<CommandEmpty className="text-xs">컬럼을 찾을 수 없습니다.</CommandEmpty>
|
||||
<CommandGroup className="max-h-[200px] overflow-auto">
|
||||
{leftTableColumns
|
||||
.filter((column) => !['company_code', 'company_name'].includes(column.columnName))
|
||||
.map((column) => (
|
||||
<CommandItem
|
||||
key={column.columnName}
|
||||
value={column.columnName}
|
||||
onSelect={(value) => {
|
||||
const newColumns = [...(config.leftPanel?.itemAddConfig?.addModalColumns || [])];
|
||||
newColumns[index] = {
|
||||
...newColumns[index],
|
||||
name: value,
|
||||
label: column.columnLabel || value,
|
||||
};
|
||||
updateLeftPanel({
|
||||
itemAddConfig: {
|
||||
...config.leftPanel?.itemAddConfig,
|
||||
addModalColumns: newColumns,
|
||||
parentColumn: config.leftPanel?.itemAddConfig?.parentColumn || "",
|
||||
sourceColumn: config.leftPanel?.itemAddConfig?.sourceColumn || "",
|
||||
}
|
||||
});
|
||||
}}
|
||||
className="text-xs"
|
||||
>
|
||||
<Check
|
||||
className={cn(
|
||||
"mr-2 h-3 w-3",
|
||||
col.name === column.columnName ? "opacity-100" : "opacity-0"
|
||||
)}
|
||||
/>
|
||||
{column.columnLabel || column.columnName}
|
||||
<span className="ml-2 text-[10px] text-gray-500">
|
||||
({column.columnName})
|
||||
</span>
|
||||
</CommandItem>
|
||||
))}
|
||||
</CommandGroup>
|
||||
</Command>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
</div>
|
||||
<div className="flex items-center gap-1">
|
||||
<label className="flex cursor-pointer items-center gap-1 text-[10px] text-gray-600">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={col.required ?? false}
|
||||
disabled={isPK}
|
||||
onChange={(e) => {
|
||||
const newColumns = [...(config.leftPanel?.itemAddConfig?.addModalColumns || [])];
|
||||
newColumns[index] = {
|
||||
...newColumns[index],
|
||||
required: e.target.checked,
|
||||
};
|
||||
updateLeftPanel({
|
||||
itemAddConfig: {
|
||||
...config.leftPanel?.itemAddConfig,
|
||||
addModalColumns: newColumns,
|
||||
parentColumn: config.leftPanel?.itemAddConfig?.parentColumn || "",
|
||||
sourceColumn: config.leftPanel?.itemAddConfig?.sourceColumn || "",
|
||||
}
|
||||
});
|
||||
}}
|
||||
className="h-3 w-3"
|
||||
/>
|
||||
필수
|
||||
</label>
|
||||
</div>
|
||||
<Button
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
disabled={isPK}
|
||||
onClick={() => {
|
||||
const newColumns = (config.leftPanel?.itemAddConfig?.addModalColumns || []).filter(
|
||||
(_, i) => i !== index
|
||||
);
|
||||
updateLeftPanel({
|
||||
itemAddConfig: {
|
||||
...config.leftPanel?.itemAddConfig,
|
||||
addModalColumns: newColumns,
|
||||
parentColumn: config.leftPanel?.itemAddConfig?.parentColumn || "",
|
||||
sourceColumn: config.leftPanel?.itemAddConfig?.sourceColumn || "",
|
||||
}
|
||||
});
|
||||
}}
|
||||
className="h-7 w-7 p-0"
|
||||
title={isPK ? "PK 컬럼은 삭제할 수 없습니다" : ""}
|
||||
>
|
||||
<X className="h-3 w-3" />
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
})
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 좌측 패널 추가 모달 컬럼 설정 */}
|
||||
{config.leftPanel?.showAdd && (
|
||||
<div className="space-y-3 rounded-lg border border-purple-200 bg-purple-50 p-3">
|
||||
|
||||
Reference in New Issue
Block a user