New field creates fields widget field (#18022)

## Context
Introducing "NewFieldDefaultConfiguration" to FIELDS widget
configurations
```typescript
{
  isVisible: boolean;
  viewFieldGroupId: string | null;
}
```

This configuration will define where a new field should be added (which
section) and its default visibility inside FIELDS widget views.
The new field position should always be at the end (meaning the last
position for the view fields OR the last position of a viewFieldGroup)

See "New fields" on this screenshot
<img width="401" height="724" alt="Layout V1"
src="https://github.com/user-attachments/assets/4969bcaa-f244-4504-8947-778a02c24c47"
/>
This commit is contained in:
Weiko
2026-02-18 12:03:27 +01:00
committed by GitHub
parent 477fbc0865
commit f3faa11dd2
18 changed files with 1203 additions and 33 deletions
@@ -16,7 +16,10 @@ export type FromCreatePageLayoutWidgetInputToFlatPageLayoutWidgetToCreateArgs =
flatApplication: FlatApplication;
} & Pick<
AllFlatEntityMaps,
'flatPageLayoutTabMaps' | 'flatObjectMetadataMaps' | 'flatFieldMetadataMaps'
| 'flatPageLayoutTabMaps'
| 'flatObjectMetadataMaps'
| 'flatFieldMetadataMaps'
| 'flatViewFieldGroupMaps'
>;
export const fromCreatePageLayoutWidgetInputToFlatPageLayoutWidgetToCreate = ({
@@ -26,6 +29,7 @@ export const fromCreatePageLayoutWidgetInputToFlatPageLayoutWidgetToCreate = ({
flatPageLayoutTabMaps,
flatObjectMetadataMaps,
flatFieldMetadataMaps,
flatViewFieldGroupMaps,
}: FromCreatePageLayoutWidgetInputToFlatPageLayoutWidgetToCreateArgs): FlatPageLayoutWidget => {
const { pageLayoutTabId, ...createPageLayoutWidgetInput } =
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties(
@@ -76,6 +80,8 @@ export const fromCreatePageLayoutWidgetInputToFlatPageLayoutWidgetToCreate = ({
configuration: createPageLayoutWidgetInput.configuration,
fieldMetadataUniversalIdentifierById:
flatFieldMetadataMaps.universalIdentifierById,
viewFieldGroupUniversalIdentifierById:
flatViewFieldGroupMaps.universalIdentifierById,
shouldThrowOnMissingIdentifier: true,
}),
};
@@ -42,10 +42,12 @@ const getFieldMetadataUniversalIdentifier = ({
export const fromPageLayoutWidgetConfigurationToUniversalConfiguration = ({
configuration,
fieldMetadataUniversalIdentifierById,
viewFieldGroupUniversalIdentifierById = {},
shouldThrowOnMissingIdentifier = false,
}: {
configuration: PageLayoutWidgetConfiguration;
fieldMetadataUniversalIdentifierById: Partial<Record<string, string>>;
viewFieldGroupUniversalIdentifierById?: Partial<Record<string, string>>;
shouldThrowOnMissingIdentifier?: boolean;
}): UniversalPageLayoutWidgetConfiguration => {
switch (configuration.configurationType) {
@@ -200,9 +202,43 @@ export const fromPageLayoutWidgetConfigurationToUniversalConfiguration = ({
};
}
case WidgetConfigurationType.FIELDS: {
const { newFieldDefaultConfiguration, ...rest } = configuration;
if (!isDefined(newFieldDefaultConfiguration)) {
return configuration;
}
let viewFieldGroupUniversalIdentifier: string | null = null;
if (isDefined(newFieldDefaultConfiguration.viewFieldGroupId)) {
viewFieldGroupUniversalIdentifier =
viewFieldGroupUniversalIdentifierById[
newFieldDefaultConfiguration.viewFieldGroupId
] ?? null;
if (
!isDefined(viewFieldGroupUniversalIdentifier) &&
shouldThrowOnMissingIdentifier
) {
throw new FlatEntityMapsException(
`View field group universal identifier not found for id: ${newFieldDefaultConfiguration.viewFieldGroupId}`,
FlatEntityMapsExceptionCode.RELATION_UNIVERSAL_IDENTIFIER_NOT_FOUND,
);
}
}
return {
...rest,
newFieldDefaultConfiguration: {
isVisible: newFieldDefaultConfiguration.isVisible,
viewFieldGroupId: viewFieldGroupUniversalIdentifier,
},
};
}
case WidgetConfigurationType.VIEW:
case WidgetConfigurationType.FIELD:
case WidgetConfigurationType.FIELDS:
case WidgetConfigurationType.TIMELINE:
case WidgetConfigurationType.TASKS:
case WidgetConfigurationType.NOTES:
@@ -12,6 +12,7 @@ import { type FromEntityToFlatEntityArgs } from 'src/engine/workspace-cache/type
type FromPageLayoutWidgetEntityToFlatPageLayoutWidgetArgs =
FromEntityToFlatEntityArgs<'pageLayoutWidget'> & {
fieldMetadataUniversalIdentifierById: Partial<Record<string, string>>;
viewFieldGroupUniversalIdentifierById?: Partial<Record<string, string>>;
};
export const fromPageLayoutWidgetEntityToFlatPageLayoutWidget = ({
@@ -20,6 +21,7 @@ export const fromPageLayoutWidgetEntityToFlatPageLayoutWidget = ({
pageLayoutTabIdToUniversalIdentifierMap,
objectMetadataIdToUniversalIdentifierMap,
fieldMetadataUniversalIdentifierById,
viewFieldGroupUniversalIdentifierById,
}: FromPageLayoutWidgetEntityToFlatPageLayoutWidgetArgs): FlatPageLayoutWidget => {
const pageLayoutWidgetEntityWithoutRelations = removePropertiesFromRecord(
pageLayoutWidgetEntity,
@@ -70,6 +72,7 @@ export const fromPageLayoutWidgetEntityToFlatPageLayoutWidget = ({
fromPageLayoutWidgetConfigurationToUniversalConfiguration({
configuration: pageLayoutWidgetEntityWithoutRelations.configuration,
fieldMetadataUniversalIdentifierById,
viewFieldGroupUniversalIdentifierById,
});
return {
@@ -30,12 +30,15 @@ export const fromUpdatePageLayoutWidgetInputToFlatPageLayoutWidgetToUpdateOrThro
flatPageLayoutWidgetMaps,
flatObjectMetadataMaps,
flatFieldMetadataMaps,
flatViewFieldGroupMaps,
}: {
updatePageLayoutWidgetInput: UpdatePageLayoutWidgetInputWithId;
flatPageLayoutWidgetMaps: FlatPageLayoutWidgetMaps;
} & Pick<
AllFlatEntityMaps,
'flatObjectMetadataMaps' | 'flatFieldMetadataMaps'
| 'flatObjectMetadataMaps'
| 'flatFieldMetadataMaps'
| 'flatViewFieldGroupMaps'
>): FlatPageLayoutWidget => {
const { id: pageLayoutWidgetToUpdateId } =
extractAndSanitizeObjectStringFields(rawUpdatePageLayoutWidgetInput, [
@@ -97,6 +100,8 @@ export const fromUpdatePageLayoutWidgetInputToFlatPageLayoutWidgetToUpdateOrThro
configuration: flatPageLayoutWidgetToUpdate.configuration,
fieldMetadataUniversalIdentifierById:
flatFieldMetadataMaps.universalIdentifierById,
viewFieldGroupUniversalIdentifierById:
flatViewFieldGroupMaps.universalIdentifierById,
});
}