자물쇠 누르면 컬럼 값 변경 안됩니다.
This commit is contained in:
parent
417d77729d
commit
65227c5e03
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ export interface ColumnConfig {
|
|||
// 새로운 기능들
|
||||
hidden?: boolean; // 숨김 기능 (편집기에서는 연하게, 실제 화면에서는 숨김)
|
||||
autoGeneration?: AutoGenerationConfig; // 자동생성 설정
|
||||
editable?: boolean; // 🆕 편집 가능 여부 (기본값: true, false면 인라인 편집 불가)
|
||||
|
||||
// 🎯 추가 조인 컬럼 정보 (조인 탭에서 추가한 컬럼들)
|
||||
additionalJoinInfo?: {
|
||||
|
|
|
|||
Loading…
Reference in New Issue