Skip to content

Commit cfb4d2f

Browse files
improvement(tables): show the lock chip only when a table is actually locked
- The header chip rendered whenever an admin had the flag on, so an unlocked table permanently carried a "Lock settings" entry. Header space is for state: the chip now appears only once something is locked and names the mode. The admin route to the panel on an unlocked table is the breadcrumb dropdown, which already had it - Keep the Append-only name when the schema is locked too. Append-only describes the row semantics and a schema lock doesn't change them; the detail line calls out the locked columns instead
1 parent 0dcbc56 commit cfb4d2f

2 files changed

Lines changed: 15 additions & 10 deletions

File tree

apps/sim/app/workspace/[workspaceId]/tables/[tableId]/lock-copy.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,16 @@ export function describeLocks(locks: TableLocks): { name: string; detail: string
6060
if (locked.length === LOCK_FIELDS.length) {
6161
return { name: 'Read-only', detail: 'no one can change this table’s rows or columns.' }
6262
}
63-
// Only the exact three-lock shape is Append-only — with the schema locked too
64-
// the chip would claim columns are mutable when they aren't.
65-
if (!locks.insertLocked && locks.updateLocked && locks.deleteLocked && !locks.schemaLocked) {
66-
return { name: 'Append-only', detail: 'rows can be added, but not edited or deleted.' }
63+
// Append-only describes the row semantics — adding is the only thing left.
64+
// A schema lock on top doesn't change that, so it keeps the name and is
65+
// called out in the detail rather than demoted to the generic case.
66+
if (!locks.insertLocked && locks.updateLocked && locks.deleteLocked) {
67+
return {
68+
name: 'Append-only',
69+
detail: locks.schemaLocked
70+
? 'rows can be added, but not edited or deleted, and columns are locked.'
71+
: 'rows can be added, but not edited or deleted.',
72+
}
6773
}
6874
return { name: 'Locked', detail: `${locked.join(', ')} locked.` }
6975
}

apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table.tsx

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -644,16 +644,15 @@ export function Table({
644644

645645
const headerActions = useMemo(() => {
646646
if (!tableData) return undefined
647+
// Header space is for state, not for settings: the chip appears only once
648+
// something is actually locked, and names the mode so it reads at a glance.
649+
// Reaching the panel on an unlocked table is the dropdown's job.
647650
const anyLocked = lockedNouns(tableData.locks).length > 0
648-
// Name the mode when locked so the state is legible on open; admins get the
649-
// entry point on an unlocked table only where the feature is enabled —
650-
// otherwise the panel opens and Save 403s against the server-side gate.
651-
const lockLabel = anyLocked ? describeLocks(tableData.locks).name : 'Lock settings'
652651
return [
653-
...(anyLocked || (userPermissions.canAdmin && tableLocksEnabled)
652+
...(anyLocked
654653
? [
655654
{
656-
label: lockLabel,
655+
label: describeLocks(tableData.locks).name,
657656
icon: Lock,
658657
onClick: () =>
659658
userPermissions.canAdmin ? setShowLockSettings(true) : showBlockedToast('status'),

0 commit comments

Comments
 (0)