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:
+8
-1
@@ -1,8 +1,9 @@
|
||||
import { Field, ObjectType } from '@nestjs/graphql';
|
||||
import { Field, HideField, ObjectType } from '@nestjs/graphql';
|
||||
|
||||
import { IDField } from '@ptc-org/nestjs-query-graphql';
|
||||
|
||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||
import { type ViewFieldGroupOverrides } from 'src/engine/metadata-modules/view-field-group/entities/view-field-group.entity';
|
||||
import { ViewFieldDTO } from 'src/engine/metadata-modules/view-field/dtos/view-field.dto';
|
||||
|
||||
@ObjectType('CoreViewFieldGroup')
|
||||
@@ -36,4 +37,10 @@ export class ViewFieldGroupDTO {
|
||||
|
||||
@Field(() => [ViewFieldDTO])
|
||||
viewFields?: ViewFieldDTO[];
|
||||
|
||||
@Field(() => Boolean, { nullable: false })
|
||||
isOverridden: boolean;
|
||||
|
||||
@HideField()
|
||||
overrides?: ViewFieldGroupOverrides | null;
|
||||
}
|
||||
|
||||
+8
-2
@@ -14,13 +14,19 @@ import {
|
||||
|
||||
import { ViewFieldEntity } from 'src/engine/metadata-modules/view-field/entities/view-field.entity';
|
||||
import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity';
|
||||
import { SyncableEntity } from 'src/engine/workspace-manager/types/syncable-entity.interface';
|
||||
import { OverridableEntity } from 'src/engine/workspace-manager/types/overridable-entity';
|
||||
|
||||
export type ViewFieldGroupOverrides = {
|
||||
name?: string;
|
||||
position?: number;
|
||||
isVisible?: boolean;
|
||||
};
|
||||
|
||||
@Entity({ name: 'viewFieldGroup', schema: 'core' })
|
||||
@Index('IDX_VIEW_FIELD_GROUP_WORKSPACE_ID_VIEW_ID', ['workspaceId', 'viewId'])
|
||||
@Index('IDX_VIEW_FIELD_GROUP_VIEW_ID', ['viewId'])
|
||||
export class ViewFieldGroupEntity
|
||||
extends SyncableEntity
|
||||
extends OverridableEntity<ViewFieldGroupOverrides>
|
||||
implements Required<ViewFieldGroupEntity>
|
||||
{
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
|
||||
+26
@@ -2,6 +2,7 @@ import { UseFilters, UseGuards } from '@nestjs/common';
|
||||
import {
|
||||
Args,
|
||||
Context,
|
||||
Float,
|
||||
Mutation,
|
||||
Parent,
|
||||
Query,
|
||||
@@ -9,6 +10,7 @@ import {
|
||||
} from '@nestjs/graphql';
|
||||
|
||||
import { isArray } from '@sniptt/guards';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { MetadataResolver } from 'src/engine/api/graphql/graphql-config/decorators/metadata-resolver.decorator';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
@@ -16,6 +18,7 @@ import { type IDataloaders } from 'src/engine/dataloaders/dataloader.interface';
|
||||
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
|
||||
import { NoPermissionGuard } from 'src/engine/guards/no-permission.guard';
|
||||
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
|
||||
import { resolveOverridableEntityProperty } from 'src/engine/metadata-modules/utils/resolve-overridable-entity-property.util';
|
||||
import { CreateViewFieldGroupInput } from 'src/engine/metadata-modules/view-field-group/dtos/inputs/create-view-field-group.input';
|
||||
import { DeleteViewFieldGroupInput } from 'src/engine/metadata-modules/view-field-group/dtos/inputs/delete-view-field-group.input';
|
||||
import { DestroyViewFieldGroupInput } from 'src/engine/metadata-modules/view-field-group/dtos/inputs/destroy-view-field-group.input';
|
||||
@@ -39,6 +42,29 @@ export class ViewFieldGroupResolver {
|
||||
private readonly fieldsWidgetUpsertService: FieldsWidgetUpsertService,
|
||||
) {}
|
||||
|
||||
@ResolveField(() => String)
|
||||
name(@Parent() viewFieldGroup: ViewFieldGroupDTO): string {
|
||||
return resolveOverridableEntityProperty(viewFieldGroup, 'name');
|
||||
}
|
||||
|
||||
@ResolveField(() => Float)
|
||||
position(@Parent() viewFieldGroup: ViewFieldGroupDTO): number {
|
||||
return resolveOverridableEntityProperty(viewFieldGroup, 'position');
|
||||
}
|
||||
|
||||
@ResolveField(() => Boolean)
|
||||
isVisible(@Parent() viewFieldGroup: ViewFieldGroupDTO): boolean {
|
||||
return resolveOverridableEntityProperty(viewFieldGroup, 'isVisible');
|
||||
}
|
||||
|
||||
@ResolveField(() => Boolean)
|
||||
isOverridden(@Parent() viewFieldGroup: ViewFieldGroupDTO): boolean {
|
||||
return (
|
||||
isDefined(viewFieldGroup.overrides) &&
|
||||
Object.keys(viewFieldGroup.overrides).length > 0
|
||||
);
|
||||
}
|
||||
|
||||
@Query(() => [ViewFieldGroupDTO])
|
||||
@UseGuards(NoPermissionGuard)
|
||||
async getCoreViewFieldGroups(
|
||||
|
||||
+297
-34
@@ -14,8 +14,11 @@ import { isFlatPageLayoutWidgetConfigurationOfType } from 'src/engine/metadata-m
|
||||
import { type FlatViewFieldGroupMaps } from 'src/engine/metadata-modules/flat-view-field-group/types/flat-view-field-group-maps.type';
|
||||
import { type FlatViewFieldGroup } from 'src/engine/metadata-modules/flat-view-field-group/types/flat-view-field-group.type';
|
||||
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 FlatViewMaps } from 'src/engine/metadata-modules/flat-view/types/flat-view-maps.type';
|
||||
import { WidgetConfigurationType } from 'src/engine/metadata-modules/page-layout-widget/enums/widget-configuration-type.type';
|
||||
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 UpsertFieldsWidgetFieldInput } from 'src/engine/metadata-modules/view-field-group/dtos/inputs/upsert-fields-widget-field.input';
|
||||
import { UpsertFieldsWidgetGroupInput } from 'src/engine/metadata-modules/view-field-group/dtos/inputs/upsert-fields-widget-group.input';
|
||||
import { UpsertFieldsWidgetInput } from 'src/engine/metadata-modules/view-field-group/dtos/inputs/upsert-fields-widget.input';
|
||||
@@ -204,11 +207,30 @@ export class FieldsWidgetUpsertService {
|
||||
}),
|
||||
);
|
||||
} else if (this.hasGroupChanged(existingGroup, inputGroup)) {
|
||||
const shouldOverride = isCallerOverridingEntity({
|
||||
callerApplicationUniversalIdentifier: applicationUniversalIdentifier,
|
||||
entityApplicationUniversalIdentifier:
|
||||
existingGroup.applicationUniversalIdentifier,
|
||||
workspaceCustomApplicationUniversalIdentifier:
|
||||
applicationUniversalIdentifier,
|
||||
});
|
||||
|
||||
const { overrides, updatedEditableProperties: sanitizedGroupProps } =
|
||||
sanitizeOverridableEntityInput({
|
||||
metadataName: 'viewFieldGroup',
|
||||
existingFlatEntity: existingGroup,
|
||||
updatedEditableProperties: {
|
||||
name: inputGroup.name,
|
||||
position: inputGroup.position,
|
||||
isVisible: inputGroup.isVisible,
|
||||
},
|
||||
shouldOverride,
|
||||
});
|
||||
|
||||
groupsToUpdate.push({
|
||||
...existingGroup,
|
||||
name: inputGroup.name,
|
||||
position: inputGroup.position,
|
||||
isVisible: inputGroup.isVisible,
|
||||
...sanitizedGroupProps,
|
||||
overrides,
|
||||
updatedAt: now,
|
||||
});
|
||||
}
|
||||
@@ -251,10 +273,22 @@ export class FieldsWidgetUpsertService {
|
||||
|
||||
const newViewFieldGroupId = inputGroup.id;
|
||||
|
||||
const resolvedIsVisible = isDefined(existingField.overrides?.isVisible)
|
||||
? existingField.overrides.isVisible
|
||||
: existingField.isVisible;
|
||||
const resolvedPosition = isDefined(existingField.overrides?.position)
|
||||
? existingField.overrides.position
|
||||
: existingField.position;
|
||||
// null is a valid override value (meaning "ungrouped"), so use !== undefined
|
||||
const resolvedViewFieldGroupId =
|
||||
existingField.overrides?.viewFieldGroupId !== undefined
|
||||
? existingField.overrides.viewFieldGroupId
|
||||
: existingField.viewFieldGroupId;
|
||||
|
||||
const hasChanged =
|
||||
existingField.isVisible !== inputField.isVisible ||
|
||||
existingField.position !== inputField.position ||
|
||||
existingField.viewFieldGroupId !== newViewFieldGroupId;
|
||||
resolvedIsVisible !== inputField.isVisible ||
|
||||
resolvedPosition !== inputField.position ||
|
||||
resolvedViewFieldGroupId !== newViewFieldGroupId;
|
||||
|
||||
if (!hasChanged) {
|
||||
return [];
|
||||
@@ -271,18 +305,72 @@ export class FieldsWidgetUpsertService {
|
||||
},
|
||||
});
|
||||
|
||||
return [
|
||||
{
|
||||
...existingField,
|
||||
isVisible: inputField.isVisible,
|
||||
position: inputField.position,
|
||||
viewFieldGroupId: newViewFieldGroupId,
|
||||
viewFieldGroupUniversalIdentifier,
|
||||
updatedAt: now,
|
||||
},
|
||||
];
|
||||
const shouldOverride = isCallerOverridingEntity({
|
||||
callerApplicationUniversalIdentifier: applicationUniversalIdentifier,
|
||||
entityApplicationUniversalIdentifier:
|
||||
existingField.applicationUniversalIdentifier,
|
||||
workspaceCustomApplicationUniversalIdentifier:
|
||||
applicationUniversalIdentifier,
|
||||
});
|
||||
|
||||
const { overrides, updatedEditableProperties: sanitizedFieldProps } =
|
||||
sanitizeOverridableEntityInput({
|
||||
metadataName: 'viewField',
|
||||
existingFlatEntity: existingField,
|
||||
updatedEditableProperties: {
|
||||
isVisible: inputField.isVisible,
|
||||
position: inputField.position,
|
||||
viewFieldGroupId: newViewFieldGroupId,
|
||||
},
|
||||
shouldOverride,
|
||||
});
|
||||
|
||||
const updatedField: FlatViewField = {
|
||||
...existingField,
|
||||
...sanitizedFieldProps,
|
||||
overrides,
|
||||
updatedAt: now,
|
||||
};
|
||||
|
||||
if (sanitizedFieldProps.viewFieldGroupId !== undefined) {
|
||||
const resolved = resolveEntityRelationUniversalIdentifiers({
|
||||
metadataName: 'viewField',
|
||||
foreignKeyValues: {
|
||||
viewFieldGroupId: updatedField.viewFieldGroupId,
|
||||
},
|
||||
flatEntityMaps: {
|
||||
flatViewFieldGroupMaps: optimisticFlatViewFieldGroupMaps,
|
||||
},
|
||||
});
|
||||
|
||||
updatedField.viewFieldGroupUniversalIdentifier =
|
||||
resolved.viewFieldGroupUniversalIdentifier;
|
||||
}
|
||||
|
||||
if (isDefined(overrides)) {
|
||||
updatedField.universalOverrides =
|
||||
fromViewFieldOverridesToUniversalOverrides({
|
||||
overrides,
|
||||
viewFieldGroupUniversalIdentifierById:
|
||||
optimisticFlatViewFieldGroupMaps.universalIdentifierById,
|
||||
});
|
||||
} else {
|
||||
updatedField.universalOverrides = null;
|
||||
}
|
||||
|
||||
return [updatedField];
|
||||
});
|
||||
|
||||
const fieldsWithStaleGroupOverrides =
|
||||
this.buildFieldUpdatesForStaleGroupOverrides({
|
||||
existingViewFields,
|
||||
groupsToDelete,
|
||||
alreadyUpdatedFieldIds: new Set(
|
||||
viewFieldsToUpdate.map((field) => field.id),
|
||||
),
|
||||
now,
|
||||
});
|
||||
|
||||
const validateAndBuildResult =
|
||||
await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration(
|
||||
{
|
||||
@@ -295,7 +383,10 @@ export class FieldsWidgetUpsertService {
|
||||
viewField: {
|
||||
flatEntityToCreate: [],
|
||||
flatEntityToDelete: [],
|
||||
flatEntityToUpdate: viewFieldsToUpdate,
|
||||
flatEntityToUpdate: [
|
||||
...viewFieldsToUpdate,
|
||||
...fieldsWithStaleGroupOverrides,
|
||||
],
|
||||
},
|
||||
},
|
||||
workspaceId,
|
||||
@@ -338,27 +429,80 @@ export class FieldsWidgetUpsertService {
|
||||
return [];
|
||||
}
|
||||
|
||||
const resolvedIsVisible = isDefined(existingField.overrides?.isVisible)
|
||||
? existingField.overrides.isVisible
|
||||
: existingField.isVisible;
|
||||
const resolvedPosition = isDefined(existingField.overrides?.position)
|
||||
? existingField.overrides.position
|
||||
: existingField.position;
|
||||
const resolvedViewFieldGroupId =
|
||||
existingField.overrides?.viewFieldGroupId !== undefined
|
||||
? existingField.overrides.viewFieldGroupId
|
||||
: existingField.viewFieldGroupId;
|
||||
|
||||
const hasChanged =
|
||||
existingField.isVisible !== inputField.isVisible ||
|
||||
existingField.position !== inputField.position ||
|
||||
existingField.viewFieldGroupId !== null;
|
||||
resolvedIsVisible !== inputField.isVisible ||
|
||||
resolvedPosition !== inputField.position ||
|
||||
resolvedViewFieldGroupId !== null;
|
||||
|
||||
if (!hasChanged) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
...existingField,
|
||||
isVisible: inputField.isVisible,
|
||||
position: inputField.position,
|
||||
viewFieldGroupId: null,
|
||||
viewFieldGroupUniversalIdentifier: null,
|
||||
updatedAt: now,
|
||||
},
|
||||
];
|
||||
const shouldOverride = isCallerOverridingEntity({
|
||||
callerApplicationUniversalIdentifier: applicationUniversalIdentifier,
|
||||
entityApplicationUniversalIdentifier:
|
||||
existingField.applicationUniversalIdentifier,
|
||||
workspaceCustomApplicationUniversalIdentifier:
|
||||
applicationUniversalIdentifier,
|
||||
});
|
||||
|
||||
const { overrides, updatedEditableProperties: sanitizedFieldProps } =
|
||||
sanitizeOverridableEntityInput({
|
||||
metadataName: 'viewField',
|
||||
existingFlatEntity: existingField,
|
||||
updatedEditableProperties: {
|
||||
isVisible: inputField.isVisible,
|
||||
position: inputField.position,
|
||||
viewFieldGroupId: null as string | null,
|
||||
},
|
||||
shouldOverride,
|
||||
});
|
||||
|
||||
const updatedField: FlatViewField = {
|
||||
...existingField,
|
||||
...sanitizedFieldProps,
|
||||
overrides,
|
||||
updatedAt: now,
|
||||
};
|
||||
|
||||
if (sanitizedFieldProps.viewFieldGroupId !== undefined) {
|
||||
updatedField.viewFieldGroupUniversalIdentifier = null;
|
||||
}
|
||||
|
||||
if (isDefined(overrides)) {
|
||||
updatedField.universalOverrides =
|
||||
fromViewFieldOverridesToUniversalOverrides({
|
||||
overrides,
|
||||
viewFieldGroupUniversalIdentifierById: {},
|
||||
});
|
||||
} else {
|
||||
updatedField.universalOverrides = null;
|
||||
}
|
||||
|
||||
return [updatedField];
|
||||
});
|
||||
|
||||
const fieldsWithStaleGroupOverrides =
|
||||
this.buildFieldUpdatesForStaleGroupOverrides({
|
||||
existingViewFields,
|
||||
groupsToDelete,
|
||||
alreadyUpdatedFieldIds: new Set(
|
||||
viewFieldsToUpdate.map((field) => field.id),
|
||||
),
|
||||
now: new Date().toISOString(),
|
||||
});
|
||||
|
||||
const validateAndBuildResult =
|
||||
await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration(
|
||||
{
|
||||
@@ -371,7 +515,10 @@ export class FieldsWidgetUpsertService {
|
||||
viewField: {
|
||||
flatEntityToCreate: [],
|
||||
flatEntityToDelete: [],
|
||||
flatEntityToUpdate: viewFieldsToUpdate,
|
||||
flatEntityToUpdate: [
|
||||
...viewFieldsToUpdate,
|
||||
...fieldsWithStaleGroupOverrides,
|
||||
],
|
||||
},
|
||||
},
|
||||
workspaceId,
|
||||
@@ -388,6 +535,111 @@ export class FieldsWidgetUpsertService {
|
||||
}
|
||||
}
|
||||
|
||||
private buildFieldUpdatesForStaleGroupOverrides({
|
||||
existingViewFields,
|
||||
groupsToDelete,
|
||||
alreadyUpdatedFieldIds,
|
||||
now,
|
||||
}: {
|
||||
existingViewFields: FlatViewField[];
|
||||
groupsToDelete: FlatViewFieldGroup[];
|
||||
alreadyUpdatedFieldIds: Set<string>;
|
||||
now: string;
|
||||
}): FlatViewField[] {
|
||||
if (groupsToDelete.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const deletedGroupIds = new Set(groupsToDelete.map((group) => group.id));
|
||||
|
||||
return existingViewFields
|
||||
.filter((field) => {
|
||||
if (alreadyUpdatedFieldIds.has(field.id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const overriddenGroupId = field.overrides?.viewFieldGroupId;
|
||||
|
||||
const hasStaleOverride =
|
||||
isDefined(overriddenGroupId) &&
|
||||
typeof overriddenGroupId === 'string' &&
|
||||
deletedGroupIds.has(overriddenGroupId);
|
||||
|
||||
const hasStaleBase =
|
||||
overriddenGroupId === undefined &&
|
||||
isDefined(field.viewFieldGroupId) &&
|
||||
deletedGroupIds.has(field.viewFieldGroupId);
|
||||
|
||||
const hasStaleBaseHiddenByNullOverride =
|
||||
overriddenGroupId === null &&
|
||||
isDefined(field.viewFieldGroupId) &&
|
||||
deletedGroupIds.has(field.viewFieldGroupId);
|
||||
|
||||
return (
|
||||
hasStaleOverride || hasStaleBase || hasStaleBaseHiddenByNullOverride
|
||||
);
|
||||
})
|
||||
.map((field) => {
|
||||
const overriddenGroupId = field.overrides?.viewFieldGroupId;
|
||||
const hasStaleOverride =
|
||||
isDefined(overriddenGroupId) &&
|
||||
typeof overriddenGroupId === 'string' &&
|
||||
deletedGroupIds.has(overriddenGroupId);
|
||||
|
||||
if (hasStaleOverride) {
|
||||
const { viewFieldGroupId: _, ...remainingOverrides } =
|
||||
field.overrides!;
|
||||
|
||||
const cleanedOverrides =
|
||||
Object.keys(remainingOverrides).length > 0
|
||||
? (remainingOverrides as typeof field.overrides)
|
||||
: null;
|
||||
|
||||
const baseGroupIsAlsoStale =
|
||||
isDefined(field.viewFieldGroupId) &&
|
||||
deletedGroupIds.has(field.viewFieldGroupId);
|
||||
|
||||
return {
|
||||
...field,
|
||||
...(baseGroupIsAlsoStale
|
||||
? {
|
||||
viewFieldGroupId: null,
|
||||
viewFieldGroupUniversalIdentifier: null,
|
||||
}
|
||||
: {}),
|
||||
overrides: cleanedOverrides,
|
||||
universalOverrides: isDefined(cleanedOverrides)
|
||||
? fromViewFieldOverridesToUniversalOverrides({
|
||||
overrides: cleanedOverrides,
|
||||
viewFieldGroupUniversalIdentifierById: {},
|
||||
})
|
||||
: null,
|
||||
updatedAt: now,
|
||||
};
|
||||
}
|
||||
|
||||
if (
|
||||
overriddenGroupId === null &&
|
||||
isDefined(field.viewFieldGroupId) &&
|
||||
deletedGroupIds.has(field.viewFieldGroupId)
|
||||
) {
|
||||
return {
|
||||
...field,
|
||||
viewFieldGroupId: null,
|
||||
viewFieldGroupUniversalIdentifier: null,
|
||||
updatedAt: now,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
...field,
|
||||
viewFieldGroupId: null,
|
||||
viewFieldGroupUniversalIdentifier: null,
|
||||
updatedAt: now,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
private buildGroupToCreate({
|
||||
inputGroup,
|
||||
viewId,
|
||||
@@ -423,6 +675,7 @@ export class FieldsWidgetUpsertService {
|
||||
isVisible: inputGroup.isVisible,
|
||||
viewId,
|
||||
viewUniversalIdentifier,
|
||||
overrides: null,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
deletedAt: null,
|
||||
@@ -435,10 +688,20 @@ export class FieldsWidgetUpsertService {
|
||||
existing: FlatViewFieldGroup,
|
||||
input: UpsertFieldsWidgetGroupInput,
|
||||
): boolean {
|
||||
const resolvedName = isDefined(existing.overrides?.name)
|
||||
? existing.overrides.name
|
||||
: existing.name;
|
||||
const resolvedPosition = isDefined(existing.overrides?.position)
|
||||
? existing.overrides.position
|
||||
: existing.position;
|
||||
const resolvedIsVisible = isDefined(existing.overrides?.isVisible)
|
||||
? existing.overrides.isVisible
|
||||
: existing.isVisible;
|
||||
|
||||
return (
|
||||
existing.name !== input.name ||
|
||||
existing.position !== input.position ||
|
||||
existing.isVisible !== input.isVisible
|
||||
resolvedName !== input.name ||
|
||||
resolvedPosition !== input.position ||
|
||||
resolvedIsVisible !== input.isVisible
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+4
@@ -157,6 +157,10 @@ export class ViewFieldGroupService {
|
||||
fromUpdateViewFieldGroupInputToFlatViewFieldGroupToUpdateOrThrow({
|
||||
flatViewFieldGroupMaps: existingFlatViewFieldGroupMaps,
|
||||
updateViewFieldGroupInput,
|
||||
callerApplicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
workspaceCustomApplicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
});
|
||||
|
||||
const validateAndBuildResult =
|
||||
|
||||
+4
@@ -1,3 +1,5 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type FlatViewFieldGroup } from 'src/engine/metadata-modules/flat-view-field-group/types/flat-view-field-group.type';
|
||||
import { type ViewFieldGroupDTO } from 'src/engine/metadata-modules/view-field-group/dtos/view-field-group.dto';
|
||||
|
||||
@@ -8,6 +10,8 @@ export const fromFlatViewFieldGroupToViewFieldGroupDto = (
|
||||
|
||||
return {
|
||||
...rest,
|
||||
isOverridden:
|
||||
isDefined(rest.overrides) && Object.keys(rest.overrides).length > 0,
|
||||
createdAt: new Date(createdAt),
|
||||
updatedAt: new Date(updatedAt),
|
||||
deletedAt: deletedAt ? new Date(deletedAt) : null,
|
||||
|
||||
Reference in New Issue
Block a user