자물쇠 누르면 컬럼 값 변경 안됩니다.

This commit is contained in:
leeheejin 2025-12-05 17:42:35 +09:00
parent 417d77729d
commit 65227c5e03
3 changed files with 88 additions and 24 deletions

View File

@ -31,6 +31,7 @@ import {
Edit,
CheckSquare,
Trash2,
Lock,
} from "lucide-react";
import * as XLSX from "xlsx";
import { FileText, ChevronRightIcon } from "lucide-react";
@ -391,11 +392,13 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
checkboxCol = {
columnName: "__checkbox__",
displayName: "",
webType: "checkbox",
visible: true,
sortable: false,
filterable: false,
searchable: false,
width: 40,
align: "center" as const,
order: -1,
editable: false, // 체크박스는 편집 불가
};
}
@ -1933,10 +1936,17 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
// 체크박스 컬럼은 편집 불가
if (columnName === "__checkbox__") return;
// 🆕 편집 불가 컬럼 체크
const column = visibleColumns.find((col) => col.columnName === columnName);
if (column?.editable === false) {
toast.warning(`'${column.displayName || columnName}' 컬럼은 편집할 수 없습니다.`);
return;
}
setEditingCell({ rowIndex, colIndex, columnName, originalValue: value });
setEditingValue(value !== null && value !== undefined ? String(value) : "");
setFocusedCell({ rowIndex, colIndex });
}, []);
}, [visibleColumns]);
// 🆕 편집 모드 진입 placeholder (실제 구현은 visibleColumns 정의 후)
const startEditingRef = useRef<() => void>(() => {});
@ -3552,6 +3562,11 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
{
const col = visibleColumns[colIndex];
if (col && col.columnName !== "__checkbox__") {
// 🆕 편집 불가 컬럼 체크
if (col.editable === false) {
toast.warning(`'${col.displayName || col.columnName}' 컬럼은 편집할 수 없습니다.`);
break;
}
const row = data[rowIndex];
const mappedCol = joinColumnMapping[col.columnName] || col.columnName;
const val = row?.[mappedCol];
@ -3696,6 +3711,11 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
if (e.key.length === 1 && !e.ctrlKey && !e.altKey && !e.metaKey) {
const column = visibleColumns[colIndex];
if (column && column.columnName !== "__checkbox__") {
// 🆕 편집 불가 컬럼 체크
if (column.editable === false) {
toast.warning(`'${column.displayName || column.columnName}' 컬럼은 편집할 수 없습니다.`);
break;
}
e.preventDefault();
// 편집 시작 (현재 키를 초기값으로)
const row = data[rowIndex];
@ -5039,6 +5059,12 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
renderCheckboxHeader()
) : (
<div style={{ display: "flex", alignItems: "center", gap: "4px", justifyContent: "center" }}>
{/* 🆕 편집 불가 컬럼 표시 */}
{column.editable === false && (
<span title="편집 불가">
<Lock className="h-3 w-3 text-muted-foreground" />
</span>
)}
<span>{columnLabels[column.columnName] || column.displayName}</span>
{column.sortable !== false && sortColumn === column.columnName && (
<span>{sortDirection === "asc" ? "↑" : "↓"}</span>
@ -5458,6 +5484,8 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
cellValidationError && "bg-red-50 dark:bg-red-950/40 ring-2 ring-red-500 ring-inset",
// 🆕 검색 하이라이트 스타일 (노란 배경)
isSearchHighlighted && !isCellFocused && "bg-yellow-200 dark:bg-yellow-700/50",
// 🆕 편집 불가 컬럼 스타일 (연한 회색 배경)
column.editable === false && "bg-gray-50 dark:bg-gray-900/30",
)}
// 🆕 유효성 에러 툴팁
title={cellValidationError || undefined}
@ -5762,25 +5790,39 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
<div className="bg-border my-1 h-px" />
{/* 셀 편집 */}
<button
className="hover:bg-accent hover:text-accent-foreground flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-sm"
onClick={() => {
const col = visibleColumns[contextMenu.colIndex];
if (col) {
setEditingCell({
rowIndex: contextMenu.rowIndex,
colIndex: contextMenu.colIndex,
columnName: col.columnName,
originalValue: contextMenu.row[col.columnName],
});
setEditingValue(String(contextMenu.row[col.columnName] ?? ""));
}
closeContextMenu();
}}
>
<Edit className="h-4 w-4" />
</button>
{(() => {
const col = visibleColumns[contextMenu.colIndex];
const isEditable = col?.editable !== false && col?.columnName !== "__checkbox__";
return (
<button
className={`flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-sm ${
isEditable
? "hover:bg-accent hover:text-accent-foreground"
: "opacity-50 cursor-not-allowed"
}`}
onClick={() => {
if (!isEditable) {
toast.warning(`'${col?.displayName || col?.columnName}' 컬럼은 편집할 수 없습니다.`);
closeContextMenu();
return;
}
if (col) {
setEditingCell({
rowIndex: contextMenu.rowIndex,
colIndex: contextMenu.colIndex,
columnName: col.columnName,
originalValue: contextMenu.row[col.columnName],
});
setEditingValue(String(contextMenu.row[col.columnName] ?? ""));
}
closeContextMenu();
}}
>
<Edit className="h-4 w-4" />
{!isEditable && "(잠김)"}
</button>
);
})()}
{/* 행 선택/해제 */}
<button

View File

@ -10,7 +10,7 @@ import { TableListConfig, ColumnConfig } from "./types";
import { entityJoinApi } from "@/lib/api/entityJoin";
import { tableTypeApi } from "@/lib/api/screen";
import { tableManagementApi } from "@/lib/api/tableManagement";
import { Plus, Trash2, ArrowUp, ArrowDown, ChevronsUpDown, Check } from "lucide-react";
import { Plus, Trash2, ArrowUp, ArrowDown, ChevronsUpDown, Check, Lock, Unlock } from "lucide-react";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from "@/components/ui/command";
import { cn } from "@/lib/utils";
@ -1141,8 +1141,28 @@ export const TableListConfigPanel: React.FC<TableListConfigPanelProps> = ({
)}
</div>
{/* 필터 체크박스 + 순서 변경 + 삭제 버튼 */}
{/* 편집 가능 여부 + 필터 체크박스 */}
<div className="flex shrink-0 items-center gap-1">
{/* 🆕 편집 가능 여부 토글 */}
<Button
variant="ghost"
size="sm"
onClick={() => {
updateColumn(column.columnName, {
editable: column.editable === false ? true : false
});
}}
className="h-6 w-6 p-0"
title={column.editable === false ? "편집 불가 (클릭하여 편집 허용)" : "편집 가능 (클릭하여 편집 잠금)"}
>
{column.editable === false ? (
<Lock className="h-3 w-3 text-destructive" />
) : (
<Unlock className="h-3 w-3 text-muted-foreground" />
)}
</Button>
{/* 필터 체크박스 */}
<Checkbox
checked={config.filter?.filters?.some((f) => f.columnName === column.columnName) || false}
onCheckedChange={(checked) => {
@ -1173,6 +1193,7 @@ export const TableListConfigPanel: React.FC<TableListConfigPanelProps> = ({
}
}}
className="h-3 w-3"
title="필터에 추가"
/>
</div>

View File

@ -77,6 +77,7 @@ export interface ColumnConfig {
// 새로운 기능들
hidden?: boolean; // 숨김 기능 (편집기에서는 연하게, 실제 화면에서는 숨김)
autoGeneration?: AutoGenerationConfig; // 자동생성 설정
editable?: boolean; // 🆕 편집 가능 여부 (기본값: true, false면 인라인 편집 불가)
// 🎯 추가 조인 컬럼 정보 (조인 탭에서 추가한 컬럼들)
additionalJoinInfo?: {