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: main config #14800

Merged
merged 13 commits into from
Feb 26, 2025
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@ import type { FormItem } from '@altinn/ux-editor/types/FormItem';
import { ComponentType } from 'app-shared/types/ComponentType';
import { screen } from '@testing-library/react';
import { ComponentMainConfig } from './ComponentMainConfig';
import { component1Mock } from '@altinn/ux-editor/testing/layoutMock';
import { addFeatureFlagToLocalStorage, FeatureFlag } from 'app-shared/utils/featureToggleUtils';
import { textMock } from '@studio/testing/mocks/i18nMock';
import { typedLocalStorage } from '@studio/pure-functions';
import { component1Mock } from '@altinn/ux-editor/testing/layoutMock';
import { renderWithProviders } from '../../../testing/mocks';
import { createQueryClientMock } from 'app-shared/mocks/queryClientMock';
import { QueryKey } from 'app-shared/types/QueryKey';
Expand All @@ -21,25 +19,18 @@ const summary2ComponentMock: FormItem = {
};

describe('ComponentMainConfig', () => {
afterEach(() => {
jest.clearAllMocks();
typedLocalStorage.removeItem('featureFlags');
});
afterEach(() => jest.clearAllMocks);

it('should render summary2 config when the component type matches', async () => {
renderComponentMainConfig(summary2ComponentMock);

const targetHeader = screen.getByText(textMock('ux_editor.component_properties.target'));
expect(targetHeader).toBeInTheDocument();
});

it('should render header config when feature flag is set, but the type does not match', async () => {
addFeatureFlagToLocalStorage(FeatureFlag.MainConfig);
it('should not render any config when the component type does not match', async () => {
renderComponentMainConfig(component1Mock);

const sectionHeader = textMock('ux_editor.component_properties.main_configuration');
const headerMainConfig = screen.getByText(sectionHeader);
expect(headerMainConfig).toBeInTheDocument();
const wrapper = screen.getByTestId('component-wrapper');
expect(wrapper).toBeEmptyDOMElement();
});
});

Expand All @@ -48,7 +39,9 @@ const renderComponentMainConfig = (component: FormItem) => {
const queryClient = createQueryClientMock();
queryClient.setQueryData([QueryKey.LayoutSetsExtended, org, app], layoutSetsExtendedMock);
return renderWithProviders(
<ComponentMainConfig component={component} handleComponentChange={handleComponentChange} />,
<div data-testid='component-wrapper'>
<ComponentMainConfig component={component} handleComponentChange={handleComponentChange} />
</div>,
{ queryClient },
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import React from 'react';
import type { FormItem } from '../../../types/FormItem';
import { ComponentType } from 'app-shared/types/ComponentType';
import { SummaryMainConfig } from './SpecificMainConfig/SummaryMainConfig';
import { HeaderMainConfig } from './HeaderMainConfig';

export type ComponentMainConfigProps = {
component: FormItem;
Expand All @@ -19,6 +18,6 @@ export const ComponentMainConfig = ({
<SummaryMainConfig component={component} handleComponentChange={handleComponentChange} />
);
default:
return <HeaderMainConfig />;
return null;
}
};
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
.wrapper {
display: block;
margin-top: var(--fds-spacing-3);
width: 100%;
margin-bottom: calc(-1 * var(--fds-spacing-4));
}

.navigateSubformButton {
margin-left: var(--fds-spacing-3);
margin-bottom: var(--fds-spacing-3);
margin-left: var(--fds-spacing-5);
margin-top: var(--fds-spacing-1);
margin-bottom: var(--fds-spacing-2);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { EditLayoutSet } from './EditLayoutSet';
import type { ComponentType } from 'app-shared/types/ComponentType';
import type { IGenericEditComponent } from '../../../../components/config/componentConfig';
import { DefinedLayoutSet } from './DefinedLayoutSet/DefinedLayoutSet';
import { StudioButton } from '@studio/components';
import { StudioButton, StudioDivider } from '@studio/components';
import { useTranslation } from 'react-i18next';
import { PencilIcon } from '@studio/icons';
import { useAppContext } from '@altinn/ux-editor/hooks';
Expand All @@ -19,7 +19,7 @@ export const EditLayoutSetForSubform = <T extends ComponentType>({
const existingLayoutSetForSubform = component['layoutSet'];
if (existingLayoutSetForSubform) {
return (
<>
<div className={classes.wrapper}>
<DefinedLayoutSet existingLayoutSetForSubform={existingLayoutSetForSubform} />
<StudioButton
icon={<PencilIcon />}
Expand All @@ -30,7 +30,8 @@ export const EditLayoutSetForSubform = <T extends ComponentType>({
>
{t('ux_editor.component_properties.navigate_to_subform_button')}
</StudioButton>
</>
<StudioDivider color='subtle' />
</div>
);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
.componentMainConfig {
padding: var(--fds-spacing-5);
padding: var(--fds-spacing-4) var(--fds-spacing-5) var(--fds-spacing-1);
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
.content {
.mainContent {
display: flex;
flex-direction: column;
background-color: var(--fds-semantic-surface-neutral-default);
gap: var(--fds-spacing-2);
align-items: flex-start;
}

.alertWrapper {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import type { IFormLayouts } from '@altinn/ux-editor/types/global';
import { app, org } from '@studio/testing/testids';
import { ComponentType } from 'app-shared/types/ComponentType';
import { componentMocks } from '@altinn/ux-editor/testing/componentMocks';
import { addFeatureFlagToLocalStorage, FeatureFlag } from 'app-shared/utils/featureToggleUtils';
import { typedLocalStorage } from '@studio/pure-functions';

const mockHandleComponentUpdate = jest.fn();

Expand All @@ -30,7 +32,10 @@ const defaultProps: PropertiesHeaderProps = {
};

describe('PropertiesHeader', () => {
afterEach(jest.clearAllMocks);
afterEach(() => {
jest.clearAllMocks();
typedLocalStorage.removeItem('featureFlags');
});

it('renders the header name for the component', () => {
renderPropertiesHeader();
Expand Down Expand Up @@ -162,7 +167,24 @@ describe('PropertiesHeader', () => {
const alert = screen.queryByText(textMock('ux_editor.component_properties.deprecated.Input'));
expect(alert).not.toBeInTheDocument();
});

it('should render main configuration header when feature flag is set', () => {
addFeatureFlagToLocalStorage(FeatureFlag.MainConfig);
renderPropertiesHeader({ formItem: componentMocks[ComponentType.Input] });

const sectionHeader = textMock('ux_editor.component_properties.main_configuration');
const headerMainConfig = screen.getByText(sectionHeader);
expect(headerMainConfig).toBeInTheDocument();
});

it('should not render main configuration header when feature flag is not set', () => {
renderPropertiesHeader({ formItem: componentMocks[ComponentType.Input] });
const sectionHeader = textMock('ux_editor.component_properties.main_configuration');
const headerMainConfig = screen.queryByText(sectionHeader);
expect(headerMainConfig).not.toBeInTheDocument();
});
});

const renderPropertiesHeader = (props: Partial<PropertiesHeaderProps> = {}) => {
const componentType = props.formItem ? props.formItem.type : defaultProps.formItem.type;
queryClientMock.setQueryData(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type { FormItem } from '../../../types/FormItem';
import { ComponentType } from 'app-shared/types/ComponentType';
import { EditLayoutSetForSubform } from './EditLayoutSetForSubform';
import { ComponentMainConfig } from './ComponentMainConfig';
import { HeaderMainConfig } from './HeaderMainConfig';
import { isComponentDeprecated } from '@altinn/ux-editor/utils/component';
import { FeatureFlag, shouldDisplayFeature } from 'app-shared/utils/featureToggleUtils';

Expand All @@ -29,6 +30,12 @@ export const PropertiesHeader = ({
? QuestionmarkDiamondIcon
: formItemConfigs[formItem.type]?.icon;

const hideContentWhenSubformGuide =
formItem.type === ComponentType.Subform && !formItem['layoutSet'];

const displayMainConfigHeader =
shouldDisplayFeature(FeatureFlag.MainConfig) || ComponentType.Summary2 === formItem.type;

return (
<>
<StudioSectionHeader
Expand All @@ -47,19 +54,27 @@ export const PropertiesHeader = ({
{t(`ux_editor.component_properties.deprecated.${formItem.type}`)}
</StudioAlert>
)}
<div className={classes.content}>
<EditComponentIdRow component={formItem} handleComponentUpdate={handleComponentUpdate} />
<div className={classes.mainContent}>
{formItem.type === ComponentType.Subform && (
<EditLayoutSetForSubform
component={formItem}
handleComponentChange={handleComponentUpdate}
/>
)}
{!hideContentWhenSubformGuide && displayMainConfigHeader && <HeaderMainConfig />}
{!hideContentWhenSubformGuide && (
<>
<EditComponentIdRow
component={formItem}
handleComponentUpdate={handleComponentUpdate}
/>
<ComponentMainConfig
component={formItem}
handleComponentChange={handleComponentUpdate}
/>
</>
)}
</div>
{(formItem.type === ComponentType.Summary2 ||
shouldDisplayFeature(FeatureFlag.MainConfig)) && (
<ComponentMainConfig component={formItem} handleComponentChange={handleComponentUpdate} />
)}
</>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import type {
Summary2TargetConfig,
} from 'app-shared/types/ComponentSpecificConfig';
import { Summary2Target } from '../../../config/componentSpecificContent/Summary2/Summary2Target/Summary2Target';
import { HeaderMainConfig } from '../HeaderMainConfig';

export type SummaryMainConfigProps = {
component: FormItem<ComponentType.Summary2>;
Expand All @@ -35,9 +34,7 @@ export const SummaryMainConfig = ({ component, handleComponentChange }: SummaryM

return (
<>
<HeaderMainConfig>
<Summary2Target target={component.target} onChange={handleTargetChange} />
</HeaderMainConfig>
<Summary2Target target={component.target} onChange={handleTargetChange} />
<Accordion color='subtle'>
<Accordion.Item open={accordionOpen['summary2overrides'] === true}>
<Accordion.Header
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
.targetConfig {
padding-top: var(--fds-spacing-5);
padding: var(--fds-spacing-5);
background-color: var(--fds-semantic-background-subtle);
border-top: 2px solid var(--fds-semantic-border-divider-subtle);
border-bottom: 2px solid var(--fds-semantic-border-divider-subtle);
}

.targetConfig > * {
Expand Down