View field override (#18572)
## Context This PR introduces overrides for view fields which will be useful for page layout FIELDS widgets fields position/groups/visibility override + restore logic.
This commit is contained in:
+1
@@ -199,6 +199,7 @@ export const computeFlatViewFieldsFromFieldsWidgets = ({
|
||||
size: DEFAULT_VIEW_FIELD_SIZE,
|
||||
position,
|
||||
aggregateOperation: null,
|
||||
universalOverrides: null,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
deletedAt: null,
|
||||
|
||||
+1
@@ -66,6 +66,7 @@ export const fromCreateViewFieldInputToFlatViewFieldToCreate = ({
|
||||
size: createViewFieldInput.size ?? DEFAULT_VIEW_FIELD_SIZE,
|
||||
position: createViewFieldInput.position ?? 0,
|
||||
aggregateOperation: createViewFieldInput.aggregateOperation ?? null,
|
||||
universalOverrides: null,
|
||||
viewFieldGroupUniversalIdentifier,
|
||||
applicationUniversalIdentifier: flatApplication.universalIdentifier,
|
||||
};
|
||||
|
||||
+45
-7
@@ -10,6 +10,9 @@ import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/
|
||||
import { resolveEntityRelationUniversalIdentifiers } from 'src/engine/metadata-modules/flat-entity/utils/resolve-entity-relation-universal-identifiers.util';
|
||||
import { FLAT_VIEW_FIELD_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-view-field/constants/flat-view-field-editable-properties.constant';
|
||||
import { type FlatViewFieldMaps } from 'src/engine/metadata-modules/flat-view-field/types/flat-view-field-maps.type';
|
||||
import { fromViewFieldOverridesToUniversalOverrides } from 'src/engine/metadata-modules/flat-view-field/utils/from-view-field-overrides-to-universal-overrides.util';
|
||||
import { isCallerOverridingEntity } from 'src/engine/metadata-modules/utils/is-caller-overriding-entity.util';
|
||||
import { sanitizeOverridableEntityInput } from 'src/engine/metadata-modules/utils/sanitize-overridable-entity-input.util';
|
||||
import { type UpdateViewFieldInput } from 'src/engine/metadata-modules/view-field/dtos/inputs/update-view-field.input';
|
||||
import {
|
||||
ViewFieldException,
|
||||
@@ -22,9 +25,13 @@ export const fromUpdateViewFieldInputToFlatViewFieldToUpdateOrThrow = ({
|
||||
updateViewFieldInput: rawUpdateViewFieldInput,
|
||||
flatViewFieldMaps,
|
||||
flatViewFieldGroupMaps,
|
||||
callerApplicationUniversalIdentifier,
|
||||
workspaceCustomApplicationUniversalIdentifier,
|
||||
}: {
|
||||
updateViewFieldInput: UpdateViewFieldInput;
|
||||
flatViewFieldMaps: FlatViewFieldMaps;
|
||||
callerApplicationUniversalIdentifier: string;
|
||||
workspaceCustomApplicationUniversalIdentifier: string;
|
||||
} & Pick<
|
||||
AllFlatEntityMaps,
|
||||
'flatViewFieldGroupMaps'
|
||||
@@ -47,23 +54,43 @@ export const fromUpdateViewFieldInputToFlatViewFieldToUpdateOrThrow = ({
|
||||
);
|
||||
}
|
||||
|
||||
const updatedEditableFieldProperties = extractAndSanitizeObjectStringFields(
|
||||
const editableProperties = extractAndSanitizeObjectStringFields(
|
||||
rawUpdateViewFieldInput.update,
|
||||
FLAT_VIEW_FIELD_EDITABLE_PROPERTIES,
|
||||
);
|
||||
|
||||
const flatViewFieldToUpdate = mergeUpdateInExistingRecord({
|
||||
existing: existingFlatViewFieldToUpdate,
|
||||
properties: FLAT_VIEW_FIELD_EDITABLE_PROPERTIES,
|
||||
update: updatedEditableFieldProperties,
|
||||
const shouldOverride = isCallerOverridingEntity({
|
||||
callerApplicationUniversalIdentifier,
|
||||
entityApplicationUniversalIdentifier:
|
||||
existingFlatViewFieldToUpdate.applicationUniversalIdentifier,
|
||||
workspaceCustomApplicationUniversalIdentifier,
|
||||
});
|
||||
|
||||
if (updatedEditableFieldProperties.viewFieldGroupId !== undefined) {
|
||||
const { overrides, updatedEditableProperties } =
|
||||
sanitizeOverridableEntityInput({
|
||||
metadataName: 'viewField',
|
||||
existingFlatEntity: existingFlatViewFieldToUpdate,
|
||||
updatedEditableProperties: editableProperties,
|
||||
shouldOverride,
|
||||
});
|
||||
|
||||
const mergedRecord = mergeUpdateInExistingRecord({
|
||||
existing: existingFlatViewFieldToUpdate,
|
||||
properties: [...FLAT_VIEW_FIELD_EDITABLE_PROPERTIES],
|
||||
update: updatedEditableProperties,
|
||||
});
|
||||
|
||||
const flatViewFieldToUpdate = {
|
||||
...mergedRecord,
|
||||
overrides,
|
||||
} as UniversalFlatViewField;
|
||||
|
||||
if (updatedEditableProperties.viewFieldGroupId !== undefined) {
|
||||
const { viewFieldGroupUniversalIdentifier } =
|
||||
resolveEntityRelationUniversalIdentifiers({
|
||||
metadataName: 'viewField',
|
||||
foreignKeyValues: {
|
||||
viewFieldGroupId: flatViewFieldToUpdate.viewFieldGroupId,
|
||||
viewFieldGroupId: mergedRecord.viewFieldGroupId,
|
||||
},
|
||||
flatEntityMaps: { flatViewFieldGroupMaps },
|
||||
});
|
||||
@@ -72,5 +99,16 @@ export const fromUpdateViewFieldInputToFlatViewFieldToUpdateOrThrow = ({
|
||||
viewFieldGroupUniversalIdentifier;
|
||||
}
|
||||
|
||||
if (isDefined(overrides)) {
|
||||
flatViewFieldToUpdate.universalOverrides =
|
||||
fromViewFieldOverridesToUniversalOverrides({
|
||||
overrides,
|
||||
viewFieldGroupUniversalIdentifierById:
|
||||
flatViewFieldGroupMaps.universalIdentifierById,
|
||||
});
|
||||
} else {
|
||||
flatViewFieldToUpdate.universalOverrides = null;
|
||||
}
|
||||
|
||||
return flatViewFieldToUpdate;
|
||||
};
|
||||
|
||||
+14
@@ -6,6 +6,7 @@ import {
|
||||
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
|
||||
import { getMetadataEntityRelationProperties } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-entity-relation-properties.util';
|
||||
import { type FlatViewField } from 'src/engine/metadata-modules/flat-view-field/types/flat-view-field.type';
|
||||
import { fromViewFieldOverridesToUniversalOverrides } from 'src/engine/metadata-modules/flat-view-field/utils/from-view-field-overrides-to-universal-overrides.util';
|
||||
import { type FromEntityToFlatEntityArgs } from 'src/engine/workspace-cache/types/from-entity-to-flat-entity-args.type';
|
||||
|
||||
export const fromViewFieldEntityToFlatViewField = ({
|
||||
@@ -69,6 +70,18 @@ export const fromViewFieldEntityToFlatViewField = ({
|
||||
}
|
||||
}
|
||||
|
||||
const viewFieldGroupUniversalIdentifierById = Object.fromEntries(
|
||||
viewFieldGroupIdToUniversalIdentifierMap.entries(),
|
||||
);
|
||||
|
||||
const universalOverrides = isDefined(viewFieldEntity.overrides)
|
||||
? fromViewFieldOverridesToUniversalOverrides({
|
||||
overrides: viewFieldEntity.overrides,
|
||||
viewFieldGroupUniversalIdentifierById,
|
||||
shouldThrowOnMissingIdentifier: false,
|
||||
})
|
||||
: null;
|
||||
|
||||
return {
|
||||
...viewFieldEntityWithoutRelations,
|
||||
createdAt: viewFieldEntity.createdAt.toISOString(),
|
||||
@@ -79,5 +92,6 @@ export const fromViewFieldEntityToFlatViewField = ({
|
||||
fieldMetadataUniversalIdentifier,
|
||||
viewUniversalIdentifier,
|
||||
viewFieldGroupUniversalIdentifier,
|
||||
universalOverrides,
|
||||
};
|
||||
};
|
||||
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
import { type FormatRecordSerializedRelationProperties } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import {
|
||||
FlatEntityMapsException,
|
||||
FlatEntityMapsExceptionCode,
|
||||
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
|
||||
import { type ViewFieldOverrides } from 'src/engine/metadata-modules/view-field/entities/view-field.entity';
|
||||
|
||||
type UniversalViewFieldOverrides =
|
||||
FormatRecordSerializedRelationProperties<ViewFieldOverrides>;
|
||||
|
||||
export const fromViewFieldOverridesToUniversalOverrides = ({
|
||||
overrides,
|
||||
viewFieldGroupUniversalIdentifierById,
|
||||
shouldThrowOnMissingIdentifier = true,
|
||||
}: {
|
||||
overrides: ViewFieldOverrides;
|
||||
viewFieldGroupUniversalIdentifierById: Partial<Record<string, string>>;
|
||||
shouldThrowOnMissingIdentifier?: boolean;
|
||||
}): UniversalViewFieldOverrides => {
|
||||
const { viewFieldGroupId, ...scalarOverrides } = overrides;
|
||||
|
||||
if (!isDefined(viewFieldGroupId)) {
|
||||
return {
|
||||
...scalarOverrides,
|
||||
...(viewFieldGroupId === null
|
||||
? { viewFieldGroupUniversalIdentifier: null }
|
||||
: {}),
|
||||
};
|
||||
}
|
||||
|
||||
const viewFieldGroupUniversalIdentifier =
|
||||
viewFieldGroupUniversalIdentifierById[viewFieldGroupId];
|
||||
|
||||
if (!isDefined(viewFieldGroupUniversalIdentifier)) {
|
||||
if (shouldThrowOnMissingIdentifier) {
|
||||
throw new FlatEntityMapsException(
|
||||
`ViewFieldGroup universal identifier not found for id: ${viewFieldGroupId}`,
|
||||
FlatEntityMapsExceptionCode.RELATION_UNIVERSAL_IDENTIFIER_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
...scalarOverrides,
|
||||
viewFieldGroupUniversalIdentifier: null,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
...scalarOverrides,
|
||||
viewFieldGroupUniversalIdentifier,
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user