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

feat(summary2): add new props to overrides #14644

Merged
merged 1 commit into from
Feb 14, 2025
Merged
Show file tree
Hide file tree
Changes from all 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
3 changes: 3 additions & 0 deletions frontend/language/src/nb.json
Original file line number Diff line number Diff line change
Expand Up @@ -1489,6 +1489,9 @@
"ux_editor.component_properties.summary.add_override": "Lag en ny overstyring",
"ux_editor.component_properties.summary.override.choose_component": "Velg komponent",
"ux_editor.component_properties.summary.override.description": "Overstyringer per komponent for oppsummeringen",
"ux_editor.component_properties.summary.override.display": "Visningstype",
"ux_editor.component_properties.summary.override.display.full": "Fullstendig",
"ux_editor.component_properties.summary.override.display.table": "Tabell",
"ux_editor.component_properties.summary.override.display_type": "Visningstype",
"ux_editor.component_properties.summary.override.display_type.list": "Liste",
"ux_editor.component_properties.summary.override.display_type.string": "Tekst",
Expand Down
11 changes: 6 additions & 5 deletions frontend/packages/shared/src/types/ComponentSpecificConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,6 @@ type SummarizableComponentProps = {
renderAsSummary?: BooleanExpression;
};

export type SummaryTargetType = 'page' | 'layoutSet' | 'component';

export type SummaryCustomTargetType = 'list' | 'string';

type LabeledComponentProps = {
labelSettings?: LabelSettings;
};
Expand Down Expand Up @@ -136,14 +132,19 @@ type PageValidation = {
show: AllowedValidationMasks;
};

export type OverrideDisplayType = 'list' | 'string';
export type OverrideDisplay = 'table' | 'full';
export type Summary2OverrideConfig = {
componentId: string;
hidden?: boolean;
emptyFieldText?: string;
isCompact?: boolean;
displayType?: SummaryCustomTargetType;
displayType?: OverrideDisplayType;
display?: OverrideDisplay;
};

export type SummaryTargetType = 'page' | 'layoutSet' | 'component';

