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

Update data model selection in component config #12949

Merged
merged 53 commits into from
Jul 16, 2024
Merged
Show file tree
Hide file tree
Changes from 48 commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
0f36dcd
replace `LegacySelect` with `NativeSelect`
lassopicasso Jun 4, 2024
f5066f8
update existing config - display default data model together with dat…
lassopicasso Jun 4, 2024
88935f7
add featureflag
lassopicasso Jun 4, 2024
336f377
Remove hack in metadata response - issue #12457 is solved
lassopicasso Jun 5, 2024
4772b9a
Merge branch 'main' into update-data-model-selection-in-component-config
lassopicasso Jun 5, 2024
cdd25dd
use StudioDisplayTile in current config
lassopicasso Jun 7, 2024
162ff9d
adjust size of icon + some other adjustments
lassopicasso Jun 7, 2024
28107fa
temp hard update input schema to new structure from apps
lassopicasso Jun 7, 2024
365f794
small adjustment in text
lassopicasso Jun 7, 2024
d561fcf
functionality in place - refactor to one more level - two components …
lassopicasso Jun 11, 2024
d301645
rename editDataModelbindings folder and files to single instead of pl…
lassopicasso Jun 11, 2024
3a464d0
Merge branch 'main' into update-data-model-selection-in-component-config
lassopicasso Jun 12, 2024
789c9fb
rename SelectDataModelComponent -> SelectDataFieldComponent
lassopicasso Jun 12, 2024
cb63a5c
Add validation to datamodelbindings + refactoring
lassopicasso Jun 19, 2024
f181a9e
redo hook
lassopicasso Jun 21, 2024
3d03307
add validations
lassopicasso Jun 21, 2024
7ecd65f
Merge branch 'main' into update-data-model-selection-in-component-config
lassopicasso Jun 21, 2024
0c8430b
update text resources and update properties in new format: instead of…
lassopicasso Jun 21, 2024
3c7f379
Fix editDataModelBinding tests
lassopicasso Jun 24, 2024
261411c
definedBinding test
lassopicasso Jun 25, 2024
a7514f2
add test file for undefinedbinding
lassopicasso Jun 26, 2024
5799f97
editBinding tests
lassopicasso Jul 1, 2024
ce31d56
update defined and undefined binding tests
lassopicasso Jul 1, 2024
2cd75a3
smaller changes revealed on building tests
lassopicasso Jul 1, 2024
bd2380e
rename dataModel.ts -> dataModelUtils.ts
lassopicasso Jul 2, 2024
6e2edae
create tests for useValidDataModels hook
lassopicasso Jul 2, 2024
16a0002
fix old tests + update new tests
lassopicasso Jul 2, 2024
4fc214f
small fix
lassopicasso Jul 2, 2024
de2ed54
add editDataModelBinding tests + update editbinding tests
lassopicasso Jul 3, 2024
8d5720d
Merge branch 'main' into update-data-model-selection-in-component-config
lassopicasso Jul 3, 2024
78b217b
remove waitFor
lassopicasso Jul 3, 2024
bff626f
update data model tests
lassopicasso Jul 3, 2024
195d7f6
update data model utils + remove a util no longer used
lassopicasso Jul 3, 2024
3f58c7a
add tests for data model utils + small stuff
lassopicasso Jul 3, 2024
8cfae91
cover some untested code
lassopicasso Jul 4, 2024
d2912b1
Merge branch 'main' into update-data-model-selection-in-component-config
lassopicasso Jul 4, 2024
5d1e103
Merge branch 'main' into update-data-model-selection-in-component-config
lassopicasso Jul 4, 2024
827e672
Fix playwright tests
lassopicasso Jul 4, 2024
cff4ba7
Merge branch 'main' into update-data-model-selection-in-component-config
lassopicasso Jul 4, 2024
306fc80
Merge branch 'main' into update-data-model-selection-in-component-config
lassopicasso Jul 8, 2024
0332424
add playwright test
lassopicasso Jul 8, 2024
f3100f7
Merge branch 'main' into update-data-model-selection-in-component-config
lassopicasso Jul 8, 2024
f548115
PR feedback
lassopicasso Jul 15, 2024
bb0da0f
Merge branch 'main' into update-data-model-selection-in-component-config
lassopicasso Jul 15, 2024
9eda0cb
Merge branch 'update-data-model-selection-in-component-config' of htt…
lassopicasso Jul 15, 2024
042473a
fix buttons gap
lassopicasso Jul 15, 2024
cb735e4
fix errors after merge with main
lassopicasso Jul 15, 2024
64bad72
change useDataModelMetadataQuery to object parameters
lassopicasso Jul 16, 2024
26828d0
redo `removeQueries` with `invalidQueries` and add refetch instead
lassopicasso Jul 16, 2024
b46db4e
Merge branch 'main' into update-data-model-selection-in-component-config
lassopicasso Jul 16, 2024
8b7cc0a
when deleting binding, set field and datatype to empty string
lassopicasso Jul 16, 2024
c9db02e
fix unit test after updating datatype to string
lassopicasso Jul 16, 2024
67e604b
Merge branch 'main' into update-data-model-selection-in-component-config
lassopicasso Jul 16, 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
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export const useDeleteDataModelMutation = () => {
queryClient.removeQueries({
queryKey: [QueryKey.JsonSchema, org, app, xsdPath],
});
queryClient.invalidateQueries({ queryKey: [QueryKey.AppMetadataModelIds, org, app] });
queryClient.removeQueries({ queryKey: [QueryKey.AppMetadataModelIds, org, app] });
standeren marked this conversation as resolved.
Show resolved Hide resolved
},
});
};
Expand Down
4 changes: 4 additions & 0 deletions frontend/language/src/nb.json
Original file line number Diff line number Diff line change
Expand Up @@ -1568,7 +1568,11 @@
"ux_editor.modal_properties_component_id_not_unique_error": "Komponenten må ha en unik ID",
"ux_editor.modal_properties_component_id_not_valid": "Komponent-ID-en må ha minst 2 tegn. ID-en kan ikke starte med bindestrek (-) eller slutte med bindestrek og tall. Bruk bare tegn fra det engelske alfabetet.",
"ux_editor.modal_properties_custom_code_list_id": "ID til egendefinert kodeliste",
"ux_editor.modal_properties_data_model_binding": "Datamodell",
"ux_editor.modal_properties_data_model_binding_not_present": "Denne komponenten kan ikke knyttes til et datamodellfelt",
"ux_editor.modal_properties_data_model_field_binding": "Datamodellknytning",
"ux_editor.modal_properties_data_model_field_choose": "Velg datamodellfelt",
"ux_editor.modal_properties_data_model_field_update": "Datamodellfelt må oppdateres",
"ux_editor.modal_properties_data_model_helper": "Velg en datamodellknytning",
"ux_editor.modal_properties_data_model_label.address": "Gateadresse",
"ux_editor.modal_properties_data_model_label.answer": "Svar",
Expand Down
3 changes: 2 additions & 1 deletion frontend/packages/shared/src/utils/featureToggleUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ export type SupportedFeatureFlags =
| 'componentConfigBeta'
| 'shouldOverrideAppLibCheck'
| 'resourceMigration'
| 'displayPaymentTaskProcessEditor';
| 'displayPaymentTaskProcessEditor'
| 'multipleDataModelsPerTask';

