Refactor onboarding user vars to be absent when user is fully onboarded (#6531)

In this PR:
- take feedbacks from: https://github.com/twentyhq/twenty/pull/6530 /
https://github.com/twentyhq/twenty/pull/6529 /
https://github.com/twentyhq/twenty/pull/6526 /
https://github.com/twentyhq/twenty/pull/6512
- refactor onboarding uservars to be absent when the user is fully
onboarded: isStepComplete ==> isStepIncomplete
- introduce a new workspace.activationStatus: CREATION_ONGOING

I'm retesting the whole flow:
- with/without BILLING
- sign in with/without SSO
- sign up with/without SSO
- another workspaceMembers join the team
- subscriptionCanceled
- access to billingPortal
This commit is contained in:
Charles Bochet
2024-08-04 20:37:36 +02:00
committed by GitHub
parent c543716381
commit 03204021cb
49 changed files with 517 additions and 364 deletions

View File

@ -1,3 +1,5 @@
import { Logger } from '@nestjs/common';
import { Command, CommandRunner } from 'nest-commander';
import { EntityManager } from 'typeorm';
@ -43,6 +45,7 @@ import { WorkspaceSyncMetadataService } from 'src/engine/workspace-manager/works
})
export class DataSeedWorkspaceCommand extends CommandRunner {
workspaceIds = [SEED_APPLE_WORKSPACE_ID, SEED_TWENTY_WORKSPACE_ID];
private readonly logger = new Logger(DataSeedWorkspaceCommand.name);
constructor(
private readonly dataSourceService: DataSourceService,
@ -86,7 +89,7 @@ export class DataSeedWorkspaceCommand extends CommandRunner {
});
}
} catch (error) {
console.error(error);
this.logger.error(error);
return;
}
@ -197,7 +200,7 @@ export class DataSeedWorkspaceCommand extends CommandRunner {
},
);
} catch (error) {
console.error(error);
this.logger.error(error);
}
await this.typeORMService.disconnectFromDataSource(dataSourceMetadata.id);

View File

