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: Warn user about deprecated components #14677

Merged
merged 9 commits into from
Feb 20, 2025
1 change: 1 addition & 0 deletions frontend/language/src/nb.json
Original file line number Diff line number Diff line change
Expand Up @@ -1311,6 +1311,7 @@
"ux_editor.component_properties.dateSent": "Dato eksemplaret ble sendt inn",
"ux_editor.component_properties.defaultTab": "Standardfane",
"ux_editor.component_properties.deleteButton": "Slett-knapp",
"ux_editor.component_properties.deprecated.Summary": "Vi har forbedret komponenten for å oppsummere data. Bruk den nye oppsummeringskomponenten i stedet. Hvis du har brukt den gamle i apper som fortsatt er aktive, vil den fungere som normalt",
"ux_editor.component_properties.direction": "Retning",
"ux_editor.component_properties.display": "Visning",
"ux_editor.component_properties.displayMode": "Visningsmodus (enkel eller liste)",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,7 @@
gap: var(--fds-spacing-2);
align-items: flex-start;
}

.alertWrapper {
margin: var(--fds-spacing-3);
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { layout1NameMock, layoutMock } from '@altinn/ux-editor/testing/layoutMoc
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';

const mockHandleComponentUpdate = jest.fn();

Expand Down Expand Up @@ -149,6 +150,18 @@ describe('PropertiesHeader', () => {
});
expect(setLayoutSetButton).not.toBeInTheDocument();
});

it('should show warning when component is deprecated', () => {
renderPropertiesHeader({ formItem: componentMocks[ComponentType.Summary] });
const alert = screen.getByText(textMock('ux_editor.component_properties.deprecated.Summary'));
expect(alert).toBeInTheDocument();
});

it('should not show warning when component is not deprecated', () => {
renderPropertiesHeader({ formItem: componentMocks[ComponentType.Input] });
const alert = screen.queryByText(textMock('ux_editor.component_properties.deprecated.Input'));
expect(alert).not.toBeInTheDocument();
});
});
const renderPropertiesHeader = (props: Partial<PropertiesHeaderProps> = {}) => {
const componentType = props.formItem ? props.formItem.type : defaultProps.formItem.type;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ import React from 'react';
import classes from './PropertiesHeader.module.css';
import { formItemConfigs } from '../../../data/formItemConfig';
import { QuestionmarkDiamondIcon } from '@studio/icons';
import { StudioSectionHeader } from '@studio/components';

import { StudioAlert, StudioSectionHeader } from '@studio/components';
import { getComponentHelperTextByComponentType } from '../../../utils/language';
import { useTranslation } from 'react-i18next';
import { EditComponentIdRow } from './EditComponentIdRow';
import type { FormItem } from '../../../types/FormItem';
import { ComponentType } from 'app-shared/types/ComponentType';
import { EditLayoutSetForSubform } from './EditLayoutSetForSubform';
import { ComponentMainConfig } from './ComponentMainConfig';
import { isComponentDeprecated } from '@altinn/ux-editor/utils/component';

export type PropertiesHeaderProps = {
formItem: FormItem;
Expand Down Expand Up @@ -41,6 +41,11 @@ export const PropertiesHeader = ({
title: t('ux_editor.component_help_text_general_title'),
}}
/>
{isComponentDeprecated(formItem.type) && (
<StudioAlert size='sm' className={classes.alertWrapper} severity='warning'>
{t(`ux_editor.component_properties.deprecated.${formItem.type}`)}
</StudioAlert>
)}
<div className={classes.content}>
<EditComponentIdRow component={formItem} handleComponentUpdate={handleComponentUpdate} />
{formItem.type === ComponentType.Subform && (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,7 @@
.duplicateComponentIds {
background-color: var(--fds-semantic-surface-danger-subtle) !important;
}

.deprecatedComponent {
background-color: var(--fds-semantic-surface-warning-default);
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { isContainer } from '../../../../../utils/formItemUtils';
import { useFormItemContext } from '../../../../FormItemContext';
import { useAppContext } from '../../../../../hooks';
import classNames from 'classnames';
import { isComponentDeprecated } from '@altinn/ux-editor/utils/component';

export interface FormItemTitleProps {
children: ReactNode;
Expand Down Expand Up @@ -43,6 +44,7 @@ export const FormItemTitle = ({ children, formItem, duplicateComponents }: FormI
<div
className={classNames(classes.root, {
[classes.duplicateComponentIds]: duplicateComponents?.includes(formItem.id),
[classes.deprecatedComponent]: isComponentDeprecated(formItem.type),
})}
>
<div className={classes.label}>{children}</div>
Expand Down
7 changes: 7 additions & 0 deletions frontend/packages/ux-editor/src/testing/componentMocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,12 @@ const repeatingGroupContainer: FormContainer<ComponentType.RepeatingGroup> = {
itemType: 'CONTAINER',
dataModelBindings: { group: '' },
};

const summaryComponent: FormComponent<ComponentType.Summary> = {
...commonProps(ComponentType.Summary),
componentRef: 'some-component',
};

const summary2Component: FormComponent<ComponentType.Summary2> = {
...commonProps(ComponentType.Summary2),
target: {
Expand Down Expand Up @@ -211,5 +217,6 @@ export const componentMocks = {
[ComponentType.Subform]: subformComponent,
[ComponentType.TextArea]: textareaComponent,
[ComponentType.Custom]: thirdPartyComponent,
[ComponentType.Summary]: summaryComponent,
[ComponentType.Summary2]: summary2Component,
};
11 changes: 11 additions & 0 deletions frontend/packages/ux-editor/src/utils/component.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
PropertyTypes,
propertyTypeMatcher,
getSupportedPropertyKeysForPropertyType,
isComponentDeprecated,
} from './component';
import { ComponentType, CustomComponentType } from 'app-shared/types/ComponentType';
import type {
Expand Down Expand Up @@ -466,3 +467,13 @@ describe('getSupportedPropertyKeysForPropertyType', () => {
).toEqual(['testProperty1']);
});
});

describe('isComponentDeprecated', () => {
it('should return true if component is deprecated', () => {
expect(isComponentDeprecated(ComponentType.Summary)).toBe(true);
});

it('should return false if component is not deprecated', () => {
expect(isComponentDeprecated(ComponentType.Input)).toBe(false);
});
});
7 changes: 6 additions & 1 deletion frontend/packages/ux-editor/src/utils/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import type {
FormRadioButtonsComponent,
SelectionComponentType,
} from '../types/FormComponent';
import type { ComponentType, CustomComponentType } from 'app-shared/types/ComponentType';
import { ComponentType, type CustomComponentType } from 'app-shared/types/ComponentType';
import { formItemConfigs } from '../data/formItemConfig';
import type { FormItem } from '../types/FormItem';
import type { KeyValuePairs } from 'app-shared/types/KeyValuePairs';
Expand Down Expand Up @@ -208,3 +208,8 @@ export const isPropertyTypeSupported = (property: KeyValuePairs) => {

return supportedPropertyTypes.includes(property?.type);
};

export const isComponentDeprecated = (type: ComponentType) => {
const deprecatedComponents = [ComponentType.Summary];
return deprecatedComponents.includes(type);
};