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: reorganize summary2 config #14460

Merged
merged 33 commits into from
Jan 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
d9c300a
draft ui changes
Jondyr Jan 8, 2025
47aea27
refactoring and design adjustments
Jondyr Jan 9, 2025
52312bc
Change property logic to match new UX
Jondyr Jan 13, 2025
0b44622
Test changes
Jondyr Jan 13, 2025
9dce202
Add overflow hidden to all span inside card
Jondyr Jan 13, 2025
ec09277
Make overrides collapsable
Jondyr Jan 13, 2025
8727343
Remove index.ts file
Jondyr Jan 13, 2025
d4cece0
fix state handling on empty component
Jondyr Jan 13, 2025
9bc5b9d
Make tests open collapsed field
Jondyr Jan 13, 2025
3e37dd5
Regex escaping dot
Jondyr Jan 13, 2025
df7cd3b
Coderabbit comments
Jondyr Jan 13, 2025
7ecb200
Rework onChange
Jondyr Jan 13, 2025
933ee63
Simplify element
Jondyr Jan 13, 2025
2e6feea
Remove unused code
Jondyr Jan 13, 2025
5568524
Add test for ComponentMainConfig
Jondyr Jan 13, 2025
4b698c3
Add some more test cases
Jondyr Jan 14, 2025
9c496b9
Tidying, rework logic
Jondyr Jan 14, 2025
78824db
Fix state mutation
Jondyr Jan 14, 2025
94ae4bd
Fix test assertion
Jondyr Jan 14, 2025
7869aa4
Test changes
Jondyr Jan 14, 2025
1950572
Delete frontend/packages/ux-editor/src/components/config/componentSpe…
Jondyr Jan 21, 2025
e844f92
Design feedback changes
Jondyr Jan 22, 2025
594a238
Remove extra label and fix test
Jondyr Jan 22, 2025
f10ad7e
Add test for emptyTextField
Jondyr Jan 22, 2025
9320a11
Disable save button on overrides when no component is selected
Jondyr Jan 22, 2025
c1df6e3
Remove unused css
Jondyr Jan 22, 2025
a45826d
Add reusable RequiredIndicator component
Jondyr Jan 20, 2025
b1be70b
Move Summary2 target config to main config above overrides
Jondyr Jan 20, 2025
0f501d8
Add mocks to tests
Jondyr Jan 20, 2025
3dfcf71
Add translation key for main configuration
Jondyr Jan 21, 2025
cf6f196
Add test case for main config
Jondyr Jan 21, 2025
ded0d41
Merge branch 'main' into 20-01-summary2-reorganize-config
Jondyr Jan 27, 2025
3c330f5
Merge branch 'main' into 20-01-summary2-reorganize-config
lassopicasso Jan 28, 2025
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: 2 additions & 0 deletions frontend/language/src/nb.json
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,7 @@
"general.production_environment_alt": "Produksjonsmiljøet",
"general.profile_icon": "Profilikon",
"general.reload": "Last inn på nytt",
"general.required": "Må fylles ut",
"general.save": "Lagre",
"general.saving": "Lagrer",
"general.search": "Søk",
Expand Down Expand Up @@ -1394,6 +1395,7 @@
"ux_editor.component_properties.layout": "Visning",
"ux_editor.component_properties.layoutSet": "Navn på sidegruppe",
"ux_editor.component_properties.loading": "Laster inn",
"ux_editor.component_properties.main_configuration": "Hovedinnstillinger",
"ux_editor.component_properties.mapping": "Mapping",
"ux_editor.component_properties.maxCount": "Maks antall repetisjoner",
"ux_editor.component_properties.maxDate": "Seneste dato",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.componentMainConfig {
padding: var(--fds-spacing-5);
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@ import userEvent from '@testing-library/user-event';
import { createQueryClientMock } from 'app-shared/mocks/queryClientMock';
import { QueryKey } from 'app-shared/types/QueryKey';
import { app, org } from '@studio/testing/testids';
import { layoutSet1NameMock } from '../../../testing/layoutSetsMock';
import {
layoutSet1NameMock,
layoutSet2NameMock,
layoutSetsMock,
} from '../../../testing/layoutSetsMock';
import { layout1NameMock, layoutMock } from '../../../testing/layoutMock';

const summary2Component: FormItem = {
Expand All @@ -20,6 +24,10 @@ const summary2Component: FormItem = {

describe('ComponentMainConfig', () => {
describe('Summary2', () => {
beforeEach(() => {
jest.clearAllMocks();
});

it('should render summary2 config', async () => {
const user = userEvent.setup();
render(summary2Component);
Expand All @@ -46,6 +54,13 @@ describe('ComponentMainConfig', () => {
await user.click(summary2AddOverrideButton());
expect(handleComponentChange).toHaveBeenCalledTimes(1);
});

it('should call handleComponentChange when changing target', async () => {
const user = userEvent.setup();
render(summary2Component);
await user.selectOptions(summary2TargetLayoutSet(), layoutSet2NameMock);
expect(handleComponentChange).toHaveBeenCalledTimes(1);
});
});
});

Expand All @@ -58,12 +73,16 @@ const summary2CollapsedButton = (n: number) =>
name: new RegExp(`ux_editor.component_properties.summary.overrides.nth.*:${n}}`),
});

const summary2TargetLayoutSet = () =>
screen.getByRole('combobox', { name: /ux_editor.component_properties.target_layoutSet_id/ });

const handleComponentChange = jest.fn();
const render = (component: FormItem) => {
const queryClient = createQueryClientMock();
queryClient.setQueryData([QueryKey.FormLayouts, org, app, layoutSet1NameMock], {
[layout1NameMock]: layoutMock,
});
queryClient.setQueryData([QueryKey.LayoutSets, org, app], layoutSetsMock);
renderWithProviders(
<ComponentMainConfig component={component} handleComponentChange={handleComponentChange} />,
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
import React from 'react';
import type { FormItem } from '../../../types/FormItem';
import classes from './ComponentMainConfig.module.css';
import { ComponentType } from 'app-shared/types/ComponentType';
import { Accordion } from '@digdir/designsystemet-react';
import { useTranslation } from 'react-i18next';
import { Summary2Override } from '../../config/componentSpecificContent/Summary2/Override/Summary2Override';
import type { Summary2OverrideConfig } from 'app-shared/types/ComponentSpecificConfig';
import type {
Summary2OverrideConfig,
Summary2TargetConfig,
} from 'app-shared/types/ComponentSpecificConfig';
import { Summary2Target } from '../../config/componentSpecificContent/Summary2/Summary2Target/Summary2Target';
import { StudioHeading } from '@studio/components';
import { RequiredIndicator } from '../../RequiredIndicator';

export type ComponentMainConfigProps = {
component: FormItem;
Expand All @@ -24,25 +31,43 @@ export const ComponentMainConfig = ({
handleComponentChange(updatedComponent);
};

const handleTargetChange = (updatedTarget: Summary2TargetConfig): void => {
const updatedComponent = { ...component } as FormItem<ComponentType.Summary2>;
updatedComponent.target = updatedTarget;
handleComponentChange(updatedComponent);
};

return (
<>
{component.type === ComponentType.Summary2 && (
<Accordion color='subtle'>
<Accordion.Item open={accordionOpen['summary2overrides'] === true}>
<Accordion.Header
onHeaderClick={() =>
setAccordionOpen((prev) => {
return { ...prev, summary2overrides: !prev['summary2overrides'] };
})
}
>
{t('ux_editor.component_properties.summary.override.title')}
</Accordion.Header>
<Accordion.Content>
<Summary2Override overrides={component.overrides} onChange={handleOverridesChange} />
</Accordion.Content>
</Accordion.Item>
</Accordion>
<>
<div className={classes.componentMainConfig}>
<StudioHeading size='2xs'>
{t('ux_editor.component_properties.main_configuration')}
<RequiredIndicator />
</StudioHeading>
<Summary2Target target={component.target} onChange={handleTargetChange} />
</div>
<Accordion color='subtle'>
<Accordion.Item open={accordionOpen['summary2overrides'] === true}>
<Accordion.Header
onHeaderClick={() =>
setAccordionOpen((prev) => {
return { ...prev, summary2overrides: !prev['summary2overrides'] };
})
}
>
{t('ux_editor.component_properties.summary.override.title')}
</Accordion.Header>
<Accordion.Content>
<Summary2Override
overrides={component.overrides}
onChange={handleOverridesChange}
/>
</Accordion.Content>
</Accordion.Item>
</Accordion>
</>
)}
</>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.requiredIndicator {
display: inline;
height: var(--fds-sizing-7);
border-radius: var(--fds-radius-sm);
padding: var(--fds-spacing-2);
}
14 changes: 14 additions & 0 deletions frontend/packages/ux-editor/src/components/RequiredIndicator.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React from 'react';
import classes from './RequiredIndicator.module.css';
import { StudioTag } from '@studio/components';
import { useTranslation } from 'react-i18next';

export const RequiredIndicator = () => {
const { t } = useTranslation();

return (
<StudioTag size='sm' className={classes.requiredIndicator} color='warning'>
{t('general.required')}
</StudioTag>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.targetConfig {
padding-top: var(--fds-spacing-5);
}

.targetConfig > * {
padding-bottom: var(--fds-spacing-2);
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { Summary2ComponentReferenceSelector } from '../Summary2ComponentReferenceSelector';
import {
StudioCard,
StudioHeading,
StudioParagraph,
StudioNativeSelect,
StudioTextfield,
} from '@studio/components';
import React from 'react';
import classes from './Summary2Target.module.css';
import { useStudioEnvironmentParams } from 'app-shared/hooks/useStudioEnvironmentParams';
import type {
Summary2TargetConfig,
Expand Down Expand Up @@ -62,66 +62,62 @@ export const Summary2Target = ({ target, onChange }: Summary2TargetProps) => {
};

return (
<StudioCard>
<StudioCard.Header>
<StudioHeading size='2xs'>{t('ux_editor.component_properties.target')}</StudioHeading>
</StudioCard.Header>
<div className={classes.targetConfig}>
<StudioHeading size='2xs'>{t('ux_editor.component_properties.target')}</StudioHeading>
<StudioParagraph size='sm'>
{t('ux_editor.component_properties.target_description')}
</StudioParagraph>
<StudioCard.Content>
<StudioNativeSelect
<StudioNativeSelect
size='sm'
label={t('ux_editor.component_properties.target_layoutSet_id')}
value={target.taskId}
onChange={(e) => handleLayoutSetChange(e.target.value)}
>
{layoutSetOptions.map((layoutSet) => (
<option key={layoutSet.id} value={layoutSet.tasks[0]}>
{layoutSet.id}
</option>
))}
</StudioNativeSelect>
<StudioNativeSelect
size='sm'
label={t('ux_editor.component_properties.target_type')}
value={target.type}
onChange={handleTypeChange}
>
{targetTypes.map((type) => (
<option key={type.value} value={type.value}>
{type.label}
</option>
))}
</StudioNativeSelect>
{target.type === 'page' && (
<Summary2ComponentReferenceSelector
key={target.id} // TODO: Remove the key when https://github.com/digdir/designsystemet/issues/2264 is fixed
label={t('ux_editor.component_properties.target_unit_page')}
value={target.id}
options={pageOptions}
onValueChange={handleTargetIdChange}
/>
)}
{target.type === 'component' && (
<Summary2ComponentReferenceSelector
key={target.id} // TODO: Remove the key when https://github.com/digdir/designsystemet/issues/2264 is fixed
label={t('ux_editor.component_properties.target_unit_component')}
value={target.id}
options={componentOptions}
onValueChange={handleTargetIdChange}
/>
)}
{target.type === 'layoutSet' && (
<StudioTextfield
key={target.id} // TODO: Remove the key when https://github.com/digdir/designsystemet/issues/2264 is fixed
size='sm'
label={t('ux_editor.component_properties.target_layoutSet_id')}
value={target.taskId}
onChange={(e) => handleLayoutSetChange(e.target.value)}
>
{layoutSetOptions.map((layoutSet) => (
<option key={layoutSet.id} value={layoutSet.tasks[0]}>
{layoutSet.id}
</option>
))}
</StudioNativeSelect>
<StudioNativeSelect
size='sm'
label={t('ux_editor.component_properties.target_type')}
value={target.type}
onChange={handleTypeChange}
>
{targetTypes.map((type) => (
<option key={type.value} value={type.value}>
{type.label}
</option>
))}
</StudioNativeSelect>
{target.type === 'page' && (
<Summary2ComponentReferenceSelector
key={target.id} // TODO: Remove the key when https://github.com/digdir/designsystemet/issues/2264 is fixed
label={t('ux_editor.component_properties.target_unit_page')}
value={target.id}
options={pageOptions}
onValueChange={handleTargetIdChange}
/>
)}
{target.type === 'component' && (
<Summary2ComponentReferenceSelector
key={target.id} // TODO: Remove the key when https://github.com/digdir/designsystemet/issues/2264 is fixed
label={t('ux_editor.component_properties.target_unit_component')}
value={target.id}
options={componentOptions}
onValueChange={handleTargetIdChange}
/>
)}
{target.type === 'layoutSet' && (
<StudioTextfield
key={target.id} // TODO: Remove the key when https://github.com/digdir/designsystemet/issues/2264 is fixed
size='sm'
label={t('ux_editor.component_properties.target_unit_layout_set')}
value={selectedLayoutSetTargetName}
disabled={true}
/>
)}
</StudioCard.Content>
</StudioCard>
label={t('ux_editor.component_properties.target_unit_layout_set')}
value={selectedLayoutSetTargetName}
disabled={true}
/>
)}
</div>
);
};
Loading