/*
* Please add all the features that you want to be toggle on by default here.
Expand Down
6 changes: 5 additions & 1 deletion frontend/packages/ux-editor/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@ export function App() {
const { selectedFormLayoutSetName } = useAppContext();
const { isSuccess: areWidgetsFetched, isError: widgetFetchedError } = useWidgetsQuery(org, app);
const { isSuccess: isDataModelFetched, isError: dataModelFetchedError } =
useDataModelMetadataQuery(org, app, selectedFormLayoutSetName, undefined);
useDataModelMetadataQuery({
org,
app,
layoutSetName: selectedFormLayoutSetName,
});
const { isSuccess: areTextResourcesFetched } = useTextResourcesQuery(org, app);

const componentIsReady = areWidgetsFetched && isDataModelFetched && areTextResourcesFetched;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { screen } from '@testing-library/react';
import { screen, waitForElementToBeRemoved } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { DataModelBindings } from './DataModelBindings';
import { FormItemContext } from '../../containers/FormItemContext';
Expand All @@ -17,19 +17,21 @@ import { layoutSet1NameMock } from '@altinn/ux-editor/testing/layoutSetsMock';
import { app, org } from '@studio/testing/testids';
import type { DataModelMetadataResponse } from 'app-shared/types/api';

const defaultModel = 'testModel';

const dataModelMetadata: DataModelMetadataResponse = {
elements: {
testModel: {
id: 'testModel',
id: defaultModel,
type: 'ComplexType',
dataBindingName: 'testModel',
displayString: 'testModel',
dataBindingName: defaultModel,
displayString: defaultModel,
isReadOnly: false,
isTagContent: false,
jsonSchemaPointer: '#/definitions/testModel',
maxOccurs: 1,
minOccurs: 1,
name: 'testModel',
name: defaultModel,
parentElement: null,
restrictions: [],
texts: [],
Expand Down Expand Up @@ -115,7 +117,7 @@ describe('DataModelBindings', () => {
},
);

it('should render already existing bindings in previewMode with label', () => {
it('should render already existing bindings in previewMode with label', async () => {
render({
props: {
formItem: {
Expand All @@ -131,6 +133,10 @@ describe('DataModelBindings', () => {
},
});

await waitForElementToBeRemoved(() =>
screen.queryAllByTitle(textMock('ux_editor.modal_properties_loading')),
);

['address', 'careOf'].forEach((prop) => {
const dataModelButton = screen.getByText(
textMock(`ux_editor.modal_properties_data_model_label.${prop}`),
Expand Down Expand Up @@ -281,8 +287,13 @@ describe('DataModelBindings', () => {
name: textMock(`ux_editor.component_title.Input`),
});
await user.click(dataModelButton);
const option = screen.getByText('testModel');
await user.click(option);

const dataModelFieldSelector = screen.getByRole('combobox', {
name: textMock('ux_editor.modal_properties_data_model_field_binding'),
});
const option = screen.getByRole('option', { name: defaultModel });
await user.selectOptions(dataModelFieldSelector, option);

expect(formItemContextProviderMock.handleUpdate).toHaveBeenCalledTimes(1);
expect(formItemContextProviderMock.debounceSave).toHaveBeenCalledTimes(1);
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useState } from 'react';
import { EditDataModelBindings } from '../config/editModal/EditDataModelBindings/EditDataModelBindings';
import { EditDataModelBinding } from '../config/editModal/EditDataModelBinding/EditDataModelBinding';
import { StudioProperty, StudioSpinner } from '@studio/components';
import { Alert, Switch } from '@digdir/designsystemet-react';
import { useComponentSchemaQuery } from '../../hooks/queries/useComponentSchemaQuery';
Expand All @@ -15,6 +15,7 @@ export const DataModelBindings = (): React.JSX.Element => {
const { formItemId, formItem, handleUpdate, debounceSave } = useFormItemContext();
const { data: schema } = useComponentSchemaQuery(formItem.type);
const [multipleAttachments, setMultipleAttachments] = useState<boolean>(false);

const t = useText();

React.useEffect(() => {
Expand Down Expand Up @@ -87,7 +88,7 @@ export const DataModelBindings = (): React.JSX.Element => {
className={classes.dataModelBindings}
key={`${formItem.id}-data-model-${propertyKey}`}
>
<EditDataModelBindings
<EditDataModelBinding
component={formItem}
handleComponentChange={async (updatedComponent, mutateOptions) => {
handleUpdate(updatedComponent);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react';
import { v1 as uuidv1 } from 'uuid';
import Modal from 'react-modal';
import { getComponentTitleByComponentType } from '../../utils/language';
import { SelectDataModelComponent } from './SelectDataModelComponent';
import { SelectDataFieldComponent } from './SelectDataFieldComponent';
import type {
IFormDesignerComponents,
IFormDesignerContainers,
Expand Down Expand Up @@ -332,13 +332,12 @@ class ConditionalRendering extends React.Component<
/>

<div>
<SelectDataModelComponent
<SelectDataFieldComponent
label={this.props.t('ux_editor.modal_properties_data_model_helper')}
onDataModelChange={this.handleParamDataChange.bind(null, paramName)}
selectedElement={
this.state.conditionalRendering.inputParams[paramName]
}
hideRestrictions={true}
/>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,13 @@ const waitForData = async () => {
const layoutSchemaResult = renderHookWithProviders(() => useLayoutSchemaQuery()).result;
await waitFor(() => expect(layoutSchemaResult.current[0].isSuccess).toBe(true));
const dataModelMetadataResult = renderHookWithProviders(
() => useDataModelMetadataQuery(org, app, layoutSet1NameMock, dataModelNameMock),
() =>
useDataModelMetadataQuery({
org,
app,
layoutSetName: layoutSet1NameMock,
dataModelName: dataModelNameMock,
}),
{ queries: { getDataModelMetadata } },
).result;
await waitFor(() => expect(dataModelMetadataResult.current.isSuccess).toBe(true));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,11 @@ export const ExpressionContent = ({
const { org, app } = useStudioEnvironmentParams();
const { selectedFormLayoutSetName } = useAppContext();
const { data: formLayoutsData } = useFormLayoutsQuery(org, app, selectedFormLayoutSetName);
const { data: dataModelMetadata } = useDataModelMetadataQuery(
const { data: dataModelMetadata } = useDataModelMetadataQuery({
org,
app,
selectedFormLayoutSetName,
undefined,
);
layoutSetName: selectedFormLayoutSetName,
});
const dataLookupOptions: Partial<DataLookupOptions> = useMemo(
() => ({
[DataLookupFuncName.Component]: getComponentIds(formLayoutsData),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import { v1 as uuidv1 } from 'uuid';
import { SelectDataModelComponent } from './SelectDataModelComponent';
import { SelectDataFieldComponent } from './SelectDataFieldComponent';
import type { IRuleModelFieldElement } from '../../types/global';
import { withTranslation } from 'react-i18next';
import classes from './RuleComponent.module.css';
Expand Down Expand Up @@ -176,11 +176,10 @@ class Rule extends React.Component<IRuleComponentProps, IRuleComponentState> {
disabled={true}
/>
<div>
<SelectDataModelComponent
<SelectDataFieldComponent
label={this.props.t('ux_editor.modal_properties_data_model_helper')}
onDataModelChange={this.handleParamDataChange.bind(null, paramName)}
selectedElement={this.state.ruleConnection.inputParams[paramName]}
hideRestrictions={true}
/>
</div>
</div>
Expand All @@ -207,11 +206,10 @@ class Rule extends React.Component<IRuleComponentProps, IRuleComponentState> {
disabled={true}
/>
<div>
<SelectDataModelComponent
<SelectDataFieldComponent
label={this.props.t('ux_editor.modal_properties_data_model_helper')}
onDataModelChange={this.handleOutParamDataChange.bind(null, 'outParam0')}
selectedElement={this.state.ruleConnection.outParams.outParam0}
hideRestrictions={true}
/>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import React from 'react';
import { screen, waitFor } from '@testing-library/react';
import { screen } from '@testing-library/react';
import { renderWithProviders } from '../../testing/mocks';
import { SelectDataModelComponent } from './SelectDataModelComponent';
import { SelectDataFieldComponent } from './SelectDataFieldComponent';
import { textMock } from '@studio/testing/mocks/i18nMock';
import userEvent from '@testing-library/user-event';
import { ComponentType } from 'app-shared/types/ComponentType';
import { getDataModelFieldsFilter } from '../../utils/dataModel';
import { getDataModelFieldsFilter } from '../../utils/dataModelUtils';
import { queryClientMock } from 'app-shared/mocks/queryClientMock';
import { QueryKey } from 'app-shared/types/QueryKey';
import { app, org } from '@studio/testing/testids';
Expand Down Expand Up @@ -75,7 +75,7 @@ const render = async ({
dataModelMetadata,
);
renderWithProviders(
<SelectDataModelComponent
<SelectDataFieldComponent
label={textMock(`ux_editor.component_title.${componentType}`)}
onDataModelChange={handleComponentChange}
dataModelFieldsFilter={getDataModelFieldsFilter(componentType, label)}
Expand All @@ -87,15 +87,18 @@ const render = async ({
describe('SelectDataModelComponent', () => {
it('should show select with no selected option by default', async () => {
await render();

expect(
screen.getByText(textMock(`ux_editor.component_title.${ComponentType.Input}`)),
screen.getByLabelText(textMock(`ux_editor.component_title.${ComponentType.Input}`)),
).toBeInTheDocument();
expect(screen.getByRole('combobox').getAttribute('value')).toEqual('');
const selector = screen.getByRole('combobox') as HTMLSelectElement;
expect(selector.value).toEqual('');
});

it('renders when dataModelData is undefined', async () => {
await render({ dataModelMetadata: undefined });
const bindingTitle = screen.getByText(

const bindingTitle = screen.getByLabelText(
textMock(`ux_editor.component_title.${ComponentType.Input}`),
);
expect(bindingTitle).toBeInTheDocument();
Expand All @@ -115,13 +118,14 @@ describe('SelectDataModelComponent', () => {
await render({
handleComponentChange,
});

const selectElement = screen.getByRole('combobox', {
name: textMock(`ux_editor.component_title.${ComponentType.Input}`),
});
await user.click(selectElement);
const optionElement = screen.getByText('testModel.field1');
await user.click(optionElement);
await waitFor(() => {});
const optionElement = screen.getByRole('option', { name: 'testModel.field1' });
await user.selectOptions(selectElement, optionElement);

expect(handleComponentChange).toHaveBeenCalled();
expect(handleComponentChange).toHaveBeenCalledWith('testModel.field1');
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,39 +1,44 @@
import React, { useEffect } from 'react';
import { LegacySelect } from '@digdir/design-system-react';
import { StudioNativeSelect } from '@studio/components';
import { useDataModelMetadataQuery } from '../../hooks/queries/useDataModelMetadataQuery';
import { FormField } from '../FormField';
import type { Option } from '@altinn/text-editor/types';
import { useStudioEnvironmentParams } from 'app-shared/hooks/useStudioEnvironmentParams';
import type { DataModelFieldElement } from 'app-shared/types/DataModelFieldElement';
import { useAppContext } from '../../hooks';

export interface ISelectDataModelProps {
export interface ISelectDataFieldProps {
inputId?: string;
selectedElement: string;
label: string;
onDataModelChange: (dataModelField: string) => void;
noOptionsMessage?: string;
hideRestrictions?: boolean;
dataModelFieldsFilter?: (dataModelField: DataModelFieldElement) => boolean;
componentType?: string;
propertyPath?: string;
helpText?: string;
dataModelName?: string;
}

export const SelectDataModelComponent = ({
export const SelectDataFieldComponent = ({
inputId,
selectedElement,
label,
onDataModelChange,
noOptionsMessage,
dataModelFieldsFilter,
componentType,
helpText,
propertyPath,
}: ISelectDataModelProps) => {
dataModelName,
}: ISelectDataFieldProps) => {
const { org, app } = useStudioEnvironmentParams();
const { selectedFormLayoutSetName } = useAppContext();
const { data } = useDataModelMetadataQuery(org, app, selectedFormLayoutSetName, undefined);
const { data } = useDataModelMetadataQuery({
org,
app,
layoutSetName: selectedFormLayoutSetName,
dataModelName,
});
const [dataModelElementNames, setDataModelElementNames] = React.useState<Option[]>([]);

useEffect(() => {
Expand All @@ -45,10 +50,11 @@ export const SelectDataModelComponent = ({
setDataModelElementNames(elementNames);
}, [data, dataModelFieldsFilter]);

const onChangeSelectedBinding = (e: any) => {
onDataModelChange(e);
const onChangeSelectedBinding = (value: string) => {
onDataModelChange(value);
};

dataModelElementNames.unshift({ value: '', label: '' });
return (
<FormField
id={inputId}
Expand All @@ -59,11 +65,13 @@ export const SelectDataModelComponent = ({
helpText={helpText}
label={label}
renderField={({ fieldProps }) => (
<LegacySelect
{...fieldProps}
onChange={(e: any) => fieldProps.onChange(e)}
options={dataModelElementNames}
/>
<StudioNativeSelect {...fieldProps} onChange={(e) => fieldProps.onChange(e.target.value)}>
{dataModelElementNames.map((element) => (
<option key={element.value} value={element.value}>
{element.label}
</option>
))}
</StudioNativeSelect>
)}
/>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,7 @@
display: flex;
gap: var(--fds-spacing-1);
}

.error {
background-color: var(--fds-semantic-surface-danger-subtle);
}
Loading