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

This commit is contained in:
leeheejin 2025-12-05 17:42:35 +09:00 committed by kjs
parent 179ff5b68b
commit fab292f465
3 changed files with 88 additions and 24 deletions

View File

@ -31,6 +31,7 @@ import {
Edit, Edit,
CheckSquare, CheckSquare,
Trash2, Trash2,
Lock,
} from "lucide-react"; } from "lucide-react";
import * as XLSX from "xlsx"; import * as XLSX from "xlsx";
import { FileText, ChevronRightIcon } from "lucide-react"; import { FileText, ChevronRightIcon } from "lucide-react";
@ -391,11 +392,13 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
checkboxCol = { checkboxCol = {
columnName: "__checkbox__", columnName: "__checkbox__",
displayName: "", displayName: "",
webType: "checkbox",
visible: true, visible: true,
sortable: false, sortable: false,
filterable: false, searchable: false,
width: 40, width: 40,
align: "center" as const,
order: -1,
editable: false, // 체크박스는 편집 불가
}; };
} }
@ -2068,10 +2071,17 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
// 체크박스 컬럼은 편집 불가 // 체크박스 컬럼은 편집 불가
if (columnName === "__checkbox__") return; 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 }); setEditingCell({ rowIndex, colIndex, columnName, originalValue: value });
setEditingValue(value !== null && value !== undefined ? String(value) : ""); setEditingValue(value !== null && value !== undefined ? String(value) : "");
setFocusedCell({ rowIndex, colIndex }); setFocusedCell({ rowIndex, colIndex });
}, []); }, [visibleColumns]);
// 🆕 편집 모드 진입 placeholder (실제 구현은 visibleColumns 정의 후) // 🆕 편집 모드 진입 placeholder (실제 구현은 visibleColumns 정의 후)
const startEditingRef = useRef<() => void>(() => {}); const startEditingRef = useRef<() => void>(() => {});
@ -3687,6 +3697,11 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
{ {
const col = visibleColumns[colIndex]; const col = visibleColumns[colIndex];
if (col && col.columnName !== "__checkbox__") { if (col && col.columnName !== "__checkbox__") {
// 🆕 편집 불가 컬럼 체크
if (col.editable === false) {
toast.warning(`'${col.displayName || col.columnName}' 컬럼은 편집할 수 없습니다.`);
break;
}
const row = data[rowIndex]; const row = data[rowIndex];
const mappedCol = joinColumnMapping[col.columnName] || col.columnName; const mappedCol = joinColumnMapping[col.columnName] || col.columnName;
const val = row?.[mappedCol]; const val = row?.[mappedCol];
@ -3831,6 +3846,11 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
if (e.key.length === 1 && !e.ctrlKey && !e.altKey && !e.metaKey) { if (e.key.length === 1 && !e.ctrlKey && !e.altKey && !e.metaKey) {
const column = visibleColumns[colIndex]; const column = visibleColumns[colIndex];
if (column && column.columnName !== "__checkbox__") { if (column && column.columnName !== "__checkbox__") {
// 🆕 편집 불가 컬럼 체크
if (column.editable === false) {
toast.warning(`'${column.displayName || column.columnName}' 컬럼은 편집할 수 없습니다.`);
break;
}
e.preventDefault(); e.preventDefault();
// 편집 시작 (현재 키를 초기값으로) // 편집 시작 (현재 키를 초기값으로)
const row = data[rowIndex]; const row = data[rowIndex];
@ -5186,6 +5206,12 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
renderCheckboxHeader() renderCheckboxHeader()
) : ( ) : (
<div style={{ display: "flex", alignItems: "center", gap: "4px", justifyContent: "center" }}> <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> <span>{columnLabels[column.columnName] || column.displayName}</span>
{column.sortable !== false && sortColumn === column.columnName && ( {column.sortable !== false && sortColumn === column.columnName && (
<span>{sortDirection === "asc" ? "↑" : "↓"}</span> <span>{sortDirection === "asc" ? "↑" : "↓"}</span>
@ -5605,6 +5631,8 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
cellValidationError && "bg-red-50 dark:bg-red-950/40 ring-2 ring-red-500 ring-inset", 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", isSearchHighlighted && !isCellFocused && "bg-yellow-200 dark:bg-yellow-700/50",
// 🆕 편집 불가 컬럼 스타일 (연한 회색 배경)
column.editable === false && "bg-gray-50 dark:bg-gray-900/30",
)} )}
// 🆕 유효성 에러 툴팁 // 🆕 유효성 에러 툴팁
title={cellValidationError || undefined} title={cellValidationError || undefined}
@ -5909,10 +5937,22 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
<div className="bg-border my-1 h-px" /> <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]; 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) { if (col) {
setEditingCell({ setEditingCell({
rowIndex: contextMenu.rowIndex, rowIndex: contextMenu.rowIndex,
@ -5926,8 +5966,10 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
}} }}
> >
<Edit className="h-4 w-4" /> <Edit className="h-4 w-4" />
{!isEditable && "(잠김)"}
</button> </button>
);
})()}
{/* 행 선택/해제 */} {/* 행 선택/해제 */}
<button <button

View File

@ -10,7 +10,7 @@ import { TableListConfig, ColumnConfig } from "./types";
import { entityJoinApi } from "@/lib/api/entityJoin"; import { entityJoinApi } from "@/lib/api/entityJoin";
import { tableTypeApi } from "@/lib/api/screen"; import { tableTypeApi } from "@/lib/api/screen";
import { tableManagementApi } from "@/lib/api/tableManagement"; 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 { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from "@/components/ui/command"; import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from "@/components/ui/command";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
@ -1143,8 +1143,28 @@ export const TableListConfigPanel: React.FC<TableListConfigPanelProps> = ({
)} )}
</div> </div>
{/* 필터 체크박스 + 순서 변경 + 삭제 버튼 */} {/* 편집 가능 여부 + 필터 체크박스 */}
<div className="flex shrink-0 items-center gap-1"> <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 <Checkbox
checked={config.filter?.filters?.some((f) => f.columnName === column.columnName) || false} checked={config.filter?.filters?.some((f) => f.columnName === column.columnName) || false}
onCheckedChange={(checked) => { onCheckedChange={(checked) => {
@ -1174,6 +1194,7 @@ export const TableListConfigPanel: React.FC<TableListConfigPanelProps> = ({
} }
}} }}
className="h-3 w-3" className="h-3 w-3"
title="필터에 추가"
/> />
</div> </div>

View File

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