From 852431c537842d1cc609dcba830576a2ef9d5aac Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 28 Oct 2025 18:49:35 +0000 Subject: [PATCH 1/6] Initial plan From 7c22f9075e0d39271661b64869ec8a5f0b7d8c34 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 28 Oct 2025 19:01:08 +0000 Subject: [PATCH 2/6] Add protection check for vernacular field in RecentEntry Co-authored-by: imnasnainaec <6411521+imnasnainaec@users.noreply.github.com> --- .../DataEntry/DataEntryTable/RecentEntry.tsx | 9 +++- .../DataEntryTable/tests/RecentEntry.test.tsx | 45 ++++++++++++++++++- 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/src/components/DataEntry/DataEntryTable/RecentEntry.tsx b/src/components/DataEntry/DataEntryTable/RecentEntry.tsx index b6f0e68aa5..d955cac404 100644 --- a/src/components/DataEntry/DataEntryTable/RecentEntry.tsx +++ b/src/components/DataEntry/DataEntryTable/RecentEntry.tsx @@ -80,6 +80,11 @@ export function RecentEntry(props: RecentEntryProps): ReactElement { const handleUpdateNote = (noteText: string): Promise => props.updateNote(props.rowIndex, noteText); + // Check if word or sense is protected + const isProtected = + (props.entry.protectReasons && props.entry.protectReasons.length > 0) || + (sense.protectReasons && sense.protectReasons.length > 0); + return ( 1} + isDisabled={ + props.disabled || props.entry.senses.length > 1 || isProtected + } updateVernField={updateVernField} onBlur={() => conditionallyUpdateVern()} handleEnter={() => { diff --git a/src/components/DataEntry/DataEntryTable/tests/RecentEntry.test.tsx b/src/components/DataEntry/DataEntryTable/tests/RecentEntry.test.tsx index 81e77d24e2..4da7cd9d89 100644 --- a/src/components/DataEntry/DataEntryTable/tests/RecentEntry.test.tsx +++ b/src/components/DataEntry/DataEntryTable/tests/RecentEntry.test.tsx @@ -5,7 +5,7 @@ import userEvent, { UserEvent } from "@testing-library/user-event"; import { Provider } from "react-redux"; import configureMockStore from "redux-mock-store"; -import { Word } from "api/models"; +import { ReasonType, Word } from "api/models"; import RecentEntry, { RecentEntryIdPrefix, } from "components/DataEntry/DataEntryTable/RecentEntry"; @@ -186,4 +186,47 @@ describe("ExistingEntry", () => { expect(mockUpdateNote).toHaveBeenCalledWith(0, mockText); }); }); + + describe("protection", () => { + it("disables vernacular if word is protected", async () => { + const protectedWord: Word = { + ...mockWord, + protectReasons: [{ type: ReasonType.Etymologies }], + }; + await renderWithWord(protectedWord); + const { vernField } = getVernAndGlossFields(); + expect(vernField).toBeDisabled(); + }); + + it("disables vernacular if sense is protected", async () => { + const protectedSenseWord: Word = { + ...mockWord, + senses: [ + { + ...mockWord.senses[0], + protectReasons: [{ type: ReasonType.Examples }], + }, + ], + }; + await renderWithWord(protectedSenseWord); + const { vernField } = getVernAndGlossFields(); + expect(vernField).toBeDisabled(); + }); + + it("enables vernacular if neither word nor sense is protected", async () => { + const unprotectedWord: Word = { + ...mockWord, + protectReasons: [], + senses: [ + { + ...mockWord.senses[0], + protectReasons: [], + }, + ], + }; + await renderWithWord(unprotectedWord); + const { vernField } = getVernAndGlossFields(); + expect(vernField).toBeEnabled(); + }); + }); }); From f1bdf7017a789203cc636856ae55ebb4db4f6953 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 28 Oct 2025 20:35:19 +0000 Subject: [PATCH 3/6] Use accessibility property instead of protectReasons array Co-authored-by: imnasnainaec <6411521+imnasnainaec@users.noreply.github.com> --- .../DataEntry/DataEntryTable/RecentEntry.tsx | 12 +++++------- .../DataEntryTable/tests/RecentEntry.test.tsx | 10 +++++----- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/components/DataEntry/DataEntryTable/RecentEntry.tsx b/src/components/DataEntry/DataEntryTable/RecentEntry.tsx index d955cac404..31ff99e20b 100644 --- a/src/components/DataEntry/DataEntryTable/RecentEntry.tsx +++ b/src/components/DataEntry/DataEntryTable/RecentEntry.tsx @@ -1,7 +1,7 @@ import { Grid2 } from "@mui/material"; import { ReactElement, memo, useState } from "react"; -import { Pronunciation, Word, WritingSystem } from "api/models"; +import { Pronunciation, Status, Word, WritingSystem } from "api/models"; import NoteButton from "components/Buttons/NoteButton"; import { DeleteEntry, @@ -80,11 +80,6 @@ export function RecentEntry(props: RecentEntryProps): ReactElement { const handleUpdateNote = (noteText: string): Promise => props.updateNote(props.rowIndex, noteText); - // Check if word or sense is protected - const isProtected = - (props.entry.protectReasons && props.entry.protectReasons.length > 0) || - (sense.protectReasons && sense.protectReasons.length > 0); - return ( 1 || isProtected + props.disabled || + props.entry.senses.length > 1 || + props.entry.accessibility === Status.Protected || + sense.accessibility === Status.Protected } updateVernField={updateVernField} onBlur={() => conditionallyUpdateVern()} diff --git a/src/components/DataEntry/DataEntryTable/tests/RecentEntry.test.tsx b/src/components/DataEntry/DataEntryTable/tests/RecentEntry.test.tsx index 4da7cd9d89..530a08789d 100644 --- a/src/components/DataEntry/DataEntryTable/tests/RecentEntry.test.tsx +++ b/src/components/DataEntry/DataEntryTable/tests/RecentEntry.test.tsx @@ -5,7 +5,7 @@ import userEvent, { UserEvent } from "@testing-library/user-event"; import { Provider } from "react-redux"; import configureMockStore from "redux-mock-store"; -import { ReasonType, Word } from "api/models"; +import { Status, Word } from "api/models"; import RecentEntry, { RecentEntryIdPrefix, } from "components/DataEntry/DataEntryTable/RecentEntry"; @@ -191,7 +191,7 @@ describe("ExistingEntry", () => { it("disables vernacular if word is protected", async () => { const protectedWord: Word = { ...mockWord, - protectReasons: [{ type: ReasonType.Etymologies }], + accessibility: Status.Protected, }; await renderWithWord(protectedWord); const { vernField } = getVernAndGlossFields(); @@ -204,7 +204,7 @@ describe("ExistingEntry", () => { senses: [ { ...mockWord.senses[0], - protectReasons: [{ type: ReasonType.Examples }], + accessibility: Status.Protected, }, ], }; @@ -216,11 +216,11 @@ describe("ExistingEntry", () => { it("enables vernacular if neither word nor sense is protected", async () => { const unprotectedWord: Word = { ...mockWord, - protectReasons: [], + accessibility: Status.Active, senses: [ { ...mockWord.senses[0], - protectReasons: [], + accessibility: Status.Active, }, ], }; From 48358aac8e1c12ebf88754453f3ef530175acb77 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 28 Oct 2025 20:47:27 +0000 Subject: [PATCH 4/6] Move protection tests into vernacular describe block Co-authored-by: imnasnainaec <6411521+imnasnainaec@users.noreply.github.com> --- .../DataEntryTable/tests/RecentEntry.test.tsx | 84 +++++++++---------- 1 file changed, 41 insertions(+), 43 deletions(-) diff --git a/src/components/DataEntry/DataEntryTable/tests/RecentEntry.test.tsx b/src/components/DataEntry/DataEntryTable/tests/RecentEntry.test.tsx index 530a08789d..9eab88f46a 100644 --- a/src/components/DataEntry/DataEntryTable/tests/RecentEntry.test.tsx +++ b/src/components/DataEntry/DataEntryTable/tests/RecentEntry.test.tsx @@ -132,6 +132,47 @@ describe("ExistingEntry", () => { await agent.click(glossField); expect(mockUpdateVern).toHaveBeenCalledWith(0, mockText); }); + + it("disables vernacular if word is protected", async () => { + const protectedWord: Word = { + ...mockWord, + accessibility: Status.Protected, + }; + await renderWithWord(protectedWord); + const { vernField } = getVernAndGlossFields(); + expect(vernField).toBeDisabled(); + }); + + it("disables vernacular if sense is protected", async () => { + const protectedSenseWord: Word = { + ...mockWord, + senses: [ + { + ...mockWord.senses[0], + accessibility: Status.Protected, + }, + ], + }; + await renderWithWord(protectedSenseWord); + const { vernField } = getVernAndGlossFields(); + expect(vernField).toBeDisabled(); + }); + + it("enables vernacular if neither word nor sense is protected", async () => { + const unprotectedWord: Word = { + ...mockWord, + accessibility: Status.Active, + senses: [ + { + ...mockWord.senses[0], + accessibility: Status.Active, + }, + ], + }; + await renderWithWord(unprotectedWord); + const { vernField } = getVernAndGlossFields(); + expect(vernField).toBeEnabled(); + }); }); describe("gloss", () => { @@ -186,47 +227,4 @@ describe("ExistingEntry", () => { expect(mockUpdateNote).toHaveBeenCalledWith(0, mockText); }); }); - - describe("protection", () => { - it("disables vernacular if word is protected", async () => { - const protectedWord: Word = { - ...mockWord, - accessibility: Status.Protected, - }; - await renderWithWord(protectedWord); - const { vernField } = getVernAndGlossFields(); - expect(vernField).toBeDisabled(); - }); - - it("disables vernacular if sense is protected", async () => { - const protectedSenseWord: Word = { - ...mockWord, - senses: [ - { - ...mockWord.senses[0], - accessibility: Status.Protected, - }, - ], - }; - await renderWithWord(protectedSenseWord); - const { vernField } = getVernAndGlossFields(); - expect(vernField).toBeDisabled(); - }); - - it("enables vernacular if neither word nor sense is protected", async () => { - const unprotectedWord: Word = { - ...mockWord, - accessibility: Status.Active, - senses: [ - { - ...mockWord.senses[0], - accessibility: Status.Active, - }, - ], - }; - await renderWithWord(unprotectedWord); - const { vernField } = getVernAndGlossFields(); - expect(vernField).toBeEnabled(); - }); - }); }); From 82d7252eb6c02b4e55567f783d870fda1d48b95e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 28 Oct 2025 20:57:53 +0000 Subject: [PATCH 5/6] Remove redundant test for enabled vernacular field Co-authored-by: imnasnainaec <6411521+imnasnainaec@users.noreply.github.com> --- .../DataEntryTable/tests/RecentEntry.test.tsx | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/components/DataEntry/DataEntryTable/tests/RecentEntry.test.tsx b/src/components/DataEntry/DataEntryTable/tests/RecentEntry.test.tsx index 9eab88f46a..70b525c541 100644 --- a/src/components/DataEntry/DataEntryTable/tests/RecentEntry.test.tsx +++ b/src/components/DataEntry/DataEntryTable/tests/RecentEntry.test.tsx @@ -157,22 +157,6 @@ describe("ExistingEntry", () => { const { vernField } = getVernAndGlossFields(); expect(vernField).toBeDisabled(); }); - - it("enables vernacular if neither word nor sense is protected", async () => { - const unprotectedWord: Word = { - ...mockWord, - accessibility: Status.Active, - senses: [ - { - ...mockWord.senses[0], - accessibility: Status.Active, - }, - ], - }; - await renderWithWord(unprotectedWord); - const { vernField } = getVernAndGlossFields(); - expect(vernField).toBeEnabled(); - }); }); describe("gloss", () => { From 3e9cd2bae08398230872045e0ba900f225f7351d Mon Sep 17 00:00:00 2001 From: Danny Rorabaugh Date: Wed, 29 Oct 2025 13:33:50 -0400 Subject: [PATCH 6/6] Condense --- .../DataEntry/DataEntryTable/tests/RecentEntry.test.tsx | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/components/DataEntry/DataEntryTable/tests/RecentEntry.test.tsx b/src/components/DataEntry/DataEntryTable/tests/RecentEntry.test.tsx index 70b525c541..9318d91554 100644 --- a/src/components/DataEntry/DataEntryTable/tests/RecentEntry.test.tsx +++ b/src/components/DataEntry/DataEntryTable/tests/RecentEntry.test.tsx @@ -146,12 +146,7 @@ describe("ExistingEntry", () => { it("disables vernacular if sense is protected", async () => { const protectedSenseWord: Word = { ...mockWord, - senses: [ - { - ...mockWord.senses[0], - accessibility: Status.Protected, - }, - ], + senses: [{ ...mockWord.senses[0], accessibility: Status.Protected }], }; await renderWithWord(protectedSenseWord); const { vernField } = getVernAndGlossFields();