Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ describe("getEntryEditRestrictionForField", () => {
expect(getEntryEditRestrictionForField(meta())).toBe(
ENTRY_RESTRICTION_MESSAGES.unlocalized
);
setEntryEditRestriction(scope, "entryLocked");
expect(getEntryEditRestrictionForField(meta())).toBe(
ENTRY_RESTRICTION_MESSAGES.entryLocked
);
Comment on lines +58 to +61

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should fix — This exercises the union member and the message, but not the line that makes the feature work across the parent boundary.

setEntryEditRestriction takes an already-typed EntryEditRestriction and writes it straight to the store, so nothing here passes through toEntryEditRestriction. The "entryLocked" entry you added to RESTRICTIONS in fieldLockStore.ts is the only thing that lets the parent's string survive, and it has no coverage: delete that one line and this suite still passes while a locked entry stays fully editable on a real canvas.

Worth a case on the parent path, alongside the existing ENTRY_EDIT_RESTRICTION_UPDATE test in the restriction updates block:

it("accepts entryLocked from the parent", () => {
    useEntryEditRestrictionUpdateEvent();
    const handler = mockPostMessage.on.mock.calls[0][1] as any;
    handler({ data: { ...scope, restriction: "entryLocked" } });
    expect(getEntryEditRestriction(scope)).toBe("entryLocked");
});

Generated by Claude Code

setEntryEditRestriction(scope, "unsavedVariant");
expect(getEntryEditRestrictionForField(meta())).toBe(
ENTRY_RESTRICTION_MESSAGES.unsavedVariant
Expand Down
2 changes: 2 additions & 0 deletions src/visualBuilder/utils/fieldLockIndicator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ export function getPeerLockForField(
export const ENTRY_RESTRICTION_MESSAGES: Record<EntryEditRestriction, string> = {
olderVersion:
"You're viewing an older version of this entry. Switch to the latest version to edit.",
entryLocked:
"This entry was updated by someone else. Reload the entry to keep editing.",
unlocalized:
"This entry isn't localized in this language yet. Save it from the form to localize it, then edit here.",
unsavedVariant:
Expand Down
2 changes: 2 additions & 0 deletions src/visualBuilder/utils/fieldLockStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export type EntryFieldLockInfo = Record<string, EntryFieldLock>;
/** Why the parent has turned editing off for a whole entry scope. */
export type EntryEditRestriction =
| "olderVersion"
| "entryLocked"
| "unlocalized"
| "unsavedVariant";

Expand Down Expand Up @@ -122,6 +123,7 @@ export function getEntryEditRestrictionWriteSeq(): number {

const RESTRICTIONS: ReadonlySet<string> = new Set([
"olderVersion",
"entryLocked",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit — This set repeats the EntryEditRestriction union with nothing tying the two together, so they can drift silently.

ENTRY_RESTRICTION_MESSAGES is typed Record<EntryEditRestriction, string>, so a missing message breaks the build. This set is a ReadonlySet<string>, so the next restriction added to the union compiles clean while toEntryEditRestriction quietly rejects it at runtime, which fails in the direction nobody checks. You updated both correctly here; nothing makes the next person do the same.

Keying it by the union turns that into a compile error:

const RESTRICTIONS: Record<EntryEditRestriction, true> = {
    olderVersion: true,
    entryLocked: true,
    unlocalized: true,
    unsavedVariant: true,
};

toEntryEditRestriction would then test with Object.prototype.hasOwnProperty.call(RESTRICTIONS, value). Deriving the set from the messages record would be the other option, but it would import fieldLockIndicator back into this module and close an import cycle, so I would not go that way.


Generated by Claude Code

"unlocalized",
"unsavedVariant",
]);
Expand Down
Loading