diff --git a/frontend/language/src/nb.json b/frontend/language/src/nb.json index 2771b095367..94a7a0299c4 100644 --- a/frontend/language/src/nb.json +++ b/frontend/language/src/nb.json @@ -148,7 +148,6 @@ "code_list_editor.text_resource.description.search_mode": "Søkemodus for beskrivelse til element nummer {{number}}", "code_list_editor.text_resource.description.select": "Finn beskrivelse for verdi nummer {{number}}", "code_list_editor.text_resource.description.value": "Oppgi beskrivelse for verdi nummer {{number}}", - "code_list_editor.text_resource.empty_list": "Fant ingen tekstressurser.", "code_list_editor.text_resource.helpText.edit_mode": "Redigeringsmodus for hjelpetekst til element nummer {{number}}", "code_list_editor.text_resource.helpText.search_mode": "Søkemodus for hjelpetekst til element nummer {{number}}", "code_list_editor.text_resource.helpText.select": "Finn hjelpetekst for verdi nummer {{number}}", @@ -158,6 +157,7 @@ "code_list_editor.text_resource.label.search_mode": "Søkemodus for ledetekst til element nummer {{number}}", "code_list_editor.text_resource.label.select": "Finn ledetekst for verdi nummer {{number}}", "code_list_editor.text_resource.label.value": "Oppgi ledetekst for verdi nummer {{number}}", + "code_list_editor.text_resource.unset_option_label": "Ikke oppgitt", "code_list_editor.value_item": "Verdi for alternativ {{number}}", "contact.altinn_servicedesk.content": "Er du tjenesteeier og har du behov for hjelp? Ta kontakt med oss!", "contact.altinn_servicedesk.heading": "Altinn Servicedesk", diff --git a/frontend/libs/studio-components/src/components/StudioCodelistEditor/test-data/texts.ts b/frontend/libs/studio-components/src/components/StudioCodelistEditor/test-data/texts.ts index 3e5b5844899..7d58c9f6a3f 100644 --- a/frontend/libs/studio-components/src/components/StudioCodelistEditor/test-data/texts.ts +++ b/frontend/libs/studio-components/src/components/StudioCodelistEditor/test-data/texts.ts @@ -31,10 +31,10 @@ function textResourceTexts( ): TextResourceInputTexts { return { editValue: createTextResourceEditButtonTitle(rowNumber, property), - emptyResourceList: 'No text resources found.', idLabel: 'ID:', search: createTextResourceSearchButtonTitle(rowNumber, property), textResourcePickerLabel: createTextResourcePickerLabel(rowNumber, property), + unsetOptionLabel: 'None', valueLabel: createTextResourceValueLabel(rowNumber, property), }; } diff --git a/frontend/libs/studio-components/src/components/StudioInputTable/test-data/testTableData.ts b/frontend/libs/studio-components/src/components/StudioInputTable/test-data/testTableData.ts index 94227ab4c75..322704ed718 100644 --- a/frontend/libs/studio-components/src/components/StudioInputTable/test-data/testTableData.ts +++ b/frontend/libs/studio-components/src/components/StudioInputTable/test-data/testTableData.ts @@ -1,5 +1,5 @@ import type { CellTextResourceInputProps } from '../Cell/CellTextResource'; -import type { TextResourceInputTexts } from '../../StudioTextResourceInput/types/TextResourceInputTexts'; +import type { TextResourceInputTexts } from '../../StudioTextResourceInput'; import { textResourcesMock } from '../../../test-data/textResourcesMock'; export const headerCheckboxLabel = 'Select all'; @@ -35,9 +35,9 @@ export const textResourceProps = (rowNumber: number): CellTextResourceInputProps export const textResourceTexts = (rowNumber: number): TextResourceInputTexts => ({ editValue: textResourceEditLabel(rowNumber), - emptyResourceList: 'Fant ingen tekstressurser', idLabel: 'ID:', search: textResourceSearchLabel(rowNumber), textResourcePickerLabel: textResourcePickerLabel(rowNumber), + unsetOptionLabel: 'Ikke oppgitt', valueLabel: textResourceValueLabel(rowNumber), }); diff --git a/frontend/libs/studio-components/src/components/StudioTextResourceInput/StudioTextResourceInput.stories.tsx b/frontend/libs/studio-components/src/components/StudioTextResourceInput/StudioTextResourceInput.stories.tsx index 8c5c8398b82..436a43034aa 100644 --- a/frontend/libs/studio-components/src/components/StudioTextResourceInput/StudioTextResourceInput.stories.tsx +++ b/frontend/libs/studio-components/src/components/StudioTextResourceInput/StudioTextResourceInput.stories.tsx @@ -37,10 +37,10 @@ export const Preview: Story = { textResources: textResourcesMock, texts: { editValue: 'Rediger verdi', - emptyResourceList: 'Fant ingen tekstressurser', idLabel: 'ID:', search: 'Søk', textResourcePickerLabel: 'Velg tekstressurs', + unsetOptionLabel: 'Ikke oppgitt', valueLabel: 'Tekstverdi', }, }, diff --git a/frontend/libs/studio-components/src/components/StudioTextResourceInput/StudioTextResourceInput.test.tsx b/frontend/libs/studio-components/src/components/StudioTextResourceInput/StudioTextResourceInput.test.tsx index 366084cf827..b00bf0fa36c 100644 --- a/frontend/libs/studio-components/src/components/StudioTextResourceInput/StudioTextResourceInput.test.tsx +++ b/frontend/libs/studio-components/src/components/StudioTextResourceInput/StudioTextResourceInput.test.tsx @@ -18,10 +18,10 @@ import { testCustomAttributes } from '../../test-utils/testCustomAttributes'; const textResources: TextResource[] = textResourcesMock; const texts: TextResourceInputTexts = { editValue: 'Rediger verdi', - emptyResourceList: 'Fant ingen tekstressurser', idLabel: 'ID:', search: 'Søk', textResourcePickerLabel: 'Velg tekstressurs', + unsetOptionLabel: 'Ikke oppgitt', valueLabel: 'Tekstverdi', }; const currentId = 'land.NO'; diff --git a/frontend/libs/studio-components/src/components/StudioTextResourceInput/StudioTextResourceInput.tsx b/frontend/libs/studio-components/src/components/StudioTextResourceInput/StudioTextResourceInput.tsx index ff9625132f6..fdac921c40b 100644 --- a/frontend/libs/studio-components/src/components/StudioTextResourceInput/StudioTextResourceInput.tsx +++ b/frontend/libs/studio-components/src/components/StudioTextResourceInput/StudioTextResourceInput.tsx @@ -128,12 +128,12 @@ const InputBox = forwardRef( return ( diff --git a/frontend/libs/studio-components/src/components/StudioTextResourceInput/types/Mode.ts b/frontend/libs/studio-components/src/components/StudioTextResourceInput/types/Mode.ts new file mode 100644 index 00000000000..b764d754993 --- /dev/null +++ b/frontend/libs/studio-components/src/components/StudioTextResourceInput/types/Mode.ts @@ -0,0 +1,4 @@ +export enum Mode { + EditValue = 'editValue', + Search = 'search', +} diff --git a/frontend/libs/studio-components/src/components/StudioTextResourceInput/types/TextResourceInputTexts.ts b/frontend/libs/studio-components/src/components/StudioTextResourceInput/types/TextResourceInputTexts.ts index d7db6f24b88..be06896c946 100644 --- a/frontend/libs/studio-components/src/components/StudioTextResourceInput/types/TextResourceInputTexts.ts +++ b/frontend/libs/studio-components/src/components/StudioTextResourceInput/types/TextResourceInputTexts.ts @@ -1,8 +1,8 @@ export type TextResourceInputTexts = { - emptyResourceList: string; editValue: string; search: string; idLabel: string; valueLabel: string; textResourcePickerLabel: string; + unsetOptionLabel: string; }; diff --git a/frontend/libs/studio-components/src/components/StudioTextResourcePicker/StudioTextResourcePicker.module.css b/frontend/libs/studio-components/src/components/StudioTextResourcePicker/StudioTextResourcePicker.module.css new file mode 100644 index 00000000000..68f6db86cfe --- /dev/null +++ b/frontend/libs/studio-components/src/components/StudioTextResourcePicker/StudioTextResourcePicker.module.css @@ -0,0 +1,3 @@ +.unsetOption label { + font-style: italic; +} diff --git a/frontend/libs/studio-components/src/components/StudioTextResourcePicker/StudioTextResourcePicker.stories.tsx b/frontend/libs/studio-components/src/components/StudioTextResourcePicker/StudioTextResourcePicker.stories.tsx index 98f737c4278..be675311a40 100644 --- a/frontend/libs/studio-components/src/components/StudioTextResourcePicker/StudioTextResourcePicker.stories.tsx +++ b/frontend/libs/studio-components/src/components/StudioTextResourcePicker/StudioTextResourcePicker.stories.tsx @@ -13,9 +13,9 @@ export default meta; export const Preview: Story = { args: { label: 'Velg tekst', - emptyListText: 'Fant ingen tekster', textResources: textResourcesMock, onValueChange: (id: string) => console.log(id), + unsetOptionLabel: 'Ikke oppgitt', value: 'land.NO', }, }; diff --git a/frontend/libs/studio-components/src/components/StudioTextResourcePicker/StudioTextResourcePicker.test.tsx b/frontend/libs/studio-components/src/components/StudioTextResourcePicker/StudioTextResourcePicker.test.tsx index 9f56f380d0d..d23bea8333d 100644 --- a/frontend/libs/studio-components/src/components/StudioTextResourcePicker/StudioTextResourcePicker.test.tsx +++ b/frontend/libs/studio-components/src/components/StudioTextResourcePicker/StudioTextResourcePicker.test.tsx @@ -14,14 +14,16 @@ import type { TextResource } from '../../types/TextResource'; // Test data: const textResources = textResourcesMock; const onValueChange = jest.fn(); -const emptyListText = 'No text resources'; +const unsetOptionLabel = 'Unset'; const defaultProps: StudioTextResourcePickerProps = { - emptyListText, onValueChange, textResources, + unsetOptionLabel, }; describe('StudioTextResourcePicker', () => { + beforeEach(jest.clearAllMocks); + it('Renders a combobox', () => { renderTextResourcePicker(); expect(getCombobox()).toBeInTheDocument(); @@ -58,19 +60,35 @@ describe('StudioTextResourcePicker', () => { expect(onValueChange).toHaveBeenCalledWith(textResourceToPick.id); }); - it('Displays the empty list text when the user clicks and there are no text resources', async () => { - const user = userEvent.setup(); - renderTextResourcePicker({ textResources: [] }); - await user.click(getCombobox()); - expect(screen.getByText(emptyListText)).toBeInTheDocument(); - }); - it("Renders with the text of the text resource of which the ID is given by the component's value prop", () => { const pickedTextResource = textResources[129]; renderTextResourcePicker({ value: pickedTextResource.id }); expect(getCombobox()).toHaveValue(pickedTextResource.value); }); + it('Displays the unset option when the user clicks', async () => { + const user = userEvent.setup(); + renderTextResourcePicker(); + await user.click(getCombobox()); + expect(screen.getByRole('option', { name: unsetOptionLabel })).toBeInTheDocument(); + }); + + it('Renders with the unset option selected by default', () => { + renderTextResourcePicker(); + expect(getCombobox()).toHaveValue(unsetOptionLabel); + }); + + it('Calls the onValueChange callback with null when the user selects the unset option', async () => { + const user = userEvent.setup(); + const value = textResources[129].id; + renderTextResourcePicker({ value }); + await user.click(getCombobox()); + await user.click(screen.getByRole('option', { name: unsetOptionLabel })); + await waitFor(expect(onValueChange).toHaveBeenCalled); + expect(onValueChange).toHaveBeenCalledTimes(1); + expect(onValueChange).toHaveBeenCalledWith(null); + }); + it('Forwards the ref', () => { testRefForwarding((ref) => renderTextResourcePicker({}, ref), getCombobox); }); diff --git a/frontend/libs/studio-components/src/components/StudioTextResourcePicker/StudioTextResourcePicker.tsx b/frontend/libs/studio-components/src/components/StudioTextResourcePicker/StudioTextResourcePicker.tsx index cd5ecd92fd4..aeb56e718e9 100644 --- a/frontend/libs/studio-components/src/components/StudioTextResourcePicker/StudioTextResourcePicker.tsx +++ b/frontend/libs/studio-components/src/components/StudioTextResourcePicker/StudioTextResourcePicker.tsx @@ -4,36 +4,49 @@ import type { TextResource } from '../../types/TextResource'; import type { StudioComboboxProps } from '../StudioCombobox'; import { StudioCombobox } from '../StudioCombobox'; import type { Override } from '../../types/Override'; +import classes from './StudioTextResourcePicker.module.css'; export type StudioTextResourcePickerProps = Override< { - emptyListText: string; - onValueChange: (id: string) => void; + onValueChange: (id: string | null) => void; textResources: TextResource[]; + unsetOptionLabel: string; value?: string; }, StudioComboboxProps >; export const StudioTextResourcePicker = forwardRef( - ({ textResources, onSelect, onValueChange, emptyListText, value, ...rest }, ref) => { - const handleValueChange = useCallback(([id]: string[]) => onValueChange(id), [onValueChange]); + ({ textResources, onSelect, onValueChange, unsetOptionLabel, value, ...rest }, ref) => { + const handleValueChange = useCallback( + ([id]: string[]) => onValueChange(id || null), + [onValueChange], + ); return ( - {emptyListText} + {renderUnsetOption(unsetOptionLabel)} {renderTextResourceOptions(textResources)} ); }, ); +function renderUnsetOption(label: string): ReactElement { + // This cannot be a component function since the option component must be a direct child of the combobox component. + return ( + + {label} + + ); +} + function renderTextResourceOptions(textResources: TextResource[]): ReactElement[] { // This cannot be a component function since the option components must be direct children of the combobox component. return textResources.map(renderTextResourceOption); diff --git a/frontend/libs/studio-content-library/src/ContentLibrary/LibraryBody/pages/CodeListPage/hooks/useCodeListEditorTexts.ts b/frontend/libs/studio-content-library/src/ContentLibrary/LibraryBody/pages/CodeListPage/hooks/useCodeListEditorTexts.ts index a3324e38017..089b85f024e 100644 --- a/frontend/libs/studio-content-library/src/ContentLibrary/LibraryBody/pages/CodeListPage/hooks/useCodeListEditorTexts.ts +++ b/frontend/libs/studio-content-library/src/ContentLibrary/LibraryBody/pages/CodeListPage/hooks/useCodeListEditorTexts.ts @@ -39,10 +39,10 @@ function useTextResourceTexts(): ( const prefix = 'code_list_editor.text_resource'; return (number: number, property: CodeListItemTextProperty) => ({ editValue: t(`${prefix}.${property}.edit_mode`, { number }), - emptyResourceList: t(`${prefix}.empty_list`), idLabel: t(`${prefix}.id_label`), search: t(`${prefix}.${property}.search_mode`, { number }), textResourcePickerLabel: t(`${prefix}.${property}.select`, { number }), + unsetOptionLabel: t(`${prefix}.unset_option_label`), valueLabel: t(`${prefix}.${property}.value`, { number }), }); } diff --git a/frontend/packages/ux-editor/src/components/config/editModal/EditOptions/OptionTabs/hooks/useOptionListEditorTexts.ts b/frontend/packages/ux-editor/src/components/config/editModal/EditOptions/OptionTabs/hooks/useOptionListEditorTexts.ts index 0bae3659964..6d0fca41528 100644 --- a/frontend/packages/ux-editor/src/components/config/editModal/EditOptions/OptionTabs/hooks/useOptionListEditorTexts.ts +++ b/frontend/packages/ux-editor/src/components/config/editModal/EditOptions/OptionTabs/hooks/useOptionListEditorTexts.ts @@ -43,6 +43,7 @@ function useTextResourceTexts(): ( idLabel: t(`${prefix}.id_label`), search: t(`${prefix}.${property}.search_mode`, { number }), textResourcePickerLabel: t(`${prefix}.${property}.select`, { number }), + unsetOptionLabel: t(`${prefix}.unset_option_label`), valueLabel: t(`${prefix}.${property}.value`, { number }), }); }