message list member backfill (#23176)
<!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/twentyhq/twenty/pull/23176?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. -->
This commit is contained in:
+1
-4
@@ -7,8 +7,7 @@ import {
|
||||
type UnsubscribeTopicsQuery,
|
||||
UnsubscribeTopicVisibility,
|
||||
} from '~/generated-metadata/graphql';
|
||||
import { Pill, Status } from 'twenty-ui/data-display';
|
||||
import { IconLock } from 'twenty-ui/icon';
|
||||
import { Status } from 'twenty-ui/data-display';
|
||||
import { useNavigateSettings } from '~/hooks/useNavigateSettings';
|
||||
|
||||
type UnsubscribeTopic = UnsubscribeTopicsQuery['unsubscribeTopics'][number];
|
||||
@@ -20,13 +19,11 @@ export const SettingsWorkspaceUnsubscribeTopicSection = () => {
|
||||
|
||||
const title = t`Unsubscribe topics`;
|
||||
const description = t`Email categories recipients can opt out of`;
|
||||
const organizationPill = <Pill Icon={IconLock} label={t`Organization`} />;
|
||||
|
||||
return (
|
||||
<SettingsTableListSection<UnsubscribeTopic>
|
||||
title={title}
|
||||
description={description}
|
||||
headerAdornment={organizationPill}
|
||||
items={unsubscribeTopics}
|
||||
columns={[
|
||||
{
|
||||
|
||||
-3
@@ -6,8 +6,6 @@ import { SettingsTableListSection } from '@/settings/components/SettingsTableLis
|
||||
import { SettingsWorkspaceEmailChannelDomainStatusCell } from '@/settings/workspace/components/SettingsWorkspaceEmailChannelDomainStatusCell';
|
||||
import { SettingsWorkspaceEmailGroupSourceCell } from '@/settings/workspace/components/SettingsWorkspaceEmailGroupSourceCell';
|
||||
import { MessageChannelType, SettingsPath } from 'twenty-shared/types';
|
||||
import { Pill } from 'twenty-ui/data-display';
|
||||
import { IconLock } from 'twenty-ui/icon';
|
||||
import { useNavigateSettings } from '~/hooks/useNavigateSettings';
|
||||
|
||||
export const SettingsWorkspaceEmailGroupSection = () => {
|
||||
@@ -23,7 +21,6 @@ export const SettingsWorkspaceEmailGroupSection = () => {
|
||||
<SettingsTableListSection<MessageChannel>
|
||||
title={t`Channels`}
|
||||
description={t`Addresses your workspace uses to send and receive email from shared inboxes`}
|
||||
headerAdornment={<Pill Icon={IconLock} label={t`Organization`} />}
|
||||
items={emailGroupChannels}
|
||||
columns={[
|
||||
{ label: t`Email`, Cell: SettingsWorkspaceEmailGroupSourceCell },
|
||||
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { WorkspaceIteratorModule } from 'src/database/commands/command-runners/workspace-iterator.module';
|
||||
import { BackfillMessageListMembersJunctionTargetCommand } from 'src/database/commands/upgrade-version-command/2-24/2-24-workspace-command-1784567000000-backfill-message-list-members-junction-target.command';
|
||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { WorkspaceCacheModule } from 'src/engine/workspace-cache/workspace-cache.module';
|
||||
import { WorkspaceMigrationRunnerModule } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/workspace-migration-runner.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([FieldMetadataEntity]),
|
||||
WorkspaceCacheModule,
|
||||
WorkspaceMigrationRunnerModule,
|
||||
WorkspaceIteratorModule,
|
||||
],
|
||||
providers: [BackfillMessageListMembersJunctionTargetCommand],
|
||||
})
|
||||
export class V2_24_UpgradeVersionCommandModule {}
|
||||
+138
@@ -0,0 +1,138 @@
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { Command } from 'nest-commander';
|
||||
import { STANDARD_OBJECTS } from 'twenty-shared/metadata';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import { ProvisionedWorkspaceCommandRunner } from 'src/database/commands/command-runners/provisioned-workspace.command-runner';
|
||||
import { WorkspaceIteratorService } from 'src/database/commands/command-runners/workspace-iterator.service';
|
||||
import { type RunOnWorkspaceArgs } from 'src/database/commands/command-runners/workspace.command-runner';
|
||||
import { RegisteredWorkspaceCommand } from 'src/engine/core-modules/upgrade/decorators/registered-workspace-command.decorator';
|
||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { isFieldMetadataSettingsOfType } from 'src/engine/metadata-modules/field-metadata/utils/is-field-metadata-settings-of-type.util';
|
||||
import { getMetadataFlatEntityMapsKey } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-flat-entity-maps-key.util';
|
||||
import { getMetadataRelatedMetadataNames } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-related-metadata-names.util';
|
||||
import { getMetadataSerializedRelationNames } from 'src/engine/metadata-modules/flat-entity/utils/get-metadata-serialized-relation-names.util';
|
||||
import { WorkspaceCacheService } from 'src/engine/workspace-cache/services/workspace-cache.service';
|
||||
import { WorkspaceMigrationRunnerService } from 'src/engine/workspace-manager/workspace-migration/workspace-migration-runner/services/workspace-migration-runner.service';
|
||||
|
||||
const MEMBERS_FIELD_UNIVERSAL_IDENTIFIER =
|
||||
STANDARD_OBJECTS.messageList.fields.members.universalIdentifier;
|
||||
|
||||
const PERSON_FIELD_UNIVERSAL_IDENTIFIER =
|
||||
STANDARD_OBJECTS.messageListMember.fields.person.universalIdentifier;
|
||||
|
||||
@RegisteredWorkspaceCommand('2.24.0', 1784567000000)
|
||||
@Command({
|
||||
name: 'upgrade:2-24:backfill-message-list-members-junction-target',
|
||||
description:
|
||||
'Backfill the junction target field id on messageList.members for workspaces provisioned before it was declared, so the record page renders the members junction picker.',
|
||||
})
|
||||
export class BackfillMessageListMembersJunctionTargetCommand extends ProvisionedWorkspaceCommandRunner {
|
||||
constructor(
|
||||
protected readonly workspaceIteratorService: WorkspaceIteratorService,
|
||||
private readonly workspaceCacheService: WorkspaceCacheService,
|
||||
private readonly workspaceMigrationRunnerService: WorkspaceMigrationRunnerService,
|
||||
@InjectRepository(FieldMetadataEntity)
|
||||
private readonly fieldMetadataRepository: Repository<FieldMetadataEntity>,
|
||||
) {
|
||||
super(workspaceIteratorService);
|
||||
}
|
||||
|
||||
override async runOnWorkspace({
|
||||
workspaceId,
|
||||
options,
|
||||
}: RunOnWorkspaceArgs): Promise<void> {
|
||||
const isDryRun = options.dryRun ?? false;
|
||||
|
||||
const { flatFieldMetadataMaps } =
|
||||
await this.workspaceCacheService.getOrRecompute(workspaceId, [
|
||||
'flatFieldMetadataMaps',
|
||||
]);
|
||||
|
||||
const membersFlatFieldMetadata =
|
||||
flatFieldMetadataMaps.byUniversalIdentifier[
|
||||
MEMBERS_FIELD_UNIVERSAL_IDENTIFIER
|
||||
];
|
||||
|
||||
if (!isDefined(membersFlatFieldMetadata)) {
|
||||
this.logger.log(
|
||||
`No messageList.members field for workspace ${workspaceId}, skipping`,
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const currentSettings = membersFlatFieldMetadata.settings;
|
||||
|
||||
if (
|
||||
!isFieldMetadataSettingsOfType(currentSettings, FieldMetadataType.RELATION)
|
||||
) {
|
||||
this.logger.warn(
|
||||
`messageList.members has no relation settings for workspace ${workspaceId}, skipping`,
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (isDefined(currentSettings.junctionTargetFieldId)) {
|
||||
this.logger.log(
|
||||
`messageList.members junction target already set for workspace ${workspaceId}, skipping`,
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const personFlatFieldMetadata =
|
||||
flatFieldMetadataMaps.byUniversalIdentifier[
|
||||
PERSON_FIELD_UNIVERSAL_IDENTIFIER
|
||||
];
|
||||
|
||||
if (!isDefined(personFlatFieldMetadata)) {
|
||||
this.logger.warn(
|
||||
`No messageListMember.person field for workspace ${workspaceId}, skipping`,
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const updatedSettings = {
|
||||
...currentSettings,
|
||||
junctionTargetFieldId: personFlatFieldMetadata.id,
|
||||
};
|
||||
|
||||
this.logger.log(
|
||||
`${isDryRun ? '[DRY RUN] ' : ''}Backfilling messageList.members junction target for workspace ${workspaceId}`,
|
||||
);
|
||||
|
||||
if (isDryRun) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this.fieldMetadataRepository.update(
|
||||
{ id: membersFlatFieldMetadata.id, workspaceId },
|
||||
{ settings: updatedSettings },
|
||||
);
|
||||
|
||||
const fieldMetadataRelatedNames = [
|
||||
'fieldMetadata',
|
||||
...getMetadataRelatedMetadataNames('fieldMetadata'),
|
||||
...getMetadataSerializedRelationNames('fieldMetadata'),
|
||||
'index',
|
||||
] as const;
|
||||
const allFlatEntityMapsKeys = [
|
||||
...new Set(fieldMetadataRelatedNames.map(getMetadataFlatEntityMapsKey)),
|
||||
];
|
||||
|
||||
await this.workspaceMigrationRunnerService.invalidateCache({
|
||||
allFlatEntityMapsKeys,
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
this.logger.log(
|
||||
`Backfilled messageList.members junction target for workspace ${workspaceId}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
+2
@@ -24,6 +24,7 @@ import { V2_20_UpgradeVersionCommandModule } from 'src/database/commands/upgrade
|
||||
import { V2_21_UpgradeVersionCommandModule } from 'src/database/commands/upgrade-version-command/2-21/2-21-upgrade-version-command.module';
|
||||
import { V2_22_UpgradeVersionCommandModule } from 'src/database/commands/upgrade-version-command/2-22/2-22-upgrade-version-command.module';
|
||||
import { V2_23_UpgradeVersionCommandModule } from 'src/database/commands/upgrade-version-command/2-23/2-23-upgrade-version-command.module';
|
||||
import { V2_24_UpgradeVersionCommandModule } from 'src/database/commands/upgrade-version-command/2-24/2-24-upgrade-version-command.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
@@ -51,6 +52,7 @@ import { V2_23_UpgradeVersionCommandModule } from 'src/database/commands/upgrade
|
||||
V2_21_UpgradeVersionCommandModule,
|
||||
V2_22_UpgradeVersionCommandModule,
|
||||
V2_23_UpgradeVersionCommandModule,
|
||||
V2_24_UpgradeVersionCommandModule,
|
||||
],
|
||||
})
|
||||
export class WorkspaceCommandProviderModule {}
|
||||
|
||||
Reference in New Issue
Block a user