diff --git a/packages/twenty-server/src/database/commands/data-seed-dev-workspace.command.ts b/packages/twenty-server/src/database/commands/data-seed-dev-workspace.command.ts index af786fd2b..c133ad72d 100644 --- a/packages/twenty-server/src/database/commands/data-seed-dev-workspace.command.ts +++ b/packages/twenty-server/src/database/commands/data-seed-dev-workspace.command.ts @@ -1,13 +1,18 @@ import { Logger } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; import { Command, CommandRunner } from 'nest-commander'; -import { EntityManager } from 'typeorm'; +import { EntityManager, Repository } from 'typeorm'; import { seedCoreSchema } from 'src/database/typeorm-seeds/core'; import { SEED_APPLE_WORKSPACE_ID, SEED_TWENTY_WORKSPACE_ID, } from 'src/database/typeorm-seeds/core/workspaces'; +import { + getDevSeedCompanyCustomFields, + getDevSeedPeopleCustomFields, +} from 'src/database/typeorm-seeds/metadata/fieldsMetadata'; import { seedCalendarChannels } from 'src/database/typeorm-seeds/workspace/calendar-channel'; import { seedCalendarChannelEventAssociations } from 'src/database/typeorm-seeds/workspace/calendar-channel-event-association'; import { seedCalendarEventParticipants } from 'src/database/typeorm-seeds/workspace/calendar-event-participants'; @@ -31,10 +36,13 @@ import { CacheStorageService } from 'src/engine/integrations/cache-storage/cache import { InjectCacheStorage } from 'src/engine/integrations/cache-storage/decorators/cache-storage.decorator'; import { CacheStorageNamespace } from 'src/engine/integrations/cache-storage/types/cache-storage-namespace.enum'; import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service'; +import { FieldMetadataService } from 'src/engine/metadata-modules/field-metadata/field-metadata.service'; +import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service'; import { WorkspaceCacheVersionService } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.service'; import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service'; import { viewPrefillData } from 'src/engine/workspace-manager/standard-objects-prefill-data/view'; +import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; import { WorkspaceSyncMetadataService } from 'src/engine/workspace-manager/workspace-sync-metadata/workspace-sync-metadata.service'; // TODO: implement dry-run @@ -52,6 +60,9 @@ export class DataSeedWorkspaceCommand extends CommandRunner { private readonly typeORMService: TypeORMService, private readonly workspaceSyncMetadataService: WorkspaceSyncMetadataService, private readonly workspaceDataSourceService: WorkspaceDataSourceService, + private readonly fieldMetadataService: FieldMetadataService, + @InjectRepository(ObjectMetadataEntity, 'metadata') + private readonly objectMetadataRepository: Repository, private readonly objectMetadataService: ObjectMetadataService, @InjectCacheStorage(CacheStorageNamespace.WorkspaceSchema) private readonly workspaceSchemaCache: CacheStorageService, @@ -128,6 +139,15 @@ export class DataSeedWorkspaceCommand extends CommandRunner { const featureFlags = await featureFlagRepository.find({}); + await this.seedCompanyCustomFields( + objectMetadataMap[STANDARD_OBJECT_IDS.company], + workspaceId, + ); + await this.seedPeopleCustomFields( + objectMetadataMap[STANDARD_OBJECT_IDS.person], + workspaceId, + ); + await workspaceDataSource.transaction( async (entityManager: EntityManager) => { await seedCompanies(entityManager, dataSourceMetadata.schema); @@ -206,4 +226,55 @@ export class DataSeedWorkspaceCommand extends CommandRunner { await this.typeORMService.disconnectFromDataSource(dataSourceMetadata.id); } } + + async seedCompanyCustomFields( + companyObjectMetadata: ObjectMetadataEntity, + workspaceId: string, + ) { + const companyObjectMetadataId = companyObjectMetadata?.id; + + if (!companyObjectMetadataId) { + throw new Error( + `Company object metadata not found for workspace ${workspaceId}, can't seed custom fields`, + ); + } + + const DEV_SEED_COMPANY_CUSTOM_FIELDS = getDevSeedCompanyCustomFields( + companyObjectMetadataId, + workspaceId, + ); + + for (const customField of DEV_SEED_COMPANY_CUSTOM_FIELDS) { + // TODO: Use createMany once implemented for better performances + await this.fieldMetadataService.createOne({ + ...customField, + isCustom: true, + }); + } + } + + async seedPeopleCustomFields( + personObjectMetadata: ObjectMetadataEntity, + workspaceId: string, + ) { + const personObjectMetadataId = personObjectMetadata?.id; + + if (!personObjectMetadataId) { + throw new Error( + `Person object metadata not found for workspace ${workspaceId}, can't seed custom fields`, + ); + } + + const DEV_SEED_PERSON_CUSTOM_FIELDS = getDevSeedPeopleCustomFields( + personObjectMetadataId, + workspaceId, + ); + + for (const customField of DEV_SEED_PERSON_CUSTOM_FIELDS) { + await this.fieldMetadataService.createOne({ + ...customField, + isCustom: true, + }); + } + } } diff --git a/packages/twenty-server/src/database/commands/database-command.module.ts b/packages/twenty-server/src/database/commands/database-command.module.ts index b06b92e6c..80d685c95 100644 --- a/packages/twenty-server/src/database/commands/database-command.module.ts +++ b/packages/twenty-server/src/database/commands/database-command.module.ts @@ -16,6 +16,7 @@ import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { WorkspaceModule } from 'src/engine/core-modules/workspace/workspace.module'; 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 { FieldMetadataModule } from 'src/engine/metadata-modules/field-metadata/field-metadata.module'; import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadata/object-metadata.module'; import { WorkspaceCacheVersionModule } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.module'; @@ -42,6 +43,7 @@ import { WorkspaceSyncMetadataModule } from 'src/engine/workspace-manager/worksp WorkspaceSyncMetadataModule, WorkspaceStatusModule, ObjectMetadataModule, + FieldMetadataModule, DataSeedDemoWorkspaceModule, WorkspaceCacheVersionModule, UpgradeTo0_23CommandModule, diff --git a/packages/twenty-server/src/database/typeorm-seeds/metadata/fieldsMetadata.ts b/packages/twenty-server/src/database/typeorm-seeds/metadata/fieldsMetadata.ts new file mode 100644 index 000000000..ec8135154 --- /dev/null +++ b/packages/twenty-server/src/database/typeorm-seeds/metadata/fieldsMetadata.ts @@ -0,0 +1,174 @@ +import { CreateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input'; +import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; + +export const getDevSeedCompanyCustomFields = ( + objectMetadataId: string, + workspaceId: string, +): CreateFieldInput[] => { + return [ + { + workspaceId, + type: FieldMetadataType.TEXT, + name: 'tagline', + label: 'Tagline', + description: "Company's Tagline", + icon: 'IconAdCircle', + isActive: true, + isNullable: false, + objectMetadataId, + }, + { + workspaceId, + type: FieldMetadataType.LINKS, + name: 'introVideo', + label: 'Intro Video', + description: "Company's Intro Video", + icon: 'IconVideo', + isActive: true, + isNullable: true, + objectMetadataId, + }, + { + workspaceId, + type: FieldMetadataType.MULTI_SELECT, + name: 'workPolicy', + label: 'Work Policy', + description: "Company's Work Policy", + icon: 'IconHome', + isActive: true, + isNullable: true, + objectMetadataId, + options: [ + { + color: 'green', + label: 'On-Site', + position: 0, + value: 'ON_SITE', + }, + { + color: 'turquoise', + label: 'Hybrid', + position: 1, + value: 'HYBRID', + }, + { + color: 'sky', + label: 'Remote Work', + position: 2, + value: 'REMOTE_WORK', + }, + ], + }, + { + workspaceId, + type: FieldMetadataType.BOOLEAN, + name: 'visaSponsorship', + label: 'Visa Sponsorship', + description: "Company's Visa Sponsorship Policy", + icon: 'IconBrandVisa', + isActive: true, + isNullable: true, + objectMetadataId, + defaultValue: false, + }, + ]; +}; + +export const getDevSeedPeopleCustomFields = ( + objectMetadataId: string, + workspaceId: string, +): CreateFieldInput[] => { + return [ + { + workspaceId, + type: FieldMetadataType.TEXT, + name: 'intro', + label: 'Intro', + description: "Contact's Intro", + icon: 'IconNote', + isActive: true, + isNullable: true, + objectMetadataId, + }, + { + workspaceId, + type: FieldMetadataType.PHONE, + name: 'whatsapp', + label: 'Whatsapp', + description: "Contact's Whatsapp Number", + icon: 'IconBrandWhatsapp', + isActive: true, + isNullable: false, + objectMetadataId, + }, + { + workspaceId, + type: FieldMetadataType.MULTI_SELECT, + name: 'workPrefereance', + label: 'Work Preference', + description: "Person's Work Preference", + icon: 'IconHome', + isActive: true, + isNullable: true, + objectMetadataId, + options: [ + { + color: 'green', + label: 'On-Site', + position: 0, + value: 'ON_SITE', + }, + { + color: 'turquoise', + label: 'Hybrid', + position: 1, + value: 'HYBRID', + }, + { + color: 'sky', + label: 'Remote Work', + position: 2, + value: 'REMOTE_WORK', + }, + ], + }, + { + workspaceId, + type: FieldMetadataType.RATING, + name: 'performanceRating', + label: 'Performance Rating', + description: "Person's Performance Rating", + icon: 'IconStars', + isActive: true, + isNullable: true, + objectMetadataId, + options: [ + { + label: '1', + value: 'RATING_1', + position: 0, + }, + { + label: '2', + value: 'RATING_2', + position: 1, + }, + { + label: '3', + value: 'RATING_3', + position: 2, + }, + { + label: '4', + value: 'RATING_4', + position: 3, + }, + { + label: '5', + value: 'RATING_5', + position: 4, + }, + ], + }, + ]; +}; diff --git a/packages/twenty-server/src/database/typeorm-seeds/workspace/companies.ts b/packages/twenty-server/src/database/typeorm-seeds/workspace/companies.ts index c2e84868d..6b149edee 100644 --- a/packages/twenty-server/src/database/typeorm-seeds/workspace/companies.ts +++ b/packages/twenty-server/src/database/typeorm-seeds/workspace/companies.ts @@ -38,6 +38,8 @@ export const seedCompanies = async ( 'addressAddressPostcode', 'addressAddressCountry', 'position', + 'tagline', + 'workPolicy', 'createdBySource', 'createdByWorkspaceMemberId', 'createdByName', @@ -55,6 +57,8 @@ export const seedCompanies = async ( addressAddressPostcode: null, addressAddressCountry: 'Ireland', position: 1, + tagline: "Linkedin's tagline", + workPolicy: ['ON_SITE'], createdBySource: 'MANUAL', createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM, createdByName: 'Tim Apple', @@ -70,6 +74,8 @@ export const seedCompanies = async ( addressAddressPostcode: null, addressAddressCountry: null, position: 2, + tagline: "Facebook's tagline", + workPolicy: ['REMOTE_WORK'], createdBySource: 'MANUAL', createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM, createdByName: 'Tim Apple', @@ -85,6 +91,8 @@ export const seedCompanies = async ( addressAddressPostcode: '75009', addressAddressCountry: 'France', position: 3, + tagline: "Qonto's tagline", + workPolicy: ['ON_SITE'], createdBySource: 'MANUAL', createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM, createdByName: 'Tim Apple', @@ -100,6 +108,8 @@ export const seedCompanies = async ( addressAddressPostcode: null, addressAddressCountry: null, position: 4, + tagline: "Microsoft's tagline", + workPolicy: ['ON_SITE', 'HYBRID'], createdBySource: 'MANUAL', createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM, createdByName: 'Tim Apple', @@ -115,6 +125,8 @@ export const seedCompanies = async ( addressAddressPostcode: '94103', addressAddressCountry: 'United States', position: 5, + tagline: "Airbnb's tagline", + workPolicy: ['ON_SITE'], createdBySource: 'MANUAL', createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM, createdByName: 'Tim Apple', @@ -130,6 +142,8 @@ export const seedCompanies = async ( addressAddressPostcode: '94102', addressAddressCountry: 'United States', position: 6, + tagline: "Google's tagline", + workPolicy: ['HYBRID', 'REMOTE_WORK'], createdBySource: 'MANUAL', createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM, createdByName: 'Tim Apple', @@ -145,6 +159,8 @@ export const seedCompanies = async ( addressAddressPostcode: '94110', addressAddressCountry: 'United States', position: 7, + tagline: "Netflix's tagline", + workPolicy: ['REMOTE_WORK'], createdBySource: 'MANUAL', createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM, createdByName: 'Tim Apple', @@ -160,6 +176,8 @@ export const seedCompanies = async ( addressAddressPostcode: null, addressAddressCountry: null, position: 8, + tagline: "Libeo's tagline", + workPolicy: ['HYBRID'], createdBySource: 'MANUAL', createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM, createdByName: 'Tim Apple', @@ -175,6 +193,8 @@ export const seedCompanies = async ( addressAddressPostcode: null, addressAddressCountry: null, position: 9, + tagline: "Claap's tagline", + workPolicy: ['ON_SITE', 'REMOTE_WORK'], createdBySource: 'MANUAL', createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM, createdByName: 'Tim Apple', @@ -190,6 +210,8 @@ export const seedCompanies = async ( addressAddressPostcode: null, addressAddressCountry: null, position: 10, + tagline: "Hasura's tagline", + workPolicy: ['HYBRID'], createdBySource: 'MANUAL', createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM, createdByName: 'Tim Apple', @@ -205,6 +227,8 @@ export const seedCompanies = async ( addressAddressPostcode: null, addressAddressCountry: null, position: 11, + tagline: "Wework's tagline", + workPolicy: ['ON_SITE'], createdBySource: 'MANUAL', createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM, createdByName: 'Tim Apple', @@ -220,6 +244,8 @@ export const seedCompanies = async ( addressAddressPostcode: null, addressAddressCountry: null, position: 12, + tagline: "Samsung's tagline", + workPolicy: ['HYBRID'], createdBySource: 'MANUAL', createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM, createdByName: 'Tim Apple', @@ -235,6 +261,8 @@ export const seedCompanies = async ( addressAddressPostcode: null, addressAddressCountry: null, position: 13, + tagline: "Algolia's tagline", + workPolicy: ['ON_SITE'], createdBySource: 'MANUAL', createdByWorkspaceMemberId: null, createdByName: '', diff --git a/packages/twenty-server/src/database/typeorm-seeds/workspace/people.ts b/packages/twenty-server/src/database/typeorm-seeds/workspace/people.ts index 27cdfccda..6063b4be6 100644 --- a/packages/twenty-server/src/database/typeorm-seeds/workspace/people.ts +++ b/packages/twenty-server/src/database/typeorm-seeds/workspace/people.ts @@ -39,6 +39,7 @@ export const seedPeople = async ( 'companyId', 'email', 'position', + 'whatsapp', 'createdBySource', 'createdByWorkspaceMemberId', 'createdByName', @@ -54,6 +55,7 @@ export const seedPeople = async ( companyId: DEV_SEED_COMPANY_IDS.LINKEDIN, email: 'christoph.calisto@linkedin.com', position: 1, + whatsapp: '+33789012345', createdBySource: 'MANUAL', createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM, createdByName: 'Tim Apple', @@ -67,6 +69,7 @@ export const seedPeople = async ( companyId: DEV_SEED_COMPANY_IDS.LINKEDIN, email: 'sylvie.palmer@linkedin.com', position: 2, + whatsapp: '+33780123456', createdBySource: 'MANUAL', createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM, createdByName: 'Tim Apple', @@ -80,6 +83,7 @@ export const seedPeople = async ( companyId: DEV_SEED_COMPANY_IDS.QONTO, email: 'christopher.gonzalez@qonto.com', position: 3, + whatsapp: '+33789012345', createdBySource: 'MANUAL', createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM, createdByName: 'Tim Apple', @@ -93,6 +97,7 @@ export const seedPeople = async ( companyId: DEV_SEED_COMPANY_IDS.QONTO, email: 'ashley.parker@qonto.com', position: 4, + whatsapp: '+33780123456', createdBySource: 'MANUAL', createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM, createdByName: 'Tim Apple', @@ -106,6 +111,7 @@ export const seedPeople = async ( companyId: DEV_SEED_COMPANY_IDS.MICROSOFT, email: 'nicholas.wright@microsoft.com', position: 5, + whatsapp: '+33781234567', createdBySource: 'MANUAL', createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM, createdByName: 'Tim Apple', @@ -119,6 +125,7 @@ export const seedPeople = async ( companyId: DEV_SEED_COMPANY_IDS.MICROSOFT, email: 'isabella.scott@microsoft.com', position: 6, + whatsapp: '+33782345678', createdBySource: 'MANUAL', createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM, createdByName: 'Tim Apple', @@ -132,6 +139,7 @@ export const seedPeople = async ( companyId: DEV_SEED_COMPANY_IDS.MICROSOFT, email: 'matthew.green@microsoft.com', position: 7, + whatsapp: '+33783456789', createdBySource: 'MANUAL', createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM, createdByName: 'Tim Apple', @@ -145,6 +153,7 @@ export const seedPeople = async ( companyId: DEV_SEED_COMPANY_IDS.AIRBNB, email: 'elizabeth.baker@airbnb.com', position: 8, + whatsapp: '+33784567890', createdBySource: 'MANUAL', createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM, createdByName: 'Tim Apple', @@ -158,6 +167,7 @@ export const seedPeople = async ( companyId: DEV_SEED_COMPANY_IDS.AIRBNB, email: 'christopher.nelson@airbnb.com', position: 9, + whatsapp: '+33785678901', createdBySource: 'MANUAL', createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM, createdByName: 'Tim Apple', @@ -171,6 +181,7 @@ export const seedPeople = async ( companyId: DEV_SEED_COMPANY_IDS.AIRBNB, email: 'avery.carter@airbnb.com', position: 10, + whatsapp: '+33786789012', createdBySource: 'MANUAL', createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM, createdByName: 'Tim Apple', @@ -184,6 +195,7 @@ export const seedPeople = async ( companyId: DEV_SEED_COMPANY_IDS.GOOGLE, email: 'ethan.mitchell@google.com', position: 11, + whatsapp: '+33787890123', createdBySource: 'MANUAL', createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM, createdByName: 'Tim Apple', @@ -197,6 +209,7 @@ export const seedPeople = async ( companyId: DEV_SEED_COMPANY_IDS.GOOGLE, email: 'madison.perez@google.com', position: 12, + whatsapp: '+33788901234', createdBySource: 'MANUAL', createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM, createdByName: 'Tim Apple', @@ -210,6 +223,7 @@ export const seedPeople = async ( companyId: DEV_SEED_COMPANY_IDS.GOOGLE, email: 'bertrand.voulzy@google.com', position: 13, + whatsapp: '+33788901234', createdBySource: 'MANUAL', createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM, createdByName: 'Tim Apple', @@ -223,6 +237,7 @@ export const seedPeople = async ( companyId: DEV_SEED_COMPANY_IDS.GOOGLE, email: 'louis.duss@google.com', position: 14, + whatsapp: '+33788901234', createdBySource: 'MANUAL', createdByWorkspaceMemberId: DEV_SEED_WORKSPACE_MEMBER_IDS.TIM, createdByName: 'Tim Apple', @@ -236,6 +251,7 @@ export const seedPeople = async ( companyId: DEV_SEED_COMPANY_IDS.GOOGLE, email: 'lorie.vladim@google.com', position: 15, + whatsapp: '+33788901235', createdBySource: 'MANUAL', createdByWorkspaceMemberId: null, createdByName: '',