Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Support unsetting the text resource in the text resource picker #14496

Merged
merged 5 commits into from
Jan 27, 2025
Merged
Show file tree
Hide file tree
Changes from 3 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
2 changes: 1 addition & 1 deletion frontend/language/src/nb.json
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,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}}",
Expand All @@ -178,6 +177,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",
standeren marked this conversation as resolved.
Show resolved Hide resolved
"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",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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),
noTextResourceOptionLabel: 'None',
valueLabel: createTextResourceValueLabel(rowNumber, property),
};
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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';
Expand Down Expand Up @@ -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),
noTextResourceOptionLabel: 'Ikke oppgitt',
valueLabel: textResourceValueLabel(rowNumber),
});
Original file line number Diff line number Diff line change
Expand Up @@ -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',
noTextResourceOptionLabel: 'Ikke oppgitt',
valueLabel: 'Tekstverdi',
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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',
noTextResourceOptionLabel: 'Ikke oppgitt',
valueLabel: 'Tekstverdi',
};
const currentId = 'land.NO';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,12 +128,12 @@ const InputBox = forwardRef<HTMLInputElement, InputBoxProps>(
return (
<StudioTextResourcePicker
className={className}
emptyListText={texts.emptyResourceList}
label={texts.textResourcePickerLabel}
onValueChange={onChangeCurrentId}
onKeyDown={onKeyDown}
textResources={textResources}
ref={ref}
textResources={textResources}
noTextResourceOptionLabel={texts.noTextResourceOptionLabel}
value={currentId}
{...rest}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export enum Mode {
EditValue = 'editValue',
Search = 'search',
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
export type TextResourceInputTexts = {
emptyResourceList: string;
editValue: string;
search: string;
idLabel: string;
valueLabel: string;
textResourcePickerLabel: string;
noTextResourceOptionLabel: string;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.noTextResourceOption label {
font-style: italic;
}
Original file line number Diff line number Diff line change
Expand Up @@ -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),
noTextResourceOptionLabel: 'Ikke oppgitt',
value: 'land.NO',
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -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 noTextResourceOptionLabel = 'Unset';
const defaultProps: StudioTextResourcePickerProps = {
emptyListText,
onValueChange,
textResources,
noTextResourceOptionLabel,
};

describe('StudioTextResourcePicker', () => {
beforeEach(jest.clearAllMocks);

it('Renders a combobox', () => {
renderTextResourcePicker();
expect(getCombobox()).toBeInTheDocument();
Expand Down Expand Up @@ -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 no text resource option when the user clicks', async () => {
const user = userEvent.setup();
renderTextResourcePicker();
await user.click(getCombobox());
expect(screen.getByRole('option', { name: noTextResourceOptionLabel })).toBeInTheDocument();
});

it('Renders with the no text resource option selected by default', () => {
renderTextResourcePicker();
expect(getCombobox()).toHaveValue(noTextResourceOptionLabel);
});

it('Calls the onValueChange callback with null when the user selects the unset option', async () => {
standeren marked this conversation as resolved.
Show resolved Hide resolved
const user = userEvent.setup();
const value = textResources[129].id;
renderTextResourcePicker({ value });
await user.click(getCombobox());
await user.click(screen.getByRole('option', { name: noTextResourceOptionLabel }));
await waitFor(expect(onValueChange).toHaveBeenCalled);
expect(onValueChange).toHaveBeenCalledTimes(1);
expect(onValueChange).toHaveBeenCalledWith(null);
});

it('Forwards the ref', () => {
testRefForwarding<HTMLInputElement>((ref) => renderTextResourcePicker({}, ref), getCombobox);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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[];
noTextResourceOptionLabel: string;
value?: string;
},
StudioComboboxProps
>;

export const StudioTextResourcePicker = forwardRef<HTMLInputElement, StudioTextResourcePickerProps>(
({ textResources, onSelect, onValueChange, emptyListText, value, ...rest }, ref) => {
const handleValueChange = useCallback(([id]: string[]) => onValueChange(id), [onValueChange]);
({ textResources, onSelect, onValueChange, noTextResourceOptionLabel, value, ...rest }, ref) => {
const handleValueChange = useCallback(
([id]: string[]) => onValueChange(id || null),
[onValueChange],
);

return (
<StudioCombobox
hideLabel
onValueChange={handleValueChange}
value={value ? [value] : []}
value={value ? [value] : ['']}
{...rest}
ref={ref}
>
<StudioCombobox.Empty>{emptyListText}</StudioCombobox.Empty>
{renderNoTextResourceOption(noTextResourceOptionLabel)}
{renderTextResourceOptions(textResources)}
</StudioCombobox>
);
},
);

function renderNoTextResourceOption(label: string): ReactElement {
// This cannot be a component function since the option component must be a direct child of the combobox component.
standeren marked this conversation as resolved.
Show resolved Hide resolved
return (
<StudioCombobox.Option className={classes.noTextResourceOption} value=''>
{label}
</StudioCombobox.Option>
);
}

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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 }),
noTextResourceOptionLabel: t(`${prefix}.unset_option_label`),
valueLabel: t(`${prefix}.${property}.value`, { number }),
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ function useTextResourceTexts(): (
idLabel: t(`${prefix}.id_label`),
search: t(`${prefix}.${property}.search_mode`, { number }),
textResourcePickerLabel: t(`${prefix}.${property}.select`, { number }),
noTextResourceOptionLabel: t(`${prefix}.unset_option_label`),
valueLabel: t(`${prefix}.${property}.value`, { number }),
});
}
Loading