feat(editor): Improve n8n welcome experience (#3289)

*  Injecting a welcome sticky note if a corresponding flag has been received from backend

* 🔒 Allowing resources from `/static` route to be displayed in markown component.

*  Implemented image width control via markdown URLs

* 💄Updating quickstart video thumbnail images.

* 🔨 Updated new workflow action name and quickstart sticky name

*  Added quickstart menu item in the Help menu

* 🔨 Moving quickstart video thumbnail to the translation file.

* 🔒 Limiting http static resource requests in markdown img tags only to image files.

* 🔒 Adding more file types to supported image list in markown component.

* 👌 Extracting quickstart note name to constant.

* 🐘 add DB migration sqlite

* ️ add logic for onboarding flow flag

* 🐘 add postgres migration for user settings

* 🐘 add mysql migration for user settings

*  Injecting a welcome sticky note if a corresponding flag has been received from backend

* 🔒 Allowing resources from `/static` route to be displayed in markown component.

*  Implemented image width control via markdown URLs

* 💄Updating quickstart video thumbnail images.

* 🔨 Updated new workflow action name and quickstart sticky name

*  Added quickstart menu item in the Help menu

* 🔨 Moving quickstart video thumbnail to the translation file.

* 🔒 Limiting http static resource requests in markdown img tags only to image files.

* 🔒 Adding more file types to supported image list in markown component.

* 👌 Extracting quickstart note name to constant.

* 📈 Added telemetry events to quickstart sticky note.

*  Disable sticky node type from showing in expression editor

* 🔨 Improving welcome video link detecton when triggering telemetry events

* 👌Moved sticky links click handling logic outside of the design system, removed user and instance id from telemetry events.

* 👌Improving sticky note link telemetry tracking.

* 🔨 Refactoring markdown component click event logic.

* 🔨 Moving bits of clicked link detection logic to Markdown component.

* 💄Fixing code spacing.

* remove transpileonly option

* update package lock

* 💄Changing the default route to `/workflow`, updating welcome sticky content.

* remove hardcoded

* 🐛 Fixing the onboarding threshold logic so sticky notes are skipped when counting nodes.

* 👕 Fixing linting errors.

Co-authored-by: Milorad Filipović <milorad.filipovic19@gmail.com>
Co-authored-by: Milorad Filipović <miloradfilipovic19@gmail.com>
Co-authored-by: Ben Hesseldieck <b.hesseldieck@gmail.com>
Co-authored-by: Milorad Filipović <milorad@n8n.io>
This commit is contained in:
Mutasem Aldmour
2022-05-16 18:19:33 +02:00
committed by GitHub
parent 68cbb78680
commit 35f2ce2359
29 changed files with 1346 additions and 95629 deletions

View File

@@ -16,7 +16,7 @@ import {
} from 'typeorm';
import { IsEmail, IsString, Length } from 'class-validator';
import * as config from '../../../config';
import { DatabaseType, IPersonalizationSurveyAnswers } from '../..';
import { DatabaseType, IPersonalizationSurveyAnswers, IUserSettings } from '../..';
import { Role } from './Role';
import { SharedWorkflow } from './SharedWorkflow';
import { SharedCredentials } from './SharedCredentials';
@@ -102,6 +102,12 @@ export class User {
})
personalizationAnswers: IPersonalizationSurveyAnswers | null;
@Column({
type: resolveDataType('json') as ColumnOptions['type'],
nullable: true,
})
settings: IUserSettings | null;
@ManyToOne(() => Role, (role) => role.globalForUsers, {
cascade: true,
nullable: false,

View File

@@ -0,0 +1,25 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
import * as config from '../../../../config';
export class AddUserSettings1652367743993 implements MigrationInterface {
name = 'AddUserSettings1652367743993';
public async up(queryRunner: QueryRunner): Promise<void> {
const tablePrefix = config.getEnv('database.tablePrefix');
await queryRunner.query(
'ALTER TABLE `' + tablePrefix + 'user` ADD COLUMN `settings` json NULL DEFAULT NULL',
);
await queryRunner.query(
'ALTER TABLE `' +
tablePrefix +
'user` CHANGE COLUMN `personalizationAnswers` `personalizationAnswers` json NULL DEFAULT NULL',
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
const tablePrefix = config.getEnv('database.tablePrefix');
await queryRunner.query('ALTER TABLE `' + tablePrefix + 'user` DROP COLUMN `settings`');
}
}

View File

@@ -13,6 +13,7 @@ import { UpdateWorkflowCredentials1630451444017 } from './1630451444017-UpdateWo
import { AddExecutionEntityIndexes1644424784709 } from './1644424784709-AddExecutionEntityIndexes';
import { CreateUserManagement1646992772331 } from './1646992772331-CreateUserManagement';
import { LowerCaseUserEmail1648740597343 } from './1648740597343-LowerCaseUserEmail';
import { AddUserSettings1652367743993 } from './1652367743993-AddUserSettings';
export const mysqlMigrations = [
InitialMigration1588157391238,
@@ -30,4 +31,5 @@ export const mysqlMigrations = [
AddExecutionEntityIndexes1644424784709,
CreateUserManagement1646992772331,
LowerCaseUserEmail1648740597343,
AddUserSettings1652367743993,
];

View File

@@ -0,0 +1,30 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
import * as config from '../../../../config';
export class AddUserSettings1652367743993 implements MigrationInterface {
name = 'AddUserSettings1652367743993';
public async up(queryRunner: QueryRunner): Promise<void> {
let tablePrefix = config.getEnv('database.tablePrefix');
const schema = config.getEnv('database.postgresdb.schema');
if (schema) {
tablePrefix = schema + '.' + tablePrefix;
}
await queryRunner.query(`ALTER TABLE ${tablePrefix}user ADD COLUMN settings json`);
await queryRunner.query(
`ALTER TABLE ${tablePrefix}user ALTER COLUMN "personalizationAnswers" TYPE json USING to_jsonb("personalizationAnswers")::json;`,
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
let tablePrefix = config.getEnv('database.tablePrefix');
const schema = config.getEnv('database.postgresdb.schema');
if (schema) {
tablePrefix = schema + '.' + tablePrefix;
}
await queryRunner.query(`ALTER TABLE ${tablePrefix}user DROP COLUMN settings`);
}
}

View File

@@ -11,6 +11,7 @@ import { AddExecutionEntityIndexes1644422880309 } from './1644422880309-AddExecu
import { IncreaseTypeVarcharLimit1646834195327 } from './1646834195327-IncreaseTypeVarcharLimit';
import { CreateUserManagement1646992772331 } from './1646992772331-CreateUserManagement';
import { LowerCaseUserEmail1648740597343 } from './1648740597343-LowerCaseUserEmail';
import { AddUserSettings1652367743993 } from './1652367743993-AddUserSettings';
export const postgresMigrations = [
InitialMigration1587669153312,
@@ -26,4 +27,5 @@ export const postgresMigrations = [
IncreaseTypeVarcharLimit1646834195327,
CreateUserManagement1646992772331,
LowerCaseUserEmail1648740597343,
AddUserSettings1652367743993,
];

View File

@@ -0,0 +1,52 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
import * as config from '../../../../config';
import { logMigrationEnd, logMigrationStart } from '../../utils/migrationHelpers';
export class AddUserSettings1652367743993 implements MigrationInterface {
name = 'AddUserSettings1652367743993';
public async up(queryRunner: QueryRunner): Promise<void> {
logMigrationStart(this.name);
const tablePrefix = config.getEnv('database.tablePrefix');
await queryRunner.query('PRAGMA foreign_keys=OFF');
await queryRunner.query(
`CREATE TABLE "temporary_user" ("id" varchar PRIMARY KEY NOT NULL, "email" varchar(255), "firstName" varchar(32), "lastName" varchar(32), "password" varchar, "resetPasswordToken" varchar, "resetPasswordTokenExpiration" integer DEFAULT NULL, "personalizationAnswers" text, "createdAt" datetime(3) NOT NULL DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')), "updatedAt" datetime(3) NOT NULL DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')), "globalRoleId" integer NOT NULL, "settings" text, CONSTRAINT "FK_${tablePrefix}f0609be844f9200ff4365b1bb3d" FOREIGN KEY ("globalRoleId") REFERENCES "${tablePrefix}role" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION)`,
);
await queryRunner.query(
`INSERT INTO "temporary_user"("id", "email", "firstName", "lastName", "password", "resetPasswordToken", "resetPasswordTokenExpiration", "personalizationAnswers", "createdAt", "updatedAt", "globalRoleId") SELECT "id", "email", "firstName", "lastName", "password", "resetPasswordToken", "resetPasswordTokenExpiration", "personalizationAnswers", "createdAt", "updatedAt", "globalRoleId" FROM "${tablePrefix}user"`,
);
await queryRunner.query(`DROP TABLE "${tablePrefix}user"`);
await queryRunner.query(`ALTER TABLE "temporary_user" RENAME TO "${tablePrefix}user"`);
await queryRunner.query(
`CREATE UNIQUE INDEX "UQ_${tablePrefix}e12875dfb3b1d92d7d7c5377e2" ON "${tablePrefix}user" ("email")`,
);
await queryRunner.query('PRAGMA foreign_keys=ON');
logMigrationEnd(this.name);
}
public async down(queryRunner: QueryRunner): Promise<void> {
const tablePrefix = config.getEnv('database.tablePrefix');
await queryRunner.query('PRAGMA foreign_keys=OFF');
await queryRunner.query(`ALTER TABLE "${tablePrefix}user" RENAME TO "temporary_user"`);
await queryRunner.query(
`CREATE TABLE "${tablePrefix}user" ("id" varchar PRIMARY KEY NOT NULL, "email" varchar(255), "firstName" varchar(32), "lastName" varchar(32), "password" varchar, "resetPasswordToken" varchar, "resetPasswordTokenExpiration" integer DEFAULT NULL, "personalizationAnswers" text, "createdAt" datetime(3) NOT NULL DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')), "updatedAt" datetime(3) NOT NULL DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')), "globalRoleId" integer NOT NULL, CONSTRAINT "FK_${tablePrefix}f0609be844f9200ff4365b1bb3d" FOREIGN KEY ("globalRoleId") REFERENCES "${tablePrefix}role" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION)`,
);
await queryRunner.query(
`INSERT INTO "${tablePrefix}user"("id", "email", "firstName", "lastName", "password", "resetPasswordToken", "resetPasswordTokenExpiration", "personalizationAnswers", "createdAt", "updatedAt", "globalRoleId") SELECT "id", "email", "firstName", "lastName", "password", "resetPasswordToken", "resetPasswordTokenExpiration", "personalizationAnswers", "createdAt", "updatedAt", "globalRoleId" FROM "temporary_user"`,
);
await queryRunner.query(`DROP TABLE "temporary_user"`);
await queryRunner.query(
`CREATE UNIQUE INDEX "UQ_${tablePrefix}e12875dfb3b1d92d7d7c5377e2" ON "${tablePrefix}user" ("email")`,
);
await queryRunner.query('PRAGMA foreign_keys=ON');
}
}

View File

@@ -12,6 +12,7 @@ import { UpdateWorkflowCredentials1630330987096 } from './1630330987096-UpdateWo
import { AddExecutionEntityIndexes1644421939510 } from './1644421939510-AddExecutionEntityIndexes';
import { CreateUserManagement1646992772331 } from './1646992772331-CreateUserManagement';
import { LowerCaseUserEmail1648740597343 } from './1648740597343-LowerCaseUserEmail';
import { AddUserSettings1652367743993 } from './1652367743993-AddUserSettings';
const sqliteMigrations = [
InitialMigration1588102412422,
@@ -26,6 +27,7 @@ const sqliteMigrations = [
AddExecutionEntityIndexes1644421939510,
CreateUserManagement1646992772331,
LowerCaseUserEmail1648740597343,
AddUserSettings1652367743993,
];
export { sqliteMigrations };