Fix/metadata object and settings post merge (#2269)

* WIP

* WIP2

* Seed views standard objects

* Migrate views to the new data model

---------

Co-authored-by: Lucas Bordeau <bordeau.lucas@gmail.com>
This commit is contained in:
Charles Bochet
2023-10-28 12:25:43 +02:00
committed by GitHub
parent afd4b7c634
commit b591023eb3
30 changed files with 609 additions and 208 deletions

View File

@ -0,0 +1,47 @@
import { Command, CommandRunner, Option } from 'nest-commander';
import { TenantInitialisationService } from '../tenant-initialisation/tenant-initialisation.service';
import { DataSourceMetadataService } from '../data-source-metadata/data-source-metadata.service';
// TODO: implement dry-run
interface DataSeedTenantOptions {
workspaceId: string;
}
@Command({
name: 'tenant:data-seed',
description: 'Seed tenant with initial data',
})
export class DataSeedTenantCommand extends CommandRunner {
constructor(
private readonly dataSourceMetadataService: DataSourceMetadataService,
private readonly tenantInitialisationService: TenantInitialisationService,
) {
super();
}
async run(
_passedParam: string[],
options: DataSeedTenantOptions,
): Promise<void> {
const dataSourceMetadata =
await this.dataSourceMetadataService.getLastDataSourceMetadataFromWorkspaceIdOrFail(
options.workspaceId,
);
// TODO: run in a dedicated job + run queries in a transaction.
await this.tenantInitialisationService.prefillWorkspaceWithStandardObjects(
dataSourceMetadata,
options.workspaceId,
);
}
// TODO: workspaceId should be optional and we should run migrations for all workspaces
@Option({
flags: '-w, --workspace-id [workspace_id]',
description: 'workspace id',
required: true,
})
parseWorkspaceId(value: string): string {
return value;
}
}

View File

@ -9,6 +9,7 @@ import { DataSourceMetadataModule } from 'src/metadata/data-source-metadata/data
import { SyncTenantMetadataCommand } from './sync-tenant-metadata.command';
import { RunTenantMigrationsCommand } from './run-tenant-migrations.command';
import { DataSeedTenantCommand } from './data-seed-tenant.command';
@Module({
imports: [
@ -19,6 +20,10 @@ import { RunTenantMigrationsCommand } from './run-tenant-migrations.command';
DataSourceMetadataModule,
TenantInitialisationModule,
],
providers: [RunTenantMigrationsCommand, SyncTenantMetadataCommand],
providers: [
RunTenantMigrationsCommand,
SyncTenantMetadataCommand,
DataSeedTenantCommand,
],
})
export class MetadataCommandModule {}

View File

@ -1,7 +1,6 @@
import { Command, CommandRunner, Option } from 'nest-commander';
import { ObjectMetadataService } from 'src/metadata/object-metadata/services/object-metadata.service';
import { FieldMetadataService } from 'src/metadata/field-metadata/services/field-metadata.service';
import { TenantInitialisationService } from 'src/metadata/tenant-initialisation/tenant-initialisation.service';
import { DataSourceMetadataService } from 'src/metadata/data-source-metadata/data-source-metadata.service';
@ -17,7 +16,6 @@ interface RunTenantMigrationsOptions {
export class SyncTenantMetadataCommand extends CommandRunner {
constructor(
private readonly objectMetadataService: ObjectMetadataService,
private readonly fieldMetadataService: FieldMetadataService,
private readonly dataSourceMetadataService: DataSourceMetadataService,
private readonly tenantInitialisationService: TenantInitialisationService,
) {

View File

@ -1,4 +1,5 @@
{
"id": "1a8487a0-480c-434e-b4c7-e22408b97047",
"nameSingular": "companyV2",
"namePlural": "companiesV2",
"labelSingular": "Company",

View File

@ -1,7 +1,11 @@
import companyObject from './companies/companies.metadata.json';
import personObject from './people/people.metadata.json';
import viewObject from './views/views.metadata.json';
import viewFieldObject from './view-fields/view-fields.metadata.json';
export const standardObjectsMetadata = {
companyV2: companyObject,
personV2: personObject,
viewV2: viewObject,
viewFieldV2: viewFieldObject,
};

View File

@ -1,5 +1,9 @@
import companySeeds from './companies/companies.seeds.json';
import viewSeeds from './views/views.seeds.json';
import viewFieldSeeds from './view-fields/view-fields.seeds.json';
export const standardObjectsSeeds = {
companyV2: companySeeds,
viewV2: viewSeeds,
viewFieldV2: viewFieldSeeds,
};

View File

@ -0,0 +1,77 @@
{
"nameSingular": "viewFieldV2",
"namePlural": "viewFieldsV2",
"labelSingular": "View Field",
"labelPlural": "View Fields",
"targetTableName": "viewField",
"description": "(System) View Fields",
"icon": "arrows-sort",
"fields": [
{
"type": "text",
"name": "objectId",
"label": "Object Id",
"targetColumnMap": {
"value": "objectId"
},
"description": "View Field target object",
"icon": null,
"isNullable": false
},
{
"type": "text",
"name": "fieldId",
"label": "Field Id",
"targetColumnMap": {
"value": "fieldId"
},
"description": "View Field target field",
"icon": null,
"isNullable": false
},
{
"type": "text",
"name": "viewId",
"label": "View Id",
"targetColumnMap": {
"value": "viewId"
},
"description": "View Field related view",
"icon": null,
"isNullable": false
},
{
"type": "boolean",
"name": "isVisible",
"label": "Visible",
"targetColumnMap": {
"value": "isVisible"
},
"description": "View Field visibility",
"icon": null,
"isNullable": false
},
{
"type": "number",
"name": "size",
"label": "Size",
"targetColumnMap": {
"value": "size"
},
"description": "View Field size",
"icon": null,
"isNullable": false
},
{
"type": "number",
"name": "position",
"label": "Position",
"targetColumnMap": {
"value": "position"
},
"description": "View Field position",
"icon": null,
"isNullable": false
}
]
}

View File

@ -0,0 +1,43 @@
[
{
"objectId": "1a8487a0-480c-434e-b4c7-e22408b97047",
"fieldId": "name",
"viewId": "10bec73c-0aea-4cc4-a3b2-8c2186f29b43",
"position": 0,
"isVisible": true,
"size": 180
},
{
"objectId": "company",
"fieldId": "name",
"viewId": "37a8a866-eb17-4e76-9382-03143a2f6a80",
"position": 0,
"isVisible": true,
"size": 180
},
{
"objectId": "company",
"fieldId": "domainName",
"viewId": "37a8a866-eb17-4e76-9382-03143a2f6a80",
"position": 1,
"isVisible": true,
"size": 100
},
{
"objectId": "company",
"fieldId": "accountOwner",
"viewId": "37a8a866-eb17-4e76-9382-03143a2f6a80",
"position": 2,
"isVisible": true,
"size": 150
},
{
"objectId": "company",
"fieldId": "createdAt",
"viewId": "37a8a866-eb17-4e76-9382-03143a2f6a80",
"position": 3,
"isVisible": true,
"size": 150
}
]

View File

@ -0,0 +1,44 @@
{
"nameSingular": "viewV2",
"namePlural": "viewsV2",
"labelSingular": "View",
"labelPlural": "Views",
"targetTableName": "view",
"description": "(System) Views",
"icon": "layout-collage",
"fields": [
{
"type": "text",
"name": "name",
"label": "Name",
"targetColumnMap": {
"value": "name"
},
"description": "View name",
"icon": null,
"isNullable": false
},
{
"type": "text",
"name": "objectId",
"label": "Object Id",
"targetColumnMap": {
"value": "objectId"
},
"description": "View target object",
"icon": null,
"isNullable": false
},
{
"type": "text",
"name": "type",
"label": "Type",
"targetColumnMap": {
"value": "type"
},
"description": "View type",
"icon": null,
"isNullable": false
}
]
}

View File

@ -0,0 +1,26 @@
[
{
"id": "37a8a866-eb17-4e76-9382-03143a2f6a80",
"name": "All companies",
"objectId": "company",
"type": "Table"
},
{
"id": "6095799e-b48f-4e00-b071-10818083593a",
"name": "All companies",
"objectId": "person",
"type": "Table"
},
{
"id": "e26f66b7-f890-4a5c-b4d2-ec09987b5308",
"name": "All Opportunities",
"objectId": "company",
"type": "Pipeline"
},
{
"id": "10bec73c-0aea-4cc4-a3b2-8c2186f29b43",
"name": "All Companies (V2)",
"objectId": "1a8487a0-480c-434e-b4c7-e22408b97047",
"type": "Table"
}
]

View File

@ -98,7 +98,7 @@ export class TenantInitialisationService {
);
}
private async prefillWorkspaceWithStandardObjects(
public async prefillWorkspaceWithStandardObjects(
dataSourceMetadata: DataSourceMetadata,
workspaceId: string,
) {
@ -117,11 +117,7 @@ export class TenantInitialisationService {
continue;
}
const fields = standardObjectsMetadata[object.nameSingular].fields;
const columns = fields.map((field: FieldMetadata) =>
Object.values(field.targetColumnMap),
);
const columns = Object.keys(seedData[0]);
await workspaceDataSource
?.createQueryBuilder()

View File

@ -0,0 +1,29 @@
import { TenantMigrationTableAction } from 'src/metadata/tenant-migration/tenant-migration.entity';
export const addViewTable: TenantMigrationTableAction[] = [
{
name: 'view',
action: 'create',
},
{
name: 'view',
action: 'alter',
columns: [
{
name: 'name',
type: 'varchar',
action: 'create',
},
{
name: 'objectId',
type: 'varchar',
action: 'create',
},
{
name: 'type',
type: 'varchar',
action: 'create',
},
],
},
];

View File

@ -0,0 +1,44 @@
import { TenantMigrationTableAction } from 'src/metadata/tenant-migration/tenant-migration.entity';
export const addViewFieldTable: TenantMigrationTableAction[] = [
{
name: 'viewField',
action: 'create',
},
{
name: 'viewField',
action: 'alter',
columns: [
{
name: 'objectId',
type: 'varchar',
action: 'create',
},
{
name: 'fieldId',
type: 'varchar',
action: 'create',
},
{
name: 'viewId',
type: 'varchar',
action: 'create',
},
{
name: 'position',
type: 'integer',
action: 'create',
},
{
name: 'isVisible',
type: 'boolean',
action: 'create',
},
{
name: 'size',
type: 'integer',
action: 'create',
},
],
},
];

View File

@ -1,8 +1,12 @@
import { addCompanyTable } from './migrations/1697618009-addCompanyTable';
import { addPeopleTable } from './migrations/1697618010-addPeopleTable';
import { addViewTable } from './migrations/1697618011-addViewTable';
import { addViewFieldTable } from './migrations/1697618012-addViewFieldTable';
// TODO: read the folder and return all migrations
export const standardMigrations = {
'1697618009-addCompanyTable': addCompanyTable,
'1697618010-addPeopleTable': addPeopleTable,
'1697618011-addViewTable': addViewTable,
'1697618012-addViewFieldTable': addViewFieldTable,
};