Migrate page layout widget to v2 of the API (#16323)

This commit is contained in:
Raphaël Bosi
2025-12-05 14:04:06 +01:00
committed by GitHub
parent 56e66315cd
commit 077be7644c
159 changed files with 1760 additions and 308 deletions
@@ -26,6 +26,7 @@ export const useMetadataErrorHandler = () => {
role: t`role`,
roleTarget: t`role target`,
agent: t`agent`,
pageLayoutWidget: t`page layout widget`,
pageLayoutTab: t`page layout tab`,
} as const satisfies Record<AllMetadataName, string>;
@@ -0,0 +1,61 @@
import { type MigrationInterface, type QueryRunner } from 'typeorm';
export class AddUniversalIdentifierAndApplicationIdToPageLayoutWidget1764858276847
implements MigrationInterface
{
name =
'AddUniversalIdentifierAndApplicationIdToPageLayoutWidget1764858276847';
public async up(queryRunner: QueryRunner): Promise<void> {
// Add columns as nullable first
await queryRunner.query(
`ALTER TABLE "core"."pageLayoutWidget" ADD "universalIdentifier" uuid`,
);
await queryRunner.query(
`ALTER TABLE "core"."pageLayoutWidget" ADD "applicationId" uuid`,
);
// Populate existing rows with universalIdentifier and applicationId
await queryRunner.query(
`UPDATE "core"."pageLayoutWidget"
SET "universalIdentifier" = gen_random_uuid(),
"applicationId" = (
SELECT "workspaceCustomApplicationId"
FROM "core"."workspace"
WHERE "workspace"."id" = "pageLayoutWidget"."workspaceId"
)
WHERE "universalIdentifier" IS NULL OR "applicationId" IS NULL`,
);
// Add NOT NULL constraints
await queryRunner.query(
`ALTER TABLE "core"."pageLayoutWidget" ALTER COLUMN "universalIdentifier" SET NOT NULL`,
);
await queryRunner.query(
`ALTER TABLE "core"."pageLayoutWidget" ALTER COLUMN "applicationId" SET NOT NULL`,
);
// Add unique index and foreign key
await queryRunner.query(
`CREATE UNIQUE INDEX "IDX_2a33a0e7e44c393ca7bb578dae" ON "core"."pageLayoutWidget" ("workspaceId", "universalIdentifier")`,
);
await queryRunner.query(
`ALTER TABLE "core"."pageLayoutWidget" ADD CONSTRAINT "FK_fb84d310b4cfe5916ced6fc3e2a" FOREIGN KEY ("applicationId") REFERENCES "core"."application"("id") ON DELETE CASCADE ON UPDATE NO ACTION`,
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "core"."pageLayoutWidget" DROP CONSTRAINT "FK_fb84d310b4cfe5916ced6fc3e2a"`,
);
await queryRunner.query(
`DROP INDEX "core"."IDX_2a33a0e7e44c393ca7bb578dae"`,
);
await queryRunner.query(
`ALTER TABLE "core"."pageLayoutWidget" DROP COLUMN "applicationId"`,
);
await queryRunner.query(
`ALTER TABLE "core"."pageLayoutWidget" DROP COLUMN "universalIdentifier"`,
);
}
}
@@ -37,7 +37,7 @@ import { MessageQueueModule } from 'src/engine/core-modules/message-queue/messag
import { messageQueueModuleFactory } from 'src/engine/core-modules/message-queue/message-queue.module-factory';
import { TimelineMessagingModule } from 'src/engine/core-modules/messaging/timeline-messaging.module';
import { OpenApiModule } from 'src/engine/core-modules/open-api/open-api.module';
import { PageLayoutModule } from 'src/engine/core-modules/page-layout/page-layout.module';
import { PageLayoutModule } from 'src/engine/metadata-modules/page-layout/page-layout.module';
import { PostgresCredentialsModule } from 'src/engine/core-modules/postgres-credentials/postgres-credentials.module';
import { PublicDomainModule } from 'src/engine/core-modules/public-domain/public-domain.module';
import { RedisClientModule } from 'src/engine/core-modules/redis-client/redis-client.module';
@@ -1,50 +0,0 @@
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module';
import { PageLayoutTabController } from 'src/engine/core-modules/page-layout/controllers/page-layout-tab.controller';
import { PageLayoutWidgetController } from 'src/engine/core-modules/page-layout/controllers/page-layout-widget.controller';
import { PageLayoutController } from 'src/engine/core-modules/page-layout/controllers/page-layout.controller';
import { PageLayoutTabEntity } from 'src/engine/core-modules/page-layout/entities/page-layout-tab.entity';
import { PageLayoutWidgetEntity } from 'src/engine/core-modules/page-layout/entities/page-layout-widget.entity';
import { PageLayoutEntity } from 'src/engine/core-modules/page-layout/entities/page-layout.entity';
import { PageLayoutTabResolver } from 'src/engine/core-modules/page-layout/resolvers/page-layout-tab.resolver';
import { PageLayoutWidgetResolver } from 'src/engine/core-modules/page-layout/resolvers/page-layout-widget.resolver';
import { PageLayoutResolver } from 'src/engine/core-modules/page-layout/resolvers/page-layout.resolver';
import { PageLayoutTabService } from 'src/engine/core-modules/page-layout/services/page-layout-tab.service';
import { PageLayoutUpdateService } from 'src/engine/core-modules/page-layout/services/page-layout-update.service';
import { PageLayoutWidgetService } from 'src/engine/core-modules/page-layout/services/page-layout-widget.service';
import { PageLayoutService } from 'src/engine/core-modules/page-layout/services/page-layout.service';
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
import { PermissionsModule } from 'src/engine/metadata-modules/permissions/permissions.module';
import { TwentyORMModule } from 'src/engine/twenty-orm/twenty-orm.module';
@Module({
imports: [
TypeOrmModule.forFeature([
PageLayoutEntity,
PageLayoutTabEntity,
PageLayoutWidgetEntity,
WorkspaceEntity,
]),
TwentyORMModule,
PermissionsModule,
FeatureFlagModule,
],
controllers: [
PageLayoutController,
PageLayoutTabController,
PageLayoutWidgetController,
],
providers: [
PageLayoutService,
PageLayoutTabService,
PageLayoutWidgetService,
PageLayoutResolver,
PageLayoutTabResolver,
PageLayoutWidgetResolver,
PageLayoutUpdateService,
],
exports: [PageLayoutService, PageLayoutTabService, PageLayoutWidgetService],
})
export class PageLayoutModule {}
@@ -7,6 +7,7 @@ import { type MetadataFlatEntity } from 'src/engine/metadata-modules/flat-entity
import { FLAT_FIELD_METADATA_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-field-metadata/constants/flat-field-metadata-editable-properties.constant';
import { FLAT_OBJECT_METADATA_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-object-metadata/constants/flat-object-metadata-editable-properties.constant';
import { FLAT_PAGE_LAYOUT_TAB_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-page-layout-tab/constants/flat-page-layout-tab-editable-properties.constant';
import { FLAT_PAGE_LAYOUT_WIDGET_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-page-layout-widget/constants/flat-page-layout-widget-editable-properties.constant';
import { FLAT_ROLE_TARGET_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-role-target/constants/flat-role-target-editable-properties.constant';
import { FLAT_ROLE_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-role/constants/flat-role-editable-properties.constant';
import { FLAT_VIEW_FIELD_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-view-field/constants/flat-view-field-editable-properties.constant';
@@ -112,6 +113,13 @@ export const ALL_FLAT_ENTITY_PROPERTIES_TO_COMPARE_AND_STRINGIFY = {
'evaluationInputs',
],
},
pageLayoutWidget: {
propertiesToCompare: [
...FLAT_PAGE_LAYOUT_WIDGET_EDITABLE_PROPERTIES,
'deletedAt',
],
propertiesToStringify: ['gridPosition', 'configuration'],
},
pageLayoutTab: {
propertiesToCompare: [...FLAT_PAGE_LAYOUT_TAB_EDITABLE_PROPERTIES],
propertiesToStringify: [],
@@ -113,5 +113,6 @@ export const ALL_METADATA_RELATED_METADATA_BY_FOREIGN_KEY = {
},
},
agent: {},
pageLayoutWidget: {},
pageLayoutTab: {},
} as const satisfies MetadataNameAndRelations;
@@ -54,5 +54,6 @@ export const ALL_METADATA_REQUIRED_METADATA_FOR_VALIDATION = {
role: true,
},
agent: {},
pageLayoutWidget: {},
pageLayoutTab: {},
} as const satisfies MetadataRequiredForValidation;
@@ -1,11 +1,12 @@
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
import { WorkspaceFlatFieldMetadataMapCacheService } from 'src/engine/metadata-modules/flat-field-metadata/services/workspace-flat-field-metadata-map-cache.service';
import { WorkspaceFlatIndexMapCacheService } from 'src/engine/metadata-modules/flat-index-metadata/services/workspace-flat-index-map-cache.service';
import { WorkspaceFlatObjectMetadataMapCacheService } from 'src/engine/metadata-modules/flat-object-metadata/services/workspace-flat-object-metadata-map-cache.service';
import { WorkspaceFlatPageLayoutWidgetMapCacheService } from 'src/engine/metadata-modules/flat-page-layout-widget/services/workspace-flat-page-layout-widget-map-cache.service';
import { WorkspaceFlatViewFieldMapCacheService } from 'src/engine/metadata-modules/flat-view-field/services/workspace-flat-view-field-map-cache.service';
import { WorkspaceFlatViewFilterMapCacheService } from 'src/engine/metadata-modules/flat-view-filter/services/workspace-flat-view-filter-map-cache.service';
import { WorkspaceFlatViewGroupMapCacheService } from 'src/engine/metadata-modules/flat-view-group/services/workspace-flat-view-group-map-cache.service';
@@ -13,6 +14,7 @@ import { WorkspaceFlatViewMapCacheService } from 'src/engine/metadata-modules/fl
import { IndexFieldMetadataEntity } from 'src/engine/metadata-modules/index-metadata/index-field-metadata.entity';
import { IndexMetadataEntity } from 'src/engine/metadata-modules/index-metadata/index-metadata.entity';
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { PageLayoutWidgetEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout-widget.entity';
import { ViewFieldEntity } from 'src/engine/metadata-modules/view-field/entities/view-field.entity';
import { ViewFilterEntity } from 'src/engine/metadata-modules/view-filter/entities/view-filter.entity';
import { ViewGroupEntity } from 'src/engine/metadata-modules/view-group/entities/view-group.entity';
@@ -31,6 +33,7 @@ import { WorkspaceCacheModule } from 'src/engine/workspace-cache/workspace-cache
IndexFieldMetadataEntity,
FieldMetadataEntity,
ObjectMetadataEntity,
PageLayoutWidgetEntity,
]),
],
providers: [
@@ -42,6 +45,7 @@ import { WorkspaceCacheModule } from 'src/engine/workspace-cache/workspace-cache
WorkspaceFlatIndexMapCacheService,
WorkspaceFlatFieldMetadataMapCacheService,
WorkspaceFlatViewGroupMapCacheService,
WorkspaceFlatPageLayoutWidgetMapCacheService,
],
exports: [
WorkspaceManyOrAllFlatEntityMapsCacheService,
@@ -52,6 +56,7 @@ import { WorkspaceCacheModule } from 'src/engine/workspace-cache/workspace-cache
WorkspaceFlatIndexMapCacheService,
WorkspaceFlatFieldMetadataMapCacheService,
WorkspaceFlatViewGroupMapCacheService,
WorkspaceFlatPageLayoutWidgetMapCacheService,
],
})
export class WorkspaceManyOrAllFlatEntityMapsCacheModule {}
@@ -1,4 +1,3 @@
import { type PageLayoutTabEntity } from 'src/engine/core-modules/page-layout/entities/page-layout-tab.entity';
import { type AgentEntity } from 'src/engine/metadata-modules/ai/ai-agent/entities/agent.entity';
import { type CronTriggerEntity } from 'src/engine/metadata-modules/cron-trigger/entities/cron-trigger.entity';
import { type FlatCronTrigger } from 'src/engine/metadata-modules/cron-trigger/types/flat-cron-trigger.type';
@@ -10,6 +9,7 @@ import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-m
import { type FlatIndexMetadata } from 'src/engine/metadata-modules/flat-index-metadata/types/flat-index-metadata.type';
import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type';
import { type FlatPageLayoutTab } from 'src/engine/metadata-modules/flat-page-layout-tab/types/flat-page-layout-tab.type';
import { type FlatPageLayoutWidget } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget.type';
import { type FlatRoleTarget } from 'src/engine/metadata-modules/flat-role-target/types/flat-role-target.type';
import { type FlatRole } from 'src/engine/metadata-modules/flat-role/types/flat-role.type';
import { type FlatViewField } from 'src/engine/metadata-modules/flat-view-field/types/flat-view-field.type';
@@ -18,6 +18,8 @@ import { type FlatViewGroup } from 'src/engine/metadata-modules/flat-view-group/
import { type FlatView } from 'src/engine/metadata-modules/flat-view/types/flat-view.type';
import { type IndexMetadataEntity } from 'src/engine/metadata-modules/index-metadata/index-metadata.entity';
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { type PageLayoutTabEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout-tab.entity';
import { type PageLayoutWidgetEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout-widget.entity';
import { type RoleTargetEntity } from 'src/engine/metadata-modules/role-target/role-target.entity';
import { type RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
import { type RouteTriggerEntity } from 'src/engine/metadata-modules/route-trigger/route-trigger.entity';
@@ -33,11 +35,6 @@ import {
type DeleteAgentAction,
type UpdateAgentAction,
} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/agent/types/workspace-migration-v2-agent-action-builder.service';
import {
type CreatePageLayoutTabAction,
type DeletePageLayoutTabAction,
type UpdatePageLayoutTabAction,
} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/page-layout-tab/types/workspace-migration-page-layout-tab-action-v2.type';
import {
type CreateCronTriggerAction,
type DeleteCronTriggerAction,
@@ -62,6 +59,16 @@ import {
type DeleteObjectAction,
type UpdateObjectAction,
} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/object/types/workspace-migration-object-action-v2';
import {
type CreatePageLayoutTabAction,
type DeletePageLayoutTabAction,
type UpdatePageLayoutTabAction,
} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/page-layout-tab/types/workspace-migration-page-layout-tab-action-v2.type';
import {
type CreatePageLayoutWidgetAction,
type DeletePageLayoutWidgetAction,
type UpdatePageLayoutWidgetAction,
} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/page-layout-widget/types/workspace-migration-page-layout-widget-action-v2.type';
import {
type CreateRoleTargetAction,
type DeleteRoleTargetAction,
@@ -230,6 +237,15 @@ export type AllFlatEntityTypesByMetadataName = {
flatEntity: FlatAgent;
entity: AgentEntity;
};
pageLayoutWidget: {
actions: {
created: CreatePageLayoutWidgetAction;
updated: UpdatePageLayoutWidgetAction;
deleted: DeletePageLayoutWidgetAction;
};
flatEntity: FlatPageLayoutWidget;
entity: PageLayoutWidgetEntity;
};
pageLayoutTab: {
actions: {
created: CreatePageLayoutTabAction;
@@ -1,9 +1,9 @@
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { PageLayoutTabEntity } from 'src/engine/core-modules/page-layout/entities/page-layout-tab.entity';
import { WorkspaceFlatPageLayoutTabMapCacheService } from 'src/engine/metadata-modules/flat-page-layout-tab/services/workspace-flat-page-layout-tab-map-cache.service';
import { WorkspaceManyOrAllFlatEntityMapsCacheModule } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.module';
import { WorkspaceFlatPageLayoutTabMapCacheService } from 'src/engine/metadata-modules/flat-page-layout-tab/services/workspace-flat-page-layout-tab-map-cache.service';
import { PageLayoutTabEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout-tab.entity';
@Module({
imports: [
@@ -5,10 +5,10 @@ import { Repository } from 'typeorm';
import { WorkspaceCacheProvider } from 'src/engine/workspace-cache/interfaces/workspace-cache-provider.service';
import { PageLayoutTabEntity } from 'src/engine/core-modules/page-layout/entities/page-layout-tab.entity';
import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/constant/create-empty-flat-entity-maps.constant';
import { type FlatPageLayoutTabMaps } from 'src/engine/metadata-modules/flat-page-layout-tab/types/flat-page-layout-tab-maps.type';
import { transformPageLayoutTabEntityToFlatPageLayoutTab } from 'src/engine/metadata-modules/flat-page-layout-tab/utils/transform-page-layout-tab-entity-to-flat-page-layout-tab.util';
import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/constant/create-empty-flat-entity-maps.constant';
import { PageLayoutTabEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout-tab.entity';
import { WorkspaceCache } from 'src/engine/workspace-cache/decorators/workspace-cache.decorator';
import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration-v2/utils/add-flat-entity-to-flat-entity-maps-through-mutation-or-throw.util';
@@ -1,5 +1,5 @@
import { type PageLayoutTabEntity } from 'src/engine/core-modules/page-layout/entities/page-layout-tab.entity';
import { type FlatEntityFrom } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';
import { type PageLayoutTabEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout-tab.entity';
export const pageLayoutTabEntityRelationProperties = [
'workspace',
@@ -1,5 +1,5 @@
import { type PageLayoutTabEntity } from 'src/engine/core-modules/page-layout/entities/page-layout-tab.entity';
import { type FlatPageLayoutTab } from 'src/engine/metadata-modules/flat-page-layout-tab/types/flat-page-layout-tab.type';
import { type PageLayoutTabEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout-tab.entity';
export const transformPageLayoutTabEntityToFlatPageLayoutTab = (
pageLayoutTabEntity: PageLayoutTabEntity,
@@ -0,0 +1,9 @@
import { type FlatPageLayoutWidget } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget.type';
export const FLAT_PAGE_LAYOUT_WIDGET_EDITABLE_PROPERTIES = [
'title',
'type',
'objectMetadataId',
'gridPosition',
'configuration',
] as const satisfies (keyof FlatPageLayoutWidget)[];
@@ -0,0 +1,8 @@
import { type PageLayoutWidgetEntityRelationProperties } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget.type';
export const PAGE_LAYOUT_WIDGET_ENTITY_RELATION_PROPERTIES = [
'workspace',
'pageLayoutTab',
'objectMetadata',
'application',
] as const satisfies PageLayoutWidgetEntityRelationProperties[];
@@ -0,0 +1,12 @@
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { WorkspaceFlatPageLayoutWidgetMapCacheService } from 'src/engine/metadata-modules/flat-page-layout-widget/services/workspace-flat-page-layout-widget-map-cache.service';
import { PageLayoutWidgetEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout-widget.entity';
@Module({
imports: [TypeOrmModule.forFeature([PageLayoutWidgetEntity])],
providers: [WorkspaceFlatPageLayoutWidgetMapCacheService],
exports: [WorkspaceFlatPageLayoutWidgetMapCacheService],
})
export class FlatPageLayoutWidgetModule {}
@@ -0,0 +1,52 @@
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { WorkspaceCacheProvider } from 'src/engine/workspace-cache/interfaces/workspace-cache-provider.service';
import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/constant/create-empty-flat-entity-maps.constant';
import { FlatPageLayoutWidgetMaps } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget-maps.type';
import { fromPageLayoutWidgetEntityToFlatPageLayoutWidget } from 'src/engine/metadata-modules/flat-page-layout-widget/utils/from-page-layout-widget-entity-to-flat-page-layout-widget.util';
import { PageLayoutWidgetEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout-widget.entity';
import { WorkspaceCache } from 'src/engine/workspace-cache/decorators/workspace-cache.decorator';
import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration-v2/utils/add-flat-entity-to-flat-entity-maps-through-mutation-or-throw.util';
@Injectable()
@WorkspaceCache('flatPageLayoutWidgetMaps')
export class WorkspaceFlatPageLayoutWidgetMapCacheService extends WorkspaceCacheProvider<FlatPageLayoutWidgetMaps> {
constructor(
@InjectRepository(PageLayoutWidgetEntity)
private readonly pageLayoutWidgetRepository: Repository<PageLayoutWidgetEntity>,
) {
super();
}
async computeForCache(
workspaceId: string,
): Promise<FlatPageLayoutWidgetMaps> {
const existingPageLayoutWidgets =
await this.pageLayoutWidgetRepository.find({
where: {
workspaceId,
},
withDeleted: true,
});
const flatPageLayoutWidgetMaps = createEmptyFlatEntityMaps();
for (const pageLayoutWidgetEntity of existingPageLayoutWidgets) {
const flatPageLayoutWidget =
fromPageLayoutWidgetEntityToFlatPageLayoutWidget(
pageLayoutWidgetEntity,
);
addFlatEntityToFlatEntityMapsThroughMutationOrThrow({
flatEntity: flatPageLayoutWidget,
flatEntityMapsToMutate: flatPageLayoutWidgetMaps,
});
}
return flatPageLayoutWidgetMaps;
}
}
@@ -0,0 +1,4 @@
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
import { type FlatPageLayoutWidget } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget.type';
export type FlatPageLayoutWidgetMaps = FlatEntityMaps<FlatPageLayoutWidget>;
@@ -0,0 +1,21 @@
import { type ApplicationEntity } from 'src/engine/core-modules/application/application.entity';
import { type WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
import { type FlatEntityFrom } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { type PageLayoutTabEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout-tab.entity';
import { type PageLayoutWidgetEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout-widget.entity';
import { type ExtractRecordTypeOrmRelationProperties } from 'src/engine/workspace-manager/workspace-migration-v2/types/extract-record-typeorm-relation-properties.type';
export type PageLayoutWidgetEntityRelationProperties =
ExtractRecordTypeOrmRelationProperties<
PageLayoutWidgetEntity,
| PageLayoutTabEntity
| ObjectMetadataEntity
| WorkspaceEntity
| ApplicationEntity
>;
export type FlatPageLayoutWidget = FlatEntityFrom<
PageLayoutWidgetEntity,
PageLayoutWidgetEntityRelationProperties
>;
@@ -0,0 +1,44 @@
import { trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties } from 'twenty-shared/utils';
import { v4 } from 'uuid';
import { type FlatPageLayoutWidget } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget.type';
import { type CreatePageLayoutWidgetInput } from 'src/engine/metadata-modules/page-layout/dtos/inputs/create-page-layout-widget.input';
import { WidgetType } from 'src/engine/metadata-modules/page-layout/enums/widget-type.enum';
export type FromCreatePageLayoutWidgetInputToFlatPageLayoutWidgetToCreateArgs =
{
createPageLayoutWidgetInput: CreatePageLayoutWidgetInput;
workspaceId: string;
workspaceCustomApplicationId: string;
};
export const fromCreatePageLayoutWidgetInputToFlatPageLayoutWidgetToCreate = ({
createPageLayoutWidgetInput: rawCreatePageLayoutWidgetInput,
workspaceId,
workspaceCustomApplicationId,
}: FromCreatePageLayoutWidgetInputToFlatPageLayoutWidgetToCreateArgs): FlatPageLayoutWidget => {
const { pageLayoutTabId, ...createPageLayoutWidgetInput } =
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties(
rawCreatePageLayoutWidgetInput,
['pageLayoutTabId'],
);
const createdAt = new Date();
const pageLayoutWidgetId = v4();
return {
id: pageLayoutWidgetId,
pageLayoutTabId,
workspaceId,
createdAt,
updatedAt: createdAt,
deletedAt: null,
universalIdentifier: pageLayoutWidgetId,
title: createPageLayoutWidgetInput.title,
type: createPageLayoutWidgetInput.type ?? WidgetType.VIEW,
objectMetadataId: createPageLayoutWidgetInput.objectMetadataId ?? null,
gridPosition: createPageLayoutWidgetInput.gridPosition,
configuration: createPageLayoutWidgetInput.configuration ?? null,
applicationId: workspaceCustomApplicationId,
};
};
@@ -0,0 +1,41 @@
import { t } from '@lingui/core/macro';
import {
extractAndSanitizeObjectStringFields,
isDefined,
} from 'twenty-shared/utils';
import { type FlatPageLayoutWidgetMaps } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget-maps.type';
import { type FlatPageLayoutWidget } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget.type';
import { type DeletePageLayoutWidgetInput } from 'src/engine/metadata-modules/page-layout/dtos/inputs/delete-page-layout-widget.input';
import {
PageLayoutWidgetException,
PageLayoutWidgetExceptionCode,
} from 'src/engine/metadata-modules/page-layout/exceptions/page-layout-widget.exception';
export const fromDeletePageLayoutWidgetInputToFlatPageLayoutWidgetOrThrow = ({
deletePageLayoutWidgetInput: rawDeletePageLayoutWidgetInput,
flatPageLayoutWidgetMaps,
}: {
deletePageLayoutWidgetInput: DeletePageLayoutWidgetInput;
flatPageLayoutWidgetMaps: FlatPageLayoutWidgetMaps;
}): FlatPageLayoutWidget => {
const { id: pageLayoutWidgetId } = extractAndSanitizeObjectStringFields(
rawDeletePageLayoutWidgetInput,
['id'],
);
const existingFlatPageLayoutWidgetToDelete =
flatPageLayoutWidgetMaps.byId[pageLayoutWidgetId];
if (!isDefined(existingFlatPageLayoutWidgetToDelete)) {
throw new PageLayoutWidgetException(
t`Page layout widget to delete not found`,
PageLayoutWidgetExceptionCode.PAGE_LAYOUT_WIDGET_NOT_FOUND,
);
}
return {
...existingFlatPageLayoutWidgetToDelete,
deletedAt: new Date(),
};
};
@@ -0,0 +1,38 @@
import { t } from '@lingui/core/macro';
import {
extractAndSanitizeObjectStringFields,
isDefined,
} from 'twenty-shared/utils';
import { type FlatPageLayoutWidgetMaps } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget-maps.type';
import { type FlatPageLayoutWidget } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget.type';
import { type DestroyPageLayoutWidgetInput } from 'src/engine/metadata-modules/page-layout/dtos/inputs/destroy-page-layout-widget.input';
import {
PageLayoutWidgetException,
PageLayoutWidgetExceptionCode,
} from 'src/engine/metadata-modules/page-layout/exceptions/page-layout-widget.exception';
export const fromDestroyPageLayoutWidgetInputToFlatPageLayoutWidgetOrThrow = ({
destroyPageLayoutWidgetInput,
flatPageLayoutWidgetMaps,
}: {
destroyPageLayoutWidgetInput: DestroyPageLayoutWidgetInput;
flatPageLayoutWidgetMaps: FlatPageLayoutWidgetMaps;
}): FlatPageLayoutWidget => {
const { id: pageLayoutWidgetId } = extractAndSanitizeObjectStringFields(
destroyPageLayoutWidgetInput,
['id'],
);
const existingFlatPageLayoutWidgetToDestroy =
flatPageLayoutWidgetMaps.byId[pageLayoutWidgetId];
if (!isDefined(existingFlatPageLayoutWidgetToDestroy)) {
throw new PageLayoutWidgetException(
t`Page layout widget to destroy not found`,
PageLayoutWidgetExceptionCode.PAGE_LAYOUT_WIDGET_NOT_FOUND,
);
}
return existingFlatPageLayoutWidgetToDestroy;
};
@@ -0,0 +1,22 @@
import { removePropertiesFromRecord } from 'twenty-shared/utils';
import { PAGE_LAYOUT_WIDGET_ENTITY_RELATION_PROPERTIES } from 'src/engine/metadata-modules/flat-page-layout-widget/constants/page-layout-widget-entity-relation-properties.constant';
import { type FlatPageLayoutWidget } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget.type';
import { type PageLayoutWidgetEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout-widget.entity';
export const fromPageLayoutWidgetEntityToFlatPageLayoutWidget = (
pageLayoutWidgetEntity: PageLayoutWidgetEntity,
): FlatPageLayoutWidget => {
const pageLayoutWidgetEntityWithoutRelations = removePropertiesFromRecord(
pageLayoutWidgetEntity,
PAGE_LAYOUT_WIDGET_ENTITY_RELATION_PROPERTIES,
);
return {
...pageLayoutWidgetEntityWithoutRelations,
universalIdentifier:
pageLayoutWidgetEntityWithoutRelations.universalIdentifier ??
pageLayoutWidgetEntityWithoutRelations.id,
applicationId: pageLayoutWidgetEntityWithoutRelations.applicationId ?? null,
};
};
@@ -0,0 +1,55 @@
import { t } from '@lingui/core/macro';
import {
extractAndSanitizeObjectStringFields,
isDefined,
} from 'twenty-shared/utils';
import { FLAT_PAGE_LAYOUT_WIDGET_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-page-layout-widget/constants/flat-page-layout-widget-editable-properties.constant';
import { type FlatPageLayoutWidgetMaps } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget-maps.type';
import { type FlatPageLayoutWidget } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget.type';
import { type UpdatePageLayoutWidgetInput } from 'src/engine/metadata-modules/page-layout/dtos/inputs/update-page-layout-widget.input';
import {
PageLayoutWidgetException,
PageLayoutWidgetExceptionCode,
} from 'src/engine/metadata-modules/page-layout/exceptions/page-layout-widget.exception';
import { mergeUpdateInExistingRecord } from 'src/utils/merge-update-in-existing-record.util';
export type UpdatePageLayoutWidgetInputWithId = {
id: string;
update: UpdatePageLayoutWidgetInput;
};
export const fromUpdatePageLayoutWidgetInputToFlatPageLayoutWidgetToUpdateOrThrow =
({
updatePageLayoutWidgetInput: rawUpdatePageLayoutWidgetInput,
flatPageLayoutWidgetMaps,
}: {
updatePageLayoutWidgetInput: UpdatePageLayoutWidgetInputWithId;
flatPageLayoutWidgetMaps: FlatPageLayoutWidgetMaps;
}): FlatPageLayoutWidget => {
const { id: pageLayoutWidgetToUpdateId } =
extractAndSanitizeObjectStringFields(rawUpdatePageLayoutWidgetInput, [
'id',
]);
const existingFlatPageLayoutWidgetToUpdate =
flatPageLayoutWidgetMaps.byId[pageLayoutWidgetToUpdateId];
if (!isDefined(existingFlatPageLayoutWidgetToUpdate)) {
throw new PageLayoutWidgetException(
t`Page layout widget to update not found`,
PageLayoutWidgetExceptionCode.PAGE_LAYOUT_WIDGET_NOT_FOUND,
);
}
const updatedEditableFieldProperties = extractAndSanitizeObjectStringFields(
rawUpdatePageLayoutWidgetInput.update,
FLAT_PAGE_LAYOUT_WIDGET_EDITABLE_PROPERTIES,
);
return mergeUpdateInExistingRecord({
existing: existingFlatPageLayoutWidgetToUpdate,
properties: FLAT_PAGE_LAYOUT_WIDGET_EDITABLE_PROPERTIES,
update: updatedEditableFieldProperties,
});
};
@@ -13,17 +13,17 @@ import {
import { isDefined } from 'twenty-shared/utils';
import { CreatePageLayoutTabInput } from 'src/engine/core-modules/page-layout/dtos/inputs/create-page-layout-tab.input';
import { UpdatePageLayoutTabInput } from 'src/engine/core-modules/page-layout/dtos/inputs/update-page-layout-tab.input';
import { type PageLayoutTabDTO } from 'src/engine/core-modules/page-layout/dtos/page-layout-tab.dto';
import { CreatePageLayoutTabInput } from 'src/engine/metadata-modules/page-layout/dtos/inputs/create-page-layout-tab.input';
import { UpdatePageLayoutTabInput } from 'src/engine/metadata-modules/page-layout/dtos/inputs/update-page-layout-tab.input';
import { type PageLayoutTabDTO } from 'src/engine/metadata-modules/page-layout/dtos/page-layout-tab.dto';
import {
generatePageLayoutTabExceptionMessage,
PageLayoutTabException,
PageLayoutTabExceptionCode,
PageLayoutTabExceptionMessageKey,
} from 'src/engine/core-modules/page-layout/exceptions/page-layout-tab.exception';
import { PageLayoutTabRestApiExceptionFilter } from 'src/engine/core-modules/page-layout/filters/page-layout-tab-rest-api-exception.filter';
import { PageLayoutTabService } from 'src/engine/core-modules/page-layout/services/page-layout-tab.service';
} from 'src/engine/metadata-modules/page-layout/exceptions/page-layout-tab.exception';
import { PageLayoutTabRestApiExceptionFilter } from 'src/engine/metadata-modules/page-layout/filters/page-layout-tab-rest-api-exception.filter';
import { PageLayoutTabService } from 'src/engine/metadata-modules/page-layout/services/page-layout-tab.service';
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
import { NoPermissionGuard } from 'src/engine/guards/no-permission.guard';
@@ -13,22 +13,22 @@ import {
import { isDefined } from 'class-validator';
import { CreatePageLayoutWidgetInput } from 'src/engine/core-modules/page-layout/dtos/inputs/create-page-layout-widget.input';
import { UpdatePageLayoutWidgetInput } from 'src/engine/core-modules/page-layout/dtos/inputs/update-page-layout-widget.input';
import { type PageLayoutWidgetDTO } from 'src/engine/core-modules/page-layout/dtos/page-layout-widget.dto';
import {
generatePageLayoutWidgetExceptionMessage,
PageLayoutWidgetException,
PageLayoutWidgetExceptionCode,
PageLayoutWidgetExceptionMessageKey,
} from 'src/engine/core-modules/page-layout/exceptions/page-layout-widget.exception';
import { PageLayoutWidgetRestApiExceptionFilter } from 'src/engine/core-modules/page-layout/filters/page-layout-widget-rest-api-exception.filter';
import { PageLayoutWidgetService } from 'src/engine/core-modules/page-layout/services/page-layout-widget.service';
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
import { NoPermissionGuard } from 'src/engine/guards/no-permission.guard';
import { SettingsPermissionGuard } from 'src/engine/guards/settings-permission.guard';
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
import { CreatePageLayoutWidgetInput } from 'src/engine/metadata-modules/page-layout/dtos/inputs/create-page-layout-widget.input';
import { UpdatePageLayoutWidgetInput } from 'src/engine/metadata-modules/page-layout/dtos/inputs/update-page-layout-widget.input';
import { type PageLayoutWidgetDTO } from 'src/engine/metadata-modules/page-layout/dtos/page-layout-widget.dto';
import {
generatePageLayoutWidgetExceptionMessage,
PageLayoutWidgetException,
PageLayoutWidgetExceptionCode,
PageLayoutWidgetExceptionMessageKey,
} from 'src/engine/metadata-modules/page-layout/exceptions/page-layout-widget.exception';
import { PageLayoutWidgetRestApiExceptionFilter } from 'src/engine/metadata-modules/page-layout/filters/page-layout-widget-rest-api-exception.filter';
import { PageLayoutWidgetService } from 'src/engine/metadata-modules/page-layout/services/page-layout-widget.service';
import { PermissionFlagType } from 'src/engine/metadata-modules/permissions/constants/permission-flag-type.constants';
@Controller('rest/metadata/pageLayoutWidgets')
@@ -13,12 +13,12 @@ import {
import { isDefined } from 'twenty-shared/utils';
import { CreatePageLayoutInput } from 'src/engine/core-modules/page-layout/dtos/inputs/create-page-layout.input';
import { UpdatePageLayoutInput } from 'src/engine/core-modules/page-layout/dtos/inputs/update-page-layout.input';
import { type PageLayoutDTO } from 'src/engine/core-modules/page-layout/dtos/page-layout.dto';
import { PageLayoutEntity } from 'src/engine/core-modules/page-layout/entities/page-layout.entity';
import { PageLayoutRestApiExceptionFilter } from 'src/engine/core-modules/page-layout/filters/page-layout-rest-api-exception.filter';
import { PageLayoutService } from 'src/engine/core-modules/page-layout/services/page-layout.service';
import { CreatePageLayoutInput } from 'src/engine/metadata-modules/page-layout/dtos/inputs/create-page-layout.input';
import { UpdatePageLayoutInput } from 'src/engine/metadata-modules/page-layout/dtos/inputs/update-page-layout.input';
import { type PageLayoutDTO } from 'src/engine/metadata-modules/page-layout/dtos/page-layout.dto';
import { PageLayoutEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout.entity';
import { PageLayoutRestApiExceptionFilter } from 'src/engine/metadata-modules/page-layout/filters/page-layout-rest-api-exception.filter';
import { PageLayoutService } from 'src/engine/metadata-modules/page-layout/services/page-layout.service';
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
import { NoPermissionGuard } from 'src/engine/guards/no-permission.guard';
@@ -19,7 +19,7 @@ import { ObjectRecordFilter } from 'src/engine/api/graphql/workspace-query-build
import { AggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/aggregate-operations.constant';
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
import { GraphType } from 'src/engine/core-modules/page-layout/enums/graph-type.enum';
import { GraphType } from 'src/engine/metadata-modules/page-layout/enums/graph-type.enum';
@ObjectType('AggregateChartConfiguration')
export class AggregateChartConfigurationDTO {
@@ -21,11 +21,11 @@ import { ObjectRecordFilter } from 'src/engine/api/graphql/workspace-query-build
import { AggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/aggregate-operations.constant';
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
import { AxisNameDisplay } from 'src/engine/core-modules/page-layout/enums/axis-name-display.enum';
import { BarChartGroupMode } from 'src/engine/core-modules/page-layout/enums/bar-chart-group-mode.enum';
import { ObjectRecordGroupByDateGranularity } from 'src/engine/core-modules/page-layout/enums/date-granularity.enum';
import { GraphOrderBy } from 'src/engine/core-modules/page-layout/enums/graph-order-by.enum';
import { GraphType } from 'src/engine/core-modules/page-layout/enums/graph-type.enum';
import { AxisNameDisplay } from 'src/engine/metadata-modules/page-layout/enums/axis-name-display.enum';
import { BarChartGroupMode } from 'src/engine/metadata-modules/page-layout/enums/bar-chart-group-mode.enum';
import { ObjectRecordGroupByDateGranularity } from 'src/engine/metadata-modules/page-layout/enums/date-granularity.enum';
import { GraphOrderBy } from 'src/engine/metadata-modules/page-layout/enums/graph-order-by.enum';
import { GraphType } from 'src/engine/metadata-modules/page-layout/enums/graph-type.enum';
@ObjectType('BarChartConfiguration')
export class BarChartConfigurationDTO {
@@ -19,7 +19,7 @@ import { ObjectRecordFilter } from 'src/engine/api/graphql/workspace-query-build
import { AggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/aggregate-operations.constant';
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
import { GraphType } from 'src/engine/core-modules/page-layout/enums/graph-type.enum';
import { GraphType } from 'src/engine/metadata-modules/page-layout/enums/graph-type.enum';
@ObjectType('GaugeChartConfiguration')
export class GaugeChartConfigurationDTO {
@@ -13,8 +13,8 @@ import {
import { GraphQLJSON } from 'graphql-type-json';
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
import { GridPositionInput } from 'src/engine/core-modules/page-layout/dtos/inputs/grid-position.input';
import { WidgetType } from 'src/engine/core-modules/page-layout/enums/widget-type.enum';
import { GridPositionInput } from 'src/engine/metadata-modules/page-layout/dtos/inputs/grid-position.input';
import { WidgetType } from 'src/engine/metadata-modules/page-layout/enums/widget-type.enum';
@InputType()
export class CreatePageLayoutWidgetInput {
@@ -9,7 +9,7 @@ import {
} from 'class-validator';
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
import { PageLayoutType } from 'src/engine/core-modules/page-layout/enums/page-layout-type.enum';
import { PageLayoutType } from 'src/engine/metadata-modules/page-layout/enums/page-layout-type.enum';
@InputType()
export class CreatePageLayoutInput {
@@ -0,0 +1,13 @@
import { Field, InputType } from '@nestjs/graphql';
import { IsNotEmpty, IsUUID } from 'class-validator';
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
@InputType()
export class DeletePageLayoutWidgetInput {
@Field(() => UUIDScalarType)
@IsUUID()
@IsNotEmpty()
id: string;
}
@@ -0,0 +1,13 @@
import { Field, InputType } from '@nestjs/graphql';
import { IsNotEmpty, IsUUID } from 'class-validator';
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
@InputType()
export class DestroyPageLayoutWidgetInput {
@Field(() => UUIDScalarType)
@IsUUID()
@IsNotEmpty()
id: string;
}
@@ -2,7 +2,7 @@ import { Field, InputType } from '@nestjs/graphql';
import { IsInt, IsNotEmpty, Min } from 'class-validator';
import { GridPosition } from 'src/engine/core-modules/page-layout/types/grid-position.type';
import { GridPosition } from 'src/engine/metadata-modules/page-layout/types/grid-position.type';
@InputType('GridPositionInput')
export class GridPositionInput implements GridPosition {
@@ -11,7 +11,7 @@ import {
} from 'class-validator';
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
import { UpdatePageLayoutWidgetWithIdInput } from 'src/engine/core-modules/page-layout/dtos/inputs/update-page-layout-widget-with-id.input';
import { UpdatePageLayoutWidgetWithIdInput } from 'src/engine/metadata-modules/page-layout/dtos/inputs/update-page-layout-widget-with-id.input';
@InputType()
export class UpdatePageLayoutTabWithWidgetsInput {
@@ -13,8 +13,8 @@ import {
import { GraphQLJSON } from 'graphql-type-json';
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
import { GridPositionInput } from 'src/engine/core-modules/page-layout/dtos/inputs/grid-position.input';
import { WidgetType } from 'src/engine/core-modules/page-layout/enums/widget-type.enum';
import { GridPositionInput } from 'src/engine/metadata-modules/page-layout/dtos/inputs/grid-position.input';
import { WidgetType } from 'src/engine/metadata-modules/page-layout/enums/widget-type.enum';
@InputType()
export class UpdatePageLayoutWidgetWithIdInput {
@@ -12,8 +12,8 @@ import {
import { GraphQLJSON } from 'graphql-type-json';
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
import { GridPositionInput } from 'src/engine/core-modules/page-layout/dtos/inputs/grid-position.input';
import { WidgetType } from 'src/engine/core-modules/page-layout/enums/widget-type.enum';
import { GridPositionInput } from 'src/engine/metadata-modules/page-layout/dtos/inputs/grid-position.input';
import { WidgetType } from 'src/engine/metadata-modules/page-layout/enums/widget-type.enum';
@InputType()
export class UpdatePageLayoutWidgetInput {
@@ -13,8 +13,8 @@ import {
} from 'class-validator';
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
import { UpdatePageLayoutTabWithWidgetsInput } from 'src/engine/core-modules/page-layout/dtos/inputs/update-page-layout-tab-with-widgets.input';
import { PageLayoutType } from 'src/engine/core-modules/page-layout/enums/page-layout-type.enum';
import { UpdatePageLayoutTabWithWidgetsInput } from 'src/engine/metadata-modules/page-layout/dtos/inputs/update-page-layout-tab-with-widgets.input';
import { PageLayoutType } from 'src/engine/metadata-modules/page-layout/enums/page-layout-type.enum';
@InputType()
export class UpdatePageLayoutWithTabsInput {
@@ -3,7 +3,7 @@ import { Field, InputType } from '@nestjs/graphql';
import { IsEnum, IsOptional, IsString, IsUUID } from 'class-validator';
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
import { PageLayoutType } from 'src/engine/core-modules/page-layout/enums/page-layout-type.enum';
import { PageLayoutType } from 'src/engine/metadata-modules/page-layout/enums/page-layout-type.enum';
@InputType()
export class UpdatePageLayoutInput {
@@ -20,10 +20,10 @@ import { ObjectRecordFilter } from 'src/engine/api/graphql/workspace-query-build
import { AggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/aggregate-operations.constant';
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
import { AxisNameDisplay } from 'src/engine/core-modules/page-layout/enums/axis-name-display.enum';
import { ObjectRecordGroupByDateGranularity } from 'src/engine/core-modules/page-layout/enums/date-granularity.enum';
import { GraphOrderBy } from 'src/engine/core-modules/page-layout/enums/graph-order-by.enum';
import { GraphType } from 'src/engine/core-modules/page-layout/enums/graph-type.enum';
import { AxisNameDisplay } from 'src/engine/metadata-modules/page-layout/enums/axis-name-display.enum';
import { ObjectRecordGroupByDateGranularity } from 'src/engine/metadata-modules/page-layout/enums/date-granularity.enum';
import { GraphOrderBy } from 'src/engine/metadata-modules/page-layout/enums/graph-order-by.enum';
import { GraphType } from 'src/engine/metadata-modules/page-layout/enums/graph-type.enum';
@ObjectType('LineChartConfiguration')
export class LineChartConfigurationDTO {
@@ -3,7 +3,7 @@ import { Field, Float, 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 { PageLayoutWidgetDTO } from 'src/engine/core-modules/page-layout/dtos/page-layout-widget.dto';
import { PageLayoutWidgetDTO } from 'src/engine/metadata-modules/page-layout/dtos/page-layout-widget.dto';
@ObjectType('PageLayoutTab')
export class PageLayoutTabDTO {
@@ -6,8 +6,8 @@ import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/
import {
WidgetConfiguration,
WidgetConfigurationInterface,
} from 'src/engine/core-modules/page-layout/dtos/widget-configuration.interface';
import { WidgetType } from 'src/engine/core-modules/page-layout/enums/widget-type.enum';
} from 'src/engine/metadata-modules/page-layout/dtos/widget-configuration.interface';
import { WidgetType } from 'src/engine/metadata-modules/page-layout/enums/widget-type.enum';
registerEnumType(WidgetType, { name: 'WidgetType' });
@@ -3,8 +3,8 @@ import { Field, ObjectType, registerEnumType } 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 { PageLayoutTabDTO } from 'src/engine/core-modules/page-layout/dtos/page-layout-tab.dto';
import { PageLayoutType } from 'src/engine/core-modules/page-layout/enums/page-layout-type.enum';
import { PageLayoutTabDTO } from 'src/engine/metadata-modules/page-layout/dtos/page-layout-tab.dto';
import { PageLayoutType } from 'src/engine/metadata-modules/page-layout/enums/page-layout-type.enum';
registerEnumType(PageLayoutType, { name: 'PageLayoutType' });
@@ -19,9 +19,9 @@ import { ObjectRecordFilter } from 'src/engine/api/graphql/workspace-query-build
import { AggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/aggregate-operations.constant';
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
import { ObjectRecordGroupByDateGranularity } from 'src/engine/core-modules/page-layout/enums/date-granularity.enum';
import { GraphOrderBy } from 'src/engine/core-modules/page-layout/enums/graph-order-by.enum';
import { GraphType } from 'src/engine/core-modules/page-layout/enums/graph-type.enum';
import { ObjectRecordGroupByDateGranularity } from 'src/engine/metadata-modules/page-layout/enums/date-granularity.enum';
import { GraphOrderBy } from 'src/engine/metadata-modules/page-layout/enums/graph-order-by.enum';
import { GraphType } from 'src/engine/metadata-modules/page-layout/enums/graph-type.enum';
@ObjectType('PieChartConfiguration')
export class PieChartConfigurationDTO {
@@ -3,7 +3,7 @@ import { Field, ObjectType } from '@nestjs/graphql';
import { Type } from 'class-transformer';
import { IsNotEmpty, ValidateNested } from 'class-validator';
import { RichTextV2BodyDTO } from 'src/engine/core-modules/page-layout/dtos/rich-text-v2-body.dto';
import { RichTextV2BodyDTO } from 'src/engine/metadata-modules/page-layout/dtos/rich-text-v2-body.dto';
@ObjectType('StandaloneRichTextConfiguration')
export class StandaloneRichTextConfigurationDTO {
@@ -1,14 +1,14 @@
import { createUnionType } from '@nestjs/graphql';
import { AggregateChartConfigurationDTO } from 'src/engine/core-modules/page-layout/dtos/aggregate-chart-configuration.dto';
import { BarChartConfigurationDTO } from 'src/engine/core-modules/page-layout/dtos/bar-chart-configuration.dto';
import { GaugeChartConfigurationDTO } from 'src/engine/core-modules/page-layout/dtos/gauge-chart-configuration.dto';
import { IframeConfigurationDTO } from 'src/engine/core-modules/page-layout/dtos/iframe-configuration.dto';
import { LineChartConfigurationDTO } from 'src/engine/core-modules/page-layout/dtos/line-chart-configuration.dto';
import { PieChartConfigurationDTO } from 'src/engine/core-modules/page-layout/dtos/pie-chart-configuration.dto';
import { StandaloneRichTextConfigurationDTO } from 'src/engine/core-modules/page-layout/dtos/standalone-rich-text-configuration.dto';
import { GraphType } from 'src/engine/core-modules/page-layout/enums/graph-type.enum';
import { WidgetConfigurationType } from 'src/engine/core-modules/page-layout/enums/widget-configuration-type.enum';
import { AggregateChartConfigurationDTO } from 'src/engine/metadata-modules/page-layout/dtos/aggregate-chart-configuration.dto';
import { BarChartConfigurationDTO } from 'src/engine/metadata-modules/page-layout/dtos/bar-chart-configuration.dto';
import { GaugeChartConfigurationDTO } from 'src/engine/metadata-modules/page-layout/dtos/gauge-chart-configuration.dto';
import { IframeConfigurationDTO } from 'src/engine/metadata-modules/page-layout/dtos/iframe-configuration.dto';
import { LineChartConfigurationDTO } from 'src/engine/metadata-modules/page-layout/dtos/line-chart-configuration.dto';
import { PieChartConfigurationDTO } from 'src/engine/metadata-modules/page-layout/dtos/pie-chart-configuration.dto';
import { StandaloneRichTextConfigurationDTO } from 'src/engine/metadata-modules/page-layout/dtos/standalone-rich-text-configuration.dto';
import { GraphType } from 'src/engine/metadata-modules/page-layout/enums/graph-type.enum';
import { WidgetConfigurationType } from 'src/engine/metadata-modules/page-layout/enums/widget-configuration-type.enum';
export const WidgetConfiguration = createUnionType({
name: 'WidgetConfiguration',
@@ -16,9 +16,9 @@ import {
import { StrictSyncableEntity } from 'src/engine/workspace-manager/workspace-sync/interfaces/strict-syncable-entity.interface';
import { PageLayoutWidgetEntity } from 'src/engine/core-modules/page-layout/entities/page-layout-widget.entity';
import { PageLayoutEntity } from 'src/engine/core-modules/page-layout/entities/page-layout.entity';
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
import { PageLayoutWidgetEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout-widget.entity';
import { PageLayoutEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout.entity';
@Entity({ name: 'pageLayoutTab', schema: 'core' })
@ObjectType('PageLayoutTab')
@@ -13,12 +13,14 @@ import {
UpdateDateColumn,
} from 'typeorm';
import { WidgetConfigurationInterface } from 'src/engine/core-modules/page-layout/dtos/widget-configuration.interface';
import { PageLayoutTabEntity } from 'src/engine/core-modules/page-layout/entities/page-layout-tab.entity';
import { WidgetType } from 'src/engine/core-modules/page-layout/enums/widget-type.enum';
import { GridPosition } from 'src/engine/core-modules/page-layout/types/grid-position.type';
import { StrictSyncableEntity } from 'src/engine/workspace-manager/workspace-sync/interfaces/strict-syncable-entity.interface';
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { WidgetConfigurationInterface } from 'src/engine/metadata-modules/page-layout/dtos/widget-configuration.interface';
import { PageLayoutTabEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout-tab.entity';
import { WidgetType } from 'src/engine/metadata-modules/page-layout/enums/widget-type.enum';
import { GridPosition } from 'src/engine/metadata-modules/page-layout/types/grid-position.type';
@Entity({ name: 'pageLayoutWidget', schema: 'core' })
@ObjectType('PageLayoutWidget')
@@ -28,6 +30,7 @@ import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadat
{ where: '"deletedAt" IS NULL' },
)
export class PageLayoutWidgetEntity
extends StrictSyncableEntity
implements Required<PageLayoutWidgetEntity>
{
@PrimaryGeneratedColumn('uuid')
@@ -14,8 +14,8 @@ import {
UpdateDateColumn,
} from 'typeorm';
import { PageLayoutTabEntity } from 'src/engine/core-modules/page-layout/entities/page-layout-tab.entity';
import { PageLayoutType } from 'src/engine/core-modules/page-layout/enums/page-layout-type.enum';
import { PageLayoutTabEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout-tab.entity';
import { PageLayoutType } from 'src/engine/metadata-modules/page-layout/enums/page-layout-type.enum';
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
@@ -10,7 +10,7 @@ import { HttpExceptionHandlerService } from 'src/engine/core-modules/exception-h
import {
PageLayoutException,
PageLayoutExceptionCode,
} from 'src/engine/core-modules/page-layout/exceptions/page-layout.exception';
} from 'src/engine/metadata-modules/page-layout/exceptions/page-layout.exception';
@Catch(PageLayoutException)
export class PageLayoutRestApiExceptionFilter implements ExceptionFilter {
@@ -10,7 +10,7 @@ import { HttpExceptionHandlerService } from 'src/engine/core-modules/exception-h
import {
PageLayoutTabException,
PageLayoutTabExceptionCode,
} from 'src/engine/core-modules/page-layout/exceptions/page-layout-tab.exception';
} from 'src/engine/metadata-modules/page-layout/exceptions/page-layout-tab.exception';
@Catch(PageLayoutTabException)
export class PageLayoutTabRestApiExceptionFilter implements ExceptionFilter {
@@ -10,7 +10,7 @@ import { HttpExceptionHandlerService } from 'src/engine/core-modules/exception-h
import {
PageLayoutWidgetException,
PageLayoutWidgetExceptionCode,
} from 'src/engine/core-modules/page-layout/exceptions/page-layout-widget.exception';
} from 'src/engine/metadata-modules/page-layout/exceptions/page-layout-widget.exception';
@Catch(PageLayoutWidgetException)
export class PageLayoutWidgetRestApiExceptionFilter implements ExceptionFilter {
@@ -0,0 +1,56 @@
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module';
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
import { WorkspaceManyOrAllFlatEntityMapsCacheModule } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.module';
import { PageLayoutTabController } from 'src/engine/metadata-modules/page-layout/controllers/page-layout-tab.controller';
import { PageLayoutWidgetController } from 'src/engine/metadata-modules/page-layout/controllers/page-layout-widget.controller';
import { PageLayoutController } from 'src/engine/metadata-modules/page-layout/controllers/page-layout.controller';
import { PageLayoutTabEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout-tab.entity';
import { PageLayoutWidgetEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout-widget.entity';
import { PageLayoutEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout.entity';
import { PageLayoutTabResolver } from 'src/engine/metadata-modules/page-layout/resolvers/page-layout-tab.resolver';
import { PageLayoutWidgetResolver } from 'src/engine/metadata-modules/page-layout/resolvers/page-layout-widget.resolver';
import { PageLayoutResolver } from 'src/engine/metadata-modules/page-layout/resolvers/page-layout.resolver';
import { PageLayoutTabService } from 'src/engine/metadata-modules/page-layout/services/page-layout-tab.service';
import { PageLayoutUpdateService } from 'src/engine/metadata-modules/page-layout/services/page-layout-update.service';
import { PageLayoutWidgetService } from 'src/engine/metadata-modules/page-layout/services/page-layout-widget.service';
import { PageLayoutService } from 'src/engine/metadata-modules/page-layout/services/page-layout.service';
import { PermissionsModule } from 'src/engine/metadata-modules/permissions/permissions.module';
import { TwentyORMModule } from 'src/engine/twenty-orm/twenty-orm.module';
import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/workspace-cache-storage.module';
import { WorkspaceMigrationV2Module } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-v2.module';
@Module({
imports: [
TypeOrmModule.forFeature([
PageLayoutEntity,
PageLayoutTabEntity,
PageLayoutWidgetEntity,
WorkspaceEntity,
]),
TwentyORMModule,
PermissionsModule,
FeatureFlagModule,
WorkspaceCacheStorageModule,
WorkspaceMigrationV2Module,
WorkspaceManyOrAllFlatEntityMapsCacheModule,
],
controllers: [
PageLayoutController,
PageLayoutTabController,
PageLayoutWidgetController,
],
providers: [
PageLayoutService,
PageLayoutTabService,
PageLayoutWidgetService,
PageLayoutResolver,
PageLayoutTabResolver,
PageLayoutWidgetResolver,
PageLayoutUpdateService,
],
exports: [PageLayoutService, PageLayoutTabService, PageLayoutWidgetService],
})
export class PageLayoutModule {}
@@ -4,11 +4,11 @@ import { Args, Mutation, Query, Resolver } from '@nestjs/graphql';
import { isDefined } from 'twenty-shared/utils';
import { ResolverValidationPipe } from 'src/engine/core-modules/graphql/pipes/resolver-validation.pipe';
import { CreatePageLayoutTabInput } from 'src/engine/core-modules/page-layout/dtos/inputs/create-page-layout-tab.input';
import { UpdatePageLayoutTabInput } from 'src/engine/core-modules/page-layout/dtos/inputs/update-page-layout-tab.input';
import { PageLayoutTabDTO } from 'src/engine/core-modules/page-layout/dtos/page-layout-tab.dto';
import { PageLayoutTabService } from 'src/engine/core-modules/page-layout/services/page-layout-tab.service';
import { PageLayoutGraphqlApiExceptionFilter } from 'src/engine/core-modules/page-layout/utils/page-layout-graphql-api-exception.filter';
import { CreatePageLayoutTabInput } from 'src/engine/metadata-modules/page-layout/dtos/inputs/create-page-layout-tab.input';
import { UpdatePageLayoutTabInput } from 'src/engine/metadata-modules/page-layout/dtos/inputs/update-page-layout-tab.input';
import { PageLayoutTabDTO } from 'src/engine/metadata-modules/page-layout/dtos/page-layout-tab.dto';
import { PageLayoutTabService } from 'src/engine/metadata-modules/page-layout/services/page-layout-tab.service';
import { PageLayoutGraphqlApiExceptionFilter } from 'src/engine/metadata-modules/page-layout/utils/page-layout-graphql-api-exception.filter';
import { type WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
import { NoPermissionGuard } from 'src/engine/guards/no-permission.guard';
@@ -9,18 +9,18 @@ import {
} from '@nestjs/graphql';
import { ResolverValidationPipe } from 'src/engine/core-modules/graphql/pipes/resolver-validation.pipe';
import { CreatePageLayoutWidgetInput } from 'src/engine/core-modules/page-layout/dtos/inputs/create-page-layout-widget.input';
import { UpdatePageLayoutWidgetInput } from 'src/engine/core-modules/page-layout/dtos/inputs/update-page-layout-widget.input';
import { PageLayoutWidgetDTO } from 'src/engine/core-modules/page-layout/dtos/page-layout-widget.dto';
import { WidgetConfiguration } from 'src/engine/core-modules/page-layout/dtos/widget-configuration.interface';
import { PageLayoutWidgetService } from 'src/engine/core-modules/page-layout/services/page-layout-widget.service';
import { injectWidgetConfigurationDiscriminator } from 'src/engine/core-modules/page-layout/utils/inject-widget-configuration-discriminator.util';
import { PageLayoutGraphqlApiExceptionFilter } from 'src/engine/core-modules/page-layout/utils/page-layout-graphql-api-exception.filter';
import { type WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
import { NoPermissionGuard } from 'src/engine/guards/no-permission.guard';
import { SettingsPermissionGuard } from 'src/engine/guards/settings-permission.guard';
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
import { CreatePageLayoutWidgetInput } from 'src/engine/metadata-modules/page-layout/dtos/inputs/create-page-layout-widget.input';
import { UpdatePageLayoutWidgetInput } from 'src/engine/metadata-modules/page-layout/dtos/inputs/update-page-layout-widget.input';
import { PageLayoutWidgetDTO } from 'src/engine/metadata-modules/page-layout/dtos/page-layout-widget.dto';
import { WidgetConfiguration } from 'src/engine/metadata-modules/page-layout/dtos/widget-configuration.interface';
import { PageLayoutWidgetService } from 'src/engine/metadata-modules/page-layout/services/page-layout-widget.service';
import { injectWidgetConfigurationDiscriminator } from 'src/engine/metadata-modules/page-layout/utils/inject-widget-configuration-discriminator.util';
import { PageLayoutGraphqlApiExceptionFilter } from 'src/engine/metadata-modules/page-layout/utils/page-layout-graphql-api-exception.filter';
import { PermissionFlagType } from 'src/engine/metadata-modules/permissions/constants/permission-flag-type.constants';
@Resolver(() => PageLayoutWidgetDTO)
@@ -4,13 +4,13 @@ import { Args, Mutation, Query, Resolver } from '@nestjs/graphql';
import { isDefined } from 'twenty-shared/utils';
import { ResolverValidationPipe } from 'src/engine/core-modules/graphql/pipes/resolver-validation.pipe';
import { CreatePageLayoutInput } from 'src/engine/core-modules/page-layout/dtos/inputs/create-page-layout.input';
import { UpdatePageLayoutWithTabsInput } from 'src/engine/core-modules/page-layout/dtos/inputs/update-page-layout-with-tabs.input';
import { UpdatePageLayoutInput } from 'src/engine/core-modules/page-layout/dtos/inputs/update-page-layout.input';
import { PageLayoutDTO } from 'src/engine/core-modules/page-layout/dtos/page-layout.dto';
import { PageLayoutUpdateService } from 'src/engine/core-modules/page-layout/services/page-layout-update.service';
import { PageLayoutService } from 'src/engine/core-modules/page-layout/services/page-layout.service';
import { PageLayoutGraphqlApiExceptionFilter } from 'src/engine/core-modules/page-layout/utils/page-layout-graphql-api-exception.filter';
import { CreatePageLayoutInput } from 'src/engine/metadata-modules/page-layout/dtos/inputs/create-page-layout.input';
import { UpdatePageLayoutWithTabsInput } from 'src/engine/metadata-modules/page-layout/dtos/inputs/update-page-layout-with-tabs.input';
import { UpdatePageLayoutInput } from 'src/engine/metadata-modules/page-layout/dtos/inputs/update-page-layout.input';
import { PageLayoutDTO } from 'src/engine/metadata-modules/page-layout/dtos/page-layout.dto';
import { PageLayoutUpdateService } from 'src/engine/metadata-modules/page-layout/services/page-layout-update.service';
import { PageLayoutService } from 'src/engine/metadata-modules/page-layout/services/page-layout.service';
import { PageLayoutGraphqlApiExceptionFilter } from 'src/engine/metadata-modules/page-layout/utils/page-layout-graphql-api-exception.filter';
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
import { NoPermissionGuard } from 'src/engine/guards/no-permission.guard';
@@ -4,22 +4,22 @@ import { getRepositoryToken } from '@nestjs/typeorm';
import { type Repository } from 'typeorm';
import { type ApplicationEntity } from 'src/engine/core-modules/application/application.entity';
import { PageLayoutTabEntity } from 'src/engine/core-modules/page-layout/entities/page-layout-tab.entity';
import { type PageLayoutWidgetEntity } from 'src/engine/core-modules/page-layout/entities/page-layout-widget.entity';
import { WidgetType } from 'src/engine/core-modules/page-layout/enums/widget-type.enum';
import { PageLayoutTabEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout-tab.entity';
import { type PageLayoutWidgetEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout-widget.entity';
import { WidgetType } from 'src/engine/metadata-modules/page-layout/enums/widget-type.enum';
import {
generatePageLayoutTabExceptionMessage,
PageLayoutTabException,
PageLayoutTabExceptionCode,
PageLayoutTabExceptionMessageKey,
} from 'src/engine/core-modules/page-layout/exceptions/page-layout-tab.exception';
} from 'src/engine/metadata-modules/page-layout/exceptions/page-layout-tab.exception';
import {
PageLayoutException,
PageLayoutExceptionCode,
} from 'src/engine/core-modules/page-layout/exceptions/page-layout.exception';
import { PageLayoutTabService } from 'src/engine/core-modules/page-layout/services/page-layout-tab.service';
import { PageLayoutService } from 'src/engine/core-modules/page-layout/services/page-layout.service';
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
} from 'src/engine/metadata-modules/page-layout/exceptions/page-layout.exception';
import { PageLayoutTabService } from 'src/engine/metadata-modules/page-layout/services/page-layout-tab.service';
import { PageLayoutService } from 'src/engine/metadata-modules/page-layout/services/page-layout.service';
import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator';
describe('PageLayoutTabService', () => {
let pageLayoutTabService: PageLayoutTabService;
@@ -3,18 +3,18 @@ import { Test, type TestingModule } from '@nestjs/testing';
import { DataSource, type EntityManager } from 'typeorm';
import { type ApplicationEntity } from 'src/engine/core-modules/application/application.entity';
import { type UpdatePageLayoutTabWithWidgetsInput } from 'src/engine/core-modules/page-layout/dtos/inputs/update-page-layout-tab-with-widgets.input';
import { type UpdatePageLayoutWidgetWithIdInput } from 'src/engine/core-modules/page-layout/dtos/inputs/update-page-layout-widget-with-id.input';
import { type PageLayoutTabEntity } from 'src/engine/core-modules/page-layout/entities/page-layout-tab.entity';
import { type PageLayoutWidgetEntity } from 'src/engine/core-modules/page-layout/entities/page-layout-widget.entity';
import { type PageLayoutEntity } from 'src/engine/core-modules/page-layout/entities/page-layout.entity';
import { PageLayoutType } from 'src/engine/core-modules/page-layout/enums/page-layout-type.enum';
import { WidgetType } from 'src/engine/core-modules/page-layout/enums/widget-type.enum';
import { PageLayoutTabService } from 'src/engine/core-modules/page-layout/services/page-layout-tab.service';
import { PageLayoutUpdateService } from 'src/engine/core-modules/page-layout/services/page-layout-update.service';
import { PageLayoutWidgetService } from 'src/engine/core-modules/page-layout/services/page-layout-widget.service';
import { PageLayoutService } from 'src/engine/core-modules/page-layout/services/page-layout.service';
import { type WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
import { type UpdatePageLayoutTabWithWidgetsInput } from 'src/engine/metadata-modules/page-layout/dtos/inputs/update-page-layout-tab-with-widgets.input';
import { type UpdatePageLayoutWidgetWithIdInput } from 'src/engine/metadata-modules/page-layout/dtos/inputs/update-page-layout-widget-with-id.input';
import { type PageLayoutTabEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout-tab.entity';
import { type PageLayoutWidgetEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout-widget.entity';
import { type PageLayoutEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout.entity';
import { PageLayoutType } from 'src/engine/metadata-modules/page-layout/enums/page-layout-type.enum';
import { WidgetType } from 'src/engine/metadata-modules/page-layout/enums/widget-type.enum';
import { PageLayoutTabService } from 'src/engine/metadata-modules/page-layout/services/page-layout-tab.service';
import { PageLayoutUpdateService } from 'src/engine/metadata-modules/page-layout/services/page-layout-update.service';
import { PageLayoutWidgetService } from 'src/engine/metadata-modules/page-layout/services/page-layout-widget.service';
import { PageLayoutService } from 'src/engine/metadata-modules/page-layout/services/page-layout.service';
describe('PageLayoutUpdateService', () => {
let pageLayoutUpdateService: PageLayoutUpdateService;
@@ -4,20 +4,21 @@ import { getRepositoryToken } from '@nestjs/typeorm';
import { IsNull, type Repository } from 'typeorm';
import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service';
import { PageLayoutWidgetEntity } from 'src/engine/core-modules/page-layout/entities/page-layout-widget.entity';
import { WidgetType } from 'src/engine/core-modules/page-layout/enums/widget-type.enum';
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
import { PageLayoutWidgetEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout-widget.entity';
import { WidgetType } from 'src/engine/metadata-modules/page-layout/enums/widget-type.enum';
import {
PageLayoutTabException,
PageLayoutTabExceptionCode,
} from 'src/engine/core-modules/page-layout/exceptions/page-layout-tab.exception';
} from 'src/engine/metadata-modules/page-layout/exceptions/page-layout-tab.exception';
import {
generatePageLayoutWidgetExceptionMessage,
PageLayoutWidgetException,
PageLayoutWidgetExceptionCode,
PageLayoutWidgetExceptionMessageKey,
} from 'src/engine/core-modules/page-layout/exceptions/page-layout-widget.exception';
import { PageLayoutTabService } from 'src/engine/core-modules/page-layout/services/page-layout-tab.service';
import { PageLayoutWidgetService } from 'src/engine/core-modules/page-layout/services/page-layout-widget.service';
} from 'src/engine/metadata-modules/page-layout/exceptions/page-layout-widget.exception';
import { PageLayoutTabService } from 'src/engine/metadata-modules/page-layout/services/page-layout-tab.service';
import { PageLayoutWidgetService } from 'src/engine/metadata-modules/page-layout/services/page-layout-widget.service';
describe('PageLayoutWidgetService', () => {
let pageLayoutWidgetService: PageLayoutWidgetService;
@@ -59,6 +60,15 @@ describe('PageLayoutWidgetService', () => {
restore: jest.fn(),
},
},
{
provide: getRepositoryToken(WorkspaceEntity),
useValue: {
findOne: jest.fn(),
findOneOrFail: jest.fn().mockResolvedValue({
workspaceCustomApplicationId: 'application-id',
}),
},
},
{
provide: PageLayoutTabService,
useValue: {
@@ -200,6 +210,8 @@ describe('PageLayoutWidgetService', () => {
expect(pageLayoutWidgetRepository.insert).toHaveBeenCalledWith({
...validPageLayoutWidgetData,
workspaceId,
applicationId: 'application-id',
universalIdentifier: expect.any(String),
});
expect(result).toEqual(mockPageLayoutWidget);
});
@@ -3,16 +3,16 @@ import { getRepositoryToken } from '@nestjs/typeorm';
import { IsNull, type Repository } from 'typeorm';
import { type CreatePageLayoutInput } from 'src/engine/core-modules/page-layout/dtos/inputs/create-page-layout.input';
import { PageLayoutEntity } from 'src/engine/core-modules/page-layout/entities/page-layout.entity';
import { PageLayoutType } from 'src/engine/core-modules/page-layout/enums/page-layout-type.enum';
import { type CreatePageLayoutInput } from 'src/engine/metadata-modules/page-layout/dtos/inputs/create-page-layout.input';
import { PageLayoutEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout.entity';
import { PageLayoutType } from 'src/engine/metadata-modules/page-layout/enums/page-layout-type.enum';
import {
PageLayoutException,
PageLayoutExceptionCode,
PageLayoutExceptionMessageKey,
generatePageLayoutExceptionMessage,
} from 'src/engine/core-modules/page-layout/exceptions/page-layout.exception';
import { PageLayoutService } from 'src/engine/core-modules/page-layout/services/page-layout.service';
} from 'src/engine/metadata-modules/page-layout/exceptions/page-layout.exception';
import { PageLayoutService } from 'src/engine/metadata-modules/page-layout/services/page-layout.service';
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
describe('PageLayoutService', () => {
@@ -6,20 +6,20 @@ import { EntityManager, IsNull, Repository } from 'typeorm';
import { QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialEntity';
import { v4 } from 'uuid';
import { CreatePageLayoutTabInput } from 'src/engine/core-modules/page-layout/dtos/inputs/create-page-layout-tab.input';
import { PageLayoutTabEntity } from 'src/engine/core-modules/page-layout/entities/page-layout-tab.entity';
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
import { CreatePageLayoutTabInput } from 'src/engine/metadata-modules/page-layout/dtos/inputs/create-page-layout-tab.input';
import { PageLayoutTabEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout-tab.entity';
import {
PageLayoutTabException,
PageLayoutTabExceptionCode,
PageLayoutTabExceptionMessageKey,
generatePageLayoutTabExceptionMessage,
} from 'src/engine/core-modules/page-layout/exceptions/page-layout-tab.exception';
} from 'src/engine/metadata-modules/page-layout/exceptions/page-layout-tab.exception';
import {
PageLayoutException,
PageLayoutExceptionCode,
} from 'src/engine/core-modules/page-layout/exceptions/page-layout.exception';
import { PageLayoutService } from 'src/engine/core-modules/page-layout/services/page-layout.service';
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
} from 'src/engine/metadata-modules/page-layout/exceptions/page-layout.exception';
import { PageLayoutService } from 'src/engine/metadata-modules/page-layout/services/page-layout.service';
@Injectable()
export class PageLayoutTabService {
@@ -3,16 +3,16 @@ import { Injectable } from '@nestjs/common';
import { computeDiffBetweenObjects, isDefined } from 'twenty-shared/utils';
import { DataSource, EntityManager } from 'typeorm';
import { CreatePageLayoutWidgetInput } from 'src/engine/core-modules/page-layout/dtos/inputs/create-page-layout-widget.input';
import { UpdatePageLayoutTabWithWidgetsInput } from 'src/engine/core-modules/page-layout/dtos/inputs/update-page-layout-tab-with-widgets.input';
import { UpdatePageLayoutWidgetWithIdInput } from 'src/engine/core-modules/page-layout/dtos/inputs/update-page-layout-widget-with-id.input';
import { UpdatePageLayoutWithTabsInput } from 'src/engine/core-modules/page-layout/dtos/inputs/update-page-layout-with-tabs.input';
import { PageLayoutTabEntity } from 'src/engine/core-modules/page-layout/entities/page-layout-tab.entity';
import { PageLayoutWidgetEntity } from 'src/engine/core-modules/page-layout/entities/page-layout-widget.entity';
import { PageLayoutEntity } from 'src/engine/core-modules/page-layout/entities/page-layout.entity';
import { PageLayoutTabService } from 'src/engine/core-modules/page-layout/services/page-layout-tab.service';
import { PageLayoutWidgetService } from 'src/engine/core-modules/page-layout/services/page-layout-widget.service';
import { PageLayoutService } from 'src/engine/core-modules/page-layout/services/page-layout.service';
import { CreatePageLayoutWidgetInput } from 'src/engine/metadata-modules/page-layout/dtos/inputs/create-page-layout-widget.input';
import { UpdatePageLayoutTabWithWidgetsInput } from 'src/engine/metadata-modules/page-layout/dtos/inputs/update-page-layout-tab-with-widgets.input';
import { UpdatePageLayoutWidgetWithIdInput } from 'src/engine/metadata-modules/page-layout/dtos/inputs/update-page-layout-widget-with-id.input';
import { UpdatePageLayoutWithTabsInput } from 'src/engine/metadata-modules/page-layout/dtos/inputs/update-page-layout-with-tabs.input';
import { PageLayoutTabEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout-tab.entity';
import { PageLayoutWidgetEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout-widget.entity';
import { PageLayoutEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout.entity';
import { PageLayoutTabService } from 'src/engine/metadata-modules/page-layout/services/page-layout-tab.service';
import { PageLayoutWidgetService } from 'src/engine/metadata-modules/page-layout/services/page-layout-widget.service';
import { PageLayoutService } from 'src/engine/metadata-modules/page-layout/services/page-layout.service';
type UpdatePageLayoutWithTabsParams = {
id: string;
@@ -4,32 +4,36 @@ import { InjectRepository } from '@nestjs/typeorm';
import { isDefined } from 'twenty-shared/utils';
import { EntityManager, IsNull, Repository } from 'typeorm';
import { QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialEntity';
import { v4 } from 'uuid';
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service';
import { CreatePageLayoutWidgetInput } from 'src/engine/core-modules/page-layout/dtos/inputs/create-page-layout-widget.input';
import { UpdatePageLayoutWidgetInput } from 'src/engine/core-modules/page-layout/dtos/inputs/update-page-layout-widget.input';
import { WidgetConfigurationInterface } from 'src/engine/core-modules/page-layout/dtos/widget-configuration.interface';
import { PageLayoutWidgetEntity } from 'src/engine/core-modules/page-layout/entities/page-layout-widget.entity';
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
import { CreatePageLayoutWidgetInput } from 'src/engine/metadata-modules/page-layout/dtos/inputs/create-page-layout-widget.input';
import { UpdatePageLayoutWidgetInput } from 'src/engine/metadata-modules/page-layout/dtos/inputs/update-page-layout-widget.input';
import { WidgetConfigurationInterface } from 'src/engine/metadata-modules/page-layout/dtos/widget-configuration.interface';
import { PageLayoutWidgetEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout-widget.entity';
import {
PageLayoutTabException,
PageLayoutTabExceptionCode,
} from 'src/engine/core-modules/page-layout/exceptions/page-layout-tab.exception';
} from 'src/engine/metadata-modules/page-layout/exceptions/page-layout-tab.exception';
import {
PageLayoutWidgetException,
PageLayoutWidgetExceptionCode,
PageLayoutWidgetExceptionMessageKey,
generatePageLayoutWidgetExceptionMessage,
} from 'src/engine/core-modules/page-layout/exceptions/page-layout-widget.exception';
import { PageLayoutTabService } from 'src/engine/core-modules/page-layout/services/page-layout-tab.service';
import { validateAndTransformWidgetConfiguration } from 'src/engine/core-modules/page-layout/utils/validate-and-transform-widget-configuration.util';
import { validateWidgetGridPosition } from 'src/engine/core-modules/page-layout/utils/validate-widget-grid-position.util';
} from 'src/engine/metadata-modules/page-layout/exceptions/page-layout-widget.exception';
import { PageLayoutTabService } from 'src/engine/metadata-modules/page-layout/services/page-layout-tab.service';
import { validateAndTransformWidgetConfiguration } from 'src/engine/metadata-modules/page-layout/utils/validate-and-transform-widget-configuration.util';
import { validateWidgetGridPosition } from 'src/engine/metadata-modules/page-layout/utils/validate-widget-grid-position.util';
@Injectable()
export class PageLayoutWidgetService {
constructor(
@InjectRepository(PageLayoutWidgetEntity)
private readonly pageLayoutWidgetRepository: Repository<PageLayoutWidgetEntity>,
@InjectRepository(WorkspaceEntity)
private readonly workspaceRepository: Repository<WorkspaceEntity>,
private readonly pageLayoutTabService: PageLayoutTabService,
private readonly featureFlagService: FeatureFlagService,
) {}
@@ -171,11 +175,22 @@ export class PageLayoutWidgetService {
}
}
const workspace = await (
transactionManager
? transactionManager.getRepository(WorkspaceEntity)
: this.workspaceRepository
).findOneOrFail({
where: { id: workspaceId },
select: ['workspaceCustomApplicationId'],
});
const repository = this.getPageLayoutWidgetRepository(transactionManager);
const insertResult = await repository.insert({
...pageLayoutWidgetData,
workspaceId,
universalIdentifier: v4(),
applicationId: workspace.workspaceCustomApplicationId,
...(validatedConfig && { configuration: validatedConfig }),
} as QueryDeepPartialEntity<PageLayoutWidgetEntity>);
@@ -5,15 +5,15 @@ import { isDefined } from 'twenty-shared/utils';
import { EntityManager, IsNull, Repository } from 'typeorm';
import { QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialEntity';
import { CreatePageLayoutInput } from 'src/engine/core-modules/page-layout/dtos/inputs/create-page-layout.input';
import { PageLayoutEntity } from 'src/engine/core-modules/page-layout/entities/page-layout.entity';
import { PageLayoutType } from 'src/engine/core-modules/page-layout/enums/page-layout-type.enum';
import { CreatePageLayoutInput } from 'src/engine/metadata-modules/page-layout/dtos/inputs/create-page-layout.input';
import { PageLayoutEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout.entity';
import { PageLayoutType } from 'src/engine/metadata-modules/page-layout/enums/page-layout-type.enum';
import {
PageLayoutException,
PageLayoutExceptionCode,
PageLayoutExceptionMessageKey,
generatePageLayoutExceptionMessage,
} from 'src/engine/core-modules/page-layout/exceptions/page-layout.exception';
} from 'src/engine/metadata-modules/page-layout/exceptions/page-layout.exception';
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
@Injectable()
@@ -22,8 +22,8 @@ import {
TEST_VERTICAL_BAR_CHART_CONFIG_MINIMAL,
} from 'test/integration/constants/widget-configuration-test-data.constants';
import { WidgetType } from 'src/engine/core-modules/page-layout/enums/widget-type.enum';
import { validateAndTransformWidgetConfiguration } from 'src/engine/core-modules/page-layout/utils/validate-and-transform-widget-configuration.util';
import { WidgetType } from 'src/engine/metadata-modules/page-layout/enums/widget-type.enum';
import { validateAndTransformWidgetConfiguration } from 'src/engine/metadata-modules/page-layout/utils/validate-and-transform-widget-configuration.util';
jest.mock(
'src/engine/core-modules/record-transformer/utils/transform-rich-text-v2.util',
@@ -1,7 +1,7 @@
import { WIDGET_GRID_MAX_COLUMNS } from 'src/engine/core-modules/page-layout/constants/widget-grid-max-columns.constant';
import { WIDGET_GRID_MAX_ROWS } from 'src/engine/core-modules/page-layout/constants/widget-grid-max-rows.constant';
import { PageLayoutWidgetException } from 'src/engine/core-modules/page-layout/exceptions/page-layout-widget.exception';
import { validateWidgetGridPosition } from 'src/engine/core-modules/page-layout/utils/validate-widget-grid-position.util';
import { WIDGET_GRID_MAX_COLUMNS } from 'src/engine/metadata-modules/page-layout/constants/widget-grid-max-columns.constant';
import { WIDGET_GRID_MAX_ROWS } from 'src/engine/metadata-modules/page-layout/constants/widget-grid-max-rows.constant';
import { PageLayoutWidgetException } from 'src/engine/metadata-modules/page-layout/exceptions/page-layout-widget.exception';
import { validateWidgetGridPosition } from 'src/engine/metadata-modules/page-layout/utils/validate-widget-grid-position.util';
describe('validateWidgetGridPosition', () => {
const validGridPosition = {
@@ -1,6 +1,6 @@
import { type WidgetConfigurationInterface } from 'src/engine/core-modules/page-layout/dtos/widget-configuration.interface';
import { WidgetConfigurationType } from 'src/engine/core-modules/page-layout/enums/widget-configuration-type.enum';
import { WidgetType } from 'src/engine/core-modules/page-layout/enums/widget-type.enum';
import { type WidgetConfigurationInterface } from 'src/engine/metadata-modules/page-layout/dtos/widget-configuration.interface';
import { WidgetConfigurationType } from 'src/engine/metadata-modules/page-layout/enums/widget-configuration-type.enum';
import { WidgetType } from 'src/engine/metadata-modules/page-layout/enums/widget-type.enum';
type ConfigurationWithDiscriminator = WidgetConfigurationInterface & {
configurationType: WidgetConfigurationType;
@@ -7,15 +7,15 @@ import {
import {
PageLayoutTabException,
PageLayoutTabExceptionCode,
} from 'src/engine/core-modules/page-layout/exceptions/page-layout-tab.exception';
} from 'src/engine/metadata-modules/page-layout/exceptions/page-layout-tab.exception';
import {
PageLayoutWidgetException,
PageLayoutWidgetExceptionCode,
} from 'src/engine/core-modules/page-layout/exceptions/page-layout-widget.exception';
} from 'src/engine/metadata-modules/page-layout/exceptions/page-layout-widget.exception';
import {
PageLayoutException,
PageLayoutExceptionCode,
} from 'src/engine/core-modules/page-layout/exceptions/page-layout.exception';
} from 'src/engine/metadata-modules/page-layout/exceptions/page-layout.exception';
export const pageLayoutGraphqlApiExceptionHandler = (error: Error) => {
if (error instanceof PageLayoutException) {
@@ -1,10 +1,10 @@
import { ArgumentsHost, Catch } from '@nestjs/common';
import { GqlExceptionFilter } from '@nestjs/graphql';
import { PageLayoutTabException } from 'src/engine/core-modules/page-layout/exceptions/page-layout-tab.exception';
import { PageLayoutWidgetException } from 'src/engine/core-modules/page-layout/exceptions/page-layout-widget.exception';
import { PageLayoutException } from 'src/engine/core-modules/page-layout/exceptions/page-layout.exception';
import { pageLayoutGraphqlApiExceptionHandler } from 'src/engine/core-modules/page-layout/utils/page-layout-graphql-api-exception-handler.util';
import { PageLayoutTabException } from 'src/engine/metadata-modules/page-layout/exceptions/page-layout-tab.exception';
import { PageLayoutWidgetException } from 'src/engine/metadata-modules/page-layout/exceptions/page-layout-widget.exception';
import { PageLayoutException } from 'src/engine/metadata-modules/page-layout/exceptions/page-layout.exception';
import { pageLayoutGraphqlApiExceptionHandler } from 'src/engine/metadata-modules/page-layout/utils/page-layout-graphql-api-exception-handler.util';
@Catch(PageLayoutException, PageLayoutTabException, PageLayoutWidgetException)
export class PageLayoutGraphqlApiExceptionFilter implements GqlExceptionFilter {
@@ -2,18 +2,18 @@ import { plainToInstance } from 'class-transformer';
import { validateSync, type ValidationError } from 'class-validator';
import { isDefined } from 'twenty-shared/utils';
import { AggregateChartConfigurationDTO } from 'src/engine/core-modules/page-layout/dtos/aggregate-chart-configuration.dto';
import { transformRichTextV2Value } from 'src/engine/core-modules/record-transformer/utils/transform-rich-text-v2.util';
import { BarChartConfigurationDTO } from 'src/engine/core-modules/page-layout/dtos/bar-chart-configuration.dto';
import { GaugeChartConfigurationDTO } from 'src/engine/core-modules/page-layout/dtos/gauge-chart-configuration.dto';
import { IframeConfigurationDTO } from 'src/engine/core-modules/page-layout/dtos/iframe-configuration.dto';
import { LineChartConfigurationDTO } from 'src/engine/core-modules/page-layout/dtos/line-chart-configuration.dto';
import { PieChartConfigurationDTO } from 'src/engine/core-modules/page-layout/dtos/pie-chart-configuration.dto';
import { StandaloneRichTextConfigurationDTO } from 'src/engine/core-modules/page-layout/dtos/standalone-rich-text-configuration.dto';
import { type WidgetConfigurationInterface } from 'src/engine/core-modules/page-layout/dtos/widget-configuration.interface';
import { BarChartGroupMode } from 'src/engine/core-modules/page-layout/enums/bar-chart-group-mode.enum';
import { GraphType } from 'src/engine/core-modules/page-layout/enums/graph-type.enum';
import { WidgetType } from 'src/engine/core-modules/page-layout/enums/widget-type.enum';
import { AggregateChartConfigurationDTO } from 'src/engine/metadata-modules/page-layout/dtos/aggregate-chart-configuration.dto';
import { BarChartConfigurationDTO } from 'src/engine/metadata-modules/page-layout/dtos/bar-chart-configuration.dto';
import { GaugeChartConfigurationDTO } from 'src/engine/metadata-modules/page-layout/dtos/gauge-chart-configuration.dto';
import { IframeConfigurationDTO } from 'src/engine/metadata-modules/page-layout/dtos/iframe-configuration.dto';
import { LineChartConfigurationDTO } from 'src/engine/metadata-modules/page-layout/dtos/line-chart-configuration.dto';
import { PieChartConfigurationDTO } from 'src/engine/metadata-modules/page-layout/dtos/pie-chart-configuration.dto';
import { StandaloneRichTextConfigurationDTO } from 'src/engine/metadata-modules/page-layout/dtos/standalone-rich-text-configuration.dto';
import { type WidgetConfigurationInterface } from 'src/engine/metadata-modules/page-layout/dtos/widget-configuration.interface';
import { BarChartGroupMode } from 'src/engine/metadata-modules/page-layout/enums/bar-chart-group-mode.enum';
import { GraphType } from 'src/engine/metadata-modules/page-layout/enums/graph-type.enum';
import { WidgetType } from 'src/engine/metadata-modules/page-layout/enums/widget-type.enum';
const formatValidationErrors = (errors: ValidationError[]): string => {
return errors
@@ -1,11 +1,11 @@
import { WIDGET_GRID_MAX_COLUMNS } from 'src/engine/core-modules/page-layout/constants/widget-grid-max-columns.constant';
import { WIDGET_GRID_MAX_ROWS } from 'src/engine/core-modules/page-layout/constants/widget-grid-max-rows.constant';
import { WIDGET_GRID_MAX_COLUMNS } from 'src/engine/metadata-modules/page-layout/constants/widget-grid-max-columns.constant';
import { WIDGET_GRID_MAX_ROWS } from 'src/engine/metadata-modules/page-layout/constants/widget-grid-max-rows.constant';
import {
PageLayoutWidgetException,
PageLayoutWidgetExceptionCode,
PageLayoutWidgetExceptionMessageKey,
generatePageLayoutWidgetExceptionMessage,
} from 'src/engine/core-modules/page-layout/exceptions/page-layout-widget.exception';
} from 'src/engine/metadata-modules/page-layout/exceptions/page-layout-widget.exception';
type GridPosition = {
row: number;
@@ -29,6 +29,7 @@ export const WORKSPACE_CACHE_KEYS_V2 = {
ORMEntityMetadatas: 'orm:entity-metadatas',
flatAgentMaps: 'flat-maps:agent',
flatRoleTargetByAgentIdMaps: 'flat-maps:flatRoleTargetByAgentId',
flatPageLayoutWidgetMaps: 'flat-maps:page-layout-widget',
flatPageLayoutTabMaps: 'flat-maps:flatPageLayoutTabMaps',
} as const satisfies Record<WorkspaceCacheKeyName, string>;
@@ -1,4 +1,4 @@
import { PageLayoutType } from 'src/engine/core-modules/page-layout/enums/page-layout-type.enum';
import { PageLayoutType } from 'src/engine/metadata-modules/page-layout/enums/page-layout-type.enum';
import { PAGE_LAYOUT_SEEDS } from 'src/engine/workspace-manager/dev-seeder/core/constants/page-layout-seeds.constant';
import { generateSeedId } from 'src/engine/workspace-manager/dev-seeder/core/utils/generate-seed-id.util';
@@ -3,8 +3,8 @@ import { isDefined } from 'twenty-shared/utils';
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
import { AggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/aggregate-operations.constant';
import { AxisNameDisplay } from 'src/engine/core-modules/page-layout/enums/axis-name-display.enum';
import { WidgetType } from 'src/engine/core-modules/page-layout/enums/widget-type.enum';
import { AxisNameDisplay } from 'src/engine/metadata-modules/page-layout/enums/axis-name-display.enum';
import { WidgetType } from 'src/engine/metadata-modules/page-layout/enums/widget-type.enum';
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { PAGE_LAYOUT_TAB_SEEDS } from 'src/engine/workspace-manager/dev-seeder/core/constants/page-layout-tab-seeds.constant';
import { PAGE_LAYOUT_WIDGET_SEEDS } from 'src/engine/workspace-manager/dev-seeder/core/constants/page-layout-widget-seeds.constant';
@@ -3,9 +3,9 @@ import { isDefined } from 'twenty-shared/utils';
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
import { AggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/aggregate-operations.constant';
import { AxisNameDisplay } from 'src/engine/core-modules/page-layout/enums/axis-name-display.enum';
import { GraphType } from 'src/engine/core-modules/page-layout/enums/graph-type.enum';
import { WidgetType } from 'src/engine/core-modules/page-layout/enums/widget-type.enum';
import { AxisNameDisplay } from 'src/engine/metadata-modules/page-layout/enums/axis-name-display.enum';
import { GraphType } from 'src/engine/metadata-modules/page-layout/enums/graph-type.enum';
import { WidgetType } from 'src/engine/metadata-modules/page-layout/enums/widget-type.enum';
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { PAGE_LAYOUT_TAB_SEEDS } from 'src/engine/workspace-manager/dev-seeder/core/constants/page-layout-tab-seeds.constant';
import { PAGE_LAYOUT_WIDGET_SEEDS } from 'src/engine/workspace-manager/dev-seeder/core/constants/page-layout-widget-seeds.constant';
@@ -1,7 +1,8 @@
import { type DataSource } from 'typeorm';
import { v4 } from 'uuid';
import { validateAndTransformWidgetConfiguration } from 'src/engine/core-modules/page-layout/utils/validate-and-transform-widget-configuration.util';
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { validateAndTransformWidgetConfiguration } from 'src/engine/metadata-modules/page-layout/utils/validate-and-transform-widget-configuration.util';
import { getPageLayoutWidgetDataSeeds } from 'src/engine/workspace-manager/dev-seeder/core/utils/get-page-layout-widget-data-seeds.util';
export const seedPageLayoutWidgets = async ({
@@ -10,12 +11,14 @@ export const seedPageLayoutWidgets = async ({
workspaceId,
objectMetadataItems,
isDashboardV2Enabled,
workspaceCustomApplicationId,
}: {
dataSource: DataSource;
schemaName: string;
workspaceId: string;
objectMetadataItems: ObjectMetadataEntity[];
isDashboardV2Enabled: boolean;
workspaceCustomApplicationId: string;
}) => {
const widgetSeeds = getPageLayoutWidgetDataSeeds(
workspaceId,
@@ -38,6 +41,8 @@ export const seedPageLayoutWidgets = async ({
workspaceId,
gridPosition: widget.gridPosition,
configuration: validatedConfiguration,
universalIdentifier: v4(),
applicationId: workspaceCustomApplicationId,
};
}),
);
@@ -55,6 +60,8 @@ export const seedPageLayoutWidgets = async ({
'configuration',
'objectMetadataId',
'workspaceId',
'universalIdentifier',
'applicationId',
])
.values(pageLayoutWidgets)
.orIgnore()
@@ -135,6 +135,7 @@ export class DevSeederService {
workspaceId,
objectMetadataItems,
isDashboardV2Enabled,
workspaceCustomApplicationId: workspaceCustomFlatApplication.id,
});
await this.devSeederDataService.seed({
@@ -89,6 +89,11 @@ export const computeTwentyStandardApplicationAllFlatEntityMaps = ({
idByUniversalIdentifier: {},
universalIdentifiersByApplicationId: {},
},
flatPageLayoutWidgetMaps: {
byId: {},
idByUniversalIdentifier: {},
universalIdentifiersByApplicationId: {},
},
flatPageLayoutTabMaps: {
byId: {},
idByUniversalIdentifier: {},
@@ -31,6 +31,7 @@ export const fromWorkspaceMigrationBuilderExceptionToMetadataValidationResponseE
invalidViewGroup: 0,
invalidRole: 0,
invalidRoleTarget: 0,
invalidPageLayoutWidget: 0,
totalErrors: 0,
invalidPageLayoutTab: 0,
},
@@ -0,0 +1,18 @@
import { type FlatEntityPropertiesUpdates } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-properties-updates.type';
import { type FlatPageLayoutWidget } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget.type';
export type CreatePageLayoutWidgetAction = {
type: 'create_page_layout_widget';
pageLayoutWidget: FlatPageLayoutWidget;
};
export type UpdatePageLayoutWidgetAction = {
type: 'update_page_layout_widget';
pageLayoutWidgetId: string;
updates: FlatEntityPropertiesUpdates<'pageLayoutWidget'>;
};
export type DeletePageLayoutWidgetAction = {
type: 'delete_page_layout_widget';
pageLayoutWidgetId: string;
};
@@ -0,0 +1,111 @@
import { Injectable } from '@nestjs/common';
import { ALL_METADATA_NAME } from 'twenty-shared/metadata';
import { UpdatePageLayoutWidgetAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/page-layout-widget/types/workspace-migration-page-layout-widget-action-v2.type';
import { WorkspaceEntityMigrationBuilderV2Service } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/services/workspace-entity-migration-builder-v2.service';
import { FlatEntityUpdateValidationArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/flat-entity-update-validation-args.type';
import { FlatEntityValidationArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/flat-entity-validation-args.type';
import { FlatEntityValidationReturnType } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/flat-entity-validation-result.type';
import { FlatPageLayoutWidgetValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-page-layout-widget-validator.service';
@Injectable()
export class WorkspaceMigrationV2PageLayoutWidgetActionsBuilderService extends WorkspaceEntityMigrationBuilderV2Service<
typeof ALL_METADATA_NAME.pageLayoutWidget
> {
constructor(
private readonly flatPageLayoutWidgetValidatorService: FlatPageLayoutWidgetValidatorService,
) {
super(ALL_METADATA_NAME.pageLayoutWidget);
}
protected validateFlatEntityCreation(
args: FlatEntityValidationArgs<typeof ALL_METADATA_NAME.pageLayoutWidget>,
): FlatEntityValidationReturnType<
typeof ALL_METADATA_NAME.pageLayoutWidget,
'created'
> {
const validationResult =
this.flatPageLayoutWidgetValidatorService.validateFlatPageLayoutWidgetCreation(
args,
);
if (validationResult.errors.length > 0) {
return {
status: 'fail',
...validationResult,
};
}
return {
status: 'success',
action: {
type: 'create_page_layout_widget',
pageLayoutWidget: args.flatEntityToValidate,
},
};
}
protected validateFlatEntityDeletion(
args: FlatEntityValidationArgs<typeof ALL_METADATA_NAME.pageLayoutWidget>,
): FlatEntityValidationReturnType<
typeof ALL_METADATA_NAME.pageLayoutWidget,
'deleted'
> {
const validationResult =
this.flatPageLayoutWidgetValidatorService.validateFlatPageLayoutWidgetDeletion(
args,
);
if (validationResult.errors.length > 0) {
return {
status: 'fail',
...validationResult,
};
}
const { flatEntityToValidate: flatPageLayoutWidgetToValidate } = args;
return {
status: 'success',
action: {
type: 'delete_page_layout_widget',
pageLayoutWidgetId: flatPageLayoutWidgetToValidate.id,
},
};
}
protected validateFlatEntityUpdate(
args: FlatEntityUpdateValidationArgs<
typeof ALL_METADATA_NAME.pageLayoutWidget
>,
): FlatEntityValidationReturnType<
typeof ALL_METADATA_NAME.pageLayoutWidget,
'updated'
> {
const validationResult =
this.flatPageLayoutWidgetValidatorService.validateFlatPageLayoutWidgetUpdate(
args,
);
if (validationResult.errors.length > 0) {
return {
status: 'fail',
...validationResult,
};
}
const { flatEntityId, flatEntityUpdates } = args;
const updatePageLayoutWidgetAction: UpdatePageLayoutWidgetAction = {
type: 'update_page_layout_widget',
pageLayoutWidgetId: flatEntityId,
updates: flatEntityUpdates,
};
return {
status: 'success',
action: updatePageLayoutWidgetAction,
};
}
}

Some files were not shown because too many files have changed in this diff Show More