Metadata api create entity in workspace custom app (#15911)
# Introduction Cleaner and fewer scope version of https://github.com/twentyhq/twenty/pull/15745 ( removed sync-metadata hack through, too ambitious migration and upgrade ) Please note that this PR won't have any interaction with the existing sync-metadata Which mean that the sync metadata does not update the standard entities applicationId and universalIdentifier, and it won't we will deprecate it on favor of a workspace migration aka twenty-standard app installation ## API Metadata Any operation going through the api metadata nows automatically scope the related entity to the workspace custom application instance. ( optionally passing an applicationId to allow current hacky implem of app sync service ) We need to either ignore the tests or remove the cli status check from the blocking status badges for a PR to be merged ## New workspace Already handled in previous https://github.com/twentyhq/twenty/pull/15625, when a workspace is created it gets created a twenty standard and custom workspace instance All his views and permissions will be prefilled to the its twenty standard app instance with a specific universalIdentifier ## New universalIdentifier At the contrary as before with standardIds, universalIdentifier are unique for a given workspace This means that createdAt field of both object company and opportunity will have a unique universalIdentifier whereas they share the same standardId ## FlatApplication Introduced the flatApplication and cache. Will migrate existing `MetadataName` to be `SyncableMetadataName` in a following PR ## What's next Next we will describe a twenty standard app configuration as json that will be used to generate a workspace migration that will be run instead of the sync metadata, in a nutshell we aim to deprecated the sync metadata So we can standardize any entity to have a non nullable applicationId and universalIdentifier ## Upgrade command Introduced an upgrade command that will create a custom workspace instance for any workspace that do not have one in order to align with the new behavior when creating a new workspace
This commit is contained in:
+19
-2
@@ -9,6 +9,7 @@ import {
|
||||
ActiveOrSuspendedWorkspacesMigrationCommandRunner,
|
||||
type RunOnWorkspaceArgs,
|
||||
} from 'src/database/commands/command-runners/active-or-suspended-workspaces-migration.command-runner';
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { DataSourceEntity } from 'src/engine/metadata-modules/data-source/data-source.entity';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
@@ -37,6 +38,7 @@ export class SeedDashboardViewCommand extends ActiveOrSuspendedWorkspacesMigrati
|
||||
private readonly dataSourceRepository: Repository<DataSourceEntity>,
|
||||
@InjectRepository(ViewEntity)
|
||||
private readonly viewRepository: Repository<ViewEntity>,
|
||||
private readonly applicationService: ApplicationService,
|
||||
) {
|
||||
super(workspaceRepository, twentyORMGlobalManager);
|
||||
}
|
||||
@@ -59,7 +61,17 @@ export class SeedDashboardViewCommand extends ActiveOrSuspendedWorkspacesMigrati
|
||||
);
|
||||
}
|
||||
|
||||
const views = [dashboardsAllView([dashboardObjectMetadata], true)];
|
||||
const { twentyStandardFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{ workspaceId },
|
||||
);
|
||||
const views = [
|
||||
dashboardsAllView({
|
||||
objectMetadataItems: [dashboardObjectMetadata],
|
||||
useCoreNaming: true,
|
||||
twentyStandardFlatApplication,
|
||||
}),
|
||||
];
|
||||
|
||||
const schema = await this.dataSourceRepository.findOne({
|
||||
where: {
|
||||
@@ -99,7 +111,12 @@ export class SeedDashboardViewCommand extends ActiveOrSuspendedWorkspacesMigrati
|
||||
|
||||
await queryRunner.connect();
|
||||
|
||||
const createdViews = await createCoreViews(queryRunner, workspaceId, views);
|
||||
const createdViews = await createCoreViews(
|
||||
queryRunner,
|
||||
workspaceId,
|
||||
views,
|
||||
twentyStandardFlatApplication,
|
||||
);
|
||||
|
||||
await prefillWorkspaceFavorites(
|
||||
createdViews.map((view) => view.id),
|
||||
|
||||
+6
@@ -11,9 +11,12 @@ import { MigrateAttachmentTypeToFileCategoryCommand } from 'src/database/command
|
||||
import { MigrateChannelPartialFullSyncStagesCommand } from 'src/database/commands/upgrade-version-command/1-10/1-10-migrate-channel-partial-full-sync-stages.command';
|
||||
import { RegenerateSearchVectorsCommand } from 'src/database/commands/upgrade-version-command/1-10/1-10-regenerate-search-vectors.command';
|
||||
import { SeedDashboardViewCommand } from 'src/database/commands/upgrade-version-command/1-10/1-10-seed-dashboard-view.command';
|
||||
import { ApplicationEntity } from 'src/engine/core-modules/application/application.entity';
|
||||
import { ApplicationModule } from 'src/engine/core-modules/application/application.module';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { DataSourceEntity } from 'src/engine/metadata-modules/data-source/data-source.entity';
|
||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheModule } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.module';
|
||||
import { IndexMetadataEntity } from 'src/engine/metadata-modules/index-metadata/index-metadata.entity';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadata/object-metadata.module';
|
||||
@@ -30,10 +33,13 @@ import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/
|
||||
IndexMetadataEntity,
|
||||
ViewEntity,
|
||||
DataSourceEntity,
|
||||
ApplicationEntity,
|
||||
]),
|
||||
WorkspaceSchemaManagerModule,
|
||||
WorkspaceCacheStorageModule,
|
||||
ObjectMetadataModule,
|
||||
WorkspaceManyOrAllFlatEntityMapsCacheModule,
|
||||
ApplicationModule,
|
||||
],
|
||||
providers: [
|
||||
MigrateChannelPartialFullSyncStagesCommand,
|
||||
|
||||
+1
-1
@@ -9,9 +9,9 @@ import {
|
||||
} from 'src/database/commands/command-runners/active-or-suspended-workspaces-migration.command-runner';
|
||||
import { ApplicationEntity } from 'src/engine/core-modules/application/application.entity';
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
|
||||
import { TWENTY_STANDARD_APPLICATION } from 'src/engine/core-modules/application/constants/twenty-standard-applications';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
|
||||
import { TWENTY_STANDARD_APPLICATION } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/twenty-standard-applications';
|
||||
|
||||
@Command({
|
||||
name: 'upgrade:1-11:create-twenty-standard-application',
|
||||
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { Command } from 'nest-commander';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import {
|
||||
ActiveOrSuspendedWorkspacesMigrationCommandRunner,
|
||||
type RunOnWorkspaceArgs,
|
||||
} from 'src/database/commands/command-runners/active-or-suspended-workspaces-migration.command-runner';
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
|
||||
|
||||
@Command({
|
||||
name: 'upgrade:1-12:create-workspace-custom-application',
|
||||
description:
|
||||
'Create workspace-custom application for workspaces that do not have them',
|
||||
})
|
||||
export class CreateWorkspaceCustomApplicationCommand extends ActiveOrSuspendedWorkspacesMigrationCommandRunner {
|
||||
constructor(
|
||||
@InjectRepository(WorkspaceEntity)
|
||||
protected readonly workspaceRepository: Repository<WorkspaceEntity>,
|
||||
protected readonly twentyORMGlobalManager: TwentyORMGlobalManager,
|
||||
private readonly applicationService: ApplicationService,
|
||||
) {
|
||||
super(workspaceRepository, twentyORMGlobalManager);
|
||||
}
|
||||
|
||||
override async runOnWorkspace({
|
||||
workspaceId,
|
||||
}: RunOnWorkspaceArgs): Promise<void> {
|
||||
this.logger.log(
|
||||
`Checking standard applications for workspace ${workspaceId}`,
|
||||
);
|
||||
|
||||
const workspace = await this.workspaceRepository.findOne({
|
||||
where: { id: workspaceId },
|
||||
});
|
||||
|
||||
if (!isDefined(workspace)) {
|
||||
throw new Error(`${workspaceId} workspace not found`);
|
||||
}
|
||||
|
||||
if (isDefined(workspace.workspaceCustomApplicationId)) {
|
||||
this.logger.log(
|
||||
`${workspaceId} skipping custom workspace application creation as already exists`,
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const customWorkspaceApplication =
|
||||
await this.applicationService.createWorkspaceCustomApplication({
|
||||
workspaceId,
|
||||
workspaceDisplayName: workspace.displayName,
|
||||
});
|
||||
|
||||
await this.workspaceRepository.update(workspace.id, {
|
||||
workspaceCustomApplicationId: customWorkspaceApplication.id,
|
||||
});
|
||||
|
||||
this.logger.log(`Successfully create workspace custom application`);
|
||||
}
|
||||
}
|
||||
+15
-23
@@ -1,18 +1,17 @@
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { Repository } from 'typeorm';
|
||||
import { Command } from 'nest-commander';
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
|
||||
import { ApplicationEntity } from 'src/engine/core-modules/application/application.entity';
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
|
||||
import {
|
||||
ActiveOrSuspendedWorkspacesMigrationCommandRunner,
|
||||
RunOnWorkspaceArgs,
|
||||
} from 'src/database/commands/command-runners/active-or-suspended-workspaces-migration.command-runner';
|
||||
import { TWENTY_STANDARD_APPLICATION } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/twenty-standard-applications';
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
|
||||
|
||||
// Note: this command needs to be run after CreateWorkspaceCustomApplicationCommand
|
||||
@Command({
|
||||
name: 'upgrade:1-12:set-standard-application-not-uninstallable',
|
||||
description: 'Set canBeUninstalled flag to false for standard applications',
|
||||
@@ -22,8 +21,6 @@ export class SetStandardApplicationNotUninstallableCommand extends ActiveOrSuspe
|
||||
@InjectRepository(WorkspaceEntity)
|
||||
protected readonly workspaceRepository: Repository<WorkspaceEntity>,
|
||||
protected readonly twentyORMGlobalManager: TwentyORMGlobalManager,
|
||||
@InjectRepository(ApplicationEntity)
|
||||
private readonly applicationRepository: Repository<ApplicationEntity>,
|
||||
private readonly applicationService: ApplicationService,
|
||||
) {
|
||||
super(workspaceRepository, twentyORMGlobalManager);
|
||||
@@ -35,36 +32,31 @@ export class SetStandardApplicationNotUninstallableCommand extends ActiveOrSuspe
|
||||
}: RunOnWorkspaceArgs): Promise<void> {
|
||||
try {
|
||||
this.logger.log(
|
||||
`Checking standard applications for workspace ${workspaceId}`,
|
||||
`Checking workspace applications for workspace ${workspaceId}`,
|
||||
);
|
||||
|
||||
const existingApplications = await this.applicationRepository.find({
|
||||
where: [
|
||||
const { twentyStandardFlatApplication, workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
universalIdentifier:
|
||||
TWENTY_STANDARD_APPLICATION.universalIdentifier,
|
||||
},
|
||||
{
|
||||
workspaceId,
|
||||
description: 'Workspace custom application',
|
||||
sourcePath: 'workspace-custom',
|
||||
},
|
||||
],
|
||||
});
|
||||
);
|
||||
|
||||
if (options.dryRun) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const existingApplication of existingApplications) {
|
||||
for (const existingApplication of [
|
||||
twentyStandardFlatApplication,
|
||||
workspaceCustomFlatApplication,
|
||||
]) {
|
||||
await this.applicationService.update(existingApplication.id, {
|
||||
canBeUninstalled: false,
|
||||
});
|
||||
}
|
||||
this.logger.log(`Successfully updated standard applications`);
|
||||
this.logger.log(`Successfully updated workspace application`);
|
||||
} catch (e) {
|
||||
this.logger.error(`Failed to update standard applications`, e);
|
||||
this.logger.error(`Failed to update workspace application`, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+13
-7
@@ -1,19 +1,25 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { ApplicationEntity } from 'src/engine/core-modules/application/application.entity';
|
||||
import { WorkspaceSchemaManagerModule } from 'src/engine/twenty-orm/workspace-schema-manager/workspace-schema-manager.module';
|
||||
import { ApplicationModule } from 'src/engine/core-modules/application/application.module';
|
||||
import { CreateWorkspaceCustomApplicationCommand } from 'src/database/commands/upgrade-version-command/1-12/1-12-create-workspace-custom-application.command';
|
||||
import { SetStandardApplicationNotUninstallableCommand } from 'src/database/commands/upgrade-version-command/1-12/1-12-set-standard-application-not-uninstallable.command';
|
||||
import { ApplicationModule } from 'src/engine/core-modules/application/application.module';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { WorkspaceSchemaManagerModule } from 'src/engine/twenty-orm/workspace-schema-manager/workspace-schema-manager.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([WorkspaceEntity, ApplicationEntity]),
|
||||
TypeOrmModule.forFeature([WorkspaceEntity]),
|
||||
WorkspaceSchemaManagerModule,
|
||||
ApplicationModule,
|
||||
],
|
||||
providers: [SetStandardApplicationNotUninstallableCommand],
|
||||
exports: [SetStandardApplicationNotUninstallableCommand],
|
||||
providers: [
|
||||
CreateWorkspaceCustomApplicationCommand,
|
||||
SetStandardApplicationNotUninstallableCommand,
|
||||
],
|
||||
exports: [
|
||||
CreateWorkspaceCustomApplicationCommand,
|
||||
SetStandardApplicationNotUninstallableCommand,
|
||||
],
|
||||
})
|
||||
export class V1_12_UpgradeVersionCommandModule {}
|
||||
|
||||
+1
-1
@@ -3,10 +3,10 @@ import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { V1_10_UpgradeVersionCommandModule } from 'src/database/commands/upgrade-version-command/1-10/1-10-upgrade-version-command.module';
|
||||
import { V1_11_UpgradeVersionCommandModule } from 'src/database/commands/upgrade-version-command/1-11/1-11-upgrade-version-command.module';
|
||||
import { V1_12_UpgradeVersionCommandModule } from 'src/database/commands/upgrade-version-command/1-12/1-12-upgrade-version-command.module';
|
||||
import { V1_6_UpgradeVersionCommandModule } from 'src/database/commands/upgrade-version-command/1-6/1-6-upgrade-version-command.module';
|
||||
import { V1_7_UpgradeVersionCommandModule } from 'src/database/commands/upgrade-version-command/1-7/1-7-upgrade-version-command.module';
|
||||
import { V1_8_UpgradeVersionCommandModule } from 'src/database/commands/upgrade-version-command/1-8/1-8-upgrade-version-command.module';
|
||||
import { V1_12_UpgradeVersionCommandModule } from 'src/database/commands/upgrade-version-command/1-12/1-12-upgrade-version-command.module';
|
||||
import { UpgradeCommand } from 'src/database/commands/upgrade-version-command/upgrade.command';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { WorkspaceSyncMetadataModule } from 'src/engine/workspace-manager/workspace-sync-metadata/workspace-sync-metadata.module';
|
||||
|
||||
+6
-6
@@ -18,10 +18,11 @@ import { MigrateAttachmentAuthorToCreatedByCommand } from 'src/database/commands
|
||||
import { MigrateAttachmentTypeToFileCategoryCommand } from 'src/database/commands/upgrade-version-command/1-10/1-10-migrate-attachment-type-to-file-category.command';
|
||||
import { MigrateChannelPartialFullSyncStagesCommand } from 'src/database/commands/upgrade-version-command/1-10/1-10-migrate-channel-partial-full-sync-stages.command';
|
||||
import { RegenerateSearchVectorsCommand } from 'src/database/commands/upgrade-version-command/1-10/1-10-regenerate-search-vectors.command';
|
||||
import { SeedDashboardViewCommand } from 'src/database/commands/upgrade-version-command/1-10/1-10-seed-dashboard-view.command';
|
||||
import { CleanOrphanedRoleTargetsCommand } from 'src/database/commands/upgrade-version-command/1-11/1-11-clean-orphaned-role-targets.command';
|
||||
import { CleanOrphanedUserWorkspacesCommand } from 'src/database/commands/upgrade-version-command/1-11/1-11-clean-orphaned-user-workspaces.command';
|
||||
import { CreateTwentyStandardApplicationCommand } from 'src/database/commands/upgrade-version-command/1-11/1-11-create-twenty-standard-application.command';
|
||||
import { CreateWorkspaceCustomApplicationCommand } from 'src/database/commands/upgrade-version-command/1-12/1-12-create-workspace-custom-application.command';
|
||||
import { SetStandardApplicationNotUninstallableCommand } from 'src/database/commands/upgrade-version-command/1-12/1-12-set-standard-application-not-uninstallable.command';
|
||||
import { FixLabelIdentifierPositionAndVisibilityCommand } from 'src/database/commands/upgrade-version-command/1-6/1-6-fix-label-identifier-position-and-visibility.command';
|
||||
import { BackfillWorkflowManualTriggerAvailabilityCommand } from 'src/database/commands/upgrade-version-command/1-7/1-7-backfill-workflow-manual-trigger-availability.command';
|
||||
import { DeduplicateUniqueFieldsCommand } from 'src/database/commands/upgrade-version-command/1-8/1-8-deduplicate-unique-fields.command';
|
||||
@@ -33,7 +34,6 @@ import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twent
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
|
||||
import { SyncWorkspaceMetadataCommand } from 'src/engine/workspace-manager/workspace-sync-metadata/commands/sync-workspace-metadata.command';
|
||||
import { SetStandardApplicationNotUninstallableCommand } from 'src/database/commands/upgrade-version-command/1-12/1-12-set-standard-application-not-uninstallable.command';
|
||||
|
||||
@Command({
|
||||
name: 'upgrade',
|
||||
@@ -70,7 +70,6 @@ export class UpgradeCommand extends UpgradeCommandRunner {
|
||||
protected readonly cleanOrphanedKanbanAggregateOperationFieldMetadataIdCommand: CleanOrphanedKanbanAggregateOperationFieldMetadataIdCommand,
|
||||
protected readonly migrateChannelPartialFullSyncStagesCommand: MigrateChannelPartialFullSyncStagesCommand,
|
||||
protected readonly makeSureDashboardNamingAvailableCommand: MakeSureDashboardNamingAvailableCommand,
|
||||
protected readonly seedDashboardViewCommand: SeedDashboardViewCommand,
|
||||
protected readonly createViewKanbanFieldMetadataIdForeignKeyMigrationCommand: CreateViewKanbanFieldMetadataIdForeignKeyMigrationCommand,
|
||||
protected readonly flushWorkspaceCacheCommand: FlushCacheCommand,
|
||||
|
||||
@@ -81,6 +80,8 @@ export class UpgradeCommand extends UpgradeCommandRunner {
|
||||
|
||||
// 1.12 Commands
|
||||
protected readonlysetStandardApplicationNotUninstallableCommand: SetStandardApplicationNotUninstallableCommand,
|
||||
protected readonly createTwentyStandardApplicationCommand: CreateTwentyStandardApplicationCommand,
|
||||
protected readonly createWorkspaceCustomApplicationCommand: CreateWorkspaceCustomApplicationCommand,
|
||||
) {
|
||||
super(
|
||||
workspaceRepository,
|
||||
@@ -124,13 +125,12 @@ export class UpgradeCommand extends UpgradeCommandRunner {
|
||||
afterSyncMetadata: [
|
||||
this.migrateAttachmentAuthorToCreatedByCommand,
|
||||
this.migrateAttachmentTypeToFileCategoryCommand,
|
||||
this.seedDashboardViewCommand,
|
||||
this.flushWorkspaceCacheCommand,
|
||||
],
|
||||
};
|
||||
|
||||
const commands_1110: VersionCommands = {
|
||||
beforeSyncMetadata: [this.seedStandardApplicationsCommand],
|
||||
beforeSyncMetadata: [this.createTwentyStandardApplicationCommand],
|
||||
afterSyncMetadata: [
|
||||
this.cleanOrphanedUserWorkspacesCommand,
|
||||
this.cleanOrphanedRoleTargetsCommand,
|
||||
@@ -138,7 +138,7 @@ export class UpgradeCommand extends UpgradeCommandRunner {
|
||||
};
|
||||
|
||||
const commands_1120: VersionCommands = {
|
||||
beforeSyncMetadata: [],
|
||||
beforeSyncMetadata: [this.createWorkspaceCustomApplicationCommand],
|
||||
afterSyncMetadata: [
|
||||
this.readonlysetStandardApplicationNotUninstallableCommand,
|
||||
],
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
|
||||
import { ApplicationResolver } from 'src/engine/core-modules/application/application.resolver';
|
||||
import { ApplicationSyncService } from 'src/engine/core-modules/application/application-sync.service';
|
||||
import { ApplicationModule } from 'src/engine/core-modules/application/application.module';
|
||||
import { ApplicationVariableEntityModule } from 'src/engine/core-modules/applicationVariable/application-variable.module';
|
||||
import { CronTriggerModule } from 'src/engine/metadata-modules/cron-trigger/cron-trigger.module';
|
||||
import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module';
|
||||
import { DatabaseEventTriggerModule } from 'src/engine/metadata-modules/database-event-trigger/database-event-trigger.module';
|
||||
import { FieldMetadataModule } from 'src/engine/metadata-modules/field-metadata/field-metadata.module';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheModule } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.module';
|
||||
import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadata/object-metadata.module';
|
||||
import { PermissionsModule } from 'src/engine/metadata-modules/permissions/permissions.module';
|
||||
import { RouteTriggerModule } from 'src/engine/metadata-modules/route-trigger/route-trigger.module';
|
||||
import { ServerlessFunctionLayerModule } from 'src/engine/metadata-modules/serverless-function-layer/serverless-function-layer.module';
|
||||
import { ServerlessFunctionModule } from 'src/engine/metadata-modules/serverless-function/serverless-function.module';
|
||||
import { WorkspaceMigrationV2Module } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-v2.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
ApplicationModule,
|
||||
ApplicationVariableEntityModule,
|
||||
WorkspaceManyOrAllFlatEntityMapsCacheModule,
|
||||
ObjectMetadataModule,
|
||||
FieldMetadataModule,
|
||||
DataSourceModule,
|
||||
ServerlessFunctionLayerModule,
|
||||
ServerlessFunctionModule,
|
||||
DatabaseEventTriggerModule,
|
||||
CronTriggerModule,
|
||||
RouteTriggerModule,
|
||||
WorkspaceMigrationV2Module,
|
||||
PermissionsModule,
|
||||
],
|
||||
providers: [ApplicationResolver, ApplicationSyncService],
|
||||
exports: [ApplicationSyncService],
|
||||
})
|
||||
export class ApplicationSyncModule {}
|
||||
+17
@@ -284,6 +284,7 @@ export class ApplicationSyncService {
|
||||
await this.fieldMetadataServiceV2.createOneField({
|
||||
createFieldInput,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -406,6 +407,7 @@ export class ApplicationSyncService {
|
||||
|
||||
const createdObject = await this.objectMetadataServiceV2.createOneObject({
|
||||
createObjectInput,
|
||||
applicationId,
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
@@ -526,18 +528,21 @@ export class ApplicationSyncService {
|
||||
serverlessFunctionId: serverlessFunctionToUpdate.id,
|
||||
triggersToSync: serverlessFunctionToSync.triggers || [],
|
||||
workspaceId,
|
||||
applicationId,
|
||||
});
|
||||
|
||||
await this.syncCronTriggersForServerlessFunction({
|
||||
serverlessFunctionId: serverlessFunctionToUpdate.id,
|
||||
triggersToSync: serverlessFunctionToSync.triggers || [],
|
||||
workspaceId,
|
||||
applicationId,
|
||||
});
|
||||
|
||||
await this.syncRouteTriggersForServerlessFunction({
|
||||
serverlessFunctionId: serverlessFunctionToUpdate.id,
|
||||
triggersToSync: serverlessFunctionToSync.triggers || [],
|
||||
workspaceId,
|
||||
applicationId,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -567,18 +572,21 @@ export class ApplicationSyncService {
|
||||
serverlessFunctionId: createdServerlessFunction.id,
|
||||
triggersToSync: serverlessFunctionToCreate.triggers || [],
|
||||
workspaceId,
|
||||
applicationId,
|
||||
});
|
||||
|
||||
await this.syncCronTriggersForServerlessFunction({
|
||||
serverlessFunctionId: createdServerlessFunction.id,
|
||||
triggersToSync: serverlessFunctionToCreate.triggers || [],
|
||||
workspaceId,
|
||||
applicationId,
|
||||
});
|
||||
|
||||
await this.syncRouteTriggersForServerlessFunction({
|
||||
serverlessFunctionId: createdServerlessFunction.id,
|
||||
triggersToSync: serverlessFunctionToCreate.triggers || [],
|
||||
workspaceId,
|
||||
applicationId,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -587,10 +595,12 @@ export class ApplicationSyncService {
|
||||
serverlessFunctionId,
|
||||
triggersToSync,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
}: {
|
||||
serverlessFunctionId: string;
|
||||
triggersToSync: ServerlessFunctionTriggerManifest[];
|
||||
workspaceId: string;
|
||||
applicationId: string;
|
||||
}) {
|
||||
const databaseEventTriggersToSync = triggersToSync.filter(
|
||||
(trigger) => trigger.type === 'databaseEvent',
|
||||
@@ -695,6 +705,7 @@ export class ApplicationSyncService {
|
||||
await this.databaseEventTriggerV2Service.createOne(
|
||||
createDatabaseEventTriggerInput,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -703,10 +714,12 @@ export class ApplicationSyncService {
|
||||
serverlessFunctionId,
|
||||
triggersToSync,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
}: {
|
||||
serverlessFunctionId: string;
|
||||
triggersToSync: ServerlessFunctionTriggerManifest[];
|
||||
workspaceId: string;
|
||||
applicationId: string;
|
||||
}) {
|
||||
const cronTriggersToSync = triggersToSync.filter(
|
||||
(trigger) => trigger.type === 'cron',
|
||||
@@ -808,6 +821,7 @@ export class ApplicationSyncService {
|
||||
await this.cronTriggerV2Service.createOne(
|
||||
createCronTriggerInput,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -816,10 +830,12 @@ export class ApplicationSyncService {
|
||||
serverlessFunctionId,
|
||||
triggersToSync,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
}: {
|
||||
serverlessFunctionId: string;
|
||||
triggersToSync: ServerlessFunctionTriggerManifest[];
|
||||
workspaceId: string;
|
||||
applicationId: string;
|
||||
}) {
|
||||
const routeTriggersToSync = triggersToSync.filter(
|
||||
(trigger) => trigger.type === 'route',
|
||||
@@ -922,6 +938,7 @@ export class ApplicationSyncService {
|
||||
await this.routeTriggerV2Service.createOne(
|
||||
createRouteTriggerInput,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,42 +1,19 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { ApplicationSyncService } from 'src/engine/core-modules/application/application-sync.service';
|
||||
import { ApplicationEntity } from 'src/engine/core-modules/application/application.entity';
|
||||
import { ApplicationResolver } from 'src/engine/core-modules/application/application.resolver';
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
|
||||
import { ApplicationVariableEntityModule } from 'src/engine/core-modules/applicationVariable/application-variable.module';
|
||||
import { WorkspaceFlatApplicationMapCacheService } from 'src/engine/core-modules/application/services/workspace-flat-application-map-cache.service';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { AgentEntity } from 'src/engine/metadata-modules/agent/agent.entity';
|
||||
import { CronTriggerModule } from 'src/engine/metadata-modules/cron-trigger/cron-trigger.module';
|
||||
import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module';
|
||||
import { DatabaseEventTriggerModule } from 'src/engine/metadata-modules/database-event-trigger/database-event-trigger.module';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheModule } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.module';
|
||||
import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadata/object-metadata.module';
|
||||
import { PermissionsModule } from 'src/engine/metadata-modules/permissions/permissions.module';
|
||||
import { RouteTriggerModule } from 'src/engine/metadata-modules/route-trigger/route-trigger.module';
|
||||
import { ServerlessFunctionLayerModule } from 'src/engine/metadata-modules/serverless-function-layer/serverless-function-layer.module';
|
||||
import { ServerlessFunctionModule } from 'src/engine/metadata-modules/serverless-function/serverless-function.module';
|
||||
import { WorkspaceMigrationV2Module } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-v2.module';
|
||||
import { FieldMetadataModule } from 'src/engine/metadata-modules/field-metadata/field-metadata.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([ApplicationEntity, AgentEntity, WorkspaceEntity]),
|
||||
WorkspaceManyOrAllFlatEntityMapsCacheModule,
|
||||
ObjectMetadataModule,
|
||||
FieldMetadataModule,
|
||||
DataSourceModule,
|
||||
ApplicationVariableEntityModule,
|
||||
ServerlessFunctionLayerModule,
|
||||
ServerlessFunctionModule,
|
||||
DatabaseEventTriggerModule,
|
||||
CronTriggerModule,
|
||||
RouteTriggerModule,
|
||||
WorkspaceMigrationV2Module,
|
||||
PermissionsModule,
|
||||
],
|
||||
exports: [ApplicationService],
|
||||
providers: [ApplicationResolver, ApplicationService, ApplicationSyncService],
|
||||
exports: [ApplicationService, WorkspaceFlatApplicationMapCacheService],
|
||||
providers: [ApplicationService, WorkspaceFlatApplicationMapCacheService],
|
||||
})
|
||||
export class ApplicationModule {}
|
||||
|
||||
+125
-14
@@ -3,23 +3,86 @@ import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { type QueryRunner, Repository } from 'typeorm';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { ApplicationEntity } from 'src/engine/core-modules/application/application.entity';
|
||||
import {
|
||||
ApplicationException,
|
||||
ApplicationExceptionCode,
|
||||
} from 'src/engine/core-modules/application/application.exception';
|
||||
import { TWENTY_STANDARD_APPLICATION } from 'src/engine/core-modules/application/constants/twenty-standard-applications';
|
||||
import { WorkspaceFlatApplicationMapCacheService } from 'src/engine/core-modules/application/services/workspace-flat-application-map-cache.service';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { TWENTY_STANDARD_APPLICATION } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/twenty-standard-applications';
|
||||
|
||||
@Injectable()
|
||||
export class ApplicationService {
|
||||
constructor(
|
||||
@InjectRepository(ApplicationEntity)
|
||||
private readonly applicationRepository: Repository<ApplicationEntity>,
|
||||
private readonly flatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
|
||||
private readonly workspaceManyOrAllFlatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
|
||||
private readonly workspaceFlatApplicationMapCacheService: WorkspaceFlatApplicationMapCacheService,
|
||||
@InjectRepository(WorkspaceEntity)
|
||||
private readonly workspaceRepository: Repository<WorkspaceEntity>,
|
||||
) {}
|
||||
|
||||
async findWorkspaceTwentyStandardAndCustomApplicationOrThrow({
|
||||
workspaceId,
|
||||
}: {
|
||||
workspaceId: string;
|
||||
}) {
|
||||
const workspace = await this.workspaceRepository.findOne({
|
||||
where: {
|
||||
id: workspaceId,
|
||||
},
|
||||
});
|
||||
|
||||
if (!isDefined(workspace)) {
|
||||
throw new ApplicationException(
|
||||
`Could not find workspace ${workspaceId}`,
|
||||
ApplicationExceptionCode.APPLICATION_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const flatApplicationMaps =
|
||||
await this.workspaceFlatApplicationMapCacheService.getExistingOrRecomputeFlatMaps(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
const twentyStandardApplicationId =
|
||||
flatApplicationMaps.idByUniversalIdentifier[
|
||||
TWENTY_STANDARD_APPLICATION.universalIdentifier
|
||||
];
|
||||
|
||||
if (!isDefined(twentyStandardApplicationId)) {
|
||||
throw new ApplicationException(
|
||||
`Could not find workspace twenty standard applicationId in cache ${workspaceId}`,
|
||||
ApplicationExceptionCode.APPLICATION_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
const twentyStandardFlatApplication =
|
||||
flatApplicationMaps.byId[twentyStandardApplicationId];
|
||||
const workspaceCustomFlatApplication =
|
||||
flatApplicationMaps.byId[workspace.workspaceCustomApplicationId];
|
||||
|
||||
if (
|
||||
!isDefined(twentyStandardFlatApplication) ||
|
||||
!isDefined(workspaceCustomFlatApplication)
|
||||
) {
|
||||
throw new ApplicationException(
|
||||
`Could not find workspace custom and standard applications ${workspace.id}`,
|
||||
ApplicationExceptionCode.APPLICATION_NOT_FOUND,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
twentyStandardFlatApplication,
|
||||
workspaceCustomFlatApplication,
|
||||
};
|
||||
}
|
||||
|
||||
async findManyApplications(
|
||||
workspaceId: string,
|
||||
): Promise<ApplicationEntity[]> {
|
||||
@@ -82,31 +145,63 @@ export class ApplicationService {
|
||||
async createTwentyStandardApplication(
|
||||
{
|
||||
workspaceId,
|
||||
skipCacheInvalidation = false,
|
||||
}: {
|
||||
workspaceId: string;
|
||||
skipCacheInvalidation?: boolean;
|
||||
},
|
||||
queryRunner?: QueryRunner,
|
||||
) {
|
||||
return await this.create(
|
||||
const twentyStandardApplication = await this.create(
|
||||
{
|
||||
...TWENTY_STANDARD_APPLICATION,
|
||||
serverlessFunctionLayerId: null,
|
||||
workspaceId,
|
||||
canBeUninstalled: false,
|
||||
},
|
||||
queryRunner,
|
||||
);
|
||||
|
||||
if (!skipCacheInvalidation) {
|
||||
await this.workspaceFlatApplicationMapCacheService.invalidateCache({
|
||||
workspaceId,
|
||||
});
|
||||
}
|
||||
|
||||
return twentyStandardApplication;
|
||||
}
|
||||
|
||||
async createWorkspaceCustomApplication(
|
||||
{
|
||||
workspaceId,
|
||||
workspaceDisplayName,
|
||||
}: {
|
||||
workspaceId: string;
|
||||
workspaceDisplayName?: string;
|
||||
},
|
||||
queryRunner?: QueryRunner,
|
||||
) {
|
||||
const applicationId = v4();
|
||||
const workspaceCustomApplication = await this.create(
|
||||
{
|
||||
description: 'Workspace custom application',
|
||||
name: `${isDefined(workspaceDisplayName) ? workspaceDisplayName : 'Workspace'}'s custom application`,
|
||||
sourcePath: 'workspace-custom',
|
||||
version: '1.0.0',
|
||||
universalIdentifier: applicationId,
|
||||
workspaceId: workspaceId,
|
||||
id: applicationId,
|
||||
serverlessFunctionLayerId: null,
|
||||
canBeUninstalled: false,
|
||||
},
|
||||
queryRunner,
|
||||
);
|
||||
|
||||
return workspaceCustomApplication;
|
||||
}
|
||||
|
||||
async create(
|
||||
data: {
|
||||
universalIdentifier?: string;
|
||||
name: string;
|
||||
description?: string;
|
||||
version?: string;
|
||||
serverlessFunctionLayerId: string | null;
|
||||
sourcePath: string;
|
||||
workspaceId: string;
|
||||
},
|
||||
data: Partial<ApplicationEntity> & { workspaceId: string },
|
||||
queryRunner?: QueryRunner,
|
||||
): Promise<ApplicationEntity> {
|
||||
const application = this.applicationRepository.create({
|
||||
@@ -118,7 +213,13 @@ export class ApplicationService {
|
||||
return queryRunner.manager.save(ApplicationEntity, application);
|
||||
}
|
||||
|
||||
return this.applicationRepository.save(application);
|
||||
const savedApplication = await this.applicationRepository.save(application);
|
||||
|
||||
await this.workspaceFlatApplicationMapCacheService.invalidateCache({
|
||||
workspaceId: data.workspaceId,
|
||||
});
|
||||
|
||||
return savedApplication;
|
||||
}
|
||||
|
||||
async update(
|
||||
@@ -127,6 +228,10 @@ export class ApplicationService {
|
||||
): Promise<ApplicationEntity> {
|
||||
await this.applicationRepository.update({ id }, data);
|
||||
|
||||
await this.workspaceFlatApplicationMapCacheService.invalidateCache({
|
||||
workspaceId: data.workspaceId as string,
|
||||
});
|
||||
|
||||
const updatedApplication = await this.findById(id);
|
||||
|
||||
if (!updatedApplication) {
|
||||
@@ -151,8 +256,14 @@ export class ApplicationService {
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
await this.flatEntityMapsCacheService.invalidateFlatEntityMaps({
|
||||
await this.workspaceFlatApplicationMapCacheService.invalidateCache({
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
await this.workspaceManyOrAllFlatEntityMapsCacheService.invalidateFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
import { type ApplicationEntity } from 'src/engine/core-modules/application/application.entity';
|
||||
|
||||
export const APPLICATION_ENTITY_RELATION_PROPERTIES = [
|
||||
'workspace',
|
||||
'agents',
|
||||
'serverlessFunctions',
|
||||
'objects',
|
||||
'applicationVariables',
|
||||
] as const satisfies (keyof ApplicationEntity)[];
|
||||
+1919
File diff suppressed because it is too large
Load Diff
+7
-15
@@ -8,20 +8,12 @@ export const TWENTY_STANDARD_APPLICATION = {
|
||||
version: '1.0.0',
|
||||
sourcePath: 'cli-sync',
|
||||
sourceType: 'local',
|
||||
canBeUninstalled: false,
|
||||
} as const satisfies CreateApplicationInput;
|
||||
|
||||
export type CreateApplicationInput = Omit<
|
||||
} as const satisfies Pick<
|
||||
ApplicationEntity,
|
||||
| 'workspaceId'
|
||||
| 'serverlessFunctionLayerId'
|
||||
| 'id'
|
||||
| 'createdAt'
|
||||
| 'updatedAt'
|
||||
| 'deletedAt'
|
||||
| 'workspace'
|
||||
| 'agents'
|
||||
| 'applicationVariables'
|
||||
| 'objects'
|
||||
| 'serverlessFunctions'
|
||||
| 'universalIdentifier'
|
||||
| 'name'
|
||||
| 'description'
|
||||
| 'version'
|
||||
| 'sourcePath'
|
||||
| 'sourceType'
|
||||
>;
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { AllMetadataName } from 'twenty-shared/metadata';
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import { ApplicationEntity } from 'src/engine/core-modules/application/application.entity';
|
||||
import { FlatApplicationCacheMaps } from 'src/engine/core-modules/application/types/flat-application-cache-maps.type';
|
||||
import { fromApplicationEntityToFlatApplication } from 'src/engine/core-modules/application/utils/from-application-entity-to-flat-application.util';
|
||||
import { InjectCacheStorage } from 'src/engine/core-modules/cache-storage/decorators/cache-storage.decorator';
|
||||
import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service';
|
||||
import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum';
|
||||
import { MetadataToFlatEntityMapsKey } from 'src/engine/metadata-modules/flat-entity/types/metadata-to-flat-entity-maps-key';
|
||||
import { WorkspaceFlatMapCache } from 'src/engine/workspace-flat-map-cache/decorators/workspace-flat-map-cache.decorator';
|
||||
import { WorkspaceFlatMapCacheService } from 'src/engine/workspace-flat-map-cache/services/workspace-flat-map-cache.service';
|
||||
|
||||
@Injectable()
|
||||
@WorkspaceFlatMapCache(
|
||||
'flatApplicationMaps' as MetadataToFlatEntityMapsKey<AllMetadataName>,
|
||||
) // TODO prastoin introduce SyncableMetadata notion
|
||||
export class WorkspaceFlatApplicationMapCacheService extends WorkspaceFlatMapCacheService<FlatApplicationCacheMaps> {
|
||||
constructor(
|
||||
@InjectCacheStorage(CacheStorageNamespace.EngineWorkspace)
|
||||
cacheStorageService: CacheStorageService,
|
||||
@InjectRepository(ApplicationEntity)
|
||||
private readonly applicationRepository: Repository<ApplicationEntity>,
|
||||
) {
|
||||
super(cacheStorageService);
|
||||
}
|
||||
|
||||
protected async computeFlatMap({
|
||||
workspaceId,
|
||||
}: {
|
||||
workspaceId: string;
|
||||
}): Promise<FlatApplicationCacheMaps> {
|
||||
const applicationEntities = await this.applicationRepository.find({
|
||||
where: {
|
||||
workspaceId,
|
||||
},
|
||||
withDeleted: true,
|
||||
});
|
||||
|
||||
const flatApplicationMaps: FlatApplicationCacheMaps = {
|
||||
byId: {},
|
||||
idByUniversalIdentifier: {},
|
||||
};
|
||||
|
||||
for (const applicationEntity of applicationEntities) {
|
||||
const flatApplication =
|
||||
fromApplicationEntityToFlatApplication(applicationEntity);
|
||||
|
||||
flatApplicationMaps.byId[flatApplication.id] = flatApplication;
|
||||
flatApplicationMaps.idByUniversalIdentifier[
|
||||
flatApplication.universalIdentifier
|
||||
] = flatApplication.id;
|
||||
}
|
||||
|
||||
return flatApplicationMaps;
|
||||
}
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
import { type APPLICATION_ENTITY_RELATION_PROPERTIES } from 'src/engine/core-modules/application/constants/application-entity-relation-properties.constant';
|
||||
|
||||
export type ApplicationEntityRelationProperties =
|
||||
(typeof APPLICATION_ENTITY_RELATION_PROPERTIES)[number];
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
|
||||
export type FlatApplicationCacheMaps = {
|
||||
byId: Partial<Record<string, FlatApplication>>;
|
||||
idByUniversalIdentifier: Partial<Record<string, string>>;
|
||||
};
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
import { type ApplicationEntity } from 'src/engine/core-modules/application/application.entity';
|
||||
import { type ApplicationEntityRelationProperties } from 'src/engine/core-modules/application/types/application-entity-relation-properties.type';
|
||||
|
||||
export type FlatApplication = Omit<
|
||||
ApplicationEntity,
|
||||
ApplicationEntityRelationProperties
|
||||
>;
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
import { removePropertiesFromRecord } from 'twenty-shared/utils';
|
||||
|
||||
import { type ApplicationEntity } from 'src/engine/core-modules/application/application.entity';
|
||||
import { APPLICATION_ENTITY_RELATION_PROPERTIES } from 'src/engine/core-modules/application/constants/application-entity-relation-properties.constant';
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
|
||||
export const fromApplicationEntityToFlatApplication = (
|
||||
applicationEntity: ApplicationEntity,
|
||||
): FlatApplication =>
|
||||
removePropertiesFromRecord(
|
||||
applicationEntity,
|
||||
APPLICATION_ENTITY_RELATION_PROPERTIES,
|
||||
);
|
||||
+12
-15
@@ -11,6 +11,7 @@ import { v4 } from 'uuid';
|
||||
import { USER_SIGNUP_EVENT_NAME } from 'src/engine/api/graphql/workspace-query-runner/constants/user-signup-event-name.constants';
|
||||
import { type AppTokenEntity } from 'src/engine/core-modules/app-token/app-token.entity';
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
|
||||
import { WorkspaceFlatApplicationMapCacheService } from 'src/engine/core-modules/application/services/workspace-flat-application-map-cache.service';
|
||||
import {
|
||||
AuthException,
|
||||
AuthExceptionCode,
|
||||
@@ -39,7 +40,6 @@ import { WorkspaceInvitationService } from 'src/engine/core-modules/workspace-in
|
||||
import { AuthProviderEnum } from 'src/engine/core-modules/workspace/types/workspace.type';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { WorkspaceEventEmitter } from 'src/engine/workspace-event-emitter/workspace-event-emitter';
|
||||
import { computeWorkspaceCustomCreateApplicationInput } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/compute-workspace-custom-create-application-input';
|
||||
import { getDomainNameByEmail } from 'src/utils/get-domain-name-by-email';
|
||||
import { isWorkEmail } from 'src/utils/is-work-email';
|
||||
|
||||
@@ -60,6 +60,7 @@ export class SignInUpService {
|
||||
private readonly subdomainManagerService: SubdomainManagerService,
|
||||
private readonly userService: UserService,
|
||||
private readonly metricsService: MetricsService,
|
||||
private readonly workspaceFlatApplicationMapCacheService: WorkspaceFlatApplicationMapCacheService,
|
||||
private readonly applicationService: ApplicationService,
|
||||
@InjectDataSource()
|
||||
private readonly dataSource: DataSource,
|
||||
@@ -459,26 +460,19 @@ export class SignInUpService {
|
||||
isWorkEmailFound && (await isLogoUrlValid()) ? logoUrl : undefined;
|
||||
|
||||
const workspaceId = v4();
|
||||
const workspaceCustomApplicationCreateInput =
|
||||
computeWorkspaceCustomCreateApplicationInput({
|
||||
workspace: {
|
||||
id: workspaceId,
|
||||
},
|
||||
});
|
||||
|
||||
const queryRunner = this.dataSource.createQueryRunner();
|
||||
|
||||
await queryRunner.connect();
|
||||
await queryRunner.startTransaction();
|
||||
|
||||
try {
|
||||
const workspaceCustomApplication = await this.applicationService.create(
|
||||
{
|
||||
...workspaceCustomApplicationCreateInput,
|
||||
serverlessFunctionLayerId: null,
|
||||
},
|
||||
queryRunner,
|
||||
);
|
||||
const workspaceCustomApplication =
|
||||
await this.applicationService.createWorkspaceCustomApplication(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
queryRunner,
|
||||
);
|
||||
|
||||
const workspaceToCreate = this.workspaceRepository.create({
|
||||
id: workspaceId,
|
||||
@@ -532,6 +526,9 @@ export class SignInUpService {
|
||||
);
|
||||
|
||||
await queryRunner.commitTransaction();
|
||||
await this.workspaceFlatApplicationMapCacheService.invalidateCache({
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
return { user, workspace };
|
||||
} catch (error) {
|
||||
|
||||
@@ -9,6 +9,7 @@ import { AiModule } from 'src/engine/core-modules/ai/ai.module';
|
||||
import { ApiKeyModule } from 'src/engine/core-modules/api-key/api-key.module';
|
||||
import { AppTokenModule } from 'src/engine/core-modules/app-token/app-token.module';
|
||||
import { ApplicationModule } from 'src/engine/core-modules/application/application.module';
|
||||
import { ApplicationSyncModule } from 'src/engine/core-modules/application/application-sync.module';
|
||||
import { ApprovedAccessDomainModule } from 'src/engine/core-modules/approved-access-domain/approved-access-domain.module';
|
||||
import { AuthModule } from 'src/engine/core-modules/auth/auth.module';
|
||||
import { BillingWebhookModule } from 'src/engine/core-modules/billing-webhook/billing-webhook.module';
|
||||
@@ -77,6 +78,7 @@ import { FileModule } from './file/file.module';
|
||||
FileModule,
|
||||
OpenApiModule,
|
||||
ApplicationModule,
|
||||
ApplicationSyncModule,
|
||||
AppTokenModule,
|
||||
TimelineMessagingModule,
|
||||
TimelineCalendarEventModule,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { ApplicationModule } from 'src/engine/core-modules/application/application.module';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { CronTriggerCronCommand } from 'src/engine/metadata-modules/cron-trigger/crons/commands/cron-trigger.cron.command';
|
||||
import { CronTriggerCronJob } from 'src/engine/metadata-modules/cron-trigger/crons/jobs/cron-trigger.cron.job';
|
||||
@@ -15,6 +16,7 @@ import { WorkspaceMigrationV2Module } from 'src/engine/workspace-manager/workspa
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([WorkspaceEntity, CronTriggerEntity]),
|
||||
ApplicationModule,
|
||||
WorkspaceManyOrAllFlatEntityMapsCacheModule,
|
||||
PermissionsModule,
|
||||
WorkspaceMigrationV2Module,
|
||||
|
||||
+16
@@ -2,6 +2,7 @@ import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
|
||||
import { CreateCronTriggerInput } from 'src/engine/metadata-modules/cron-trigger/dtos/create-cron-trigger.input';
|
||||
import { CronTriggerIdInput } from 'src/engine/metadata-modules/cron-trigger/dtos/cron-trigger-id.input';
|
||||
import { UpdateCronTriggerInput } from 'src/engine/metadata-modules/cron-trigger/dtos/update-cron-trigger.input';
|
||||
@@ -23,12 +24,25 @@ export class CronTriggerV2Service {
|
||||
constructor(
|
||||
private readonly flatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
|
||||
private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService,
|
||||
private readonly applicationService: ApplicationService,
|
||||
) {}
|
||||
|
||||
async createOne(
|
||||
cronTriggerInput: CreateCronTriggerInput,
|
||||
workspaceId: string,
|
||||
/**
|
||||
* @deprecated do not use call validateBuildAndRunWorkspaceMigration contextually
|
||||
* when interacting with another application than workspace custom one
|
||||
* */
|
||||
applicationId?: string,
|
||||
) {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
const flatEntityMaps =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
@@ -43,6 +57,8 @@ export class CronTriggerV2Service {
|
||||
{
|
||||
createCronTriggerInput: cronTriggerInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId:
|
||||
applicationId ?? workspaceCustomFlatApplication.id,
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
+6
-3
@@ -6,18 +6,21 @@ import { type FlatCronTrigger } from 'src/engine/metadata-modules/cron-trigger/t
|
||||
export const fromCreateCronTriggerInputToFlatCronTrigger = ({
|
||||
createCronTriggerInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
}: {
|
||||
createCronTriggerInput: CreateCronTriggerInput;
|
||||
workspaceId: string;
|
||||
workspaceCustomApplicationId: string;
|
||||
}): FlatCronTrigger => {
|
||||
const now = new Date();
|
||||
const id = v4();
|
||||
|
||||
return {
|
||||
id: v4(),
|
||||
universalIdentifier: createCronTriggerInput.universalIdentifier ?? v4(),
|
||||
id,
|
||||
universalIdentifier: createCronTriggerInput.universalIdentifier ?? id,
|
||||
settings: createCronTriggerInput.settings,
|
||||
serverlessFunctionId: createCronTriggerInput.serverlessFunctionId,
|
||||
applicationId: createCronTriggerInput.applicationId ?? null,
|
||||
applicationId: workspaceCustomApplicationId,
|
||||
workspaceId,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
|
||||
+2
@@ -1,6 +1,7 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { ApplicationModule } from 'src/engine/core-modules/application/application.module';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { DatabaseEventTriggerEntity } from 'src/engine/metadata-modules/database-event-trigger/entities/database-event-trigger.entity';
|
||||
import { CallDatabaseEventTriggerJobsJob } from 'src/engine/metadata-modules/database-event-trigger/jobs/call-database-event-trigger-jobs.job';
|
||||
@@ -14,6 +15,7 @@ import { WorkspaceMigrationV2Module } from 'src/engine/workspace-manager/workspa
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([WorkspaceEntity, DatabaseEventTriggerEntity]),
|
||||
ApplicationModule,
|
||||
WorkspaceManyOrAllFlatEntityMapsCacheModule,
|
||||
PermissionsModule,
|
||||
WorkspaceMigrationV2Module,
|
||||
|
||||
+16
@@ -2,6 +2,7 @@ import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
|
||||
import { CreateDatabaseEventTriggerInput } from 'src/engine/metadata-modules/database-event-trigger/dtos/create-database-event-trigger.input';
|
||||
import { DatabaseEventTriggerIdInput } from 'src/engine/metadata-modules/database-event-trigger/dtos/database-event-trigger-id.input';
|
||||
import { UpdateDatabaseEventTriggerInput } from 'src/engine/metadata-modules/database-event-trigger/dtos/update-database-event-trigger.input';
|
||||
@@ -23,12 +24,25 @@ export class DatabaseEventTriggerV2Service {
|
||||
constructor(
|
||||
private readonly flatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
|
||||
private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService,
|
||||
private readonly applicationService: ApplicationService,
|
||||
) {}
|
||||
|
||||
async createOne(
|
||||
databaseEventTriggerInput: CreateDatabaseEventTriggerInput,
|
||||
workspaceId: string,
|
||||
/**
|
||||
* @deprecated do not use call validateBuildAndRunWorkspaceMigration contextually
|
||||
* when interacting with another application than workspace custom one
|
||||
* */
|
||||
applicationId?: string,
|
||||
) {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
const flatEntityMaps =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
@@ -47,6 +61,8 @@ export class DatabaseEventTriggerV2Service {
|
||||
fromCreateDatabaseEventTriggerInputToFlatDatabaseEventTrigger({
|
||||
createDatabaseEventTriggerInput: databaseEventTriggerInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId:
|
||||
applicationId ?? workspaceCustomFlatApplication.id,
|
||||
});
|
||||
|
||||
const validateAndBuildResult =
|
||||
|
||||
+6
-3
@@ -6,21 +6,24 @@ import { type FlatDatabaseEventTrigger } from 'src/engine/metadata-modules/datab
|
||||
export const fromCreateDatabaseEventTriggerInputToFlatDatabaseEventTrigger = ({
|
||||
createDatabaseEventTriggerInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
}: {
|
||||
createDatabaseEventTriggerInput: CreateDatabaseEventTriggerInput;
|
||||
workspaceId: string;
|
||||
workspaceCustomApplicationId: string;
|
||||
}): FlatDatabaseEventTrigger => {
|
||||
const now = new Date();
|
||||
const id = uuidV4();
|
||||
|
||||
return {
|
||||
id: uuidV4(),
|
||||
id,
|
||||
universalIdentifier:
|
||||
createDatabaseEventTriggerInput.universalIdentifier ?? uuidV4(),
|
||||
createDatabaseEventTriggerInput.universalIdentifier ?? id,
|
||||
settings: createDatabaseEventTriggerInput.settings,
|
||||
serverlessFunctionId: createDatabaseEventTriggerInput.serverlessFunctionId,
|
||||
workspaceId,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
applicationId: createDatabaseEventTriggerInput.applicationId ?? null,
|
||||
applicationId: workspaceCustomApplicationId,
|
||||
};
|
||||
};
|
||||
|
||||
+2
@@ -9,6 +9,7 @@ import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm';
|
||||
|
||||
import { TypeORMModule } from 'src/database/typeorm/typeorm.module';
|
||||
import { ActorModule } from 'src/engine/core-modules/actor/actor.module';
|
||||
import { ApplicationModule } from 'src/engine/core-modules/application/application.module';
|
||||
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';
|
||||
@@ -60,6 +61,7 @@ import { UpdateFieldInput } from './dtos/update-field.input';
|
||||
DataSourceModule,
|
||||
TypeORMModule,
|
||||
ActorModule,
|
||||
ApplicationModule,
|
||||
FeatureFlagModule,
|
||||
ViewModule,
|
||||
ViewFieldModule,
|
||||
|
||||
+24
@@ -5,6 +5,7 @@ import { TypeOrmQueryService } from '@ptc-org/nestjs-query-typeorm';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { FindOneOptions, Repository } from 'typeorm';
|
||||
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
|
||||
import { type CreateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input';
|
||||
import { type DeleteOneFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/delete-field.input';
|
||||
import { type UpdateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/update-field.input';
|
||||
@@ -32,6 +33,7 @@ export class FieldMetadataServiceV2 extends TypeOrmQueryService<FieldMetadataEnt
|
||||
private readonly fieldMetadataRepository: Repository<FieldMetadataEntity>,
|
||||
private readonly flatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
|
||||
private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService,
|
||||
private readonly applicationService: ApplicationService,
|
||||
) {
|
||||
super(fieldMetadataRepository);
|
||||
}
|
||||
@@ -39,13 +41,20 @@ export class FieldMetadataServiceV2 extends TypeOrmQueryService<FieldMetadataEnt
|
||||
async createOneField({
|
||||
createFieldInput,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
}: {
|
||||
createFieldInput: Omit<CreateFieldInput, 'workspaceId'>;
|
||||
workspaceId: string;
|
||||
/**
|
||||
* @deprecated do not use call validateBuildAndRunWorkspaceMigration contextually
|
||||
* when interacting with another application than workspace custom one
|
||||
* */
|
||||
applicationId?: string;
|
||||
}): Promise<FlatFieldMetadata> {
|
||||
const [createdFieldMetadata] = await this.createManyFields({
|
||||
workspaceId,
|
||||
createFieldInputs: [createFieldInput],
|
||||
applicationId,
|
||||
});
|
||||
|
||||
if (!isDefined(createdFieldMetadata)) {
|
||||
@@ -283,14 +292,27 @@ export class FieldMetadataServiceV2 extends TypeOrmQueryService<FieldMetadataEnt
|
||||
async createManyFields({
|
||||
createFieldInputs,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
}: {
|
||||
createFieldInputs: Omit<CreateFieldInput, 'workspaceId'>[];
|
||||
workspaceId: string;
|
||||
/**
|
||||
* @deprecated do not use call validateBuildAndRunWorkspaceMigration contextually
|
||||
* when interacting with another application than workspace custom one
|
||||
* */
|
||||
applicationId?: string;
|
||||
}): Promise<FlatFieldMetadata[]> {
|
||||
if (createFieldInputs.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
const {
|
||||
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
|
||||
flatIndexMaps: existingFlatIndexMaps,
|
||||
@@ -316,6 +338,8 @@ export class FieldMetadataServiceV2 extends TypeOrmQueryService<FieldMetadataEnt
|
||||
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
|
||||
createFieldInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId:
|
||||
applicationId ?? workspaceCustomFlatApplication.id,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
+6
-6
@@ -104,7 +104,7 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su
|
||||
"result": {
|
||||
"flatFieldMetadatas": [
|
||||
{
|
||||
"applicationId": null,
|
||||
"applicationId": Any<String>,
|
||||
"calendarViewIds": [],
|
||||
"createdAt": Any<ClockDate>,
|
||||
"defaultValue": null,
|
||||
@@ -140,7 +140,7 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su
|
||||
"workspaceId": Any<String>,
|
||||
},
|
||||
{
|
||||
"applicationId": null,
|
||||
"applicationId": Any<String>,
|
||||
"calendarViewIds": [],
|
||||
"createdAt": Any<ClockDate>,
|
||||
"defaultValue": null,
|
||||
@@ -178,7 +178,7 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su
|
||||
"workspaceId": Any<String>,
|
||||
},
|
||||
{
|
||||
"applicationId": null,
|
||||
"applicationId": Any<String>,
|
||||
"calendarViewIds": [],
|
||||
"createdAt": Any<ClockDate>,
|
||||
"defaultValue": null,
|
||||
@@ -214,7 +214,7 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su
|
||||
"workspaceId": Any<String>,
|
||||
},
|
||||
{
|
||||
"applicationId": null,
|
||||
"applicationId": Any<String>,
|
||||
"calendarViewIds": [],
|
||||
"createdAt": Any<ClockDate>,
|
||||
"defaultValue": null,
|
||||
@@ -254,7 +254,7 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su
|
||||
],
|
||||
"indexMetadatas": [
|
||||
{
|
||||
"applicationId": null,
|
||||
"applicationId": Any<String>,
|
||||
"createdAt": Any<ClockDate>,
|
||||
"flatIndexFieldMetadatas": [
|
||||
{
|
||||
@@ -278,7 +278,7 @@ exports[`fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test su
|
||||
"workspaceId": Any<String>,
|
||||
},
|
||||
{
|
||||
"applicationId": null,
|
||||
"applicationId": Any<String>,
|
||||
"createdAt": Any<ClockDate>,
|
||||
"flatIndexFieldMetadatas": [
|
||||
{
|
||||
|
||||
+14
@@ -42,6 +42,8 @@ describe('fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test s
|
||||
'should create morph relation field metadata with valid input on rocket object to pet object',
|
||||
context: {
|
||||
input: {
|
||||
workspaceCustomApplicationId:
|
||||
'20202020-81ee-42da-a281-668632f32fe7',
|
||||
createFieldInput: {
|
||||
name: 'newField',
|
||||
label: 'newFieldLabel',
|
||||
@@ -100,6 +102,8 @@ describe('fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test s
|
||||
title: 'should fail when morphRelationsCreationPayload is missing',
|
||||
context: {
|
||||
input: {
|
||||
workspaceCustomApplicationId:
|
||||
'20202020-81ee-42da-a281-668632f32fe7',
|
||||
createFieldInput: {
|
||||
name: 'newField',
|
||||
label: 'newFieldLabel',
|
||||
@@ -118,6 +122,8 @@ describe('fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test s
|
||||
title: 'should fail when morphRelationsCreationPayload is empty array',
|
||||
context: {
|
||||
input: {
|
||||
workspaceCustomApplicationId:
|
||||
'20202020-81ee-42da-a281-668632f32fe7',
|
||||
createFieldInput: {
|
||||
name: 'newField',
|
||||
label: 'newFieldLabel',
|
||||
@@ -137,6 +143,8 @@ describe('fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test s
|
||||
'should fail when morphRelationsCreationPayload has different relation types',
|
||||
context: {
|
||||
input: {
|
||||
workspaceCustomApplicationId:
|
||||
'20202020-81ee-42da-a281-668632f32fe7',
|
||||
createFieldInput: {
|
||||
name: 'newField',
|
||||
label: 'newFieldLabel',
|
||||
@@ -169,6 +177,8 @@ describe('fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test s
|
||||
'should fail when morphRelationsCreationPayload has several references to same object metadata',
|
||||
context: {
|
||||
input: {
|
||||
workspaceCustomApplicationId:
|
||||
'20202020-81ee-42da-a281-668632f32fe7',
|
||||
createFieldInput: {
|
||||
name: 'newField',
|
||||
label: 'newFieldLabel',
|
||||
@@ -201,6 +211,8 @@ describe('fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test s
|
||||
'should fail when morphRelationsCreationPayload has invalid relation payload',
|
||||
context: {
|
||||
input: {
|
||||
workspaceCustomApplicationId:
|
||||
'20202020-81ee-42da-a281-668632f32fe7',
|
||||
createFieldInput: {
|
||||
name: 'newField',
|
||||
label: 'newFieldLabel',
|
||||
@@ -225,6 +237,8 @@ describe('fromCreateFieldInputToFlatFieldMetadatasToCreate MORPH_RELATION test s
|
||||
title: 'should fail when target object metadata is not found',
|
||||
context: {
|
||||
input: {
|
||||
workspaceCustomApplicationId:
|
||||
'20202020-81ee-42da-a281-668632f32fe7',
|
||||
createFieldInput: {
|
||||
name: 'newField',
|
||||
label: 'newFieldLabel',
|
||||
|
||||
+5
@@ -25,12 +25,14 @@ import { type FlatIndexMetadata } from 'src/engine/metadata-modules/flat-index-m
|
||||
export type FromCreateFieldInputToFlatObjectMetadataArgs = {
|
||||
createFieldInput: Omit<CreateFieldInput, 'workspaceId'>;
|
||||
workspaceId: string;
|
||||
workspaceCustomApplicationId: string;
|
||||
} & Pick<AllFlatEntityMaps, 'flatObjectMetadataMaps'>;
|
||||
|
||||
export const fromCreateFieldInputToFlatFieldMetadatasToCreate = async ({
|
||||
createFieldInput: rawCreateFieldInput,
|
||||
workspaceId,
|
||||
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
|
||||
workspaceCustomApplicationId,
|
||||
}: FromCreateFieldInputToFlatObjectMetadataArgs): Promise<
|
||||
FieldInputTranspilationResult<{
|
||||
flatFieldMetadatas: FlatFieldMetadata[];
|
||||
@@ -71,6 +73,7 @@ export const fromCreateFieldInputToFlatFieldMetadatasToCreate = async ({
|
||||
createFieldInput,
|
||||
workspaceId,
|
||||
fieldMetadataId,
|
||||
workspaceCustomApplicationId,
|
||||
});
|
||||
|
||||
switch (createFieldInput.type) {
|
||||
@@ -83,6 +86,7 @@ export const fromCreateFieldInputToFlatFieldMetadatasToCreate = async ({
|
||||
existingFlatObjectMetadataMaps,
|
||||
sourceFlatObjectMetadata: parentFlatObjectMetadata,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
});
|
||||
}
|
||||
case FieldMetadataType.RELATION: {
|
||||
@@ -94,6 +98,7 @@ export const fromCreateFieldInputToFlatFieldMetadatasToCreate = async ({
|
||||
type: createFieldInput.type,
|
||||
},
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
});
|
||||
}
|
||||
case FieldMetadataType.RATING: {
|
||||
|
||||
+3
@@ -21,12 +21,14 @@ type FromMorphRelationCreateFieldInputToFlatFieldMetadatasArgs = {
|
||||
existingFlatObjectMetadataMaps: FlatEntityMaps<FlatObjectMetadata>;
|
||||
sourceFlatObjectMetadata: FlatObjectMetadata;
|
||||
workspaceId: string;
|
||||
workspaceCustomApplicationId: string;
|
||||
};
|
||||
export const fromMorphRelationCreateFieldInputToFlatFieldMetadatas = async ({
|
||||
createFieldInput,
|
||||
existingFlatObjectMetadataMaps,
|
||||
sourceFlatObjectMetadata,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
}: FromMorphRelationCreateFieldInputToFlatFieldMetadatasArgs): Promise<
|
||||
FieldInputTranspilationResult<{
|
||||
flatFieldMetadatas: FlatFieldMetadata[];
|
||||
@@ -90,6 +92,7 @@ export const fromMorphRelationCreateFieldInputToFlatFieldMetadatas = async ({
|
||||
targetFlatObjectMetadata,
|
||||
workspaceId,
|
||||
morphId,
|
||||
workspaceCustomApplicationId,
|
||||
});
|
||||
|
||||
return {
|
||||
|
||||
+3
@@ -21,12 +21,14 @@ type FromRelationCreateFieldInputToFlatFieldMetadataArgs = {
|
||||
existingFlatObjectMetadataMaps: FlatEntityMaps<FlatObjectMetadata>;
|
||||
sourceFlatObjectMetadata: FlatObjectMetadata;
|
||||
workspaceId: string;
|
||||
workspaceCustomApplicationId: string;
|
||||
};
|
||||
export const fromRelationCreateFieldInputToFlatFieldMetadatas = async ({
|
||||
existingFlatObjectMetadataMaps,
|
||||
sourceFlatObjectMetadata,
|
||||
createFieldInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
}: FromRelationCreateFieldInputToFlatFieldMetadataArgs): Promise<
|
||||
FieldInputTranspilationResult<SourceTargetMorphOrRelationFlatFieldAndFlatIndex>
|
||||
> => {
|
||||
@@ -67,6 +69,7 @@ export const fromRelationCreateFieldInputToFlatFieldMetadatas = async ({
|
||||
sourceFlatObjectMetadata,
|
||||
targetFlatObjectMetadata,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
});
|
||||
|
||||
return {
|
||||
|
||||
+1
-1
@@ -44,7 +44,7 @@ export const generateIndexForFlatFieldMetadata = ({
|
||||
universalIdentifier: indexId,
|
||||
updatedAt: createdAt,
|
||||
workspaceId,
|
||||
applicationId: null,
|
||||
applicationId: flatFieldMetadata.applicationId,
|
||||
},
|
||||
flatObjectMetadata,
|
||||
},
|
||||
|
||||
+5
-1
@@ -1,7 +1,7 @@
|
||||
import {
|
||||
FieldMetadataType,
|
||||
RelationType,
|
||||
RelationOnDeleteAction,
|
||||
RelationType,
|
||||
} from 'twenty-shared/types';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
@@ -46,6 +46,7 @@ type GenerateMorphOrRelationFlatFieldMetadataPairArgs = {
|
||||
> & { type: MorphOrRelationFieldMetadataType };
|
||||
workspaceId: string;
|
||||
morphId?: string | null;
|
||||
workspaceCustomApplicationId: string;
|
||||
};
|
||||
|
||||
export type SourceTargetMorphOrRelationFlatFieldAndFlatIndex = {
|
||||
@@ -58,6 +59,7 @@ export const generateMorphOrRelationFlatFieldMetadataPair = ({
|
||||
sourceFlatObjectMetadata,
|
||||
targetFlatObjectMetadata,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
sourceFlatObjectMetadataJoinColumnName,
|
||||
morphId = null,
|
||||
}: GenerateMorphOrRelationFlatFieldMetadataPairArgs): SourceTargetMorphOrRelationFlatFieldAndFlatIndex => {
|
||||
@@ -78,6 +80,7 @@ export const generateMorphOrRelationFlatFieldMetadataPair = ({
|
||||
createFieldInput,
|
||||
workspaceId,
|
||||
fieldMetadataId: sourceRelationTargetFieldMetadataId,
|
||||
workspaceCustomApplicationId,
|
||||
}),
|
||||
morphId,
|
||||
objectMetadataId: sourceFlatObjectMetadata.id,
|
||||
@@ -116,6 +119,7 @@ export const generateMorphOrRelationFlatFieldMetadataPair = ({
|
||||
createFieldInput: targetCreateFieldInput,
|
||||
workspaceId,
|
||||
fieldMetadataId: targetRelationTargetFieldMetadataId,
|
||||
workspaceCustomApplicationId,
|
||||
}),
|
||||
type: FieldMetadataType.RELATION,
|
||||
defaultValue: null,
|
||||
|
||||
+3
-1
@@ -9,11 +9,13 @@ type GetDefaultFlatFieldMetadataArgs = {
|
||||
fieldMetadataId: string;
|
||||
createFieldInput: Omit<CreateFieldInput, 'workspaceId'>;
|
||||
workspaceId: string;
|
||||
workspaceCustomApplicationId: string;
|
||||
};
|
||||
export const getDefaultFlatFieldMetadata = ({
|
||||
createFieldInput,
|
||||
fieldMetadataId,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
}: GetDefaultFlatFieldMetadataArgs) => {
|
||||
const { defaultValue, settings } = extractAndSanitizeObjectStringFields(
|
||||
createFieldInput,
|
||||
@@ -56,7 +58,7 @@ export const getDefaultFlatFieldMetadata = ({
|
||||
updatedAt: createdAt,
|
||||
isUIReadOnly: createFieldInput.isUIReadOnly ?? false,
|
||||
morphId: null,
|
||||
applicationId: createFieldInput.applicationId ?? null,
|
||||
applicationId: workspaceCustomApplicationId,
|
||||
viewFilterIds: [],
|
||||
viewGroupIds: [],
|
||||
kanbanAggregateOperationViewIds: [],
|
||||
|
||||
+4
-2
@@ -17,11 +17,13 @@ type FromCreateObjectInputToFlatObjectMetadataAndFlatFieldMetadatasToCreateArgs
|
||||
{
|
||||
createObjectInput: CreateObjectInput;
|
||||
workspaceId: string;
|
||||
workspaceCustomApplicationId: string;
|
||||
} & Pick<AllFlatEntityMaps, 'flatObjectMetadataMaps'>;
|
||||
export const fromCreateObjectInputToFlatObjectMetadataAndFlatFieldMetadatasToCreate =
|
||||
({
|
||||
createObjectInput: rawCreateObjectInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
|
||||
}: FromCreateObjectInputToFlatObjectMetadataAndFlatFieldMetadatasToCreateArgs): {
|
||||
flatObjectMetadataToCreate: FlatObjectMetadata;
|
||||
@@ -48,7 +50,7 @@ export const fromCreateObjectInputToFlatObjectMetadataAndFlatFieldMetadatasToCre
|
||||
buildDefaultFlatFieldMetadatasForCustomObject({
|
||||
flatObjectMetadata: {
|
||||
id: objectMetadataId,
|
||||
applicationId: createObjectInput.applicationId ?? null,
|
||||
applicationId: workspaceCustomApplicationId,
|
||||
},
|
||||
workspaceId,
|
||||
});
|
||||
@@ -81,7 +83,7 @@ export const fromCreateObjectInputToFlatObjectMetadataAndFlatFieldMetadatasToCre
|
||||
shortcut: createObjectInput.shortcut ?? null,
|
||||
standardId: createObjectInput.standardId ?? null,
|
||||
standardOverrides: null,
|
||||
applicationId: createObjectInput.applicationId ?? null,
|
||||
applicationId: workspaceCustomApplicationId,
|
||||
universalIdentifier: objectMetadataId,
|
||||
targetTableName: 'DEPRECATED',
|
||||
workspaceId,
|
||||
|
||||
+3
-1
@@ -8,11 +8,13 @@ import { DEFAULT_VIEW_FIELD_SIZE } from 'src/engine/workspace-manager/standard-o
|
||||
export type FromCreateViewFieldInputToFlatViewFieldToCreateArgs = {
|
||||
createViewFieldInput: CreateViewFieldInput;
|
||||
workspaceId: string;
|
||||
workspaceCustomApplicationId: string;
|
||||
};
|
||||
|
||||
export const fromCreateViewFieldInputToFlatViewFieldToCreate = ({
|
||||
createViewFieldInput: rawCreateViewFieldInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
}: FromCreateViewFieldInputToFlatViewFieldToCreateArgs): FlatViewField => {
|
||||
const { fieldMetadataId, viewId, ...createViewFieldInput } =
|
||||
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties(
|
||||
@@ -37,6 +39,6 @@ export const fromCreateViewFieldInputToFlatViewFieldToCreate = ({
|
||||
size: createViewFieldInput.size ?? DEFAULT_VIEW_FIELD_SIZE,
|
||||
position: createViewFieldInput.position ?? 0,
|
||||
aggregateOperation: createViewFieldInput.aggregateOperation ?? null,
|
||||
applicationId: createViewFieldInput.applicationId ?? null,
|
||||
applicationId: workspaceCustomApplicationId,
|
||||
};
|
||||
};
|
||||
|
||||
+3
-1
@@ -8,9 +8,11 @@ import { type CreateViewFilterInput } from 'src/engine/metadata-modules/view-fil
|
||||
export const fromCreateViewFilterInputToFlatViewFilterToCreate = ({
|
||||
createViewFilterInput: rawCreateViewFilterInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
}: {
|
||||
createViewFilterInput: CreateViewFilterInput;
|
||||
workspaceId: string;
|
||||
workspaceCustomApplicationId: string;
|
||||
}): FlatViewFilter => {
|
||||
const { fieldMetadataId, viewId, value, ...createViewFilterInput } =
|
||||
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties(
|
||||
@@ -44,6 +46,6 @@ export const fromCreateViewFilterInputToFlatViewFilterToCreate = ({
|
||||
positionInViewFilterGroup:
|
||||
createViewFilterInput.positionInViewFilterGroup ?? null,
|
||||
subFieldName: createViewFilterInput.subFieldName ?? null,
|
||||
applicationId: createViewFilterInput.applicationId ?? null,
|
||||
applicationId: workspaceCustomApplicationId,
|
||||
};
|
||||
};
|
||||
|
||||
+3
-1
@@ -7,9 +7,11 @@ import { type CreateViewGroupInput } from 'src/engine/metadata-modules/view-grou
|
||||
export const fromCreateViewGroupInputToFlatViewGroupToCreate = ({
|
||||
createViewGroupInput: rawCreateViewGroupInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
}: {
|
||||
createViewGroupInput: CreateViewGroupInput;
|
||||
workspaceId: string;
|
||||
workspaceCustomApplicationId: string;
|
||||
}): FlatViewGroup => {
|
||||
const { fieldMetadataId, viewId, ...createViewGroupInput } =
|
||||
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties(
|
||||
@@ -33,6 +35,6 @@ export const fromCreateViewGroupInputToFlatViewGroupToCreate = ({
|
||||
isVisible: createViewGroupInput.isVisible ?? true,
|
||||
fieldValue: createViewGroupInput.fieldValue,
|
||||
position: createViewGroupInput.position ?? 0,
|
||||
applicationId: createViewGroupInput.applicationId ?? null,
|
||||
applicationId: workspaceCustomApplicationId,
|
||||
};
|
||||
};
|
||||
|
||||
+3
-1
@@ -11,10 +11,12 @@ export const fromCreateViewInputToFlatViewToCreate = ({
|
||||
createViewInput: rawCreateViewInput,
|
||||
workspaceId,
|
||||
createdByUserWorkspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
}: {
|
||||
createViewInput: CreateViewInput;
|
||||
workspaceId: string;
|
||||
createdByUserWorkspaceId?: string;
|
||||
workspaceCustomApplicationId: string;
|
||||
}): FlatView => {
|
||||
const { objectMetadataId, ...createViewInput } =
|
||||
trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties(
|
||||
@@ -52,6 +54,6 @@ export const fromCreateViewInputToFlatViewToCreate = ({
|
||||
viewFieldIds: [],
|
||||
viewFilterIds: [],
|
||||
viewGroupIds: [],
|
||||
applicationId: createViewInput.applicationId ?? null,
|
||||
applicationId: workspaceCustomApplicationId,
|
||||
};
|
||||
};
|
||||
|
||||
+28
-4
@@ -5,6 +5,7 @@ import { TypeOrmQueryService } from '@ptc-org/nestjs-query-typeorm';
|
||||
import { fromArrayToUniqueKeyRecord, isDefined } from 'twenty-shared/utils';
|
||||
import { FindManyOptions, FindOneOptions, Repository } from 'typeorm';
|
||||
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { computeFlatEntityMapsFromTo } from 'src/engine/metadata-modules/flat-entity/utils/compute-flat-entity-maps-from-to.util';
|
||||
import { findManyFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-many-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
@@ -43,6 +44,7 @@ export class ObjectMetadataServiceV2 extends TypeOrmQueryService<ObjectMetadataE
|
||||
private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService,
|
||||
private readonly workspacePermissionsCacheService: WorkspacePermissionsCacheService,
|
||||
private readonly twentyORMGlobalManager: TwentyORMGlobalManager,
|
||||
private readonly applicationService: ApplicationService,
|
||||
) {
|
||||
super(objectMetadataRepository);
|
||||
}
|
||||
@@ -323,10 +325,22 @@ export class ObjectMetadataServiceV2 extends TypeOrmQueryService<ObjectMetadataE
|
||||
async createOneObject({
|
||||
createObjectInput,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
}: {
|
||||
createObjectInput: CreateObjectInput;
|
||||
workspaceId: string;
|
||||
/**
|
||||
* @deprecated do not use call validateBuildAndRunWorkspaceMigration contextually
|
||||
* when interacting with another application than workspace custom one
|
||||
* */
|
||||
applicationId?: string;
|
||||
}): Promise<FlatObjectMetadata> {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
const {
|
||||
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
|
||||
flatViewMaps: existingFlatViewMaps,
|
||||
@@ -354,6 +368,8 @@ export class ObjectMetadataServiceV2 extends TypeOrmQueryService<ObjectMetadataE
|
||||
} = fromCreateObjectInputToFlatObjectMetadataAndFlatFieldMetadatasToCreate({
|
||||
createObjectInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId:
|
||||
applicationId ?? workspaceCustomFlatApplication.id,
|
||||
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
|
||||
});
|
||||
|
||||
@@ -367,13 +383,15 @@ export class ObjectMetadataServiceV2 extends TypeOrmQueryService<ObjectMetadataE
|
||||
flatEntityToUpdate: [],
|
||||
});
|
||||
|
||||
const flatDefaultViewToCreate = await this.createDefaultFlatView({
|
||||
const flatDefaultViewToCreate = await this.computeFlatViewToCreate({
|
||||
objectMetadata: flatObjectMetadataToCreate,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId: workspaceCustomFlatApplication.id,
|
||||
});
|
||||
|
||||
const flatDefaultViewFieldsToCreate =
|
||||
await this.createDefaultFlatViewFields({
|
||||
await this.computeFlatViewFieldsToCreate({
|
||||
workspaceCustomApplicationId: workspaceCustomFlatApplication.id,
|
||||
objectFlatFieldMetadatas: findManyFlatEntityByIdInFlatEntityMapsOrThrow(
|
||||
{
|
||||
flatEntityMaps: flatFieldMetadataMapsFromTo.to,
|
||||
@@ -456,10 +474,12 @@ export class ObjectMetadataServiceV2 extends TypeOrmQueryService<ObjectMetadataE
|
||||
return createdFlatObjectMetadata;
|
||||
}
|
||||
|
||||
private async createDefaultFlatView({
|
||||
private async computeFlatViewToCreate({
|
||||
objectMetadata,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
}: {
|
||||
workspaceCustomApplicationId: string;
|
||||
objectMetadata: FlatObjectMetadata;
|
||||
workspaceId: string;
|
||||
}) {
|
||||
@@ -475,16 +495,19 @@ export class ObjectMetadataServiceV2 extends TypeOrmQueryService<ObjectMetadataE
|
||||
const flatViewFromCreateInput = fromCreateViewInputToFlatViewToCreate({
|
||||
createViewInput: defaultViewInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
});
|
||||
|
||||
return flatViewFromCreateInput;
|
||||
}
|
||||
|
||||
private async createDefaultFlatViewFields({
|
||||
private async computeFlatViewFieldsToCreate({
|
||||
objectFlatFieldMetadatas,
|
||||
viewId,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
}: {
|
||||
workspaceCustomApplicationId: string;
|
||||
objectFlatFieldMetadatas: FlatFieldMetadata[];
|
||||
viewId: string;
|
||||
workspaceId: string;
|
||||
@@ -500,6 +523,7 @@ export class ObjectMetadataServiceV2 extends TypeOrmQueryService<ObjectMetadataE
|
||||
size: DEFAULT_VIEW_FIELD_SIZE,
|
||||
viewId: viewId,
|
||||
},
|
||||
workspaceCustomApplicationId,
|
||||
workspaceId: workspaceId,
|
||||
}),
|
||||
);
|
||||
|
||||
+2
@@ -9,6 +9,7 @@ import {
|
||||
import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm';
|
||||
|
||||
import { TypeORMModule } from 'src/database/typeorm/typeorm.module';
|
||||
import { ApplicationModule } from 'src/engine/core-modules/application/application.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';
|
||||
@@ -50,6 +51,7 @@ import { WorkspaceMigrationV2Module } from 'src/engine/workspace-manager/workspa
|
||||
FieldMetadataEntity,
|
||||
]),
|
||||
TypeOrmModule.forFeature([FeatureFlagEntity, ViewEntity]),
|
||||
ApplicationModule,
|
||||
DataSourceModule,
|
||||
WorkspaceMigrationModule,
|
||||
WorkspaceMigrationRunnerModule,
|
||||
|
||||
-123
@@ -1,123 +0,0 @@
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { type FieldMetadataEntity } 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,
|
||||
): Array<Partial<FieldMetadataEntity> & { id: string }> => [
|
||||
{
|
||||
id: v4(),
|
||||
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,
|
||||
isUIReadOnly: true,
|
||||
workspaceId,
|
||||
defaultValue: 'uuid',
|
||||
},
|
||||
{
|
||||
id: v4(),
|
||||
standardId: CUSTOM_OBJECT_STANDARD_FIELD_IDS.name,
|
||||
type: FieldMetadataType.TEXT,
|
||||
name: 'name',
|
||||
label: 'Name',
|
||||
icon: 'IconAbc',
|
||||
description: 'Name',
|
||||
isNullable: false,
|
||||
isActive: true,
|
||||
isCustom: false,
|
||||
isUIReadOnly: false,
|
||||
workspaceId,
|
||||
defaultValue: "''",
|
||||
},
|
||||
{
|
||||
id: v4(),
|
||||
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,
|
||||
isUIReadOnly: false,
|
||||
workspaceId,
|
||||
defaultValue: 'now',
|
||||
},
|
||||
{
|
||||
id: v4(),
|
||||
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,
|
||||
isUIReadOnly: false,
|
||||
workspaceId,
|
||||
defaultValue: 'now',
|
||||
},
|
||||
{
|
||||
id: v4(),
|
||||
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,
|
||||
isUIReadOnly: true,
|
||||
workspaceId,
|
||||
defaultValue: null,
|
||||
},
|
||||
{
|
||||
id: v4(),
|
||||
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,
|
||||
isUIReadOnly: true,
|
||||
workspaceId,
|
||||
defaultValue: { name: "''", source: "'MANUAL'" },
|
||||
},
|
||||
{
|
||||
id: v4(),
|
||||
standardId: CUSTOM_OBJECT_STANDARD_FIELD_IDS.position,
|
||||
type: FieldMetadataType.POSITION,
|
||||
name: 'position',
|
||||
label: 'Position',
|
||||
icon: 'IconHierarchy2',
|
||||
description: 'Position',
|
||||
isNullable: false,
|
||||
isActive: true,
|
||||
isCustom: false,
|
||||
isSystem: true,
|
||||
isUIReadOnly: false,
|
||||
workspaceId,
|
||||
defaultValue: 0,
|
||||
},
|
||||
];
|
||||
+24
-41
@@ -7,7 +7,6 @@ import {
|
||||
BASE_OBJECT_STANDARD_FIELD_IDS,
|
||||
CUSTOM_OBJECT_STANDARD_FIELD_IDS,
|
||||
} from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
|
||||
import { createDeterministicUuid } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/create-deterministic-uuid.util';
|
||||
import { getTsVectorColumnExpressionFromFields } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/get-ts-vector-column-expression.util';
|
||||
|
||||
type BuildDefaultFlatFieldMetadataForCustomObjectArgs = {
|
||||
@@ -24,9 +23,10 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({
|
||||
flatObjectMetadata: { id: objectMetadataId, applicationId },
|
||||
}: BuildDefaultFlatFieldMetadataForCustomObjectArgs) => {
|
||||
const createdAt = new Date();
|
||||
const idFieldId = v4();
|
||||
const idField: FlatFieldMetadata<FieldMetadataType.UUID> = {
|
||||
type: FieldMetadataType.UUID,
|
||||
id: v4(),
|
||||
id: idFieldId,
|
||||
viewFieldIds: [],
|
||||
viewGroupIds: [],
|
||||
kanbanAggregateOperationViewIds: [],
|
||||
@@ -34,10 +34,7 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({
|
||||
isLabelSyncedWithName: false,
|
||||
isUnique: true,
|
||||
objectMetadataId,
|
||||
universalIdentifier: createDeterministicUuid([
|
||||
objectMetadataId,
|
||||
BASE_OBJECT_STANDARD_FIELD_IDS.id,
|
||||
]),
|
||||
universalIdentifier: idFieldId,
|
||||
workspaceId,
|
||||
standardId: BASE_OBJECT_STANDARD_FIELD_IDS.id,
|
||||
name: 'id',
|
||||
@@ -63,9 +60,10 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({
|
||||
applicationId: applicationId ?? null,
|
||||
};
|
||||
|
||||
const nameFieldId = v4();
|
||||
const nameField: FlatFieldMetadata<FieldMetadataType.TEXT> = {
|
||||
type: FieldMetadataType.TEXT,
|
||||
id: v4(),
|
||||
id: nameFieldId,
|
||||
viewFieldIds: [],
|
||||
viewGroupIds: [],
|
||||
kanbanAggregateOperationViewIds: [],
|
||||
@@ -73,10 +71,7 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({
|
||||
isLabelSyncedWithName: false,
|
||||
isUnique: false,
|
||||
objectMetadataId,
|
||||
universalIdentifier: createDeterministicUuid([
|
||||
objectMetadataId,
|
||||
CUSTOM_OBJECT_STANDARD_FIELD_IDS.name,
|
||||
]),
|
||||
universalIdentifier: nameFieldId,
|
||||
workspaceId,
|
||||
standardId: CUSTOM_OBJECT_STANDARD_FIELD_IDS.name,
|
||||
name: 'name',
|
||||
@@ -102,9 +97,10 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({
|
||||
applicationId: applicationId ?? null,
|
||||
};
|
||||
|
||||
const createdAtFieldId = v4();
|
||||
const createdAtField: FlatFieldMetadata<FieldMetadataType.DATE_TIME> = {
|
||||
type: FieldMetadataType.DATE_TIME,
|
||||
id: v4(),
|
||||
id: createdAtFieldId,
|
||||
viewFieldIds: [],
|
||||
viewGroupIds: [],
|
||||
kanbanAggregateOperationViewIds: [],
|
||||
@@ -112,10 +108,7 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({
|
||||
isLabelSyncedWithName: false,
|
||||
isUnique: false,
|
||||
objectMetadataId,
|
||||
universalIdentifier: createDeterministicUuid([
|
||||
objectMetadataId,
|
||||
BASE_OBJECT_STANDARD_FIELD_IDS.createdAt,
|
||||
]),
|
||||
universalIdentifier: createdAtFieldId,
|
||||
workspaceId,
|
||||
standardId: BASE_OBJECT_STANDARD_FIELD_IDS.createdAt,
|
||||
name: 'createdAt',
|
||||
@@ -141,9 +134,10 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({
|
||||
applicationId: applicationId ?? null,
|
||||
};
|
||||
|
||||
const updatedAtFieldId = v4();
|
||||
const updatedAtField: FlatFieldMetadata<FieldMetadataType.DATE_TIME> = {
|
||||
type: FieldMetadataType.DATE_TIME,
|
||||
id: v4(),
|
||||
id: updatedAtFieldId,
|
||||
viewFieldIds: [],
|
||||
viewGroupIds: [],
|
||||
kanbanAggregateOperationViewIds: [],
|
||||
@@ -151,10 +145,7 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({
|
||||
isLabelSyncedWithName: false,
|
||||
isUnique: false,
|
||||
objectMetadataId,
|
||||
universalIdentifier: createDeterministicUuid([
|
||||
objectMetadataId,
|
||||
BASE_OBJECT_STANDARD_FIELD_IDS.updatedAt,
|
||||
]),
|
||||
universalIdentifier: updatedAtFieldId,
|
||||
workspaceId,
|
||||
standardId: BASE_OBJECT_STANDARD_FIELD_IDS.updatedAt,
|
||||
name: 'updatedAt',
|
||||
@@ -180,9 +171,10 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({
|
||||
applicationId: applicationId ?? null,
|
||||
};
|
||||
|
||||
const deletedAtFieldId = v4();
|
||||
const deletedAtField: FlatFieldMetadata<FieldMetadataType.DATE_TIME> = {
|
||||
type: FieldMetadataType.DATE_TIME,
|
||||
id: v4(),
|
||||
id: deletedAtFieldId,
|
||||
viewFieldIds: [],
|
||||
viewGroupIds: [],
|
||||
kanbanAggregateOperationViewIds: [],
|
||||
@@ -190,10 +182,7 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({
|
||||
isLabelSyncedWithName: false,
|
||||
isUnique: false,
|
||||
objectMetadataId,
|
||||
universalIdentifier: createDeterministicUuid([
|
||||
objectMetadataId,
|
||||
BASE_OBJECT_STANDARD_FIELD_IDS.deletedAt,
|
||||
]),
|
||||
universalIdentifier: deletedAtFieldId,
|
||||
workspaceId,
|
||||
standardId: BASE_OBJECT_STANDARD_FIELD_IDS.deletedAt,
|
||||
name: 'deletedAt',
|
||||
@@ -219,9 +208,10 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({
|
||||
applicationId: applicationId ?? null,
|
||||
};
|
||||
|
||||
const createdByFieldId = v4();
|
||||
const createdByField: FlatFieldMetadata<FieldMetadataType.ACTOR> = {
|
||||
type: FieldMetadataType.ACTOR,
|
||||
id: v4(),
|
||||
id: createdByFieldId,
|
||||
viewFieldIds: [],
|
||||
viewGroupIds: [],
|
||||
kanbanAggregateOperationViewIds: [],
|
||||
@@ -229,10 +219,7 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({
|
||||
isLabelSyncedWithName: false,
|
||||
isUnique: false,
|
||||
objectMetadataId,
|
||||
universalIdentifier: createDeterministicUuid([
|
||||
objectMetadataId,
|
||||
CUSTOM_OBJECT_STANDARD_FIELD_IDS.createdBy,
|
||||
]),
|
||||
universalIdentifier: createdByFieldId,
|
||||
workspaceId,
|
||||
standardId: CUSTOM_OBJECT_STANDARD_FIELD_IDS.createdBy,
|
||||
name: 'createdBy',
|
||||
@@ -257,9 +244,10 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({
|
||||
applicationId: applicationId ?? null,
|
||||
};
|
||||
|
||||
const positionFieldId = v4();
|
||||
const positionField: FlatFieldMetadata<FieldMetadataType.POSITION> = {
|
||||
type: FieldMetadataType.POSITION,
|
||||
id: v4(),
|
||||
id: positionFieldId,
|
||||
viewFieldIds: [],
|
||||
viewGroupIds: [],
|
||||
kanbanAggregateOperationViewIds: [],
|
||||
@@ -267,10 +255,7 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({
|
||||
isLabelSyncedWithName: false,
|
||||
isUnique: false,
|
||||
objectMetadataId,
|
||||
universalIdentifier: createDeterministicUuid([
|
||||
objectMetadataId,
|
||||
CUSTOM_OBJECT_STANDARD_FIELD_IDS.position,
|
||||
]),
|
||||
universalIdentifier: positionFieldId,
|
||||
workspaceId,
|
||||
standardId: CUSTOM_OBJECT_STANDARD_FIELD_IDS.position,
|
||||
name: 'position',
|
||||
@@ -296,20 +281,18 @@ export const buildDefaultFlatFieldMetadatasForCustomObject = ({
|
||||
applicationId: applicationId ?? null,
|
||||
};
|
||||
|
||||
const searchVectorFieldId = v4();
|
||||
const searchVectorField: FlatFieldMetadata<FieldMetadataType.TS_VECTOR> = {
|
||||
type: FieldMetadataType.TS_VECTOR,
|
||||
viewFieldIds: [],
|
||||
viewGroupIds: [],
|
||||
kanbanAggregateOperationViewIds: [],
|
||||
calendarViewIds: [],
|
||||
id: v4(),
|
||||
id: searchVectorFieldId,
|
||||
isLabelSyncedWithName: false,
|
||||
isUnique: false,
|
||||
objectMetadataId,
|
||||
universalIdentifier: createDeterministicUuid([
|
||||
objectMetadataId,
|
||||
CUSTOM_OBJECT_STANDARD_FIELD_IDS.searchVector,
|
||||
]),
|
||||
universalIdentifier: searchVectorFieldId,
|
||||
workspaceId,
|
||||
standardId: CUSTOM_OBJECT_STANDARD_FIELD_IDS.searchVector,
|
||||
name: 'searchVector',
|
||||
|
||||
+8
-31
@@ -1,7 +1,7 @@
|
||||
import { type STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
|
||||
import { FieldMetadataType, RelationOnDeleteAction } from 'twenty-shared/types';
|
||||
import { capitalize, isDefined } from 'twenty-shared/utils';
|
||||
import { v4 } from 'uuid';
|
||||
import { type STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
|
||||
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
|
||||
@@ -16,15 +16,9 @@ import {
|
||||
} from 'src/engine/metadata-modules/object-metadata/object-metadata.exception';
|
||||
import { buildDescriptionForRelationFieldMetadataOnFromField } from 'src/engine/metadata-modules/object-metadata/utils/build-description-for-relation-field-on-from-field.util';
|
||||
import { buildDescriptionForRelationFieldMetadataOnToField } from 'src/engine/metadata-modules/object-metadata/utils/build-description-for-relation-field-on-to-field.util';
|
||||
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_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 {
|
||||
createDeterministicUuid,
|
||||
createRelationDeterministicUuid,
|
||||
} from 'src/engine/workspace-manager/workspace-sync-metadata/utils/create-deterministic-uuid.util';
|
||||
import { createRelationDeterministicUuid } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/create-deterministic-uuid.util';
|
||||
|
||||
const generateSourceFlatFieldMetadata = ({
|
||||
workspaceId,
|
||||
@@ -49,17 +43,6 @@ const generateSourceFlatFieldMetadata = ({
|
||||
STANDARD_OBJECT_ICONS[
|
||||
targetFlatObjectMetadata.nameSingular as keyof typeof STANDARD_OBJECT_ICONS
|
||||
] || 'IconBuildingSkyscraper';
|
||||
const standardId =
|
||||
CUSTOM_OBJECT_STANDARD_FIELD_IDS[
|
||||
targetFlatObjectMetadata.namePlural as keyof typeof CUSTOM_OBJECT_STANDARD_FIELD_IDS
|
||||
];
|
||||
|
||||
if (!isDefined(standardId)) {
|
||||
throw new ObjectMetadataException(
|
||||
`Standard field ID not found for target object ${targetFlatObjectMetadata.namePlural}`,
|
||||
ObjectMetadataExceptionCode.INTERNAL_SERVER_ERROR,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
calendarViewIds: [],
|
||||
@@ -89,16 +72,13 @@ const generateSourceFlatFieldMetadata = ({
|
||||
settings: {
|
||||
relationType: RelationType.ONE_TO_MANY,
|
||||
},
|
||||
standardId,
|
||||
standardId: null,
|
||||
standardOverrides: null,
|
||||
type: FieldMetadataType.RELATION,
|
||||
universalIdentifier: createDeterministicUuid([
|
||||
sourceFlatObjectMetadata.id,
|
||||
standardId,
|
||||
]),
|
||||
universalIdentifier: sourceFieldMetadataId,
|
||||
workspaceId,
|
||||
morphId: null,
|
||||
applicationId: sourceFlatObjectMetadata.applicationId ?? null,
|
||||
applicationId: sourceFlatObjectMetadata.applicationId,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -165,11 +145,8 @@ const generateTargetFlatFieldMetadata = ({
|
||||
relationTargetFieldMetadataId: sourceFlatFieldMetadata.id,
|
||||
relationTargetObjectMetadataId: sourceFlatObjectMetadata.id,
|
||||
standardOverrides: null,
|
||||
universalIdentifier: createDeterministicUuid([
|
||||
targetFlatObjectMetadata.id,
|
||||
standardId,
|
||||
]),
|
||||
applicationId: sourceFlatObjectMetadata.applicationId ?? null,
|
||||
universalIdentifier: sourceFlatFieldMetadata.relationTargetFieldMetadataId,
|
||||
applicationId: sourceFlatObjectMetadata.applicationId,
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { ApiKeyModule } from 'src/engine/core-modules/api-key/api-key.module';
|
||||
import { ApplicationModule } from 'src/engine/core-modules/application/application.module';
|
||||
import { FileModule } from 'src/engine/core-modules/file/file.module';
|
||||
import { UserWorkspaceEntity } from 'src/engine/core-modules/user-workspace/user-workspace.entity';
|
||||
import { UserWorkspaceModule } from 'src/engine/core-modules/user-workspace/user-workspace.module';
|
||||
@@ -30,6 +31,7 @@ import { WorkspacePermissionsCacheModule } from 'src/engine/metadata-modules/wor
|
||||
PermissionFlagModule,
|
||||
WorkspacePermissionsCacheModule,
|
||||
FileModule,
|
||||
ApplicationModule,
|
||||
],
|
||||
providers: [RoleService, RoleResolver],
|
||||
exports: [RoleService],
|
||||
|
||||
@@ -3,7 +3,9 @@ import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { Repository } from 'typeorm';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { MEMBER_ROLE_LABEL } from 'src/engine/metadata-modules/permissions/constants/member-role-label.constants';
|
||||
import {
|
||||
@@ -29,6 +31,7 @@ export class RoleService {
|
||||
private readonly roleRepository: Repository<RoleEntity>,
|
||||
private readonly userRoleService: UserRoleService,
|
||||
private readonly workspacePermissionsCacheService: WorkspacePermissionsCacheService,
|
||||
private readonly applicationService: ApplicationService,
|
||||
) {}
|
||||
|
||||
public async getWorkspaceRoles(workspaceId: string): Promise<RoleEntity[]> {
|
||||
@@ -70,10 +73,18 @@ export class RoleService {
|
||||
input: CreateRoleInput;
|
||||
workspaceId: string;
|
||||
}): Promise<RoleEntity> {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
await this.validateRoleInputOrThrow({ input, workspaceId });
|
||||
|
||||
const id = input.id ?? v4();
|
||||
const role = await this.roleRepository.save({
|
||||
id: input.id,
|
||||
id,
|
||||
label: input.label,
|
||||
description: input.description,
|
||||
icon: input.icon,
|
||||
@@ -88,6 +99,8 @@ export class RoleService {
|
||||
canBeAssignedToApiKeys: input.canBeAssignedToApiKeys,
|
||||
isEditable: true,
|
||||
workspaceId,
|
||||
applicationId: workspaceCustomFlatApplication.id,
|
||||
universalIdentifier: id,
|
||||
});
|
||||
|
||||
await this.workspacePermissionsCacheService.recomputeRolesPermissionsCache({
|
||||
@@ -198,9 +211,13 @@ export class RoleService {
|
||||
|
||||
public async createMemberRole({
|
||||
workspaceId,
|
||||
applicationId,
|
||||
}: {
|
||||
applicationId: string;
|
||||
workspaceId: string;
|
||||
}): Promise<RoleEntity> {
|
||||
const id = v4();
|
||||
|
||||
return this.roleRepository.save({
|
||||
label: MEMBER_ROLE_LABEL,
|
||||
description: 'Member role',
|
||||
@@ -216,15 +233,22 @@ export class RoleService {
|
||||
canBeAssignedToApiKeys: false,
|
||||
isEditable: true,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
id,
|
||||
universalIdentifier: id,
|
||||
});
|
||||
}
|
||||
|
||||
// Only used for dev seeding and testing
|
||||
public async createGuestRole({
|
||||
workspaceId,
|
||||
applicationId,
|
||||
}: {
|
||||
workspaceId: string;
|
||||
applicationId: string;
|
||||
}): Promise<RoleEntity> {
|
||||
const id = v4();
|
||||
|
||||
return this.roleRepository.save({
|
||||
label: 'Guest',
|
||||
description: 'Guest role',
|
||||
@@ -240,6 +264,9 @@ export class RoleService {
|
||||
canBeAssignedToApiKeys: false,
|
||||
isEditable: false,
|
||||
workspaceId,
|
||||
applicationId,
|
||||
id,
|
||||
universalIdentifier: id,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+2
@@ -1,6 +1,7 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { ApplicationModule } from 'src/engine/core-modules/application/application.module';
|
||||
import { TokenModule } from 'src/engine/core-modules/auth/token/token.module';
|
||||
import { WorkspaceDomainsModule } from 'src/engine/core-modules/domain/workspace-domains/workspace-domains.module';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheModule } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.module';
|
||||
@@ -17,6 +18,7 @@ import { WorkspaceMigrationV2Module } from 'src/engine/workspace-manager/workspa
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([RouteTriggerEntity]),
|
||||
ApplicationModule,
|
||||
TokenModule,
|
||||
WorkspaceDomainsModule,
|
||||
ServerlessFunctionModule,
|
||||
|
||||
+16
@@ -2,6 +2,7 @@ import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { computeFlatEntityMapsFromTo } from 'src/engine/metadata-modules/flat-entity/utils/compute-flat-entity-maps-from-to.util';
|
||||
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
@@ -23,12 +24,25 @@ export class RouteTriggerV2Service {
|
||||
constructor(
|
||||
private readonly flatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
|
||||
private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService,
|
||||
private readonly applicationService: ApplicationService,
|
||||
) {}
|
||||
|
||||
async createOne(
|
||||
routeTriggerInput: CreateRouteTriggerInput,
|
||||
workspaceId: string,
|
||||
/**
|
||||
* @deprecated do not use call validateBuildAndRunWorkspaceMigration contextually
|
||||
* when interacting with another application than workspace custom one
|
||||
* */
|
||||
applicationId?: string,
|
||||
) {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
const flatEntityMaps =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
@@ -43,6 +57,8 @@ export class RouteTriggerV2Service {
|
||||
fromCreateRouteTriggerInputToFlatRouteTrigger({
|
||||
createRouteTriggerInput: routeTriggerInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId:
|
||||
applicationId ?? workspaceCustomFlatApplication.id,
|
||||
});
|
||||
|
||||
const validateAndBuildResult =
|
||||
|
||||
+6
-4
@@ -6,16 +6,18 @@ import { type FlatRouteTrigger } from 'src/engine/metadata-modules/route-trigger
|
||||
export const fromCreateRouteTriggerInputToFlatRouteTrigger = ({
|
||||
createRouteTriggerInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
}: {
|
||||
createRouteTriggerInput: CreateRouteTriggerInput;
|
||||
workspaceId: string;
|
||||
workspaceCustomApplicationId: string;
|
||||
}): FlatRouteTrigger => {
|
||||
const now = new Date();
|
||||
const id = uuidV4();
|
||||
|
||||
return {
|
||||
id: uuidV4(),
|
||||
universalIdentifier:
|
||||
createRouteTriggerInput.universalIdentifier ?? uuidV4(),
|
||||
id,
|
||||
universalIdentifier: createRouteTriggerInput.universalIdentifier ?? id,
|
||||
path: createRouteTriggerInput.path,
|
||||
isAuthRequired: createRouteTriggerInput.isAuthRequired,
|
||||
httpMethod: createRouteTriggerInput.httpMethod,
|
||||
@@ -23,6 +25,6 @@ export const fromCreateRouteTriggerInputToFlatRouteTrigger = ({
|
||||
workspaceId,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
applicationId: createRouteTriggerInput.applicationId ?? null,
|
||||
applicationId: workspaceCustomApplicationId,
|
||||
};
|
||||
};
|
||||
|
||||
+2
@@ -3,6 +3,7 @@ import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm';
|
||||
|
||||
import { ApplicationModule } from 'src/engine/core-modules/application/application.module';
|
||||
import { AuditModule } from 'src/engine/core-modules/audit/audit.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';
|
||||
@@ -35,6 +36,7 @@ import { WorkspaceMigrationV2Module } from 'src/engine/workspace-manager/workspa
|
||||
]),
|
||||
FileModule,
|
||||
ThrottlerModule,
|
||||
ApplicationModule,
|
||||
AuditModule,
|
||||
FeatureFlagModule,
|
||||
PermissionsModule,
|
||||
|
||||
+10
@@ -2,6 +2,7 @@ import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { computeFlatEntityMapsFromTo } from 'src/engine/metadata-modules/flat-entity/utils/compute-flat-entity-maps-from-to.util';
|
||||
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
@@ -23,6 +24,7 @@ export class ServerlessFunctionV2Service {
|
||||
constructor(
|
||||
private readonly flatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
|
||||
private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService,
|
||||
private readonly applicationService: ApplicationService,
|
||||
) {}
|
||||
|
||||
async createOne({
|
||||
@@ -34,6 +36,13 @@ export class ServerlessFunctionV2Service {
|
||||
};
|
||||
workspaceId: string;
|
||||
}) {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
const flatEntityMaps =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
@@ -49,6 +58,7 @@ export class ServerlessFunctionV2Service {
|
||||
fromCreateServerlessFunctionInputToFlatServerlessFunction({
|
||||
createServerlessFunctionInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId: workspaceCustomFlatApplication.id,
|
||||
});
|
||||
|
||||
const validateAndBuildResult =
|
||||
|
||||
+4
-2
@@ -14,11 +14,13 @@ export type FromCreateServerlessFunctionInputToFlatServerlessFunctionArgs = {
|
||||
serverlessFunctionLayerId: string;
|
||||
};
|
||||
workspaceId: string;
|
||||
workspaceCustomApplicationId: string;
|
||||
};
|
||||
|
||||
export const fromCreateServerlessFunctionInputToFlatServerlessFunction = ({
|
||||
createServerlessFunctionInput: rawCreateServerlessFunctionInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId,
|
||||
}: FromCreateServerlessFunctionInputToFlatServerlessFunctionArgs): FlatServerlessFunction => {
|
||||
const id = v4();
|
||||
const currentDate = new Date();
|
||||
@@ -35,13 +37,13 @@ export const fromCreateServerlessFunctionInputToFlatServerlessFunction = ({
|
||||
handlerName:
|
||||
rawCreateServerlessFunctionInput.handlerName ?? DEFAULT_HANDLER_NAME,
|
||||
universalIdentifier:
|
||||
rawCreateServerlessFunctionInput.universalIdentifier ?? v4(),
|
||||
rawCreateServerlessFunctionInput.universalIdentifier ?? id,
|
||||
createdAt: currentDate,
|
||||
updatedAt: currentDate,
|
||||
deletedAt: null,
|
||||
latestVersion: null,
|
||||
publishedVersions: [],
|
||||
applicationId: rawCreateServerlessFunctionInput.applicationId ?? null,
|
||||
applicationId: workspaceCustomApplicationId,
|
||||
runtime: ServerlessFunctionRuntime.NODE22,
|
||||
timeoutSeconds: rawCreateServerlessFunctionInput.timeoutSeconds ?? 300,
|
||||
serverlessFunctionLayerId:
|
||||
|
||||
+10
@@ -4,6 +4,7 @@ import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { IsNull, Repository } from 'typeorm';
|
||||
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { computeFlatEntityMapsFromTo } from 'src/engine/metadata-modules/flat-entity/utils/compute-flat-entity-maps-from-to.util';
|
||||
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
@@ -32,6 +33,7 @@ export class ViewFieldV2Service {
|
||||
private readonly workspaceManyOrAllFlatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
|
||||
@InjectRepository(ViewFieldEntity)
|
||||
private readonly viewFieldRepository: Repository<ViewFieldEntity>,
|
||||
private readonly applicationService: ApplicationService,
|
||||
) {}
|
||||
|
||||
async createOne({
|
||||
@@ -67,6 +69,13 @@ export class ViewFieldV2Service {
|
||||
return [];
|
||||
}
|
||||
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
const {
|
||||
flatViewFieldMaps: existingFlatViewFieldMaps,
|
||||
flatViewMaps,
|
||||
@@ -89,6 +98,7 @@ export class ViewFieldV2Service {
|
||||
fromCreateViewFieldInputToFlatViewFieldToCreate({
|
||||
createViewFieldInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId: workspaceCustomFlatApplication.id,
|
||||
}),
|
||||
);
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { ApplicationModule } from 'src/engine/core-modules/application/application.module';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheModule } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.module';
|
||||
import { PermissionsModule } from 'src/engine/metadata-modules/permissions/permissions.module';
|
||||
import { ViewFieldController } from 'src/engine/metadata-modules/view-field/controllers/view-field.controller';
|
||||
@@ -16,6 +17,7 @@ import { WorkspaceMigrationV2Module } from 'src/engine/workspace-manager/workspa
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([ViewFieldEntity, ViewEntity]),
|
||||
WorkspaceCacheStorageModule,
|
||||
ApplicationModule,
|
||||
PermissionsModule,
|
||||
WorkspaceMigrationV2Module,
|
||||
WorkspaceManyOrAllFlatEntityMapsCacheModule,
|
||||
|
||||
+10
@@ -2,6 +2,7 @@ import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { computeFlatEntityMapsFromTo } from 'src/engine/metadata-modules/flat-entity/utils/compute-flat-entity-maps-from-to.util';
|
||||
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
@@ -22,6 +23,7 @@ export class ViewFilterV2Service {
|
||||
constructor(
|
||||
private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService,
|
||||
private readonly flatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
|
||||
private readonly applicationService: ApplicationService,
|
||||
) {}
|
||||
|
||||
async createOne({
|
||||
@@ -31,6 +33,13 @@ export class ViewFilterV2Service {
|
||||
createViewFilterInput: CreateViewFilterInput;
|
||||
workspaceId: string;
|
||||
}): Promise<ViewFilterDTO> {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
const {
|
||||
flatViewFilterMaps: existingFlatViewFilterMaps,
|
||||
flatViewMaps,
|
||||
@@ -52,6 +61,7 @@ export class ViewFilterV2Service {
|
||||
fromCreateViewFilterInputToFlatViewFilterToCreate({
|
||||
createViewFilterInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId: workspaceCustomFlatApplication.id,
|
||||
});
|
||||
|
||||
const validateAndBuildResult =
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { ApplicationModule } from 'src/engine/core-modules/application/application.module';
|
||||
import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheModule } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.module';
|
||||
import { PermissionsModule } from 'src/engine/metadata-modules/permissions/permissions.module';
|
||||
@@ -18,6 +19,7 @@ import { WorkspaceMigrationV2Module } from 'src/engine/workspace-manager/workspa
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([ViewFilterEntity, ViewEntity]),
|
||||
WorkspaceCacheStorageModule,
|
||||
ApplicationModule,
|
||||
FeatureFlagModule,
|
||||
PermissionsModule,
|
||||
WorkspaceMigrationV2Module,
|
||||
|
||||
+10
@@ -2,6 +2,7 @@ import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { computeFlatEntityMapsFromTo } from 'src/engine/metadata-modules/flat-entity/utils/compute-flat-entity-maps-from-to.util';
|
||||
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
@@ -27,6 +28,7 @@ export class ViewGroupV2Service {
|
||||
constructor(
|
||||
private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService,
|
||||
private readonly flatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
|
||||
private readonly applicationService: ApplicationService,
|
||||
) {}
|
||||
|
||||
async createOne({
|
||||
@@ -62,6 +64,13 @@ export class ViewGroupV2Service {
|
||||
return [];
|
||||
}
|
||||
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
const {
|
||||
flatViewGroupMaps: existingFlatViewGroupMaps,
|
||||
flatViewMaps,
|
||||
@@ -82,6 +91,7 @@ export class ViewGroupV2Service {
|
||||
fromCreateViewGroupInputToFlatViewGroupToCreate({
|
||||
createViewGroupInput,
|
||||
workspaceId,
|
||||
workspaceCustomApplicationId: workspaceCustomFlatApplication.id,
|
||||
}),
|
||||
);
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { ApplicationModule } from 'src/engine/core-modules/application/application.module';
|
||||
import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheModule } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.module';
|
||||
import { PermissionsModule } from 'src/engine/metadata-modules/permissions/permissions.module';
|
||||
@@ -18,6 +19,7 @@ import { WorkspaceMigrationV2Module } from 'src/engine/workspace-manager/workspa
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([ViewGroupEntity, ViewEntity]),
|
||||
WorkspaceCacheStorageModule,
|
||||
ApplicationModule,
|
||||
FeatureFlagModule,
|
||||
PermissionsModule,
|
||||
WorkspaceMigrationV2Module,
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { computeFlatEntityMapsFromTo } from 'src/engine/metadata-modules/flat-entity/utils/compute-flat-entity-maps-from-to.util';
|
||||
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
@@ -22,6 +23,7 @@ export class ViewV2Service {
|
||||
constructor(
|
||||
private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService,
|
||||
private readonly flatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
|
||||
private readonly applicationService: ApplicationService,
|
||||
) {}
|
||||
|
||||
async createOne({
|
||||
@@ -33,6 +35,13 @@ export class ViewV2Service {
|
||||
workspaceId: string;
|
||||
createdByUserWorkspaceId?: string;
|
||||
}): Promise<ViewDTO> {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
const {
|
||||
flatObjectMetadataMaps,
|
||||
flatViewMaps: existingFlatViewMaps,
|
||||
@@ -52,6 +61,7 @@ export class ViewV2Service {
|
||||
createViewInput,
|
||||
workspaceId,
|
||||
createdByUserWorkspaceId,
|
||||
workspaceCustomApplicationId: workspaceCustomFlatApplication.id,
|
||||
});
|
||||
|
||||
const validateAndBuildResult =
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { ApplicationModule } from 'src/engine/core-modules/application/application.module';
|
||||
import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module';
|
||||
import { I18nModule } from 'src/engine/core-modules/i18n/i18n.module';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheModule } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.module';
|
||||
@@ -32,6 +33,7 @@ import { WorkspaceMigrationV2Module } from 'src/engine/workspace-manager/workspa
|
||||
ViewGroupModule,
|
||||
ViewSortModule,
|
||||
I18nModule,
|
||||
ApplicationModule,
|
||||
FeatureFlagModule,
|
||||
PermissionsModule,
|
||||
UserRoleModule,
|
||||
|
||||
+1
-5
@@ -8,8 +8,6 @@ import { isDefined } from 'twenty-shared/utils';
|
||||
import { InjectCacheStorage } from 'src/engine/core-modules/cache-storage/decorators/cache-storage.decorator';
|
||||
import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service';
|
||||
import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum';
|
||||
import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/flat-entity-maps.type';
|
||||
import { type FlatEntity } from 'src/engine/metadata-modules/flat-entity/types/flat-entity.type';
|
||||
import { WORKSPACE_FLAT_MAP_CACHE_KEY } from 'src/engine/workspace-flat-map-cache/decorators/workspace-flat-map-cache.decorator';
|
||||
import {
|
||||
WorkspaceFlatMapCacheException,
|
||||
@@ -17,9 +15,7 @@ import {
|
||||
} from 'src/engine/workspace-flat-map-cache/exceptions/workspace-flat-map-cache.exception';
|
||||
|
||||
@Injectable()
|
||||
export abstract class WorkspaceFlatMapCacheService<
|
||||
T extends FlatEntityMaps<FlatEntity>,
|
||||
> {
|
||||
export abstract class WorkspaceFlatMapCacheService<T> {
|
||||
protected readonly logger = new Logger(this.constructor.name);
|
||||
|
||||
private readonly localCacheFlatMaps = new Map<string, T>();
|
||||
|
||||
+10
-1
@@ -4,6 +4,7 @@ import { InjectDataSource, InjectRepository } from '@nestjs/typeorm';
|
||||
import { WorkspaceActivationStatus } from 'twenty-shared/workspace';
|
||||
import { DataSource, Repository } from 'typeorm';
|
||||
|
||||
import { ApplicationEntity } from 'src/engine/core-modules/application/application.entity';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { FieldPermissionService } from 'src/engine/metadata-modules/object-permission/field-permission/field-permission.service';
|
||||
@@ -41,7 +42,13 @@ export class DevSeederPermissionsService {
|
||||
private readonly coreDataSource: DataSource,
|
||||
) {}
|
||||
|
||||
public async initPermissions(workspaceId: string) {
|
||||
public async initPermissions({
|
||||
twentyStandardApplication,
|
||||
workspaceId,
|
||||
}: {
|
||||
workspaceId: string;
|
||||
twentyStandardApplication: ApplicationEntity;
|
||||
}) {
|
||||
const adminRole = await this.roleRepository.findOne({
|
||||
where: {
|
||||
standardId: ADMIN_ROLE.standardId,
|
||||
@@ -100,6 +107,7 @@ export class DevSeederPermissionsService {
|
||||
|
||||
const guestRole = await this.roleService.createGuestRole({
|
||||
workspaceId,
|
||||
applicationId: twentyStandardApplication.id,
|
||||
});
|
||||
|
||||
await this.userRoleService.assignRoleToUserWorkspace({
|
||||
@@ -135,6 +143,7 @@ export class DevSeederPermissionsService {
|
||||
|
||||
const memberRole = await this.roleService.createMemberRole({
|
||||
workspaceId,
|
||||
applicationId: twentyStandardApplication.id,
|
||||
});
|
||||
|
||||
await this.coreDataSource
|
||||
|
||||
+9
-16
@@ -13,7 +13,6 @@ import { seedFeatureFlags } from 'src/engine/workspace-manager/dev-seeder/core/u
|
||||
import { seedUserWorkspaces } from 'src/engine/workspace-manager/dev-seeder/core/utils/seed-user-workspaces.util';
|
||||
import { seedUsers } from 'src/engine/workspace-manager/dev-seeder/core/utils/seed-users.util';
|
||||
import { createWorkspace } from 'src/engine/workspace-manager/dev-seeder/core/utils/seed-workspace.util';
|
||||
import { computeWorkspaceCustomCreateApplicationInput } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/compute-workspace-custom-create-application-input';
|
||||
import { extractVersionMajorMinorPatch } from 'src/utils/version/extract-version-major-minor-patch';
|
||||
|
||||
type SeedCoreSchemaArgs = {
|
||||
@@ -36,14 +35,6 @@ export const seedCoreSchema = async ({
|
||||
const schemaName = 'core';
|
||||
|
||||
const createWorkspaceStaticInput = SEEDER_CREATE_WORKSPACE_INPUT[workspaceId];
|
||||
const workspaceCustomApplicationCreateInput =
|
||||
computeWorkspaceCustomCreateApplicationInput({
|
||||
workspace: {
|
||||
id: workspaceId,
|
||||
displayName: createWorkspaceStaticInput.displayName,
|
||||
},
|
||||
});
|
||||
|
||||
const version = extractVersionMajorMinorPatch(appVersion);
|
||||
const queryRunner = dataSource.createQueryRunner();
|
||||
|
||||
@@ -51,13 +42,14 @@ export const seedCoreSchema = async ({
|
||||
await queryRunner.startTransaction();
|
||||
|
||||
try {
|
||||
const customWorkspaceApplication = await applicationService.create(
|
||||
{
|
||||
...workspaceCustomApplicationCreateInput,
|
||||
serverlessFunctionLayerId: null,
|
||||
},
|
||||
queryRunner,
|
||||
);
|
||||
const customWorkspaceApplication =
|
||||
await applicationService.createWorkspaceCustomApplication(
|
||||
{
|
||||
workspaceId,
|
||||
workspaceDisplayName: createWorkspaceStaticInput.displayName,
|
||||
},
|
||||
queryRunner,
|
||||
);
|
||||
|
||||
await createWorkspace({
|
||||
queryRunner,
|
||||
@@ -76,6 +68,7 @@ export const seedCoreSchema = async ({
|
||||
await applicationService.createTwentyStandardApplication(
|
||||
{
|
||||
workspaceId,
|
||||
skipCacheInvalidation: true,
|
||||
},
|
||||
queryRunner,
|
||||
);
|
||||
|
||||
+8
@@ -4,6 +4,7 @@ import { InjectDataSource } from '@nestjs/typeorm';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { DataSource } from 'typeorm';
|
||||
|
||||
import { FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import { type DataSourceEntity } from 'src/engine/metadata-modules/data-source/data-source.entity';
|
||||
import { CreateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input';
|
||||
import { FieldMetadataServiceV2 } from 'src/engine/metadata-modules/field-metadata/services/field-metadata.service-v2';
|
||||
@@ -85,9 +86,11 @@ export class DevSeederMetadataService {
|
||||
dataSourceMetadata,
|
||||
workspaceId,
|
||||
featureFlags,
|
||||
twentyStandardFlatApplication,
|
||||
}: {
|
||||
dataSourceMetadata: DataSourceEntity;
|
||||
workspaceId: string;
|
||||
twentyStandardFlatApplication: FlatApplication;
|
||||
featureFlags?: Record<string, boolean>;
|
||||
}) {
|
||||
const config = this.workspaceConfigs[workspaceId];
|
||||
@@ -98,6 +101,7 @@ export class DevSeederMetadataService {
|
||||
);
|
||||
}
|
||||
|
||||
// TODO get
|
||||
for (const obj of config.objects) {
|
||||
await this.seedCustomObject({
|
||||
dataSourceId: dataSourceMetadata.id,
|
||||
@@ -126,6 +130,7 @@ export class DevSeederMetadataService {
|
||||
workspaceId,
|
||||
dataSourceMetadata,
|
||||
featureFlags,
|
||||
twentyStandardFlatApplication,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -181,10 +186,12 @@ export class DevSeederMetadataService {
|
||||
workspaceId,
|
||||
dataSourceMetadata,
|
||||
featureFlags,
|
||||
twentyStandardFlatApplication,
|
||||
}: {
|
||||
workspaceId: string;
|
||||
dataSourceMetadata: DataSourceEntity;
|
||||
featureFlags?: Record<string, boolean>;
|
||||
twentyStandardFlatApplication: FlatApplication;
|
||||
}): Promise<void> {
|
||||
const createdObjectMetadata =
|
||||
await this.objectMetadataServiceV2.findManyWithinWorkspace(workspaceId);
|
||||
@@ -195,6 +202,7 @@ export class DevSeederMetadataService {
|
||||
objectMetadataItems: createdObjectMetadata,
|
||||
workspaceSchemaName: dataSourceMetadata.schema,
|
||||
featureFlags,
|
||||
twentyStandardFlatApplication,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+19
-2
@@ -5,6 +5,8 @@ import { isDefined } from 'twenty-shared/utils';
|
||||
import { DataSource } from 'typeorm';
|
||||
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
|
||||
import { TWENTY_STANDARD_APPLICATION } from 'src/engine/core-modules/application/constants/twenty-standard-applications';
|
||||
import { WorkspaceFlatApplicationMapCacheService } from 'src/engine/core-modules/application/services/workspace-flat-application-map-cache.service';
|
||||
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||
import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service';
|
||||
import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service';
|
||||
@@ -21,7 +23,6 @@ import { seedPageLayoutWidgets } from 'src/engine/workspace-manager/dev-seeder/c
|
||||
import { seedPageLayouts } from 'src/engine/workspace-manager/dev-seeder/core/utils/seed-page-layouts.util';
|
||||
import { DevSeederDataService } from 'src/engine/workspace-manager/dev-seeder/data/services/dev-seeder-data.service';
|
||||
import { DevSeederMetadataService } from 'src/engine/workspace-manager/dev-seeder/metadata/services/dev-seeder-metadata.service';
|
||||
import { TWENTY_STANDARD_APPLICATION } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/twenty-standard-applications';
|
||||
import { WorkspaceSyncMetadataService } from 'src/engine/workspace-manager/workspace-sync-metadata/workspace-sync-metadata.service';
|
||||
|
||||
@Injectable()
|
||||
@@ -38,6 +39,7 @@ export class DevSeederService {
|
||||
private readonly flatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
|
||||
private readonly devSeederDataService: DevSeederDataService,
|
||||
private readonly applicationService: ApplicationService,
|
||||
private readonly workspaceFlatApplicationMapCacheService: WorkspaceFlatApplicationMapCacheService,
|
||||
@InjectDataSource()
|
||||
private readonly coreDataSource: DataSource,
|
||||
) {}
|
||||
@@ -59,6 +61,10 @@ export class DevSeederService {
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
await this.workspaceFlatApplicationMapCacheService.invalidateCache({
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
const dataSourceMetadata =
|
||||
await this.dataSourceService.createDataSourceMetadata(
|
||||
workspaceId,
|
||||
@@ -80,6 +86,13 @@ export class DevSeederService {
|
||||
);
|
||||
}
|
||||
|
||||
const { twentyStandardFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
await this.workspaceSyncMetadataService.synchronize({
|
||||
workspaceId: workspaceId,
|
||||
dataSourceId: dataSourceMetadata.id,
|
||||
@@ -90,13 +103,17 @@ export class DevSeederService {
|
||||
dataSourceMetadata,
|
||||
workspaceId,
|
||||
featureFlags,
|
||||
twentyStandardFlatApplication,
|
||||
});
|
||||
|
||||
await this.devSeederMetadataService.seedRelations({
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
await this.devSeederPermissionsService.initPermissions(workspaceId);
|
||||
await this.devSeederPermissionsService.initPermissions({
|
||||
workspaceId,
|
||||
twentyStandardApplication,
|
||||
});
|
||||
|
||||
await seedPageLayouts(this.coreDataSource, 'core', workspaceId);
|
||||
await seedPageLayoutTabs(this.coreDataSource, 'core', workspaceId);
|
||||
|
||||
+45
-26
@@ -1,7 +1,7 @@
|
||||
import { isString } from '@sniptt/guards';
|
||||
import { type DataSource, type QueryRunner } from 'typeorm';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { ViewFieldEntity } from 'src/engine/metadata-modules/view-field/entities/view-field.entity';
|
||||
import { ViewFilterEntity } from 'src/engine/metadata-modules/view-filter/entities/view-filter.entity';
|
||||
@@ -39,6 +39,7 @@ type PrefillCoreViewsArgs = {
|
||||
objectMetadataItems: ObjectMetadataEntity[];
|
||||
featureFlags?: Record<string, boolean>;
|
||||
workspaceSchemaName: string;
|
||||
twentyStandardFlatApplication: FlatApplication;
|
||||
};
|
||||
|
||||
export const prefillCoreViews = async ({
|
||||
@@ -46,25 +47,32 @@ export const prefillCoreViews = async ({
|
||||
workspaceId,
|
||||
objectMetadataItems,
|
||||
workspaceSchemaName,
|
||||
twentyStandardFlatApplication,
|
||||
}: PrefillCoreViewsArgs): Promise<ViewEntity[]> => {
|
||||
const views = [
|
||||
companiesAllView(objectMetadataItems, true),
|
||||
peopleAllView(objectMetadataItems, true),
|
||||
opportunitiesAllView(objectMetadataItems, true),
|
||||
opportunitiesByStageView(objectMetadataItems, true),
|
||||
notesAllView(objectMetadataItems, true),
|
||||
tasksAllView(objectMetadataItems, true),
|
||||
tasksAssignedToMeView(objectMetadataItems, true),
|
||||
tasksByStatusView(objectMetadataItems, true),
|
||||
workflowsAllView(objectMetadataItems, true),
|
||||
workflowVersionsAllView(objectMetadataItems, true),
|
||||
workflowRunsAllView(objectMetadataItems, true),
|
||||
dashboardsAllView(objectMetadataItems, true),
|
||||
workspaceMembersAllView(objectMetadataItems, true),
|
||||
messagesAllView(objectMetadataItems, true),
|
||||
messageThreadsAllView(objectMetadataItems, true),
|
||||
calendarEventsAllView(objectMetadataItems, true),
|
||||
];
|
||||
companiesAllView,
|
||||
peopleAllView,
|
||||
opportunitiesAllView,
|
||||
opportunitiesByStageView,
|
||||
notesAllView,
|
||||
tasksAllView,
|
||||
tasksAssignedToMeView,
|
||||
tasksByStatusView,
|
||||
workflowsAllView,
|
||||
workflowVersionsAllView,
|
||||
workflowRunsAllView,
|
||||
dashboardsAllView,
|
||||
workspaceMembersAllView,
|
||||
messagesAllView,
|
||||
messageThreadsAllView,
|
||||
calendarEventsAllView,
|
||||
].map((seeder) =>
|
||||
seeder({
|
||||
objectMetadataItems,
|
||||
useCoreNaming: true,
|
||||
twentyStandardFlatApplication,
|
||||
}),
|
||||
);
|
||||
|
||||
const queryRunner = coreDataSource.createQueryRunner();
|
||||
|
||||
@@ -73,7 +81,12 @@ export const prefillCoreViews = async ({
|
||||
try {
|
||||
await queryRunner.startTransaction();
|
||||
|
||||
const createdViews = await createCoreViews(queryRunner, workspaceId, views);
|
||||
const createdViews = await createCoreViews(
|
||||
queryRunner,
|
||||
workspaceId,
|
||||
views,
|
||||
twentyStandardFlatApplication,
|
||||
);
|
||||
|
||||
await prefillWorkspaceFavorites(
|
||||
createdViews
|
||||
@@ -112,13 +125,9 @@ export const createCoreViews = async (
|
||||
queryRunner: QueryRunner,
|
||||
workspaceId: string,
|
||||
viewDefinitions: ViewDefinition[],
|
||||
twentyStandardFlatApplication: FlatApplication,
|
||||
): Promise<ViewEntity[]> => {
|
||||
const viewDefinitionsWithId = viewDefinitions.map((viewDefinition) => ({
|
||||
...viewDefinition,
|
||||
id: v4(),
|
||||
}));
|
||||
|
||||
const coreViews: Partial<ViewEntity>[] = viewDefinitionsWithId.map(
|
||||
const coreViews: Partial<ViewEntity>[] = viewDefinitions.map(
|
||||
({
|
||||
id,
|
||||
name,
|
||||
@@ -131,6 +140,8 @@ export const createCoreViews = async (
|
||||
openRecordIn,
|
||||
kanbanAggregateOperation,
|
||||
kanbanAggregateOperationFieldMetadataId,
|
||||
applicationId,
|
||||
universalIdentifier,
|
||||
}) => ({
|
||||
id,
|
||||
name: isString(name) ? name : name.message || '',
|
||||
@@ -150,13 +161,15 @@ export const createCoreViews = async (
|
||||
workspaceId,
|
||||
anyFieldFilterValue: null,
|
||||
visibility: ViewVisibility.WORKSPACE,
|
||||
applicationId,
|
||||
universalIdentifier,
|
||||
}),
|
||||
);
|
||||
|
||||
const viewRepository = queryRunner.manager.getRepository(ViewEntity);
|
||||
const createdViews = await viewRepository.save(coreViews);
|
||||
|
||||
for (const viewDefinition of viewDefinitionsWithId) {
|
||||
for (const viewDefinition of viewDefinitions) {
|
||||
if (viewDefinition.fields && viewDefinition.fields.length > 0) {
|
||||
const coreViewFields: Partial<ViewFieldEntity>[] =
|
||||
viewDefinition.fields.map((field) => ({
|
||||
@@ -166,6 +179,8 @@ export const createCoreViews = async (
|
||||
size: field.size,
|
||||
viewId: viewDefinition.id,
|
||||
workspaceId,
|
||||
applicationId: twentyStandardFlatApplication.id,
|
||||
universalIdentifier: field.universalIdentifier,
|
||||
}));
|
||||
|
||||
const viewFieldRepository =
|
||||
@@ -182,6 +197,8 @@ export const createCoreViews = async (
|
||||
operand: filter.operand,
|
||||
value: filter.value,
|
||||
workspaceId,
|
||||
applicationId: twentyStandardFlatApplication.id,
|
||||
universalIdentifier: filter.universalIdentifier,
|
||||
}));
|
||||
|
||||
const viewFilterRepository =
|
||||
@@ -203,6 +220,8 @@ export const createCoreViews = async (
|
||||
position: group.position,
|
||||
viewId: viewDefinition.id,
|
||||
workspaceId,
|
||||
applicationId: twentyStandardFlatApplication.id,
|
||||
universalIdentifier: group.universalIdentifier,
|
||||
}));
|
||||
|
||||
const viewGroupRepository =
|
||||
|
||||
+7
@@ -11,13 +11,18 @@ export interface ViewDefinition {
|
||||
type: string;
|
||||
key: string | null;
|
||||
position: number;
|
||||
applicationId: string;
|
||||
universalIdentifier: string;
|
||||
icon?: string;
|
||||
isCustom?: boolean;
|
||||
openRecordIn?: ViewOpenRecordInType;
|
||||
kanbanFieldMetadataId?: string;
|
||||
kanbanAggregateOperation?: AggregateOperations;
|
||||
kanbanAggregateOperationFieldMetadataId?: string;
|
||||
calendarFieldMetadataId?: string;
|
||||
calendarLayout?: string;
|
||||
fields?: {
|
||||
universalIdentifier: string;
|
||||
fieldMetadataId: string;
|
||||
position: number;
|
||||
isVisible: boolean;
|
||||
@@ -25,12 +30,14 @@ export interface ViewDefinition {
|
||||
aggregateOperation?: AggregateOperations;
|
||||
}[];
|
||||
filters?: {
|
||||
universalIdentifier: string;
|
||||
fieldMetadataId: string;
|
||||
displayValue: string;
|
||||
operand: ViewFilterOperand;
|
||||
value: string;
|
||||
}[];
|
||||
groups?: {
|
||||
universalIdentifier: string;
|
||||
fieldMetadataId: string;
|
||||
isVisible: boolean;
|
||||
fieldValue: string;
|
||||
|
||||
+43
-4
@@ -1,17 +1,26 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { STANDARD_OBJECTS } from 'src/engine/core-modules/application/constants/standard-object.constant';
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface';
|
||||
import { DEFAULT_VIEW_FIELD_SIZE } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/constants/DEFAULT_VIEW_FIELD_SIZE';
|
||||
import {
|
||||
BASE_OBJECT_STANDARD_FIELD_IDS,
|
||||
CALENDAR_EVENT_STANDARD_FIELD_IDS,
|
||||
} from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
|
||||
|
||||
export const calendarEventsAllView = (
|
||||
objectMetadataItems: ObjectMetadataEntity[],
|
||||
useCoreNaming = false,
|
||||
) => {
|
||||
export const calendarEventsAllView = ({
|
||||
objectMetadataItems,
|
||||
twentyStandardFlatApplication,
|
||||
useCoreNaming,
|
||||
}: {
|
||||
objectMetadataItems: ObjectMetadataEntity[];
|
||||
useCoreNaming?: boolean;
|
||||
twentyStandardFlatApplication: FlatApplication;
|
||||
}): ViewDefinition => {
|
||||
const calendarEventObjectMetadata = objectMetadataItems.find(
|
||||
(object) => object.standardId === STANDARD_OBJECT_IDS.calendarEvent,
|
||||
);
|
||||
@@ -20,7 +29,13 @@ export const calendarEventsAllView = (
|
||||
throw new Error('CalendarEvent object metadata not found');
|
||||
}
|
||||
|
||||
const viewUniversalIdentifier =
|
||||
STANDARD_OBJECTS.calendarEvent.views.allCalendarEvents.universalIdentifier;
|
||||
|
||||
return {
|
||||
id: v4(),
|
||||
universalIdentifier: viewUniversalIdentifier,
|
||||
applicationId: twentyStandardFlatApplication.id,
|
||||
name: useCoreNaming ? msg`All {objectLabelPlural}` : 'All Calendar Events',
|
||||
objectMetadataId: calendarEventObjectMetadata.id ?? '',
|
||||
type: 'calendar',
|
||||
@@ -45,6 +60,9 @@ export const calendarEventsAllView = (
|
||||
position: 0,
|
||||
isVisible: true,
|
||||
size: DEFAULT_VIEW_FIELD_SIZE,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.calendarEvent.views.allCalendarEvents.viewFields
|
||||
.title.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -55,6 +73,9 @@ export const calendarEventsAllView = (
|
||||
position: 1,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.calendarEvent.views.allCalendarEvents.viewFields
|
||||
.startsAt.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -65,6 +86,9 @@ export const calendarEventsAllView = (
|
||||
position: 2,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.calendarEvent.views.allCalendarEvents.viewFields
|
||||
.endsAt.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -75,6 +99,9 @@ export const calendarEventsAllView = (
|
||||
position: 3,
|
||||
isVisible: true,
|
||||
size: 100,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.calendarEvent.views.allCalendarEvents.viewFields
|
||||
.isFullDay.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -85,6 +112,9 @@ export const calendarEventsAllView = (
|
||||
position: 4,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.calendarEvent.views.allCalendarEvents.viewFields
|
||||
.location.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -96,6 +126,9 @@ export const calendarEventsAllView = (
|
||||
position: 5,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.calendarEvent.views.allCalendarEvents.viewFields
|
||||
.conferenceLink.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -106,6 +139,9 @@ export const calendarEventsAllView = (
|
||||
position: 6,
|
||||
isVisible: true,
|
||||
size: 100,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.calendarEvent.views.allCalendarEvents.viewFields
|
||||
.isCanceled.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -116,6 +152,9 @@ export const calendarEventsAllView = (
|
||||
position: 7,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.calendarEvent.views.allCalendarEvents.viewFields
|
||||
.createdAt.universalIdentifier,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
+42
-3
@@ -1,18 +1,27 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { AggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/aggregate-operations.constant';
|
||||
import { STANDARD_OBJECTS } from 'src/engine/core-modules/application/constants/standard-object.constant';
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface';
|
||||
import { DEFAULT_VIEW_FIELD_SIZE } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/constants/DEFAULT_VIEW_FIELD_SIZE';
|
||||
import {
|
||||
BASE_OBJECT_STANDARD_FIELD_IDS,
|
||||
COMPANY_STANDARD_FIELD_IDS,
|
||||
} from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
|
||||
|
||||
export const companiesAllView = (
|
||||
objectMetadataItems: ObjectMetadataEntity[],
|
||||
export const companiesAllView = ({
|
||||
objectMetadataItems,
|
||||
useCoreNaming = false,
|
||||
) => {
|
||||
twentyStandardFlatApplication,
|
||||
}: {
|
||||
objectMetadataItems: ObjectMetadataEntity[];
|
||||
useCoreNaming?: boolean;
|
||||
twentyStandardFlatApplication: FlatApplication;
|
||||
}): ViewDefinition => {
|
||||
const companyObjectMetadata = objectMetadataItems.find(
|
||||
(object) => object.standardId === STANDARD_OBJECT_IDS.company,
|
||||
);
|
||||
@@ -21,7 +30,13 @@ export const companiesAllView = (
|
||||
throw new Error('Company object metadata not found');
|
||||
}
|
||||
|
||||
const viewUniversalIdentifier =
|
||||
STANDARD_OBJECTS.company.views.allCompanies.universalIdentifier;
|
||||
|
||||
return {
|
||||
id: v4(),
|
||||
universalIdentifier: viewUniversalIdentifier,
|
||||
applicationId: twentyStandardFlatApplication.id,
|
||||
name: useCoreNaming ? msg`All {objectLabelPlural}` : 'All Companies',
|
||||
objectMetadataId: companyObjectMetadata.id ?? '',
|
||||
type: 'table',
|
||||
@@ -39,6 +54,9 @@ export const companiesAllView = (
|
||||
position: 0,
|
||||
isVisible: true,
|
||||
size: DEFAULT_VIEW_FIELD_SIZE,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.company.views.allCompanies.viewFields.name
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -50,6 +68,9 @@ export const companiesAllView = (
|
||||
isVisible: true,
|
||||
size: 100,
|
||||
aggregateOperation: AggregateOperations.COUNT,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.company.views.allCompanies.viewFields.domainName
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -60,6 +81,9 @@ export const companiesAllView = (
|
||||
position: 2,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.company.views.allCompanies.viewFields.createdBy
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -70,6 +94,9 @@ export const companiesAllView = (
|
||||
position: 3,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.company.views.allCompanies.viewFields.accountOwner
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -80,6 +107,9 @@ export const companiesAllView = (
|
||||
position: 4,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.company.views.allCompanies.viewFields.createdAt
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -91,6 +121,9 @@ export const companiesAllView = (
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
aggregateOperation: AggregateOperations.MAX,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.company.views.allCompanies.viewFields.employees
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -102,6 +135,9 @@ export const companiesAllView = (
|
||||
isVisible: true,
|
||||
size: 170,
|
||||
aggregateOperation: AggregateOperations.PERCENTAGE_EMPTY,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.company.views.allCompanies.viewFields.linkedinLink
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -112,6 +148,9 @@ export const companiesAllView = (
|
||||
isVisible: true,
|
||||
size: 170,
|
||||
aggregateOperation: AggregateOperations.COUNT_NOT_EMPTY,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.company.views.allCompanies.viewFields.address
|
||||
.universalIdentifier,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
-53
@@ -1,53 +0,0 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
|
||||
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { DEFAULT_VIEW_FIELD_SIZE } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/constants/DEFAULT_VIEW_FIELD_SIZE';
|
||||
|
||||
export const customAllView = (
|
||||
objectMetadataItem: ObjectMetadataEntity,
|
||||
useCoreNaming = false,
|
||||
) => {
|
||||
const nameField = objectMetadataItem.fields.find(
|
||||
(field) => field.name === 'name',
|
||||
);
|
||||
|
||||
const otherFields = objectMetadataItem.fields.filter(
|
||||
(field) => field.name !== 'name',
|
||||
);
|
||||
|
||||
if (!nameField) {
|
||||
throw new Error(
|
||||
`Name field not found while creating All ${objectMetadataItem.namePlural} view`,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
name: useCoreNaming
|
||||
? msg`All {objectLabelPlural}`
|
||||
: `All ${objectMetadataItem.labelPlural}`,
|
||||
objectMetadataId: objectMetadataItem.id,
|
||||
type: 'table',
|
||||
key: 'INDEX',
|
||||
position: 0,
|
||||
icon: 'IconList',
|
||||
isCustom: false,
|
||||
kanbanFieldMetadataId: '',
|
||||
filters: [],
|
||||
fields: [
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataItem.fields.find((field) => field.name === 'name')
|
||||
?.id ?? '',
|
||||
position: 0,
|
||||
isVisible: true,
|
||||
size: DEFAULT_VIEW_FIELD_SIZE,
|
||||
},
|
||||
...otherFields.map((field, index) => ({
|
||||
fieldMetadataId: field.id,
|
||||
position: index + 1,
|
||||
isVisible: true,
|
||||
size: DEFAULT_VIEW_FIELD_SIZE,
|
||||
})),
|
||||
],
|
||||
};
|
||||
};
|
||||
+30
-3
@@ -1,17 +1,26 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { STANDARD_OBJECTS } from 'src/engine/core-modules/application/constants/standard-object.constant';
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { ViewOpenRecordInType } from 'src/engine/metadata-modules/view/types/view-open-record-in-type.type';
|
||||
import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface';
|
||||
import {
|
||||
BASE_OBJECT_STANDARD_FIELD_IDS,
|
||||
DASHBOARD_STANDARD_FIELD_IDS,
|
||||
} from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
|
||||
|
||||
export const dashboardsAllView = (
|
||||
objectMetadataItems: ObjectMetadataEntity[],
|
||||
export const dashboardsAllView = ({
|
||||
objectMetadataItems,
|
||||
useCoreNaming = false,
|
||||
) => {
|
||||
twentyStandardFlatApplication,
|
||||
}: {
|
||||
objectMetadataItems: ObjectMetadataEntity[];
|
||||
useCoreNaming?: boolean;
|
||||
twentyStandardFlatApplication: FlatApplication;
|
||||
}): ViewDefinition => {
|
||||
const dashboardObjectMetadata = objectMetadataItems.find(
|
||||
(object) => object.standardId === STANDARD_OBJECT_IDS.dashboard,
|
||||
);
|
||||
@@ -20,7 +29,13 @@ export const dashboardsAllView = (
|
||||
throw new Error('Dashboard object metadata not found');
|
||||
}
|
||||
|
||||
const viewUniversalIdentifier =
|
||||
STANDARD_OBJECTS.dashboard.views.allDashboards.universalIdentifier;
|
||||
|
||||
return {
|
||||
id: v4(),
|
||||
universalIdentifier: viewUniversalIdentifier,
|
||||
applicationId: twentyStandardFlatApplication.id,
|
||||
name: useCoreNaming ? msg`All {objectLabelPlural}` : 'All Dashboards',
|
||||
objectMetadataId: dashboardObjectMetadata.id ?? '',
|
||||
type: 'table',
|
||||
@@ -39,6 +54,9 @@ export const dashboardsAllView = (
|
||||
position: 0,
|
||||
isVisible: true,
|
||||
size: 200,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.dashboard.views.allDashboards.viewFields.title
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -49,6 +67,9 @@ export const dashboardsAllView = (
|
||||
position: 1,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.dashboard.views.allDashboards.viewFields.createdBy
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -59,6 +80,9 @@ export const dashboardsAllView = (
|
||||
position: 2,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.dashboard.views.allDashboards.viewFields.createdAt
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -69,6 +93,9 @@ export const dashboardsAllView = (
|
||||
position: 3,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.dashboard.views.allDashboards.viewFields.updatedAt
|
||||
.universalIdentifier,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
+25
-4
@@ -1,17 +1,26 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { STANDARD_OBJECTS } from 'src/engine/core-modules/application/constants/standard-object.constant';
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface';
|
||||
import { DEFAULT_VIEW_FIELD_SIZE } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/constants/DEFAULT_VIEW_FIELD_SIZE';
|
||||
import {
|
||||
BASE_OBJECT_STANDARD_FIELD_IDS,
|
||||
MESSAGE_THREAD_STANDARD_FIELD_IDS,
|
||||
} from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
|
||||
|
||||
export const messageThreadsAllView = (
|
||||
objectMetadataItems: ObjectMetadataEntity[],
|
||||
useCoreNaming = false,
|
||||
) => {
|
||||
export const messageThreadsAllView = ({
|
||||
objectMetadataItems,
|
||||
twentyStandardFlatApplication,
|
||||
useCoreNaming,
|
||||
}: {
|
||||
objectMetadataItems: ObjectMetadataEntity[];
|
||||
useCoreNaming?: boolean;
|
||||
twentyStandardFlatApplication: FlatApplication;
|
||||
}): ViewDefinition => {
|
||||
const messageThreadObjectMetadata = objectMetadataItems.find(
|
||||
(object) => object.standardId === STANDARD_OBJECT_IDS.messageThread,
|
||||
);
|
||||
@@ -20,7 +29,13 @@ export const messageThreadsAllView = (
|
||||
throw new Error('MessageThread object metadata not found');
|
||||
}
|
||||
|
||||
const viewUniversalIdentifier =
|
||||
STANDARD_OBJECTS.messageThread.views.allMessageThreads.universalIdentifier;
|
||||
|
||||
return {
|
||||
id: v4(),
|
||||
universalIdentifier: viewUniversalIdentifier,
|
||||
applicationId: twentyStandardFlatApplication.id,
|
||||
name: useCoreNaming ? msg`All {objectLabelPlural}` : 'All Message Threads',
|
||||
objectMetadataId: messageThreadObjectMetadata.id ?? '',
|
||||
type: 'table',
|
||||
@@ -39,6 +54,9 @@ export const messageThreadsAllView = (
|
||||
position: 0,
|
||||
isVisible: true,
|
||||
size: DEFAULT_VIEW_FIELD_SIZE,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.messageThread.views.allMessageThreads.viewFields
|
||||
.messages.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -49,6 +67,9 @@ export const messageThreadsAllView = (
|
||||
position: 1,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.messageThread.views.allMessageThreads.viewFields
|
||||
.createdAt.universalIdentifier,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
+40
-4
@@ -1,17 +1,26 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { STANDARD_OBJECTS } from 'src/engine/core-modules/application/constants/standard-object.constant';
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface';
|
||||
import { DEFAULT_VIEW_FIELD_SIZE } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/constants/DEFAULT_VIEW_FIELD_SIZE';
|
||||
import {
|
||||
BASE_OBJECT_STANDARD_FIELD_IDS,
|
||||
MESSAGE_STANDARD_FIELD_IDS,
|
||||
} from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
|
||||
|
||||
export const messagesAllView = (
|
||||
objectMetadataItems: ObjectMetadataEntity[],
|
||||
useCoreNaming = false,
|
||||
) => {
|
||||
export const messagesAllView = ({
|
||||
objectMetadataItems,
|
||||
twentyStandardFlatApplication,
|
||||
useCoreNaming,
|
||||
}: {
|
||||
objectMetadataItems: ObjectMetadataEntity[];
|
||||
useCoreNaming?: boolean;
|
||||
twentyStandardFlatApplication: FlatApplication;
|
||||
}): ViewDefinition => {
|
||||
const messageObjectMetadata = objectMetadataItems.find(
|
||||
(object) => object.standardId === STANDARD_OBJECT_IDS.message,
|
||||
);
|
||||
@@ -20,7 +29,13 @@ export const messagesAllView = (
|
||||
throw new Error('Message object metadata not found');
|
||||
}
|
||||
|
||||
const viewUniversalIdentifier =
|
||||
STANDARD_OBJECTS.message.views.allMessages.universalIdentifier;
|
||||
|
||||
return {
|
||||
id: v4(),
|
||||
universalIdentifier: viewUniversalIdentifier,
|
||||
applicationId: twentyStandardFlatApplication.id,
|
||||
name: useCoreNaming ? msg`All {objectLabelPlural}` : 'All Messages',
|
||||
objectMetadataId: messageObjectMetadata.id ?? '',
|
||||
type: 'table',
|
||||
@@ -38,6 +53,9 @@ export const messagesAllView = (
|
||||
position: 0,
|
||||
isVisible: true,
|
||||
size: DEFAULT_VIEW_FIELD_SIZE,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.message.views.allMessages.viewFields.subject
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -48,6 +66,9 @@ export const messagesAllView = (
|
||||
position: 1,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.message.views.allMessages.viewFields.messageThread
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -59,6 +80,9 @@ export const messagesAllView = (
|
||||
position: 2,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.message.views.allMessages.viewFields
|
||||
.messageParticipants.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -69,6 +93,9 @@ export const messagesAllView = (
|
||||
position: 3,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.message.views.allMessages.viewFields.receivedAt
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -79,6 +106,9 @@ export const messagesAllView = (
|
||||
position: 4,
|
||||
isVisible: true,
|
||||
size: 180,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.message.views.allMessages.viewFields.headerMessageId
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -88,6 +118,9 @@ export const messagesAllView = (
|
||||
position: 5,
|
||||
isVisible: true,
|
||||
size: 200,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.message.views.allMessages.viewFields.text
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -98,6 +131,9 @@ export const messagesAllView = (
|
||||
position: 6,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.message.views.allMessages.viewFields.createdAt
|
||||
.universalIdentifier,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
+35
-7
@@ -1,16 +1,25 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { STANDARD_OBJECTS } from 'src/engine/core-modules/application/constants/standard-object.constant';
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface';
|
||||
import {
|
||||
BASE_OBJECT_STANDARD_FIELD_IDS,
|
||||
NOTE_STANDARD_FIELD_IDS,
|
||||
} from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
|
||||
|
||||
export const notesAllView = (
|
||||
objectMetadataItems: ObjectMetadataEntity[],
|
||||
export const notesAllView = ({
|
||||
objectMetadataItems,
|
||||
useCoreNaming = false,
|
||||
) => {
|
||||
twentyStandardFlatApplication,
|
||||
}: {
|
||||
objectMetadataItems: ObjectMetadataEntity[];
|
||||
useCoreNaming?: boolean;
|
||||
twentyStandardFlatApplication: FlatApplication;
|
||||
}): ViewDefinition => {
|
||||
const noteObjectMetadata = objectMetadataItems.find(
|
||||
(object) => object.standardId === STANDARD_OBJECT_IDS.note,
|
||||
);
|
||||
@@ -19,7 +28,13 @@ export const notesAllView = (
|
||||
throw new Error('Note object metadata not found');
|
||||
}
|
||||
|
||||
const viewUniversalIdentifier =
|
||||
STANDARD_OBJECTS.note.views.allNotes.universalIdentifier;
|
||||
|
||||
return {
|
||||
id: v4(),
|
||||
universalIdentifier: viewUniversalIdentifier,
|
||||
applicationId: twentyStandardFlatApplication.id,
|
||||
name: useCoreNaming ? msg`All {objectLabelPlural}` : 'All Notes',
|
||||
objectMetadataId: noteObjectMetadata.id,
|
||||
type: 'table',
|
||||
@@ -37,6 +52,9 @@ export const notesAllView = (
|
||||
position: 0,
|
||||
isVisible: true,
|
||||
size: 210,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.note.views.allNotes.viewFields.title
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -46,6 +64,9 @@ export const notesAllView = (
|
||||
position: 1,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.note.views.allNotes.viewFields.noteTargets
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -55,6 +76,9 @@ export const notesAllView = (
|
||||
position: 2,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.note.views.allNotes.viewFields.bodyV2
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -64,6 +88,9 @@ export const notesAllView = (
|
||||
position: 3,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.note.views.allNotes.viewFields.createdBy
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -74,18 +101,19 @@ export const notesAllView = (
|
||||
position: 4,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.note.views.allNotes.viewFields.createdAt
|
||||
.universalIdentifier,
|
||||
},
|
||||
/*
|
||||
TODO: Add later, since we don't have real-time it probably doesn't work well?
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataMap[STANDARD_OBJECT_IDS.note].fields[
|
||||
BASE_OBJECT_STANDARD_FIELD_IDS.updatedAt
|
||||
objectMetadataMap[STANDARD_OBJECT_IDS.note].fields[.updatedAt
|
||||
],
|
||||
position: 0,
|
||||
isVisible: true,
|
||||
size: 210,
|
||||
},
|
||||
size: 210},
|
||||
*/
|
||||
],
|
||||
};
|
||||
|
||||
+36
-3
@@ -1,14 +1,23 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { AggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/aggregate-operations.constant';
|
||||
import { STANDARD_OBJECTS } from 'src/engine/core-modules/application/constants/standard-object.constant';
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface';
|
||||
import { OPPORTUNITY_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
|
||||
|
||||
export const opportunitiesAllView = (
|
||||
objectMetadataItems: ObjectMetadataEntity[],
|
||||
export const opportunitiesAllView = ({
|
||||
objectMetadataItems,
|
||||
useCoreNaming = false,
|
||||
) => {
|
||||
twentyStandardFlatApplication,
|
||||
}: {
|
||||
objectMetadataItems: ObjectMetadataEntity[];
|
||||
useCoreNaming?: boolean;
|
||||
twentyStandardFlatApplication: FlatApplication;
|
||||
}): ViewDefinition => {
|
||||
const opportunityObjectMetadata = objectMetadataItems.find(
|
||||
(object) => object.standardId === STANDARD_OBJECT_IDS.opportunity,
|
||||
);
|
||||
@@ -17,7 +26,13 @@ export const opportunitiesAllView = (
|
||||
throw new Error('Opportunity object metadata not found');
|
||||
}
|
||||
|
||||
const viewUniversalIdentifier =
|
||||
STANDARD_OBJECTS.opportunity.views.allOpportunities.universalIdentifier;
|
||||
|
||||
return {
|
||||
id: v4(),
|
||||
universalIdentifier: viewUniversalIdentifier,
|
||||
applicationId: twentyStandardFlatApplication.id,
|
||||
name: useCoreNaming ? msg`All {objectLabelPlural}` : 'All Opportunities',
|
||||
objectMetadataId: opportunityObjectMetadata.id,
|
||||
type: 'table',
|
||||
@@ -35,6 +50,9 @@ export const opportunitiesAllView = (
|
||||
position: 0,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.opportunity.views.allOpportunities.viewFields.name
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -46,6 +64,9 @@ export const opportunitiesAllView = (
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
aggregateOperation: AggregateOperations.AVG,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.opportunity.views.allOpportunities.viewFields.amount
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -56,6 +77,9 @@ export const opportunitiesAllView = (
|
||||
position: 2,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.opportunity.views.allOpportunities.viewFields
|
||||
.createdBy.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -67,6 +91,9 @@ export const opportunitiesAllView = (
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
aggregateOperation: AggregateOperations.MIN,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.opportunity.views.allOpportunities.viewFields
|
||||
.closeDate.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -77,6 +104,9 @@ export const opportunitiesAllView = (
|
||||
position: 4,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.opportunity.views.allOpportunities.viewFields.company
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -88,6 +118,9 @@ export const opportunitiesAllView = (
|
||||
position: 5,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.opportunity.views.allOpportunities.viewFields
|
||||
.pointOfContact.universalIdentifier,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
+51
-3
@@ -1,14 +1,23 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { AggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/aggregate-operations.constant';
|
||||
import { STANDARD_OBJECTS } from 'src/engine/core-modules/application/constants/standard-object.constant';
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface';
|
||||
import { OPPORTUNITY_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
|
||||
|
||||
export const opportunitiesByStageView = (
|
||||
objectMetadataItems: ObjectMetadataEntity[],
|
||||
export const opportunitiesByStageView = ({
|
||||
objectMetadataItems,
|
||||
useCoreNaming = false,
|
||||
) => {
|
||||
twentyStandardFlatApplication,
|
||||
}: {
|
||||
objectMetadataItems: ObjectMetadataEntity[];
|
||||
useCoreNaming?: boolean;
|
||||
twentyStandardFlatApplication: FlatApplication;
|
||||
}): ViewDefinition => {
|
||||
const opportunityObjectMetadata = objectMetadataItems.find(
|
||||
(object) => object.standardId === STANDARD_OBJECT_IDS.opportunity,
|
||||
);
|
||||
@@ -17,7 +26,13 @@ export const opportunitiesByStageView = (
|
||||
throw new Error('Opportunity object metadata not found');
|
||||
}
|
||||
|
||||
const viewUniversalIdentifier =
|
||||
STANDARD_OBJECTS.opportunity.views.byStage.universalIdentifier;
|
||||
|
||||
return {
|
||||
id: v4(),
|
||||
universalIdentifier: viewUniversalIdentifier,
|
||||
applicationId: twentyStandardFlatApplication.id,
|
||||
name: useCoreNaming ? msg`By Stage` : 'By Stage',
|
||||
objectMetadataId: opportunityObjectMetadata.id,
|
||||
type: 'kanban',
|
||||
@@ -43,6 +58,9 @@ export const opportunitiesByStageView = (
|
||||
position: 0,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.opportunity.views.byStage.viewFields.name
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -53,6 +71,9 @@ export const opportunitiesByStageView = (
|
||||
position: 1,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.opportunity.views.byStage.viewFields.amount
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -63,6 +84,9 @@ export const opportunitiesByStageView = (
|
||||
position: 2,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.opportunity.views.byStage.viewFields.createdBy
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -73,6 +97,9 @@ export const opportunitiesByStageView = (
|
||||
position: 3,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.opportunity.views.byStage.viewFields.closeDate
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -83,6 +110,9 @@ export const opportunitiesByStageView = (
|
||||
position: 4,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.opportunity.views.byStage.viewFields.company
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -94,6 +124,9 @@ export const opportunitiesByStageView = (
|
||||
position: 5,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.opportunity.views.byStage.viewFields.pointOfContact
|
||||
.universalIdentifier,
|
||||
},
|
||||
],
|
||||
groups: [
|
||||
@@ -106,6 +139,9 @@ export const opportunitiesByStageView = (
|
||||
isVisible: true,
|
||||
fieldValue: 'NEW',
|
||||
position: 0,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.opportunity.views.byStage.viewGroups!.new
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -116,6 +152,9 @@ export const opportunitiesByStageView = (
|
||||
isVisible: true,
|
||||
fieldValue: 'SCREENING',
|
||||
position: 1,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.opportunity.views.byStage.viewGroups!.screening
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -126,6 +165,9 @@ export const opportunitiesByStageView = (
|
||||
isVisible: true,
|
||||
fieldValue: 'MEETING',
|
||||
position: 2,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.opportunity.views.byStage.viewGroups!.meeting
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -136,6 +178,9 @@ export const opportunitiesByStageView = (
|
||||
isVisible: true,
|
||||
fieldValue: 'PROPOSAL',
|
||||
position: 3,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.opportunity.views.byStage.viewGroups!.proposal
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -146,6 +191,9 @@ export const opportunitiesByStageView = (
|
||||
isVisible: true,
|
||||
fieldValue: 'CUSTOMER',
|
||||
position: 4,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.opportunity.views.byStage.viewGroups!.customer
|
||||
.universalIdentifier,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
-150
@@ -1,150 +0,0 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
|
||||
|
||||
import { AggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/aggregate-operations.constant';
|
||||
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { OPPORTUNITY_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
|
||||
|
||||
export const opportunitiesTableByStageView = (
|
||||
objectMetadataItems: ObjectMetadataEntity[],
|
||||
useCoreNaming = false,
|
||||
) => {
|
||||
const opportunityObjectMetadata = objectMetadataItems.find(
|
||||
(object) => object.standardId === STANDARD_OBJECT_IDS.opportunity,
|
||||
);
|
||||
|
||||
if (!opportunityObjectMetadata) {
|
||||
throw new Error('Opportunity object metadata not found');
|
||||
}
|
||||
|
||||
return {
|
||||
name: useCoreNaming ? msg`By Stage` : 'By Stage',
|
||||
objectMetadataId: opportunityObjectMetadata.id,
|
||||
type: 'table',
|
||||
key: null,
|
||||
position: 1,
|
||||
icon: 'IconList',
|
||||
kanbanFieldMetadataId:
|
||||
opportunityObjectMetadata.fields.find(
|
||||
(field) => field.standardId === OPPORTUNITY_STANDARD_FIELD_IDS.stage,
|
||||
)?.id ?? '',
|
||||
filters: [],
|
||||
fields: [
|
||||
{
|
||||
fieldMetadataId:
|
||||
opportunityObjectMetadata.fields.find(
|
||||
(field) => field.standardId === OPPORTUNITY_STANDARD_FIELD_IDS.name,
|
||||
)?.id ?? '',
|
||||
position: 0,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
opportunityObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === OPPORTUNITY_STANDARD_FIELD_IDS.amount,
|
||||
)?.id ?? '',
|
||||
position: 1,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
aggregateOperation: AggregateOperations.AVG,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
opportunityObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === OPPORTUNITY_STANDARD_FIELD_IDS.createdBy,
|
||||
)?.id ?? '',
|
||||
position: 2,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
opportunityObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === OPPORTUNITY_STANDARD_FIELD_IDS.closeDate,
|
||||
)?.id ?? '',
|
||||
position: 3,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
aggregateOperation: AggregateOperations.MAX,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
opportunityObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === OPPORTUNITY_STANDARD_FIELD_IDS.company,
|
||||
)?.id ?? '',
|
||||
position: 4,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
aggregateOperation: AggregateOperations.COUNT,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
opportunityObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId ===
|
||||
OPPORTUNITY_STANDARD_FIELD_IDS.pointOfContact,
|
||||
)?.id ?? '',
|
||||
position: 5,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
],
|
||||
groups: [
|
||||
{
|
||||
fieldMetadataId:
|
||||
opportunityObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === OPPORTUNITY_STANDARD_FIELD_IDS.stage,
|
||||
)?.id ?? '',
|
||||
isVisible: true,
|
||||
fieldValue: 'NEW',
|
||||
position: 0,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
opportunityObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === OPPORTUNITY_STANDARD_FIELD_IDS.stage,
|
||||
)?.id ?? '',
|
||||
isVisible: true,
|
||||
fieldValue: 'SCREENING',
|
||||
position: 1,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
opportunityObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === OPPORTUNITY_STANDARD_FIELD_IDS.stage,
|
||||
)?.id ?? '',
|
||||
isVisible: true,
|
||||
fieldValue: 'MEETING',
|
||||
position: 2,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
opportunityObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === OPPORTUNITY_STANDARD_FIELD_IDS.stage,
|
||||
)?.id ?? '',
|
||||
isVisible: true,
|
||||
fieldValue: 'PROPOSAL',
|
||||
position: 3,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
opportunityObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === OPPORTUNITY_STANDARD_FIELD_IDS.stage,
|
||||
)?.id ?? '',
|
||||
isVisible: true,
|
||||
fieldValue: 'CUSTOMER',
|
||||
position: 4,
|
||||
},
|
||||
],
|
||||
};
|
||||
};
|
||||
+48
-3
@@ -1,17 +1,26 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { AggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/aggregate-operations.constant';
|
||||
import { STANDARD_OBJECTS } from 'src/engine/core-modules/application/constants/standard-object.constant';
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface';
|
||||
import {
|
||||
BASE_OBJECT_STANDARD_FIELD_IDS,
|
||||
PERSON_STANDARD_FIELD_IDS,
|
||||
} from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
|
||||
|
||||
export const peopleAllView = (
|
||||
objectMetadataItems: ObjectMetadataEntity[],
|
||||
export const peopleAllView = ({
|
||||
objectMetadataItems,
|
||||
useCoreNaming = false,
|
||||
) => {
|
||||
twentyStandardFlatApplication,
|
||||
}: {
|
||||
objectMetadataItems: ObjectMetadataEntity[];
|
||||
useCoreNaming?: boolean;
|
||||
twentyStandardFlatApplication: FlatApplication;
|
||||
}): ViewDefinition => {
|
||||
const personObjectMetadata = objectMetadataItems.find(
|
||||
(object) => object.standardId === STANDARD_OBJECT_IDS.person,
|
||||
);
|
||||
@@ -20,7 +29,13 @@ export const peopleAllView = (
|
||||
throw new Error('Person object metadata not found');
|
||||
}
|
||||
|
||||
const viewUniversalIdentifier =
|
||||
STANDARD_OBJECTS.person.views.allPeople.universalIdentifier;
|
||||
|
||||
return {
|
||||
id: v4(),
|
||||
universalIdentifier: viewUniversalIdentifier,
|
||||
applicationId: twentyStandardFlatApplication.id,
|
||||
name: useCoreNaming ? msg`All {objectLabelPlural}` : 'All People',
|
||||
objectMetadataId: personObjectMetadata.id,
|
||||
type: 'table',
|
||||
@@ -38,6 +53,9 @@ export const peopleAllView = (
|
||||
position: 0,
|
||||
isVisible: true,
|
||||
size: 210,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.person.views.allPeople.viewFields.name
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -48,6 +66,9 @@ export const peopleAllView = (
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
aggregateOperation: AggregateOperations.COUNT_UNIQUE_VALUES,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.person.views.allPeople.viewFields.emails
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -57,6 +78,9 @@ export const peopleAllView = (
|
||||
position: 2,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.person.views.allPeople.viewFields.createdBy
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -66,6 +90,9 @@ export const peopleAllView = (
|
||||
position: 3,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.person.views.allPeople.viewFields.company
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -76,6 +103,9 @@ export const peopleAllView = (
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
aggregateOperation: AggregateOperations.PERCENTAGE_EMPTY,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.person.views.allPeople.viewFields.phones
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -87,6 +117,9 @@ export const peopleAllView = (
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
aggregateOperation: AggregateOperations.MIN,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.person.views.allPeople.viewFields.createdAt
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -96,6 +129,9 @@ export const peopleAllView = (
|
||||
position: 6,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.person.views.allPeople.viewFields.city
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -105,6 +141,9 @@ export const peopleAllView = (
|
||||
position: 7,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.person.views.allPeople.viewFields.jobTitle
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -115,6 +154,9 @@ export const peopleAllView = (
|
||||
position: 8,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.person.views.allPeople.viewFields.linkedinLink
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -124,6 +166,9 @@ export const peopleAllView = (
|
||||
position: 9,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.person.views.allPeople.viewFields.xLink
|
||||
.universalIdentifier,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
+45
-9
@@ -1,16 +1,25 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { STANDARD_OBJECTS } from 'src/engine/core-modules/application/constants/standard-object.constant';
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface';
|
||||
import {
|
||||
BASE_OBJECT_STANDARD_FIELD_IDS,
|
||||
TASK_STANDARD_FIELD_IDS,
|
||||
} from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
|
||||
|
||||
export const tasksAllView = (
|
||||
objectMetadataItems: ObjectMetadataEntity[],
|
||||
export const tasksAllView = ({
|
||||
objectMetadataItems,
|
||||
useCoreNaming = false,
|
||||
) => {
|
||||
twentyStandardFlatApplication,
|
||||
}: {
|
||||
objectMetadataItems: ObjectMetadataEntity[];
|
||||
useCoreNaming?: boolean;
|
||||
twentyStandardFlatApplication: FlatApplication;
|
||||
}): ViewDefinition => {
|
||||
const taskObjectMetadata = objectMetadataItems.find(
|
||||
(object) => object.standardId === STANDARD_OBJECT_IDS.task,
|
||||
);
|
||||
@@ -19,7 +28,13 @@ export const tasksAllView = (
|
||||
throw new Error('Task object metadata not found');
|
||||
}
|
||||
|
||||
const viewUniversalIdentifier =
|
||||
STANDARD_OBJECTS.task.views.allTasks.universalIdentifier;
|
||||
|
||||
return {
|
||||
id: v4(),
|
||||
universalIdentifier: viewUniversalIdentifier,
|
||||
applicationId: twentyStandardFlatApplication.id,
|
||||
name: useCoreNaming ? msg`All {objectLabelPlural}` : 'All Tasks',
|
||||
objectMetadataId: taskObjectMetadata.id,
|
||||
type: 'table',
|
||||
@@ -35,8 +50,7 @@ export const tasksAllView = (
|
||||
],
|
||||
displayValue: 'Task',
|
||||
operand: 'is',
|
||||
value: '["TASK"]',
|
||||
},
|
||||
value: '["TASK"]'},
|
||||
],*/,
|
||||
fields: [
|
||||
{
|
||||
@@ -47,6 +61,9 @@ export const tasksAllView = (
|
||||
position: 0,
|
||||
isVisible: true,
|
||||
size: 210,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.task.views.allTasks.viewFields.title
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -56,6 +73,9 @@ export const tasksAllView = (
|
||||
position: 2,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.task.views.allTasks.viewFields.status
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -65,6 +85,9 @@ export const tasksAllView = (
|
||||
position: 3,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.task.views.allTasks.viewFields.taskTargets
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -74,6 +97,9 @@ export const tasksAllView = (
|
||||
position: 4,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.task.views.allTasks.viewFields.createdBy
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -83,6 +109,9 @@ export const tasksAllView = (
|
||||
position: 5,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.task.views.allTasks.viewFields.dueAt
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -92,6 +121,9 @@ export const tasksAllView = (
|
||||
position: 6,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.task.views.allTasks.viewFields.assignee
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -101,6 +133,9 @@ export const tasksAllView = (
|
||||
position: 7,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.task.views.allTasks.viewFields.bodyV2
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -111,18 +146,19 @@ export const tasksAllView = (
|
||||
position: 8,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.task.views.allTasks.viewFields.createdAt
|
||||
.universalIdentifier,
|
||||
},
|
||||
/*
|
||||
TODO: Add later, since we don't have real-time it probably doesn't work well?
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataMap[STANDARD_OBJECT_IDS.task].fields[
|
||||
BASE_OBJECT_STANDARD_FIELD_IDS.updatedAt
|
||||
objectMetadataMap[STANDARD_OBJECT_IDS.task].fields[.updatedAt
|
||||
],
|
||||
position: 0,
|
||||
isVisible: true,
|
||||
size: 210,
|
||||
},
|
||||
size: 210},
|
||||
*/
|
||||
],
|
||||
};
|
||||
|
||||
+56
-6
@@ -1,17 +1,26 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { ViewFilterOperand } from 'twenty-shared/types';
|
||||
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
|
||||
import { ViewFilterOperand } from 'twenty-shared/types';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { STANDARD_OBJECTS } from 'src/engine/core-modules/application/constants/standard-object.constant';
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface';
|
||||
import {
|
||||
BASE_OBJECT_STANDARD_FIELD_IDS,
|
||||
TASK_STANDARD_FIELD_IDS,
|
||||
} from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
|
||||
|
||||
export const tasksAssignedToMeView = (
|
||||
objectMetadataItems: ObjectMetadataEntity[],
|
||||
export const tasksAssignedToMeView = ({
|
||||
objectMetadataItems,
|
||||
useCoreNaming = false,
|
||||
) => {
|
||||
twentyStandardFlatApplication,
|
||||
}: {
|
||||
objectMetadataItems: ObjectMetadataEntity[];
|
||||
useCoreNaming?: boolean;
|
||||
twentyStandardFlatApplication: FlatApplication;
|
||||
}): ViewDefinition => {
|
||||
const taskObjectMetadata = objectMetadataItems.find(
|
||||
(object) => object.standardId === STANDARD_OBJECT_IDS.task,
|
||||
);
|
||||
@@ -20,7 +29,13 @@ export const tasksAssignedToMeView = (
|
||||
throw new Error('Task object metadata not found');
|
||||
}
|
||||
|
||||
const viewUniversalIdentifier =
|
||||
STANDARD_OBJECTS.task.views.assignedToMe.universalIdentifier;
|
||||
|
||||
return {
|
||||
id: v4(),
|
||||
universalIdentifier: viewUniversalIdentifier,
|
||||
applicationId: twentyStandardFlatApplication.id,
|
||||
name: useCoreNaming ? msg`Assigned to Me` : 'Assigned to Me',
|
||||
objectMetadataId: taskObjectMetadata.id,
|
||||
type: 'table',
|
||||
@@ -40,6 +55,9 @@ export const tasksAssignedToMeView = (
|
||||
isCurrentWorkspaceMemberSelected: true,
|
||||
selectedRecordIds: [],
|
||||
}),
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.task.views.assignedToMe.viewFilters!.assigneeIsMe
|
||||
.universalIdentifier,
|
||||
},
|
||||
],
|
||||
fields: [
|
||||
@@ -51,6 +69,9 @@ export const tasksAssignedToMeView = (
|
||||
position: 0,
|
||||
isVisible: true,
|
||||
size: 210,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.task.views.assignedToMe.viewFields.title
|
||||
.universalIdentifier,
|
||||
},
|
||||
/*{
|
||||
fieldMetadataId:
|
||||
@@ -59,8 +80,7 @@ export const tasksAssignedToMeView = (
|
||||
],
|
||||
position: 2,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},*/
|
||||
size: 150},*/
|
||||
{
|
||||
fieldMetadataId:
|
||||
taskObjectMetadata.fields.find(
|
||||
@@ -69,6 +89,9 @@ export const tasksAssignedToMeView = (
|
||||
position: 3,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.task.views.assignedToMe.viewFields.taskTargets
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -78,6 +101,9 @@ export const tasksAssignedToMeView = (
|
||||
position: 4,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.task.views.assignedToMe.viewFields.createdBy
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -87,6 +113,9 @@ export const tasksAssignedToMeView = (
|
||||
position: 5,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.task.views.assignedToMe.viewFields.dueAt
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -96,6 +125,9 @@ export const tasksAssignedToMeView = (
|
||||
position: 6,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.task.views.assignedToMe.viewFields.assignee
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -105,6 +137,9 @@ export const tasksAssignedToMeView = (
|
||||
position: 7,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.task.views.assignedToMe.viewFields.bodyV2
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -115,6 +150,9 @@ export const tasksAssignedToMeView = (
|
||||
position: 8,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.task.views.assignedToMe.viewFields.createdAt
|
||||
.universalIdentifier,
|
||||
},
|
||||
],
|
||||
groups: [
|
||||
@@ -126,6 +164,9 @@ export const tasksAssignedToMeView = (
|
||||
isVisible: true,
|
||||
fieldValue: 'TODO',
|
||||
position: 0,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.task.views.assignedToMe.viewGroups!.todo
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -135,6 +176,9 @@ export const tasksAssignedToMeView = (
|
||||
isVisible: true,
|
||||
fieldValue: 'IN_PROGRESS',
|
||||
position: 1,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.task.views.assignedToMe.viewGroups!.inProgress
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -144,6 +188,9 @@ export const tasksAssignedToMeView = (
|
||||
isVisible: true,
|
||||
fieldValue: 'DONE',
|
||||
position: 2,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.task.views.assignedToMe.viewGroups!.done
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -153,6 +200,9 @@ export const tasksAssignedToMeView = (
|
||||
isVisible: true,
|
||||
fieldValue: '',
|
||||
position: 3,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.task.views.assignedToMe.viewGroups!.empty
|
||||
.universalIdentifier,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
+45
-9
@@ -1,16 +1,25 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { STANDARD_OBJECTS } from 'src/engine/core-modules/application/constants/standard-object.constant';
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface';
|
||||
import {
|
||||
BASE_OBJECT_STANDARD_FIELD_IDS,
|
||||
TASK_STANDARD_FIELD_IDS,
|
||||
} from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
|
||||
|
||||
export const tasksByStatusView = (
|
||||
objectMetadataItems: ObjectMetadataEntity[],
|
||||
export const tasksByStatusView = ({
|
||||
objectMetadataItems,
|
||||
useCoreNaming = false,
|
||||
) => {
|
||||
twentyStandardFlatApplication,
|
||||
}: {
|
||||
objectMetadataItems: ObjectMetadataEntity[];
|
||||
useCoreNaming?: boolean;
|
||||
twentyStandardFlatApplication: FlatApplication;
|
||||
}): ViewDefinition => {
|
||||
const taskObjectMetadata = objectMetadataItems.find(
|
||||
(object) => object.standardId === STANDARD_OBJECT_IDS.task,
|
||||
);
|
||||
@@ -19,7 +28,13 @@ export const tasksByStatusView = (
|
||||
throw new Error('Task object metadata not found');
|
||||
}
|
||||
|
||||
const viewUniversalIdentifier =
|
||||
STANDARD_OBJECTS.task.views.byStatus.universalIdentifier;
|
||||
|
||||
return {
|
||||
id: v4(),
|
||||
universalIdentifier: viewUniversalIdentifier,
|
||||
applicationId: twentyStandardFlatApplication.id,
|
||||
name: useCoreNaming ? msg`By Status` : 'By Status',
|
||||
objectMetadataId: taskObjectMetadata.id,
|
||||
type: 'kanban',
|
||||
@@ -38,8 +53,7 @@ export const tasksByStatusView = (
|
||||
],
|
||||
displayValue: 'Task',
|
||||
operand: 'is',
|
||||
value: '["TASK"]',
|
||||
},
|
||||
value: '["TASK"]'},
|
||||
],*/,
|
||||
fields: [
|
||||
{
|
||||
@@ -50,6 +64,9 @@ export const tasksByStatusView = (
|
||||
position: 0,
|
||||
isVisible: true,
|
||||
size: 210,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.task.views.byStatus.viewFields.title
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -59,6 +76,9 @@ export const tasksByStatusView = (
|
||||
position: 2,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.task.views.byStatus.viewFields.status
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -68,6 +88,9 @@ export const tasksByStatusView = (
|
||||
position: 3,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.task.views.byStatus.viewFields.dueAt
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -77,6 +100,9 @@ export const tasksByStatusView = (
|
||||
position: 4,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.task.views.byStatus.viewFields.assignee
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -87,18 +113,19 @@ export const tasksByStatusView = (
|
||||
position: 6,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.task.views.byStatus.viewFields.createdAt
|
||||
.universalIdentifier,
|
||||
},
|
||||
/*
|
||||
TODO: Add later, since we don't have real-time it probably doesn't work well?
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataMap[STANDARD_OBJECT_IDS.task].fields[
|
||||
BASE_OBJECT_STANDARD_FIELD_IDS.updatedAt
|
||||
objectMetadataMap[STANDARD_OBJECT_IDS.task].fields[.updatedAt
|
||||
],
|
||||
position: 0,
|
||||
isVisible: true,
|
||||
size: 210,
|
||||
},
|
||||
size: 210},
|
||||
*/
|
||||
],
|
||||
groups: [
|
||||
@@ -110,6 +137,9 @@ export const tasksByStatusView = (
|
||||
isVisible: true,
|
||||
fieldValue: 'TODO',
|
||||
position: 0,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.task.views.byStatus.viewGroups!.todo
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -119,6 +149,9 @@ export const tasksByStatusView = (
|
||||
isVisible: true,
|
||||
fieldValue: 'IN_PROGRESS',
|
||||
position: 1,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.task.views.byStatus.viewGroups!.inProgress
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -128,6 +161,9 @@ export const tasksByStatusView = (
|
||||
isVisible: true,
|
||||
fieldValue: 'DONE',
|
||||
position: 2,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.task.views.byStatus.viewGroups!.done
|
||||
.universalIdentifier,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
+36
-3
@@ -1,14 +1,23 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { STANDARD_OBJECTS } from 'src/engine/core-modules/application/constants/standard-object.constant';
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { ViewOpenRecordInType } from 'src/engine/metadata-modules/view/types/view-open-record-in-type.type';
|
||||
import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface';
|
||||
import { WORKFLOW_RUN_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
|
||||
|
||||
export const workflowRunsAllView = (
|
||||
objectMetadataItems: ObjectMetadataEntity[],
|
||||
export const workflowRunsAllView = ({
|
||||
objectMetadataItems,
|
||||
useCoreNaming = false,
|
||||
) => {
|
||||
twentyStandardFlatApplication,
|
||||
}: {
|
||||
objectMetadataItems: ObjectMetadataEntity[];
|
||||
useCoreNaming?: boolean;
|
||||
twentyStandardFlatApplication: FlatApplication;
|
||||
}): ViewDefinition => {
|
||||
const workflowRunObjectMetadata = objectMetadataItems.find(
|
||||
(object) => object.standardId === STANDARD_OBJECT_IDS.workflowRun,
|
||||
);
|
||||
@@ -17,7 +26,13 @@ export const workflowRunsAllView = (
|
||||
throw new Error('Workflow run object metadata not found');
|
||||
}
|
||||
|
||||
const viewUniversalIdentifier =
|
||||
STANDARD_OBJECTS.workflowRun.views.allWorkflowRuns.universalIdentifier;
|
||||
|
||||
return {
|
||||
id: v4(),
|
||||
universalIdentifier: viewUniversalIdentifier,
|
||||
applicationId: twentyStandardFlatApplication.id,
|
||||
name: useCoreNaming ? msg`All {objectLabelPlural}` : 'All Workflow Runs',
|
||||
objectMetadataId: workflowRunObjectMetadata.id,
|
||||
type: 'table',
|
||||
@@ -37,6 +52,9 @@ export const workflowRunsAllView = (
|
||||
position: 0,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.workflowRun.views.allWorkflowRuns.viewFields.name
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -47,6 +65,9 @@ export const workflowRunsAllView = (
|
||||
position: 1,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.workflowRun.views.allWorkflowRuns.viewFields.workflow
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -57,6 +78,9 @@ export const workflowRunsAllView = (
|
||||
position: 2,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.workflowRun.views.allWorkflowRuns.viewFields.status
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -67,6 +91,9 @@ export const workflowRunsAllView = (
|
||||
position: 3,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.workflowRun.views.allWorkflowRuns.viewFields
|
||||
.startedAt.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -77,6 +104,9 @@ export const workflowRunsAllView = (
|
||||
position: 4,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.workflowRun.views.allWorkflowRuns.viewFields
|
||||
.createdBy.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -88,6 +118,9 @@ export const workflowRunsAllView = (
|
||||
position: 5,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.workflowRun.views.allWorkflowRuns.viewFields
|
||||
.workflowVersion.universalIdentifier,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
+34
-3
@@ -1,17 +1,26 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { STANDARD_OBJECTS } from 'src/engine/core-modules/application/constants/standard-object.constant';
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { ViewOpenRecordInType } from 'src/engine/metadata-modules/view/types/view-open-record-in-type.type';
|
||||
import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface';
|
||||
import {
|
||||
BASE_OBJECT_STANDARD_FIELD_IDS,
|
||||
WORKFLOW_VERSION_STANDARD_FIELD_IDS,
|
||||
} from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
|
||||
|
||||
export const workflowVersionsAllView = (
|
||||
objectMetadataItems: ObjectMetadataEntity[],
|
||||
export const workflowVersionsAllView = ({
|
||||
objectMetadataItems,
|
||||
useCoreNaming = false,
|
||||
) => {
|
||||
twentyStandardFlatApplication,
|
||||
}: {
|
||||
objectMetadataItems: ObjectMetadataEntity[];
|
||||
useCoreNaming?: boolean;
|
||||
twentyStandardFlatApplication: FlatApplication;
|
||||
}): ViewDefinition => {
|
||||
const workflowVersionObjectMetadata = objectMetadataItems.find(
|
||||
(object) => object.standardId === STANDARD_OBJECT_IDS.workflowVersion,
|
||||
);
|
||||
@@ -20,7 +29,14 @@ export const workflowVersionsAllView = (
|
||||
throw new Error('Workflow version object metadata not found');
|
||||
}
|
||||
|
||||
const viewUniversalIdentifier =
|
||||
STANDARD_OBJECTS.workflowVersion.views.allWorkflowVersions
|
||||
.universalIdentifier;
|
||||
|
||||
return {
|
||||
id: v4(),
|
||||
universalIdentifier: viewUniversalIdentifier,
|
||||
applicationId: twentyStandardFlatApplication.id,
|
||||
name: useCoreNaming
|
||||
? msg`All {objectLabelPlural}`
|
||||
: 'All Workflow Versions',
|
||||
@@ -42,6 +58,9 @@ export const workflowVersionsAllView = (
|
||||
position: 0,
|
||||
isVisible: true,
|
||||
size: 210,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.workflowVersion.views.allWorkflowVersions.viewFields
|
||||
.name.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -52,6 +71,9 @@ export const workflowVersionsAllView = (
|
||||
position: 1,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.workflowVersion.views.allWorkflowVersions.viewFields
|
||||
.workflow.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -62,6 +84,9 @@ export const workflowVersionsAllView = (
|
||||
position: 2,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.workflowVersion.views.allWorkflowVersions.viewFields
|
||||
.status.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -72,6 +97,9 @@ export const workflowVersionsAllView = (
|
||||
position: 3,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.workflowVersion.views.allWorkflowVersions.viewFields
|
||||
.updatedAt.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -82,6 +110,9 @@ export const workflowVersionsAllView = (
|
||||
position: 4,
|
||||
isVisible: false,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.workflowVersion.views.allWorkflowVersions.viewFields
|
||||
.runs.universalIdentifier,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
+36
-3
@@ -1,17 +1,26 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { STANDARD_OBJECTS } from 'src/engine/core-modules/application/constants/standard-object.constant';
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { ViewOpenRecordInType } from 'src/engine/metadata-modules/view/types/view-open-record-in-type.type';
|
||||
import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface';
|
||||
import {
|
||||
BASE_OBJECT_STANDARD_FIELD_IDS,
|
||||
WORKFLOW_STANDARD_FIELD_IDS,
|
||||
} from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
|
||||
|
||||
export const workflowsAllView = (
|
||||
objectMetadataItems: ObjectMetadataEntity[],
|
||||
export const workflowsAllView = ({
|
||||
objectMetadataItems,
|
||||
useCoreNaming = false,
|
||||
) => {
|
||||
twentyStandardFlatApplication,
|
||||
}: {
|
||||
objectMetadataItems: ObjectMetadataEntity[];
|
||||
useCoreNaming?: boolean;
|
||||
twentyStandardFlatApplication: FlatApplication;
|
||||
}): ViewDefinition => {
|
||||
const workflowObjectMetadata = objectMetadataItems.find(
|
||||
(object) => object.standardId === STANDARD_OBJECT_IDS.workflow,
|
||||
);
|
||||
@@ -20,7 +29,13 @@ export const workflowsAllView = (
|
||||
throw new Error('Workflow object metadata not found');
|
||||
}
|
||||
|
||||
const viewUniversalIdentifier =
|
||||
STANDARD_OBJECTS.workflow.views.allWorkflows.universalIdentifier;
|
||||
|
||||
return {
|
||||
id: v4(),
|
||||
universalIdentifier: viewUniversalIdentifier,
|
||||
applicationId: twentyStandardFlatApplication.id,
|
||||
name: useCoreNaming ? msg`All {objectLabelPlural}` : 'All Workflows',
|
||||
objectMetadataId: workflowObjectMetadata.id,
|
||||
type: 'table',
|
||||
@@ -39,6 +54,9 @@ export const workflowsAllView = (
|
||||
position: 0,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.workflow.views.allWorkflows.viewFields.name
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -49,6 +67,9 @@ export const workflowsAllView = (
|
||||
position: 1,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.workflow.views.allWorkflows.viewFields.statuses
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -59,6 +80,9 @@ export const workflowsAllView = (
|
||||
position: 2,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.workflow.views.allWorkflows.viewFields.updatedAt
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -69,6 +93,9 @@ export const workflowsAllView = (
|
||||
position: 3,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.workflow.views.allWorkflows.viewFields.createdBy
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -79,6 +106,9 @@ export const workflowsAllView = (
|
||||
position: 4,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.workflow.views.allWorkflows.viewFields.versions
|
||||
.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -88,6 +118,9 @@ export const workflowsAllView = (
|
||||
position: 5,
|
||||
isVisible: false,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.workflow.views.allWorkflows.viewFields.runs
|
||||
.universalIdentifier,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
+47
-4
@@ -1,17 +1,26 @@
|
||||
import { msg } from '@lingui/core/macro';
|
||||
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { STANDARD_OBJECTS } from 'src/engine/core-modules/application/constants/standard-object.constant';
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface';
|
||||
import { DEFAULT_VIEW_FIELD_SIZE } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/constants/DEFAULT_VIEW_FIELD_SIZE';
|
||||
import {
|
||||
BASE_OBJECT_STANDARD_FIELD_IDS,
|
||||
WORKSPACE_MEMBER_STANDARD_FIELD_IDS,
|
||||
} from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
|
||||
|
||||
export const workspaceMembersAllView = (
|
||||
objectMetadataItems: ObjectMetadataEntity[],
|
||||
useCoreNaming = false,
|
||||
) => {
|
||||
export const workspaceMembersAllView = ({
|
||||
objectMetadataItems,
|
||||
twentyStandardFlatApplication,
|
||||
useCoreNaming,
|
||||
}: {
|
||||
objectMetadataItems: ObjectMetadataEntity[];
|
||||
useCoreNaming?: boolean;
|
||||
twentyStandardFlatApplication: FlatApplication;
|
||||
}): ViewDefinition => {
|
||||
const workspaceMemberObjectMetadata = objectMetadataItems.find(
|
||||
(object) => object.standardId === STANDARD_OBJECT_IDS.workspaceMember,
|
||||
);
|
||||
@@ -20,7 +29,14 @@ export const workspaceMembersAllView = (
|
||||
throw new Error('WorkspaceMember object metadata not found');
|
||||
}
|
||||
|
||||
const viewUniversalIdentifier =
|
||||
STANDARD_OBJECTS.workspaceMember.views.allWorkspaceMembers
|
||||
.universalIdentifier;
|
||||
|
||||
return {
|
||||
id: v4(),
|
||||
universalIdentifier: viewUniversalIdentifier,
|
||||
applicationId: twentyStandardFlatApplication.id,
|
||||
name: useCoreNaming
|
||||
? msg`All {objectLabelPlural}`
|
||||
: 'All Workspace Members',
|
||||
@@ -41,6 +57,9 @@ export const workspaceMembersAllView = (
|
||||
position: 0,
|
||||
isVisible: true,
|
||||
size: DEFAULT_VIEW_FIELD_SIZE,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.workspaceMember.views.allWorkspaceMembers.viewFields
|
||||
.name.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -52,6 +71,9 @@ export const workspaceMembersAllView = (
|
||||
position: 1,
|
||||
isVisible: true,
|
||||
size: 180,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.workspaceMember.views.allWorkspaceMembers.viewFields
|
||||
.userEmail.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -63,6 +85,9 @@ export const workspaceMembersAllView = (
|
||||
position: 2,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.workspaceMember.views.allWorkspaceMembers.viewFields
|
||||
.avatarUrl.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -74,6 +99,9 @@ export const workspaceMembersAllView = (
|
||||
position: 3,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.workspaceMember.views.allWorkspaceMembers.viewFields
|
||||
.colorScheme.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -84,6 +112,9 @@ export const workspaceMembersAllView = (
|
||||
position: 4,
|
||||
isVisible: true,
|
||||
size: 120,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.workspaceMember.views.allWorkspaceMembers.viewFields
|
||||
.locale.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -94,6 +125,9 @@ export const workspaceMembersAllView = (
|
||||
position: 5,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.workspaceMember.views.allWorkspaceMembers.viewFields
|
||||
.timeZone.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -105,6 +139,9 @@ export const workspaceMembersAllView = (
|
||||
position: 6,
|
||||
isVisible: true,
|
||||
size: 120,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.workspaceMember.views.allWorkspaceMembers.viewFields
|
||||
.dateFormat.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -116,6 +153,9 @@ export const workspaceMembersAllView = (
|
||||
position: 7,
|
||||
isVisible: true,
|
||||
size: 120,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.workspaceMember.views.allWorkspaceMembers.viewFields
|
||||
.timeFormat.universalIdentifier,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
@@ -126,6 +166,9 @@ export const workspaceMembersAllView = (
|
||||
position: 8,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
universalIdentifier:
|
||||
STANDARD_OBJECTS.workspaceMember.views.allWorkspaceMembers.viewFields
|
||||
.createdAt.universalIdentifier,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
@@ -4,6 +4,7 @@ import { InjectDataSource, InjectRepository } from '@nestjs/typeorm';
|
||||
import { DataSource, Repository } from 'typeorm';
|
||||
|
||||
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
|
||||
import { FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service';
|
||||
import { UserWorkspaceEntity } from 'src/engine/core-modules/user-workspace/user-workspace.entity';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
@@ -79,9 +80,10 @@ export class WorkspaceManagerService {
|
||||
const featureFlags =
|
||||
await this.featureFlagService.getWorkspaceFeatureFlagsMap(workspaceId);
|
||||
|
||||
await this.applicationService.createTwentyStandardApplication({
|
||||
workspaceId,
|
||||
});
|
||||
const twentyStandardApplication =
|
||||
await this.applicationService.createTwentyStandardApplication({
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
// TODO later replace by twenty-standard installation aka workspaceMigration run
|
||||
await this.workspaceSyncMetadataService.synchronize({
|
||||
@@ -96,7 +98,18 @@ export class WorkspaceManagerService {
|
||||
`Metadata creation took ${dataSourceMetadataCreationEnd - dataSourceMetadataCreationStart}ms`,
|
||||
);
|
||||
|
||||
await this.setupDefaultRoles(workspaceId, userId);
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
|
||||
await this.setupDefaultRoles({
|
||||
workspaceId,
|
||||
userId,
|
||||
workspaceCustomFlatApplication,
|
||||
});
|
||||
|
||||
const prefillStandardObjectsStart = performance.now();
|
||||
|
||||
@@ -104,6 +117,7 @@ export class WorkspaceManagerService {
|
||||
dataSourceMetadata,
|
||||
workspaceId,
|
||||
featureFlags,
|
||||
twentyStandardApplication,
|
||||
);
|
||||
|
||||
const prefillStandardObjectsEnd = performance.now();
|
||||
@@ -117,6 +131,7 @@ export class WorkspaceManagerService {
|
||||
dataSourceMetadata: DataSourceEntity,
|
||||
workspaceId: string,
|
||||
featureFlags: Record<string, boolean>,
|
||||
twentyStandardFlatApplication: FlatApplication,
|
||||
) {
|
||||
const createdObjectMetadata =
|
||||
await this.objectMetadataServiceV2.findManyWithinWorkspace(workspaceId);
|
||||
@@ -128,6 +143,7 @@ export class WorkspaceManagerService {
|
||||
);
|
||||
|
||||
await prefillCoreViews({
|
||||
twentyStandardFlatApplication,
|
||||
coreDataSource: this.coreDataSource,
|
||||
workspaceId,
|
||||
objectMetadataItems: createdObjectMetadata,
|
||||
@@ -155,10 +171,15 @@ export class WorkspaceManagerService {
|
||||
await this.workspaceDataSourceService.deleteWorkspaceDBSchema(workspaceId);
|
||||
}
|
||||
|
||||
private async setupDefaultRoles(
|
||||
workspaceId: string,
|
||||
userId: string,
|
||||
): Promise<void> {
|
||||
private async setupDefaultRoles({
|
||||
userId,
|
||||
workspaceId,
|
||||
workspaceCustomFlatApplication,
|
||||
}: {
|
||||
workspaceId: string;
|
||||
userId: string;
|
||||
workspaceCustomFlatApplication: FlatApplication;
|
||||
}): Promise<void> {
|
||||
const adminRole = await this.roleRepository.findOne({
|
||||
where: {
|
||||
standardId: ADMIN_ROLE.standardId,
|
||||
@@ -180,6 +201,7 @@ export class WorkspaceManagerService {
|
||||
|
||||
const memberRole = await this.roleService.createMemberRole({
|
||||
workspaceId,
|
||||
applicationId: workspaceCustomFlatApplication.id,
|
||||
});
|
||||
|
||||
await this.workspaceRepository.update(workspaceId, {
|
||||
|
||||
+8
-1
@@ -18,7 +18,14 @@ type AgentComparatorResult = {
|
||||
|
||||
type WorkspaceAgentComparatorArgs = FromTo<FlatAgent[], 'FlatAgents'>;
|
||||
|
||||
const agentPropertiesToIgnore = ['id', 'createdAt', 'updatedAt', 'workspaceId'];
|
||||
const agentPropertiesToIgnore = [
|
||||
'id',
|
||||
'createdAt',
|
||||
'updatedAt',
|
||||
'workspaceId',
|
||||
'universalIdentifier',
|
||||
'applicationId',
|
||||
];
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceAgentComparator {
|
||||
|
||||
+2
@@ -29,6 +29,8 @@ const commonFieldPropertiesToIgnore = [
|
||||
'relationTargetObjectMetadataId',
|
||||
'relationTargetFieldMetadata',
|
||||
'relationTargetObjectMetadata',
|
||||
'universalIdentifier',
|
||||
'applicationId',
|
||||
];
|
||||
|
||||
const fieldPropertiesToStringify = ['defaultValue'] as const;
|
||||
|
||||
+7
-1
@@ -10,7 +10,13 @@ import {
|
||||
import { type IndexMetadataEntity } from 'src/engine/metadata-modules/index-metadata/index-metadata.entity';
|
||||
import { transformMetadataForComparison } from 'src/engine/workspace-manager/workspace-sync-metadata/comparators/utils/transform-metadata-for-comparison.util';
|
||||
|
||||
const propertiesToIgnore = ['createdAt', 'updatedAt', 'indexFieldMetadatas'];
|
||||
const propertiesToIgnore = [
|
||||
'createdAt',
|
||||
'updatedAt',
|
||||
'indexFieldMetadatas',
|
||||
'universalIdentifier',
|
||||
'applicationId',
|
||||
];
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceIndexComparator {
|
||||
|
||||
+2
@@ -20,6 +20,8 @@ const objectPropertiesToIgnore = [
|
||||
'imageIdentifierFieldMetadataId',
|
||||
'isActive',
|
||||
'fields',
|
||||
'universalIdentifier',
|
||||
'applicationId',
|
||||
];
|
||||
|
||||
@Injectable()
|
||||
|
||||
+2
@@ -37,6 +37,8 @@ const rolePropertiesToIgnore = [
|
||||
'permissionFlags',
|
||||
'objectPermissions',
|
||||
'fieldPermissions',
|
||||
'universalIdentifier',
|
||||
'applicationId',
|
||||
];
|
||||
|
||||
@Injectable()
|
||||
|
||||
-30
@@ -157,33 +157,6 @@ export const CONNECTED_ACCOUNT_STANDARD_FIELD_IDS = {
|
||||
connectionParameters: '20202020-a1b2-46be-814f-6228af16c481',
|
||||
} as const;
|
||||
|
||||
export const EVENT_STANDARD_FIELD_IDS = {
|
||||
properties: '20202020-f142-4b04-b91b-6a2b4af3bf10',
|
||||
workspaceMember: '20202020-af23-4479-9a30-868edc474b35',
|
||||
person: '20202020-c414-45b9-a60a-ac27aa96229e',
|
||||
company: '20202020-04ad-4221-a744-7a8278a5ce20',
|
||||
opportunity: '20202020-7664-4a35-a3df-580d389fd5f0',
|
||||
custom: '20202020-4a71-41b0-9f83-9cdcca3f8b14',
|
||||
} as const;
|
||||
|
||||
export const AUDIT_LOGS_STANDARD_FIELD_IDS = {
|
||||
name: '20202020-2462-4b9d-b5d9-745febb3b095',
|
||||
properties: '20202020-5d36-470e-8fad-d56ea3ab2fd0',
|
||||
context: '20202020-b9d1-4058-9a75-7469cab5ca8c',
|
||||
objectName: '20202020-76ba-4c47-b7e5-96034005d00a',
|
||||
objectMetadataId: '20202020-127b-409d-9864-0ec44aa9ed98',
|
||||
recordId: '20202020-c578-4acf-bf94-eb53b035cea2',
|
||||
workspaceMember: '20202020-6e96-4300-b3f5-67a707147385',
|
||||
} as const;
|
||||
|
||||
export const BEHAVIORAL_EVENT_STANDARD_FIELD_IDS = {
|
||||
name: '20202020-2462-4b9d-b5d9-745febb3b095',
|
||||
properties: '20202020-5d36-470e-8fad-d56ea3ab2fd0',
|
||||
context: '20202020-bd62-4b5b-8385-6caeed8f8078',
|
||||
objectName: '20202020-a744-406c-a2e1-9d83d74f4341',
|
||||
recordId: '20202020-6d8b-4ca5-9869-f882cb335673',
|
||||
} as const;
|
||||
|
||||
export const TIMELINE_ACTIVITY_STANDARD_FIELD_IDS = {
|
||||
happensAt: '20202020-9526-4993-b339-c4318c4d39f0',
|
||||
type: '20202020-5e7b-4ccd-8b8a-86b94b474134',
|
||||
@@ -537,7 +510,6 @@ export const WORKSPACE_MEMBER_STANDARD_FIELD_IDS = {
|
||||
calendarStartDay: '20202020-92d0-1d7f-a126-25ededa6b142',
|
||||
numberFormat: '20202020-7f40-4e7f-b126-11c0eda6b141',
|
||||
} as const;
|
||||
|
||||
export const CUSTOM_OBJECT_STANDARD_FIELD_IDS = {
|
||||
name: '20202020-ba07-4ffd-ba63-009491f5749c',
|
||||
position: '20202020-c2bd-4e16-bb9a-c8b0411bf49d',
|
||||
@@ -568,7 +540,6 @@ export const STANDARD_OBJECT_FIELD_IDS = {
|
||||
activity: ACTIVITY_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,
|
||||
@@ -579,7 +550,6 @@ export const STANDARD_OBJECT_FIELD_IDS = {
|
||||
connectedAccount: CONNECTED_ACCOUNT_STANDARD_FIELD_IDS,
|
||||
dashboard: DASHBOARD_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,
|
||||
|
||||
-1
@@ -1,5 +1,4 @@
|
||||
import { type FeatureFlagMap } from 'src/engine/core-modules/feature-flag/interfaces/feature-flag-map.interface';
|
||||
|
||||
export interface WorkspaceSyncContext {
|
||||
workspaceId: string;
|
||||
dataSourceId: string;
|
||||
|
||||
-27
@@ -1,27 +0,0 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { type WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { type CreateApplicationInput } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/twenty-standard-applications';
|
||||
|
||||
export const computeWorkspaceCustomCreateApplicationInput = ({
|
||||
workspace,
|
||||
applicationId = v4(),
|
||||
}: {
|
||||
applicationId?: string;
|
||||
workspace: Pick<WorkspaceEntity, 'id' | 'displayName'>;
|
||||
}) =>
|
||||
({
|
||||
description: 'Workspace custom application',
|
||||
name: `${isDefined(workspace.displayName) ? `${workspace.displayName}'s ` : ''}custom application`,
|
||||
sourcePath: 'workspace-custom',
|
||||
sourceType: 'local',
|
||||
version: '1.0.0',
|
||||
universalIdentifier: applicationId,
|
||||
workspaceId: workspace.id,
|
||||
id: applicationId,
|
||||
canBeUninstalled: false,
|
||||
}) as const satisfies CreateApplicationInput & {
|
||||
workspaceId: string;
|
||||
id: string;
|
||||
};
|
||||
+1
-1
@@ -10,7 +10,7 @@ import { jestExpectToBeDefined } from 'test/utils/jest-expect-to-be-defined.util
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { WorkspaceActivationStatus } from 'twenty-shared/workspace';
|
||||
|
||||
import { TWENTY_STANDARD_APPLICATION } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/twenty-standard-applications';
|
||||
import { TWENTY_STANDARD_APPLICATION } from 'src/engine/core-modules/application/constants/twenty-standard-applications';
|
||||
|
||||
describe('Successful user and workspace creation', () => {
|
||||
let createdUserAccessToken: string | undefined;
|
||||
|
||||
Reference in New Issue
Block a user