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

refactor: Redesign/refactor next recommended action #14032

Merged
merged 30 commits into from
Nov 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
fb09f99
redesign user story for next recommended action for subform component
lassopicasso Nov 8, 2024
11e49b8
remove old code - no subforms available warning
lassopicasso Nov 11, 2024
6dfe24d
add new class
lassopicasso Nov 11, 2024
102dba2
add instructions component if user has no subforms
lassopicasso Nov 11, 2024
9341753
refactor logic
lassopicasso Nov 11, 2024
6ba6f55
new text keys
lassopicasso Nov 11, 2024
1542457
some refactor + subform button in config header + css adjustments
lassopicasso Nov 11, 2024
c0450aa
Merge branch 'main' into redesign/refactor-next-recommended-action
lassopicasso Nov 11, 2024
83c2baf
small refactor + small adjustments + cleanup
lassopicasso Nov 11, 2024
b6bc130
fix tests in createNewsubformlayoutset
lassopicasso Nov 12, 2024
ac8979a
keep the selected layoutset
lassopicasso Nov 12, 2024
5eb7621
fix
lassopicasso Nov 12, 2024
a9fc62b
fix tests
lassopicasso Nov 12, 2024
19cdb8c
remove unused import
lassopicasso Nov 12, 2024
5e83f18
fix tests after change text key
lassopicasso Nov 12, 2024
e145619
add data-testid to card and remove unecessary prop
lassopicasso Nov 13, 2024
0949c94
test-refactor `editLayoutsetforsubform` - remove old tests, update te…
lassopicasso Nov 13, 2024
a815260
tests for editLayoutSet
lassopicasso Nov 13, 2024
fce3b3a
tests for createNewSubformLayoutset
lassopicasso Nov 13, 2024
a81a9bc
tests for subform selector (selectlayoutSet)
lassopicasso Nov 13, 2024
b94074b
remove disabled prop in test
lassopicasso Nov 13, 2024
1234eaa
Merge branch 'main' into redesign/refactor-next-recommended-action
lassopicasso Nov 13, 2024
156b84c
fix conflict issue
lassopicasso Nov 13, 2024
075ce9d
add 1 test to cover coverage
lassopicasso Nov 13, 2024
f5e5a78
remove some unused text keys for subform
lassopicasso Nov 14, 2024
b96e875
Merge branch 'main' into redesign/refactor-next-recommended-action
lassopicasso Nov 14, 2024
542b16d
remove one more unused text key
lassopicasso Nov 14, 2024
a77f3ff
Merge branch 'redesign/refactor-next-recommended-action' of https://g…
lassopicasso Nov 14, 2024
7356545
add testId and sort it alphabetically
lassopicasso Nov 15, 2024
21d4c71
Merge branch 'main' into redesign/refactor-next-recommended-action
lassopicasso Nov 15, 2024
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
18 changes: 12 additions & 6 deletions frontend/language/src/nb.json
Original file line number Diff line number Diff line change
Expand Up @@ -1272,6 +1272,7 @@
"ux_editor.component_properties.minWidth": "Minimumshøyde",
"ux_editor.component_properties.mode": "Modus",
"ux_editor.component_properties.multiPage": "Fordel gruppen over flere sider",
"ux_editor.component_properties.navigate_to_subform_button": "Utform underskjemaet",
"ux_editor.component_properties.nextButton": "Vis Neste-knapp",
"ux_editor.component_properties.openByDefault": "Feltet skal være åpent ved innlasting",
"ux_editor.component_properties.openInNewTab": "Åpne lenken i ny fane",
Expand Down Expand Up @@ -1327,22 +1328,27 @@
"ux_editor.component_properties.stickyHeader": "Fest tittelraden",
"ux_editor.component_properties.style": "Stil",
"ux_editor.component_properties.subdomains": "Subdomener (kommaseparert)",
"ux_editor.component_properties.subform": "Sidegruppe for underskjema",
"ux_editor.component_properties.subform.choose_layout_set": "Velg et underskjema...",
"ux_editor.component_properties.subform.choose_layout_set_description": " Før du kan bruke komponenten Tabell for underskjema, må du velge hvilket underskjema du skal bruke den med. Deretter kan du velge hvilke egenskaper komponenten skal ha.",
"ux_editor.component_properties.subform.choose_layout_set_description": "Velg først underskjemaet du vil bruke i Tabell for underskjema. Deretter kan du sette opp egenskapene for komponenten.",
"ux_editor.component_properties.subform.choose_layout_set_header": "Velg underskjemaet du vil bruke",
"ux_editor.component_properties.subform.choose_layout_set_label": "Velg et underskjema",
"ux_editor.component_properties.subform.create_layout_set_button": "Lag et nytt underskjema",
"ux_editor.component_properties.subform.create_layout_set_description": "Hvis du velger å lage et nytt underskjema, oppretter vi et tomt underskjema for deg. Det må du selv utforme, før du kan sette opp tabellen.",
"ux_editor.component_properties.subform.create_layout_set_button": "Opprett et nytt underskjema",
"ux_editor.component_properties.subform.created_layout_set_name": "Navn på underskjema",
"ux_editor.component_properties.subform.data_model_binding_label": "Velg datamodellknytning",
"ux_editor.component_properties.subform.data_model_empty_messsage": "Ingen tilgjengelige datamodeller",
"ux_editor.component_properties.subform.go_to_layout_set": "Gå til utforming av underskjemaet",
"ux_editor.component_properties.subform.layout_set_is_missing_content_heading": "Underskjemaet ditt mangler innhold.",
"ux_editor.component_properties.subform.layout_set_is_missing_content_paragraph": "Denne tabellen bruker underskjemaet for å hente feltene og tekstene som skal vises i tabellen. Velg Utform underskjemaet for å legge inn innhold.",
"ux_editor.component_properties.subform.no_layout_sets_acting_as_subform": "Det finnes ingen sidegrupper i løsningen som kan brukes som et underskjema",
"ux_editor.component_properties.subform.no_existing_layout_set_create_content": "Du må først utforme underskjemaet, med de feltene og tekstene du vil vise i tabellen.",
"ux_editor.component_properties.subform.no_existing_layout_set_empty_subform": "Når du velger Lag underskjema, oppretter vi et tomt underskjema for deg, og legger til i listen med sider du kan utforme.",
"ux_editor.component_properties.subform.no_existing_layout_set_header": "Før du kan sette opp Tabell for underskjema, må du lage underskjemaet",
"ux_editor.component_properties.subform.no_existing_layout_set_instruction_datamodel": "Velg en datamodellknytning og bekreft med den grønne haken.",
"ux_editor.component_properties.subform.no_existing_layout_set_instruction_design": "Gå til Utform underskjemaet og lag innholdet til det.",
"ux_editor.component_properties.subform.no_existing_layout_set_instruction_name": "Gi underskjemaet et godt navn som du husker.",
"ux_editor.component_properties.subform.no_existing_layout_set_instruction_table_setup": "Gå tilbake til komponenten Tabell for underskjema og sett opp tabellen med de feltene du har utformet i underskjemaet.",
"ux_editor.component_properties.subform.no_existing_layout_set_instructions_header": "Slik gjør du:",
"ux_editor.component_properties.subform.selected_layout_set_label": "Underskjema",
"ux_editor.component_properties.subform.selected_layout_set_title": "Endre underskjemakobling til {{subform}}",
"ux_editor.component_properties.subform.selected_layout_set_title": "Valgt underskjemakobling er {{subform}}",
"ux_editor.component_properties.summary.add_override": "Legg til overstyring",
"ux_editor.component_properties.summary.override.component_id": "ID på komponenten",
"ux_editor.component_properties.summary.override.empty_field_text": "Tekst for tomme felter",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const StudioRecommendedNextAction = ({
}: StudioRecommendedNextActionProps): React.ReactElement => {
const formName = useId();
return (
<form name={formName} onSubmit={onSave}>
<form name={formName} onSubmit={onSave} data-testid='recommendedNextActionCard'>
Jondyr marked this conversation as resolved.
Show resolved Hide resolved
<StudioCard>
<StudioCard.Header>
<Heading size='xs'>{title}</Heading>
Expand Down
16 changes: 16 additions & 0 deletions frontend/packages/ux-editor/src/classes/SubformUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,20 @@ export class SubformUtilsImpl implements SubformUtils {
(set) => set.type === 'subform',
) as Array<SubformLayoutSet>;
}

public get recommendedNextActionText(): {
title: string;
description: string;
} {
return this.hasSubforms
? {
title: 'ux_editor.component_properties.subform.choose_layout_set_header',
description: 'ux_editor.component_properties.subform.choose_layout_set_description',
}
: {
title: 'ux_editor.component_properties.subform.no_existing_layout_set_header',
description:
'ux_editor.component_properties.subform.no_existing_layout_set_create_content',
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,11 @@ describe('EditSubformTableColumns', () => {
textMock('ux_editor.component_properties.subform.layout_set_is_missing_content_paragraph'),
),
).toBeInTheDocument();
expect(screen.getByRole('button', { name: textMock('top_menu.create') })).toBeInTheDocument();
expect(
screen.getByRole('button', {
name: textMock('ux_editor.component_properties.navigate_to_subform_button'),
}),
).toBeInTheDocument();
});
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.redirectButton {
margin-top: var(--fds-spacing-3);
max-width: var(--fds-sizing-30);
align-self: flex-start;
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@ describe('SubformMissingContentWarning', () => {
textMock('ux_editor.component_properties.subform.layout_set_is_missing_content_paragraph'),
),
).toBeInTheDocument();
expect(screen.getByRole('button', { name: textMock('top_menu.create') })).toBeInTheDocument();
expect(
screen.getByRole('button', {
name: textMock('ux_editor.component_properties.navigate_to_subform_button'),
}),
).toBeInTheDocument();
});
it('calls redirect/state change functions on redirect button click', async () => {
const user = userEvent.setup();
Expand All @@ -36,7 +40,11 @@ describe('SubformMissingContentWarning', () => {
<SubformMissingContentWarning subformLayoutSetName={subformLayoutSetName} />,
);

await user.click(screen.getByRole('button', { name: textMock('top_menu.create') }));
await user.click(
screen.getByRole('button', {
name: textMock('ux_editor.component_properties.navigate_to_subform_button'),
}),
);

expect(setSelectedFormLayoutName).toHaveBeenCalledTimes(1);
expect(setSelectedFormLayoutName).toHaveBeenCalledWith(undefined);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,12 @@ export const SubformMissingContentWarning = ({
</StudioParagraph>
<StudioButton
onClick={handleOnRedirectClick}
variant='primary'
color='second'
icon={<PencilIcon />}
iconPlacement='left'
disabled={!subformLayoutSetName}
className={classes.redirectButton}
>
{t('top_menu.create')}
{t('ux_editor.component_properties.navigate_to_subform_button')}
</StudioButton>
</StudioAlert>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
.savelayoutSetButton {
.buttonGroup {
display: flex;
align-self: flex-start;
border: 2px solid var(--success-color);
color: var(--success-color);
}

.headerIcon {
font-size: large;
gap: var(--fds-spacing-2);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@ import { renderWithProviders } from '../../../../../../testing/mocks';
import { CreateNewSubformLayoutSet } from './CreateNewSubformLayoutSet';
import { textMock } from '@studio/testing/mocks/i18nMock';
import { screen } from '@testing-library/react';
import { createQueryClientMock } from 'app-shared/mocks/queryClientMock';
import { layoutSets } from 'app-shared/mocks/mocks';
import userEvent from '@testing-library/user-event';
import { AppContext } from '../../../../../../AppContext';
import { appContextMock } from '../../../../../../testing/appContextMock';
import type { ServicesContextProps } from 'app-shared/contexts/ServicesContext';
import { queriesMock } from 'app-shared/mocks/queriesMock';
import { createQueryClientMock } from 'app-shared/mocks/queryClientMock';

const onSubformCreatedMock = jest.fn();
const onUpdateLayoutSetMock = jest.fn();
const setShowCreateSubformCardMock = jest.fn();
const selectedOptionDataType = 'moped';

jest.mock('./SubformDataModelSelect', () => ({
Expand All @@ -31,44 +30,41 @@ jest.mock('./SubformDataModelSelect', () => ({
describe('CreateNewSubformLayoutSet ', () => {
afterEach(jest.clearAllMocks);

it('displays the card with label and input field', () => {
renderCreateNewSubformLayoutSet();
const card = screen.getByRole('textbox', {
name: textMock('ux_editor.component_properties.subform.created_layout_set_name'),
});
it('displays the card with label, input field and data model select', () => {
renderCreateNewSubformLayoutSet({});
const subformNameInput = screen.getByRole('textbox');
const dataModelSelect = screen.getByRole('combobox');

expect(card).toBeInTheDocument();
expect(subformNameInput).toBeInTheDocument();
expect(dataModelSelect).toBeInTheDocument();
});

it('displays the input field', () => {
renderCreateNewSubformLayoutSet();
const input = screen.getByRole('textbox');
expect(input).toBeInTheDocument();
});
it('displays the save button and close button', () => {
renderCreateNewSubformLayoutSet({});
const saveButton = screen.getByRole('button', { name: textMock('general.save') });
const closeButton = screen.getByRole('button', { name: textMock('general.close') });

it('displays the data model select', async () => {
renderCreateNewSubformLayoutSet();
const dataModelSelect = screen.getByRole('combobox');
expect(dataModelSelect).toBeInTheDocument();
expect(saveButton).toBeInTheDocument();
expect(closeButton).toBeInTheDocument();
});

it('displays the save button', () => {
renderCreateNewSubformLayoutSet();
const saveButton = screen.getByRole('button', { name: textMock('general.close') });
expect(saveButton).toBeInTheDocument();
it('displays not the close button when hasSubforms is false', () => {
renderCreateNewSubformLayoutSet({ hasSubforms: false });
const closeButton = screen.queryByRole('button', { name: textMock('general.close') });
expect(closeButton).not.toBeInTheDocument();
});

it('calls onSubformCreated when save button is clicked', async () => {
const user = userEvent.setup();
renderCreateNewSubformLayoutSet();
renderCreateNewSubformLayoutSet({});
const input = screen.getByRole('textbox');
await user.type(input, 'NewSubform');
const dataModelSelect = screen.getByRole('combobox');
await user.selectOptions(dataModelSelect, ['moped']);
const saveButton = screen.getByRole('button', { name: textMock('general.close') });
const saveButton = screen.getByRole('button', { name: textMock('general.save') });
await user.click(saveButton);
expect(onSubformCreatedMock).toHaveBeenCalledTimes(1);
expect(onSubformCreatedMock).toHaveBeenCalledWith('NewSubform');
expect(onUpdateLayoutSetMock).toHaveBeenCalledTimes(1);
expect(onUpdateLayoutSetMock).toHaveBeenCalledWith('NewSubform');
});

it('displays loading spinner when save button is clicked', async () => {
Expand All @@ -81,7 +77,7 @@ describe('CreateNewSubformLayoutSet ', () => {
}),
);
renderCreateNewSubformLayoutSet({
addLayoutSet: addLayoutSetMock,
queries: { addLayoutSet: addLayoutSetMock },
});

const input = screen.getByRole('textbox');
Expand All @@ -90,7 +86,7 @@ describe('CreateNewSubformLayoutSet ', () => {
const dataModelSelect = screen.getByRole('combobox');
await user.selectOptions(dataModelSelect, ['moped']);

const saveButton = screen.getByRole('button', { name: textMock('general.close') });
const saveButton = screen.getByRole('button', { name: textMock('general.save') });
await user.click(saveButton);

const spinner = await screen.findByText(textMock('general.loading'));
Expand All @@ -99,42 +95,37 @@ describe('CreateNewSubformLayoutSet ', () => {

it('disables the save button when input is invalid', async () => {
const user = userEvent.setup();
renderCreateNewSubformLayoutSet();
renderCreateNewSubformLayoutSet({});

const saveButton = screen.getByRole('button', { name: textMock('general.close') });
const dataModelSelect = screen.getByRole('combobox');
await user.selectOptions(dataModelSelect, ['moped']);

const saveButton = screen.getByRole('button', { name: textMock('general.save') });
expect(saveButton).toBeDisabled();

const input = screen.getByRole('textbox');

await user.type(input, 'æøå');
expect(saveButton).toBeDisabled();

await user.clear(input);
await user.type(input, 'e re a');
expect(saveButton).toBeDisabled();

await user.clear(input);
await user.type(input, 'NewSubform');

const dataModelSelect = screen.getByRole('combobox');
await user.selectOptions(dataModelSelect, ['moped']);
expect(saveButton).not.toBeDisabled();
});

it('disables the save button when the input is valid and no data model is selected', async () => {
it('disables the save button when the input is valid and data model is invalid', async () => {
const user = userEvent.setup();
renderCreateNewSubformLayoutSet();
renderCreateNewSubformLayoutSet({});

const input = screen.getByRole('textbox');
await user.type(input, 'NewSubform');

const saveButton = screen.getByRole('button', { name: textMock('general.close') });
const saveButton = screen.getByRole('button', { name: textMock('general.save') });
expect(saveButton).toBeDisabled();
});

it('does not disable the save button when the input is valid and a data model is selected', async () => {
it('enables save button when both input and data model is valid', async () => {
const user = userEvent.setup();
renderCreateNewSubformLayoutSet();
renderCreateNewSubformLayoutSet({});

const input = screen.getByRole('textbox');
await user.type(input, 'NewSubform');
Expand All @@ -147,11 +138,22 @@ describe('CreateNewSubformLayoutSet ', () => {
});
});

const renderCreateNewSubformLayoutSet = (queries?: Partial<ServicesContextProps>) => {
type RenderCreateNewSubformLayoutSetProps = {
hasSubforms?: boolean;
queries?: Partial<ServicesContextProps>;
};

const renderCreateNewSubformLayoutSet = ({
hasSubforms = true,
queries,
}: RenderCreateNewSubformLayoutSetProps) => {
return renderWithProviders(
<AppContext.Provider value={{ ...appContextMock }}>
<CreateNewSubformLayoutSet onSubformCreated={onSubformCreatedMock} layoutSets={layoutSets} />
</AppContext.Provider>,
<CreateNewSubformLayoutSet
onUpdateLayoutSet={onUpdateLayoutSetMock}
layoutSets={layoutSets}
setShowCreateSubformCard={setShowCreateSubformCardMock}
hasSubforms={hasSubforms}
/>,
{
queries: { ...queriesMock, ...queries },
queryClient: createQueryClientMock(),
Expand Down
Loading