export type Summary2TargetConfig = {
type?: SummaryTargetType;
id?: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,15 @@ import React, { type ChangeEvent } from 'react';
import type { Summary2OverrideConfig } from 'app-shared/types/ComponentSpecificConfig';
import { StudioSwitch } from '@studio/components';
import { useTranslation } from 'react-i18next';
import { useStudioEnvironmentParams } from 'app-shared/hooks/useStudioEnvironmentParams';
import { useAppContext } from '../../../../../../hooks';
import { useFormLayoutsQuery } from '../../../../../../hooks/queries/useFormLayoutsQuery';
import { getAllLayoutComponents } from '../../../../../../utils/formLayoutUtils';
import { ComponentType } from 'app-shared/types/ComponentType';

type CompactViewSwitchProps = {
onChange: (updatedOverride: Summary2OverrideConfig) => void;
override: Summary2OverrideConfig;
};

export const CompactViewSwitch = ({ onChange, override }: CompactViewSwitchProps) => {
export const Summary2OverrideCompactSwitch = ({ onChange, override }: CompactViewSwitchProps) => {
const { t } = useTranslation();
const { org, app } = useStudioEnvironmentParams();
const { selectedFormLayoutSetName } = useAppContext();
const { data: formLayoutsData } = useFormLayoutsQuery(org, app, selectedFormLayoutSetName);

const components = Object.values(formLayoutsData).flatMap((layout) =>
getAllLayoutComponents(layout),
);
const component = components.find((comp) => comp.id === override.componentId);
const isGroupComponent = component?.type === (ComponentType.Group as ComponentType);

if (!isGroupComponent) {
return null;
}
return (
<StudioSwitch
position='right'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import React from 'react';
import type {
OverrideDisplay,
Summary2OverrideConfig,
} from 'app-shared/types/ComponentSpecificConfig';
import { StudioNativeSelect } from '@studio/components';
import { useTranslation } from 'react-i18next';

type Summary2OverrideDisplaySelectProps = {
onChange: (override: Summary2OverrideConfig) => void;
override: Summary2OverrideConfig;
};

export const Summary2OverrideDisplaySelect = ({
onChange,
override,
}: Summary2OverrideDisplaySelectProps) => {
const { t } = useTranslation();

const options = [
{ value: 'table', text: t('ux_editor.component_properties.summary.override.display.table') },
{ value: 'full', text: t('ux_editor.component_properties.summary.override.display.full') },
];

return (
<StudioNativeSelect
size='sm'
label={t('ux_editor.component_properties.summary.override.display')}
value={override.display}
onChange={(event) => {
onChange({ ...override, display: event.target.value as OverrideDisplay });
}}
Jondyr marked this conversation as resolved.
Show resolved Hide resolved
>
{options.map((option) => (
<option key={option.value} value={option.value}>
{option.text}
</option>
))}
</StudioNativeSelect>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,26 @@ import React from 'react';
import { StudioCard, StudioNativeSelect } from '@studio/components';
import type {
Summary2OverrideConfig,
SummaryCustomTargetType,
OverrideDisplayType,
} from 'app-shared/types/ComponentSpecificConfig';
import { type CustomConfigType, useCustomConfigType } from '../hook/useCustomConfigType';
import { useTranslation } from 'react-i18next';
import { mapSelectedTypeToConfig } from '../utils';
import { ComponentType } from 'app-shared/types/ComponentType';
import type { TargetComponentProps } from '../../Summary2Target/targetUtils';

export type Summary2OverrideDisplayTypeProps = {
override: Summary2OverrideConfig;
componentOptions: TargetComponentProps[];
onChange: (override: Summary2OverrideConfig) => void;
};

export const Summary2OverrideDisplayType = ({
override,
componentOptions,
onChange,
}: Summary2OverrideDisplayTypeProps) => {
const { t } = useTranslation();
const { displayType, componentId } = override;
const selectedComponentType = componentOptions?.find((comp) => comp.id === componentId)?.type;
const customConfigTypes: CustomConfigType[] = useCustomConfigType();

const checkboxOrMultipleselect =
selectedComponentType?.includes(ComponentType.MultipleSelect) ||
selectedComponentType?.includes(ComponentType.Checkboxes);

if (!checkboxOrMultipleselect) {
return null;
}

const handleCustomTypeChange = (newDisplayType: SummaryCustomTargetType): void => {
const handleCustomTypeChange = (newDisplayType: OverrideDisplayType): void => {
const summary2OverrideConfig = mapSelectedTypeToConfig({
componentId,
displayType: newDisplayType,
Expand All @@ -48,7 +35,7 @@ export const Summary2OverrideDisplayType = ({
size='sm'
label={t('ux_editor.component_properties.summary.override.display_type')}
value={displayType || 'list'}
onChange={(e) => handleCustomTypeChange(e.target.value as SummaryCustomTargetType)}
onChange={(e) => handleCustomTypeChange(e.target.value as OverrideDisplayType)}
>
{customConfigTypes.map((type: CustomConfigType) => (
<option key={type.label} value={type.value}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,26 @@ import {
componentWithMultipleSelectMock,
layout1NameMock,
layoutMock,
container2IdMock,
subformComponentMock,
} from '../../../../../testing/layoutMock';
import { textMock } from '@studio/testing/mocks/i18nMock';
import { layoutSet1NameMock, layoutSetsExtendedMock } from '../../../../../testing/layoutSetsMock';
import { renderWithProviders } from '../../../../../testing/mocks';
import type {
OverrideDisplay,
OverrideDisplayType,
} from 'app-shared/types/ComponentSpecificConfig';

const checkBoxId = componentWithOptionsMock.id;
const multipleSelectId = componentWithMultipleSelectMock.id;
const subformComponentId = subformComponentMock.id;
const layoutMockWithMultipleSelect = {
...layoutMock,
components: {
...layoutMock.components,
[multipleSelectId]: componentWithMultipleSelectMock,
[subformComponentId]: subformComponentMock,
},
};

Expand All @@ -42,11 +50,12 @@ describe('Summary2Override', () => {
});

it('should be able to remove override', async () => {
const user = userEvent.setup();
render({
overrides: [{ componentId: '1' }],
});
await userEvent.click(overrideCollapsedButton(1));
await userEvent.click(removeOverrideButton());
await user.click(overrideCollapsedButton(1));
await user.click(removeOverrideButton());
expect(defaultProps.onChange).toHaveBeenCalledWith([]);
});

Expand All @@ -57,7 +66,7 @@ describe('Summary2Override', () => {
render({ overrides: [{ componentId }] });

await user.click(overrideCollapsedButton(1));
await user.click(overrideTypeSelector());
await user.click(overrideDisplayTypeSelector());
expect(renderedTypeOptions()).toBeTruthy();
},
);
Expand Down Expand Up @@ -143,7 +152,7 @@ describe('Summary2Override', () => {
const user = userEvent.setup();
render({ overrides: [{ componentId: multipleSelectId }] });
await user.click(overrideCollapsedButton(1));
await user.selectOptions(overrideTypeSelector(), overrideSelectType('string'));
await user.selectOptions(overrideDisplayTypeSelector(), overrideDisplayType('string'));

expect(defaultProps.onChange).toHaveBeenCalledWith(
expect.arrayContaining([{ componentId: multipleSelectId, displayType: 'string' }]),
Expand All @@ -154,7 +163,7 @@ describe('Summary2Override', () => {
const user = userEvent.setup();
render({ overrides: [{ componentId: checkBoxId }] });
await user.click(overrideCollapsedButton(1));
await user.selectOptions(overrideTypeSelector(), overrideSelectType('string'));
await user.selectOptions(overrideDisplayTypeSelector(), overrideDisplayType('string'));

await waitFor(() =>
expect(defaultProps.onChange).toHaveBeenCalledWith(
Expand All @@ -164,20 +173,61 @@ describe('Summary2Override', () => {
});

it('should collapse and uncollapse override', async () => {
const user = userEvent.setup();
render({ overrides: [{ componentId: '1' }] });
await userEvent.click(overrideCollapsedButton(1));
await user.click(overrideCollapsedButton(1));
expect(
screen.queryByRole('button', {
name: textMock('ux_editor.component_properties.summary.overrides.nth.*:1}'),
}),
).not.toBeInTheDocument();
await userEvent.click(overrideCloseButton());
await user.click(overrideCloseButton());
expect(
screen.queryByRole('button', {
name: textMock('ux_editor.component_properties.summary.overrides.nth.*:1}'),
}),
).not.toBeInTheDocument();
});

it('should render component specific overrides', async () => {
const user = userEvent.setup();
render({ overrides: [{ componentId: container2IdMock }] });

await user.click(overrideCollapsedButton(1));
await user.selectOptions(overrideDisplaySelector(), overrideDisplaySelectType('table'));

expect(defaultProps.onChange).toHaveBeenCalledWith(
expect.arrayContaining([{ componentId: container2IdMock, display: 'table' }]),
);
});

it.each([
{
componentId: container2IdMock,
defaultProps: { componentId: container2IdMock, display: 'full' },
},
{
componentId: subformComponentId,
defaultProps: { componentId: subformComponentId, display: 'table' },
},
])('should set default props for components', async (args) => {
const user = userEvent.setup();
render({ overrides: [{ componentId: component1IdMock }] });

await user.click(overrideCollapsedButton(1));
await user.click(overrideComponentSelect());
await user.click(
screen.getByRole('option', {
name: new RegExp(args.componentId),
}),
);

await waitFor(() =>
expect(defaultProps.onChange).toHaveBeenCalledWith(
expect.arrayContaining([expect.objectContaining(args.defaultProps)]),
),
);
});
});

const overrideCloseButton = () =>
Expand All @@ -202,12 +252,22 @@ const overrideComponentSelect = () =>
name: textMock('ux_editor.component_properties.summary.override.choose_component'),
});

const overrideTypeSelector = () =>
const overrideDisplaySelector = () =>
screen.getByRole('combobox', {
name: textMock('ux_editor.component_properties.summary.override.display'),
});

const overrideDisplaySelectType = (type: OverrideDisplay) =>
screen.getByRole('option', {
name: textMock(`ux_editor.component_properties.summary.override.display.${type}`),
});

const overrideDisplayTypeSelector = () =>
screen.getByRole('combobox', {
name: textMock('ux_editor.component_properties.summary.override.display_type'),
});

const overrideSelectType = (type: string) =>
const overrideDisplayType = (type: OverrideDisplayType) =>
screen.getByRole('option', {
name: textMock(`ux_editor.component_properties.summary.override.display_type.${type}`),
});
Expand Down
Loading
Loading