Implement page layout override (#18472)
This commit is contained in:
+9
-1
@@ -11,7 +11,10 @@ import {
|
||||
ValidateNested,
|
||||
} from 'class-validator';
|
||||
import { GraphQLJSON } from 'graphql-type-json';
|
||||
import { PageLayoutWidgetPosition } from 'twenty-shared/types';
|
||||
import {
|
||||
PageLayoutWidgetConditionalDisplay,
|
||||
PageLayoutWidgetPosition,
|
||||
} from 'twenty-shared/types';
|
||||
|
||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||
import { GridPositionInput } from 'src/engine/metadata-modules/page-layout-widget/dtos/inputs/grid-position.input';
|
||||
@@ -60,4 +63,9 @@ export class UpdatePageLayoutWidgetWithIdInput {
|
||||
@IsObject()
|
||||
@IsOptional()
|
||||
configuration: AllPageLayoutWidgetConfiguration;
|
||||
|
||||
@Field(() => GraphQLJSON, { nullable: true })
|
||||
@IsObject()
|
||||
@IsOptional()
|
||||
conditionalDisplay?: PageLayoutWidgetConditionalDisplay | null;
|
||||
}
|
||||
|
||||
+9
-1
@@ -10,7 +10,10 @@ import {
|
||||
ValidateNested,
|
||||
} from 'class-validator';
|
||||
import { GraphQLJSON } from 'graphql-type-json';
|
||||
import { PageLayoutWidgetPosition } from 'twenty-shared/types';
|
||||
import {
|
||||
PageLayoutWidgetConditionalDisplay,
|
||||
PageLayoutWidgetPosition,
|
||||
} from 'twenty-shared/types';
|
||||
|
||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||
import { GridPositionInput } from 'src/engine/metadata-modules/page-layout-widget/dtos/inputs/grid-position.input';
|
||||
@@ -49,4 +52,9 @@ export class UpdatePageLayoutWidgetInput {
|
||||
@IsObject()
|
||||
@IsOptional()
|
||||
configuration?: AllPageLayoutWidgetConfiguration;
|
||||
|
||||
@Field(() => GraphQLJSON, { nullable: true })
|
||||
@IsObject()
|
||||
@IsOptional()
|
||||
conditionalDisplay?: PageLayoutWidgetConditionalDisplay | null;
|
||||
}
|
||||
|
||||
+13
-1
@@ -1,4 +1,9 @@
|
||||
import { Field, ObjectType, registerEnumType } from '@nestjs/graphql';
|
||||
import {
|
||||
Field,
|
||||
HideField,
|
||||
ObjectType,
|
||||
registerEnumType,
|
||||
} from '@nestjs/graphql';
|
||||
|
||||
import { IDField } from '@ptc-org/nestjs-query-graphql';
|
||||
import GraphQLJSON from 'graphql-type-json';
|
||||
@@ -8,6 +13,7 @@ import {
|
||||
} from 'twenty-shared/types';
|
||||
|
||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||
import { type PageLayoutWidgetOverrides } from 'src/engine/metadata-modules/page-layout-widget/entities/page-layout-widget.entity';
|
||||
import { PageLayoutWidgetPositionUnion } from 'src/engine/metadata-modules/page-layout-widget/dtos/page-layout-widget-position.union';
|
||||
import { WidgetConfiguration } from 'src/engine/metadata-modules/page-layout-widget/dtos/widget-configuration.interface';
|
||||
import { WidgetType } from 'src/engine/metadata-modules/page-layout-widget/enums/widget-type.enum';
|
||||
@@ -67,4 +73,10 @@ export class PageLayoutWidgetDTO {
|
||||
|
||||
@Field(() => Date, { nullable: true })
|
||||
deletedAt?: Date;
|
||||
|
||||
@Field(() => Boolean, { nullable: false })
|
||||
isOverridden: boolean;
|
||||
|
||||
@HideField()
|
||||
overrides?: PageLayoutWidgetOverrides | null;
|
||||
}
|
||||
|
||||
+8
-2
@@ -23,9 +23,15 @@ import { PageLayoutTabEntity } from 'src/engine/metadata-modules/page-layout-tab
|
||||
import { WidgetConfigurationType } from 'src/engine/metadata-modules/page-layout-widget/enums/widget-configuration-type.type';
|
||||
import { WidgetType } from 'src/engine/metadata-modules/page-layout-widget/enums/widget-type.enum';
|
||||
import { PageLayoutWidgetConfigurationTypeSettings } from 'src/engine/metadata-modules/page-layout-widget/types/page-layout-widget-configuration.type';
|
||||
import { SyncableEntity } from 'src/engine/workspace-manager/types/syncable-entity.interface';
|
||||
import { OverridableEntity } from 'src/engine/workspace-manager/types/overridable-entity';
|
||||
import { type JsonbProperty } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/jsonb-property.type';
|
||||
|
||||
export type PageLayoutWidgetOverrides = {
|
||||
title?: string;
|
||||
position?: PageLayoutWidgetPosition | null;
|
||||
conditionalDisplay?: PageLayoutWidgetConditionalDisplay | null;
|
||||
};
|
||||
|
||||
@Entity({ name: 'pageLayoutWidget', schema: 'core' })
|
||||
@ObjectType('PageLayoutWidget')
|
||||
@Index(
|
||||
@@ -38,7 +44,7 @@ export class PageLayoutWidgetEntity<
|
||||
TWidgetConfigurationType extends
|
||||
WidgetConfigurationType = WidgetConfigurationType,
|
||||
>
|
||||
extends SyncableEntity
|
||||
extends OverridableEntity<PageLayoutWidgetOverrides>
|
||||
implements Required<PageLayoutWidgetEntity>
|
||||
{
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
|
||||
+17
@@ -6,6 +6,7 @@ import {
|
||||
} from '@nestjs/common';
|
||||
import { Args, Mutation, Parent, Query, ResolveField } from '@nestjs/graphql';
|
||||
|
||||
import GraphQLJSON from 'graphql-type-json';
|
||||
import { PermissionFlagType } from 'twenty-shared/constants';
|
||||
|
||||
import { ResolverValidationPipe } from 'src/engine/core-modules/graphql/pipes/resolver-validation.pipe';
|
||||
@@ -21,6 +22,7 @@ import { PageLayoutWidgetDTO } from 'src/engine/metadata-modules/page-layout-wid
|
||||
import { WidgetConfiguration } from 'src/engine/metadata-modules/page-layout-widget/dtos/widget-configuration.interface';
|
||||
import { PageLayoutWidgetService } from 'src/engine/metadata-modules/page-layout-widget/services/page-layout-widget.service';
|
||||
import { PageLayoutGraphqlApiExceptionFilter } from 'src/engine/metadata-modules/page-layout/utils/page-layout-graphql-api-exception.filter';
|
||||
import { resolveOverridableEntityProperty } from 'src/engine/metadata-modules/utils/resolve-overridable-entity-property.util';
|
||||
import { WorkspaceMigrationGraphqlApiExceptionInterceptor } from 'src/engine/workspace-manager/workspace-migration/interceptors/workspace-migration-graphql-api-exception.interceptor';
|
||||
|
||||
@MetadataResolver(() => PageLayoutWidgetDTO)
|
||||
@@ -95,6 +97,21 @@ export class PageLayoutWidgetResolver {
|
||||
});
|
||||
}
|
||||
|
||||
@ResolveField(() => String)
|
||||
title(@Parent() widget: PageLayoutWidgetDTO): string {
|
||||
return resolveOverridableEntityProperty(widget, 'title');
|
||||
}
|
||||
|
||||
@ResolveField(() => GraphQLJSON, { nullable: true })
|
||||
position(@Parent() widget: PageLayoutWidgetDTO) {
|
||||
return resolveOverridableEntityProperty(widget, 'position');
|
||||
}
|
||||
|
||||
@ResolveField(() => GraphQLJSON, { nullable: true })
|
||||
conditionalDisplay(@Parent() widget: PageLayoutWidgetDTO) {
|
||||
return resolveOverridableEntityProperty(widget, 'conditionalDisplay');
|
||||
}
|
||||
|
||||
@ResolveField(() => WidgetConfiguration, { nullable: true })
|
||||
configuration(@Parent() widget: PageLayoutWidgetDTO) {
|
||||
return widget.configuration;
|
||||
|
||||
+28
-16
@@ -327,24 +327,32 @@ export class PageLayoutWidgetService {
|
||||
existingFlatPageLayoutWidgetMaps,
|
||||
);
|
||||
|
||||
const {
|
||||
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
|
||||
flatFieldMetadataMaps: existingFlatFieldMetadataMaps,
|
||||
flatFrontComponentMaps: existingFlatFrontComponentMaps,
|
||||
flatViewFieldGroupMaps: existingFlatViewFieldGroupMaps,
|
||||
flatViewMaps: existingFlatViewMaps,
|
||||
} = await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
const [
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: [
|
||||
'flatObjectMetadataMaps',
|
||||
'flatFieldMetadataMaps',
|
||||
'flatFrontComponentMaps',
|
||||
'flatViewFieldGroupMaps',
|
||||
'flatViewMaps',
|
||||
],
|
||||
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
|
||||
flatFieldMetadataMaps: existingFlatFieldMetadataMaps,
|
||||
flatFrontComponentMaps: existingFlatFrontComponentMaps,
|
||||
flatViewFieldGroupMaps: existingFlatViewFieldGroupMaps,
|
||||
flatViewMaps: existingFlatViewMaps,
|
||||
},
|
||||
);
|
||||
{ workspaceCustomFlatApplication },
|
||||
] = await Promise.all([
|
||||
this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: [
|
||||
'flatObjectMetadataMaps',
|
||||
'flatFieldMetadataMaps',
|
||||
'flatFrontComponentMaps',
|
||||
'flatViewFieldGroupMaps',
|
||||
'flatViewMaps',
|
||||
],
|
||||
},
|
||||
),
|
||||
this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{ workspaceId },
|
||||
),
|
||||
]);
|
||||
|
||||
const isConfigurationBeingUpdated = Object.prototype.hasOwnProperty.call(
|
||||
updateData,
|
||||
@@ -377,6 +385,10 @@ export class PageLayoutWidgetService {
|
||||
flatFrontComponentMaps: existingFlatFrontComponentMaps,
|
||||
flatViewFieldGroupMaps: existingFlatViewFieldGroupMaps,
|
||||
flatViewMaps: existingFlatViewMaps,
|
||||
callerApplicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
workspaceCustomApplicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
});
|
||||
|
||||
const shouldValidateChartFields =
|
||||
|
||||
+4
@@ -1,3 +1,5 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type FlatPageLayoutWidget } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget.type';
|
||||
import { type PageLayoutWidgetDTO } from 'src/engine/metadata-modules/page-layout-widget/dtos/page-layout-widget.dto';
|
||||
|
||||
@@ -9,6 +11,8 @@ export const fromFlatPageLayoutWidgetToPageLayoutWidgetDto = (
|
||||
|
||||
return {
|
||||
...rest,
|
||||
isOverridden:
|
||||
isDefined(rest.overrides) && Object.keys(rest.overrides).length > 0,
|
||||
objectMetadataId: objectMetadataId ?? undefined,
|
||||
createdAt: new Date(createdAt),
|
||||
updatedAt: new Date(updatedAt),
|
||||
|
||||
Reference in New Issue
Block a user