diff --git a/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.module.ts b/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.module.ts index 46992a6e1..6b0074d1e 100644 --- a/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.module.ts +++ b/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.module.ts @@ -10,13 +10,15 @@ import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm'; import { TypeORMModule } from 'src/database/typeorm/typeorm.module'; import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; -import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module'; import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard'; import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module'; import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { BeforeUpdateOneObject } from 'src/engine/metadata-modules/object-metadata/hooks/before-update-one-object.hook'; import { ObjectMetadataGraphqlApiExceptionInterceptor } from 'src/engine/metadata-modules/object-metadata/interceptors/object-metadata-graphql-api-exception.interceptor'; import { ObjectMetadataResolver } from 'src/engine/metadata-modules/object-metadata/object-metadata.resolver'; +import { ObjectMetadataMigrationService } from 'src/engine/metadata-modules/object-metadata/services/object-metadata-migration.service'; +import { ObjectMetadataRelatedRecordsService } from 'src/engine/metadata-modules/object-metadata/services/object-metadata-related-records.service'; +import { ObjectMetadataRelationService } from 'src/engine/metadata-modules/object-metadata/services/object-metadata-relation.service'; import { RelationMetadataEntity } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; import { RemoteTableRelationsModule } from 'src/engine/metadata-modules/remote-server/remote-table/remote-table-relations/remote-table-relations.module'; import { SearchModule } from 'src/engine/metadata-modules/search/search.module'; @@ -46,10 +48,14 @@ import { UpdateObjectPayload } from './dtos/update-object.input'; WorkspaceMigrationRunnerModule, WorkspaceMetadataVersionModule, RemoteTableRelationsModule, - FeatureFlagModule, SearchModule, ], - services: [ObjectMetadataService], + services: [ + ObjectMetadataService, + ObjectMetadataMigrationService, + ObjectMetadataRelationService, + ObjectMetadataRelatedRecordsService, + ], resolvers: [ { EntityClass: ObjectMetadataEntity, diff --git a/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.service.ts b/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.service.ts index 56c3d549b..2e6b41605 100644 --- a/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.service.ts @@ -8,66 +8,30 @@ import { TypeOrmQueryService } from '@ptc-org/nestjs-query-typeorm'; import { isDefined } from 'class-validator'; import { FindManyOptions, FindOneOptions, In, Not, Repository } from 'typeorm'; -import { FieldMetadataSettings } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface'; - -import { TypeORMService } from 'src/database/typeorm/typeorm.service'; -import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service'; import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service'; -import { - FieldMetadataEntity, - FieldMetadataType, -} from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; -import { computeColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-column-name.util'; +import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { DeleteOneObjectInput } from 'src/engine/metadata-modules/object-metadata/dtos/delete-object.input'; import { UpdateOneObjectInput } from 'src/engine/metadata-modules/object-metadata/dtos/update-object.input'; import { ObjectMetadataException, ObjectMetadataExceptionCode, } from 'src/engine/metadata-modules/object-metadata/object-metadata.exception'; -import { buildMigrationsForCustomObjectRelations } from 'src/engine/metadata-modules/object-metadata/utils/build-migrations-for-custom-object-relations.util'; -import { validateObjectMetadataInputOrThrow } from 'src/engine/metadata-modules/object-metadata/utils/validate-object-metadata-input.util'; -import { validateNameAndLabelAreSyncOrThrow } from 'src/engine/metadata-modules/object-metadata/utils/validate-object-metadata-sync-label-name.util'; +import { ObjectMetadataMigrationService } from 'src/engine/metadata-modules/object-metadata/services/object-metadata-migration.service'; +import { ObjectMetadataRelatedRecordsService } from 'src/engine/metadata-modules/object-metadata/services/object-metadata-related-records.service'; +import { ObjectMetadataRelationService } from 'src/engine/metadata-modules/object-metadata/services/object-metadata-relation.service'; +import { buildDefaultFieldsForCustomObject } from 'src/engine/metadata-modules/object-metadata/utils/build-default-fields-for-custom-object.util'; import { - RelationMetadataEntity, - RelationMetadataType, - RelationOnDeleteAction, -} from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; -import { RelationToDelete } from 'src/engine/metadata-modules/relation-metadata/types/relation-to-delete'; + validateNameAndLabelAreSyncOrThrow, + validateNameSingularAndNamePluralAreDifferentOrThrow, + validateObjectMetadataInputOrThrow, +} from 'src/engine/metadata-modules/object-metadata/utils/validate-object-metadata-input.util'; import { RemoteTableRelationsService } from 'src/engine/metadata-modules/remote-server/remote-table/remote-table-relations/remote-table-relations.service'; import { mapUdtNameToFieldType } from 'src/engine/metadata-modules/remote-server/remote-table/utils/udt-name-mapper.util'; import { SearchService } from 'src/engine/metadata-modules/search/search.service'; import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/services/workspace-metadata-version.service'; -import { fieldMetadataTypeToColumnType } from 'src/engine/metadata-modules/workspace-migration/utils/field-metadata-type-to-column-type.util'; -import { generateMigrationName } from 'src/engine/metadata-modules/workspace-migration/utils/generate-migration-name.util'; -import { - WorkspaceMigrationColumnActionType, - WorkspaceMigrationColumnDrop, - WorkspaceMigrationTableAction, - WorkspaceMigrationTableActionType, -} from 'src/engine/metadata-modules/workspace-migration/workspace-migration.entity'; -import { WorkspaceMigrationFactory } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.factory'; -import { WorkspaceMigrationService } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.service'; -import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; import { computeObjectTargetTable } from 'src/engine/utils/compute-object-target-table.util'; -import { computeTableName } from 'src/engine/utils/compute-table-name.util'; import { WorkspaceMigrationRunnerService } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.service'; -import { - ACTIVITY_TARGET_STANDARD_FIELD_IDS, - ATTACHMENT_STANDARD_FIELD_IDS, - BASE_OBJECT_STANDARD_FIELD_IDS, - CUSTOM_OBJECT_STANDARD_FIELD_IDS, - FAVORITE_STANDARD_FIELD_IDS, - NOTE_TARGET_STANDARD_FIELD_IDS, - TASK_TARGET_STANDARD_FIELD_IDS, - TIMELINE_ACTIVITY_STANDARD_FIELD_IDS, -} from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; -import { - createForeignKeyDeterministicUuid, - createRelationDeterministicUuid, -} from 'src/engine/workspace-manager/workspace-sync-metadata/utils/create-deterministic-uuid.util'; import { isSearchableFieldType } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/is-searchable-field.util'; -import { FavoriteWorkspaceEntity } from 'src/modules/favorite/standard-objects/favorite.workspace-entity'; -import { ViewWorkspaceEntity } from 'src/modules/view/standard-objects/view.workspace-entity'; import { ObjectMetadataEntity } from './object-metadata.entity'; @@ -82,20 +46,14 @@ export class ObjectMetadataService extends TypeOrmQueryService, - @InjectRepository(RelationMetadataEntity, 'metadata') - private readonly relationMetadataRepository: Repository, - private readonly remoteTableRelationsService: RemoteTableRelationsService, - private readonly dataSourceService: DataSourceService, - private readonly typeORMService: TypeORMService, - private readonly workspaceMigrationService: WorkspaceMigrationService, - private readonly featureFlagService: FeatureFlagService, private readonly workspaceMigrationRunnerService: WorkspaceMigrationRunnerService, private readonly workspaceMetadataVersionService: WorkspaceMetadataVersionService, - private readonly twentyORMGlobalManager: TwentyORMGlobalManager, private readonly searchService: SearchService, - private readonly workspaceMigrationFactory: WorkspaceMigrationFactory, + private readonly objectMetadataRelationService: ObjectMetadataRelationService, + private readonly objectMetadataMigrationService: ObjectMetadataMigrationService, + private readonly objectMetadataRelatedRecordsService: ObjectMetadataRelatedRecordsService, ) { super(objectMetadataRepository); } @@ -115,75 +73,6 @@ export class ObjectMetadataService extends TypeOrmQueryService { - const objectMetadata = await this.objectMetadataRepository.findOne({ - relations: [ - 'fromRelations.fromFieldMetadata', - 'fromRelations.toFieldMetadata', - 'toRelations.fromFieldMetadata', - 'toRelations.toFieldMetadata', - 'fromRelations.fromObjectMetadata', - 'fromRelations.toObjectMetadata', - 'toRelations.fromObjectMetadata', - 'toRelations.toObjectMetadata', - ], - where: { - id: input.id, - workspaceId, - }, - }); - - if (!objectMetadata) { - throw new ObjectMetadataException( - 'Object does not exist', - ObjectMetadataExceptionCode.OBJECT_METADATA_NOT_FOUND, - ); - } - - // DELETE RELATIONS - if (objectMetadata.isRemote) { - await this.remoteTableRelationsService.deleteForeignKeysMetadataAndCreateMigrations( - objectMetadata.workspaceId, - objectMetadata, - ); - } else { - await this.deleteAllRelationsAndDropTable(objectMetadata, workspaceId); - } - - // DELETE VIEWS - const viewRepository = - await this.twentyORMGlobalManager.getRepositoryForWorkspace( - workspaceId, - 'view', - ); - - const views = await viewRepository.find({ - where: { - objectMetadataId: objectMetadata.id, - }, - }); - - if (views.length > 0) { - await viewRepository.delete(views.map((view) => view.id)); - } - - // DELETE OBJECT - await this.objectMetadataRepository.delete(objectMetadata.id); - - await this.workspaceMigrationRunnerService.executeMigrationFromPendingMigrations( - workspaceId, - ); - - await this.workspaceMetadataVersionService.incrementMetadataVersion( - workspaceId, - ); - - return objectMetadata; - } - override async createOne( objectMetadataInput: CreateObjectInput, ): Promise { @@ -194,15 +83,10 @@ export class ObjectMetadataService extends TypeOrmQueryService { - if (field.name === 'id' || field.name === 'deletedAt') { - return; - } - - await workspaceDataSource?.query( - `INSERT INTO ${dataSourceMetadata.schema}."viewField" - ("fieldMetadataId", "position", "isVisible", "size", "viewId") - VALUES ('${field.id}', '${index - 1}', true, 180, '${ - view[0].id - }') RETURNING *`, - ); - }); - - await this.createViewWorkspaceFavorite( - objectMetadataInput.workspaceId, - view[0].id, + await this.objectMetadataRelatedRecordsService.createObjectRelatedRecords( + createdObjectMetadata, ); await this.workspaceMetadataVersionService.incrementMetadataVersion( @@ -451,8 +205,9 @@ export class ObjectMetadataService extends TypeOrmQueryService, - ): Promise { - return this.objectMetadataRepository.findOne({ + ): Promise { + const objectMetadata = await this.objectMetadataRepository.findOne({ relations: [ - 'fields', - 'fields.fromRelationMetadata', - 'fields.toRelationMetadata', + 'fromRelations.fromFieldMetadata', + 'fromRelations.toFieldMetadata', + 'toRelations.fromFieldMetadata', + 'toRelations.toFieldMetadata', + 'fromRelations.fromObjectMetadata', + 'fromRelations.toObjectMetadata', + 'toRelations.fromObjectMetadata', + 'toRelations.toObjectMetadata', ], - ...options, where: { - ...options.where, + id: input.id, workspaceId, }, }); - } - public async findManyWithinWorkspace( - workspaceId: string, - options?: FindManyOptions, - ) { - return this.objectMetadataRepository.find({ - relations: [ - 'fields.object', - 'fields', - 'fields.fromRelationMetadata', - 'fields.toRelationMetadata', - 'fields.fromRelationMetadata.toObjectMetadata', - ], - ...options, - where: { - ...options?.where, + if (!objectMetadata) { + throw new ObjectMetadataException( + 'Object does not exist', + ObjectMetadataExceptionCode.OBJECT_METADATA_NOT_FOUND, + ); + } + + if (objectMetadata.isRemote) { + await this.remoteTableRelationsService.deleteForeignKeysMetadataAndCreateMigrations( + objectMetadata.workspaceId, + objectMetadata, + ); + } else { + await this.objectMetadataMigrationService.deleteAllRelationsAndDropTable( + objectMetadata, workspaceId, - }, - }); + ); + } + + await this.objectMetadataRelatedRecordsService.deleteObjectViews( + objectMetadata, + workspaceId, + ); + + await this.workspaceMigrationRunnerService.executeMigrationFromPendingMigrations( + workspaceId, + ); + + await this.objectMetadataRepository.delete(objectMetadata.id); + + await this.workspaceMetadataVersionService.incrementMetadataVersion( + workspaceId, + ); + + return objectMetadata; } public async findMany(options?: FindManyOptions) { @@ -557,6 +335,26 @@ export class ObjectMetadataService extends TypeOrmQueryService, + ): Promise { + return this.findManyWithinWorkspace(workspaceId, options)[0] ?? null; + } + + public async findManyWithinWorkspace( + workspaceId: string, + options?: FindManyOptions, + ) { + return this.findMany({ + ...options, + where: { + ...options?.where, + workspaceId, + }, + }); + } + public async deleteObjectsMetadata(workspaceId: string) { await this.objectMetadataRepository.delete({ workspaceId }); await this.workspaceMetadataVersionService.incrementMetadataVersion( @@ -564,859 +362,36 @@ export class ObjectMetadataService extends TypeOrmQueryService - | undefined, - ) { - const activityTargetObjectMetadata = - await this.objectMetadataRepository.findOneByOrFail({ - nameSingular: 'activityTarget', - workspaceId: workspaceId, - }); - - await this.fieldMetadataRepository.save( - // Foreign key - { - standardId: createForeignKeyDeterministicUuid({ - objectId: createdObjectMetadata.id, - standardId: ACTIVITY_TARGET_STANDARD_FIELD_IDS.custom, - }), - objectMetadataId: activityTargetObjectMetadata.id, - workspaceId: workspaceId, - isCustom: false, - isActive: true, - type: objectPrimaryKeyType, - name: `${createdObjectMetadata.nameSingular}Id`, - label: `${createdObjectMetadata.labelSingular} ID (foreign key)`, - description: `ActivityTarget ${createdObjectMetadata.labelSingular} id foreign key`, - icon: undefined, - isNullable: true, - isSystem: true, - defaultValue: undefined, - settings: { ...objectPrimaryKeyFieldSettings, isForeignKey: true }, - }, - ); - - const activityTargetRelationFieldMetadata = - await this.fieldMetadataRepository.save([ - // FROM - { - standardId: CUSTOM_OBJECT_STANDARD_FIELD_IDS.activityTargets, - objectMetadataId: createdObjectMetadata.id, - workspaceId: workspaceId, - isCustom: false, - isActive: true, - isSystem: true, - type: FieldMetadataType.RELATION, - name: 'activityTargets', - label: 'Activities', - description: `Activities tied to the ${createdObjectMetadata.labelSingular}`, - icon: 'IconCheckbox', - isNullable: true, - }, - // TO - { - standardId: createRelationDeterministicUuid({ - objectId: createdObjectMetadata.id, - standardId: ACTIVITY_TARGET_STANDARD_FIELD_IDS.custom, - }), - objectMetadataId: activityTargetObjectMetadata.id, - workspaceId: workspaceId, - isCustom: false, - isActive: true, - isSystem: true, - type: FieldMetadataType.RELATION, - name: createdObjectMetadata.nameSingular, - label: createdObjectMetadata.labelSingular, - description: `ActivityTarget ${createdObjectMetadata.labelSingular}`, - icon: 'IconBuildingSkyscraper', - isNullable: true, - }, - ]); - - const activityTargetRelationFieldMetadataMap = - activityTargetRelationFieldMetadata.reduce( - (acc, fieldMetadata: FieldMetadataEntity) => { - if (fieldMetadata.type === FieldMetadataType.RELATION) { - acc[fieldMetadata.objectMetadataId] = fieldMetadata; - } - - return acc; - }, - {}, - ); - - await this.relationMetadataRepository.save([ - { - workspaceId: workspaceId, - relationType: RelationMetadataType.ONE_TO_MANY, - fromObjectMetadataId: createdObjectMetadata.id, - toObjectMetadataId: activityTargetObjectMetadata.id, - fromFieldMetadataId: - activityTargetRelationFieldMetadataMap[createdObjectMetadata.id].id, - toFieldMetadataId: - activityTargetRelationFieldMetadataMap[ - activityTargetObjectMetadata.id - ].id, - onDeleteAction: RelationOnDeleteAction.CASCADE, - }, - ]); - - return { activityTargetObjectMetadata }; - } - - private async createNoteTargetRelation( - workspaceId: string, - createdObjectMetadata: ObjectMetadataEntity, - objectPrimaryKeyType: FieldMetadataType, - objectPrimaryKeyFieldSettings: - | FieldMetadataSettings - | undefined, - ) { - const noteTargetObjectMetadata = - await this.objectMetadataRepository.findOneByOrFail({ - nameSingular: 'noteTarget', - workspaceId: workspaceId, - }); - - await this.fieldMetadataRepository.save( - // Foreign key - { - standardId: createForeignKeyDeterministicUuid({ - objectId: createdObjectMetadata.id, - standardId: NOTE_TARGET_STANDARD_FIELD_IDS.custom, - }), - objectMetadataId: noteTargetObjectMetadata.id, - workspaceId: workspaceId, - isCustom: false, - isActive: true, - type: objectPrimaryKeyType, - name: `${createdObjectMetadata.nameSingular}Id`, - label: `${createdObjectMetadata.labelSingular} ID (foreign key)`, - description: `NoteTarget ${createdObjectMetadata.labelSingular} id foreign key`, - icon: undefined, - isNullable: true, - isSystem: true, - defaultValue: undefined, - settings: { ...objectPrimaryKeyFieldSettings, isForeignKey: true }, - }, - ); - - const noteTargetRelationFieldMetadata = - await this.fieldMetadataRepository.save([ - // FROM - { - standardId: CUSTOM_OBJECT_STANDARD_FIELD_IDS.noteTargets, - objectMetadataId: createdObjectMetadata.id, - workspaceId: workspaceId, - isCustom: false, - isActive: true, - type: FieldMetadataType.RELATION, - name: 'noteTargets', - label: 'Notes', - description: `Notes tied to the ${createdObjectMetadata.labelSingular}`, - icon: 'IconNotes', - isNullable: true, - }, - // TO - { - standardId: createRelationDeterministicUuid({ - objectId: createdObjectMetadata.id, - standardId: NOTE_TARGET_STANDARD_FIELD_IDS.custom, - }), - objectMetadataId: noteTargetObjectMetadata.id, - workspaceId: workspaceId, - isCustom: false, - isActive: true, - type: FieldMetadataType.RELATION, - name: createdObjectMetadata.nameSingular, - label: createdObjectMetadata.labelSingular, - description: `NoteTarget ${createdObjectMetadata.labelSingular}`, - icon: 'IconBuildingSkyscraper', - isNullable: true, - }, - ]); - - const noteTargetRelationFieldMetadataMap = - noteTargetRelationFieldMetadata.reduce( - (acc, fieldMetadata: FieldMetadataEntity) => { - if (fieldMetadata.type === FieldMetadataType.RELATION) { - acc[fieldMetadata.objectMetadataId] = fieldMetadata; - } - - return acc; - }, - {}, - ); - - await this.relationMetadataRepository.save([ - { - workspaceId: workspaceId, - relationType: RelationMetadataType.ONE_TO_MANY, - fromObjectMetadataId: createdObjectMetadata.id, - toObjectMetadataId: noteTargetObjectMetadata.id, - fromFieldMetadataId: - noteTargetRelationFieldMetadataMap[createdObjectMetadata.id].id, - toFieldMetadataId: - noteTargetRelationFieldMetadataMap[noteTargetObjectMetadata.id].id, - onDeleteAction: RelationOnDeleteAction.CASCADE, - }, - ]); - - return { noteTargetObjectMetadata }; - } - - private async createTaskTargetRelation( - workspaceId: string, - createdObjectMetadata: ObjectMetadataEntity, - objectPrimaryKeyType: FieldMetadataType, - objectPrimaryKeyFieldSettings: - | FieldMetadataSettings - | undefined, - ) { - const taskTargetObjectMetadata = - await this.objectMetadataRepository.findOneByOrFail({ - nameSingular: 'taskTarget', - workspaceId: workspaceId, - }); - - await this.fieldMetadataRepository.save( - // Foreign key - { - standardId: createForeignKeyDeterministicUuid({ - objectId: createdObjectMetadata.id, - standardId: TASK_TARGET_STANDARD_FIELD_IDS.custom, - }), - objectMetadataId: taskTargetObjectMetadata.id, - workspaceId: workspaceId, - isCustom: false, - isActive: true, - type: objectPrimaryKeyType, - name: `${createdObjectMetadata.nameSingular}Id`, - label: `${createdObjectMetadata.labelSingular} ID (foreign key)`, - description: `TaskTarget ${createdObjectMetadata.labelSingular} id foreign key`, - icon: undefined, - isNullable: true, - isSystem: true, - defaultValue: undefined, - settings: { ...objectPrimaryKeyFieldSettings, isForeignKey: true }, - }, - ); - - const taskTargetRelationFieldMetadata = - await this.fieldMetadataRepository.save([ - // FROM - { - standardId: CUSTOM_OBJECT_STANDARD_FIELD_IDS.taskTargets, - objectMetadataId: createdObjectMetadata.id, - workspaceId: workspaceId, - isCustom: false, - isActive: true, - type: FieldMetadataType.RELATION, - name: 'taskTargets', - label: 'Tasks', - description: `Tasks tied to the ${createdObjectMetadata.labelSingular}`, - icon: 'IconCheckbox', - isNullable: true, - }, - // TO - { - standardId: createRelationDeterministicUuid({ - objectId: createdObjectMetadata.id, - standardId: TASK_TARGET_STANDARD_FIELD_IDS.custom, - }), - objectMetadataId: taskTargetObjectMetadata.id, - workspaceId: workspaceId, - isCustom: false, - isActive: true, - type: FieldMetadataType.RELATION, - name: createdObjectMetadata.nameSingular, - label: createdObjectMetadata.labelSingular, - description: `TaskTarget ${createdObjectMetadata.labelSingular}`, - icon: 'IconBuildingSkyscraper', - isNullable: true, - }, - ]); - - const taskTargetRelationFieldMetadataMap = - taskTargetRelationFieldMetadata.reduce( - (acc, fieldMetadata: FieldMetadataEntity) => { - if (fieldMetadata.type === FieldMetadataType.RELATION) { - acc[fieldMetadata.objectMetadataId] = fieldMetadata; - } - - return acc; - }, - {}, - ); - - await this.relationMetadataRepository.save([ - { - workspaceId: workspaceId, - relationType: RelationMetadataType.ONE_TO_MANY, - fromObjectMetadataId: createdObjectMetadata.id, - toObjectMetadataId: taskTargetObjectMetadata.id, - fromFieldMetadataId: - taskTargetRelationFieldMetadataMap[createdObjectMetadata.id].id, - toFieldMetadataId: - taskTargetRelationFieldMetadataMap[taskTargetObjectMetadata.id].id, - onDeleteAction: RelationOnDeleteAction.CASCADE, - }, - ]); - - return { taskTargetObjectMetadata }; - } - - private async createAttachmentRelation( - workspaceId: string, - createdObjectMetadata: ObjectMetadataEntity, - objectPrimaryKeyType: FieldMetadataType, - objectPrimaryKeyFieldSettings: - | FieldMetadataSettings - | undefined, - ) { - const attachmentObjectMetadata = - await this.objectMetadataRepository.findOneByOrFail({ - nameSingular: 'attachment', - workspaceId: workspaceId, - }); - - await this.fieldMetadataRepository.save( - // Foreign key - { - standardId: createForeignKeyDeterministicUuid({ - objectId: createdObjectMetadata.id, - standardId: ATTACHMENT_STANDARD_FIELD_IDS.custom, - }), - objectMetadataId: attachmentObjectMetadata.id, - workspaceId: workspaceId, - isCustom: false, - isActive: true, - type: objectPrimaryKeyType, - name: `${createdObjectMetadata.nameSingular}Id`, - label: `${createdObjectMetadata.labelSingular} ID (foreign key)`, - description: `Attachment ${createdObjectMetadata.labelSingular} id foreign key`, - icon: undefined, - isNullable: true, - isSystem: true, - defaultValue: undefined, - settings: { ...objectPrimaryKeyFieldSettings, isForeignKey: true }, - }, - ); - - const attachmentRelationFieldMetadata = - await this.fieldMetadataRepository.save([ - // FROM - { - standardId: CUSTOM_OBJECT_STANDARD_FIELD_IDS.attachments, - objectMetadataId: createdObjectMetadata.id, - workspaceId: workspaceId, - isCustom: false, - isActive: true, - type: FieldMetadataType.RELATION, - name: 'attachments', - label: 'Attachments', - description: `Attachments tied to the ${createdObjectMetadata.labelSingular}`, - icon: 'IconFileImport', - isNullable: true, - }, - // TO - { - standardId: createRelationDeterministicUuid({ - objectId: createdObjectMetadata.id, - standardId: ATTACHMENT_STANDARD_FIELD_IDS.custom, - }), - objectMetadataId: attachmentObjectMetadata.id, - workspaceId: workspaceId, - isCustom: false, - isActive: true, - type: FieldMetadataType.RELATION, - name: createdObjectMetadata.nameSingular, - label: createdObjectMetadata.labelSingular, - description: `Attachment ${createdObjectMetadata.labelSingular}`, - icon: 'IconBuildingSkyscraper', - isNullable: true, - }, - ]); - - const attachmentRelationFieldMetadataMap = - attachmentRelationFieldMetadata.reduce( - (acc, fieldMetadata: FieldMetadataEntity) => { - if (fieldMetadata.type === FieldMetadataType.RELATION) { - acc[fieldMetadata.objectMetadataId] = fieldMetadata; - } - - return acc; - }, - {}, - ); - - await this.relationMetadataRepository.save([ - { - workspaceId: workspaceId, - relationType: RelationMetadataType.ONE_TO_MANY, - fromObjectMetadataId: createdObjectMetadata.id, - toObjectMetadataId: attachmentObjectMetadata.id, - fromFieldMetadataId: - attachmentRelationFieldMetadataMap[createdObjectMetadata.id].id, - toFieldMetadataId: - attachmentRelationFieldMetadataMap[attachmentObjectMetadata.id].id, - onDeleteAction: RelationOnDeleteAction.CASCADE, - }, - ]); - - return { attachmentObjectMetadata }; - } - - private async createTimelineActivityRelation( - workspaceId: string, - createdObjectMetadata: ObjectMetadataEntity, - objectPrimaryKeyType: FieldMetadataType, - objectPrimaryKeyFieldSettings: - | FieldMetadataSettings - | undefined, - ) { - const timelineActivityObjectMetadata = - await this.objectMetadataRepository.findOneByOrFail({ - nameSingular: 'timelineActivity', - workspaceId: workspaceId, - }); - - await this.fieldMetadataRepository.save( - // Foreign key - { - standardId: createForeignKeyDeterministicUuid({ - objectId: createdObjectMetadata.id, - standardId: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.custom, - }), - objectMetadataId: timelineActivityObjectMetadata.id, - workspaceId: workspaceId, - isCustom: false, - isActive: true, - type: objectPrimaryKeyType, - name: `${createdObjectMetadata.nameSingular}Id`, - label: `${createdObjectMetadata.labelSingular} ID (foreign key)`, - description: `Timeline Activity ${createdObjectMetadata.labelSingular} id foreign key`, - icon: undefined, - isNullable: true, - isSystem: true, - defaultValue: undefined, - settings: { ...objectPrimaryKeyFieldSettings, isForeignKey: true }, - }, - ); - - const timelineActivityRelationFieldMetadata = - await this.fieldMetadataRepository.save([ - // FROM - { - standardId: CUSTOM_OBJECT_STANDARD_FIELD_IDS.timelineActivities, - objectMetadataId: createdObjectMetadata.id, - workspaceId: workspaceId, - isCustom: false, - isActive: true, - type: FieldMetadataType.RELATION, - name: 'timelineActivities', - label: 'Timeline Activities', - description: `Timeline Activities tied to the ${createdObjectMetadata.labelSingular}`, - icon: 'IconIconTimelineEvent', - isNullable: true, - isSystem: true, - }, - // TO - { - standardId: createRelationDeterministicUuid({ - objectId: createdObjectMetadata.id, - standardId: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.custom, - }), - objectMetadataId: timelineActivityObjectMetadata.id, - workspaceId: workspaceId, - isCustom: false, - isActive: true, - type: FieldMetadataType.RELATION, - name: createdObjectMetadata.nameSingular, - label: createdObjectMetadata.labelSingular, - description: `Timeline Activity ${createdObjectMetadata.labelSingular}`, - icon: 'IconTimeline', - isNullable: true, - }, - ]); - - const timelineActivityRelationFieldMetadataMap = - timelineActivityRelationFieldMetadata.reduce( - (acc, fieldMetadata: FieldMetadataEntity) => { - if (fieldMetadata.type === FieldMetadataType.RELATION) { - acc[fieldMetadata.objectMetadataId] = fieldMetadata; - } - - return acc; - }, - {}, - ); - - await this.relationMetadataRepository.save([ - { - workspaceId: workspaceId, - relationType: RelationMetadataType.ONE_TO_MANY, - fromObjectMetadataId: createdObjectMetadata.id, - toObjectMetadataId: timelineActivityObjectMetadata.id, - fromFieldMetadataId: - timelineActivityRelationFieldMetadataMap[createdObjectMetadata.id].id, - toFieldMetadataId: - timelineActivityRelationFieldMetadataMap[ - timelineActivityObjectMetadata.id - ].id, - onDeleteAction: RelationOnDeleteAction.CASCADE, - }, - ]); - - return { timelineActivityObjectMetadata }; - } - - private async createFavoriteRelation( - workspaceId: string, - createdObjectMetadata: ObjectMetadataEntity, - objectPrimaryKeyType: FieldMetadataType, - objectPrimaryKeyFieldSettings: - | FieldMetadataSettings - | undefined, - ) { - const favoriteObjectMetadata = - await this.objectMetadataRepository.findOneByOrFail({ - nameSingular: 'favorite', - workspaceId: workspaceId, - }); - - await this.fieldMetadataRepository.save( - // Foreign key - { - standardId: createForeignKeyDeterministicUuid({ - objectId: createdObjectMetadata.id, - standardId: FAVORITE_STANDARD_FIELD_IDS.custom, - }), - objectMetadataId: favoriteObjectMetadata.id, - workspaceId: workspaceId, - isCustom: false, - isActive: true, - type: objectPrimaryKeyType, - name: `${createdObjectMetadata.nameSingular}Id`, - label: `${createdObjectMetadata.labelSingular} ID (foreign key)`, - description: `Favorite ${createdObjectMetadata.labelSingular} id foreign key`, - icon: undefined, - isNullable: true, - isSystem: true, - defaultValue: undefined, - settings: { ...objectPrimaryKeyFieldSettings, isForeignKey: true }, - }, - ); - - const favoriteRelationFieldMetadata = - await this.fieldMetadataRepository.save([ - // FROM - { - standardId: CUSTOM_OBJECT_STANDARD_FIELD_IDS.favorites, - objectMetadataId: createdObjectMetadata.id, - workspaceId: workspaceId, - isCustom: false, - isActive: true, - isSystem: true, - type: FieldMetadataType.RELATION, - name: 'favorites', - label: 'Favorites', - description: `Favorites tied to the ${createdObjectMetadata.labelSingular}`, - icon: 'IconHeart', - isNullable: true, - }, - // TO - { - standardId: createRelationDeterministicUuid({ - objectId: createdObjectMetadata.id, - standardId: FAVORITE_STANDARD_FIELD_IDS.custom, - }), - objectMetadataId: favoriteObjectMetadata.id, - workspaceId: workspaceId, - isCustom: false, - isActive: true, - type: FieldMetadataType.RELATION, - name: createdObjectMetadata.nameSingular, - label: createdObjectMetadata.labelSingular, - description: `Favorite ${createdObjectMetadata.labelSingular}`, - icon: 'IconHeart', - isNullable: true, - }, - ]); - - const favoriteRelationFieldMetadataMap = - favoriteRelationFieldMetadata.reduce( - (acc, fieldMetadata: FieldMetadataEntity) => { - if (fieldMetadata.type === FieldMetadataType.RELATION) { - acc[fieldMetadata.objectMetadataId] = fieldMetadata; - } - - return acc; - }, - {}, - ); - - await this.relationMetadataRepository.save([ - { - workspaceId: workspaceId, - relationType: RelationMetadataType.ONE_TO_MANY, - fromObjectMetadataId: createdObjectMetadata.id, - toObjectMetadataId: favoriteObjectMetadata.id, - fromFieldMetadataId: - favoriteRelationFieldMetadataMap[createdObjectMetadata.id].id, - toFieldMetadataId: - favoriteRelationFieldMetadataMap[favoriteObjectMetadata.id].id, - onDeleteAction: RelationOnDeleteAction.CASCADE, - }, - ]); - - return { favoriteObjectMetadata }; - } - - private async deleteAllRelationsAndDropTable( - objectMetadata: ObjectMetadataEntity, - workspaceId: string, - ) { - const relationsToDelete: RelationToDelete[] = []; - - // TODO: Most of this logic should be moved to relation-metadata.service.ts - for (const relation of [ - ...objectMetadata.fromRelations, - ...objectMetadata.toRelations, - ]) { - relationsToDelete.push({ - id: relation.id, - fromFieldMetadataId: relation.fromFieldMetadata.id, - toFieldMetadataId: relation.toFieldMetadata.id, - fromFieldMetadataName: relation.fromFieldMetadata.name, - toFieldMetadataName: relation.toFieldMetadata.name, - fromObjectMetadataId: relation.fromObjectMetadata.id, - toObjectMetadataId: relation.toObjectMetadata.id, - fromObjectName: relation.fromObjectMetadata.nameSingular, - toObjectName: relation.toObjectMetadata.nameSingular, - toFieldMetadataIsCustom: relation.toFieldMetadata.isCustom, - toObjectMetadataIsCustom: relation.toObjectMetadata.isCustom, - direction: - relation.fromObjectMetadata.nameSingular === - objectMetadata.nameSingular - ? 'from' - : 'to', - }); - } - - if (relationsToDelete.length > 0) { - await this.relationMetadataRepository.delete( - relationsToDelete.map((relation) => relation.id), - ); - } - - for (const relationToDelete of relationsToDelete) { - const foreignKeyFieldsToDelete = await this.fieldMetadataRepository.find({ - where: { - name: `${relationToDelete.toFieldMetadataName}Id`, - objectMetadataId: relationToDelete.toObjectMetadataId, - workspaceId, - }, - }); - - const foreignKeyFieldsToDeleteIds = foreignKeyFieldsToDelete.map( - (field) => field.id, - ); - - await this.fieldMetadataRepository.delete([ - ...foreignKeyFieldsToDeleteIds, - relationToDelete.fromFieldMetadataId, - relationToDelete.toFieldMetadataId, - ]); - - if (relationToDelete.direction === 'from') { - await this.workspaceMigrationService.createCustomMigration( - generateMigrationName( - `delete-${relationToDelete.fromObjectName}-${relationToDelete.toObjectName}`, + const createdRelatedObjectMetadata = await Promise.all( + relatedObjectTypes.map(async (relationType) => + this.objectMetadataRelationService.createMetadata( + objectMetadataInput.workspaceId, + createdObjectMetadata, + mapUdtNameToFieldType( + objectMetadataInput.primaryKeyColumnType ?? 'uuid', ), - workspaceId, - [ - { - name: computeTableName( - relationToDelete.toObjectName, - relationToDelete.toObjectMetadataIsCustom, - ), - action: WorkspaceMigrationTableActionType.ALTER, - columns: [ - { - action: WorkspaceMigrationColumnActionType.DROP, - columnName: computeColumnName( - relationToDelete.toFieldMetadataName, - { isForeignKey: true }, - ), - } satisfies WorkspaceMigrationColumnDrop, - ], - }, - ], - ); - } - } - - // DROP TABLE - await this.workspaceMigrationService.createCustomMigration( - generateMigrationName(`delete-${objectMetadata.nameSingular}`), - workspaceId, - [ - { - name: computeObjectTargetTable(objectMetadata), - action: WorkspaceMigrationTableActionType.DROP, - }, - ], - ); - } - - private async updateObjectRelationships( - objectMetadataId: string, - isActive: boolean, - ) { - const affectedRelations = await this.relationMetadataRepository.find({ - where: [ - { fromObjectMetadataId: objectMetadataId }, - { toObjectMetadataId: objectMetadataId }, - ], - }); - - const affectedFieldIds = affectedRelations.reduce( - (acc, { fromFieldMetadataId, toFieldMetadataId }) => { - acc.push(fromFieldMetadataId, toFieldMetadataId); - - return acc; - }, - [] as string[], + objectMetadataInput.primaryKeyFieldMetadataSettings, + relationType, + ), + ), ); - if (affectedFieldIds.length > 0) { - await this.fieldMetadataRepository.update( - { id: In(affectedFieldIds) }, - { isActive: isActive }, - ); - } - } - - private async createViewWorkspaceFavorite( - workspaceId: string, - viewId: string, - ) { - const favoriteRepository = - await this.twentyORMGlobalManager.getRepositoryForWorkspace( - workspaceId, - 'favorite', - ); - - const favoriteCount = await favoriteRepository.count(); - - return favoriteRepository.insert( - favoriteRepository.create({ - viewId, - position: favoriteCount, - }), + await this.objectMetadataMigrationService.createRelationMigrations( + createdObjectMetadata, + createdRelatedObjectMetadata, ); } @@ -1433,12 +408,12 @@ export class ObjectMetadataService extends TypeOrmQueryService { - const relatedObject = await this.objectMetadataRepository.findOneBy({ - id: fieldWihStandardRelation.objectMetadataId, - workspaceId: updatedObjectMetadata.workspaceId, - }); - - if (relatedObject) { - await this.fieldMetadataRepository.update( - { - name: existingObjectMetadata.nameSingular, - label: existingObjectMetadata.labelSingular, - }, - { - name: updatedObjectMetadata.nameSingular, - label: updatedObjectMetadata.labelSingular, - }, - ); - - const relationTableName = computeObjectTargetTable(relatedObject); - const columnName = `${existingObjectMetadata.nameSingular}Id`; - const columnType = fieldMetadataTypeToColumnType( - fieldWihStandardRelation.type, - ); - - await this.workspaceMigrationService.createCustomMigration( - generateMigrationName( - `rename-${existingObjectMetadata.nameSingular}-to-${updatedObjectMetadata.nameSingular}-in-${relatedObject.nameSingular}`, - ), - updatedObjectMetadata.workspaceId, - [ - { - name: relationTableName, - action: WorkspaceMigrationTableActionType.ALTER, - columns: [ - { - action: WorkspaceMigrationColumnActionType.ALTER, - currentColumnDefinition: { - columnName, - columnType, - isNullable: true, - defaultValue: null, - }, - alteredColumnDefinition: { - columnName: `${updatedObjectMetadata.nameSingular}Id`, - columnType, - isNullable: true, - defaultValue: null, - }, - }, - ], - }, - ], - ); - } - }), - ); - } - } - - private async updateObjectView( - updatedObjectMetadata: ObjectMetadataEntity, - workspaceId: string, - ) { - const dataSourceMetadata = - await this.dataSourceService.getLastDataSourceMetadataFromWorkspaceIdOrFail( - workspaceId, - ); - - const workspaceDataSource = - await this.typeORMService.connectToDataSource(dataSourceMetadata); - - await workspaceDataSource?.query( - `UPDATE ${dataSourceMetadata.schema}."view" - SET "name"=$1, "icon"=$2 WHERE "objectMetadataId"=$3 AND "key"=$4`, - [ - `All ${updatedObjectMetadata.labelPlural}`, - updatedObjectMetadata.icon, - updatedObjectMetadata.id, - 'INDEX', - ], - ); - } - private validatesNoOtherObjectWithSameNameExistsOrThrows = async ({ objectMetadataNameSingular, objectMetadataNamePlural, @@ -1635,18 +470,4 @@ export class ObjectMetadataService extends TypeOrmQueryService { - if ( - fullObjectMetadataAfterUpdate.nameSingular === - fullObjectMetadataAfterUpdate.namePlural - ) { - throw new ObjectMetadataException( - 'The singular and plural name cannot be the same for an object', - ObjectMetadataExceptionCode.INVALID_OBJECT_INPUT, - ); - } - }; } diff --git a/packages/twenty-server/src/engine/metadata-modules/object-metadata/services/object-metadata-migration.service.ts b/packages/twenty-server/src/engine/metadata-modules/object-metadata/services/object-metadata-migration.service.ts new file mode 100644 index 000000000..2cf079975 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/object-metadata/services/object-metadata-migration.service.ts @@ -0,0 +1,305 @@ +import { Injectable } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; + +import { Repository } from 'typeorm'; + +import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; +import { computeColumnName } from 'src/engine/metadata-modules/field-metadata/utils/compute-column-name.util'; +import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; +import { buildMigrationsForCustomObjectRelations } from 'src/engine/metadata-modules/object-metadata/utils/build-migrations-for-custom-object-relations.util'; +import { RelationMetadataEntity } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; +import { RelationToDelete } from 'src/engine/metadata-modules/relation-metadata/types/relation-to-delete'; +import { fieldMetadataTypeToColumnType } from 'src/engine/metadata-modules/workspace-migration/utils/field-metadata-type-to-column-type.util'; +import { generateMigrationName } from 'src/engine/metadata-modules/workspace-migration/utils/generate-migration-name.util'; +import { + WorkspaceMigrationColumnActionType, + WorkspaceMigrationColumnDrop, + WorkspaceMigrationTableAction, + WorkspaceMigrationTableActionType, +} from 'src/engine/metadata-modules/workspace-migration/workspace-migration.entity'; +import { WorkspaceMigrationFactory } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.factory'; +import { WorkspaceMigrationService } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.service'; +import { computeObjectTargetTable } from 'src/engine/utils/compute-object-target-table.util'; +import { computeTableName } from 'src/engine/utils/compute-table-name.util'; + +@Injectable() +export class ObjectMetadataMigrationService { + constructor( + @InjectRepository(ObjectMetadataEntity, 'metadata') + private readonly objectMetadataRepository: Repository, + @InjectRepository(FieldMetadataEntity, 'metadata') + private readonly fieldMetadataRepository: Repository, + @InjectRepository(RelationMetadataEntity, 'metadata') + private readonly relationMetadataRepository: Repository, + private readonly workspaceMigrationService: WorkspaceMigrationService, + private readonly workspaceMigrationFactory: WorkspaceMigrationFactory, + ) {} + + public async createObjectMigration( + createdObjectMetadata: ObjectMetadataEntity, + ) { + await this.workspaceMigrationService.createCustomMigration( + generateMigrationName(`create-${createdObjectMetadata.nameSingular}`), + createdObjectMetadata.workspaceId, + [ + { + name: computeObjectTargetTable(createdObjectMetadata), + action: WorkspaceMigrationTableActionType.CREATE, + } satisfies WorkspaceMigrationTableAction, + ], + ); + } + + public async createFieldMigrations( + createdObjectMetadata: ObjectMetadataEntity, + fieldMetadataCollection: FieldMetadataEntity[], + ) { + await this.workspaceMigrationService.createCustomMigration( + generateMigrationName( + `create-${createdObjectMetadata.nameSingular}-fields`, + ), + createdObjectMetadata.workspaceId, + [ + { + name: computeObjectTargetTable(createdObjectMetadata), + action: WorkspaceMigrationTableActionType.ALTER, + columns: fieldMetadataCollection.flatMap((fieldMetadata) => + this.workspaceMigrationFactory.createColumnActions( + WorkspaceMigrationColumnActionType.CREATE, + fieldMetadata, + ), + ), + }, + ], + ); + } + + public async createRelationMigrations( + createdObjectMetadata: ObjectMetadataEntity, + relatedObjectMetadataCollection: ObjectMetadataEntity[], + ) { + await this.workspaceMigrationService.createCustomMigration( + generateMigrationName( + `create-${createdObjectMetadata.nameSingular}-relations`, + ), + createdObjectMetadata.workspaceId, + buildMigrationsForCustomObjectRelations( + createdObjectMetadata, + relatedObjectMetadataCollection, + ), + ); + } + + public async createRenameTableMigration( + existingObjectMetadata: ObjectMetadataEntity, + objectMetadataForUpdate: ObjectMetadataEntity, + ) { + const newTargetTableName = computeObjectTargetTable( + objectMetadataForUpdate, + ); + const existingTargetTableName = computeObjectTargetTable( + existingObjectMetadata, + ); + + this.workspaceMigrationService.createCustomMigration( + generateMigrationName(`rename-${existingObjectMetadata.nameSingular}`), + objectMetadataForUpdate.workspaceId, + [ + { + name: existingTargetTableName, + newName: newTargetTableName, + action: WorkspaceMigrationTableActionType.ALTER, + }, + ], + ); + } + + public async createRelationsUpdatesMigrations( + existingObjectMetadata: ObjectMetadataEntity, + updatedObjectMetadata: ObjectMetadataEntity, + ) { + const existingTableName = computeObjectTargetTable(existingObjectMetadata); + const newTableName = computeObjectTargetTable(updatedObjectMetadata); + + if (existingTableName !== newTableName) { + const searchCriteria = { + isCustom: false, + settings: { + isForeignKey: true, + }, + name: `${existingObjectMetadata.nameSingular}Id`, + }; + + const fieldsWihStandardRelation = await this.fieldMetadataRepository.find( + { + where: { + isCustom: false, + settings: { + isForeignKey: true, + }, + name: `${existingObjectMetadata.nameSingular}Id`, + }, + }, + ); + + await this.fieldMetadataRepository.update(searchCriteria, { + name: `${updatedObjectMetadata.nameSingular}Id`, + }); + + await Promise.all( + fieldsWihStandardRelation.map(async (fieldWihStandardRelation) => { + const relatedObject = await this.objectMetadataRepository.findOneBy({ + id: fieldWihStandardRelation.objectMetadataId, + workspaceId: updatedObjectMetadata.workspaceId, + }); + + if (relatedObject) { + await this.fieldMetadataRepository.update( + { + name: existingObjectMetadata.nameSingular, + label: existingObjectMetadata.labelSingular, + }, + { + name: updatedObjectMetadata.nameSingular, + label: updatedObjectMetadata.labelSingular, + }, + ); + + const relationTableName = computeObjectTargetTable(relatedObject); + const columnName = `${existingObjectMetadata.nameSingular}Id`; + const columnType = fieldMetadataTypeToColumnType( + fieldWihStandardRelation.type, + ); + + await this.workspaceMigrationService.createCustomMigration( + generateMigrationName( + `rename-${existingObjectMetadata.nameSingular}-to-${updatedObjectMetadata.nameSingular}-in-${relatedObject.nameSingular}`, + ), + updatedObjectMetadata.workspaceId, + [ + { + name: relationTableName, + action: WorkspaceMigrationTableActionType.ALTER, + columns: [ + { + action: WorkspaceMigrationColumnActionType.ALTER, + currentColumnDefinition: { + columnName, + columnType, + isNullable: true, + defaultValue: null, + }, + alteredColumnDefinition: { + columnName: `${updatedObjectMetadata.nameSingular}Id`, + columnType, + isNullable: true, + defaultValue: null, + }, + }, + ], + }, + ], + ); + } + }), + ); + } + } + + public async deleteAllRelationsAndDropTable( + objectMetadata: ObjectMetadataEntity, + workspaceId: string, + ) { + const relationsToDelete: RelationToDelete[] = []; + + // TODO: Most of this logic should be moved to relation-metadata.service.ts + for (const relation of [ + ...objectMetadata.fromRelations, + ...objectMetadata.toRelations, + ]) { + relationsToDelete.push({ + id: relation.id, + fromFieldMetadataId: relation.fromFieldMetadata.id, + toFieldMetadataId: relation.toFieldMetadata.id, + fromFieldMetadataName: relation.fromFieldMetadata.name, + toFieldMetadataName: relation.toFieldMetadata.name, + fromObjectMetadataId: relation.fromObjectMetadata.id, + toObjectMetadataId: relation.toObjectMetadata.id, + fromObjectName: relation.fromObjectMetadata.nameSingular, + toObjectName: relation.toObjectMetadata.nameSingular, + toFieldMetadataIsCustom: relation.toFieldMetadata.isCustom, + toObjectMetadataIsCustom: relation.toObjectMetadata.isCustom, + direction: + relation.fromObjectMetadata.nameSingular === + objectMetadata.nameSingular + ? 'from' + : 'to', + }); + } + + if (relationsToDelete.length > 0) { + await this.relationMetadataRepository.delete( + relationsToDelete.map((relation) => relation.id), + ); + } + + for (const relationToDelete of relationsToDelete) { + const foreignKeyFieldsToDelete = await this.fieldMetadataRepository.find({ + where: { + name: `${relationToDelete.toFieldMetadataName}Id`, + objectMetadataId: relationToDelete.toObjectMetadataId, + workspaceId, + }, + }); + + const foreignKeyFieldsToDeleteIds = foreignKeyFieldsToDelete.map( + (field) => field.id, + ); + + await this.fieldMetadataRepository.delete([ + ...foreignKeyFieldsToDeleteIds, + relationToDelete.fromFieldMetadataId, + relationToDelete.toFieldMetadataId, + ]); + + if (relationToDelete.direction === 'from') { + await this.workspaceMigrationService.createCustomMigration( + generateMigrationName( + `delete-${relationToDelete.fromObjectName}-${relationToDelete.toObjectName}`, + ), + workspaceId, + [ + { + name: computeTableName( + relationToDelete.toObjectName, + relationToDelete.toObjectMetadataIsCustom, + ), + action: WorkspaceMigrationTableActionType.ALTER, + columns: [ + { + action: WorkspaceMigrationColumnActionType.DROP, + columnName: computeColumnName( + relationToDelete.toFieldMetadataName, + { isForeignKey: true }, + ), + } satisfies WorkspaceMigrationColumnDrop, + ], + }, + ], + ); + } + } + + // DROP TABLE + await this.workspaceMigrationService.createCustomMigration( + generateMigrationName(`delete-${objectMetadata.nameSingular}`), + workspaceId, + [ + { + name: computeObjectTargetTable(objectMetadata), + action: WorkspaceMigrationTableActionType.DROP, + }, + ], + ); + } +} diff --git a/packages/twenty-server/src/engine/metadata-modules/object-metadata/services/object-metadata-related-records.service.ts b/packages/twenty-server/src/engine/metadata-modules/object-metadata/services/object-metadata-related-records.service.ts new file mode 100644 index 000000000..bc1a10c0b --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/object-metadata/services/object-metadata-related-records.service.ts @@ -0,0 +1,118 @@ +import { Injectable } from '@nestjs/common'; + +import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; +import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager'; +import { FavoriteWorkspaceEntity } from 'src/modules/favorite/standard-objects/favorite.workspace-entity'; +import { ViewFieldWorkspaceEntity } from 'src/modules/view/standard-objects/view-field.workspace-entity'; +import { ViewWorkspaceEntity } from 'src/modules/view/standard-objects/view.workspace-entity'; + +@Injectable() +export class ObjectMetadataRelatedRecordsService { + constructor( + private readonly twentyORMGlobalManager: TwentyORMGlobalManager, + ) {} + + public async createObjectRelatedRecords( + objectMetadata: ObjectMetadataEntity, + ) { + const view = await this.createView(objectMetadata); + + await this.createViewFields(objectMetadata, view.id); + await this.createViewWorkspaceFavorite(objectMetadata.workspaceId, view.id); + } + + private async createView( + objectMetadata: ObjectMetadataEntity, + ): Promise { + const viewRepository = + await this.twentyORMGlobalManager.getRepositoryForWorkspace( + objectMetadata.workspaceId, + 'view', + ); + + return await viewRepository.save({ + objectMetadataId: objectMetadata.id, + type: 'table', + name: `All ${objectMetadata.labelPlural}`, + key: 'INDEX', + icon: objectMetadata.icon, + }); + } + + private async createViewFields( + objectMetadata: ObjectMetadataEntity, + viewId: string, + ): Promise { + const viewFieldRepository = + await this.twentyORMGlobalManager.getRepositoryForWorkspace( + objectMetadata.workspaceId, + 'viewField', + ); + + const viewFields = objectMetadata.fields + .filter((field) => field.name !== 'id' && field.name !== 'deletedAt') + .map((field, index) => ({ + fieldMetadataId: field.id, + position: index, + isVisible: true, + size: 180, + viewId: viewId, + })); + + await viewFieldRepository.insert(viewFields); + } + + private async createViewWorkspaceFavorite( + workspaceId: string, + viewId: string, + ): Promise { + const favoriteRepository = + await this.twentyORMGlobalManager.getRepositoryForWorkspace( + workspaceId, + 'favorite', + ); + + const favoriteCount = await favoriteRepository.count(); + + await favoriteRepository.insert( + favoriteRepository.create({ + viewId: viewId, + position: favoriteCount, + }), + ); + } + + public async updateObjectViews( + updatedObjectMetadata: ObjectMetadataEntity, + workspaceId: string, + ) { + const viewRepository = + await this.twentyORMGlobalManager.getRepositoryForWorkspace( + workspaceId, + 'view', + ); + + await viewRepository.update( + { objectMetadataId: updatedObjectMetadata.id, key: 'INDEX' }, + { + name: `All ${updatedObjectMetadata.labelPlural}`, + icon: updatedObjectMetadata.icon, + }, + ); + } + + public async deleteObjectViews( + objectMetadata: ObjectMetadataEntity, + workspaceId: string, + ) { + const viewRepository = + await this.twentyORMGlobalManager.getRepositoryForWorkspace( + workspaceId, + 'view', + ); + + await viewRepository.delete({ + objectMetadataId: objectMetadata.id, + }); + } +} diff --git a/packages/twenty-server/src/engine/metadata-modules/object-metadata/services/object-metadata-relation.service.ts b/packages/twenty-server/src/engine/metadata-modules/object-metadata/services/object-metadata-relation.service.ts new file mode 100644 index 000000000..a8054bdad --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/object-metadata/services/object-metadata-relation.service.ts @@ -0,0 +1,253 @@ +import { Injectable } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; + +import { In, Repository } from 'typeorm'; + +import { FieldMetadataSettings } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface'; + +import { + FieldMetadataEntity, + FieldMetadataType, +} from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; +import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; +import { + RelationMetadataEntity, + RelationMetadataType, + RelationOnDeleteAction, +} from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; +import { + CUSTOM_OBJECT_STANDARD_FIELD_IDS, + STANDARD_OBJECT_FIELD_IDS, +} from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; +import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons'; +import { + createForeignKeyDeterministicUuid, + createRelationDeterministicUuid, +} from 'src/engine/workspace-manager/workspace-sync-metadata/utils/create-deterministic-uuid.util'; +import { capitalize } from 'src/utils/capitalize'; + +@Injectable() +export class ObjectMetadataRelationService { + constructor( + @InjectRepository(ObjectMetadataEntity, 'metadata') + private readonly objectMetadataRepository: Repository, + @InjectRepository(FieldMetadataEntity, 'metadata') + private readonly fieldMetadataRepository: Repository, + @InjectRepository(RelationMetadataEntity, 'metadata') + private readonly relationMetadataRepository: Repository, + ) {} + + public async createMetadata( + workspaceId: string, + createdObjectMetadata: ObjectMetadataEntity, + objectPrimaryKeyType: FieldMetadataType, + objectPrimaryKeyFieldSettings: + | FieldMetadataSettings + | undefined, + relatedObjectMetadataName: string, + ) { + const relatedObjectMetadata = + await this.objectMetadataRepository.findOneByOrFail({ + nameSingular: relatedObjectMetadataName, + workspaceId: workspaceId, + }); + + await this.createForeignKeyFieldMetadata( + workspaceId, + createdObjectMetadata, + relatedObjectMetadata, + objectPrimaryKeyType, + objectPrimaryKeyFieldSettings, + ); + + const relationFieldMetadata = await this.createRelationFields( + workspaceId, + createdObjectMetadata, + relatedObjectMetadata, + ); + + await this.createRelationMetadata( + workspaceId, + createdObjectMetadata, + relatedObjectMetadata, + relationFieldMetadata, + ); + + return relatedObjectMetadata; + } + + private async createForeignKeyFieldMetadata( + workspaceId: string, + createdObjectMetadata: ObjectMetadataEntity, + relatedObjectMetadata: ObjectMetadataEntity, + objectPrimaryKeyType: FieldMetadataType, + objectPrimaryKeyFieldSettings: + | FieldMetadataSettings + | undefined, + ) { + const customStandardFieldId = + STANDARD_OBJECT_FIELD_IDS[relatedObjectMetadata.nameSingular].custom; + + if (!customStandardFieldId) { + throw new Error( + `Custom standard field ID not found for ${relatedObjectMetadata.nameSingular}`, + ); + } + + await this.fieldMetadataRepository.save({ + standardId: createForeignKeyDeterministicUuid({ + objectId: createdObjectMetadata.id, + standardId: customStandardFieldId, + }), + objectMetadataId: relatedObjectMetadata.id, + workspaceId: workspaceId, + isCustom: false, + isActive: true, + type: objectPrimaryKeyType, + name: `${createdObjectMetadata.nameSingular}Id`, + label: `${createdObjectMetadata.labelSingular} ID (foreign key)`, + description: `${relatedObjectMetadata.labelSingular} ${createdObjectMetadata.labelSingular} id foreign key`, + icon: undefined, + isNullable: true, + isSystem: true, + defaultValue: undefined, + settings: { ...objectPrimaryKeyFieldSettings, isForeignKey: true }, + }); + } + + private async createRelationFields( + workspaceId: string, + createdObjectMetadata: ObjectMetadataEntity, + relatedObjectMetadata: ObjectMetadataEntity, + ) { + return await this.fieldMetadataRepository.save([ + this.createFromField( + workspaceId, + createdObjectMetadata, + relatedObjectMetadata, + ), + this.createToField( + workspaceId, + createdObjectMetadata, + relatedObjectMetadata, + ), + ]); + } + + private createFromField( + workspaceId: string, + createdObjectMetadata: ObjectMetadataEntity, + relatedObjectMetadata: ObjectMetadataEntity, + ) { + const relationObjectMetadataNamePlural = + relatedObjectMetadata.nameSingular + 's'; + + return { + standardId: + CUSTOM_OBJECT_STANDARD_FIELD_IDS[relationObjectMetadataNamePlural], + objectMetadataId: createdObjectMetadata.id, + workspaceId: workspaceId, + isCustom: false, + isActive: true, + isSystem: true, + type: FieldMetadataType.RELATION, + name: relationObjectMetadataNamePlural, + label: capitalize(relationObjectMetadataNamePlural), + description: `${capitalize(relationObjectMetadataNamePlural)} tied to the ${createdObjectMetadata.labelSingular}`, + icon: + STANDARD_OBJECT_ICONS[relatedObjectMetadata.nameSingular] || + 'IconBuildingSkyscraper', + isNullable: true, + }; + } + + private createToField( + workspaceId: string, + createdObjectMetadata: ObjectMetadataEntity, + relatedObjectMetadata: ObjectMetadataEntity, + ) { + const customStandardFieldId = + STANDARD_OBJECT_FIELD_IDS[relatedObjectMetadata.nameSingular].custom; + + if (!customStandardFieldId) { + throw new Error( + `Custom standard field ID not found for ${relatedObjectMetadata.nameSingular}`, + ); + } + + return { + standardId: createRelationDeterministicUuid({ + objectId: createdObjectMetadata.id, + standardId: customStandardFieldId, + }), + objectMetadataId: relatedObjectMetadata.id, + workspaceId: workspaceId, + isCustom: false, + isActive: true, + isSystem: true, + type: FieldMetadataType.RELATION, + name: createdObjectMetadata.nameSingular, + label: createdObjectMetadata.labelSingular, + description: `${capitalize(relatedObjectMetadata.nameSingular)} ${createdObjectMetadata.labelSingular}`, + icon: 'IconBuildingSkyscraper', + isNullable: true, + }; + } + + private async createRelationMetadata( + workspaceId: string, + createdObjectMetadata: ObjectMetadataEntity, + relatedObjectMetadata: ObjectMetadataEntity, + relationFieldMetadata: FieldMetadataEntity[], + ) { + const relationFieldMetadataMap = relationFieldMetadata.reduce( + (acc, fieldMetadata: FieldMetadataEntity) => { + if (fieldMetadata.type === FieldMetadataType.RELATION) { + acc[fieldMetadata.objectMetadataId] = fieldMetadata; + } + + return acc; + }, + {}, + ); + + await this.relationMetadataRepository.save([ + { + workspaceId: workspaceId, + relationType: RelationMetadataType.ONE_TO_MANY, + fromObjectMetadataId: createdObjectMetadata.id, + toObjectMetadataId: relatedObjectMetadata.id, + fromFieldMetadataId: + relationFieldMetadataMap[createdObjectMetadata.id].id, + toFieldMetadataId: + relationFieldMetadataMap[relatedObjectMetadata.id].id, + onDeleteAction: RelationOnDeleteAction.CASCADE, + }, + ]); + } + + async updateObjectRelationships(objectMetadataId: string, isActive: boolean) { + const affectedRelations = await this.relationMetadataRepository.find({ + where: [ + { fromObjectMetadataId: objectMetadataId }, + { toObjectMetadataId: objectMetadataId }, + ], + }); + + const affectedFieldIds = affectedRelations.reduce( + (acc, { fromFieldMetadataId, toFieldMetadataId }) => { + acc.push(fromFieldMetadataId, toFieldMetadataId); + + return acc; + }, + [] as string[], + ); + + if (affectedFieldIds.length > 0) { + await this.fieldMetadataRepository.update( + { id: In(affectedFieldIds) }, + { isActive: isActive }, + ); + } + } +} diff --git a/packages/twenty-server/src/engine/metadata-modules/object-metadata/utils/build-default-fields-for-custom-object.util.ts b/packages/twenty-server/src/engine/metadata-modules/object-metadata/utils/build-default-fields-for-custom-object.util.ts new file mode 100644 index 000000000..19eb5b2f7 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/object-metadata/utils/build-default-fields-for-custom-object.util.ts @@ -0,0 +1,109 @@ +import { + FieldMetadataEntity, + FieldMetadataType, +} from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; +import { + BASE_OBJECT_STANDARD_FIELD_IDS, + CUSTOM_OBJECT_STANDARD_FIELD_IDS, +} from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; + +export const buildDefaultFieldsForCustomObject = ( + workspaceId: string, +): Partial[] => [ + { + standardId: BASE_OBJECT_STANDARD_FIELD_IDS.id, + type: FieldMetadataType.UUID, + name: 'id', + label: 'Id', + icon: 'Icon123', + description: 'Id', + isNullable: false, + isActive: true, + isCustom: false, + isSystem: true, + workspaceId, + defaultValue: 'uuid', + }, + { + standardId: CUSTOM_OBJECT_STANDARD_FIELD_IDS.name, + type: FieldMetadataType.TEXT, + name: 'name', + label: 'Name', + icon: 'IconAbc', + description: 'Name', + isNullable: false, + isActive: true, + isCustom: false, + workspaceId, + defaultValue: "'Untitled'", + }, + { + standardId: BASE_OBJECT_STANDARD_FIELD_IDS.createdAt, + type: FieldMetadataType.DATE_TIME, + name: 'createdAt', + label: 'Creation date', + icon: 'IconCalendar', + description: 'Creation date', + isNullable: false, + isActive: true, + isCustom: false, + workspaceId, + defaultValue: 'now', + }, + { + standardId: BASE_OBJECT_STANDARD_FIELD_IDS.updatedAt, + type: FieldMetadataType.DATE_TIME, + name: 'updatedAt', + label: 'Last update', + icon: 'IconCalendarClock', + description: 'Last time the record was changed', + isNullable: false, + isActive: true, + isCustom: false, + isSystem: false, + workspaceId, + defaultValue: 'now', + }, + { + standardId: BASE_OBJECT_STANDARD_FIELD_IDS.deletedAt, + type: FieldMetadataType.DATE_TIME, + name: 'deletedAt', + label: 'Deleted at', + icon: 'IconCalendarClock', + description: 'Deletion date', + isNullable: true, + isActive: true, + isCustom: false, + isSystem: false, + workspaceId, + defaultValue: null, + }, + { + standardId: CUSTOM_OBJECT_STANDARD_FIELD_IDS.createdBy, + type: FieldMetadataType.ACTOR, + name: 'createdBy', + label: 'Created by', + icon: 'IconCreativeCommonsSa', + description: 'The creator of the record', + isNullable: false, + isActive: true, + isCustom: false, + isSystem: false, + workspaceId, + defaultValue: { name: "''", source: "'MANUAL'" }, + }, + { + standardId: CUSTOM_OBJECT_STANDARD_FIELD_IDS.position, + type: FieldMetadataType.POSITION, + name: 'position', + label: 'Position', + icon: 'IconHierarchy2', + description: 'Position', + isNullable: true, + isActive: true, + isCustom: false, + isSystem: true, + workspaceId, + defaultValue: null, + }, +]; diff --git a/packages/twenty-server/src/engine/metadata-modules/object-metadata/utils/build-migrations-for-custom-object-relations.util.ts b/packages/twenty-server/src/engine/metadata-modules/object-metadata/utils/build-migrations-for-custom-object-relations.util.ts index 869c8d1be..0695b66b6 100644 --- a/packages/twenty-server/src/engine/metadata-modules/object-metadata/utils/build-migrations-for-custom-object-relations.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/object-metadata/utils/build-migrations-for-custom-object-relations.util.ts @@ -11,197 +11,46 @@ import { computeObjectTargetTable } from 'src/engine/utils/compute-object-target export const buildMigrationsForCustomObjectRelations = ( createdObjectMetadata: ObjectMetadataEntity, - activityTargetObjectMetadata: ObjectMetadataEntity, - attachmentObjectMetadata: ObjectMetadataEntity, - timelineActivityObjectMetadata: ObjectMetadataEntity, - favoriteObjectMetadata: ObjectMetadataEntity, - noteTargetObjectMetadata: ObjectMetadataEntity, - taskTargetObjectMetadata: ObjectMetadataEntity, -): WorkspaceMigrationTableAction[] => [ - // Add activity target relation - { - name: computeObjectTargetTable(activityTargetObjectMetadata), - action: WorkspaceMigrationTableActionType.ALTER, - columns: [ + relatedObjectMetadataCollection: ObjectMetadataEntity[], +): WorkspaceMigrationTableAction[] => { + const migrations: WorkspaceMigrationTableAction[] = []; + + for (const relatedObjectMetadata of relatedObjectMetadataCollection) { + migrations.push( { - action: WorkspaceMigrationColumnActionType.CREATE, - columnName: computeColumnName(createdObjectMetadata.nameSingular, { - isForeignKey: true, - }), - columnType: 'uuid', - isNullable: true, - defaultValue: null, - } satisfies WorkspaceMigrationColumnCreate, - ], - }, - { - name: computeObjectTargetTable(activityTargetObjectMetadata), - action: WorkspaceMigrationTableActionType.ALTER, - columns: [ - { - action: WorkspaceMigrationColumnActionType.CREATE_FOREIGN_KEY, - columnName: computeColumnName(createdObjectMetadata.nameSingular, { - isForeignKey: true, - }), - referencedTableName: computeObjectTargetTable(createdObjectMetadata), - referencedTableColumnName: 'id', - onDelete: RelationOnDeleteAction.CASCADE, + name: computeObjectTargetTable(relatedObjectMetadata), + action: WorkspaceMigrationTableActionType.ALTER, + columns: [ + { + action: WorkspaceMigrationColumnActionType.CREATE, + columnName: computeColumnName(createdObjectMetadata.nameSingular, { + isForeignKey: true, + }), + columnType: 'uuid', + isNullable: true, + defaultValue: null, + } satisfies WorkspaceMigrationColumnCreate, + ], }, - ], - }, - // Add note target relation - { - name: computeObjectTargetTable(noteTargetObjectMetadata), - action: WorkspaceMigrationTableActionType.ALTER, - columns: [ { - action: WorkspaceMigrationColumnActionType.CREATE, - columnName: computeColumnName(createdObjectMetadata.nameSingular, { - isForeignKey: true, - }), - columnType: 'uuid', - isNullable: true, - defaultValue: null, - } satisfies WorkspaceMigrationColumnCreate, - ], - }, - { - name: computeObjectTargetTable(noteTargetObjectMetadata), - action: WorkspaceMigrationTableActionType.ALTER, - columns: [ - { - action: WorkspaceMigrationColumnActionType.CREATE_FOREIGN_KEY, - columnName: computeColumnName(createdObjectMetadata.nameSingular, { - isForeignKey: true, - }), - referencedTableName: computeObjectTargetTable(createdObjectMetadata), - referencedTableColumnName: 'id', - onDelete: RelationOnDeleteAction.CASCADE, + name: computeObjectTargetTable(relatedObjectMetadata), + action: WorkspaceMigrationTableActionType.ALTER, + columns: [ + { + action: WorkspaceMigrationColumnActionType.CREATE_FOREIGN_KEY, + columnName: computeColumnName(createdObjectMetadata.nameSingular, { + isForeignKey: true, + }), + referencedTableName: computeObjectTargetTable( + createdObjectMetadata, + ), + referencedTableColumnName: 'id', + onDelete: RelationOnDeleteAction.CASCADE, + }, + ], }, - ], - }, - // Add task target relation - { - name: computeObjectTargetTable(taskTargetObjectMetadata), - action: WorkspaceMigrationTableActionType.ALTER, - columns: [ - { - action: WorkspaceMigrationColumnActionType.CREATE, - columnName: computeColumnName(createdObjectMetadata.nameSingular, { - isForeignKey: true, - }), - columnType: 'uuid', - isNullable: true, - defaultValue: null, - } satisfies WorkspaceMigrationColumnCreate, - ], - }, - { - name: computeObjectTargetTable(taskTargetObjectMetadata), - action: WorkspaceMigrationTableActionType.ALTER, - columns: [ - { - action: WorkspaceMigrationColumnActionType.CREATE_FOREIGN_KEY, - columnName: computeColumnName(createdObjectMetadata.nameSingular, { - isForeignKey: true, - }), - referencedTableName: computeObjectTargetTable(createdObjectMetadata), - referencedTableColumnName: 'id', - onDelete: RelationOnDeleteAction.CASCADE, - }, - ], - }, - // Add attachment relation - { - name: computeObjectTargetTable(attachmentObjectMetadata), - action: WorkspaceMigrationTableActionType.ALTER, - columns: [ - { - action: WorkspaceMigrationColumnActionType.CREATE, - columnName: computeColumnName(createdObjectMetadata.nameSingular, { - isForeignKey: true, - }), - columnType: 'uuid', - isNullable: true, - defaultValue: null, - } satisfies WorkspaceMigrationColumnCreate, - ], - }, - { - name: computeObjectTargetTable(attachmentObjectMetadata), - action: WorkspaceMigrationTableActionType.ALTER, - columns: [ - { - action: WorkspaceMigrationColumnActionType.CREATE_FOREIGN_KEY, - columnName: computeColumnName(createdObjectMetadata.nameSingular, { - isForeignKey: true, - }), - referencedTableName: computeObjectTargetTable(createdObjectMetadata), - referencedTableColumnName: 'id', - onDelete: RelationOnDeleteAction.CASCADE, - }, - ], - }, - // Add timeline activity relation - { - name: computeObjectTargetTable(timelineActivityObjectMetadata), - action: WorkspaceMigrationTableActionType.ALTER, - columns: [ - { - action: WorkspaceMigrationColumnActionType.CREATE, - columnName: computeColumnName(createdObjectMetadata.nameSingular, { - isForeignKey: true, - }), - columnType: 'uuid', - isNullable: true, - defaultValue: null, - } satisfies WorkspaceMigrationColumnCreate, - ], - }, - { - name: computeObjectTargetTable(timelineActivityObjectMetadata), - action: WorkspaceMigrationTableActionType.ALTER, - columns: [ - { - action: WorkspaceMigrationColumnActionType.CREATE_FOREIGN_KEY, - columnName: computeColumnName(createdObjectMetadata.nameSingular, { - isForeignKey: true, - }), - referencedTableName: computeObjectTargetTable(createdObjectMetadata), - referencedTableColumnName: 'id', - onDelete: RelationOnDeleteAction.CASCADE, - }, - ], - }, - // Add favorite relation - { - name: computeObjectTargetTable(favoriteObjectMetadata), - action: WorkspaceMigrationTableActionType.ALTER, - columns: [ - { - action: WorkspaceMigrationColumnActionType.CREATE, - columnName: computeColumnName(createdObjectMetadata.nameSingular, { - isForeignKey: true, - }), - columnType: 'uuid', - isNullable: true, - defaultValue: null, - } satisfies WorkspaceMigrationColumnCreate, - ], - }, - { - name: computeObjectTargetTable(favoriteObjectMetadata), - action: WorkspaceMigrationTableActionType.ALTER, - columns: [ - { - action: WorkspaceMigrationColumnActionType.CREATE_FOREIGN_KEY, - columnName: computeColumnName(createdObjectMetadata.nameSingular, { - isForeignKey: true, - }), - referencedTableName: computeObjectTargetTable(createdObjectMetadata), - referencedTableColumnName: 'id', - onDelete: RelationOnDeleteAction.CASCADE, - }, - ], - }, -]; + ); + } + + return migrations; +}; diff --git a/packages/twenty-server/src/engine/metadata-modules/object-metadata/utils/validate-object-metadata-input.util.ts b/packages/twenty-server/src/engine/metadata-modules/object-metadata/utils/validate-object-metadata-input.util.ts index 54b00c767..8eaa446be 100644 --- a/packages/twenty-server/src/engine/metadata-modules/object-metadata/utils/validate-object-metadata-input.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/object-metadata/utils/validate-object-metadata-input.util.ts @@ -99,24 +99,20 @@ const validateNameIsNotReservedKeywordOrThrow = (name?: string) => { }; const validateNameCamelCasedOrThrow = (name?: string) => { - if (name) { - if (name !== camelCase(name)) { - throw new ObjectMetadataException( - `Name should be in camelCase: ${name}`, - ObjectMetadataExceptionCode.INVALID_OBJECT_INPUT, - ); - } + if (name && name !== camelCase(name)) { + throw new ObjectMetadataException( + `Name should be in camelCase: ${name}`, + ObjectMetadataExceptionCode.INVALID_OBJECT_INPUT, + ); } }; const validateNameIsNotTooLongThrow = (name?: string) => { - if (name) { - if (exceedsDatabaseIdentifierMaximumLength(name)) { - throw new ObjectMetadataException( - `Name exceeds 63 characters: ${name}`, - ObjectMetadataExceptionCode.INVALID_OBJECT_INPUT, - ); - } + if (name && exceedsDatabaseIdentifierMaximumLength(name)) { + throw new ObjectMetadataException( + `Name exceeds 63 characters: ${name}`, + ObjectMetadataExceptionCode.INVALID_OBJECT_INPUT, + ); } }; @@ -142,3 +138,29 @@ export const computeMetadataNameFromLabelOrThrow = (label: string): string => { return formattedString; }; + +export const validateNameAndLabelAreSyncOrThrow = ( + label: string, + name: string, +) => { + const computedName = computeMetadataNameFromLabelOrThrow(label); + + if (name !== computedName) { + throw new ObjectMetadataException( + `Name is not synced with label. Expected name: "${computedName}", got ${name}`, + ObjectMetadataExceptionCode.INVALID_OBJECT_INPUT, + ); + } +}; + +export const validateNameSingularAndNamePluralAreDifferentOrThrow = ( + nameSingular: string, + namePlural: string, +) => { + if (nameSingular === namePlural) { + throw new ObjectMetadataException( + 'The singular and plural name cannot be the same for an object', + ObjectMetadataExceptionCode.INVALID_OBJECT_INPUT, + ); + } +}; diff --git a/packages/twenty-server/src/engine/metadata-modules/object-metadata/utils/validate-object-metadata-sync-label-name.util.ts b/packages/twenty-server/src/engine/metadata-modules/object-metadata/utils/validate-object-metadata-sync-label-name.util.ts deleted file mode 100644 index c296267d6..000000000 --- a/packages/twenty-server/src/engine/metadata-modules/object-metadata/utils/validate-object-metadata-sync-label-name.util.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { - ObjectMetadataException, - ObjectMetadataExceptionCode, -} from 'src/engine/metadata-modules/object-metadata/object-metadata.exception'; -import { computeMetadataNameFromLabelOrThrow } from 'src/engine/metadata-modules/object-metadata/utils/validate-object-metadata-input.util'; - -export const validateNameAndLabelAreSyncOrThrow = ( - label: string, - name: string, -) => { - const computedName = computeMetadataNameFromLabelOrThrow(label); - - if (name !== computedName) { - throw new ObjectMetadataException( - `Name is not synced with label. Expected name: "${computedName}", got ${name}`, - ObjectMetadataExceptionCode.INVALID_OBJECT_INPUT, - ); - } -}; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-cleaner/crons/clean-inactive-workspace.job.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-cleaner/crons/clean-inactive-workspace.job.ts index 0ebd5a207..ee883ec3a 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-cleaner/crons/clean-inactive-workspace.job.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-cleaner/crons/clean-inactive-workspace.job.ts @@ -9,13 +9,13 @@ import { import { In, Repository } from 'typeorm'; import { TypeORMService } from 'src/database/typeorm/typeorm.service'; -import { UserService } from 'src/engine/core-modules/user/services/user.service'; -import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { EmailService } from 'src/engine/core-modules/email/email.service'; import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; import { Process } from 'src/engine/core-modules/message-queue/decorators/process.decorator'; import { Processor } from 'src/engine/core-modules/message-queue/decorators/processor.decorator'; import { MessageQueue } from 'src/engine/core-modules/message-queue/message-queue.constants'; +import { UserService } from 'src/engine/core-modules/user/services/user.service'; +import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { DataSourceEntity } from 'src/engine/metadata-modules/data-source/data-source.entity'; import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service'; import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids.ts index ec2690693..44262dde5 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids.ts @@ -506,3 +506,47 @@ export const CUSTOM_OBJECT_STANDARD_FIELD_IDS = { timelineActivities: '20202020-f1ef-4ba4-8f33-1a4577afa477', searchVector: '70e56537-18ef-4811-b1c7-0a444006b815', }; + +export const STANDARD_OBJECT_FIELD_IDS = { + activityTarget: ACTIVITY_TARGET_STANDARD_FIELD_IDS, + activity: ACTIVITY_STANDARD_FIELD_IDS, + apiKey: API_KEY_STANDARD_FIELD_IDS, + attachment: ATTACHMENT_STANDARD_FIELD_IDS, + blocklist: BLOCKLIST_STANDARD_FIELD_IDS, + behavioralEvent: BEHAVIORAL_EVENT_STANDARD_FIELD_IDS, + calendarChannelEventAssociation: + CALENDAR_CHANNEL_EVENT_ASSOCIATION_STANDARD_FIELD_IDS, + calendarChannel: CALENDAR_CHANNEL_STANDARD_FIELD_IDS, + calendarEventParticipant: CALENDAR_EVENT_PARTICIPANT_STANDARD_FIELD_IDS, + calendarEvent: CALENDAR_EVENT_STANDARD_FIELD_IDS, + comment: COMMENT_STANDARD_FIELD_IDS, + company: COMPANY_STANDARD_FIELD_IDS, + connectedAccount: CONNECTED_ACCOUNT_STANDARD_FIELD_IDS, + favorite: FAVORITE_STANDARD_FIELD_IDS, + auditLog: AUDIT_LOGS_STANDARD_FIELD_IDS, + messageChannelMessageAssociation: + MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_STANDARD_FIELD_IDS, + messageChannel: MESSAGE_CHANNEL_STANDARD_FIELD_IDS, + messageParticipant: MESSAGE_PARTICIPANT_STANDARD_FIELD_IDS, + messageThread: MESSAGE_THREAD_STANDARD_FIELD_IDS, + messageThreadSubscriber: MESSAGE_THREAD_SUBSCRIBER_STANDARD_FIELD_IDS, + message: MESSAGE_STANDARD_FIELD_IDS, + note: NOTE_STANDARD_FIELD_IDS, + noteTarget: NOTE_TARGET_STANDARD_FIELD_IDS, + opportunity: OPPORTUNITY_STANDARD_FIELD_IDS, + person: PERSON_STANDARD_FIELD_IDS, + task: TASK_STANDARD_FIELD_IDS, + taskTarget: TASK_TARGET_STANDARD_FIELD_IDS, + timelineActivity: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS, + viewField: VIEW_FIELD_STANDARD_FIELD_IDS, + viewGroup: VIEW_GROUP_STANDARD_FIELD_IDS, + viewFilter: VIEW_FILTER_STANDARD_FIELD_IDS, + viewSort: VIEW_SORT_STANDARD_FIELD_IDS, + view: VIEW_STANDARD_FIELD_IDS, + webhook: WEBHOOK_STANDARD_FIELD_IDS, + workflow: WORKFLOW_STANDARD_FIELD_IDS, + workflowEventListener: WORKFLOW_EVENT_LISTENER_STANDARD_FIELD_IDS, + workflowRun: WORKFLOW_RUN_STANDARD_FIELD_IDS, + workflowVersion: WORKFLOW_VERSION_STANDARD_FIELD_IDS, + workspaceMember: WORKSPACE_MEMBER_STANDARD_FIELD_IDS, +}; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons.ts new file mode 100644 index 000000000..94b8ea3cf --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons.ts @@ -0,0 +1,41 @@ +export const STANDARD_OBJECT_ICONS = { + activityTarget: 'IconCheckbox', + activity: 'IconCheckbox', + apiKey: 'IconRobot', + attachment: 'IconFileImport', + blocklist: 'IconForbid2', + behavioralEvent: 'IconTimelineEvent', + calendarChannelEventAssociation: 'IconCalendar', + calendarChannel: 'IconCalendar', + calendarEventParticipant: 'IconCalendar', + calendarEvent: 'IconCalendar', + comment: 'IconMessageCircle', + company: 'IconBuildingSkyscraper', + connectedAccount: 'IconAt', + favorite: 'IconHeart', + auditLog: 'IconTimelineEvent', + messageChannelMessageAssociation: 'IconMessage', + messageChannel: 'IconMessage', + messageParticipant: 'IconUserCircle', + messageThread: 'IconMessage', + messageThreadSubscriber: 'IconPerson', + message: 'IconMessage', + note: 'IconNotes', + noteTarget: 'IconCheckbox', + opportunity: 'IconTargetArrow', + person: 'IconUser', + task: 'IconCheckbox', + taskTarget: 'IconCheckbox', + timelineActivity: 'IconTimelineEvent', + viewField: 'IconTag', + viewGroup: 'IconTag', + viewFilter: 'IconFilterBolt', + viewSort: 'IconArrowsSort', + view: 'IconLayoutCollage', + webhook: 'IconRobot', + workflow: 'IconSettingsAutomation', + workflowEventListener: 'IconSettingsAutomation', + workflowRun: 'IconSettingsAutomation', + workflowVersion: 'IconSettingsAutomation', + workspaceMember: 'IconUserCircle', +}; diff --git a/packages/twenty-server/src/modules/activity/standard-objects/activity-target.workspace-entity.ts b/packages/twenty-server/src/modules/activity/standard-objects/activity-target.workspace-entity.ts index 00e26c406..13d3e7b56 100644 --- a/packages/twenty-server/src/modules/activity/standard-objects/activity-target.workspace-entity.ts +++ b/packages/twenty-server/src/modules/activity/standard-objects/activity-target.workspace-entity.ts @@ -10,6 +10,7 @@ import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; import { ACTIVITY_TARGET_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; +import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; import { ActivityWorkspaceEntity } from 'src/modules/activity/standard-objects/activity.workspace-entity'; import { CompanyWorkspaceEntity } from 'src/modules/company/standard-objects/company.workspace-entity'; @@ -22,7 +23,7 @@ import { PersonWorkspaceEntity } from 'src/modules/person/standard-objects/perso labelSingular: 'Activity Target', labelPlural: 'Activity Targets', description: 'An activity target', - icon: 'IconCheckbox', + icon: STANDARD_OBJECT_ICONS.activityTarget, }) @WorkspaceIsSystem() export class ActivityTargetWorkspaceEntity extends BaseWorkspaceEntity { diff --git a/packages/twenty-server/src/modules/activity/standard-objects/activity.workspace-entity.ts b/packages/twenty-server/src/modules/activity/standard-objects/activity.workspace-entity.ts index ffd542fc1..e77828f25 100644 --- a/packages/twenty-server/src/modules/activity/standard-objects/activity.workspace-entity.ts +++ b/packages/twenty-server/src/modules/activity/standard-objects/activity.workspace-entity.ts @@ -13,6 +13,7 @@ import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; import { ACTIVITY_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; +import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; import { ActivityTargetWorkspaceEntity } from 'src/modules/activity/standard-objects/activity-target.workspace-entity'; import { CommentWorkspaceEntity } from 'src/modules/activity/standard-objects/comment.workspace-entity'; @@ -25,7 +26,7 @@ import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/sta labelSingular: 'Activity', labelPlural: 'Activities', description: 'An activity', - icon: 'IconCheckbox', + icon: STANDARD_OBJECT_ICONS.activity, labelIdentifierStandardId: ACTIVITY_STANDARD_FIELD_IDS.title, }) @WorkspaceIsSystem() diff --git a/packages/twenty-server/src/modules/activity/standard-objects/comment.workspace-entity.ts b/packages/twenty-server/src/modules/activity/standard-objects/comment.workspace-entity.ts index a572f5d07..bb849854e 100644 --- a/packages/twenty-server/src/modules/activity/standard-objects/comment.workspace-entity.ts +++ b/packages/twenty-server/src/modules/activity/standard-objects/comment.workspace-entity.ts @@ -1,17 +1,18 @@ import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface'; import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; +import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; +import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; +import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator'; +import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator'; +import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; +import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; +import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; import { COMMENT_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; +import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; import { ActivityWorkspaceEntity } from 'src/modules/activity/standard-objects/activity.workspace-entity'; import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity'; -import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator'; -import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; -import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator'; -import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; -import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; -import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; -import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; @WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.comment, @@ -19,7 +20,7 @@ import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace- labelSingular: 'Comment', labelPlural: 'Comments', description: 'A comment', - icon: 'IconMessageCircle', + icon: STANDARD_OBJECT_ICONS.comment, }) @WorkspaceIsSystem() export class CommentWorkspaceEntity extends BaseWorkspaceEntity { diff --git a/packages/twenty-server/src/modules/api-key/standard-objects/api-key.workspace-entity.ts b/packages/twenty-server/src/modules/api-key/standard-objects/api-key.workspace-entity.ts index ff48d1f32..7fd493c1c 100644 --- a/packages/twenty-server/src/modules/api-key/standard-objects/api-key.workspace-entity.ts +++ b/packages/twenty-server/src/modules/api-key/standard-objects/api-key.workspace-entity.ts @@ -6,6 +6,7 @@ import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/work import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; import { API_KEY_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; +import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; @WorkspaceEntity({ @@ -14,7 +15,7 @@ import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync labelSingular: 'API Key', labelPlural: 'API Keys', description: 'An API key', - icon: 'IconRobot', + icon: STANDARD_OBJECT_ICONS.apiKey, labelIdentifierStandardId: API_KEY_STANDARD_FIELD_IDS.name, }) @WorkspaceIsSystem() diff --git a/packages/twenty-server/src/modules/attachment/standard-objects/attachment.workspace-entity.ts b/packages/twenty-server/src/modules/attachment/standard-objects/attachment.workspace-entity.ts index bdadd2f96..d6bcc6735 100644 --- a/packages/twenty-server/src/modules/attachment/standard-objects/attachment.workspace-entity.ts +++ b/packages/twenty-server/src/modules/attachment/standard-objects/attachment.workspace-entity.ts @@ -13,6 +13,7 @@ import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; import { ATTACHMENT_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; +import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; import { ActivityWorkspaceEntity } from 'src/modules/activity/standard-objects/activity.workspace-entity'; import { CompanyWorkspaceEntity } from 'src/modules/company/standard-objects/company.workspace-entity'; @@ -28,7 +29,7 @@ import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/sta labelSingular: 'Attachment', labelPlural: 'Attachments', description: 'An attachment', - icon: 'IconFileImport', + icon: STANDARD_OBJECT_ICONS.attachment, labelIdentifierStandardId: ATTACHMENT_STANDARD_FIELD_IDS.name, }) @WorkspaceIsSystem() diff --git a/packages/twenty-server/src/modules/blocklist/standard-objects/blocklist.workspace-entity.ts b/packages/twenty-server/src/modules/blocklist/standard-objects/blocklist.workspace-entity.ts index 1e8d96bbe..3a45baa99 100644 --- a/packages/twenty-server/src/modules/blocklist/standard-objects/blocklist.workspace-entity.ts +++ b/packages/twenty-server/src/modules/blocklist/standard-objects/blocklist.workspace-entity.ts @@ -10,6 +10,7 @@ import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; import { BLOCKLIST_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; +import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity'; @@ -19,7 +20,7 @@ import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/sta labelSingular: 'Blocklist', labelPlural: 'Blocklists', description: 'Blocklist', - icon: 'IconForbid2', + icon: STANDARD_OBJECT_ICONS.blocklist, labelIdentifierStandardId: BLOCKLIST_STANDARD_FIELD_IDS.handle, }) @WorkspaceIsSystem() diff --git a/packages/twenty-server/src/modules/calendar/common/standard-objects/calendar-channel-event-association.workspace-entity.ts b/packages/twenty-server/src/modules/calendar/common/standard-objects/calendar-channel-event-association.workspace-entity.ts index ee74a697e..99cad3e5a 100644 --- a/packages/twenty-server/src/modules/calendar/common/standard-objects/calendar-channel-event-association.workspace-entity.ts +++ b/packages/twenty-server/src/modules/calendar/common/standard-objects/calendar-channel-event-association.workspace-entity.ts @@ -10,6 +10,7 @@ import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; import { CALENDAR_CHANNEL_EVENT_ASSOCIATION_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; +import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; import { CalendarChannelWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity'; import { CalendarEventWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-event.workspace-entity'; @@ -20,7 +21,7 @@ import { CalendarEventWorkspaceEntity } from 'src/modules/calendar/common/standa labelSingular: 'Calendar Channel Event Association', labelPlural: 'Calendar Channel Event Associations', description: 'Calendar Channel Event Associations', - icon: 'IconCalendar', + icon: STANDARD_OBJECT_ICONS.calendarChannelEventAssociation, }) @WorkspaceIsSystem() @WorkspaceIsNotAuditLogged() diff --git a/packages/twenty-server/src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity.ts b/packages/twenty-server/src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity.ts index fca6a0b01..ec4eb9cb7 100644 --- a/packages/twenty-server/src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity.ts +++ b/packages/twenty-server/src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity.ts @@ -16,6 +16,7 @@ import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; import { CALENDAR_CHANNEL_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; +import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; import { CalendarChannelEventAssociationWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-channel-event-association.workspace-entity'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; @@ -71,7 +72,7 @@ registerEnumType(CalendarChannelContactAutoCreationPolicy, { labelSingular: 'Calendar Channel', labelPlural: 'Calendar Channels', description: 'Calendar Channels', - icon: 'IconCalendar', + icon: STANDARD_OBJECT_ICONS.calendarChannel, labelIdentifierStandardId: CALENDAR_CHANNEL_STANDARD_FIELD_IDS.handle, }) @WorkspaceIsSystem() diff --git a/packages/twenty-server/src/modules/calendar/common/standard-objects/calendar-event-participant.workspace-entity.ts b/packages/twenty-server/src/modules/calendar/common/standard-objects/calendar-event-participant.workspace-entity.ts index 602dec628..1e2d05b16 100644 --- a/packages/twenty-server/src/modules/calendar/common/standard-objects/calendar-event-participant.workspace-entity.ts +++ b/packages/twenty-server/src/modules/calendar/common/standard-objects/calendar-event-participant.workspace-entity.ts @@ -11,6 +11,7 @@ import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; import { CALENDAR_EVENT_PARTICIPANT_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; +import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; import { CalendarEventWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-event.workspace-entity'; import { PersonWorkspaceEntity } from 'src/modules/person/standard-objects/person.workspace-entity'; @@ -29,7 +30,7 @@ export enum CalendarEventParticipantResponseStatus { labelSingular: 'Calendar event participant', labelPlural: 'Calendar event participants', description: 'Calendar event participants', - icon: 'IconCalendar', + icon: STANDARD_OBJECT_ICONS.calendarEventParticipant, labelIdentifierStandardId: CALENDAR_EVENT_PARTICIPANT_STANDARD_FIELD_IDS.handle, }) diff --git a/packages/twenty-server/src/modules/calendar/common/standard-objects/calendar-event.workspace-entity.ts b/packages/twenty-server/src/modules/calendar/common/standard-objects/calendar-event.workspace-entity.ts index 4e4bbbf86..94967baae 100644 --- a/packages/twenty-server/src/modules/calendar/common/standard-objects/calendar-event.workspace-entity.ts +++ b/packages/twenty-server/src/modules/calendar/common/standard-objects/calendar-event.workspace-entity.ts @@ -14,6 +14,7 @@ import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace- import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; import { CALENDAR_EVENT_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; +import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; import { CalendarChannelEventAssociationWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-channel-event-association.workspace-entity'; import { CalendarEventParticipantWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-event-participant.workspace-entity'; @@ -24,7 +25,7 @@ import { CalendarEventParticipantWorkspaceEntity } from 'src/modules/calendar/co labelSingular: 'Calendar event', labelPlural: 'Calendar events', description: 'Calendar events', - icon: 'IconCalendar', + icon: STANDARD_OBJECT_ICONS.calendarEvent, labelIdentifierStandardId: CALENDAR_EVENT_STANDARD_FIELD_IDS.title, }) @WorkspaceIsSystem() diff --git a/packages/twenty-server/src/modules/company/standard-objects/company.workspace-entity.ts b/packages/twenty-server/src/modules/company/standard-objects/company.workspace-entity.ts index af9d0c860..ccf9c6be7 100644 --- a/packages/twenty-server/src/modules/company/standard-objects/company.workspace-entity.ts +++ b/packages/twenty-server/src/modules/company/standard-objects/company.workspace-entity.ts @@ -24,6 +24,7 @@ import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; import { COMPANY_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; +import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; import { FieldTypeAndNameMetadata, @@ -53,7 +54,7 @@ export const SEARCH_FIELDS_FOR_COMPANY: FieldTypeAndNameMetadata[] = [ labelSingular: 'Company', labelPlural: 'Companies', description: 'A company', - icon: 'IconBuildingSkyscraper', + icon: STANDARD_OBJECT_ICONS.company, shortcut: 'C', labelIdentifierStandardId: COMPANY_STANDARD_FIELD_IDS.name, }) diff --git a/packages/twenty-server/src/modules/connected-account/standard-objects/connected-account.workspace-entity.ts b/packages/twenty-server/src/modules/connected-account/standard-objects/connected-account.workspace-entity.ts index 12363ed08..cef7d476c 100644 --- a/packages/twenty-server/src/modules/connected-account/standard-objects/connected-account.workspace-entity.ts +++ b/packages/twenty-server/src/modules/connected-account/standard-objects/connected-account.workspace-entity.ts @@ -14,6 +14,7 @@ import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; import { CONNECTED_ACCOUNT_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; +import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; import { CalendarChannelWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity'; import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; @@ -29,7 +30,7 @@ export enum ConnectedAccountProvider { labelSingular: 'Connected Account', labelPlural: 'Connected Accounts', description: 'A connected account', - icon: 'IconAt', + icon: STANDARD_OBJECT_ICONS.connectedAccount, labelIdentifierStandardId: CONNECTED_ACCOUNT_STANDARD_FIELD_IDS.handle, }) @WorkspaceIsSystem() diff --git a/packages/twenty-server/src/modules/favorite/standard-objects/favorite.workspace-entity.ts b/packages/twenty-server/src/modules/favorite/standard-objects/favorite.workspace-entity.ts index db425cda4..8098a38bd 100644 --- a/packages/twenty-server/src/modules/favorite/standard-objects/favorite.workspace-entity.ts +++ b/packages/twenty-server/src/modules/favorite/standard-objects/favorite.workspace-entity.ts @@ -15,6 +15,7 @@ import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; import { FAVORITE_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; +import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; import { CompanyWorkspaceEntity } from 'src/modules/company/standard-objects/company.workspace-entity'; import { NoteWorkspaceEntity } from 'src/modules/note/standard-objects/note.workspace-entity'; @@ -33,7 +34,7 @@ import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/sta labelSingular: 'Favorite', labelPlural: 'Favorites', description: 'A favorite', - icon: 'IconHeart', + icon: STANDARD_OBJECT_ICONS.favorite, }) @WorkspaceIsNotAuditLogged() @WorkspaceIsSystem() diff --git a/packages/twenty-server/src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity.ts b/packages/twenty-server/src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity.ts index 162a48c8f..b14cb8499 100644 --- a/packages/twenty-server/src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity.ts +++ b/packages/twenty-server/src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity.ts @@ -14,6 +14,7 @@ import { MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_STANDARD_FIELD_IDS, MESSAGE_STANDARD_FIELD_IDS, } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; +import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; import { MessageDirection } from 'src/modules/messaging/common/enums/message-direction.enum'; import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity'; @@ -25,7 +26,7 @@ import { MessageWorkspaceEntity } from 'src/modules/messaging/common/standard-ob labelSingular: 'Message Channel Message Association', labelPlural: 'Message Channel Message Associations', description: 'Message Synced with a Message Channel', - icon: 'IconMessage', + icon: STANDARD_OBJECT_ICONS.messageChannelMessageAssociation, }) @WorkspaceIsNotAuditLogged() @WorkspaceIsSystem() diff --git a/packages/twenty-server/src/modules/messaging/common/standard-objects/message-channel.workspace-entity.ts b/packages/twenty-server/src/modules/messaging/common/standard-objects/message-channel.workspace-entity.ts index 3b5b6e3a6..1e0b80b18 100644 --- a/packages/twenty-server/src/modules/messaging/common/standard-objects/message-channel.workspace-entity.ts +++ b/packages/twenty-server/src/modules/messaging/common/standard-objects/message-channel.workspace-entity.ts @@ -16,6 +16,7 @@ import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; import { MESSAGE_CHANNEL_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; +import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity'; import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity'; @@ -80,7 +81,7 @@ registerEnumType(MessageChannelContactAutoCreationPolicy, { labelSingular: 'Message Channel', labelPlural: 'Message Channels', description: 'Message Channels', - icon: 'IconMessage', + icon: STANDARD_OBJECT_ICONS.messageChannel, labelIdentifierStandardId: MESSAGE_CHANNEL_STANDARD_FIELD_IDS.handle, }) @WorkspaceIsNotAuditLogged() diff --git a/packages/twenty-server/src/modules/messaging/common/standard-objects/message-participant.workspace-entity.ts b/packages/twenty-server/src/modules/messaging/common/standard-objects/message-participant.workspace-entity.ts index d6c9524c0..40989d0ae 100644 --- a/packages/twenty-server/src/modules/messaging/common/standard-objects/message-participant.workspace-entity.ts +++ b/packages/twenty-server/src/modules/messaging/common/standard-objects/message-participant.workspace-entity.ts @@ -11,6 +11,7 @@ import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; import { MESSAGE_PARTICIPANT_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; +import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; import { MessageWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message.workspace-entity'; import { PersonWorkspaceEntity } from 'src/modules/person/standard-objects/person.workspace-entity'; @@ -22,7 +23,7 @@ import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/sta labelSingular: 'Message Participant', labelPlural: 'Message Participants', description: 'Message Participants', - icon: 'IconUserCircle', + icon: STANDARD_OBJECT_ICONS.messageParticipant, labelIdentifierStandardId: MESSAGE_PARTICIPANT_STANDARD_FIELD_IDS.handle, }) @WorkspaceIsNotAuditLogged() diff --git a/packages/twenty-server/src/modules/messaging/common/standard-objects/message-thread-subscriber.workspace-entity.ts b/packages/twenty-server/src/modules/messaging/common/standard-objects/message-thread-subscriber.workspace-entity.ts index 05f052c42..8d459f5ad 100644 --- a/packages/twenty-server/src/modules/messaging/common/standard-objects/message-thread-subscriber.workspace-entity.ts +++ b/packages/twenty-server/src/modules/messaging/common/standard-objects/message-thread-subscriber.workspace-entity.ts @@ -10,6 +10,7 @@ import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; import { MESSAGE_THREAD_SUBSCRIBER_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; +import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; import { MessageThreadWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-thread.workspace-entity'; import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity'; @@ -20,7 +21,7 @@ import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/sta labelSingular: 'Message Thread Subscriber', labelPlural: 'Message Threads Subscribers', description: 'Message Thread Subscribers', - icon: 'IconPerson', + icon: STANDARD_OBJECT_ICONS.messageThreadSubscriber, }) @WorkspaceIsNotAuditLogged() @WorkspaceIsSystem() diff --git a/packages/twenty-server/src/modules/messaging/common/standard-objects/message-thread.workspace-entity.ts b/packages/twenty-server/src/modules/messaging/common/standard-objects/message-thread.workspace-entity.ts index 255cd3dda..f6e09d310 100644 --- a/packages/twenty-server/src/modules/messaging/common/standard-objects/message-thread.workspace-entity.ts +++ b/packages/twenty-server/src/modules/messaging/common/standard-objects/message-thread.workspace-entity.ts @@ -13,6 +13,7 @@ import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace- import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; import { MESSAGE_THREAD_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; +import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; import { MessageThreadSubscriberWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-thread-subscriber.workspace-entity'; import { MessageWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message.workspace-entity'; @@ -23,7 +24,7 @@ import { MessageWorkspaceEntity } from 'src/modules/messaging/common/standard-ob labelSingular: 'Message Thread', labelPlural: 'Message Threads', description: 'Message Thread', - icon: 'IconMessage', + icon: STANDARD_OBJECT_ICONS.messageThread, }) @WorkspaceIsNotAuditLogged() @WorkspaceIsSystem() diff --git a/packages/twenty-server/src/modules/messaging/common/standard-objects/message.workspace-entity.ts b/packages/twenty-server/src/modules/messaging/common/standard-objects/message.workspace-entity.ts index 82702a773..9780aeb18 100644 --- a/packages/twenty-server/src/modules/messaging/common/standard-objects/message.workspace-entity.ts +++ b/packages/twenty-server/src/modules/messaging/common/standard-objects/message.workspace-entity.ts @@ -14,6 +14,7 @@ import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; import { MESSAGE_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; +import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity'; import { MessageParticipantWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-participant.workspace-entity'; @@ -25,7 +26,7 @@ import { MessageThreadWorkspaceEntity } from 'src/modules/messaging/common/stand labelSingular: 'Message', labelPlural: 'Messages', description: 'Message', - icon: 'IconMessage', + icon: STANDARD_OBJECT_ICONS.message, labelIdentifierStandardId: MESSAGE_STANDARD_FIELD_IDS.subject, }) @WorkspaceIsNotAuditLogged() diff --git a/packages/twenty-server/src/modules/note/standard-objects/note-target.workspace-entity.ts b/packages/twenty-server/src/modules/note/standard-objects/note-target.workspace-entity.ts index f4f260cea..ea644f00e 100644 --- a/packages/twenty-server/src/modules/note/standard-objects/note-target.workspace-entity.ts +++ b/packages/twenty-server/src/modules/note/standard-objects/note-target.workspace-entity.ts @@ -10,6 +10,7 @@ import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; import { NOTE_TARGET_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; +import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; import { CompanyWorkspaceEntity } from 'src/modules/company/standard-objects/company.workspace-entity'; import { NoteWorkspaceEntity } from 'src/modules/note/standard-objects/note.workspace-entity'; @@ -22,7 +23,7 @@ import { PersonWorkspaceEntity } from 'src/modules/person/standard-objects/perso labelSingular: 'Note Target', labelPlural: 'Note Targets', description: 'A note target', - icon: 'IconCheckbox', + icon: STANDARD_OBJECT_ICONS.noteTarget, }) @WorkspaceIsSystem() export class NoteTargetWorkspaceEntity extends BaseWorkspaceEntity { diff --git a/packages/twenty-server/src/modules/note/standard-objects/note.workspace-entity.ts b/packages/twenty-server/src/modules/note/standard-objects/note.workspace-entity.ts index 8e57cd0d8..1edd8cc8c 100644 --- a/packages/twenty-server/src/modules/note/standard-objects/note.workspace-entity.ts +++ b/packages/twenty-server/src/modules/note/standard-objects/note.workspace-entity.ts @@ -19,6 +19,7 @@ import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace- import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; import { NOTE_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; +import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; import { FieldTypeAndNameMetadata, @@ -43,7 +44,7 @@ export const SEARCH_FIELDS_FOR_NOTES: FieldTypeAndNameMetadata[] = [ labelSingular: 'Note', labelPlural: 'Notes', description: 'A note', - icon: 'IconNotes', + icon: STANDARD_OBJECT_ICONS.note, shortcut: 'N', labelIdentifierStandardId: NOTE_STANDARD_FIELD_IDS.title, }) diff --git a/packages/twenty-server/src/modules/opportunity/standard-objects/opportunity.workspace-entity.ts b/packages/twenty-server/src/modules/opportunity/standard-objects/opportunity.workspace-entity.ts index cf6b8e8b8..a3bb717d9 100644 --- a/packages/twenty-server/src/modules/opportunity/standard-objects/opportunity.workspace-entity.ts +++ b/packages/twenty-server/src/modules/opportunity/standard-objects/opportunity.workspace-entity.ts @@ -23,6 +23,7 @@ import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; import { OPPORTUNITY_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; +import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; import { FieldTypeAndNameMetadata, @@ -49,7 +50,7 @@ export const SEARCH_FIELDS_FOR_OPPORTUNITY: FieldTypeAndNameMetadata[] = [ labelSingular: 'Opportunity', labelPlural: 'Opportunities', description: 'An opportunity', - icon: 'IconTargetArrow', + icon: STANDARD_OBJECT_ICONS.opportunity, shortcut: 'O', labelIdentifierStandardId: OPPORTUNITY_STANDARD_FIELD_IDS.name, }) diff --git a/packages/twenty-server/src/modules/person/standard-objects/person.workspace-entity.ts b/packages/twenty-server/src/modules/person/standard-objects/person.workspace-entity.ts index f28d72220..e42ccace2 100644 --- a/packages/twenty-server/src/modules/person/standard-objects/person.workspace-entity.ts +++ b/packages/twenty-server/src/modules/person/standard-objects/person.workspace-entity.ts @@ -26,6 +26,7 @@ import { WorkspaceIsUnique } from 'src/engine/twenty-orm/decorators/workspace-is import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; import { PERSON_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; +import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; import { FieldTypeAndNameMetadata, @@ -58,7 +59,7 @@ export const SEARCH_FIELDS_FOR_PERSON: FieldTypeAndNameMetadata[] = [ labelSingular: 'Person', labelPlural: 'People', description: 'A person', - icon: 'IconUser', + icon: STANDARD_OBJECT_ICONS.person, shortcut: 'P', labelIdentifierStandardId: PERSON_STANDARD_FIELD_IDS.name, imageIdentifierStandardId: PERSON_STANDARD_FIELD_IDS.avatarUrl, diff --git a/packages/twenty-server/src/modules/task/standard-objects/task-target.workspace-entity.ts b/packages/twenty-server/src/modules/task/standard-objects/task-target.workspace-entity.ts index 8f9cac2ac..744b51fa8 100644 --- a/packages/twenty-server/src/modules/task/standard-objects/task-target.workspace-entity.ts +++ b/packages/twenty-server/src/modules/task/standard-objects/task-target.workspace-entity.ts @@ -10,6 +10,7 @@ import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; import { TASK_TARGET_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; +import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; import { CompanyWorkspaceEntity } from 'src/modules/company/standard-objects/company.workspace-entity'; import { OpportunityWorkspaceEntity } from 'src/modules/opportunity/standard-objects/opportunity.workspace-entity'; @@ -22,7 +23,7 @@ import { TaskWorkspaceEntity } from 'src/modules/task/standard-objects/task.work labelSingular: 'Task Target', labelPlural: 'Task Targets', description: 'An task target', - icon: 'IconCheckbox', + icon: STANDARD_OBJECT_ICONS.taskTarget, }) @WorkspaceIsSystem() export class TaskTargetWorkspaceEntity extends BaseWorkspaceEntity { diff --git a/packages/twenty-server/src/modules/task/standard-objects/task.workspace-entity.ts b/packages/twenty-server/src/modules/task/standard-objects/task.workspace-entity.ts index 1244a5606..39dc57c3a 100644 --- a/packages/twenty-server/src/modules/task/standard-objects/task.workspace-entity.ts +++ b/packages/twenty-server/src/modules/task/standard-objects/task.workspace-entity.ts @@ -20,6 +20,7 @@ import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; import { TASK_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; +import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; import { FieldTypeAndNameMetadata, @@ -45,7 +46,7 @@ export const SEARCH_FIELDS_FOR_TASK: FieldTypeAndNameMetadata[] = [ labelSingular: 'Task', labelPlural: 'Tasks', description: 'A task', - icon: 'IconCheckbox', + icon: STANDARD_OBJECT_ICONS.task, shortcut: 'T', labelIdentifierStandardId: TASK_STANDARD_FIELD_IDS.title, }) diff --git a/packages/twenty-server/src/modules/timeline/standard-objects/audit-log.workspace-entity.ts b/packages/twenty-server/src/modules/timeline/standard-objects/audit-log.workspace-entity.ts index 876d3ba7b..8de2edb58 100644 --- a/packages/twenty-server/src/modules/timeline/standard-objects/audit-log.workspace-entity.ts +++ b/packages/twenty-server/src/modules/timeline/standard-objects/audit-log.workspace-entity.ts @@ -10,6 +10,7 @@ import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; import { AUDIT_LOGS_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; +import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity'; @@ -19,7 +20,7 @@ import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/sta labelSingular: 'Audit Log', labelPlural: 'Audit Logs', description: 'An audit log of actions performed in the system', - icon: 'IconIconTimelineEvent', + icon: STANDARD_OBJECT_ICONS.auditLog, labelIdentifierStandardId: AUDIT_LOGS_STANDARD_FIELD_IDS.name, }) @WorkspaceIsSystem() diff --git a/packages/twenty-server/src/modules/timeline/standard-objects/behavioral-event.workspace-entity.ts b/packages/twenty-server/src/modules/timeline/standard-objects/behavioral-event.workspace-entity.ts index 7827ce9a6..d5ed28db7 100644 --- a/packages/twenty-server/src/modules/timeline/standard-objects/behavioral-event.workspace-entity.ts +++ b/packages/twenty-server/src/modules/timeline/standard-objects/behavioral-event.workspace-entity.ts @@ -7,6 +7,7 @@ import { WorkspaceGate } from 'src/engine/twenty-orm/decorators/workspace-gate.d import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; import { BEHAVIORAL_EVENT_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; +import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; @WorkspaceEntity({ @@ -15,7 +16,7 @@ import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync labelSingular: 'Behavioral Event', labelPlural: 'Behavioral Events', description: 'An event related to user behavior', - icon: 'IconIconTimelineEvent', + icon: STANDARD_OBJECT_ICONS.behavioralEvent, }) @WorkspaceIsSystem() @WorkspaceGate({ diff --git a/packages/twenty-server/src/modules/timeline/standard-objects/timeline-activity.workspace-entity.ts b/packages/twenty-server/src/modules/timeline/standard-objects/timeline-activity.workspace-entity.ts index 8d0eff81a..1a3c95e5f 100644 --- a/packages/twenty-server/src/modules/timeline/standard-objects/timeline-activity.workspace-entity.ts +++ b/packages/twenty-server/src/modules/timeline/standard-objects/timeline-activity.workspace-entity.ts @@ -15,6 +15,7 @@ import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; import { TIMELINE_ACTIVITY_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; +import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; import { CompanyWorkspaceEntity } from 'src/modules/company/standard-objects/company.workspace-entity'; import { NoteWorkspaceEntity } from 'src/modules/note/standard-objects/note.workspace-entity'; @@ -32,7 +33,7 @@ import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/sta labelSingular: 'Timeline Activity', labelPlural: 'Timeline Activities', description: 'Aggregated / filtered event to be displayed on the timeline', - icon: 'IconIconTimelineEvent', + icon: STANDARD_OBJECT_ICONS.timelineActivity, }) @WorkspaceIsSystem() @WorkspaceIsNotAuditLogged() diff --git a/packages/twenty-server/src/modules/view/standard-objects/view-field.workspace-entity.ts b/packages/twenty-server/src/modules/view/standard-objects/view-field.workspace-entity.ts index 3fb3d7c53..c5ba034ec 100644 --- a/packages/twenty-server/src/modules/view/standard-objects/view-field.workspace-entity.ts +++ b/packages/twenty-server/src/modules/view/standard-objects/view-field.workspace-entity.ts @@ -9,6 +9,7 @@ import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; import { VIEW_FIELD_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; +import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; import { ViewWorkspaceEntity } from 'src/modules/view/standard-objects/view.workspace-entity'; @@ -18,7 +19,7 @@ import { ViewWorkspaceEntity } from 'src/modules/view/standard-objects/view.work labelSingular: 'View Field', labelPlural: 'View Fields', description: '(System) View Fields', - icon: 'IconTag', + icon: STANDARD_OBJECT_ICONS.viewField, }) @WorkspaceIsNotAuditLogged() @WorkspaceIsSystem() diff --git a/packages/twenty-server/src/modules/view/standard-objects/view-filter.workspace-entity.ts b/packages/twenty-server/src/modules/view/standard-objects/view-filter.workspace-entity.ts index db46b466c..1d2f33546 100644 --- a/packages/twenty-server/src/modules/view/standard-objects/view-filter.workspace-entity.ts +++ b/packages/twenty-server/src/modules/view/standard-objects/view-filter.workspace-entity.ts @@ -11,6 +11,7 @@ import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; import { VIEW_FILTER_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; +import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; import { ViewWorkspaceEntity } from 'src/modules/view/standard-objects/view.workspace-entity'; @@ -20,7 +21,7 @@ import { ViewWorkspaceEntity } from 'src/modules/view/standard-objects/view.work labelSingular: 'View Filter', labelPlural: 'View Filters', description: '(System) View Filters', - icon: 'IconFilterBolt', + icon: STANDARD_OBJECT_ICONS.viewFilter, }) @WorkspaceIsNotAuditLogged() @WorkspaceIsSystem() diff --git a/packages/twenty-server/src/modules/view/standard-objects/view-group.workspace-entity.ts b/packages/twenty-server/src/modules/view/standard-objects/view-group.workspace-entity.ts index 93ff49b30..b9ebd4f05 100644 --- a/packages/twenty-server/src/modules/view/standard-objects/view-group.workspace-entity.ts +++ b/packages/twenty-server/src/modules/view/standard-objects/view-group.workspace-entity.ts @@ -1,16 +1,17 @@ import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; +import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator'; import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator'; import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator'; import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; -import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator'; +import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; import { VIEW_GROUP_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; +import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; import { ViewWorkspaceEntity } from 'src/modules/view/standard-objects/view.workspace-entity'; -import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; @WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.viewGroup, @@ -18,7 +19,7 @@ import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace- labelSingular: 'View Group', labelPlural: 'View Groups', description: '(System) View Groups', - icon: 'IconTag', + icon: STANDARD_OBJECT_ICONS.viewGroup, }) @WorkspaceIsNotAuditLogged() @WorkspaceIsSystem() diff --git a/packages/twenty-server/src/modules/view/standard-objects/view-sort.workspace-entity.ts b/packages/twenty-server/src/modules/view/standard-objects/view-sort.workspace-entity.ts index f4c65ba5c..34e06dffa 100644 --- a/packages/twenty-server/src/modules/view/standard-objects/view-sort.workspace-entity.ts +++ b/packages/twenty-server/src/modules/view/standard-objects/view-sort.workspace-entity.ts @@ -11,6 +11,7 @@ import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; import { VIEW_SORT_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; +import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; import { ViewWorkspaceEntity } from 'src/modules/view/standard-objects/view.workspace-entity'; @@ -20,7 +21,7 @@ import { ViewWorkspaceEntity } from 'src/modules/view/standard-objects/view.work labelSingular: 'View Sort', labelPlural: 'View Sorts', description: '(System) View Sorts', - icon: 'IconArrowsSort', + icon: STANDARD_OBJECT_ICONS.viewSort, }) @WorkspaceIsNotAuditLogged() @WorkspaceIsSystem() diff --git a/packages/twenty-server/src/modules/view/standard-objects/view.workspace-entity.ts b/packages/twenty-server/src/modules/view/standard-objects/view.workspace-entity.ts index f737e5cb4..72d90b4da 100644 --- a/packages/twenty-server/src/modules/view/standard-objects/view.workspace-entity.ts +++ b/packages/twenty-server/src/modules/view/standard-objects/view.workspace-entity.ts @@ -13,13 +13,14 @@ import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace- import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; import { VIEW_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; +import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; import { FavoriteWorkspaceEntity } from 'src/modules/favorite/standard-objects/favorite.workspace-entity'; import { ViewFieldWorkspaceEntity } from 'src/modules/view/standard-objects/view-field.workspace-entity'; import { ViewFilterGroupWorkspaceEntity } from 'src/modules/view/standard-objects/view-filter-group.workspace-entity'; import { ViewFilterWorkspaceEntity } from 'src/modules/view/standard-objects/view-filter.workspace-entity'; -import { ViewSortWorkspaceEntity } from 'src/modules/view/standard-objects/view-sort.workspace-entity'; import { ViewGroupWorkspaceEntity } from 'src/modules/view/standard-objects/view-group.workspace-entity'; +import { ViewSortWorkspaceEntity } from 'src/modules/view/standard-objects/view-sort.workspace-entity'; @WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.view, @@ -27,7 +28,7 @@ import { ViewGroupWorkspaceEntity } from 'src/modules/view/standard-objects/view labelSingular: 'View', labelPlural: 'Views', description: '(System) Views', - icon: 'IconLayoutCollage', + icon: STANDARD_OBJECT_ICONS.view, labelIdentifierStandardId: VIEW_STANDARD_FIELD_IDS.name, }) @WorkspaceIsNotAuditLogged() diff --git a/packages/twenty-server/src/modules/webhook/standard-objects/webhook.workspace-entity.ts b/packages/twenty-server/src/modules/webhook/standard-objects/webhook.workspace-entity.ts index a52f0e8fe..6c003cb15 100644 --- a/packages/twenty-server/src/modules/webhook/standard-objects/webhook.workspace-entity.ts +++ b/packages/twenty-server/src/modules/webhook/standard-objects/webhook.workspace-entity.ts @@ -2,12 +2,13 @@ import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/fi import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator'; import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator'; +import { WorkspaceIsDeprecated } from 'src/engine/twenty-orm/decorators/workspace-is-deprecated.decorator'; import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator'; import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; import { WEBHOOK_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; +import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; -import { WorkspaceIsDeprecated } from 'src/engine/twenty-orm/decorators/workspace-is-deprecated.decorator'; @WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.webhook, @@ -15,7 +16,7 @@ import { WorkspaceIsDeprecated } from 'src/engine/twenty-orm/decorators/workspac labelSingular: 'Webhook', labelPlural: 'Webhooks', description: 'A webhook', - icon: 'IconRobot', + icon: STANDARD_OBJECT_ICONS.webhook, labelIdentifierStandardId: WEBHOOK_STANDARD_FIELD_IDS.targetUrl, }) @WorkspaceIsNotAuditLogged() diff --git a/packages/twenty-server/src/modules/workflow/common/standard-objects/workflow-event-listener.workspace-entity.ts b/packages/twenty-server/src/modules/workflow/common/standard-objects/workflow-event-listener.workspace-entity.ts index 402891c1d..32aa8aeb5 100644 --- a/packages/twenty-server/src/modules/workflow/common/standard-objects/workflow-event-listener.workspace-entity.ts +++ b/packages/twenty-server/src/modules/workflow/common/standard-objects/workflow-event-listener.workspace-entity.ts @@ -12,6 +12,7 @@ import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; import { WORKFLOW_EVENT_LISTENER_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; +import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; import { WorkflowWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow.workspace-entity'; @@ -21,6 +22,7 @@ import { WorkflowWorkspaceEntity } from 'src/modules/workflow/common/standard-ob labelSingular: 'WorkflowEventListener', labelPlural: 'WorkflowEventListeners', description: 'A workflow event listener', + icon: STANDARD_OBJECT_ICONS.workflowEventListener, labelIdentifierStandardId: WORKFLOW_EVENT_LISTENER_STANDARD_FIELD_IDS.eventName, }) diff --git a/packages/twenty-server/src/modules/workflow/common/standard-objects/workflow-run.workspace-entity.ts b/packages/twenty-server/src/modules/workflow/common/standard-objects/workflow-run.workspace-entity.ts index 545e88a47..2e992558b 100644 --- a/packages/twenty-server/src/modules/workflow/common/standard-objects/workflow-run.workspace-entity.ts +++ b/packages/twenty-server/src/modules/workflow/common/standard-objects/workflow-run.workspace-entity.ts @@ -19,6 +19,7 @@ import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; import { WORKFLOW_RUN_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; +import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; import { FavoriteWorkspaceEntity } from 'src/modules/favorite/standard-objects/favorite.workspace-entity'; import { TimelineActivityWorkspaceEntity } from 'src/modules/timeline/standard-objects/timeline-activity.workspace-entity'; @@ -54,7 +55,7 @@ export type WorkflowRunOutput = { labelPlural: 'Workflow Runs', description: 'A workflow run', labelIdentifierStandardId: WORKFLOW_RUN_STANDARD_FIELD_IDS.name, - icon: 'IconSettingsAutomation', + icon: STANDARD_OBJECT_ICONS.workflowRun, }) @WorkspaceGate({ featureFlag: FeatureFlagKey.IsWorkflowEnabled, diff --git a/packages/twenty-server/src/modules/workflow/common/standard-objects/workflow-version.workspace-entity.ts b/packages/twenty-server/src/modules/workflow/common/standard-objects/workflow-version.workspace-entity.ts index 8e39c789a..2d526cf92 100644 --- a/packages/twenty-server/src/modules/workflow/common/standard-objects/workflow-version.workspace-entity.ts +++ b/packages/twenty-server/src/modules/workflow/common/standard-objects/workflow-version.workspace-entity.ts @@ -15,6 +15,7 @@ import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; import { WORKFLOW_VERSION_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; +import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; import { FavoriteWorkspaceEntity } from 'src/modules/favorite/standard-objects/favorite.workspace-entity'; import { TimelineActivityWorkspaceEntity } from 'src/modules/timeline/standard-objects/timeline-activity.workspace-entity'; @@ -63,7 +64,7 @@ const WorkflowVersionStatusOptions = [ labelSingular: 'Workflow Version', labelPlural: 'Workflow Versions', description: 'A workflow version', - icon: 'IconSettingsAutomation', + icon: STANDARD_OBJECT_ICONS.workflowVersion, labelIdentifierStandardId: WORKFLOW_VERSION_STANDARD_FIELD_IDS.name, }) @WorkspaceGate({ diff --git a/packages/twenty-server/src/modules/workflow/common/standard-objects/workflow.workspace-entity.ts b/packages/twenty-server/src/modules/workflow/common/standard-objects/workflow.workspace-entity.ts index 1e05d64ac..3c69a3a75 100644 --- a/packages/twenty-server/src/modules/workflow/common/standard-objects/workflow.workspace-entity.ts +++ b/packages/twenty-server/src/modules/workflow/common/standard-objects/workflow.workspace-entity.ts @@ -14,6 +14,7 @@ import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace- import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; import { WORKFLOW_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; +import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; import { FavoriteWorkspaceEntity } from 'src/modules/favorite/standard-objects/favorite.workspace-entity'; import { TimelineActivityWorkspaceEntity } from 'src/modules/timeline/standard-objects/timeline-activity.workspace-entity'; @@ -54,7 +55,7 @@ const WorkflowStatusOptions = [ labelSingular: 'Workflow', labelPlural: 'Workflows', description: 'A workflow', - icon: 'IconSettingsAutomation', + icon: STANDARD_OBJECT_ICONS.workflow, shortcut: 'W', labelIdentifierStandardId: WORKFLOW_STANDARD_FIELD_IDS.name, }) diff --git a/packages/twenty-server/src/modules/workspace-member/standard-objects/workspace-member.workspace-entity.ts b/packages/twenty-server/src/modules/workspace-member/standard-objects/workspace-member.workspace-entity.ts index 44fe88feb..cb6797c7a 100644 --- a/packages/twenty-server/src/modules/workspace-member/standard-objects/workspace-member.workspace-entity.ts +++ b/packages/twenty-server/src/modules/workspace-member/standard-objects/workspace-member.workspace-entity.ts @@ -21,6 +21,7 @@ import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace- import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; import { WORKSPACE_MEMBER_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; +import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; import { FieldTypeAndNameMetadata, @@ -78,7 +79,7 @@ export const SEARCH_FIELDS_FOR_WORKSPACE_MEMBER: FieldTypeAndNameMetadata[] = [ labelSingular: 'Workspace Member', labelPlural: 'Workspace Members', description: 'A workspace member', - icon: 'IconUserCircle', + icon: STANDARD_OBJECT_ICONS.workspaceMember, labelIdentifierStandardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.name, }) @WorkspaceIsSystem()