@ -9,7 +9,6 @@ import { DataSeedWorkspaceCommand } from 'src/database/commands/data-seed-dev-wo
import { ConfirmationQuestion } from 'src/database/commands/questions/confirmation.question';
import { UpgradeTo0_23CommandModule } from 'src/database/commands/upgrade-version/0-23/0-23-upgrade-version.module';
import { UpgradeVersionModule } from 'src/database/commands/upgrade-version/upgrade-version.module';
import { WorkspaceAddTotalCountCommand } from 'src/database/commands/workspace-add-total-count.command';
import { TypeORMModule } from 'src/database/typeorm/typeorm.module';
import { BillingSubscription } from 'src/engine/core-modules/billing/entities/billing-subscription.entity';
import { FeatureFlagEntity } from 'src/engine/core-modules/feature-flag/feature-flag.entity';
@ -51,7 +50,6 @@ import { WorkspaceSyncMetadataModule } from 'src/engine/workspace-manager/worksp
providers: [
DataSeedWorkspaceCommand,
DataSeedDemoWorkspaceCommand,
WorkspaceAddTotalCountCommand,
ConfirmationQuestion,
StartDataSeedDemoWorkspaceCronCommand,
StopDataSeedDemoWorkspaceCronCommand,

View File

@ -5,7 +5,6 @@ import chalk from 'chalk';
import { Command, CommandRunner, Option } from 'nest-commander';
import { Repository } from 'typeorm';
import { UpdateFileFolderStructureCommand } from 'src/database/commands/upgrade-version/0-23/0-23-update-file-folder-structure.command';
import { OnboardingService } from 'src/engine/core-modules/onboarding/onboarding.service';
import {
Workspace,
@ -21,7 +20,9 @@ interface BackfillNewOnboardingUserVarsCommandOptions {
description: 'Backfill new onboarding user vars for existing workspaces',
})
export class BackfillNewOnboardingUserVarsCommand extends CommandRunner {
private readonly logger = new Logger(UpdateFileFolderStructureCommand.name);
private readonly logger = new Logger(
BackfillNewOnboardingUserVarsCommand.name,
);
constructor(
@InjectRepository(Workspace, 'core')
private readonly workspaceRepository: Repository<Workspace>,
@ -43,22 +44,13 @@ export class BackfillNewOnboardingUserVarsCommand extends CommandRunner {
_passedParam: string[],
options: BackfillNewOnboardingUserVarsCommandOptions,
): Promise<void> {
let workspaces;
if (options.workspaceId) {
workspaces = await this.workspaceRepository.find({
where: {
activationStatus: WorkspaceActivationStatus.ACTIVE,
id: options.workspaceId,
},
relations: ['users'],
});
} else {
workspaces = await this.workspaceRepository.find({
where: { activationStatus: WorkspaceActivationStatus.ACTIVE },
relations: ['users'],
});
}
const workspaces = await this.workspaceRepository.find({
where: {
activationStatus: WorkspaceActivationStatus.PENDING_CREATION,
...(options.workspaceId && { id: options.workspaceId }),
},
relations: ['users'],
});
if (!workspaces.length) {
this.logger.log(chalk.yellow('No workspace found'));
@ -75,19 +67,19 @@ export class BackfillNewOnboardingUserVarsCommand extends CommandRunner {
chalk.green(`Running command on workspace ${workspace.id}`),
);
await this.onboardingService.toggleOnboardingInviteTeamCompletion({
await this.onboardingService.setOnboardingInviteTeamPending({
workspaceId: workspace.id,
value: true,
});
for (const user of workspace.users) {
await this.onboardingService.toggleOnboardingConnectAccountCompletion({
await this.onboardingService.setOnboardingCreateProfileCompletion({
userId: user.id,
workspaceId: workspace.id,
value: true,
});
await this.onboardingService.toggleOnboardingCreateProfileCompletion({
await this.onboardingService.setOnboardingConnectAccountPending({
userId: user.id,
workspaceId: workspace.id,
value: true,

View File

@ -1,49 +0,0 @@
import { Command, CommandRunner } from 'nest-commander';
import chalk from 'chalk';
import { TypeORMService } from 'src/database/typeorm/typeorm.service';
@Command({
name: 'workspace:add-total-count',
description: 'Add pg_graphql total count directive to all workspace tables',
})
export class WorkspaceAddTotalCountCommand extends CommandRunner {
constructor(private readonly typeORMService: TypeORMService) {
super();
}
async run(): Promise<void> {
const mainDataSource = this.typeORMService.getMainDataSource();
try {
await mainDataSource.query(`
DO $$
DECLARE
schema_cursor CURSOR FOR SELECT schema_name FROM information_schema.schemata WHERE schema_name LIKE 'workspace_%';
schema_name text;
table_rec record;
BEGIN
OPEN schema_cursor;
LOOP
FETCH schema_cursor INTO schema_name;
EXIT WHEN NOT FOUND;
FOR table_rec IN SELECT t.table_name FROM information_schema.tables t WHERE t.table_schema = schema_name
LOOP
EXECUTE 'COMMENT ON TABLE ' || quote_ident(schema_name) || '.' || quote_ident(table_rec.table_name) || ' IS e''@graphql({"totalCount": {"enabled": true}})'';';
END LOOP;
END LOOP;
CLOSE schema_cursor;
END $$;
`);
console.log(
chalk.green('Total count directive added to all workspace tables'),
);
} catch (error) {
console.log(
chalk.red('Error adding total count directive to all workspace tables'),
);
}
}
}

View File

@ -0,0 +1,69 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
export class UpdateActivationStatusEnumPendingCreationStatus1722256203541
implements MigrationInterface
{
name = 'UpdateActivationStatusEnumPendingCreationStatus1722256203541';
public async up(queryRunner: QueryRunner): Promise<void> {
// Set current column as text
await queryRunner.query(
`ALTER TABLE "core"."workspace" ALTER COLUMN "activationStatus" SET DATA TYPE text USING "activationStatus"::text`,
);
// Drop default value
await queryRunner.query(
`ALTER TABLE "core"."workspace" ALTER COLUMN "activationStatus" DROP DEFAULT`,
);
// Drop the old enum type
await queryRunner.query(
`DROP TYPE "core"."workspace_activationStatus_enum"`,
);
await queryRunner.query(
`CREATE TYPE "core"."workspace_activationStatus_enum" AS ENUM('PENDING_CREATION', 'ONGOING_CREATION', 'ACTIVE', 'INACTIVE')`,
);
// Re-apply the enum type
await queryRunner.query(
`ALTER TABLE "core"."workspace" ALTER COLUMN "activationStatus" SET DATA TYPE "core"."workspace_activationStatus_enum" USING "activationStatus"::"core"."workspace_activationStatus_enum"`,
);
// Update default value
await queryRunner.query(
`ALTER TABLE "core"."workspace" ALTER COLUMN "activationStatus" SET DEFAULT 'INACTIVE'`,
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
// Set current column as text
await queryRunner.query(
`ALTER TABLE "core"."workspace" ALTER COLUMN "activationStatus" SET DATA TYPE text USING "activationStatus"::text`,
);
// Drop default value
await queryRunner.query(
`ALTER TABLE "core"."workspace" ALTER COLUMN "activationStatus" DROP DEFAULT`,
);
// Drop the old enum type
await queryRunner.query(
`DROP TYPE "core"."workspace_activationStatus_enum"`,
);
await queryRunner.query(
`CREATE TYPE "core"."workspace_activationStatus_enum" AS ENUM('PENDING_CREATION', 'ACTIVE', 'INACTIVE')`,
);
// Re-apply the enum type
await queryRunner.query(
`ALTER TABLE "core"."workspace" ALTER COLUMN "activationStatus" SET DATA TYPE "core"."workspace_activationStatus_enum" USING "activationStatus"::"core"."workspace_activationStatus_enum"`,
);
// Update default value
await queryRunner.query(
`ALTER TABLE "core"."workspace" ALTER COLUMN "activationStatus" SET DEFAULT 'INACTIVE'`,
);
}
}