From cf47ad27de26019f3fe15f83c97516cfd93d0943 Mon Sep 17 00:00:00 2001 From: Danny Rorabaugh Date: Tue, 6 Aug 2024 16:48:16 -0400 Subject: [PATCH 1/3] Fix vern focus issues --- .../GlossWithSuggestions.tsx | 8 +------ .../VernWithSuggestions.tsx | 14 +++++++------ .../DataEntryTable/NewEntry/VernDialog.tsx | 1 + .../DataEntryTable/NewEntry/index.tsx | 21 ++++++------------- 4 files changed, 16 insertions(+), 28 deletions(-) diff --git a/src/components/DataEntry/DataEntryTable/EntryCellComponents/GlossWithSuggestions.tsx b/src/components/DataEntry/DataEntryTable/EntryCellComponents/GlossWithSuggestions.tsx index f4db3e58e1..3c1a1d1651 100644 --- a/src/components/DataEntry/DataEntryTable/EntryCellComponents/GlossWithSuggestions.tsx +++ b/src/components/DataEntry/DataEntryTable/EntryCellComponents/GlossWithSuggestions.tsx @@ -48,7 +48,6 @@ export default function GlossWithSuggestions( filterOptions={(options) => options} // freeSolo allows use of a typed entry not available as a drop-down option freeSolo - includeInputInList // option-never-equals-value prevents automatic option highlighting isOptionEqualToValue={() => false} options={spellChecker.getSpellingSuggestions(props.gloss)} @@ -58,13 +57,7 @@ export default function GlossWithSuggestions( props.onBlur(); } }} - onChange={(_e, newValue) => { - // onChange is triggered when an option is selected - props.updateGlossField(newValue ?? ""); - }} - inputValue={props.gloss} onInputChange={(_e, newInputValue) => { - // onInputChange is triggered by typing props.updateGlossField(newInputValue); }} renderInput={(params) => ( @@ -83,6 +76,7 @@ export default function GlossWithSuggestions( {...liProps} analysis aria-selected={selected} + key={option} lang={props.analysisLang.bcp47} > {SpellChecker.replaceAllButLastWordWithEllipses(option)} diff --git a/src/components/DataEntry/DataEntryTable/EntryCellComponents/VernWithSuggestions.tsx b/src/components/DataEntry/DataEntryTable/EntryCellComponents/VernWithSuggestions.tsx index 661ce52c9e..f868027d76 100644 --- a/src/components/DataEntry/DataEntryTable/EntryCellComponents/VernWithSuggestions.tsx +++ b/src/components/DataEntry/DataEntryTable/EntryCellComponents/VernWithSuggestions.tsx @@ -47,14 +47,11 @@ export default function VernWithSuggestions( freeSolo value={props.vernacular} options={props.suggestedVerns ?? []} + // option-never-equals-value prevents automatic option highlighting + isOptionEqualToValue={() => false} onBlur={props.onBlur} - onChange={(_e, value) => { - // onChange is triggered when an option is selected - props.updateVernField(value ?? "", true); - }} onFocus={props.onFocus} onInputChange={(_e, value) => { - // onInputChange is triggered by typing props.updateVernField(value); }} onKeyPress={(e: KeyboardEvent) => { @@ -74,7 +71,12 @@ export default function VernWithSuggestions( /> )} renderOption={(liProps, option, { selected }) => ( - + {option} )} diff --git a/src/components/DataEntry/DataEntryTable/NewEntry/VernDialog.tsx b/src/components/DataEntry/DataEntryTable/NewEntry/VernDialog.tsx index c64fd130c6..d65818911d 100644 --- a/src/components/DataEntry/DataEntryTable/NewEntry/VernDialog.tsx +++ b/src/components/DataEntry/DataEntryTable/NewEntry/VernDialog.tsx @@ -30,6 +30,7 @@ export default function VernDialog(props: vernDialogProps): ReactElement { return ( { if (reason !== "backdropClick") { diff --git a/src/components/DataEntry/DataEntryTable/NewEntry/index.tsx b/src/components/DataEntry/DataEntryTable/NewEntry/index.tsx index 361ef56ad0..97305733c0 100644 --- a/src/components/DataEntry/DataEntryTable/NewEntry/index.tsx +++ b/src/components/DataEntry/DataEntryTable/NewEntry/index.tsx @@ -206,19 +206,12 @@ export default function NewEntry(props: NewEntryProps): ReactElement { } }; - const handleEnter = async (checkGloss: boolean): Promise => { + const handleGlossEnter = async (): Promise => { // The user can never submit a new entry without a vernacular if (newVern) { - // The user can conditionally submit a new entry without a gloss - if (newGloss || !checkGloss) { - await addOrUpdateWord(); - focus(FocusTarget.Vernacular); - } else { - focus(FocusTarget.Gloss); - } - } else { - focus(FocusTarget.Vernacular); + await addOrUpdateWord(); } + focus(FocusTarget.Vernacular); }; /** Clear the duplicate selection if user returns to the vernacular field. */ @@ -270,8 +263,8 @@ export default function NewEntry(props: NewEntryProps): ReactElement { onFocus={handleOnVernFocus} suggestedVerns={suggestedVerns} // To prevent unintentional no-gloss submissions: - // If enter pressed from the vern field, check whether gloss is empty - handleEnter={() => handleEnter(true)} + // If enter pressed from the vern field, move focus to gloss field. + handleEnter={() => focus(FocusTarget.Gloss)} vernacularLang={vernacularLang} textFieldId={NewEntryId.TextFieldVern} onUpdate={() => conditionalFocus(FocusTarget.Vernacular)} @@ -298,9 +291,7 @@ export default function NewEntry(props: NewEntryProps): ReactElement { gloss={newGloss} glossInput={glossInput} updateGlossField={setNewGloss} - // To allow intentional no-gloss submissions: - // If enter pressed from the gloss field, don't check whether gloss is empty - handleEnter={() => handleEnter(false)} + handleEnter={() => handleGlossEnter()} analysisLang={analysisLang} textFieldId={NewEntryId.TextFieldGloss} onUpdate={() => conditionalFocus(FocusTarget.Gloss)} From 58ec74c66e07bf037f12071d38bed2e713da386c Mon Sep 17 00:00:00 2001 From: Danny Rorabaugh Date: Tue, 6 Aug 2024 17:09:18 -0400 Subject: [PATCH 2/3] Expand comments --- .../EntryCellComponents/GlossWithSuggestions.tsx | 5 +++++ src/components/DataEntry/DataEntryTable/NewEntry/index.tsx | 5 +++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/components/DataEntry/DataEntryTable/EntryCellComponents/GlossWithSuggestions.tsx b/src/components/DataEntry/DataEntryTable/EntryCellComponents/GlossWithSuggestions.tsx index 3c1a1d1651..3870824f27 100644 --- a/src/components/DataEntry/DataEntryTable/EntryCellComponents/GlossWithSuggestions.tsx +++ b/src/components/DataEntry/DataEntryTable/EntryCellComponents/GlossWithSuggestions.tsx @@ -82,6 +82,11 @@ export default function GlossWithSuggestions( {SpellChecker.replaceAllButLastWordWithEllipses(option)} )} + /* Even though `onKeyPress` is deprecated, we need to keep using it: + * - `onKeyDown` doesn't work with spelling suggestion selection via Enter, + * because the submission occurs before the selected suggestion is applied; + * - `onKeyUp` doesn't work with SenseDialog selection via Enter, + * because the dialog closes before the key is released. */ onKeyPress={(e: KeyboardEvent) => { if (e.key === Key.Enter) { props.handleEnter(); diff --git a/src/components/DataEntry/DataEntryTable/NewEntry/index.tsx b/src/components/DataEntry/DataEntryTable/NewEntry/index.tsx index 97305733c0..162fa7f64d 100644 --- a/src/components/DataEntry/DataEntryTable/NewEntry/index.tsx +++ b/src/components/DataEntry/DataEntryTable/NewEntry/index.tsx @@ -262,8 +262,9 @@ export default function NewEntry(props: NewEntryProps): ReactElement { }} onFocus={handleOnVernFocus} suggestedVerns={suggestedVerns} - // To prevent unintentional no-gloss submissions: - // If enter pressed from the vern field, move focus to gloss field. + // To prevent unintentional no-gloss or wrong-gloss submissions + // and to simplify interactions with Autocomplete and with the dialogs: + // if Enter is pressed from the vern field, move focus to gloss field. handleEnter={() => focus(FocusTarget.Gloss)} vernacularLang={vernacularLang} textFieldId={NewEntryId.TextFieldVern} From 8b3c7d5c51690038ef94df5a0bcecaeb3e27837d Mon Sep 17 00:00:00 2001 From: Danny Rorabaugh Date: Wed, 7 Aug 2024 11:20:46 -0400 Subject: [PATCH 3/3] Remove unused prop --- .../DataEntry/DataEntryTable/EntryCellComponents/DeleteEntry.tsx | 1 - src/components/DataEntry/DataEntryTable/RecentEntry.tsx | 1 - 2 files changed, 2 deletions(-) diff --git a/src/components/DataEntry/DataEntryTable/EntryCellComponents/DeleteEntry.tsx b/src/components/DataEntry/DataEntryTable/EntryCellComponents/DeleteEntry.tsx index dcb2976e2a..6b769482f2 100644 --- a/src/components/DataEntry/DataEntryTable/EntryCellComponents/DeleteEntry.tsx +++ b/src/components/DataEntry/DataEntryTable/EntryCellComponents/DeleteEntry.tsx @@ -13,7 +13,6 @@ interface DeleteEntryProps { // and deletion will happen when the button is pressed confirmId?: string; disabled?: boolean; - wordId?: string; } /** diff --git a/src/components/DataEntry/DataEntryTable/RecentEntry.tsx b/src/components/DataEntry/DataEntryTable/RecentEntry.tsx index 80088b4191..bdedce59ef 100644 --- a/src/components/DataEntry/DataEntryTable/RecentEntry.tsx +++ b/src/components/DataEntry/DataEntryTable/RecentEntry.tsx @@ -171,7 +171,6 @@ export function RecentEntry(props: RecentEntryProps): ReactElement { buttonId={`${idAffix}-${props.rowIndex}-delete`} confirmId={"addWords.deleteRowWarning"} disabled={editing || props.disabled} - wordId={props.entry.id} />