Deprecate old relations completely (#12482)
# What Fully deprecate old relations because we have one bug tied to it and it make the codebase complex # How I've made this PR: 1. remove metadata datasource (we only keep 'core') => this was causing extra complexity in the refactor + flaky reset 2. merge dev and demo datasets => as I needed to update the tests which is very painful, I don't want to do it twice 3. remove all code tied to RELATION_METADATA / relation-metadata.resolver, or anything tied to the old relation system 4. Remove ONE_TO_ONE and MANY_TO_MANY that are not supported 5. fix impacts on the different areas : see functional testing below # Functional testing ## Functional testing from the front-end: 1. Database Reset ✅ 2. Sign In ✅ 3. Workspace sign-up ✅ 5. Browsing table / kanban / show ✅ 6. Assigning a record in a one to many / in a many to one ✅ 7. Deleting a record involved in a relation ✅ => broken but not tied to this PR 8. "Add new" from relation picker ✅ => broken but not tied to this PR 9. Creating a Task / Note, Updating a Task / Note relations, Deleting a Task / Note (from table, show page, right drawer) ✅ => broken but not tied to this PR 10. creating a relation from settings (custom / standard x oneToMany / manyToOne) ✅ 11. updating a relation from settings should not be possible ✅ 12. deleting a relation from settings (custom / standard x oneToMany / manyToOne) ✅ 13. Make sure timeline activity still work (relation were involved there), espacially with Task / Note => to be double checked ✅ => Cannot convert undefined or null to object 14. Workspace deletion / User deletion ✅ 15. CSV Import should keep working ✅ 16. Permissions: I have tested without permissions V2 as it's still hard to test v2 work and it's not in prod yet ✅ 17. Workflows global test ✅ ## From the API: 1. Review open-api documentation (REST) ✅ 2. Make sure REST Api are still able to fetch relations ==> won't do, we have a coupling Get/Update/Create there, this requires refactoring 3. Make sure REST Api is still able to update / remove relation => won't do same ## Automated tests 1. lint + typescript ✅ 2. front unit tests: ✅ 3. server unit tests 2 ✅ 4. front stories: ✅ 5. server integration: ✅ 6. chromatic check : expected 0 7. e2e check : expected no more that current failures ## Remove // Todos 1. All are captured by functional tests above, nothing additional to do ## (Un)related regressions 1. Table loading state is not working anymore, we see the empty state before table content 2. Filtering by Creator Tim Ap return empty results 3. Not possible to add Tasks / Notes / Files from show page # Result ## New seeds that can be easily extended <img width="1920" alt="image" src="https://github.com/user-attachments/assets/d290d130-2a5f-44e6-b419-7e42a89eec4b" /> ## -5k lines of code ## No more 'metadata' dataSource (we only have 'core) ## No more relationMetadata (I haven't drop the table yet it's not referenced in the code anymore) ## We are ready to fix the 6 months lag between current API results and our mocked tests ## No more bug on relation creation / deletion --------- Co-authored-by: Weiko <corentin@twenty.com> Co-authored-by: Félix Malfait <felix@twenty.com>
This commit is contained in:
@ -12,14 +12,12 @@ import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service';
|
||||
import { PermissionsService } from 'src/engine/metadata-modules/permissions/permissions.service';
|
||||
import { RelationMetadataEntity } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity';
|
||||
import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
|
||||
import { RoleService } from 'src/engine/metadata-modules/role/role.service';
|
||||
import { UserWorkspaceRoleEntity } from 'src/engine/metadata-modules/role/user-workspace-role.entity';
|
||||
import { UserRoleService } from 'src/engine/metadata-modules/user-role/user-role.service';
|
||||
import { WorkspaceMigrationEntity } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.entity';
|
||||
import { WorkspaceMigrationService } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.service';
|
||||
import { SeederService } from 'src/engine/seeder/seeder.service';
|
||||
import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service';
|
||||
import { WorkspaceManagerService } from 'src/engine/workspace-manager/workspace-manager.service';
|
||||
import { WorkspaceSyncMetadataService } from 'src/engine/workspace-manager/workspace-sync-metadata/workspace-sync-metadata.service';
|
||||
@ -29,7 +27,6 @@ describe('WorkspaceManagerService', () => {
|
||||
let objectMetadataService: ObjectMetadataService;
|
||||
let workspaceMigrationRepository: Repository<WorkspaceMigrationEntity>;
|
||||
let dataSourceRepository: Repository<DataSourceEntity>;
|
||||
let workspaceRelationMetadataRepository: Repository<RelationMetadataEntity>;
|
||||
let workspaceFieldMetadataRepository: Repository<FieldMetadataEntity>;
|
||||
let workspaceDataSourceService: WorkspaceDataSourceService;
|
||||
let userWorkspaceRoleRepository: Repository<UserWorkspaceRoleEntity>;
|
||||
@ -50,43 +47,37 @@ describe('WorkspaceManagerService', () => {
|
||||
useValue: {},
|
||||
},
|
||||
{
|
||||
provide: getRepositoryToken(FieldMetadataEntity, 'metadata'),
|
||||
provide: getRepositoryToken(FieldMetadataEntity, 'core'),
|
||||
useValue: {
|
||||
delete: jest.fn(),
|
||||
},
|
||||
},
|
||||
{
|
||||
provide: getRepositoryToken(RelationMetadataEntity, 'metadata'),
|
||||
provide: getRepositoryToken(ObjectMetadataEntity, 'core'),
|
||||
useValue: {
|
||||
delete: jest.fn(),
|
||||
},
|
||||
},
|
||||
{
|
||||
provide: getRepositoryToken(ObjectMetadataEntity, 'metadata'),
|
||||
provide: getRepositoryToken(WorkspaceMigrationEntity, 'core'),
|
||||
useValue: {
|
||||
delete: jest.fn(),
|
||||
},
|
||||
},
|
||||
{
|
||||
provide: getRepositoryToken(WorkspaceMigrationEntity, 'metadata'),
|
||||
provide: getRepositoryToken(DataSourceEntity, 'core'),
|
||||
useValue: {
|
||||
delete: jest.fn(),
|
||||
},
|
||||
},
|
||||
{
|
||||
provide: getRepositoryToken(DataSourceEntity, 'metadata'),
|
||||
provide: getRepositoryToken(UserWorkspaceRoleEntity, 'core'),
|
||||
useValue: {
|
||||
delete: jest.fn(),
|
||||
},
|
||||
},
|
||||
{
|
||||
provide: getRepositoryToken(UserWorkspaceRoleEntity, 'metadata'),
|
||||
useValue: {
|
||||
delete: jest.fn(),
|
||||
},
|
||||
},
|
||||
{
|
||||
provide: getRepositoryToken(RoleEntity, 'metadata'),
|
||||
provide: getRepositoryToken(RoleEntity, 'core'),
|
||||
useValue: {
|
||||
delete: jest.fn(),
|
||||
},
|
||||
@ -117,10 +108,7 @@ describe('WorkspaceManagerService', () => {
|
||||
provide: WorkspaceSyncMetadataService,
|
||||
useValue: {},
|
||||
},
|
||||
{
|
||||
provide: SeederService,
|
||||
useValue: {},
|
||||
},
|
||||
|
||||
{
|
||||
provide: ObjectMetadataService,
|
||||
useValue: {
|
||||
@ -136,24 +124,21 @@ describe('WorkspaceManagerService', () => {
|
||||
);
|
||||
workspaceMigrationRepository = module.get<
|
||||
Repository<WorkspaceMigrationEntity>
|
||||
>(getRepositoryToken(WorkspaceMigrationEntity, 'metadata'));
|
||||
>(getRepositoryToken(WorkspaceMigrationEntity, 'core'));
|
||||
dataSourceRepository = module.get<Repository<DataSourceEntity>>(
|
||||
getRepositoryToken(DataSourceEntity, 'metadata'),
|
||||
getRepositoryToken(DataSourceEntity, 'core'),
|
||||
);
|
||||
workspaceRelationMetadataRepository = module.get<
|
||||
Repository<RelationMetadataEntity>
|
||||
>(getRepositoryToken(RelationMetadataEntity, 'metadata'));
|
||||
workspaceFieldMetadataRepository = module.get<
|
||||
Repository<FieldMetadataEntity>
|
||||
>(getRepositoryToken(FieldMetadataEntity, 'metadata'));
|
||||
>(getRepositoryToken(FieldMetadataEntity, 'core'));
|
||||
workspaceDataSourceService = module.get<WorkspaceDataSourceService>(
|
||||
WorkspaceDataSourceService,
|
||||
);
|
||||
userWorkspaceRoleRepository = module.get<
|
||||
Repository<UserWorkspaceRoleEntity>
|
||||
>(getRepositoryToken(UserWorkspaceRoleEntity, 'metadata'));
|
||||
>(getRepositoryToken(UserWorkspaceRoleEntity, 'core'));
|
||||
roleRepository = module.get<Repository<RoleEntity>>(
|
||||
getRepositoryToken(RoleEntity, 'metadata'),
|
||||
getRepositoryToken(RoleEntity, 'core'),
|
||||
);
|
||||
});
|
||||
|
||||
@ -165,9 +150,6 @@ describe('WorkspaceManagerService', () => {
|
||||
it('should delete all the workspace metadata tables and workspace schema', async () => {
|
||||
await service.delete('workspace-id');
|
||||
expect(objectMetadataService.deleteObjectsMetadata).toHaveBeenCalled();
|
||||
expect(workspaceRelationMetadataRepository.delete).toHaveBeenCalledWith({
|
||||
workspaceId: 'workspace-id',
|
||||
});
|
||||
expect(workspaceFieldMetadataRepository.delete).toHaveBeenCalledWith({
|
||||
workspaceId: 'workspace-id',
|
||||
});
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,31 +0,0 @@
|
||||
|
||||
import { WorkspaceEntityManager } from 'src/engine/twenty-orm/entity-manager/workspace-entity-manager';
|
||||
import { COMPANIES_DEMO } from 'src/engine/workspace-manager/demo-objects-prefill-data/companies-demo.json';
|
||||
|
||||
export const seedCompanyWithDemoData = async (
|
||||
entityManager: WorkspaceEntityManager,
|
||||
schemaName: string,
|
||||
) => {
|
||||
await entityManager
|
||||
.createQueryBuilder(undefined, undefined, undefined, {
|
||||
shouldBypassPermissionChecks: true,
|
||||
})
|
||||
.insert()
|
||||
.into(`${schemaName}.company`, [
|
||||
'name',
|
||||
'domainNamePrimaryLinkUrl',
|
||||
'addressAddressCity',
|
||||
'employees',
|
||||
'linkedinLinkPrimaryLinkUrl',
|
||||
'createdBySource',
|
||||
'createdByWorkspaceMemberId',
|
||||
'createdByName',
|
||||
'position'
|
||||
])
|
||||
.orIgnore()
|
||||
.values(
|
||||
COMPANIES_DEMO.map((company, index) => ({ ...company, position: index })),
|
||||
)
|
||||
.returning('*')
|
||||
.execute();
|
||||
};
|
||||
@ -1,78 +0,0 @@
|
||||
import { WorkspaceEntityManager } from 'src/engine/twenty-orm/entity-manager/workspace-entity-manager';
|
||||
import { DEMO_SEED_WORKSPACE_MEMBER_IDS } from 'src/engine/workspace-manager/demo-objects-prefill-data/seed-workspace-member-with-demo-data';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
const tableName = 'opportunity';
|
||||
|
||||
const getRandomStage = () => {
|
||||
const stages = ['NEW', 'SCREENING', 'MEETING', 'PROPOSAL', 'CUSTOMER'];
|
||||
|
||||
return stages[Math.floor(Math.random() * stages.length)];
|
||||
};
|
||||
|
||||
const generateRandomAmountMicros = () => {
|
||||
const firstDigit = Math.floor(Math.random() * 9) + 1;
|
||||
|
||||
return firstDigit * 10000000000;
|
||||
};
|
||||
|
||||
// @ts-expect-error legacy noImplicitAny
|
||||
const generateOpportunities = (companies) => {
|
||||
// @ts-expect-error legacy noImplicitAny
|
||||
return companies.map((company) => ({
|
||||
id: v4(),
|
||||
name: company.name,
|
||||
amountAmountMicros: generateRandomAmountMicros(),
|
||||
amountCurrencyCode: 'USD',
|
||||
closeDate: new Date(),
|
||||
stage: getRandomStage(),
|
||||
pointOfContactId: company.personId,
|
||||
companyId: company.id,
|
||||
createdBySource: 'MANUAL',
|
||||
createdByWorkspaceMemberId: DEMO_SEED_WORKSPACE_MEMBER_IDS.NOAH,
|
||||
createdByName: 'Noah A',
|
||||
}));
|
||||
};
|
||||
|
||||
export const seedOpportunityWithDemoData = async (
|
||||
entityManager: WorkspaceEntityManager,
|
||||
schemaName: string,
|
||||
) => {
|
||||
const companiesWithPeople = await entityManager?.query(
|
||||
`SELECT company.*, person.id AS "personId"
|
||||
FROM ${schemaName}.company
|
||||
LEFT JOIN ${schemaName}.person ON company.id = "person"."companyId"
|
||||
LIMIT 50`,
|
||||
);
|
||||
|
||||
const opportunities = generateOpportunities(companiesWithPeople);
|
||||
|
||||
await entityManager
|
||||
.createQueryBuilder(undefined, undefined, undefined, {
|
||||
shouldBypassPermissionChecks: true,
|
||||
})
|
||||
.insert()
|
||||
.into(`${schemaName}.${tableName}`, [
|
||||
'id',
|
||||
'name',
|
||||
'amountAmountMicros',
|
||||
'amountCurrencyCode',
|
||||
'closeDate',
|
||||
'stage',
|
||||
'pointOfContactId',
|
||||
'companyId',
|
||||
'createdBySource',
|
||||
'createdByWorkspaceMemberId',
|
||||
'createdByName',
|
||||
'position',
|
||||
])
|
||||
.orIgnore()
|
||||
.values(
|
||||
// @ts-expect-error legacy noImplicitAny
|
||||
opportunities.map((opportunity, index) => ({
|
||||
...opportunity,
|
||||
position: index,
|
||||
})),
|
||||
)
|
||||
.execute();
|
||||
};
|
||||
@ -1,52 +0,0 @@
|
||||
|
||||
import { WorkspaceEntityManager } from 'src/engine/twenty-orm/entity-manager/workspace-entity-manager';
|
||||
import { peopleDemo } from 'src/engine/workspace-manager/demo-objects-prefill-data/people-demo.json';
|
||||
|
||||
export const seedPersonWithDemoData = async (
|
||||
entityManager: WorkspaceEntityManager,
|
||||
schemaName: string,
|
||||
) => {
|
||||
const companies = await entityManager?.query(
|
||||
`SELECT * FROM ${schemaName}.company`,
|
||||
);
|
||||
|
||||
// Iterate through the array and add a UUID for each person
|
||||
const people = peopleDemo.map((person, index) => ({
|
||||
nameFirstName: person.firstName,
|
||||
nameLastName: person.lastName,
|
||||
emailsPrimaryEmail: person.email,
|
||||
linkedinLinkPrimaryLinkUrl: person.linkedinUrl,
|
||||
jobTitle: person.jobTitle,
|
||||
city: person.city,
|
||||
avatarUrl: person.avatarUrl,
|
||||
companyId: companies[Math.floor(index / 2)].id,
|
||||
createdBySource: person.createdBySource,
|
||||
createdByWorkspaceMemberId: person.createdByWorkspaceMemberId,
|
||||
createdByName: person.createdByName,
|
||||
position: index
|
||||
}));
|
||||
|
||||
await entityManager
|
||||
.createQueryBuilder(undefined, undefined, undefined, {
|
||||
shouldBypassPermissionChecks: true,
|
||||
})
|
||||
.insert()
|
||||
.into(`${schemaName}.person`, [
|
||||
'nameFirstName',
|
||||
'nameLastName',
|
||||
'emailsPrimaryEmail',
|
||||
'linkedinLinkPrimaryLinkUrl',
|
||||
'jobTitle',
|
||||
'city',
|
||||
'avatarUrl',
|
||||
'companyId',
|
||||
'createdBySource',
|
||||
'createdByWorkspaceMemberId',
|
||||
'createdByName',
|
||||
'position',
|
||||
])
|
||||
.orIgnore()
|
||||
.values(people)
|
||||
.returning('*')
|
||||
.execute();
|
||||
};
|
||||
@ -1,61 +0,0 @@
|
||||
|
||||
import { DEMO_SEED_USER_IDS } from 'src/database/typeorm-seeds/core/demo/users';
|
||||
import { WorkspaceEntityManager } from 'src/engine/twenty-orm/entity-manager/workspace-entity-manager';
|
||||
import { SOURCE_LOCALE } from 'twenty-shared/translations';
|
||||
|
||||
export const DEMO_SEED_WORKSPACE_MEMBER_IDS = {
|
||||
NOAH: '20202020-0687-4c41-b707-ed1bfca972a2',
|
||||
HUGO: '20202020-77d5-4cb6-b60a-f4a835a85d62',
|
||||
TIM: '20202020-1553-45c6-a028-5a9064cce07e',
|
||||
};
|
||||
|
||||
export const seedWorkspaceMemberWithDemoData = async (
|
||||
entityManager: WorkspaceEntityManager,
|
||||
schemaName: string,
|
||||
) => {
|
||||
await entityManager
|
||||
.createQueryBuilder(undefined, undefined, undefined, {
|
||||
shouldBypassPermissionChecks: true,
|
||||
})
|
||||
.insert()
|
||||
.into(`${schemaName}.workspaceMember`, [
|
||||
'id',
|
||||
'nameFirstName',
|
||||
'nameLastName',
|
||||
'locale',
|
||||
'colorScheme',
|
||||
'userEmail',
|
||||
'userId',
|
||||
])
|
||||
.orIgnore()
|
||||
.values([
|
||||
{
|
||||
id: DEMO_SEED_WORKSPACE_MEMBER_IDS.NOAH,
|
||||
nameFirstName: 'Noah',
|
||||
nameLastName: 'A',
|
||||
locale: SOURCE_LOCALE,
|
||||
colorScheme: 'Light',
|
||||
userEmail: 'noah@demo.dev',
|
||||
userId: DEMO_SEED_USER_IDS.NOAH,
|
||||
},
|
||||
{
|
||||
id: DEMO_SEED_WORKSPACE_MEMBER_IDS.HUGO,
|
||||
nameFirstName: 'Hugo',
|
||||
nameLastName: 'I',
|
||||
locale: SOURCE_LOCALE,
|
||||
colorScheme: 'Light',
|
||||
userEmail: 'hugo@demo.dev',
|
||||
userId: DEMO_SEED_USER_IDS.HUGO,
|
||||
},
|
||||
{
|
||||
id: DEMO_SEED_WORKSPACE_MEMBER_IDS.TIM,
|
||||
nameFirstName: 'Tim',
|
||||
nameLastName: 'Apple',
|
||||
locale: SOURCE_LOCALE,
|
||||
colorScheme: 'Light',
|
||||
userEmail: 'tim@apple.dev',
|
||||
userId: DEMO_SEED_USER_IDS.TIM,
|
||||
},
|
||||
])
|
||||
.execute();
|
||||
};
|
||||
@ -1,55 +0,0 @@
|
||||
import { DataSource } from 'typeorm';
|
||||
|
||||
import { seedWorkspaceFavorites } from 'src/database/typeorm-seeds/workspace/favorites';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { WorkspaceEntityManager } from 'src/engine/twenty-orm/entity-manager/workspace-entity-manager';
|
||||
import { shouldSeedWorkspaceFavorite } from 'src/engine/utils/should-seed-workspace-favorite';
|
||||
import { seedCompanyWithDemoData } from 'src/engine/workspace-manager/demo-objects-prefill-data/seed-company-with-demo-data';
|
||||
import { seedOpportunityWithDemoData } from 'src/engine/workspace-manager/demo-objects-prefill-data/seed-opportunity-with-demo-data';
|
||||
import { seedPersonWithDemoData } from 'src/engine/workspace-manager/demo-objects-prefill-data/seed-person-with-demo-data';
|
||||
import { seedWorkspaceMemberWithDemoData } from 'src/engine/workspace-manager/demo-objects-prefill-data/seed-workspace-member-with-demo-data';
|
||||
import { seedViewWithDemoData } from 'src/engine/workspace-manager/standard-objects-prefill-data/seed-view-with-demo-data';
|
||||
|
||||
export const seedWorkspaceWithDemoData = async (
|
||||
workspaceDataSource: DataSource,
|
||||
schemaName: string,
|
||||
objectMetadata: ObjectMetadataEntity[],
|
||||
) => {
|
||||
const objectMetadataMap = objectMetadata.reduce((acc, object) => {
|
||||
// @ts-expect-error legacy noImplicitAny
|
||||
acc[object.standardId ?? ''] = {
|
||||
id: object.id,
|
||||
fields: object.fields.reduce((acc, field) => {
|
||||
// @ts-expect-error legacy noImplicitAny
|
||||
acc[field.standardId ?? ''] = field.id;
|
||||
|
||||
return acc;
|
||||
}, {}),
|
||||
};
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
await workspaceDataSource.transaction(
|
||||
async (entityManager: WorkspaceEntityManager) => {
|
||||
await seedCompanyWithDemoData(entityManager, schemaName);
|
||||
await seedPersonWithDemoData(entityManager, schemaName);
|
||||
await seedOpportunityWithDemoData(entityManager, schemaName);
|
||||
|
||||
const viewDefinitionsWithId = await seedViewWithDemoData(
|
||||
entityManager,
|
||||
schemaName,
|
||||
objectMetadataMap,
|
||||
);
|
||||
|
||||
await seedWorkspaceFavorites(
|
||||
viewDefinitionsWithId
|
||||
.filter((view) => view.key === 'INDEX' && shouldSeedWorkspaceFavorite(view.objectMetadataId, objectMetadataMap))
|
||||
.map((view) => view.id),
|
||||
entityManager,
|
||||
schemaName,
|
||||
);
|
||||
await seedWorkspaceMemberWithDemoData(entityManager, schemaName);
|
||||
},
|
||||
);
|
||||
};
|
||||
@ -0,0 +1,33 @@
|
||||
import { DataSource } from 'typeorm';
|
||||
|
||||
const tableName = 'billingSubscription';
|
||||
|
||||
export const seedBillingSubscriptions = async (
|
||||
dataSource: DataSource,
|
||||
schemaName: string,
|
||||
workspaceId: string,
|
||||
) => {
|
||||
await dataSource
|
||||
.createQueryBuilder()
|
||||
.insert()
|
||||
.into(`${schemaName}.${tableName}`, [
|
||||
'workspaceId',
|
||||
'stripeCustomerId',
|
||||
'stripeSubscriptionId',
|
||||
'status',
|
||||
'metadata',
|
||||
])
|
||||
.orIgnore()
|
||||
.values([
|
||||
{
|
||||
workspaceId,
|
||||
stripeCustomerId: 'cus_default0',
|
||||
stripeSubscriptionId: 'sub_default0',
|
||||
status: 'active',
|
||||
metadata: {
|
||||
workspaceId,
|
||||
},
|
||||
},
|
||||
])
|
||||
.execute();
|
||||
};
|
||||
@ -0,0 +1,78 @@
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { WorkspaceActivationStatus } from 'twenty-shared/workspace';
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { RoleService } from 'src/engine/metadata-modules/role/role.service';
|
||||
import { UserRoleService } from 'src/engine/metadata-modules/user-role/user-role.service';
|
||||
import { USER_WORKSPACE_DATA_SEED_IDS } from 'src/engine/workspace-manager/dev-seeder/core/utils/seed-user-workspaces.util';
|
||||
import {
|
||||
SEED_ACME_WORKSPACE_ID,
|
||||
SEED_APPLE_WORKSPACE_ID,
|
||||
} from 'src/engine/workspace-manager/dev-seeder/core/utils/seed-workspaces.util';
|
||||
|
||||
@Injectable()
|
||||
export class DevSeederPermissionsService {
|
||||
private readonly logger = new Logger(DevSeederPermissionsService.name);
|
||||
|
||||
constructor(
|
||||
private readonly roleService: RoleService,
|
||||
private readonly userRoleService: UserRoleService,
|
||||
@InjectRepository(Workspace, 'core')
|
||||
private readonly workspaceRepository: Repository<Workspace>,
|
||||
) {}
|
||||
|
||||
public async initPermissions(workspaceId: string) {
|
||||
const adminRole = await this.roleService.createAdminRole({
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
let adminUserWorkspaceId: string | undefined;
|
||||
let memberUserWorkspaceId: string | undefined;
|
||||
|
||||
if (workspaceId === SEED_APPLE_WORKSPACE_ID) {
|
||||
adminUserWorkspaceId = USER_WORKSPACE_DATA_SEED_IDS.TIM;
|
||||
memberUserWorkspaceId = USER_WORKSPACE_DATA_SEED_IDS.JONY;
|
||||
|
||||
// Create guest role only in this workspace
|
||||
const guestRole = await this.roleService.createGuestRole({
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
await this.userRoleService.assignRoleToUserWorkspace({
|
||||
workspaceId,
|
||||
userWorkspaceId: USER_WORKSPACE_DATA_SEED_IDS.PHIL,
|
||||
roleId: guestRole.id,
|
||||
});
|
||||
} else if (workspaceId === SEED_ACME_WORKSPACE_ID) {
|
||||
adminUserWorkspaceId = USER_WORKSPACE_DATA_SEED_IDS.TIM_ACME;
|
||||
}
|
||||
|
||||
if (adminUserWorkspaceId) {
|
||||
await this.userRoleService.assignRoleToUserWorkspace({
|
||||
workspaceId,
|
||||
userWorkspaceId: adminUserWorkspaceId,
|
||||
roleId: adminRole.id,
|
||||
});
|
||||
}
|
||||
|
||||
const memberRole = await this.roleService.createMemberRole({
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
await this.workspaceRepository.update(workspaceId, {
|
||||
defaultRoleId: memberRole.id,
|
||||
activationStatus: WorkspaceActivationStatus.ACTIVE,
|
||||
});
|
||||
|
||||
if (memberUserWorkspaceId) {
|
||||
await this.userRoleService.assignRoleToUserWorkspace({
|
||||
workspaceId,
|
||||
userWorkspaceId: memberUserWorkspaceId,
|
||||
roleId: memberRole.id,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
import { DataSource } from 'typeorm';
|
||||
|
||||
import { seedBillingSubscriptions } from 'src/engine/workspace-manager/dev-seeder/core/billing/utils/seed-billing-subscriptions.util';
|
||||
import { seedFeatureFlags } from 'src/engine/workspace-manager/dev-seeder/core/utils/seed-feature-flags.util';
|
||||
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 { seedWorkspaces } from 'src/engine/workspace-manager/dev-seeder/core/utils/seed-workspaces.util';
|
||||
|
||||
type SeedCoreSchemaArgs = {
|
||||
dataSource: DataSource;
|
||||
workspaceId: string;
|
||||
appVersion: string | undefined;
|
||||
seedBilling?: boolean;
|
||||
seedFeatureFlags?: boolean;
|
||||
};
|
||||
|
||||
export const seedCoreSchema = async ({
|
||||
appVersion,
|
||||
dataSource,
|
||||
workspaceId,
|
||||
seedBilling = true,
|
||||
seedFeatureFlags: shouldSeedFeatureFlags = true,
|
||||
}: SeedCoreSchemaArgs) => {
|
||||
const schemaName = 'core';
|
||||
|
||||
await seedWorkspaces({
|
||||
dataSource,
|
||||
schemaName,
|
||||
workspaceId,
|
||||
appVersion,
|
||||
});
|
||||
await seedUsers(dataSource, schemaName);
|
||||
await seedUserWorkspaces(dataSource, schemaName, workspaceId);
|
||||
|
||||
if (shouldSeedFeatureFlags) {
|
||||
await seedFeatureFlags(dataSource, schemaName, workspaceId);
|
||||
}
|
||||
|
||||
if (seedBilling) {
|
||||
await seedBillingSubscriptions(dataSource, schemaName, workspaceId);
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,63 @@
|
||||
import { DataSource } from 'typeorm';
|
||||
|
||||
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||
|
||||
const tableName = 'featureFlag';
|
||||
|
||||
export const seedFeatureFlags = async (
|
||||
dataSource: DataSource,
|
||||
schemaName: string,
|
||||
workspaceId: string,
|
||||
) => {
|
||||
await dataSource
|
||||
.createQueryBuilder()
|
||||
.insert()
|
||||
.into(`${schemaName}.${tableName}`, ['key', 'workspaceId', 'value'])
|
||||
.orIgnore()
|
||||
.values([
|
||||
{
|
||||
key: FeatureFlagKey.IS_AIRTABLE_INTEGRATION_ENABLED,
|
||||
workspaceId: workspaceId,
|
||||
value: true,
|
||||
},
|
||||
{
|
||||
key: FeatureFlagKey.IS_POSTGRESQL_INTEGRATION_ENABLED,
|
||||
workspaceId: workspaceId,
|
||||
value: true,
|
||||
},
|
||||
{
|
||||
key: FeatureFlagKey.IS_STRIPE_INTEGRATION_ENABLED,
|
||||
workspaceId: workspaceId,
|
||||
value: true,
|
||||
},
|
||||
{
|
||||
key: FeatureFlagKey.IS_WORKFLOW_ENABLED,
|
||||
workspaceId: workspaceId,
|
||||
value: true,
|
||||
},
|
||||
{
|
||||
key: FeatureFlagKey.IS_UNIQUE_INDEXES_ENABLED,
|
||||
workspaceId: workspaceId,
|
||||
value: false,
|
||||
},
|
||||
{
|
||||
key: FeatureFlagKey.IS_AI_ENABLED,
|
||||
workspaceId: workspaceId,
|
||||
value: true,
|
||||
},
|
||||
])
|
||||
.execute();
|
||||
};
|
||||
|
||||
export const deleteFeatureFlags = async (
|
||||
dataSource: DataSource,
|
||||
schemaName: string,
|
||||
workspaceId: string,
|
||||
) => {
|
||||
await dataSource
|
||||
.createQueryBuilder()
|
||||
.delete()
|
||||
.from(`${schemaName}.${tableName}`)
|
||||
.where(`"${tableName}"."workspaceId" = :workspaceId`, { workspaceId })
|
||||
.execute();
|
||||
};
|
||||
@ -0,0 +1,90 @@
|
||||
import { DataSource } from 'typeorm';
|
||||
|
||||
import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity';
|
||||
import { USER_DATA_SEED_IDS } from 'src/engine/workspace-manager/dev-seeder/core/utils/seed-users.util';
|
||||
import {
|
||||
SEED_ACME_WORKSPACE_ID,
|
||||
SEED_APPLE_WORKSPACE_ID,
|
||||
} from 'src/engine/workspace-manager/dev-seeder/core/utils/seed-workspaces.util';
|
||||
|
||||
const tableName = 'userWorkspace';
|
||||
|
||||
export const USER_WORKSPACE_DATA_SEED_IDS = {
|
||||
TIM: '20202020-9e3b-46d4-a556-88b9ddc2b035',
|
||||
JONY: '20202020-3957-4908-9c36-2929a23f8353',
|
||||
PHIL: '20202020-7169-42cf-bc47-1cfef15264b1',
|
||||
TIM_ACME: '20202020-e10a-4c27-a90b-b08c57b02d44',
|
||||
JONY_ACME: '20202020-e10a-4c27-a90b-b08c57b02d45',
|
||||
PHIL_ACME: '20202020-e10a-4c27-a90b-b08c57b02d46',
|
||||
};
|
||||
|
||||
export const seedUserWorkspaces = async (
|
||||
dataSource: DataSource,
|
||||
schemaName: string,
|
||||
workspaceId: string,
|
||||
) => {
|
||||
let userWorkspaces: Pick<UserWorkspace, 'id' | 'userId' | 'workspaceId'>[] =
|
||||
[];
|
||||
|
||||
if (workspaceId === SEED_APPLE_WORKSPACE_ID) {
|
||||
userWorkspaces = [
|
||||
{
|
||||
id: USER_WORKSPACE_DATA_SEED_IDS.TIM,
|
||||
userId: USER_DATA_SEED_IDS.TIM,
|
||||
workspaceId,
|
||||
},
|
||||
{
|
||||
id: USER_WORKSPACE_DATA_SEED_IDS.JONY,
|
||||
userId: USER_DATA_SEED_IDS.JONY,
|
||||
workspaceId,
|
||||
},
|
||||
{
|
||||
id: USER_WORKSPACE_DATA_SEED_IDS.PHIL,
|
||||
userId: USER_DATA_SEED_IDS.PHIL,
|
||||
workspaceId,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
if (workspaceId === SEED_ACME_WORKSPACE_ID) {
|
||||
userWorkspaces = [
|
||||
{
|
||||
id: USER_WORKSPACE_DATA_SEED_IDS.TIM_ACME,
|
||||
userId: USER_DATA_SEED_IDS.TIM,
|
||||
workspaceId,
|
||||
},
|
||||
{
|
||||
id: USER_WORKSPACE_DATA_SEED_IDS.JONY_ACME,
|
||||
userId: USER_DATA_SEED_IDS.JONY,
|
||||
workspaceId,
|
||||
},
|
||||
{
|
||||
id: USER_WORKSPACE_DATA_SEED_IDS.PHIL_ACME,
|
||||
userId: USER_DATA_SEED_IDS.PHIL,
|
||||
workspaceId,
|
||||
},
|
||||
];
|
||||
}
|
||||
await dataSource
|
||||
.createQueryBuilder()
|
||||
.insert()
|
||||
.into(`${schemaName}.${tableName}`, ['id', 'userId', 'workspaceId'])
|
||||
.orIgnore()
|
||||
.values(userWorkspaces)
|
||||
.execute();
|
||||
};
|
||||
|
||||
export const deleteUserWorkspaces = async (
|
||||
dataSource: DataSource,
|
||||
schemaName: string,
|
||||
workspaceId: string,
|
||||
) => {
|
||||
await dataSource
|
||||
.createQueryBuilder()
|
||||
.delete()
|
||||
.from(`${schemaName}.${tableName}`)
|
||||
.where(`"${tableName}"."workspaceId" = :workspaceId`, {
|
||||
workspaceId,
|
||||
})
|
||||
.execute();
|
||||
};
|
||||
@ -0,0 +1,62 @@
|
||||
import { DataSource } from 'typeorm';
|
||||
|
||||
const tableName = 'user';
|
||||
|
||||
export const USER_DATA_SEED_IDS = {
|
||||
TIM: '20202020-9e3b-46d4-a556-88b9ddc2b034',
|
||||
JONY: '20202020-3957-4908-9c36-2929a23f8357',
|
||||
PHIL: '20202020-7169-42cf-bc47-1cfef15264b8',
|
||||
};
|
||||
|
||||
export const seedUsers = async (dataSource: DataSource, schemaName: string) => {
|
||||
await dataSource
|
||||
.createQueryBuilder()
|
||||
.insert()
|
||||
.into(`${schemaName}.${tableName}`, [
|
||||
'id',
|
||||
'firstName',
|
||||
'lastName',
|
||||
'email',
|
||||
'passwordHash',
|
||||
'canImpersonate',
|
||||
'canAccessFullAdminPanel',
|
||||
'isEmailVerified',
|
||||
])
|
||||
.orIgnore()
|
||||
.values([
|
||||
{
|
||||
id: USER_DATA_SEED_IDS.TIM,
|
||||
firstName: 'Tim',
|
||||
lastName: 'Apple',
|
||||
email: 'tim@apple.dev',
|
||||
passwordHash:
|
||||
'$2b$10$3LwXjJRtLsfx4hLuuXhxt.3mWgismTiZFCZSG3z9kDrSfsrBl0fT6', // tim@apple.dev
|
||||
canImpersonate: true,
|
||||
canAccessFullAdminPanel: true,
|
||||
isEmailVerified: true,
|
||||
},
|
||||
{
|
||||
id: USER_DATA_SEED_IDS.JONY,
|
||||
firstName: 'Jony',
|
||||
lastName: 'Ive',
|
||||
email: 'jony.ive@apple.dev',
|
||||
passwordHash:
|
||||
'$2b$10$3LwXjJRtLsfx4hLuuXhxt.3mWgismTiZFCZSG3z9kDrSfsrBl0fT6', // tim@apple.dev
|
||||
canImpersonate: true,
|
||||
canAccessFullAdminPanel: true,
|
||||
isEmailVerified: true,
|
||||
},
|
||||
{
|
||||
id: USER_DATA_SEED_IDS.PHIL,
|
||||
firstName: 'Phil',
|
||||
lastName: 'Schiler',
|
||||
email: 'phil.schiler@apple.dev',
|
||||
passwordHash:
|
||||
'$2b$10$3LwXjJRtLsfx4hLuuXhxt.3mWgismTiZFCZSG3z9kDrSfsrBl0fT6', // tim@apple.dev
|
||||
canImpersonate: true,
|
||||
canAccessFullAdminPanel: true,
|
||||
isEmailVerified: true,
|
||||
},
|
||||
])
|
||||
.execute();
|
||||
};
|
||||
@ -0,0 +1,83 @@
|
||||
import { WorkspaceActivationStatus } from 'twenty-shared/workspace';
|
||||
import { DataSource } from 'typeorm';
|
||||
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { extractVersionMajorMinorPatch } from 'src/utils/version/extract-version-major-minor-patch';
|
||||
|
||||
const tableName = 'workspace';
|
||||
|
||||
export const SEED_APPLE_WORKSPACE_ID = '20202020-1c25-4d02-bf25-6aeccf7ea419';
|
||||
export const SEED_ACME_WORKSPACE_ID = '3b8e6458-5fc1-4e63-8563-008ccddaa6db';
|
||||
|
||||
export type SeedWorkspaceArgs = {
|
||||
dataSource: DataSource;
|
||||
schemaName: string;
|
||||
workspaceId: string;
|
||||
appVersion: string | undefined;
|
||||
};
|
||||
|
||||
const workspaceSeederFields = [
|
||||
'id',
|
||||
'displayName',
|
||||
'subdomain',
|
||||
'inviteHash',
|
||||
'logo',
|
||||
'activationStatus',
|
||||
'version',
|
||||
] as const satisfies (keyof Workspace)[];
|
||||
|
||||
type WorkspaceSeederFields = Pick<
|
||||
Workspace,
|
||||
(typeof workspaceSeederFields)[number]
|
||||
>;
|
||||
|
||||
export const seedWorkspaces = async ({
|
||||
schemaName,
|
||||
dataSource,
|
||||
workspaceId,
|
||||
appVersion,
|
||||
}: SeedWorkspaceArgs) => {
|
||||
const version = extractVersionMajorMinorPatch(appVersion);
|
||||
|
||||
const workspaces: Record<string, WorkspaceSeederFields> = {
|
||||
[SEED_APPLE_WORKSPACE_ID]: {
|
||||
id: SEED_APPLE_WORKSPACE_ID,
|
||||
displayName: 'Apple',
|
||||
subdomain: 'apple',
|
||||
inviteHash: 'apple.dev-invite-hash',
|
||||
logo: 'https://twentyhq.github.io/placeholder-images/workspaces/apple-logo.png',
|
||||
activationStatus: WorkspaceActivationStatus.PENDING_CREATION, // will be set to active after default role creation
|
||||
version: version,
|
||||
},
|
||||
[SEED_ACME_WORKSPACE_ID]: {
|
||||
id: SEED_ACME_WORKSPACE_ID,
|
||||
displayName: 'Acme',
|
||||
subdomain: 'acme',
|
||||
inviteHash: 'acme.dev-invite-hash',
|
||||
logo: 'https://logos-world.net/wp-content/uploads/2022/05/Acme-Logo-700x394.png',
|
||||
activationStatus: WorkspaceActivationStatus.PENDING_CREATION, // will be set to active after default role creation
|
||||
version: version,
|
||||
},
|
||||
};
|
||||
|
||||
await dataSource
|
||||
.createQueryBuilder()
|
||||
.insert()
|
||||
.into(`${schemaName}.${tableName}`, workspaceSeederFields)
|
||||
.orIgnore()
|
||||
.values(workspaces[workspaceId])
|
||||
.execute();
|
||||
};
|
||||
|
||||
export const deleteWorkspaces = async (
|
||||
dataSource: DataSource,
|
||||
schemaName: string,
|
||||
workspaceId: string,
|
||||
) => {
|
||||
await dataSource
|
||||
.createQueryBuilder()
|
||||
.delete()
|
||||
.from(`${schemaName}.${tableName}`)
|
||||
.where(`${tableName}."id" = :id`, { id: workspaceId })
|
||||
.execute();
|
||||
};
|
||||
@ -0,0 +1,25 @@
|
||||
type ApiKeyDataSeed = {
|
||||
id: string;
|
||||
name: string;
|
||||
expiresAt: Date;
|
||||
};
|
||||
|
||||
export const API_KEY_DATA_SEED_COLUMNS: (keyof ApiKeyDataSeed)[] = [
|
||||
'id',
|
||||
'name',
|
||||
'expiresAt',
|
||||
];
|
||||
|
||||
export const API_KEY_DATA_SEED_IDS = {
|
||||
ID_1: '20202020-f401-4d8a-a731-64d007c27bad',
|
||||
};
|
||||
|
||||
export const API_KEY_DATA_SEEDS: ApiKeyDataSeed[] = [
|
||||
{
|
||||
id: API_KEY_DATA_SEED_IDS.ID_1,
|
||||
name: 'My api key',
|
||||
expiresAt: new Date(
|
||||
new Date().getTime() + 1000 * 60 * 60 * 24 * 365 * 100, // In 100 years
|
||||
),
|
||||
},
|
||||
];
|
||||
@ -0,0 +1,36 @@
|
||||
import { CONNECTED_ACCOUNT_DATA_SEED_IDS } from 'src/engine/workspace-manager/dev-seeder/data/constants/connected-account-data-seeds.constant';
|
||||
import { CalendarChannelVisibility } from 'src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity';
|
||||
|
||||
type CalendarChannelDataSeed = {
|
||||
id: string;
|
||||
connectedAccountId: string;
|
||||
handle: string;
|
||||
visibility: CalendarChannelVisibility;
|
||||
isContactAutoCreationEnabled: boolean;
|
||||
isSyncEnabled: boolean;
|
||||
};
|
||||
|
||||
export const CALENDAR_CHANNEL_DATA_SEED_COLUMNS: (keyof CalendarChannelDataSeed)[] =
|
||||
[
|
||||
'id',
|
||||
'connectedAccountId',
|
||||
'handle',
|
||||
'visibility',
|
||||
'isContactAutoCreationEnabled',
|
||||
'isSyncEnabled',
|
||||
];
|
||||
|
||||
export const CALENDAR_CHANNEL_DATA_SEED_IDS = {
|
||||
TIM: '20202020-a40f-4faf-bb9f-c6f9945b8203',
|
||||
};
|
||||
|
||||
export const CALENDAR_CHANNEL_DATA_SEEDS: CalendarChannelDataSeed[] = [
|
||||
{
|
||||
id: CALENDAR_CHANNEL_DATA_SEED_IDS.TIM,
|
||||
connectedAccountId: CONNECTED_ACCOUNT_DATA_SEED_IDS.TIM,
|
||||
handle: 'tim@apple.dev',
|
||||
visibility: CalendarChannelVisibility.SHARE_EVERYTHING,
|
||||
isContactAutoCreationEnabled: true,
|
||||
isSyncEnabled: true,
|
||||
},
|
||||
];
|
||||
@ -0,0 +1,34 @@
|
||||
import { CALENDAR_CHANNEL_DATA_SEED_IDS } from 'src/engine/workspace-manager/dev-seeder/data/constants/calendar-channel-data-seeds.constant';
|
||||
import { CALENDAR_EVENT_DATA_SEED_IDS } from 'src/engine/workspace-manager/dev-seeder/data/constants/calendar-event-data-seeds.constant';
|
||||
|
||||
type CalendarChannelEventAssociationDataSeed = {
|
||||
id: string;
|
||||
calendarChannelId: string;
|
||||
calendarEventId: string;
|
||||
eventExternalId: string;
|
||||
recurringEventExternalId: string;
|
||||
};
|
||||
|
||||
export const CALENDAR_CHANNEL_EVENT_ASSOCIATION_DATA_SEED_COLUMNS: (keyof CalendarChannelEventAssociationDataSeed)[] =
|
||||
[
|
||||
'id',
|
||||
'calendarChannelId',
|
||||
'calendarEventId',
|
||||
'eventExternalId',
|
||||
'recurringEventExternalId',
|
||||
];
|
||||
|
||||
export const CALENDAR_CHANNEL_EVENT_ASSOCIATION_DATA_SEED_IDS = {
|
||||
ID_1: '20202020-0687-4c41-b707-ed1bfca972a2',
|
||||
};
|
||||
|
||||
export const CALENDAR_CHANNEL_EVENT_ASSOCIATION_DATA_SEEDS: CalendarChannelEventAssociationDataSeed[] =
|
||||
[
|
||||
{
|
||||
id: CALENDAR_CHANNEL_EVENT_ASSOCIATION_DATA_SEED_IDS.ID_1,
|
||||
calendarChannelId: CALENDAR_CHANNEL_DATA_SEED_IDS.TIM,
|
||||
calendarEventId: CALENDAR_EVENT_DATA_SEED_IDS.ID_1,
|
||||
eventExternalId: 'exampleExternalId',
|
||||
recurringEventExternalId: 'exampleRecurringExternalId',
|
||||
},
|
||||
];
|
||||
@ -0,0 +1,57 @@
|
||||
type CalendarEventDataSeed = {
|
||||
id: string;
|
||||
title: string;
|
||||
isCanceled: boolean;
|
||||
isFullDay: boolean;
|
||||
startsAt: string;
|
||||
endsAt: string;
|
||||
externalCreatedAt: string;
|
||||
externalUpdatedAt: string;
|
||||
description: string;
|
||||
location: string;
|
||||
iCalUID: string;
|
||||
conferenceSolution: string;
|
||||
conferenceLinkPrimaryLinkLabel: string;
|
||||
conferenceLinkPrimaryLinkUrl: string;
|
||||
};
|
||||
|
||||
export const CALENDAR_EVENT_DATA_SEED_COLUMNS: (keyof CalendarEventDataSeed)[] =
|
||||
[
|
||||
'id',
|
||||
'title',
|
||||
'isCanceled',
|
||||
'isFullDay',
|
||||
'startsAt',
|
||||
'endsAt',
|
||||
'externalCreatedAt',
|
||||
'externalUpdatedAt',
|
||||
'description',
|
||||
'location',
|
||||
'iCalUID',
|
||||
'conferenceSolution',
|
||||
'conferenceLinkPrimaryLinkLabel',
|
||||
'conferenceLinkPrimaryLinkUrl',
|
||||
];
|
||||
|
||||
export const CALENDAR_EVENT_DATA_SEED_IDS = {
|
||||
ID_1: '20202020-1c0e-494c-a1b6-85b1c6fefaa5',
|
||||
};
|
||||
|
||||
export const CALENDAR_EVENT_DATA_SEEDS: CalendarEventDataSeed[] = [
|
||||
{
|
||||
id: CALENDAR_EVENT_DATA_SEED_IDS.ID_1,
|
||||
title: 'Meeting with Christoph',
|
||||
isCanceled: false,
|
||||
isFullDay: false,
|
||||
startsAt: new Date(new Date().setHours(10, 0)).toISOString(),
|
||||
endsAt: new Date(new Date().setHours(11, 0)).toISOString(),
|
||||
externalCreatedAt: new Date().toISOString(),
|
||||
externalUpdatedAt: new Date().toISOString(),
|
||||
description: 'Discuss project progress',
|
||||
location: 'Seattle',
|
||||
iCalUID: 'event1@calendar.com',
|
||||
conferenceSolution: 'Zoom',
|
||||
conferenceLinkPrimaryLinkLabel: 'https://zoom.us/j/1234567890',
|
||||
conferenceLinkPrimaryLinkUrl: 'https://zoom.us/j/1234567890',
|
||||
},
|
||||
];
|
||||
@ -0,0 +1,55 @@
|
||||
import { CALENDAR_EVENT_DATA_SEED_IDS } from 'src/engine/workspace-manager/dev-seeder/data/constants/calendar-event-data-seeds.constant';
|
||||
import { PERSON_DATA_SEED_IDS } from 'src/engine/workspace-manager/dev-seeder/data/constants/person-data-seeds.constant';
|
||||
import { WORKSPACE_MEMBER_DATA_SEED_IDS } from 'src/engine/workspace-manager/dev-seeder/data/constants/workspace-member-data-seeds.constant';
|
||||
import { CalendarEventParticipantResponseStatus } from 'src/modules/calendar/common/standard-objects/calendar-event-participant.workspace-entity';
|
||||
|
||||
type CalendarEventParticipantDataSeed = {
|
||||
id: string;
|
||||
calendarEventId: string;
|
||||
handle: string;
|
||||
displayName: string;
|
||||
isOrganizer: boolean;
|
||||
responseStatus: CalendarEventParticipantResponseStatus;
|
||||
personId: string | null;
|
||||
workspaceMemberId: string | null;
|
||||
};
|
||||
|
||||
export const CALENDAR_EVENT_PARTICIPANT_DATA_SEED_COLUMNS = [
|
||||
'id',
|
||||
'calendarEventId',
|
||||
'handle',
|
||||
'displayName',
|
||||
'isOrganizer',
|
||||
'responseStatus',
|
||||
'personId',
|
||||
'workspaceMemberId',
|
||||
];
|
||||
|
||||
export const CALENDAR_EVENT_PARTICIPANT_DATA_SEED_IDS = {
|
||||
ONE: '20202020-fb8f-4f0d-a36e-950e185401d4',
|
||||
TWO: '20202020-0722-40d7-9e55-cb5d00cfb654',
|
||||
};
|
||||
|
||||
export const CALENDAR_EVENT_PARTICIPANT_DATA_SEEDS: CalendarEventParticipantDataSeed[] =
|
||||
[
|
||||
{
|
||||
id: CALENDAR_EVENT_PARTICIPANT_DATA_SEED_IDS.ONE,
|
||||
calendarEventId: CALENDAR_EVENT_DATA_SEED_IDS.ID_1,
|
||||
handle: 'christoph.calisto@linkedin.com',
|
||||
displayName: 'Christoph Calisto',
|
||||
isOrganizer: true,
|
||||
responseStatus: CalendarEventParticipantResponseStatus.ACCEPTED,
|
||||
personId: PERSON_DATA_SEED_IDS.ID_1,
|
||||
workspaceMemberId: null,
|
||||
},
|
||||
{
|
||||
id: CALENDAR_EVENT_PARTICIPANT_DATA_SEED_IDS.TWO,
|
||||
calendarEventId: CALENDAR_EVENT_DATA_SEED_IDS.ID_1,
|
||||
handle: 'tim@apple.com',
|
||||
displayName: 'Tim Apple',
|
||||
isOrganizer: false,
|
||||
responseStatus: CalendarEventParticipantResponseStatus.ACCEPTED,
|
||||
personId: null,
|
||||
workspaceMemberId: WORKSPACE_MEMBER_DATA_SEED_IDS.TIM,
|
||||
},
|
||||
];
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,73 @@
|
||||
import { WORKSPACE_MEMBER_DATA_SEED_IDS } from 'src/engine/workspace-manager/dev-seeder/data/constants/workspace-member-data-seeds.constant';
|
||||
|
||||
type ConnectedAccountDataSeed = {
|
||||
id: string;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
deletedAt: Date | null;
|
||||
lastSyncHistoryId: string;
|
||||
accountOwnerId: string;
|
||||
refreshToken: string;
|
||||
accessToken: string;
|
||||
provider: string;
|
||||
handle: string;
|
||||
};
|
||||
|
||||
export const CONNECTED_ACCOUNT_DATA_SEED_COLUMNS: (keyof ConnectedAccountDataSeed)[] =
|
||||
[
|
||||
'id',
|
||||
'createdAt',
|
||||
'updatedAt',
|
||||
'deletedAt',
|
||||
'lastSyncHistoryId',
|
||||
'accountOwnerId',
|
||||
'refreshToken',
|
||||
'accessToken',
|
||||
'provider',
|
||||
'handle',
|
||||
];
|
||||
|
||||
export const CONNECTED_ACCOUNT_DATA_SEED_IDS = {
|
||||
TIM: '20202020-9ac0-4390-9a1a-ab4d2c4e1bb7',
|
||||
JONY: '20202020-0cc8-4d60-a3a4-803245698908',
|
||||
PHIL: '20202020-cafc-4323-908d-e5b42ad69fdf',
|
||||
};
|
||||
|
||||
export const CONNECTED_ACCOUNT_DATA_SEEDS: ConnectedAccountDataSeed[] = [
|
||||
{
|
||||
id: CONNECTED_ACCOUNT_DATA_SEED_IDS.TIM,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
lastSyncHistoryId: 'exampleLastSyncHistory',
|
||||
accountOwnerId: WORKSPACE_MEMBER_DATA_SEED_IDS.TIM,
|
||||
refreshToken: 'exampleRefreshToken',
|
||||
accessToken: 'exampleAccessToken',
|
||||
provider: 'google',
|
||||
handle: 'tim@apple.dev',
|
||||
},
|
||||
{
|
||||
id: CONNECTED_ACCOUNT_DATA_SEED_IDS.JONY,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
lastSyncHistoryId: 'exampleLastSyncHistory',
|
||||
accountOwnerId: WORKSPACE_MEMBER_DATA_SEED_IDS.JONY,
|
||||
refreshToken: 'exampleRefreshToken',
|
||||
accessToken: 'exampleAccessToken',
|
||||
provider: 'google',
|
||||
handle: 'jony.ive@apple.dev',
|
||||
},
|
||||
{
|
||||
id: CONNECTED_ACCOUNT_DATA_SEED_IDS.PHIL,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
lastSyncHistoryId: 'exampleLastSyncHistory',
|
||||
accountOwnerId: WORKSPACE_MEMBER_DATA_SEED_IDS.PHIL,
|
||||
refreshToken: 'exampleRefreshToken',
|
||||
accessToken: 'exampleAccessToken',
|
||||
provider: 'google',
|
||||
handle: 'phil.schiler@apple.dev',
|
||||
},
|
||||
];
|
||||
@ -0,0 +1,82 @@
|
||||
import { CONNECTED_ACCOUNT_DATA_SEED_IDS } from 'src/engine/workspace-manager/dev-seeder/data/constants/connected-account-data-seeds.constant';
|
||||
import {
|
||||
MessageChannelSyncStage,
|
||||
MessageChannelVisibility,
|
||||
} from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
|
||||
|
||||
type MessageChannelDataSeed = {
|
||||
id: string;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
deletedAt: Date | null;
|
||||
isContactAutoCreationEnabled: boolean;
|
||||
type: string;
|
||||
connectedAccountId: string;
|
||||
handle: string;
|
||||
isSyncEnabled: boolean;
|
||||
visibility: MessageChannelVisibility;
|
||||
syncStage: MessageChannelSyncStage;
|
||||
};
|
||||
|
||||
export const MESSAGE_CHANNEL_DATA_SEED_COLUMNS: (keyof MessageChannelDataSeed)[] =
|
||||
[
|
||||
'id',
|
||||
'createdAt',
|
||||
'updatedAt',
|
||||
'deletedAt',
|
||||
'isContactAutoCreationEnabled',
|
||||
'type',
|
||||
'connectedAccountId',
|
||||
'handle',
|
||||
'isSyncEnabled',
|
||||
'visibility',
|
||||
'syncStage',
|
||||
];
|
||||
|
||||
export const MESSAGE_CHANNEL_DATA_SEED_IDS = {
|
||||
TIM: '20202020-9b80-4c2c-a597-383db48de1d6',
|
||||
JONY: '20202020-5ffe-4b32-814a-983d5e4911cd',
|
||||
PHIL: '20202020-e2f1-49b5-85d2-5d3a3386990c',
|
||||
};
|
||||
|
||||
export const MESSAGE_CHANNEL_DATA_SEEDS: MessageChannelDataSeed[] = [
|
||||
{
|
||||
id: MESSAGE_CHANNEL_DATA_SEED_IDS.TIM,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
isContactAutoCreationEnabled: true,
|
||||
type: 'email',
|
||||
connectedAccountId: CONNECTED_ACCOUNT_DATA_SEED_IDS.TIM,
|
||||
handle: 'tim@apple.dev',
|
||||
isSyncEnabled: false,
|
||||
visibility: MessageChannelVisibility.SHARE_EVERYTHING,
|
||||
syncStage: MessageChannelSyncStage.FULL_MESSAGE_LIST_FETCH_PENDING,
|
||||
},
|
||||
{
|
||||
id: MESSAGE_CHANNEL_DATA_SEED_IDS.JONY,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
isContactAutoCreationEnabled: true,
|
||||
type: 'email',
|
||||
connectedAccountId: CONNECTED_ACCOUNT_DATA_SEED_IDS.JONY,
|
||||
handle: 'jony.ive@apple.dev',
|
||||
isSyncEnabled: false,
|
||||
visibility: MessageChannelVisibility.SHARE_EVERYTHING,
|
||||
syncStage: MessageChannelSyncStage.FULL_MESSAGE_LIST_FETCH_PENDING,
|
||||
},
|
||||
{
|
||||
id: MESSAGE_CHANNEL_DATA_SEED_IDS.PHIL,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
isContactAutoCreationEnabled: true,
|
||||
type: 'email',
|
||||
connectedAccountId: CONNECTED_ACCOUNT_DATA_SEED_IDS.PHIL,
|
||||
handle: 'phil.schiler@apple.dev',
|
||||
isSyncEnabled: false,
|
||||
visibility: MessageChannelVisibility.SHARE_EVERYTHING,
|
||||
syncStage: MessageChannelSyncStage.FULL_MESSAGE_LIST_FETCH_PENDING,
|
||||
},
|
||||
];
|
||||
@ -0,0 +1,71 @@
|
||||
import { MESSAGE_CHANNEL_DATA_SEED_IDS } from 'src/engine/workspace-manager/dev-seeder/data/constants/message-channel-data-seeds.constant';
|
||||
import { MESSAGE_DATA_SEED_IDS } from 'src/engine/workspace-manager/dev-seeder/data/constants/message-data-seeds.constant';
|
||||
import { MessageDirection } from 'src/modules/messaging/common/enums/message-direction.enum';
|
||||
|
||||
type MessageChannelMessageAssociationDataSeed = {
|
||||
id: string;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
deletedAt: Date | null;
|
||||
messageThreadExternalId: string | null;
|
||||
messageExternalId: string | null;
|
||||
messageId: string;
|
||||
messageChannelId: string;
|
||||
direction: MessageDirection;
|
||||
};
|
||||
|
||||
export const MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_DATA_SEED_COLUMNS: (keyof MessageChannelMessageAssociationDataSeed)[] =
|
||||
[
|
||||
'id',
|
||||
'createdAt',
|
||||
'updatedAt',
|
||||
'deletedAt',
|
||||
'messageThreadExternalId',
|
||||
'messageExternalId',
|
||||
'messageId',
|
||||
'messageChannelId',
|
||||
'direction',
|
||||
];
|
||||
|
||||
export const MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_DATA_SEED_IDS = {
|
||||
ID_1: '20202020-cc69-44ef-a82c-600c0dbf39ba',
|
||||
ID_2: '20202020-d80e-4a13-b10b-72ba09082668',
|
||||
ID_3: '20202020-e6ec-4c8a-b431-0901eaf395a9',
|
||||
};
|
||||
|
||||
export const MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_DATA_SEEDS: MessageChannelMessageAssociationDataSeed[] =
|
||||
[
|
||||
{
|
||||
id: MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_DATA_SEED_IDS.ID_1,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
messageThreadExternalId: null,
|
||||
messageExternalId: null,
|
||||
messageId: MESSAGE_DATA_SEED_IDS.ID_1,
|
||||
messageChannelId: MESSAGE_CHANNEL_DATA_SEED_IDS.TIM,
|
||||
direction: MessageDirection.OUTGOING,
|
||||
},
|
||||
{
|
||||
id: MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_DATA_SEED_IDS.ID_2,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
messageThreadExternalId: null,
|
||||
messageExternalId: null,
|
||||
messageId: MESSAGE_DATA_SEED_IDS.ID_2,
|
||||
messageChannelId: MESSAGE_CHANNEL_DATA_SEED_IDS.TIM,
|
||||
direction: MessageDirection.OUTGOING,
|
||||
},
|
||||
{
|
||||
id: MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_DATA_SEED_IDS.ID_3,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
messageThreadExternalId: null,
|
||||
messageExternalId: null,
|
||||
messageId: MESSAGE_DATA_SEED_IDS.ID_3,
|
||||
messageChannelId: MESSAGE_CHANNEL_DATA_SEED_IDS.TIM,
|
||||
direction: MessageDirection.INCOMING,
|
||||
},
|
||||
];
|
||||
@ -0,0 +1,67 @@
|
||||
import { MESSAGE_THREAD_DATA_SEED_IDS } from 'src/engine/workspace-manager/dev-seeder/data/constants/message-thread-data-seeds.constant';
|
||||
|
||||
type MessageDataSeed = {
|
||||
id: string;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
deletedAt: Date | null;
|
||||
receivedAt: Date;
|
||||
text: string;
|
||||
subject: string;
|
||||
messageThreadId: string;
|
||||
headerMessageId: string;
|
||||
};
|
||||
|
||||
export const MESSAGE_DATA_SEED_COLUMNS: (keyof MessageDataSeed)[] = [
|
||||
'id',
|
||||
'createdAt',
|
||||
'updatedAt',
|
||||
'deletedAt',
|
||||
'receivedAt',
|
||||
'text',
|
||||
'subject',
|
||||
'messageThreadId',
|
||||
'headerMessageId',
|
||||
];
|
||||
|
||||
export const MESSAGE_DATA_SEED_IDS = {
|
||||
ID_1: '20202020-2b8a-405d-8f42-e820ca921421',
|
||||
ID_2: '20202020-04c8-4f24-93f2-764948e95014',
|
||||
ID_3: '20202020-ac6b-4f86-87a2-5f5f9d1b6481',
|
||||
};
|
||||
|
||||
export const MESSAGE_DATA_SEEDS: MessageDataSeed[] = [
|
||||
{
|
||||
id: MESSAGE_DATA_SEED_IDS.ID_1,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
receivedAt: new Date(),
|
||||
text: 'Hello, \n I hope this email finds you well. I am writing to request a meeting. I believe it would be beneficial for both parties to collaborate and explore potential opportunities. Would you be available for a meeting sometime next week? Please let me know your availability, and I will arrange a suitable time. \n Looking forward to your response.\n Best regards',
|
||||
subject: 'Meeting Request',
|
||||
messageThreadId: MESSAGE_THREAD_DATA_SEED_IDS.ID_1,
|
||||
headerMessageId: '99ef24a8-2b8a-405d-8f42-e820ca921421',
|
||||
},
|
||||
{
|
||||
id: MESSAGE_DATA_SEED_IDS.ID_2,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
receivedAt: new Date(),
|
||||
text: 'Good Morning,\n I am writing to inquire about information. Could you please provide me with details regarding this topic? \n Your assistance in this matter would be greatly appreciated. Thank you in advance for your prompt response. \n Best regards,Tim',
|
||||
subject: 'Inquiry Regarding Topic',
|
||||
messageThreadId: MESSAGE_THREAD_DATA_SEED_IDS.ID_2,
|
||||
headerMessageId: '8f804a9a-04c8-4f24-93f2-764948e95014',
|
||||
},
|
||||
{
|
||||
id: MESSAGE_DATA_SEED_IDS.ID_3,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
receivedAt: new Date(),
|
||||
text: 'Good Evening,\nI wanted to extend my sincere gratitude for taking the time to meet with me earlier today. It was a pleasure discussing with you, and I am excited about the potential opportunities for collaboration. \n Please feel free to reach out if you have any further questions or require additional information. I look forward to our continued communication. Best regards.',
|
||||
subject: 'Thank You for the Meeting',
|
||||
messageThreadId: MESSAGE_THREAD_DATA_SEED_IDS.ID_1,
|
||||
headerMessageId: '3939d68a-ac6b-4f86-87a2-5f5f9d1b6481',
|
||||
},
|
||||
];
|
||||
@ -0,0 +1,114 @@
|
||||
import { MESSAGE_DATA_SEED_IDS } from 'src/engine/workspace-manager/dev-seeder/data/constants/message-data-seeds.constant';
|
||||
import { PERSON_DATA_SEED_IDS } from 'src/engine/workspace-manager/dev-seeder/data/constants/person-data-seeds.constant';
|
||||
import { WORKSPACE_MEMBER_DATA_SEED_IDS } from 'src/engine/workspace-manager/dev-seeder/data/constants/workspace-member-data-seeds.constant';
|
||||
|
||||
type MessageParticipantDataSeed = {
|
||||
id: string;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
deletedAt: Date | null;
|
||||
workspaceMemberId: string;
|
||||
personId: string;
|
||||
displayName: string;
|
||||
handle: string;
|
||||
role: string;
|
||||
messageId: string;
|
||||
};
|
||||
|
||||
export const MESSAGE_PARTICIPANT_DATA_SEED_COLUMNS: (keyof MessageParticipantDataSeed)[] =
|
||||
[
|
||||
'id',
|
||||
'createdAt',
|
||||
'updatedAt',
|
||||
'deletedAt',
|
||||
'workspaceMemberId',
|
||||
'personId',
|
||||
'displayName',
|
||||
'handle',
|
||||
'role',
|
||||
'messageId',
|
||||
];
|
||||
|
||||
export const MESSAGE_PARTICIPANT_DATA_SEED_IDS = {
|
||||
ID_1: '20202020-0f2a-49d8-8aa2-ec8786153a0b',
|
||||
ID_2: '20202020-4e83-41ec-93e2-fd70ff09f68c',
|
||||
ID_3: '20202020-e716-4dd5-ac61-3315bc559e2d',
|
||||
ID_4: '20202020-fc7d-4ad8-9aea-b78bcbf79cdd',
|
||||
ID_5: '20202020-564c-4a3c-abbf-e942e8c3f9c9',
|
||||
ID_6: '20202020-7e4a-489a-ba6b-1ae6b7d721ac',
|
||||
};
|
||||
|
||||
export const MESSAGE_PARTICIPANT_DATA_SEEDS: MessageParticipantDataSeed[] = [
|
||||
{
|
||||
id: MESSAGE_PARTICIPANT_DATA_SEED_IDS.ID_1,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
workspaceMemberId: WORKSPACE_MEMBER_DATA_SEED_IDS.TIM,
|
||||
personId: PERSON_DATA_SEED_IDS.ID_1,
|
||||
displayName: 'Christoph',
|
||||
handle: 'outgoing',
|
||||
role: 'from',
|
||||
messageId: MESSAGE_DATA_SEED_IDS.ID_1,
|
||||
},
|
||||
{
|
||||
id: MESSAGE_PARTICIPANT_DATA_SEED_IDS.ID_2,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
workspaceMemberId: WORKSPACE_MEMBER_DATA_SEED_IDS.TIM,
|
||||
personId: PERSON_DATA_SEED_IDS.ID_2,
|
||||
displayName: 'Sylvie',
|
||||
handle: 'incoming',
|
||||
role: 'to',
|
||||
messageId: MESSAGE_DATA_SEED_IDS.ID_1,
|
||||
},
|
||||
{
|
||||
id: MESSAGE_PARTICIPANT_DATA_SEED_IDS.ID_3,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
workspaceMemberId: WORKSPACE_MEMBER_DATA_SEED_IDS.TIM,
|
||||
personId: PERSON_DATA_SEED_IDS.ID_3,
|
||||
displayName: 'Christopher',
|
||||
handle: 'incoming',
|
||||
role: 'to',
|
||||
messageId: MESSAGE_DATA_SEED_IDS.ID_1,
|
||||
},
|
||||
{
|
||||
id: MESSAGE_PARTICIPANT_DATA_SEED_IDS.ID_4,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
workspaceMemberId: WORKSPACE_MEMBER_DATA_SEED_IDS.TIM,
|
||||
personId: PERSON_DATA_SEED_IDS.ID_1,
|
||||
displayName: 'Christoph',
|
||||
handle: 'outgoing',
|
||||
role: 'from',
|
||||
messageId: MESSAGE_DATA_SEED_IDS.ID_2,
|
||||
},
|
||||
{
|
||||
id: MESSAGE_PARTICIPANT_DATA_SEED_IDS.ID_5,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
workspaceMemberId: WORKSPACE_MEMBER_DATA_SEED_IDS.TIM,
|
||||
personId: PERSON_DATA_SEED_IDS.ID_2,
|
||||
displayName: 'Sylvie',
|
||||
handle: 'incoming',
|
||||
role: 'to',
|
||||
messageId: MESSAGE_DATA_SEED_IDS.ID_2,
|
||||
},
|
||||
{
|
||||
id: MESSAGE_PARTICIPANT_DATA_SEED_IDS.ID_6,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
workspaceMemberId: WORKSPACE_MEMBER_DATA_SEED_IDS.TIM,
|
||||
personId: PERSON_DATA_SEED_IDS.ID_3,
|
||||
displayName: 'Christopher',
|
||||
handle: 'incoming',
|
||||
role: 'to',
|
||||
messageId: MESSAGE_DATA_SEED_IDS.ID_2,
|
||||
},
|
||||
];
|
||||
@ -0,0 +1,44 @@
|
||||
type MessageThreadDataSeed = {
|
||||
id: string;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
deletedAt: Date | null;
|
||||
};
|
||||
|
||||
export const MESSAGE_THREAD_DATA_SEED_COLUMNS: (keyof MessageThreadDataSeed)[] =
|
||||
['id', 'createdAt', 'updatedAt', 'deletedAt'];
|
||||
|
||||
export const MESSAGE_THREAD_DATA_SEED_IDS = {
|
||||
ID_1: '20202020-8bfa-453b-b99b-bc435a7d4da8',
|
||||
ID_2: '20202020-634a-4fde-aa7c-28a0eaf203ca',
|
||||
ID_3: '20202020-1b56-4f10-a2fa-2ccaddf81f6c',
|
||||
ID_4: '20202020-d51c-485a-b1b6-ed7c63e05d72',
|
||||
ID_5: '20202020-3f74-492d-a101-2a70f50a1645',
|
||||
};
|
||||
|
||||
export const MESSAGE_THREAD_DATA_SEEDS: MessageThreadDataSeed[] = [
|
||||
{
|
||||
id: MESSAGE_THREAD_DATA_SEED_IDS.ID_1,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
},
|
||||
{
|
||||
id: MESSAGE_THREAD_DATA_SEED_IDS.ID_2,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
},
|
||||
{
|
||||
id: MESSAGE_THREAD_DATA_SEED_IDS.ID_3,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
},
|
||||
{
|
||||
id: MESSAGE_THREAD_DATA_SEED_IDS.ID_4,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
deletedAt: null,
|
||||
},
|
||||
];
|
||||
@ -0,0 +1,99 @@
|
||||
import { COMPANY_DATA_SEED_IDS } from 'src/engine/workspace-manager/dev-seeder/data/constants/company-data-seeds.constant';
|
||||
import { PERSON_DATA_SEED_IDS } from 'src/engine/workspace-manager/dev-seeder/data/constants/person-data-seeds.constant';
|
||||
import { WORKSPACE_MEMBER_DATA_SEED_IDS } from 'src/engine/workspace-manager/dev-seeder/data/constants/workspace-member-data-seeds.constant';
|
||||
|
||||
type OpportunityDataSeed = {
|
||||
id: string;
|
||||
name: string;
|
||||
amountAmountMicros: number;
|
||||
amountCurrencyCode: string;
|
||||
closeDate: Date;
|
||||
stage: string;
|
||||
position: number;
|
||||
pointOfContactId: string;
|
||||
companyId: string;
|
||||
createdBySource: string;
|
||||
createdByWorkspaceMemberId: string;
|
||||
createdByName: string;
|
||||
};
|
||||
|
||||
export const OPPORTUNITY_DATA_SEED_COLUMNS: (keyof OpportunityDataSeed)[] = [
|
||||
'id',
|
||||
'name',
|
||||
'amountAmountMicros',
|
||||
'amountCurrencyCode',
|
||||
'closeDate',
|
||||
'stage',
|
||||
'position',
|
||||
'pointOfContactId',
|
||||
'companyId',
|
||||
'createdBySource',
|
||||
'createdByWorkspaceMemberId',
|
||||
'createdByName',
|
||||
];
|
||||
|
||||
export const OPPORTUNITY_DATA_SEED_IDS = {
|
||||
ID_1: '20202020-be10-422b-a663-16bd3c2228e1',
|
||||
ID_2: '20202020-0543-4cc2-9f96-95cc699960f2',
|
||||
ID_3: '20202020-2f89-406f-90ea-180f433b2445',
|
||||
ID_4: '20202020-35b1-4045-9cde-42f715148954',
|
||||
};
|
||||
|
||||
export const OPPORTUNITY_DATA_SEEDS: OpportunityDataSeed[] = [
|
||||
{
|
||||
id: OPPORTUNITY_DATA_SEED_IDS.ID_1,
|
||||
name: 'Opportunity 1',
|
||||
amountAmountMicros: 100000,
|
||||
amountCurrencyCode: 'USD',
|
||||
closeDate: new Date(),
|
||||
stage: 'NEW',
|
||||
position: 1,
|
||||
pointOfContactId: PERSON_DATA_SEED_IDS.ID_1,
|
||||
companyId: COMPANY_DATA_SEED_IDS.ID_1,
|
||||
createdBySource: 'MANUAL',
|
||||
createdByWorkspaceMemberId: WORKSPACE_MEMBER_DATA_SEED_IDS.TIM,
|
||||
createdByName: 'Tim Cook',
|
||||
},
|
||||
{
|
||||
id: OPPORTUNITY_DATA_SEED_IDS.ID_2,
|
||||
name: 'Opportunity 2',
|
||||
amountAmountMicros: 2000000,
|
||||
amountCurrencyCode: 'USD',
|
||||
closeDate: new Date(),
|
||||
stage: 'MEETING',
|
||||
position: 2,
|
||||
pointOfContactId: PERSON_DATA_SEED_IDS.ID_2,
|
||||
companyId: COMPANY_DATA_SEED_IDS.ID_2,
|
||||
createdBySource: 'MANUAL',
|
||||
createdByWorkspaceMemberId: WORKSPACE_MEMBER_DATA_SEED_IDS.TIM,
|
||||
createdByName: 'Tim Cook',
|
||||
},
|
||||
{
|
||||
id: OPPORTUNITY_DATA_SEED_IDS.ID_3,
|
||||
name: 'Opportunity 3',
|
||||
amountAmountMicros: 300000,
|
||||
amountCurrencyCode: 'USD',
|
||||
closeDate: new Date(),
|
||||
stage: 'PROPOSAL',
|
||||
position: 3,
|
||||
pointOfContactId: PERSON_DATA_SEED_IDS.ID_3,
|
||||
companyId: COMPANY_DATA_SEED_IDS.ID_3,
|
||||
createdBySource: 'MANUAL',
|
||||
createdByWorkspaceMemberId: WORKSPACE_MEMBER_DATA_SEED_IDS.TIM,
|
||||
createdByName: 'Tim Cook',
|
||||
},
|
||||
{
|
||||
id: OPPORTUNITY_DATA_SEED_IDS.ID_4,
|
||||
name: 'Opportunity 4',
|
||||
amountAmountMicros: 4000000,
|
||||
amountCurrencyCode: 'USD',
|
||||
closeDate: new Date(),
|
||||
stage: 'PROPOSAL',
|
||||
position: 4,
|
||||
pointOfContactId: PERSON_DATA_SEED_IDS.ID_4,
|
||||
companyId: COMPANY_DATA_SEED_IDS.ID_4,
|
||||
createdBySource: 'MANUAL',
|
||||
createdByWorkspaceMemberId: WORKSPACE_MEMBER_DATA_SEED_IDS.TIM,
|
||||
createdByName: '',
|
||||
},
|
||||
];
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,204 @@
|
||||
type PetDataSeed = {
|
||||
id: string;
|
||||
name: string;
|
||||
species: string;
|
||||
traits: string[];
|
||||
comments: string;
|
||||
age: number;
|
||||
locationAddressStreet1: string;
|
||||
locationAddressStreet2: string;
|
||||
locationAddressCity: string;
|
||||
locationAddressCountry: string;
|
||||
locationAddressPostcode: string;
|
||||
locationAddressState: string;
|
||||
vetPhonePrimaryPhoneCallingCode: string;
|
||||
vetPhonePrimaryPhoneCountryCode: string;
|
||||
vetPhonePrimaryPhoneNumber: string;
|
||||
vetEmailPrimaryEmail: string;
|
||||
vetEmailAdditionalEmails: string;
|
||||
birthday: string;
|
||||
isGoodWithKids: boolean;
|
||||
picturesPrimaryLinkUrl: string;
|
||||
picturesPrimaryLinkLabel: string;
|
||||
picturesSecondaryLinks: string;
|
||||
averageCostOfKibblePerMonthAmountMicros: number;
|
||||
averageCostOfKibblePerMonthCurrencyCode: string;
|
||||
makesOwnerThinkOfFirstName: string;
|
||||
makesOwnerThinkOfLastName: string;
|
||||
soundSwag: string;
|
||||
bio: string;
|
||||
interestingFacts: string[];
|
||||
extraData: string;
|
||||
};
|
||||
|
||||
export const PET_DATA_SEED_COLUMNS: (keyof PetDataSeed)[] = [
|
||||
'id',
|
||||
'name',
|
||||
'species',
|
||||
'traits',
|
||||
'comments',
|
||||
'age',
|
||||
'locationAddressStreet1',
|
||||
'locationAddressStreet2',
|
||||
'locationAddressCity',
|
||||
'locationAddressCountry',
|
||||
'locationAddressPostcode',
|
||||
'locationAddressState',
|
||||
'vetPhonePrimaryPhoneCallingCode',
|
||||
'vetPhonePrimaryPhoneCountryCode',
|
||||
'vetPhonePrimaryPhoneNumber',
|
||||
'vetEmailPrimaryEmail',
|
||||
'vetEmailAdditionalEmails',
|
||||
'birthday',
|
||||
'isGoodWithKids',
|
||||
'picturesPrimaryLinkUrl',
|
||||
'picturesPrimaryLinkLabel',
|
||||
'picturesSecondaryLinks',
|
||||
'averageCostOfKibblePerMonthAmountMicros',
|
||||
'averageCostOfKibblePerMonthCurrencyCode',
|
||||
'makesOwnerThinkOfFirstName',
|
||||
'makesOwnerThinkOfLastName',
|
||||
'soundSwag',
|
||||
'bio',
|
||||
'interestingFacts',
|
||||
'extraData',
|
||||
];
|
||||
|
||||
export const PET_DATA_SEED_IDS = {
|
||||
ID_1: '20202020-0f2a-49d8-8aa2-ec8786153a0b',
|
||||
};
|
||||
|
||||
export const PET_DATA_SEEDS: PetDataSeed[] = [
|
||||
{
|
||||
id: PET_DATA_SEED_IDS.ID_1,
|
||||
name: 'Toby',
|
||||
species: 'DOG',
|
||||
traits: ['CURIOUS', 'FRIENDLY'],
|
||||
comments: 'Needs to have people around.',
|
||||
age: 3,
|
||||
locationAddressStreet1: '513 Batz Fork',
|
||||
locationAddressStreet2: '7344 Haley Loop',
|
||||
locationAddressCity: 'Jacksonstad',
|
||||
locationAddressCountry: 'United States',
|
||||
locationAddressPostcode: '32048-5208',
|
||||
locationAddressState: 'North Dakota',
|
||||
vetPhonePrimaryPhoneCallingCode: '+33',
|
||||
vetPhonePrimaryPhoneCountryCode: 'FR',
|
||||
vetPhonePrimaryPhoneNumber: '789012345',
|
||||
vetEmailPrimaryEmail: 'john@twenty.com',
|
||||
vetEmailAdditionalEmails: JSON.stringify([
|
||||
'tim@twenty.com',
|
||||
'timapple@twenty.com',
|
||||
'johnappletim@twenty.com',
|
||||
]),
|
||||
birthday: new Date('2019-01-01').toISOString(),
|
||||
isGoodWithKids: false,
|
||||
picturesPrimaryLinkUrl:
|
||||
'https://images.unsplash.com/photo-1507146426996-ef05306b995a?q=80&w=3270&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
|
||||
picturesPrimaryLinkLabel: 'Picture 1',
|
||||
picturesSecondaryLinks: JSON.stringify([
|
||||
{
|
||||
url: 'https://images.unsplash.com/photo-1447684808650-354ae64db5b8?q=80&w=3267&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
|
||||
label: 'Picture 2',
|
||||
},
|
||||
]),
|
||||
averageCostOfKibblePerMonthAmountMicros: 2000000000,
|
||||
averageCostOfKibblePerMonthCurrencyCode: 'USD',
|
||||
makesOwnerThinkOfFirstName: 'Brad',
|
||||
makesOwnerThinkOfLastName: 'Pitt',
|
||||
soundSwag: 'RATING_3',
|
||||
bio: '[{"id":"c2fc1fe1-8e44-41ce-a670-1819d1520fb1","type":"heading","props":{"textColor":"default","backgroundColor":"default","textAlignment":"left","level":1},"content":[{"type":"text","text":"First encounter","styles":{}}],"children":[]},{"id":"064cb9b6-caf7-440e-8fbd-bcfa332fe909","type":"paragraph","props":{"textColor":"default","backgroundColor":"default","textAlignment":"left"},"content":[{"type":"text","text":"It was a beautiful day; we went to the kennel because a friend of ours told us that the puppies were hoping to find their humans.","styles":{}}],"children":[]},{"id":"45a6c6d9-a561-49e6-b64a-4555dcb72084","type":"paragraph","props":{"textColor":"default","backgroundColor":"default","textAlignment":"left"},"content":[],"children":[]},{"id":"3dcdfa35-d200-418d-8b67-0c8540c1fa69","type":"heading","props":{"textColor":"default","backgroundColor":"default","textAlignment":"left","level":2},"content":[{"type":"text","text":"TODO","styles":{}}],"children":[]},{"id":"be99fc64-6cd4-4861-a81e-9096d92a6001","type":"checkListItem","props":{"textColor":"default","backgroundColor":"default","textAlignment":"left","checked":true},"content":[{"type":"text","text":"Go to the vet","styles":{}}],"children":[]},{"id":"3ab3777a-4258-4396-8545-8acf19ebc113","type":"checkListItem","props":{"textColor":"default","backgroundColor":"default","textAlignment":"left","checked":false},"content":[{"type":"text","text":"Buy kibbles","styles":{}}],"children":[]},{"id":"5c3a5427-4375-4154-be5a-61dceb55b87e","type":"checkListItem","props":{"textColor":"default","backgroundColor":"default","textAlignment":"left","checked":false},"content":[{"type":"text","text":"Find a cozy spot for the basket","styles":{}}],"children":[]},{"id":"efca1bfb-59a7-4abe-8b71-a9dfd4a866cf","type":"paragraph","props":{"textColor":"default","backgroundColor":"default","textAlignment":"left"},"content":[],"children":[]},{"id":"b8671315-309c-4da0-8371-8f5dc96ec42f","type":"paragraph","props":{"textColor":"default","backgroundColor":"default","textAlignment":"left"},"content":[{"type":"text","text":"What it looked like when we met :","styles":{}}],"children":[]},{"id":"07758210-8772-4861-8398-a70b044ed42b","type":"image","props":{"backgroundColor":"default","textAlignment":"left","name":"photo-1530667912788-f976e8ee0bd5?q=80&w=3269&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D","url":"https://images.unsplash.com/photo-1530667912788-f976e8ee0bd5?q=80&w=3269&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D","caption":"","showPreview":true,"previewWidth":512},"children":[]},{"id":"a61a47fa-8635-4160-b336-8459cbe15351","type":"paragraph","props":{"textColor":"default","backgroundColor":"default","textAlignment":"left"},"content":[{"type":"text","text":"Table of data :","styles":{}}],"children":[]},{"id":"28738ccc-5643-4497-ad66-e2e8c513bdfb","type":"table","props":{"textColor":"default","backgroundColor":"default"},"content":{"type":"tableContent","rows":[{"cells":[[{"type":"text","text":"Header 1","styles":{"bold":true}}],[{"type":"text","text":"Header 2","styles":{"bold":true}}],[{"type":"text","text":"Header 3","styles":{"bold":true}}]]},{"cells":[[{"type":"text","text":"Row 1 - Cell 1","styles":{}}],[{"type":"text","text":"Row 1 - Cell 2","styles":{}}],[{"type":"text","text":"Row 1 - Cell 3","styles":{}}]]}]},"children":[]},{"id":"3599afec-e653-41d8-97b6-c495afa3724e","type":"paragraph","props":{"textColor":"default","backgroundColor":"default","textAlignment":"left"},"content":[],"children":[]}]',
|
||||
interestingFacts: [
|
||||
'World’s Best Sock Thief',
|
||||
'Expert at Puppy Eyes',
|
||||
'Fearless… Except Around Bananas',
|
||||
'Signature Ear Flip',
|
||||
],
|
||||
extraData: JSON.stringify({
|
||||
settingsOnVetSoftware: {
|
||||
vetSoftware: 'VetLink',
|
||||
settings: [
|
||||
{
|
||||
key: 'Vet name',
|
||||
value: 'Dr. John Doe',
|
||||
},
|
||||
{
|
||||
key: 'Vet phone',
|
||||
value: '234-567-890',
|
||||
},
|
||||
{
|
||||
key: 'Vet email',
|
||||
value: 'asd@asd.com',
|
||||
},
|
||||
{
|
||||
key: 'Vet address',
|
||||
value:
|
||||
'513 Batz Fork, 7344 Haley Loop, Jacksonstad, North Dakota, 32048-5208, United States',
|
||||
},
|
||||
],
|
||||
},
|
||||
additionalData: [
|
||||
{
|
||||
key: 'Weight',
|
||||
value: '5kg',
|
||||
},
|
||||
{
|
||||
key: 'Height',
|
||||
value: '30cm',
|
||||
},
|
||||
{
|
||||
key: 'Length',
|
||||
value: '50cm',
|
||||
},
|
||||
{
|
||||
key: 'Breed',
|
||||
value: 'Golden Retriever',
|
||||
},
|
||||
{
|
||||
key: 'Color',
|
||||
value: 'Golden',
|
||||
},
|
||||
{
|
||||
key: 'Eye color',
|
||||
value: 'Brown',
|
||||
},
|
||||
{
|
||||
key: 'Fur',
|
||||
value: 'Long',
|
||||
},
|
||||
{
|
||||
key: 'Tail',
|
||||
value: 'Long',
|
||||
},
|
||||
{
|
||||
key: 'Ears',
|
||||
value: 'Long',
|
||||
},
|
||||
{
|
||||
key: 'Paws',
|
||||
value: 'Small',
|
||||
},
|
||||
{
|
||||
key: 'Nose',
|
||||
value: 'Wet',
|
||||
},
|
||||
{
|
||||
key: 'Teeth',
|
||||
value: 'White',
|
||||
},
|
||||
{
|
||||
key: 'Habits',
|
||||
value: 'Barks when someone is at the door',
|
||||
},
|
||||
{
|
||||
key: 'Likes',
|
||||
value: 'Belly rubs',
|
||||
},
|
||||
{
|
||||
key: 'Dislikes',
|
||||
value: 'Being alone',
|
||||
},
|
||||
],
|
||||
}),
|
||||
},
|
||||
];
|
||||
@ -0,0 +1,66 @@
|
||||
type SurveyResultDataSeed = {
|
||||
id: string;
|
||||
name: string;
|
||||
score: number;
|
||||
percentageOfCompletion: number;
|
||||
participants: number;
|
||||
averageEstimatedNumberOfAtomsInTheUniverse: string;
|
||||
comments: string;
|
||||
shortNotes: string;
|
||||
};
|
||||
|
||||
export const SURVEY_RESULT_DATA_SEED_COLUMNS: (keyof SurveyResultDataSeed)[] = [
|
||||
'id',
|
||||
'name',
|
||||
'score',
|
||||
'percentageOfCompletion',
|
||||
'participants',
|
||||
'averageEstimatedNumberOfAtomsInTheUniverse',
|
||||
'comments',
|
||||
'shortNotes',
|
||||
];
|
||||
|
||||
export const SURVEY_RESULT_DATA_SEED_IDS = {
|
||||
ID_1: '20202020-0f2a-49d8-8aa2-ec8786153a0b',
|
||||
ID_2: '20202020-4e83-41ec-93e2-fd70ff09f68c',
|
||||
ID_3: '20202020-e716-4dd5-ac61-3315bc559e2d',
|
||||
};
|
||||
|
||||
export const SURVEY_RESULT_DATA_SEEDS: SurveyResultDataSeed[] = [
|
||||
{
|
||||
id: SURVEY_RESULT_DATA_SEED_IDS.ID_1,
|
||||
name: 'First survey results - 2021',
|
||||
score: 0.26022134837694466,
|
||||
percentageOfCompletion: 76.3561814092,
|
||||
participants: 599,
|
||||
averageEstimatedNumberOfAtomsInTheUniverse:
|
||||
'78667671999742413888718514892176090137414339407788865817757694662213423853',
|
||||
comments:
|
||||
'Fuga agnosco patria volva aqua angustus utpote acquiro bestia. Abduco vorax volva agnosco alioqui. Cupiditas abbas aptus uterque bibo sonitus. Tergum carpo degero defaeco. Nostrum verumtamen tactus arbustum tui administratio. Terra sollers calculus blandior. Trans supra tricesimus. Utrum tenus comis adeo asporto sto quibusdam theologus suppono. Cursim casso alveus validus vapulus acer vis. Velum traho adipisci coerceo terminatio at allatus turbo adnuo blandior. Ante consectetur cedo cibo perferendis at amicitia degenero. Doloremque votum cupressus cerno stillicidium arcesso abundans antea sumo. Spoliatio asper solus. Vespillo distinctio ver truculenter torqueo vado aureus. Eaque bonus occaecati defungo defetiscor cibo. Thema ager usus verbum caute tergeo earum adipiscor vinculum. Delinquo tardus canonicus abbas amo confugo doloremque. Comburo quos cumque inflammatio dignissimos abstergo ventus cruentus. Tabula aliquid contego sono delectatio aeternus. Summopere crinis debitis stella conservo desipio termes vulgaris.',
|
||||
shortNotes: 'verto ascit iure tribuo vulnero',
|
||||
},
|
||||
{
|
||||
id: SURVEY_RESULT_DATA_SEED_IDS.ID_2,
|
||||
name: 'With only people from the US',
|
||||
score: 0.07128839939832687,
|
||||
percentageOfCompletion: 61.6284981836,
|
||||
participants: 575,
|
||||
averageEstimatedNumberOfAtomsInTheUniverse:
|
||||
'58714201303231867082632874445965836504227665636297405101762256297406500076',
|
||||
comments:
|
||||
'Benevolentia valens caecus triduana. Cerno curiositas amita. Urbs urbs tertius iure spes succedo aspernatur culpa caute commodo. Cohaero voluptas amplexus denuo caelestis deprimo cresco cognatus aranea. Tabula perferendis ullus taedium vulnero stella corrupti testimonium. Ventosus ars abundans coniuratio. Cohibeo turba apostolus cunae tutamen. Audacia quod benevolentia charisma. Beatus consequuntur uterque crustulum valetudo spes vicinus. Tardus curso crinis ambulo cupiditate cras ad basium volup. Trepide dapifer theologus volva. Urbanus audacia ver aeger clamo animus adsidue error thorax. Ut centum volutabrum virgo summisse earum. Campana bos adulatio candidus tabgo tempore caries coadunatio. Cenaculum absque sustineo angustus quisquam auctus laudantium carbo stella. Conservo thymbra asperiores coaegresco vergo. Cubicularis canis solio. Tener vestrum iure claustrum velum aperte crinis ascisco clarus clam. Vinco ademptio absum. Verto desolo depraedor error coadunatio.',
|
||||
shortNotes: 'tres tantillus vado aequus ago',
|
||||
},
|
||||
{
|
||||
id: SURVEY_RESULT_DATA_SEED_IDS.ID_3,
|
||||
name: 'People who like cats',
|
||||
score: 0.1480973360594362,
|
||||
percentageOfCompletion: 72.4289541366,
|
||||
participants: 590,
|
||||
averageEstimatedNumberOfAtomsInTheUniverse:
|
||||
'51790645279092482632713239096036038617511762830423654232543291815995800207',
|
||||
comments:
|
||||
'Omnis careo ait praesentium inventore amet stips versus. Charisma demens vergo ex tibi desolo harum valens urbs abeo. Subnecto tantum tenax. Esse aduro caste comprehendo color bellicus excepturi tego coniuratio stella. Cogo cognatus cogo acerbitas aro. Asper cohibeo tam venustas arma antea studio eveniet casus. Numquam benevolentia voco celer. Defungo arcesso viridis veritas adsuesco desparatus patria tondeo canonicus stillicidium. Clamo truculenter vix allatus succedo depereo aestivus praesentium. Spiritus comes adipisci. Atrocitas virtus alveus strenuus. Repellat thermae aptus placeat aut. Ambitus tunc convoco adulatio averto. Agnitio aegrotatio aequus decumbo conventus. Valens adulatio ad voluptatibus conspergo vallum tredecim correptius. Celo aranea umquam. A abscido vigor virtus tristis cavus. Truculenter natus bonus sollers vulgivagus amita. Occaecati illo voco terga carcer commodo. Succurro vociferor bene vere accusamus defluo at videlicet aranea deleniti.',
|
||||
shortNotes: 'aeneus armarium conventus curto rerum',
|
||||
},
|
||||
];
|
||||
@ -0,0 +1,58 @@
|
||||
import { USER_DATA_SEED_IDS } from 'src/engine/workspace-manager/dev-seeder/core/utils/seed-users.util';
|
||||
|
||||
type WorkspaceMemberDataSeed = {
|
||||
id: string;
|
||||
nameFirstName: string;
|
||||
nameLastName: string;
|
||||
locale: string;
|
||||
colorScheme: string;
|
||||
userEmail: string;
|
||||
userId: string;
|
||||
};
|
||||
|
||||
export const WORKSPACE_MEMBER_DATA_SEED_COLUMNS: (keyof WorkspaceMemberDataSeed)[] =
|
||||
[
|
||||
'id',
|
||||
'nameFirstName',
|
||||
'nameLastName',
|
||||
'locale',
|
||||
'colorScheme',
|
||||
'userEmail',
|
||||
'userId',
|
||||
];
|
||||
|
||||
export const WORKSPACE_MEMBER_DATA_SEED_IDS = {
|
||||
TIM: '20202020-0687-4c41-b707-ed1bfca972a7',
|
||||
JONY: '20202020-77d5-4cb6-b60a-f4a835a85d61',
|
||||
PHIL: '20202020-1553-45c6-a028-5a9064cce07f',
|
||||
};
|
||||
|
||||
export const WORKSPACE_MEMBER_DATA_SEEDS: WorkspaceMemberDataSeed[] = [
|
||||
{
|
||||
id: WORKSPACE_MEMBER_DATA_SEED_IDS.TIM,
|
||||
nameFirstName: 'Tim',
|
||||
nameLastName: 'Apple',
|
||||
locale: 'en',
|
||||
colorScheme: 'Light',
|
||||
userEmail: 'tim@apple.dev',
|
||||
userId: USER_DATA_SEED_IDS.TIM,
|
||||
},
|
||||
{
|
||||
id: WORKSPACE_MEMBER_DATA_SEED_IDS.JONY,
|
||||
nameFirstName: 'Jony',
|
||||
nameLastName: 'Ive',
|
||||
locale: 'en',
|
||||
colorScheme: 'Light',
|
||||
userEmail: 'jony.ive@apple.dev',
|
||||
userId: USER_DATA_SEED_IDS.JONY,
|
||||
},
|
||||
{
|
||||
id: WORKSPACE_MEMBER_DATA_SEED_IDS.PHIL,
|
||||
nameFirstName: 'Phil',
|
||||
nameLastName: 'Schiler',
|
||||
locale: 'en',
|
||||
colorScheme: 'Light',
|
||||
userEmail: 'phil.schiler@apple.dev',
|
||||
userId: USER_DATA_SEED_IDS.PHIL,
|
||||
},
|
||||
];
|
||||
@ -0,0 +1,250 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service';
|
||||
import { WorkspaceEntityManager } from 'src/engine/twenty-orm/entity-manager/workspace-entity-manager';
|
||||
import { shouldSeedWorkspaceFavorite } from 'src/engine/utils/should-seed-workspace-favorite';
|
||||
import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service';
|
||||
import {
|
||||
API_KEY_DATA_SEED_COLUMNS,
|
||||
API_KEY_DATA_SEEDS,
|
||||
} from 'src/engine/workspace-manager/dev-seeder/data/constants/api-key-data-seeds.constant';
|
||||
import {
|
||||
CALENDAR_CHANNEL_DATA_SEED_COLUMNS,
|
||||
CALENDAR_CHANNEL_DATA_SEEDS,
|
||||
} from 'src/engine/workspace-manager/dev-seeder/data/constants/calendar-channel-data-seeds.constant';
|
||||
import {
|
||||
CALENDAR_CHANNEL_EVENT_ASSOCIATION_DATA_SEED_COLUMNS,
|
||||
CALENDAR_CHANNEL_EVENT_ASSOCIATION_DATA_SEEDS,
|
||||
} from 'src/engine/workspace-manager/dev-seeder/data/constants/calendar-channel-event-association-data-seeds.constant';
|
||||
import {
|
||||
CALENDAR_EVENT_DATA_SEED_COLUMNS,
|
||||
CALENDAR_EVENT_DATA_SEEDS,
|
||||
} from 'src/engine/workspace-manager/dev-seeder/data/constants/calendar-event-data-seeds.constant';
|
||||
import {
|
||||
CALENDAR_EVENT_PARTICIPANT_DATA_SEED_COLUMNS,
|
||||
CALENDAR_EVENT_PARTICIPANT_DATA_SEEDS,
|
||||
} from 'src/engine/workspace-manager/dev-seeder/data/constants/calendar-event-participant-data-seeds.constant';
|
||||
import {
|
||||
COMPANY_DATA_SEED_COLUMNS,
|
||||
COMPANY_DATA_SEEDS,
|
||||
} from 'src/engine/workspace-manager/dev-seeder/data/constants/company-data-seeds.constant';
|
||||
import {
|
||||
CONNECTED_ACCOUNT_DATA_SEED_COLUMNS,
|
||||
CONNECTED_ACCOUNT_DATA_SEEDS,
|
||||
} from 'src/engine/workspace-manager/dev-seeder/data/constants/connected-account-data-seeds.constant';
|
||||
import {
|
||||
MESSAGE_CHANNEL_DATA_SEED_COLUMNS,
|
||||
MESSAGE_CHANNEL_DATA_SEEDS,
|
||||
} from 'src/engine/workspace-manager/dev-seeder/data/constants/message-channel-data-seeds.constant';
|
||||
import {
|
||||
MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_DATA_SEED_COLUMNS,
|
||||
MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_DATA_SEEDS,
|
||||
} from 'src/engine/workspace-manager/dev-seeder/data/constants/message-channel-message-association-data-seeds.constant';
|
||||
import {
|
||||
MESSAGE_DATA_SEED_COLUMNS,
|
||||
MESSAGE_DATA_SEEDS,
|
||||
} from 'src/engine/workspace-manager/dev-seeder/data/constants/message-data-seeds.constant';
|
||||
import {
|
||||
MESSAGE_PARTICIPANT_DATA_SEED_COLUMNS,
|
||||
MESSAGE_PARTICIPANT_DATA_SEEDS,
|
||||
} from 'src/engine/workspace-manager/dev-seeder/data/constants/message-participant-data-seeds.constant';
|
||||
import {
|
||||
MESSAGE_THREAD_DATA_SEED_COLUMNS,
|
||||
MESSAGE_THREAD_DATA_SEEDS,
|
||||
} from 'src/engine/workspace-manager/dev-seeder/data/constants/message-thread-data-seeds.constant';
|
||||
import {
|
||||
OPPORTUNITY_DATA_SEED_COLUMNS,
|
||||
OPPORTUNITY_DATA_SEEDS,
|
||||
} from 'src/engine/workspace-manager/dev-seeder/data/constants/opportunity-data-seeds.constant';
|
||||
import {
|
||||
PERSON_DATA_SEED_COLUMNS,
|
||||
PERSON_DATA_SEEDS,
|
||||
} from 'src/engine/workspace-manager/dev-seeder/data/constants/person-data-seeds.constant';
|
||||
import {
|
||||
PET_DATA_SEED_COLUMNS,
|
||||
PET_DATA_SEEDS,
|
||||
} from 'src/engine/workspace-manager/dev-seeder/data/constants/pet-data-seeds.constant';
|
||||
import {
|
||||
SURVEY_RESULT_DATA_SEED_COLUMNS,
|
||||
SURVEY_RESULT_DATA_SEEDS,
|
||||
} from 'src/engine/workspace-manager/dev-seeder/data/constants/survey-result-data-seeds.constant';
|
||||
import {
|
||||
WORKSPACE_MEMBER_DATA_SEED_COLUMNS,
|
||||
WORKSPACE_MEMBER_DATA_SEEDS,
|
||||
} from 'src/engine/workspace-manager/dev-seeder/data/constants/workspace-member-data-seeds.constant';
|
||||
import { prefillViews } from 'src/engine/workspace-manager/standard-objects-prefill-data/prefill-views';
|
||||
import { prefillWorkspaceFavorites } from 'src/engine/workspace-manager/standard-objects-prefill-data/prefill-workspace-favorites';
|
||||
|
||||
const RECORD_SEEDS_CONFIGS = [
|
||||
{
|
||||
tableName: 'workspaceMember',
|
||||
pgColumns: WORKSPACE_MEMBER_DATA_SEED_COLUMNS,
|
||||
recordSeeds: WORKSPACE_MEMBER_DATA_SEEDS,
|
||||
},
|
||||
{
|
||||
tableName: 'company',
|
||||
pgColumns: COMPANY_DATA_SEED_COLUMNS,
|
||||
recordSeeds: COMPANY_DATA_SEEDS,
|
||||
},
|
||||
{
|
||||
tableName: 'person',
|
||||
pgColumns: PERSON_DATA_SEED_COLUMNS,
|
||||
recordSeeds: PERSON_DATA_SEEDS,
|
||||
},
|
||||
{
|
||||
tableName: 'opportunity',
|
||||
pgColumns: OPPORTUNITY_DATA_SEED_COLUMNS,
|
||||
recordSeeds: OPPORTUNITY_DATA_SEEDS,
|
||||
},
|
||||
{
|
||||
tableName: 'apiKey',
|
||||
pgColumns: API_KEY_DATA_SEED_COLUMNS,
|
||||
recordSeeds: API_KEY_DATA_SEEDS,
|
||||
},
|
||||
{
|
||||
tableName: 'connectedAccount',
|
||||
pgColumns: CONNECTED_ACCOUNT_DATA_SEED_COLUMNS,
|
||||
recordSeeds: CONNECTED_ACCOUNT_DATA_SEEDS,
|
||||
},
|
||||
{
|
||||
tableName: 'calendarChannel',
|
||||
pgColumns: CALENDAR_CHANNEL_DATA_SEED_COLUMNS,
|
||||
recordSeeds: CALENDAR_CHANNEL_DATA_SEEDS,
|
||||
},
|
||||
{
|
||||
tableName: 'calendarEvent',
|
||||
pgColumns: CALENDAR_EVENT_DATA_SEED_COLUMNS,
|
||||
recordSeeds: CALENDAR_EVENT_DATA_SEEDS,
|
||||
},
|
||||
{
|
||||
tableName: 'calendarChannelEventAssociation',
|
||||
pgColumns: CALENDAR_CHANNEL_EVENT_ASSOCIATION_DATA_SEED_COLUMNS,
|
||||
recordSeeds: CALENDAR_CHANNEL_EVENT_ASSOCIATION_DATA_SEEDS,
|
||||
},
|
||||
{
|
||||
tableName: 'calendarEventParticipant',
|
||||
pgColumns: CALENDAR_EVENT_PARTICIPANT_DATA_SEED_COLUMNS,
|
||||
recordSeeds: CALENDAR_EVENT_PARTICIPANT_DATA_SEEDS,
|
||||
},
|
||||
{
|
||||
tableName: 'messageChannel',
|
||||
pgColumns: MESSAGE_CHANNEL_DATA_SEED_COLUMNS,
|
||||
recordSeeds: MESSAGE_CHANNEL_DATA_SEEDS,
|
||||
},
|
||||
{
|
||||
tableName: 'messageThread',
|
||||
pgColumns: MESSAGE_THREAD_DATA_SEED_COLUMNS,
|
||||
recordSeeds: MESSAGE_THREAD_DATA_SEEDS,
|
||||
},
|
||||
{
|
||||
tableName: 'message',
|
||||
pgColumns: MESSAGE_DATA_SEED_COLUMNS,
|
||||
recordSeeds: MESSAGE_DATA_SEEDS,
|
||||
},
|
||||
{
|
||||
tableName: 'messageChannelMessageAssociation',
|
||||
pgColumns: MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_DATA_SEED_COLUMNS,
|
||||
recordSeeds: MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_DATA_SEEDS,
|
||||
},
|
||||
{
|
||||
tableName: 'messageParticipant',
|
||||
pgColumns: MESSAGE_PARTICIPANT_DATA_SEED_COLUMNS,
|
||||
recordSeeds: MESSAGE_PARTICIPANT_DATA_SEEDS,
|
||||
},
|
||||
{
|
||||
tableName: '_pet',
|
||||
pgColumns: PET_DATA_SEED_COLUMNS,
|
||||
recordSeeds: PET_DATA_SEEDS,
|
||||
},
|
||||
{
|
||||
tableName: '_surveyResult',
|
||||
pgColumns: SURVEY_RESULT_DATA_SEED_COLUMNS,
|
||||
recordSeeds: SURVEY_RESULT_DATA_SEEDS,
|
||||
},
|
||||
];
|
||||
|
||||
@Injectable()
|
||||
export class DevSeederDataService {
|
||||
constructor(
|
||||
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
||||
private readonly objectMetadataService: ObjectMetadataService,
|
||||
) {}
|
||||
|
||||
public async seed({
|
||||
schemaName,
|
||||
workspaceId,
|
||||
}: {
|
||||
schemaName: string;
|
||||
workspaceId: string;
|
||||
}) {
|
||||
const mainDataSource =
|
||||
await this.workspaceDataSourceService.connectToMainDataSource();
|
||||
|
||||
if (!mainDataSource) {
|
||||
throw new Error('Could not connect to main data source');
|
||||
}
|
||||
|
||||
const objectMetadataItems =
|
||||
await this.objectMetadataService.findManyWithinWorkspace(workspaceId);
|
||||
|
||||
await mainDataSource.transaction(
|
||||
async (entityManager: WorkspaceEntityManager) => {
|
||||
for (const recordSeedsConfig of RECORD_SEEDS_CONFIGS) {
|
||||
await this.seedRecords({
|
||||
entityManager,
|
||||
schemaName,
|
||||
tableName: recordSeedsConfig.tableName,
|
||||
pgColumns: recordSeedsConfig.pgColumns,
|
||||
recordSeeds: recordSeedsConfig.recordSeeds,
|
||||
});
|
||||
}
|
||||
|
||||
const viewDefinitionsWithId = await prefillViews(
|
||||
entityManager,
|
||||
schemaName,
|
||||
objectMetadataItems,
|
||||
);
|
||||
|
||||
await prefillWorkspaceFavorites(
|
||||
viewDefinitionsWithId
|
||||
.filter(
|
||||
(view) =>
|
||||
view.key === 'INDEX' &&
|
||||
shouldSeedWorkspaceFavorite(
|
||||
view.objectMetadataId,
|
||||
objectMetadataItems,
|
||||
),
|
||||
)
|
||||
.map((view) => view.id),
|
||||
entityManager,
|
||||
schemaName,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
private async seedRecords({
|
||||
entityManager,
|
||||
schemaName,
|
||||
tableName,
|
||||
pgColumns,
|
||||
recordSeeds,
|
||||
}: {
|
||||
entityManager: WorkspaceEntityManager;
|
||||
schemaName: string;
|
||||
tableName: string;
|
||||
pgColumns: string[];
|
||||
recordSeeds: Record<string, unknown>[];
|
||||
}) {
|
||||
await entityManager
|
||||
.createQueryBuilder(undefined, undefined, undefined, {
|
||||
shouldBypassPermissionChecks: true,
|
||||
})
|
||||
.insert()
|
||||
.into(`${schemaName}.${tableName}`, pgColumns)
|
||||
.orIgnore()
|
||||
.values(recordSeeds)
|
||||
.returning('*')
|
||||
.execute();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { TypeORMModule } from 'src/database/typeorm/typeorm.module';
|
||||
import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module';
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module';
|
||||
import { FieldMetadataModule } from 'src/engine/metadata-modules/field-metadata/field-metadata.module';
|
||||
import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadata/object-metadata.module';
|
||||
import { RoleModule } from 'src/engine/metadata-modules/role/role.module';
|
||||
import { UserRoleModule } from 'src/engine/metadata-modules/user-role/user-role.module';
|
||||
import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/workspace-cache-storage.module';
|
||||
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
||||
import { DevSeederPermissionsService } from 'src/engine/workspace-manager/dev-seeder/core/services/dev-seeder-permissions.service';
|
||||
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 { DevSeederService } from 'src/engine/workspace-manager/dev-seeder/services/dev-seeder.service';
|
||||
import { WorkspaceSyncMetadataModule } from 'src/engine/workspace-manager/workspace-sync-metadata/workspace-sync-metadata.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
ObjectMetadataModule,
|
||||
FieldMetadataModule,
|
||||
WorkspaceDataSourceModule,
|
||||
WorkspaceCacheStorageModule,
|
||||
TypeORMModule,
|
||||
DataSourceModule,
|
||||
RoleModule,
|
||||
UserRoleModule,
|
||||
FeatureFlagModule,
|
||||
WorkspaceSyncMetadataModule,
|
||||
TypeOrmModule.forFeature([Workspace], 'core'),
|
||||
],
|
||||
exports: [DevSeederService],
|
||||
providers: [
|
||||
DevSeederService,
|
||||
DevSeederMetadataService,
|
||||
DevSeederPermissionsService,
|
||||
DevSeederDataService,
|
||||
],
|
||||
})
|
||||
export class DevSeederModule {}
|
||||
@ -0,0 +1,68 @@
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import { FieldMetadataSeed } from 'src/engine/workspace-manager/dev-seeder/metadata/types/field-metadata-seed.type';
|
||||
|
||||
export const COMPANY_CUSTOM_FIELD_SEEDS: FieldMetadataSeed[] = [
|
||||
{
|
||||
type: FieldMetadataType.TEXT,
|
||||
name: 'tagline',
|
||||
label: 'Tagline',
|
||||
description: "Company's Tagline",
|
||||
icon: 'IconAdCircle',
|
||||
isActive: true,
|
||||
isNullable: false,
|
||||
isUnique: false,
|
||||
defaultValue: "''",
|
||||
},
|
||||
{
|
||||
type: FieldMetadataType.LINKS,
|
||||
name: 'introVideo',
|
||||
label: 'Intro Video',
|
||||
description: "Company's Intro Video",
|
||||
icon: 'IconVideo',
|
||||
isActive: true,
|
||||
isNullable: true,
|
||||
isUnique: false,
|
||||
},
|
||||
{
|
||||
type: FieldMetadataType.MULTI_SELECT,
|
||||
name: 'workPolicy',
|
||||
label: 'Work Policy',
|
||||
description: "Company's Work Policy",
|
||||
icon: 'IconHome',
|
||||
isActive: true,
|
||||
isNullable: true,
|
||||
isUnique: false,
|
||||
options: [
|
||||
{
|
||||
color: 'green',
|
||||
label: 'On-Site',
|
||||
position: 0,
|
||||
value: 'ON_SITE',
|
||||
},
|
||||
{
|
||||
color: 'turquoise',
|
||||
label: 'Hybrid',
|
||||
position: 1,
|
||||
value: 'HYBRID',
|
||||
},
|
||||
{
|
||||
color: 'sky',
|
||||
label: 'Remote Work',
|
||||
position: 2,
|
||||
value: 'REMOTE_WORK',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: FieldMetadataType.BOOLEAN,
|
||||
name: 'visaSponsorship',
|
||||
label: 'Visa Sponsorship',
|
||||
description: "Company's Visa Sponsorship Policy",
|
||||
icon: 'IconBrandVisa',
|
||||
isActive: true,
|
||||
isNullable: true,
|
||||
isUnique: false,
|
||||
defaultValue: false,
|
||||
},
|
||||
];
|
||||
@ -0,0 +1,99 @@
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import { FieldMetadataSeed } from 'src/engine/workspace-manager/dev-seeder/metadata/types/field-metadata-seed.type';
|
||||
|
||||
export const PERSON_CUSTOM_FIELD_SEEDS: FieldMetadataSeed[] = [
|
||||
{
|
||||
type: FieldMetadataType.TEXT,
|
||||
name: 'intro',
|
||||
label: 'Intro',
|
||||
description: "Contact's Intro",
|
||||
icon: 'IconNote',
|
||||
isActive: true,
|
||||
isNullable: true,
|
||||
isUnique: false,
|
||||
},
|
||||
{
|
||||
type: FieldMetadataType.PHONES,
|
||||
name: 'whatsapp',
|
||||
label: 'Whatsapp',
|
||||
description: "Contact's Whatsapp Number",
|
||||
icon: 'IconBrandWhatsapp',
|
||||
isActive: true,
|
||||
isNullable: false,
|
||||
isUnique: false,
|
||||
defaultValue: {
|
||||
primaryPhoneNumber: "''",
|
||||
primaryPhoneCountryCode: "'FR'",
|
||||
primaryPhoneCallingCode: "'+33'",
|
||||
additionalPhones: null,
|
||||
},
|
||||
},
|
||||
{
|
||||
type: FieldMetadataType.MULTI_SELECT,
|
||||
name: 'workPreference',
|
||||
label: 'Work Preference',
|
||||
description: "Person's Work Preference",
|
||||
icon: 'IconHome',
|
||||
isActive: true,
|
||||
isNullable: true,
|
||||
isUnique: false,
|
||||
options: [
|
||||
{
|
||||
color: 'green',
|
||||
label: 'On-Site',
|
||||
position: 0,
|
||||
value: 'ON_SITE',
|
||||
},
|
||||
{
|
||||
color: 'turquoise',
|
||||
label: 'Hybrid',
|
||||
position: 1,
|
||||
value: 'HYBRID',
|
||||
},
|
||||
{
|
||||
color: 'sky',
|
||||
label: 'Remote Work',
|
||||
position: 2,
|
||||
value: 'REMOTE_WORK',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: FieldMetadataType.RATING,
|
||||
name: 'performanceRating',
|
||||
label: 'Performance Rating',
|
||||
description: "Person's Performance Rating",
|
||||
icon: 'IconStars',
|
||||
isActive: true,
|
||||
isNullable: true,
|
||||
isUnique: false,
|
||||
options: [
|
||||
{
|
||||
label: '1',
|
||||
value: 'RATING_1',
|
||||
position: 0,
|
||||
},
|
||||
{
|
||||
label: '2',
|
||||
value: 'RATING_2',
|
||||
position: 1,
|
||||
},
|
||||
{
|
||||
label: '3',
|
||||
value: 'RATING_3',
|
||||
position: 2,
|
||||
},
|
||||
{
|
||||
label: '4',
|
||||
value: 'RATING_4',
|
||||
position: 3,
|
||||
},
|
||||
{
|
||||
label: '5',
|
||||
value: 'RATING_5',
|
||||
position: 4,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
@ -0,0 +1,107 @@
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import { FieldMetadataSeed } from 'src/engine/workspace-manager/dev-seeder/metadata/types/field-metadata-seed.type';
|
||||
|
||||
export const PET_CUSTOM_FIELD_SEEDS: FieldMetadataSeed[] = [
|
||||
{
|
||||
type: FieldMetadataType.SELECT,
|
||||
label: 'Species',
|
||||
name: 'species',
|
||||
options: [
|
||||
{ label: 'Dog', value: 'DOG', position: 0, color: 'blue' },
|
||||
{ label: 'Cat', value: 'CAT', position: 1, color: 'red' },
|
||||
{ label: 'Bird', value: 'BIRD', position: 2, color: 'green' },
|
||||
{ label: 'Fish', value: 'FISH', position: 3, color: 'yellow' },
|
||||
{ label: 'Rabbit', value: 'RABBIT', position: 4, color: 'purple' },
|
||||
{ label: 'Hamster', value: 'HAMSTER', position: 5, color: 'orange' },
|
||||
],
|
||||
},
|
||||
{
|
||||
type: FieldMetadataType.MULTI_SELECT,
|
||||
label: 'Traits',
|
||||
name: 'traits',
|
||||
options: [
|
||||
{ label: 'Playful', value: 'PLAYFUL', position: 0, color: 'blue' },
|
||||
{ label: 'Friendly', value: 'FRIENDLY', position: 1, color: 'red' },
|
||||
{
|
||||
label: 'Protective',
|
||||
value: 'PROTECTIVE',
|
||||
position: 2,
|
||||
color: 'green',
|
||||
},
|
||||
{ label: 'Shy', value: 'SHY', position: 3, color: 'yellow' },
|
||||
{ label: 'Brave', value: 'BRAVE', position: 4, color: 'purple' },
|
||||
{ label: 'Curious', value: 'CURIOUS', position: 5, color: 'orange' },
|
||||
],
|
||||
},
|
||||
{
|
||||
type: FieldMetadataType.TEXT,
|
||||
label: 'Comments',
|
||||
name: 'comments',
|
||||
},
|
||||
{
|
||||
type: FieldMetadataType.NUMBER,
|
||||
label: 'Age',
|
||||
name: 'age',
|
||||
},
|
||||
{
|
||||
type: FieldMetadataType.ADDRESS,
|
||||
label: 'Location',
|
||||
name: 'location',
|
||||
},
|
||||
{
|
||||
type: FieldMetadataType.PHONES,
|
||||
label: 'Vet phone',
|
||||
name: 'vetPhone',
|
||||
},
|
||||
{
|
||||
type: FieldMetadataType.EMAILS,
|
||||
label: 'Vet email',
|
||||
name: 'vetEmail',
|
||||
},
|
||||
{
|
||||
type: FieldMetadataType.DATE,
|
||||
label: 'Birthday',
|
||||
name: 'birthday',
|
||||
},
|
||||
{
|
||||
type: FieldMetadataType.BOOLEAN,
|
||||
label: 'Is good with kids',
|
||||
name: 'isGoodWithKids',
|
||||
},
|
||||
{
|
||||
type: FieldMetadataType.LINKS,
|
||||
label: 'Pictures',
|
||||
name: 'pictures',
|
||||
},
|
||||
{
|
||||
type: FieldMetadataType.CURRENCY,
|
||||
label: 'Average cost of kibble per month',
|
||||
name: 'averageCostOfKibblePerMonth',
|
||||
},
|
||||
{
|
||||
type: FieldMetadataType.FULL_NAME,
|
||||
label: 'Makes its owner think of',
|
||||
name: 'makesOwnerThinkOf',
|
||||
},
|
||||
{
|
||||
type: FieldMetadataType.RATING,
|
||||
label: 'Sound swag (bark style, meow style, etc.)',
|
||||
name: 'soundSwag',
|
||||
},
|
||||
{
|
||||
type: FieldMetadataType.RICH_TEXT,
|
||||
label: 'Bio',
|
||||
name: 'bio',
|
||||
},
|
||||
{
|
||||
type: FieldMetadataType.ARRAY,
|
||||
label: 'Interesting facts',
|
||||
name: 'interestingFacts',
|
||||
},
|
||||
{
|
||||
type: FieldMetadataType.RAW_JSON,
|
||||
label: 'Extra data',
|
||||
name: 'extraData',
|
||||
},
|
||||
];
|
||||
@ -0,0 +1,63 @@
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import { NumberDataType } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata-settings.interface';
|
||||
|
||||
import { FieldMetadataDTO } from 'src/engine/metadata-modules/field-metadata/dtos/field-metadata.dto';
|
||||
import { FieldMetadataSeed } from 'src/engine/workspace-manager/dev-seeder/metadata/types/field-metadata-seed.type';
|
||||
|
||||
export const SURVEY_RESULT_CUSTOM_FIELD_SEEDS: FieldMetadataSeed[] = [
|
||||
{
|
||||
type: FieldMetadataType.NUMBER,
|
||||
label: 'Score (Float 3 decimals)',
|
||||
name: 'score',
|
||||
settings: {
|
||||
dataType: NumberDataType.FLOAT,
|
||||
decimals: 3,
|
||||
type: 'number',
|
||||
},
|
||||
} as FieldMetadataDTO<FieldMetadataType.NUMBER>,
|
||||
{
|
||||
type: FieldMetadataType.NUMBER,
|
||||
label: 'Percentage of completion (Float 3 decimals + percentage)',
|
||||
name: 'percentageOfCompletion',
|
||||
settings: {
|
||||
dataType: NumberDataType.FLOAT,
|
||||
decimals: 6,
|
||||
type: 'percentage',
|
||||
},
|
||||
} as FieldMetadataDTO<FieldMetadataType.NUMBER>,
|
||||
{
|
||||
type: FieldMetadataType.NUMBER,
|
||||
label: 'Participants (Int)',
|
||||
name: 'participants',
|
||||
settings: {
|
||||
dataType: NumberDataType.INT,
|
||||
type: 'number',
|
||||
},
|
||||
} as FieldMetadataDTO<FieldMetadataType.NUMBER>,
|
||||
{
|
||||
type: FieldMetadataType.NUMBER,
|
||||
label: 'Average estimated number of atoms in the universe (BigInt)',
|
||||
name: 'averageEstimatedNumberOfAtomsInTheUniverse',
|
||||
settings: {
|
||||
dataType: NumberDataType.BIGINT,
|
||||
type: 'number',
|
||||
},
|
||||
} as FieldMetadataDTO<FieldMetadataType.NUMBER>,
|
||||
{
|
||||
type: FieldMetadataType.TEXT,
|
||||
label: 'Comments (Max 5 rows)',
|
||||
name: 'comments',
|
||||
settings: {
|
||||
displayedMaxRows: 5,
|
||||
},
|
||||
} as FieldMetadataDTO<FieldMetadataType.TEXT>,
|
||||
{
|
||||
type: FieldMetadataType.TEXT,
|
||||
label: 'Short notes (Max 1 row)',
|
||||
name: 'shortNotes',
|
||||
settings: {
|
||||
displayedMaxRows: 1,
|
||||
},
|
||||
} as FieldMetadataDTO<FieldMetadataType.TEXT>,
|
||||
];
|
||||
@ -0,0 +1,9 @@
|
||||
import { ObjectMetadataSeed } from 'src/engine/workspace-manager/dev-seeder/metadata/types/object-metadata-seed.type';
|
||||
|
||||
export const PET_CUSTOM_OBJECT_SEED: ObjectMetadataSeed = {
|
||||
labelPlural: 'Pets',
|
||||
labelSingular: 'Pet',
|
||||
namePlural: 'pets',
|
||||
nameSingular: 'pet',
|
||||
icon: 'IconCat',
|
||||
};
|
||||
@ -0,0 +1,11 @@
|
||||
import { ObjectMetadataSeed } from 'src/engine/workspace-manager/dev-seeder/metadata/types/object-metadata-seed.type';
|
||||
|
||||
export const ROCKET_CUSTOM_OBJECT_SEED: ObjectMetadataSeed = {
|
||||
labelPlural: 'Rockets',
|
||||
labelSingular: 'Rocket',
|
||||
namePlural: 'rockets',
|
||||
nameSingular: 'rocket',
|
||||
icon: 'IconRocket',
|
||||
description: 'A rocket',
|
||||
isRemote: false,
|
||||
};
|
||||
@ -0,0 +1,9 @@
|
||||
import { ObjectMetadataSeed } from 'src/engine/workspace-manager/dev-seeder/metadata/types/object-metadata-seed.type';
|
||||
|
||||
export const SURVEY_RESULT_CUSTOM_OBJECT_SEED: ObjectMetadataSeed = {
|
||||
labelPlural: 'Survey results',
|
||||
labelSingular: 'Survey result',
|
||||
namePlural: 'surveyResults',
|
||||
nameSingular: 'surveyResult',
|
||||
icon: 'IconRulerMeasure',
|
||||
};
|
||||
@ -0,0 +1,115 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { DataSourceEntity } from 'src/engine/metadata-modules/data-source/data-source.entity';
|
||||
import { FieldMetadataService } from 'src/engine/metadata-modules/field-metadata/field-metadata.service';
|
||||
import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service';
|
||||
import { COMPANY_CUSTOM_FIELD_SEEDS } from 'src/engine/workspace-manager/dev-seeder/metadata/custom-fields/constants/company-custom-field-seeds.constant';
|
||||
import { PERSON_CUSTOM_FIELD_SEEDS } from 'src/engine/workspace-manager/dev-seeder/metadata/custom-fields/constants/person-custom-field-seeds.constant';
|
||||
import { PET_CUSTOM_FIELD_SEEDS } from 'src/engine/workspace-manager/dev-seeder/metadata/custom-fields/constants/pet-custom-field-seeds.constant';
|
||||
import { SURVEY_RESULT_CUSTOM_FIELD_SEEDS } from 'src/engine/workspace-manager/dev-seeder/metadata/custom-fields/constants/survey-results-field-seeds.constant';
|
||||
import { PET_CUSTOM_OBJECT_SEED } from 'src/engine/workspace-manager/dev-seeder/metadata/custom-objects/constants/pet-custom-object-seed.constant';
|
||||
import { ROCKET_CUSTOM_OBJECT_SEED } from 'src/engine/workspace-manager/dev-seeder/metadata/custom-objects/constants/rocket-custom-object-seed.constant';
|
||||
import { SURVEY_RESULT_CUSTOM_OBJECT_SEED } from 'src/engine/workspace-manager/dev-seeder/metadata/custom-objects/constants/survey-results-object-seed.constant';
|
||||
import { FieldMetadataSeed } from 'src/engine/workspace-manager/dev-seeder/metadata/types/field-metadata-seed.type';
|
||||
import { ObjectMetadataSeed } from 'src/engine/workspace-manager/dev-seeder/metadata/types/object-metadata-seed.type';
|
||||
|
||||
@Injectable()
|
||||
export class DevSeederMetadataService {
|
||||
constructor(
|
||||
private readonly objectMetadataService: ObjectMetadataService,
|
||||
private readonly fieldMetadataService: FieldMetadataService,
|
||||
) {}
|
||||
|
||||
public async seed({
|
||||
dataSourceMetadata,
|
||||
workspaceId,
|
||||
}: {
|
||||
dataSourceMetadata: DataSourceEntity;
|
||||
workspaceId: string;
|
||||
}) {
|
||||
await this.seedCustomObject({
|
||||
dataSourceId: dataSourceMetadata.id,
|
||||
workspaceId,
|
||||
objectMetadataSeed: ROCKET_CUSTOM_OBJECT_SEED,
|
||||
});
|
||||
|
||||
await this.seedCustomObject({
|
||||
dataSourceId: dataSourceMetadata.id,
|
||||
workspaceId,
|
||||
objectMetadataSeed: PET_CUSTOM_OBJECT_SEED,
|
||||
});
|
||||
|
||||
await this.seedCustomFields({
|
||||
workspaceId,
|
||||
objectMetadataNameSingular: PET_CUSTOM_OBJECT_SEED.nameSingular,
|
||||
fieldMetadataSeeds: PET_CUSTOM_FIELD_SEEDS,
|
||||
});
|
||||
|
||||
await this.seedCustomObject({
|
||||
dataSourceId: dataSourceMetadata.id,
|
||||
workspaceId,
|
||||
objectMetadataSeed: SURVEY_RESULT_CUSTOM_OBJECT_SEED,
|
||||
});
|
||||
|
||||
await this.seedCustomFields({
|
||||
workspaceId,
|
||||
objectMetadataNameSingular: SURVEY_RESULT_CUSTOM_OBJECT_SEED.nameSingular,
|
||||
fieldMetadataSeeds: SURVEY_RESULT_CUSTOM_FIELD_SEEDS,
|
||||
});
|
||||
|
||||
await this.seedCustomFields({
|
||||
workspaceId,
|
||||
objectMetadataNameSingular: 'company',
|
||||
fieldMetadataSeeds: COMPANY_CUSTOM_FIELD_SEEDS,
|
||||
});
|
||||
|
||||
await this.seedCustomFields({
|
||||
workspaceId,
|
||||
objectMetadataNameSingular: 'person',
|
||||
fieldMetadataSeeds: PERSON_CUSTOM_FIELD_SEEDS,
|
||||
});
|
||||
}
|
||||
|
||||
private async seedCustomObject({
|
||||
dataSourceId,
|
||||
workspaceId,
|
||||
objectMetadataSeed,
|
||||
}: {
|
||||
dataSourceId: string;
|
||||
workspaceId: string;
|
||||
objectMetadataSeed: ObjectMetadataSeed;
|
||||
}): Promise<void> {
|
||||
await this.objectMetadataService.createOne({
|
||||
...objectMetadataSeed,
|
||||
dataSourceId,
|
||||
workspaceId,
|
||||
});
|
||||
}
|
||||
|
||||
private async seedCustomFields({
|
||||
workspaceId,
|
||||
objectMetadataNameSingular,
|
||||
fieldMetadataSeeds,
|
||||
}: {
|
||||
workspaceId: string;
|
||||
objectMetadataNameSingular: string;
|
||||
fieldMetadataSeeds: FieldMetadataSeed[];
|
||||
}): Promise<void> {
|
||||
const objectMetadata =
|
||||
await this.objectMetadataService.findOneWithinWorkspace(workspaceId, {
|
||||
where: { nameSingular: objectMetadataNameSingular },
|
||||
});
|
||||
|
||||
if (!objectMetadata) {
|
||||
throw new Error('Object metadata not found');
|
||||
}
|
||||
|
||||
await this.fieldMetadataService.createMany(
|
||||
fieldMetadataSeeds.map((fieldMetadataSeed) => ({
|
||||
...fieldMetadataSeed,
|
||||
objectMetadataId: objectMetadata.id,
|
||||
workspaceId,
|
||||
})),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,6 @@
|
||||
import { CreateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input';
|
||||
|
||||
export type FieldMetadataSeed = Omit<
|
||||
CreateFieldInput,
|
||||
'objectMetadataId' | 'workspaceId'
|
||||
>;
|
||||
@ -0,0 +1,6 @@
|
||||
import { CreateObjectInput } from 'src/engine/metadata-modules/object-metadata/dtos/create-object.input';
|
||||
|
||||
export type ObjectMetadataSeed = Omit<
|
||||
CreateObjectInput,
|
||||
'workspaceId' | 'dataSourceId' | 'fields'
|
||||
>;
|
||||
@ -0,0 +1,83 @@
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
|
||||
import { TypeORMService } from 'src/database/typeorm/typeorm.service';
|
||||
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';
|
||||
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
||||
import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service';
|
||||
import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service';
|
||||
import { DevSeederPermissionsService } from 'src/engine/workspace-manager/dev-seeder/core/services/dev-seeder-permissions.service';
|
||||
import { seedCoreSchema } from 'src/engine/workspace-manager/dev-seeder/core/utils/seed-core-schema.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 { WorkspaceSyncMetadataService } from 'src/engine/workspace-manager/workspace-sync-metadata/workspace-sync-metadata.service';
|
||||
|
||||
@Injectable()
|
||||
export class DevSeederService {
|
||||
private readonly logger = new Logger(DevSeederService.name);
|
||||
|
||||
constructor(
|
||||
private readonly typeORMService: TypeORMService,
|
||||
private readonly workspaceCacheStorageService: WorkspaceCacheStorageService,
|
||||
private readonly twentyConfigService: TwentyConfigService,
|
||||
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
||||
private readonly dataSourceService: DataSourceService,
|
||||
private readonly featureFlagService: FeatureFlagService,
|
||||
private readonly workspaceSyncMetadataService: WorkspaceSyncMetadataService,
|
||||
private readonly devSeederMetadataService: DevSeederMetadataService,
|
||||
private readonly devSeederPermissionsService: DevSeederPermissionsService,
|
||||
private readonly devSeederDataService: DevSeederDataService,
|
||||
) {}
|
||||
|
||||
public async seedDev(workspaceId: string): Promise<void> {
|
||||
const mainDataSource = this.typeORMService.getMainDataSource();
|
||||
|
||||
if (!mainDataSource) {
|
||||
throw new Error('Could not connect to workspace data source');
|
||||
}
|
||||
|
||||
const isBillingEnabled = this.twentyConfigService.get('IS_BILLING_ENABLED');
|
||||
const appVersion = this.twentyConfigService.get('APP_VERSION');
|
||||
|
||||
await seedCoreSchema({
|
||||
dataSource: mainDataSource,
|
||||
workspaceId,
|
||||
seedBilling: isBillingEnabled,
|
||||
appVersion,
|
||||
});
|
||||
|
||||
const schemaName =
|
||||
await this.workspaceDataSourceService.createWorkspaceDBSchema(
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
const dataSourceMetadata =
|
||||
await this.dataSourceService.createDataSourceMetadata(
|
||||
workspaceId,
|
||||
schemaName,
|
||||
);
|
||||
|
||||
const featureFlags =
|
||||
await this.featureFlagService.getWorkspaceFeatureFlagsMap(workspaceId);
|
||||
|
||||
await this.workspaceSyncMetadataService.synchronize({
|
||||
workspaceId: workspaceId,
|
||||
dataSourceId: dataSourceMetadata.id,
|
||||
featureFlags,
|
||||
});
|
||||
|
||||
await this.devSeederMetadataService.seed({
|
||||
dataSourceMetadata,
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
await this.devSeederPermissionsService.initPermissions(workspaceId);
|
||||
|
||||
await this.devSeederDataService.seed({
|
||||
schemaName: dataSourceMetadata.schema,
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
await this.workspaceCacheStorageService.flush(workspaceId, undefined);
|
||||
}
|
||||
}
|
||||
@ -7,7 +7,7 @@ export const STRIPE_ID = '1f70157c-4ea5-4d81-bc49-e1401abfbb94';
|
||||
export const FIGMA_ID = '9d5bcf43-7d38-4e88-82cb-d6d4ce638bf0';
|
||||
export const NOTION_ID = '06290608-8bf0-4806-99ae-a715a6a93fad';
|
||||
|
||||
export const companyPrefillData = async (
|
||||
export const prefillCompanies = async (
|
||||
entityManager: WorkspaceEntityManager,
|
||||
schemaName: string,
|
||||
) => {
|
||||
@ -6,10 +6,9 @@ import {
|
||||
FIGMA_ID,
|
||||
NOTION_ID,
|
||||
STRIPE_ID,
|
||||
} from 'src/engine/workspace-manager/standard-objects-prefill-data/company';
|
||||
} from 'src/engine/workspace-manager/standard-objects-prefill-data/prefill-companies';
|
||||
|
||||
// FixMe: Is this file a duplicate of src/database/typeorm-seeds/workspace/people.ts
|
||||
export const personPrefillData = async (
|
||||
export const prefillPeople = async (
|
||||
entityManager: WorkspaceEntityManager,
|
||||
schemaName: string,
|
||||
) => {
|
||||
@ -1,9 +1,53 @@
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { WorkspaceEntityManager } from 'src/engine/twenty-orm/entity-manager/workspace-entity-manager';
|
||||
import { ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface';
|
||||
import { companiesAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/companies-all.view';
|
||||
import { customAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/custom-all.view';
|
||||
import { notesAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/notes-all.view';
|
||||
import { opportunitiesAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/opportunities-all.view';
|
||||
import { opportunitiesByStageView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/opportunity-by-stage.view';
|
||||
import { peopleAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/people-all.view';
|
||||
import { tasksAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/tasks-all.view';
|
||||
import { tasksAssignedToMeView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/tasks-assigned-to-me';
|
||||
import { tasksByStatusView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/tasks-by-status.view';
|
||||
import { workflowRunsAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/workflow-runs-all.view';
|
||||
import { workflowVersionsAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/workflow-versions-all.view';
|
||||
import { workflowsAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/workflows-all.view';
|
||||
|
||||
export const createWorkspaceViews = async (
|
||||
export const prefillViews = async (
|
||||
entityManager: WorkspaceEntityManager,
|
||||
schemaName: string,
|
||||
objectMetadataItems: ObjectMetadataEntity[],
|
||||
) => {
|
||||
const customObjectMetadataItems = objectMetadataItems.filter(
|
||||
(item) => item.isCustom,
|
||||
);
|
||||
|
||||
const customViews = customObjectMetadataItems.map((item) =>
|
||||
customAllView(item),
|
||||
);
|
||||
|
||||
const views = [
|
||||
companiesAllView(objectMetadataItems),
|
||||
peopleAllView(objectMetadataItems),
|
||||
opportunitiesAllView(objectMetadataItems),
|
||||
opportunitiesByStageView(objectMetadataItems),
|
||||
notesAllView(objectMetadataItems),
|
||||
tasksAllView(objectMetadataItems),
|
||||
tasksAssignedToMeView(objectMetadataItems),
|
||||
tasksByStatusView(objectMetadataItems),
|
||||
workflowsAllView(objectMetadataItems),
|
||||
workflowVersionsAllView(objectMetadataItems),
|
||||
workflowRunsAllView(objectMetadataItems),
|
||||
...customViews,
|
||||
];
|
||||
|
||||
return createWorkspaceViews(entityManager, schemaName, views);
|
||||
};
|
||||
|
||||
const createWorkspaceViews = async (
|
||||
entityManager: WorkspaceEntityManager,
|
||||
schemaName: string,
|
||||
viewDefinitions: ViewDefinition[],
|
||||
@ -0,0 +1,26 @@
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { WorkspaceEntityManager } from 'src/engine/twenty-orm/entity-manager/workspace-entity-manager';
|
||||
|
||||
const tableName = 'favorite';
|
||||
|
||||
export const prefillWorkspaceFavorites = async (
|
||||
viewIds: string[],
|
||||
entityManager: WorkspaceEntityManager,
|
||||
schemaName: string,
|
||||
) => {
|
||||
await entityManager
|
||||
.createQueryBuilder(undefined, undefined, undefined, {
|
||||
shouldBypassPermissionChecks: true,
|
||||
})
|
||||
.insert()
|
||||
.into(`${schemaName}.${tableName}`, ['id', 'viewId', 'position'])
|
||||
.values(
|
||||
viewIds.map((viewId, index) => ({
|
||||
id: v4(),
|
||||
viewId,
|
||||
position: index,
|
||||
})),
|
||||
)
|
||||
.execute();
|
||||
};
|
||||
@ -1,37 +0,0 @@
|
||||
import { ObjectMetadataStandardIdToIdMap } from 'src/engine/metadata-modules/object-metadata/interfaces/object-metadata-standard-id-to-id-map';
|
||||
|
||||
import { WorkspaceEntityManager } from 'src/engine/twenty-orm/entity-manager/workspace-entity-manager';
|
||||
import { createWorkspaceViews } from 'src/engine/workspace-manager/standard-objects-prefill-data/create-workspace-views';
|
||||
import { companiesAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/companies-all.view';
|
||||
import { notesAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/notes-all.view';
|
||||
import { opportunitiesAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/opportunities-all.view';
|
||||
import { opportunitiesByStageView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/opportunity-by-stage.view';
|
||||
import { peopleAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/people-all.view';
|
||||
import { tasksAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/tasks-all.view';
|
||||
import { tasksAssignedToMeView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/tasks-assigned-to-me';
|
||||
import { tasksByStatusView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/tasks-by-status.view';
|
||||
import { workflowRunsAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/workflow-runs-all.view';
|
||||
import { workflowVersionsAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/workflow-versions-all.view';
|
||||
import { workflowsAllView } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/workflows-all.view';
|
||||
|
||||
export const seedViewWithDemoData = async (
|
||||
entityManager: WorkspaceEntityManager,
|
||||
schemaName: string,
|
||||
objectMetadataStandardIdToIdMap: ObjectMetadataStandardIdToIdMap,
|
||||
) => {
|
||||
const viewDefinitions = [
|
||||
companiesAllView(objectMetadataStandardIdToIdMap),
|
||||
peopleAllView(objectMetadataStandardIdToIdMap),
|
||||
opportunitiesAllView(objectMetadataStandardIdToIdMap),
|
||||
opportunitiesByStageView(objectMetadataStandardIdToIdMap),
|
||||
notesAllView(objectMetadataStandardIdToIdMap),
|
||||
tasksAllView(objectMetadataStandardIdToIdMap),
|
||||
tasksAssignedToMeView(objectMetadataStandardIdToIdMap),
|
||||
tasksByStatusView(objectMetadataStandardIdToIdMap),
|
||||
workflowsAllView(objectMetadataStandardIdToIdMap),
|
||||
workflowVersionsAllView(objectMetadataStandardIdToIdMap),
|
||||
workflowRunsAllView(objectMetadataStandardIdToIdMap),
|
||||
];
|
||||
|
||||
return createWorkspaceViews(entityManager, schemaName, viewDefinitions);
|
||||
};
|
||||
@ -1,58 +1,35 @@
|
||||
import { DataSource } from 'typeorm';
|
||||
|
||||
import { seedWorkspaceFavorites } from 'src/database/typeorm-seeds/workspace/favorites';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { WorkspaceEntityManager } from 'src/engine/twenty-orm/entity-manager/workspace-entity-manager';
|
||||
import { shouldSeedWorkspaceFavorite } from 'src/engine/utils/should-seed-workspace-favorite';
|
||||
import { companyPrefillData } from 'src/engine/workspace-manager/standard-objects-prefill-data/company';
|
||||
import { personPrefillData } from 'src/engine/workspace-manager/standard-objects-prefill-data/person';
|
||||
import { seedViewWithDemoData } from 'src/engine/workspace-manager/standard-objects-prefill-data/seed-view-with-demo-data';
|
||||
import { prefillCompanies } from 'src/engine/workspace-manager/standard-objects-prefill-data/prefill-companies';
|
||||
import { prefillPeople } from 'src/engine/workspace-manager/standard-objects-prefill-data/prefill-people';
|
||||
import { prefillViews } from 'src/engine/workspace-manager/standard-objects-prefill-data/prefill-views';
|
||||
import { prefillWorkspaceFavorites } from 'src/engine/workspace-manager/standard-objects-prefill-data/prefill-workspace-favorites';
|
||||
|
||||
export const standardObjectsPrefillData = async (
|
||||
mainDataSource: DataSource,
|
||||
schemaName: string,
|
||||
objectMetadata: ObjectMetadataEntity[],
|
||||
objectMetadataItems: ObjectMetadataEntity[],
|
||||
) => {
|
||||
const objectMetadataMap = objectMetadata.reduce((acc, object) => {
|
||||
if (!object.standardId) {
|
||||
throw new Error('Standard Id is not set for object: ${object.name}');
|
||||
}
|
||||
|
||||
// @ts-expect-error legacy noImplicitAny
|
||||
acc[object.standardId] = {
|
||||
id: object.id,
|
||||
fields: object.fields.reduce((acc, field) => {
|
||||
if (!field.standardId) {
|
||||
throw new Error('Standard Id is not set for field: ${field.name}');
|
||||
}
|
||||
|
||||
// @ts-expect-error legacy noImplicitAny
|
||||
acc[field.standardId] = field.id;
|
||||
|
||||
return acc;
|
||||
}, {}),
|
||||
};
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
mainDataSource.transaction(async (entityManager: WorkspaceEntityManager) => {
|
||||
await companyPrefillData(entityManager, schemaName);
|
||||
await personPrefillData(entityManager, schemaName);
|
||||
const viewDefinitionsWithId = await seedViewWithDemoData(
|
||||
await prefillCompanies(entityManager, schemaName);
|
||||
await prefillPeople(entityManager, schemaName);
|
||||
const viewDefinitionsWithId = await prefillViews(
|
||||
entityManager,
|
||||
schemaName,
|
||||
objectMetadataMap,
|
||||
objectMetadataItems,
|
||||
);
|
||||
|
||||
await seedWorkspaceFavorites(
|
||||
await prefillWorkspaceFavorites(
|
||||
viewDefinitionsWithId
|
||||
.filter(
|
||||
(view) =>
|
||||
view.key === 'INDEX' &&
|
||||
shouldSeedWorkspaceFavorite(
|
||||
view.objectMetadataId,
|
||||
objectMetadataMap,
|
||||
objectMetadataItems,
|
||||
),
|
||||
)
|
||||
.map((view) => view.id),
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { ObjectMetadataStandardIdToIdMap } from 'src/engine/metadata-modules/object-metadata/interfaces/object-metadata-standard-id-to-id-map';
|
||||
|
||||
import { AggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/aggregate-operations.constant';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import {
|
||||
BASE_OBJECT_STANDARD_FIELD_IDS,
|
||||
COMPANY_STANDARD_FIELD_IDS,
|
||||
@ -8,12 +7,19 @@ import {
|
||||
import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids';
|
||||
|
||||
export const companiesAllView = (
|
||||
objectMetadataStandardIdToIdMap: ObjectMetadataStandardIdToIdMap,
|
||||
objectMetadataItems: ObjectMetadataEntity[],
|
||||
) => {
|
||||
const companyObjectMetadata = objectMetadataItems.find(
|
||||
(object) => object.standardId === STANDARD_OBJECT_IDS.company,
|
||||
);
|
||||
|
||||
if (!companyObjectMetadata) {
|
||||
throw new Error('Company object metadata not found');
|
||||
}
|
||||
|
||||
return {
|
||||
name: 'All Companies',
|
||||
objectMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.company].id,
|
||||
objectMetadataId: companyObjectMetadata.id ?? '',
|
||||
type: 'table',
|
||||
key: 'INDEX',
|
||||
position: 0,
|
||||
@ -23,18 +29,23 @@ export const companiesAllView = (
|
||||
fields: [
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.company].fields[
|
||||
COMPANY_STANDARD_FIELD_IDS.name
|
||||
],
|
||||
companyObjectMetadata.fields.find(
|
||||
(field) => field.standardId === COMPANY_STANDARD_FIELD_IDS.name,
|
||||
)?.id ??
|
||||
'' ??
|
||||
'',
|
||||
position: 0,
|
||||
isVisible: true,
|
||||
size: 180,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.company].fields[
|
||||
COMPANY_STANDARD_FIELD_IDS.domainName
|
||||
],
|
||||
companyObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === COMPANY_STANDARD_FIELD_IDS.domainName,
|
||||
)?.id ??
|
||||
'' ??
|
||||
'',
|
||||
position: 1,
|
||||
isVisible: true,
|
||||
size: 100,
|
||||
@ -42,36 +53,40 @@ export const companiesAllView = (
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.company].fields[
|
||||
COMPANY_STANDARD_FIELD_IDS.createdBy
|
||||
],
|
||||
companyObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === COMPANY_STANDARD_FIELD_IDS.createdBy,
|
||||
)?.id ?? '',
|
||||
position: 2,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.company].fields[
|
||||
COMPANY_STANDARD_FIELD_IDS.accountOwner
|
||||
],
|
||||
companyObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === COMPANY_STANDARD_FIELD_IDS.accountOwner,
|
||||
)?.id ?? '',
|
||||
position: 3,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.company].fields[
|
||||
BASE_OBJECT_STANDARD_FIELD_IDS.createdAt
|
||||
],
|
||||
companyObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === BASE_OBJECT_STANDARD_FIELD_IDS.createdAt,
|
||||
)?.id ?? '',
|
||||
position: 4,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.company].fields[
|
||||
COMPANY_STANDARD_FIELD_IDS.employees
|
||||
],
|
||||
companyObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === COMPANY_STANDARD_FIELD_IDS.employees,
|
||||
)?.id ?? '',
|
||||
position: 5,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
@ -79,9 +94,10 @@ export const companiesAllView = (
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.company].fields[
|
||||
COMPANY_STANDARD_FIELD_IDS.linkedinLink
|
||||
],
|
||||
companyObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === COMPANY_STANDARD_FIELD_IDS.linkedinLink,
|
||||
)?.id ?? '',
|
||||
position: 6,
|
||||
isVisible: true,
|
||||
size: 170,
|
||||
@ -89,9 +105,9 @@ export const companiesAllView = (
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.company].fields[
|
||||
COMPANY_STANDARD_FIELD_IDS.address
|
||||
],
|
||||
companyObjectMetadata.fields.find(
|
||||
(field) => field.standardId === COMPANY_STANDARD_FIELD_IDS.address,
|
||||
)?.id ?? '',
|
||||
position: 7,
|
||||
isVisible: true,
|
||||
size: 170,
|
||||
|
||||
@ -0,0 +1,44 @@
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
|
||||
export const customAllView = (objectMetadataItem: ObjectMetadataEntity) => {
|
||||
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: `All ${objectMetadataItem.namePlural}`,
|
||||
objectMetadataId: objectMetadataItem.id,
|
||||
type: 'table',
|
||||
key: 'INDEX',
|
||||
position: 0,
|
||||
icon: 'IconList',
|
||||
kanbanFieldMetadataId: '',
|
||||
filters: [],
|
||||
fields: [
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataItem.fields.find((field) => field.name === 'name')
|
||||
?.id ?? '',
|
||||
position: 0,
|
||||
isVisible: true,
|
||||
size: 180,
|
||||
},
|
||||
...otherFields.map((field, index) => ({
|
||||
fieldMetadataId: field.id,
|
||||
position: index + 1,
|
||||
isVisible: true,
|
||||
size: 180,
|
||||
})),
|
||||
],
|
||||
};
|
||||
};
|
||||
@ -1,18 +1,22 @@
|
||||
import { ObjectMetadataStandardIdToIdMap } from 'src/engine/metadata-modules/object-metadata/interfaces/object-metadata-standard-id-to-id-map';
|
||||
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import {
|
||||
BASE_OBJECT_STANDARD_FIELD_IDS,
|
||||
NOTE_STANDARD_FIELD_IDS,
|
||||
} from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
|
||||
import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids';
|
||||
|
||||
export const notesAllView = (
|
||||
objectMetadataStandardIdToIdMap: ObjectMetadataStandardIdToIdMap,
|
||||
) => {
|
||||
export const notesAllView = (objectMetadataItems: ObjectMetadataEntity[]) => {
|
||||
const noteObjectMetadata = objectMetadataItems.find(
|
||||
(object) => object.standardId === STANDARD_OBJECT_IDS.note,
|
||||
);
|
||||
|
||||
if (!noteObjectMetadata) {
|
||||
throw new Error('Note object metadata not found');
|
||||
}
|
||||
|
||||
return {
|
||||
name: 'All Notes',
|
||||
objectMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.note].id,
|
||||
objectMetadataId: noteObjectMetadata.id,
|
||||
type: 'table',
|
||||
key: 'INDEX',
|
||||
position: 0,
|
||||
@ -22,45 +26,46 @@ export const notesAllView = (
|
||||
fields: [
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.note].fields[
|
||||
NOTE_STANDARD_FIELD_IDS.title
|
||||
],
|
||||
noteObjectMetadata.fields.find(
|
||||
(field) => field.standardId === NOTE_STANDARD_FIELD_IDS.title,
|
||||
)?.id ?? '',
|
||||
position: 0,
|
||||
isVisible: true,
|
||||
size: 210,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.note].fields[
|
||||
NOTE_STANDARD_FIELD_IDS.noteTargets
|
||||
],
|
||||
noteObjectMetadata.fields.find(
|
||||
(field) => field.standardId === NOTE_STANDARD_FIELD_IDS.noteTargets,
|
||||
)?.id ?? '',
|
||||
position: 1,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.note].fields[
|
||||
NOTE_STANDARD_FIELD_IDS.bodyV2
|
||||
],
|
||||
noteObjectMetadata.fields.find(
|
||||
(field) => field.standardId === NOTE_STANDARD_FIELD_IDS.bodyV2,
|
||||
)?.id ?? '',
|
||||
position: 2,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.note].fields[
|
||||
NOTE_STANDARD_FIELD_IDS.createdBy
|
||||
],
|
||||
noteObjectMetadata.fields.find(
|
||||
(field) => field.standardId === NOTE_STANDARD_FIELD_IDS.createdBy,
|
||||
)?.id ?? '',
|
||||
position: 3,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.note].fields[
|
||||
BASE_OBJECT_STANDARD_FIELD_IDS.createdAt
|
||||
],
|
||||
noteObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === BASE_OBJECT_STANDARD_FIELD_IDS.createdAt,
|
||||
)?.id ?? '',
|
||||
position: 4,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
|
||||
@ -1,16 +1,22 @@
|
||||
import { ObjectMetadataStandardIdToIdMap } from 'src/engine/metadata-modules/object-metadata/interfaces/object-metadata-standard-id-to-id-map';
|
||||
|
||||
import { AggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/aggregate-operations.constant';
|
||||
import { 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';
|
||||
import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids';
|
||||
|
||||
export const opportunitiesAllView = (
|
||||
objectMetadataStandardIdToIdMap: ObjectMetadataStandardIdToIdMap,
|
||||
objectMetadataItems: ObjectMetadataEntity[],
|
||||
) => {
|
||||
const opportunityObjectMetadata = objectMetadataItems.find(
|
||||
(object) => object.standardId === STANDARD_OBJECT_IDS.opportunity,
|
||||
);
|
||||
|
||||
if (!opportunityObjectMetadata) {
|
||||
throw new Error('Opportunity object metadata not found');
|
||||
}
|
||||
|
||||
return {
|
||||
name: 'All Opportunities',
|
||||
objectMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity].id,
|
||||
objectMetadataId: opportunityObjectMetadata.id,
|
||||
type: 'table',
|
||||
key: 'INDEX',
|
||||
position: 0,
|
||||
@ -20,16 +26,19 @@ export const opportunitiesAllView = (
|
||||
fields: [
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity]
|
||||
.fields[OPPORTUNITY_STANDARD_FIELD_IDS.name],
|
||||
opportunityObjectMetadata.fields.find(
|
||||
(field) => field.standardId === OPPORTUNITY_STANDARD_FIELD_IDS.name,
|
||||
)?.id ?? '',
|
||||
position: 0,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity]
|
||||
.fields[OPPORTUNITY_STANDARD_FIELD_IDS.amount],
|
||||
opportunityObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === OPPORTUNITY_STANDARD_FIELD_IDS.amount,
|
||||
)?.id ?? '',
|
||||
position: 1,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
@ -37,16 +46,20 @@ export const opportunitiesAllView = (
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity]
|
||||
.fields[OPPORTUNITY_STANDARD_FIELD_IDS.createdBy],
|
||||
opportunityObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === OPPORTUNITY_STANDARD_FIELD_IDS.createdBy,
|
||||
)?.id ?? '',
|
||||
position: 2,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity]
|
||||
.fields[OPPORTUNITY_STANDARD_FIELD_IDS.closeDate],
|
||||
opportunityObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === OPPORTUNITY_STANDARD_FIELD_IDS.closeDate,
|
||||
)?.id ?? '',
|
||||
position: 3,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
@ -54,16 +67,21 @@ export const opportunitiesAllView = (
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity]
|
||||
.fields[OPPORTUNITY_STANDARD_FIELD_IDS.company],
|
||||
opportunityObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === OPPORTUNITY_STANDARD_FIELD_IDS.company,
|
||||
)?.id ?? '',
|
||||
position: 4,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity]
|
||||
.fields[OPPORTUNITY_STANDARD_FIELD_IDS.pointOfContact],
|
||||
opportunityObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId ===
|
||||
OPPORTUNITY_STANDARD_FIELD_IDS.pointOfContact,
|
||||
)?.id ?? '',
|
||||
position: 5,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
|
||||
@ -1,75 +1,93 @@
|
||||
import { ObjectMetadataStandardIdToIdMap } from 'src/engine/metadata-modules/object-metadata/interfaces/object-metadata-standard-id-to-id-map';
|
||||
|
||||
import { AggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/aggregate-operations.constant';
|
||||
import { 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';
|
||||
import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids';
|
||||
|
||||
export const opportunitiesByStageView = (
|
||||
objectMetadataStandardIdToIdMap: ObjectMetadataStandardIdToIdMap,
|
||||
objectMetadataItems: ObjectMetadataEntity[],
|
||||
) => {
|
||||
const opportunityObjectMetadata = objectMetadataItems.find(
|
||||
(object) => object.standardId === STANDARD_OBJECT_IDS.opportunity,
|
||||
);
|
||||
|
||||
if (!opportunityObjectMetadata) {
|
||||
throw new Error('Opportunity object metadata not found');
|
||||
}
|
||||
|
||||
return {
|
||||
name: 'By Stage',
|
||||
objectMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity].id,
|
||||
objectMetadataId: opportunityObjectMetadata.id,
|
||||
type: 'kanban',
|
||||
key: null,
|
||||
position: 2,
|
||||
icon: 'IconLayoutKanban',
|
||||
kanbanFieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity].fields[
|
||||
OPPORTUNITY_STANDARD_FIELD_IDS.stage
|
||||
],
|
||||
opportunityObjectMetadata.fields.find(
|
||||
(field) => field.standardId === OPPORTUNITY_STANDARD_FIELD_IDS.stage,
|
||||
)?.id ?? '',
|
||||
kanbanAggregateOperation: AggregateOperations.MIN,
|
||||
kanbanAggregateOperationFieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity].fields[
|
||||
OPPORTUNITY_STANDARD_FIELD_IDS.amount
|
||||
],
|
||||
opportunityObjectMetadata.fields.find(
|
||||
(field) => field.standardId === OPPORTUNITY_STANDARD_FIELD_IDS.amount,
|
||||
)?.id ?? '',
|
||||
filters: [],
|
||||
fields: [
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity]
|
||||
.fields[OPPORTUNITY_STANDARD_FIELD_IDS.name],
|
||||
opportunityObjectMetadata.fields.find(
|
||||
(field) => field.standardId === OPPORTUNITY_STANDARD_FIELD_IDS.name,
|
||||
)?.id ?? '',
|
||||
position: 0,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity]
|
||||
.fields[OPPORTUNITY_STANDARD_FIELD_IDS.amount],
|
||||
opportunityObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === OPPORTUNITY_STANDARD_FIELD_IDS.amount,
|
||||
)?.id ?? '',
|
||||
position: 1,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity]
|
||||
.fields[OPPORTUNITY_STANDARD_FIELD_IDS.createdBy],
|
||||
opportunityObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === OPPORTUNITY_STANDARD_FIELD_IDS.createdBy,
|
||||
)?.id ?? '',
|
||||
position: 2,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity]
|
||||
.fields[OPPORTUNITY_STANDARD_FIELD_IDS.closeDate],
|
||||
opportunityObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === OPPORTUNITY_STANDARD_FIELD_IDS.closeDate,
|
||||
)?.id ?? '',
|
||||
position: 3,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity]
|
||||
.fields[OPPORTUNITY_STANDARD_FIELD_IDS.company],
|
||||
opportunityObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === OPPORTUNITY_STANDARD_FIELD_IDS.company,
|
||||
)?.id ?? '',
|
||||
position: 4,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity]
|
||||
.fields[OPPORTUNITY_STANDARD_FIELD_IDS.pointOfContact],
|
||||
opportunityObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId ===
|
||||
OPPORTUNITY_STANDARD_FIELD_IDS.pointOfContact,
|
||||
)?.id ?? '',
|
||||
position: 5,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
@ -78,40 +96,50 @@ export const opportunitiesByStageView = (
|
||||
groups: [
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity]
|
||||
.fields[OPPORTUNITY_STANDARD_FIELD_IDS.stage],
|
||||
opportunityObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === OPPORTUNITY_STANDARD_FIELD_IDS.stage,
|
||||
)?.id ?? '',
|
||||
isVisible: true,
|
||||
fieldValue: 'NEW',
|
||||
position: 0,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity]
|
||||
.fields[OPPORTUNITY_STANDARD_FIELD_IDS.stage],
|
||||
opportunityObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === OPPORTUNITY_STANDARD_FIELD_IDS.stage,
|
||||
)?.id ?? '',
|
||||
isVisible: true,
|
||||
fieldValue: 'SCREENING',
|
||||
position: 1,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity]
|
||||
.fields[OPPORTUNITY_STANDARD_FIELD_IDS.stage],
|
||||
opportunityObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === OPPORTUNITY_STANDARD_FIELD_IDS.stage,
|
||||
)?.id ?? '',
|
||||
isVisible: true,
|
||||
fieldValue: 'MEETING',
|
||||
position: 2,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity]
|
||||
.fields[OPPORTUNITY_STANDARD_FIELD_IDS.stage],
|
||||
opportunityObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === OPPORTUNITY_STANDARD_FIELD_IDS.stage,
|
||||
)?.id ?? '',
|
||||
isVisible: true,
|
||||
fieldValue: 'PROPOSAL',
|
||||
position: 3,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity]
|
||||
.fields[OPPORTUNITY_STANDARD_FIELD_IDS.stage],
|
||||
opportunityObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === OPPORTUNITY_STANDARD_FIELD_IDS.stage,
|
||||
)?.id ?? '',
|
||||
isVisible: true,
|
||||
fieldValue: 'CUSTOMER',
|
||||
position: 4,
|
||||
|
||||
@ -1,38 +1,47 @@
|
||||
import { ObjectMetadataStandardIdToIdMap } from 'src/engine/metadata-modules/object-metadata/interfaces/object-metadata-standard-id-to-id-map';
|
||||
|
||||
import { AggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/aggregate-operations.constant';
|
||||
import { 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';
|
||||
import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids';
|
||||
|
||||
export const opportunitiesTableByStageView = (
|
||||
objectMetadataStandardIdToIdMap: ObjectMetadataStandardIdToIdMap,
|
||||
objectMetadataItems: ObjectMetadataEntity[],
|
||||
) => {
|
||||
const opportunityObjectMetadata = objectMetadataItems.find(
|
||||
(object) => object.standardId === STANDARD_OBJECT_IDS.opportunity,
|
||||
);
|
||||
|
||||
if (!opportunityObjectMetadata) {
|
||||
throw new Error('Opportunity object metadata not found');
|
||||
}
|
||||
|
||||
return {
|
||||
name: 'By Stage',
|
||||
objectMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity].id,
|
||||
objectMetadataId: opportunityObjectMetadata.id,
|
||||
type: 'table',
|
||||
key: null,
|
||||
position: 1,
|
||||
icon: 'IconList',
|
||||
kanbanFieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity].fields[
|
||||
OPPORTUNITY_STANDARD_FIELD_IDS.stage
|
||||
],
|
||||
opportunityObjectMetadata.fields.find(
|
||||
(field) => field.standardId === OPPORTUNITY_STANDARD_FIELD_IDS.stage,
|
||||
)?.id ?? '',
|
||||
filters: [],
|
||||
fields: [
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity]
|
||||
.fields[OPPORTUNITY_STANDARD_FIELD_IDS.name],
|
||||
opportunityObjectMetadata.fields.find(
|
||||
(field) => field.standardId === OPPORTUNITY_STANDARD_FIELD_IDS.name,
|
||||
)?.id ?? '',
|
||||
position: 0,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity]
|
||||
.fields[OPPORTUNITY_STANDARD_FIELD_IDS.amount],
|
||||
opportunityObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === OPPORTUNITY_STANDARD_FIELD_IDS.amount,
|
||||
)?.id ?? '',
|
||||
position: 1,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
@ -40,16 +49,20 @@ export const opportunitiesTableByStageView = (
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity]
|
||||
.fields[OPPORTUNITY_STANDARD_FIELD_IDS.createdBy],
|
||||
opportunityObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === OPPORTUNITY_STANDARD_FIELD_IDS.createdBy,
|
||||
)?.id ?? '',
|
||||
position: 2,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity]
|
||||
.fields[OPPORTUNITY_STANDARD_FIELD_IDS.closeDate],
|
||||
opportunityObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === OPPORTUNITY_STANDARD_FIELD_IDS.closeDate,
|
||||
)?.id ?? '',
|
||||
position: 3,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
@ -57,8 +70,10 @@ export const opportunitiesTableByStageView = (
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity]
|
||||
.fields[OPPORTUNITY_STANDARD_FIELD_IDS.company],
|
||||
opportunityObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === OPPORTUNITY_STANDARD_FIELD_IDS.company,
|
||||
)?.id ?? '',
|
||||
position: 4,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
@ -66,8 +81,11 @@ export const opportunitiesTableByStageView = (
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity]
|
||||
.fields[OPPORTUNITY_STANDARD_FIELD_IDS.pointOfContact],
|
||||
opportunityObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId ===
|
||||
OPPORTUNITY_STANDARD_FIELD_IDS.pointOfContact,
|
||||
)?.id ?? '',
|
||||
position: 5,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
@ -76,40 +94,50 @@ export const opportunitiesTableByStageView = (
|
||||
groups: [
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity]
|
||||
.fields[OPPORTUNITY_STANDARD_FIELD_IDS.stage],
|
||||
opportunityObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === OPPORTUNITY_STANDARD_FIELD_IDS.stage,
|
||||
)?.id ?? '',
|
||||
isVisible: true,
|
||||
fieldValue: 'NEW',
|
||||
position: 0,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity]
|
||||
.fields[OPPORTUNITY_STANDARD_FIELD_IDS.stage],
|
||||
opportunityObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === OPPORTUNITY_STANDARD_FIELD_IDS.stage,
|
||||
)?.id ?? '',
|
||||
isVisible: true,
|
||||
fieldValue: 'SCREENING',
|
||||
position: 1,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity]
|
||||
.fields[OPPORTUNITY_STANDARD_FIELD_IDS.stage],
|
||||
opportunityObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === OPPORTUNITY_STANDARD_FIELD_IDS.stage,
|
||||
)?.id ?? '',
|
||||
isVisible: true,
|
||||
fieldValue: 'MEETING',
|
||||
position: 2,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity]
|
||||
.fields[OPPORTUNITY_STANDARD_FIELD_IDS.stage],
|
||||
opportunityObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === OPPORTUNITY_STANDARD_FIELD_IDS.stage,
|
||||
)?.id ?? '',
|
||||
isVisible: true,
|
||||
fieldValue: 'PROPOSAL',
|
||||
position: 3,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.opportunity]
|
||||
.fields[OPPORTUNITY_STANDARD_FIELD_IDS.stage],
|
||||
opportunityObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === OPPORTUNITY_STANDARD_FIELD_IDS.stage,
|
||||
)?.id ?? '',
|
||||
isVisible: true,
|
||||
fieldValue: 'CUSTOMER',
|
||||
position: 4,
|
||||
|
||||
@ -1,19 +1,23 @@
|
||||
import { ObjectMetadataStandardIdToIdMap } from 'src/engine/metadata-modules/object-metadata/interfaces/object-metadata-standard-id-to-id-map';
|
||||
|
||||
import { AggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/aggregate-operations.constant';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import {
|
||||
BASE_OBJECT_STANDARD_FIELD_IDS,
|
||||
PERSON_STANDARD_FIELD_IDS,
|
||||
} from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
|
||||
import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids';
|
||||
|
||||
export const peopleAllView = (
|
||||
objectMetadataStandardIdToIdMap: ObjectMetadataStandardIdToIdMap,
|
||||
) => {
|
||||
export const peopleAllView = (objectMetadataItems: ObjectMetadataEntity[]) => {
|
||||
const personObjectMetadata = objectMetadataItems.find(
|
||||
(object) => object.standardId === STANDARD_OBJECT_IDS.person,
|
||||
);
|
||||
|
||||
if (!personObjectMetadata) {
|
||||
throw new Error('Person object metadata not found');
|
||||
}
|
||||
|
||||
return {
|
||||
name: 'All People',
|
||||
objectMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.person].id,
|
||||
objectMetadataId: personObjectMetadata.id,
|
||||
type: 'table',
|
||||
key: 'INDEX',
|
||||
position: 0,
|
||||
@ -23,18 +27,18 @@ export const peopleAllView = (
|
||||
fields: [
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.person].fields[
|
||||
PERSON_STANDARD_FIELD_IDS.name
|
||||
],
|
||||
personObjectMetadata.fields.find(
|
||||
(field) => field.standardId === PERSON_STANDARD_FIELD_IDS.name,
|
||||
)?.id ?? '',
|
||||
position: 0,
|
||||
isVisible: true,
|
||||
size: 210,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.person].fields[
|
||||
PERSON_STANDARD_FIELD_IDS.emails
|
||||
],
|
||||
personObjectMetadata.fields.find(
|
||||
(field) => field.standardId === PERSON_STANDARD_FIELD_IDS.emails,
|
||||
)?.id ?? '',
|
||||
position: 1,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
@ -42,27 +46,27 @@ export const peopleAllView = (
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.person].fields[
|
||||
PERSON_STANDARD_FIELD_IDS.createdBy
|
||||
],
|
||||
personObjectMetadata.fields.find(
|
||||
(field) => field.standardId === PERSON_STANDARD_FIELD_IDS.createdBy,
|
||||
)?.id ?? '',
|
||||
position: 2,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.person].fields[
|
||||
PERSON_STANDARD_FIELD_IDS.company
|
||||
],
|
||||
personObjectMetadata.fields.find(
|
||||
(field) => field.standardId === PERSON_STANDARD_FIELD_IDS.company,
|
||||
)?.id ?? '',
|
||||
position: 3,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.person].fields[
|
||||
PERSON_STANDARD_FIELD_IDS.phones
|
||||
],
|
||||
personObjectMetadata.fields.find(
|
||||
(field) => field.standardId === PERSON_STANDARD_FIELD_IDS.phones,
|
||||
)?.id ?? '',
|
||||
position: 4,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
@ -70,9 +74,10 @@ export const peopleAllView = (
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.person].fields[
|
||||
BASE_OBJECT_STANDARD_FIELD_IDS.createdAt
|
||||
],
|
||||
personObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === BASE_OBJECT_STANDARD_FIELD_IDS.createdAt,
|
||||
)?.id ?? '',
|
||||
position: 5,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
@ -80,36 +85,37 @@ export const peopleAllView = (
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.person].fields[
|
||||
PERSON_STANDARD_FIELD_IDS.city
|
||||
],
|
||||
personObjectMetadata.fields.find(
|
||||
(field) => field.standardId === PERSON_STANDARD_FIELD_IDS.city,
|
||||
)?.id ?? '',
|
||||
position: 6,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.person].fields[
|
||||
PERSON_STANDARD_FIELD_IDS.jobTitle
|
||||
],
|
||||
personObjectMetadata.fields.find(
|
||||
(field) => field.standardId === PERSON_STANDARD_FIELD_IDS.jobTitle,
|
||||
)?.id ?? '',
|
||||
position: 7,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.person].fields[
|
||||
PERSON_STANDARD_FIELD_IDS.linkedinLink
|
||||
],
|
||||
personObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === PERSON_STANDARD_FIELD_IDS.linkedinLink,
|
||||
)?.id ?? '',
|
||||
position: 8,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.person].fields[
|
||||
PERSON_STANDARD_FIELD_IDS.xLink
|
||||
],
|
||||
personObjectMetadata.fields.find(
|
||||
(field) => field.standardId === PERSON_STANDARD_FIELD_IDS.xLink,
|
||||
)?.id ?? '',
|
||||
position: 9,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
|
||||
@ -1,18 +1,22 @@
|
||||
import { ObjectMetadataStandardIdToIdMap } from 'src/engine/metadata-modules/object-metadata/interfaces/object-metadata-standard-id-to-id-map';
|
||||
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import {
|
||||
BASE_OBJECT_STANDARD_FIELD_IDS,
|
||||
TASK_STANDARD_FIELD_IDS,
|
||||
} from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
|
||||
import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids';
|
||||
|
||||
export const tasksAllView = (
|
||||
objectMetadataStandardIdToIdMap: ObjectMetadataStandardIdToIdMap,
|
||||
) => {
|
||||
export const tasksAllView = (objectMetadataItems: ObjectMetadataEntity[]) => {
|
||||
const taskObjectMetadata = objectMetadataItems.find(
|
||||
(object) => object.standardId === STANDARD_OBJECT_IDS.task,
|
||||
);
|
||||
|
||||
if (!taskObjectMetadata) {
|
||||
throw new Error('Task object metadata not found');
|
||||
}
|
||||
|
||||
return {
|
||||
name: 'All Tasks',
|
||||
objectMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.task].id,
|
||||
objectMetadataId: taskObjectMetadata.id,
|
||||
type: 'table',
|
||||
key: 'INDEX',
|
||||
position: 0,
|
||||
@ -32,72 +36,73 @@ export const tasksAllView = (
|
||||
fields: [
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.task].fields[
|
||||
TASK_STANDARD_FIELD_IDS.title
|
||||
],
|
||||
taskObjectMetadata.fields.find(
|
||||
(field) => field.standardId === TASK_STANDARD_FIELD_IDS.title,
|
||||
)?.id ?? '',
|
||||
position: 0,
|
||||
isVisible: true,
|
||||
size: 210,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.task].fields[
|
||||
TASK_STANDARD_FIELD_IDS.status
|
||||
],
|
||||
taskObjectMetadata.fields.find(
|
||||
(field) => field.standardId === TASK_STANDARD_FIELD_IDS.status,
|
||||
)?.id ?? '',
|
||||
position: 2,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.task].fields[
|
||||
TASK_STANDARD_FIELD_IDS.taskTargets
|
||||
],
|
||||
taskObjectMetadata.fields.find(
|
||||
(field) => field.standardId === TASK_STANDARD_FIELD_IDS.taskTargets,
|
||||
)?.id ?? '',
|
||||
position: 3,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.task].fields[
|
||||
TASK_STANDARD_FIELD_IDS.createdBy
|
||||
],
|
||||
taskObjectMetadata.fields.find(
|
||||
(field) => field.standardId === TASK_STANDARD_FIELD_IDS.createdBy,
|
||||
)?.id ?? '',
|
||||
position: 4,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.task].fields[
|
||||
TASK_STANDARD_FIELD_IDS.dueAt
|
||||
],
|
||||
taskObjectMetadata.fields.find(
|
||||
(field) => field.standardId === TASK_STANDARD_FIELD_IDS.dueAt,
|
||||
)?.id ?? '',
|
||||
position: 5,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.task].fields[
|
||||
TASK_STANDARD_FIELD_IDS.assignee
|
||||
],
|
||||
taskObjectMetadata.fields.find(
|
||||
(field) => field.standardId === TASK_STANDARD_FIELD_IDS.assignee,
|
||||
)?.id ?? '',
|
||||
position: 6,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.task].fields[
|
||||
TASK_STANDARD_FIELD_IDS.bodyV2
|
||||
],
|
||||
taskObjectMetadata.fields.find(
|
||||
(field) => field.standardId === TASK_STANDARD_FIELD_IDS.bodyV2,
|
||||
)?.id ?? '',
|
||||
position: 7,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.task].fields[
|
||||
BASE_OBJECT_STANDARD_FIELD_IDS.createdAt
|
||||
],
|
||||
taskObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === BASE_OBJECT_STANDARD_FIELD_IDS.createdAt,
|
||||
)?.id ?? '',
|
||||
position: 8,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { ObjectMetadataStandardIdToIdMap } from 'src/engine/metadata-modules/object-metadata/interfaces/object-metadata-standard-id-to-id-map';
|
||||
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import {
|
||||
BASE_OBJECT_STANDARD_FIELD_IDS,
|
||||
TASK_STANDARD_FIELD_IDS,
|
||||
@ -7,12 +6,19 @@ import {
|
||||
import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids';
|
||||
|
||||
export const tasksAssignedToMeView = (
|
||||
objectMetadataStandardIdToIdMap: ObjectMetadataStandardIdToIdMap,
|
||||
objectMetadataItems: ObjectMetadataEntity[],
|
||||
) => {
|
||||
const taskObjectMetadata = objectMetadataItems.find(
|
||||
(object) => object.standardId === STANDARD_OBJECT_IDS.task,
|
||||
);
|
||||
|
||||
if (!taskObjectMetadata) {
|
||||
throw new Error('Task object metadata not found');
|
||||
}
|
||||
|
||||
return {
|
||||
name: 'Assigned to Me',
|
||||
objectMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.task].id,
|
||||
objectMetadataId: taskObjectMetadata.id,
|
||||
type: 'table',
|
||||
key: null,
|
||||
position: 2,
|
||||
@ -21,9 +27,9 @@ export const tasksAssignedToMeView = (
|
||||
filters: [
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.task].fields[
|
||||
TASK_STANDARD_FIELD_IDS.assignee
|
||||
],
|
||||
taskObjectMetadata.fields.find(
|
||||
(field) => field.standardId === TASK_STANDARD_FIELD_IDS.assignee,
|
||||
)?.id ?? '',
|
||||
displayValue: 'Me',
|
||||
operand: 'is',
|
||||
value: JSON.stringify({
|
||||
@ -35,9 +41,9 @@ export const tasksAssignedToMeView = (
|
||||
fields: [
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.task].fields[
|
||||
TASK_STANDARD_FIELD_IDS.title
|
||||
],
|
||||
taskObjectMetadata.fields.find(
|
||||
(field) => field.standardId === TASK_STANDARD_FIELD_IDS.title,
|
||||
)?.id ?? '',
|
||||
position: 0,
|
||||
isVisible: true,
|
||||
size: 210,
|
||||
@ -53,54 +59,55 @@ export const tasksAssignedToMeView = (
|
||||
},*/
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.task].fields[
|
||||
TASK_STANDARD_FIELD_IDS.taskTargets
|
||||
],
|
||||
taskObjectMetadata.fields.find(
|
||||
(field) => field.standardId === TASK_STANDARD_FIELD_IDS.taskTargets,
|
||||
)?.id ?? '',
|
||||
position: 3,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.task].fields[
|
||||
TASK_STANDARD_FIELD_IDS.createdBy
|
||||
],
|
||||
taskObjectMetadata.fields.find(
|
||||
(field) => field.standardId === TASK_STANDARD_FIELD_IDS.createdBy,
|
||||
)?.id ?? '',
|
||||
position: 4,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.task].fields[
|
||||
TASK_STANDARD_FIELD_IDS.dueAt
|
||||
],
|
||||
taskObjectMetadata.fields.find(
|
||||
(field) => field.standardId === TASK_STANDARD_FIELD_IDS.dueAt,
|
||||
)?.id ?? '',
|
||||
position: 5,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.task].fields[
|
||||
TASK_STANDARD_FIELD_IDS.assignee
|
||||
],
|
||||
taskObjectMetadata.fields.find(
|
||||
(field) => field.standardId === TASK_STANDARD_FIELD_IDS.assignee,
|
||||
)?.id ?? '',
|
||||
position: 6,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.task].fields[
|
||||
TASK_STANDARD_FIELD_IDS.body
|
||||
],
|
||||
taskObjectMetadata.fields.find(
|
||||
(field) => field.standardId === TASK_STANDARD_FIELD_IDS.body,
|
||||
)?.id ?? '',
|
||||
position: 7,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.task].fields[
|
||||
BASE_OBJECT_STANDARD_FIELD_IDS.createdAt
|
||||
],
|
||||
taskObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === BASE_OBJECT_STANDARD_FIELD_IDS.createdAt,
|
||||
)?.id ?? '',
|
||||
position: 8,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
@ -109,36 +116,36 @@ export const tasksAssignedToMeView = (
|
||||
groups: [
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.task].fields[
|
||||
TASK_STANDARD_FIELD_IDS.status
|
||||
],
|
||||
taskObjectMetadata.fields.find(
|
||||
(field) => field.standardId === TASK_STANDARD_FIELD_IDS.status,
|
||||
)?.id ?? '',
|
||||
isVisible: true,
|
||||
fieldValue: 'TODO',
|
||||
position: 0,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.task].fields[
|
||||
TASK_STANDARD_FIELD_IDS.status
|
||||
],
|
||||
taskObjectMetadata.fields.find(
|
||||
(field) => field.standardId === TASK_STANDARD_FIELD_IDS.status,
|
||||
)?.id ?? '',
|
||||
isVisible: true,
|
||||
fieldValue: 'IN_PROGRESS',
|
||||
position: 1,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.task].fields[
|
||||
TASK_STANDARD_FIELD_IDS.status
|
||||
],
|
||||
taskObjectMetadata.fields.find(
|
||||
(field) => field.standardId === TASK_STANDARD_FIELD_IDS.status,
|
||||
)?.id ?? '',
|
||||
isVisible: true,
|
||||
fieldValue: 'DONE',
|
||||
position: 2,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.task].fields[
|
||||
TASK_STANDARD_FIELD_IDS.status
|
||||
],
|
||||
taskObjectMetadata.fields.find(
|
||||
(field) => field.standardId === TASK_STANDARD_FIELD_IDS.status,
|
||||
)?.id ?? '',
|
||||
isVisible: true,
|
||||
fieldValue: '',
|
||||
position: 3,
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { ObjectMetadataStandardIdToIdMap } from 'src/engine/metadata-modules/object-metadata/interfaces/object-metadata-standard-id-to-id-map';
|
||||
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import {
|
||||
BASE_OBJECT_STANDARD_FIELD_IDS,
|
||||
TASK_STANDARD_FIELD_IDS,
|
||||
@ -7,20 +6,27 @@ import {
|
||||
import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids';
|
||||
|
||||
export const tasksByStatusView = (
|
||||
objectMetadataStandardIdToIdMap: ObjectMetadataStandardIdToIdMap,
|
||||
objectMetadataItems: ObjectMetadataEntity[],
|
||||
) => {
|
||||
const taskObjectMetadata = objectMetadataItems.find(
|
||||
(object) => object.standardId === STANDARD_OBJECT_IDS.task,
|
||||
);
|
||||
|
||||
if (!taskObjectMetadata) {
|
||||
throw new Error('Task object metadata not found');
|
||||
}
|
||||
|
||||
return {
|
||||
name: 'By Status',
|
||||
objectMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.task].id,
|
||||
objectMetadataId: taskObjectMetadata.id,
|
||||
type: 'kanban',
|
||||
key: null,
|
||||
position: 1,
|
||||
icon: 'IconLayoutKanban',
|
||||
kanbanFieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.task].fields[
|
||||
TASK_STANDARD_FIELD_IDS.status
|
||||
],
|
||||
taskObjectMetadata.fields.find(
|
||||
(field) => field.standardId === TASK_STANDARD_FIELD_IDS.status,
|
||||
)?.id ?? '',
|
||||
filters: [] /* [
|
||||
{
|
||||
fieldMetadataId:
|
||||
@ -35,45 +41,46 @@ export const tasksByStatusView = (
|
||||
fields: [
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.task].fields[
|
||||
TASK_STANDARD_FIELD_IDS.title
|
||||
],
|
||||
taskObjectMetadata.fields.find(
|
||||
(field) => field.standardId === TASK_STANDARD_FIELD_IDS.title,
|
||||
)?.id ?? '',
|
||||
position: 0,
|
||||
isVisible: true,
|
||||
size: 210,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.task].fields[
|
||||
TASK_STANDARD_FIELD_IDS.status
|
||||
],
|
||||
taskObjectMetadata.fields.find(
|
||||
(field) => field.standardId === TASK_STANDARD_FIELD_IDS.status,
|
||||
)?.id ?? '',
|
||||
position: 2,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.task].fields[
|
||||
TASK_STANDARD_FIELD_IDS.dueAt
|
||||
],
|
||||
taskObjectMetadata.fields.find(
|
||||
(field) => field.standardId === TASK_STANDARD_FIELD_IDS.dueAt,
|
||||
)?.id ?? '',
|
||||
position: 3,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.task].fields[
|
||||
TASK_STANDARD_FIELD_IDS.assignee
|
||||
],
|
||||
taskObjectMetadata.fields.find(
|
||||
(field) => field.standardId === TASK_STANDARD_FIELD_IDS.assignee,
|
||||
)?.id ?? '',
|
||||
position: 4,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.task].fields[
|
||||
BASE_OBJECT_STANDARD_FIELD_IDS.createdAt
|
||||
],
|
||||
taskObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === BASE_OBJECT_STANDARD_FIELD_IDS.createdAt,
|
||||
)?.id ?? '',
|
||||
position: 6,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
@ -94,27 +101,27 @@ export const tasksByStatusView = (
|
||||
groups: [
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.task].fields[
|
||||
TASK_STANDARD_FIELD_IDS.status
|
||||
],
|
||||
taskObjectMetadata.fields.find(
|
||||
(field) => field.standardId === TASK_STANDARD_FIELD_IDS.status,
|
||||
)?.id ?? '',
|
||||
isVisible: true,
|
||||
fieldValue: 'TODO',
|
||||
position: 0,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.task].fields[
|
||||
TASK_STANDARD_FIELD_IDS.status
|
||||
],
|
||||
taskObjectMetadata.fields.find(
|
||||
(field) => field.standardId === TASK_STANDARD_FIELD_IDS.status,
|
||||
)?.id ?? '',
|
||||
isVisible: true,
|
||||
fieldValue: 'IN_PROGRESS',
|
||||
position: 1,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.task].fields[
|
||||
TASK_STANDARD_FIELD_IDS.status
|
||||
],
|
||||
taskObjectMetadata.fields.find(
|
||||
(field) => field.standardId === TASK_STANDARD_FIELD_IDS.status,
|
||||
)?.id ?? '',
|
||||
isVisible: true,
|
||||
fieldValue: 'DONE',
|
||||
position: 2,
|
||||
|
||||
@ -1 +0,0 @@
|
||||
// TODO
|
||||
@ -1,16 +1,22 @@
|
||||
import { ObjectMetadataStandardIdToIdMap } from 'src/engine/metadata-modules/object-metadata/interfaces/object-metadata-standard-id-to-id-map';
|
||||
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { WORKFLOW_RUN_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
|
||||
import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids';
|
||||
import { ViewOpenRecordInType } from 'src/modules/view/standard-objects/view.workspace-entity';
|
||||
|
||||
export const workflowRunsAllView = (
|
||||
objectMetadataStandardIdToIdMap: ObjectMetadataStandardIdToIdMap,
|
||||
objectMetadataItems: ObjectMetadataEntity[],
|
||||
) => {
|
||||
const workflowRunObjectMetadata = objectMetadataItems.find(
|
||||
(object) => object.standardId === STANDARD_OBJECT_IDS.workflowRun,
|
||||
);
|
||||
|
||||
if (!workflowRunObjectMetadata) {
|
||||
throw new Error('Workflow run object metadata not found');
|
||||
}
|
||||
|
||||
return {
|
||||
name: 'All Workflow Runs',
|
||||
objectMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.workflowRun].id,
|
||||
objectMetadataId: workflowRunObjectMetadata.id,
|
||||
type: 'table',
|
||||
key: 'INDEX',
|
||||
position: 0,
|
||||
@ -21,48 +27,61 @@ export const workflowRunsAllView = (
|
||||
fields: [
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.workflowRun]
|
||||
.fields[WORKFLOW_RUN_STANDARD_FIELD_IDS.name],
|
||||
workflowRunObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === WORKFLOW_RUN_STANDARD_FIELD_IDS.name,
|
||||
)?.id ?? '',
|
||||
position: 0,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.workflowRun]
|
||||
.fields[WORKFLOW_RUN_STANDARD_FIELD_IDS.workflow],
|
||||
workflowRunObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === WORKFLOW_RUN_STANDARD_FIELD_IDS.workflow,
|
||||
)?.id ?? '',
|
||||
position: 1,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.workflowRun]
|
||||
.fields[WORKFLOW_RUN_STANDARD_FIELD_IDS.status],
|
||||
workflowRunObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === WORKFLOW_RUN_STANDARD_FIELD_IDS.status,
|
||||
)?.id ?? '',
|
||||
position: 2,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.workflowRun]
|
||||
.fields[WORKFLOW_RUN_STANDARD_FIELD_IDS.startedAt],
|
||||
workflowRunObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === WORKFLOW_RUN_STANDARD_FIELD_IDS.startedAt,
|
||||
)?.id ?? '',
|
||||
position: 3,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.workflowRun]
|
||||
.fields[WORKFLOW_RUN_STANDARD_FIELD_IDS.createdBy],
|
||||
workflowRunObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === WORKFLOW_RUN_STANDARD_FIELD_IDS.createdBy,
|
||||
)?.id ?? '',
|
||||
position: 4,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.workflowRun]
|
||||
.fields[WORKFLOW_RUN_STANDARD_FIELD_IDS.workflowVersion],
|
||||
workflowRunObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId ===
|
||||
WORKFLOW_RUN_STANDARD_FIELD_IDS.workflowVersion,
|
||||
)?.id ?? '',
|
||||
position: 5,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { ObjectMetadataStandardIdToIdMap } from 'src/engine/metadata-modules/object-metadata/interfaces/object-metadata-standard-id-to-id-map';
|
||||
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import {
|
||||
BASE_OBJECT_STANDARD_FIELD_IDS,
|
||||
WORKFLOW_VERSION_STANDARD_FIELD_IDS,
|
||||
@ -8,12 +7,19 @@ import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync
|
||||
import { ViewOpenRecordInType } from 'src/modules/view/standard-objects/view.workspace-entity';
|
||||
|
||||
export const workflowVersionsAllView = (
|
||||
objectMetadataStandardIdToIdMap: ObjectMetadataStandardIdToIdMap,
|
||||
objectMetadataItems: ObjectMetadataEntity[],
|
||||
) => {
|
||||
const workflowVersionObjectMetadata = objectMetadataItems.find(
|
||||
(object) => object.standardId === STANDARD_OBJECT_IDS.workflowVersion,
|
||||
);
|
||||
|
||||
if (!workflowVersionObjectMetadata) {
|
||||
throw new Error('Workflow version object metadata not found');
|
||||
}
|
||||
|
||||
return {
|
||||
name: 'All Workflow Versions',
|
||||
objectMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.workflowVersion].id,
|
||||
objectMetadataId: workflowVersionObjectMetadata.id,
|
||||
type: 'table',
|
||||
key: 'INDEX',
|
||||
position: 0,
|
||||
@ -24,40 +30,50 @@ export const workflowVersionsAllView = (
|
||||
fields: [
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.workflowVersion]
|
||||
.fields[WORKFLOW_VERSION_STANDARD_FIELD_IDS.name],
|
||||
workflowVersionObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === WORKFLOW_VERSION_STANDARD_FIELD_IDS.name,
|
||||
)?.id ?? '',
|
||||
position: 0,
|
||||
isVisible: true,
|
||||
size: 210,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.workflowVersion]
|
||||
.fields[WORKFLOW_VERSION_STANDARD_FIELD_IDS.workflow],
|
||||
workflowVersionObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === WORKFLOW_VERSION_STANDARD_FIELD_IDS.workflow,
|
||||
)?.id ?? '',
|
||||
position: 1,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.workflowVersion]
|
||||
.fields[WORKFLOW_VERSION_STANDARD_FIELD_IDS.status],
|
||||
workflowVersionObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === WORKFLOW_VERSION_STANDARD_FIELD_IDS.status,
|
||||
)?.id ?? '',
|
||||
position: 2,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.workflowVersion]
|
||||
.fields[BASE_OBJECT_STANDARD_FIELD_IDS.updatedAt],
|
||||
workflowVersionObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === BASE_OBJECT_STANDARD_FIELD_IDS.updatedAt,
|
||||
)?.id ?? '',
|
||||
position: 3,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.workflowVersion]
|
||||
.fields[WORKFLOW_VERSION_STANDARD_FIELD_IDS.runs],
|
||||
workflowVersionObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === WORKFLOW_VERSION_STANDARD_FIELD_IDS.runs,
|
||||
)?.id ?? '',
|
||||
position: 4,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { ObjectMetadataStandardIdToIdMap } from 'src/engine/metadata-modules/object-metadata/interfaces/object-metadata-standard-id-to-id-map';
|
||||
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import {
|
||||
BASE_OBJECT_STANDARD_FIELD_IDS,
|
||||
WORKFLOW_STANDARD_FIELD_IDS,
|
||||
@ -8,12 +7,19 @@ import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync
|
||||
import { ViewOpenRecordInType } from 'src/modules/view/standard-objects/view.workspace-entity';
|
||||
|
||||
export const workflowsAllView = (
|
||||
objectMetadataStandardIdToIdMap: ObjectMetadataStandardIdToIdMap,
|
||||
objectMetadataItems: ObjectMetadataEntity[],
|
||||
) => {
|
||||
const workflowObjectMetadata = objectMetadataItems.find(
|
||||
(object) => object.standardId === STANDARD_OBJECT_IDS.workflow,
|
||||
);
|
||||
|
||||
if (!workflowObjectMetadata) {
|
||||
throw new Error('Workflow object metadata not found');
|
||||
}
|
||||
|
||||
return {
|
||||
name: 'All Workflows',
|
||||
objectMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.workflow].id,
|
||||
objectMetadataId: workflowObjectMetadata.id,
|
||||
type: 'table',
|
||||
key: 'INDEX',
|
||||
position: 0,
|
||||
@ -24,54 +30,58 @@ export const workflowsAllView = (
|
||||
fields: [
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.workflow].fields[
|
||||
WORKFLOW_STANDARD_FIELD_IDS.name
|
||||
],
|
||||
workflowObjectMetadata.fields.find(
|
||||
(field) => field.standardId === WORKFLOW_STANDARD_FIELD_IDS.name,
|
||||
)?.id ?? '',
|
||||
position: 0,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.workflow].fields[
|
||||
WORKFLOW_STANDARD_FIELD_IDS.statuses
|
||||
],
|
||||
workflowObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === WORKFLOW_STANDARD_FIELD_IDS.statuses,
|
||||
)?.id ?? '',
|
||||
position: 1,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.workflow].fields[
|
||||
BASE_OBJECT_STANDARD_FIELD_IDS.updatedAt
|
||||
],
|
||||
workflowObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === BASE_OBJECT_STANDARD_FIELD_IDS.updatedAt,
|
||||
)?.id ?? '',
|
||||
position: 2,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.workflow].fields[
|
||||
WORKFLOW_STANDARD_FIELD_IDS.createdBy
|
||||
],
|
||||
workflowObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === WORKFLOW_STANDARD_FIELD_IDS.createdBy,
|
||||
)?.id ?? '',
|
||||
position: 3,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.workflow].fields[
|
||||
WORKFLOW_STANDARD_FIELD_IDS.versions
|
||||
],
|
||||
workflowObjectMetadata.fields.find(
|
||||
(field) =>
|
||||
field.standardId === WORKFLOW_STANDARD_FIELD_IDS.versions,
|
||||
)?.id ?? '',
|
||||
position: 4,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
},
|
||||
{
|
||||
fieldMetadataId:
|
||||
objectMetadataStandardIdToIdMap[STANDARD_OBJECT_IDS.workflow].fields[
|
||||
WORKFLOW_STANDARD_FIELD_IDS.runs
|
||||
],
|
||||
workflowObjectMetadata.fields.find(
|
||||
(field) => field.standardId === WORKFLOW_STANDARD_FIELD_IDS.runs,
|
||||
)?.id ?? '',
|
||||
position: 5,
|
||||
isVisible: true,
|
||||
size: 150,
|
||||
|
||||
@ -2,7 +2,6 @@ import { WorkspaceTableStructure } from 'src/engine/workspace-manager/workspace-
|
||||
|
||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { RelationMetadataEntity } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity';
|
||||
|
||||
export enum WorkspaceHealthIssueType {
|
||||
MISSING_TABLE = 'MISSING_TABLE',
|
||||
@ -88,17 +87,6 @@ export type WorkspaceRelationIssueTypes =
|
||||
| WorkspaceHealthIssueType.RELATION_FOREIGN_KEY_ON_DELETE_ACTION_CONFLICT
|
||||
| WorkspaceHealthIssueType.RELATION_TYPE_NOT_VALID;
|
||||
|
||||
export interface WorkspaceHealthRelationIssue<
|
||||
T extends WorkspaceRelationIssueTypes,
|
||||
> {
|
||||
type: T;
|
||||
fromFieldMetadata?: FieldMetadataEntity | undefined;
|
||||
toFieldMetadata?: FieldMetadataEntity | undefined;
|
||||
relationMetadata?: RelationMetadataEntity;
|
||||
columnStructure?: WorkspaceTableStructure;
|
||||
message: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the interface for the issue type
|
||||
*/
|
||||
@ -107,9 +95,7 @@ export type WorkspaceIssueTypeToInterface<T extends WorkspaceHealthIssueType> =
|
||||
? WorkspaceHealthTableIssue<T>
|
||||
: T extends WorkspaceColumnIssueTypes
|
||||
? WorkspaceHealthColumnIssue<T>
|
||||
: T extends WorkspaceRelationIssueTypes
|
||||
? WorkspaceHealthRelationIssue<T>
|
||||
: never;
|
||||
: never;
|
||||
|
||||
/**
|
||||
* Union of all issues
|
||||
|
||||
@ -1,250 +0,0 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { WorkspaceTableStructure } from 'src/engine/workspace-manager/workspace-health/interfaces/workspace-table-definition.interface';
|
||||
import {
|
||||
WorkspaceHealthIssue,
|
||||
WorkspaceHealthIssueType,
|
||||
} from 'src/engine/workspace-manager/workspace-health/interfaces/workspace-health-issue.interface';
|
||||
import {
|
||||
WorkspaceHealthMode,
|
||||
WorkspaceHealthOptions,
|
||||
} from 'src/engine/workspace-manager/workspace-health/interfaces/workspace-health-options.interface';
|
||||
|
||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import {
|
||||
RelationMetadataEntity,
|
||||
RelationMetadataType,
|
||||
} from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity';
|
||||
import {
|
||||
RelationDirection,
|
||||
deduceRelationDirection,
|
||||
} from 'src/engine/utils/deduce-relation-direction.util';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { createRelationForeignKeyFieldMetadataName } from 'src/engine/metadata-modules/relation-metadata/utils/create-relation-foreign-key-field-metadata-name.util';
|
||||
import { isRelationFieldMetadataType } from 'src/engine/utils/is-relation-field-metadata-type.util';
|
||||
import { convertOnDeleteActionToOnDelete } from 'src/engine/workspace-manager/workspace-migration-runner/utils/convert-on-delete-action-to-on-delete.util';
|
||||
import { camelCase } from 'src/utils/camel-case';
|
||||
|
||||
@Injectable()
|
||||
export class RelationMetadataHealthService {
|
||||
constructor() {}
|
||||
|
||||
public healthCheck(
|
||||
workspaceTableColumns: WorkspaceTableStructure[],
|
||||
objectMetadataCollection: ObjectMetadataEntity[],
|
||||
objectMetadata: ObjectMetadataEntity,
|
||||
options: WorkspaceHealthOptions,
|
||||
) {
|
||||
const issues: WorkspaceHealthIssue[] = [];
|
||||
|
||||
for (const fieldMetadata of objectMetadata.fields) {
|
||||
// We're only interested in relation fields
|
||||
if (!isRelationFieldMetadataType(fieldMetadata.type)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const relationMetadata =
|
||||
fieldMetadata.fromRelationMetadata ?? fieldMetadata.toRelationMetadata;
|
||||
|
||||
if (!relationMetadata) {
|
||||
issues.push({
|
||||
type: WorkspaceHealthIssueType.RELATION_METADATA_NOT_VALID,
|
||||
message: `Field ${fieldMetadata.id} has invalid relation metadata`,
|
||||
});
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
const relationDirection = deduceRelationDirection(
|
||||
fieldMetadata,
|
||||
relationMetadata,
|
||||
);
|
||||
|
||||
// Many to many relations are not supported yet
|
||||
if (relationMetadata.relationType === RelationMetadataType.MANY_TO_MANY) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const fromObjectMetadata = objectMetadataCollection.find(
|
||||
(objectMetadata) =>
|
||||
objectMetadata.id === relationMetadata.fromObjectMetadataId,
|
||||
);
|
||||
const fromFieldMetadata = fromObjectMetadata?.fields.find(
|
||||
(fieldMetadata) =>
|
||||
fieldMetadata.id === relationMetadata.fromFieldMetadataId,
|
||||
);
|
||||
const toObjectMetadata = objectMetadataCollection.find(
|
||||
(objectMetadata) =>
|
||||
objectMetadata.id === relationMetadata.toObjectMetadataId,
|
||||
);
|
||||
const toFieldMetadata = toObjectMetadata?.fields.find(
|
||||
(fieldMetadata) =>
|
||||
fieldMetadata.id === relationMetadata.toFieldMetadataId,
|
||||
);
|
||||
|
||||
if (!fromFieldMetadata || !toFieldMetadata) {
|
||||
issues.push({
|
||||
type: WorkspaceHealthIssueType.RELATION_FROM_OR_TO_FIELD_METADATA_NOT_VALID,
|
||||
fromFieldMetadata,
|
||||
toFieldMetadata,
|
||||
relationMetadata,
|
||||
message: `Relation ${relationMetadata.id} has invalid from or to field metadata`,
|
||||
});
|
||||
|
||||
return issues;
|
||||
}
|
||||
|
||||
if (
|
||||
options.mode === WorkspaceHealthMode.All ||
|
||||
options.mode === WorkspaceHealthMode.Structure
|
||||
) {
|
||||
// Check relation structure
|
||||
const structureIssues = this.structureRelationCheck(
|
||||
fromFieldMetadata,
|
||||
toFieldMetadata,
|
||||
toObjectMetadata?.fields ?? [],
|
||||
relationDirection,
|
||||
relationMetadata,
|
||||
workspaceTableColumns,
|
||||
);
|
||||
|
||||
issues.push(...structureIssues);
|
||||
}
|
||||
|
||||
if (
|
||||
options.mode === WorkspaceHealthMode.All ||
|
||||
options.mode === WorkspaceHealthMode.Metadata
|
||||
) {
|
||||
// Check relation metadata
|
||||
const metadataIssues = this.metadataRelationCheck(
|
||||
fromFieldMetadata,
|
||||
toFieldMetadata,
|
||||
relationDirection,
|
||||
relationMetadata,
|
||||
);
|
||||
|
||||
issues.push(...metadataIssues);
|
||||
}
|
||||
}
|
||||
|
||||
return issues;
|
||||
}
|
||||
|
||||
private structureRelationCheck(
|
||||
fromFieldMetadata: FieldMetadataEntity,
|
||||
toFieldMetadata: FieldMetadataEntity,
|
||||
toObjectMetadataFields: FieldMetadataEntity[],
|
||||
relationDirection: RelationDirection,
|
||||
relationMetadata: RelationMetadataEntity,
|
||||
workspaceTableColumns: WorkspaceTableStructure[],
|
||||
): WorkspaceHealthIssue[] {
|
||||
const issues: WorkspaceHealthIssue[] = [];
|
||||
|
||||
// Nothing to check on the structure
|
||||
if (relationDirection === RelationDirection.FROM) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const foreignKeyColumnName = `${camelCase(toFieldMetadata.name)}Id`;
|
||||
const relationColumn = workspaceTableColumns.find(
|
||||
(column) => column.columnName === foreignKeyColumnName,
|
||||
);
|
||||
const relationFieldMetadata = toObjectMetadataFields.find(
|
||||
(fieldMetadata) =>
|
||||
fieldMetadata.name ===
|
||||
createRelationForeignKeyFieldMetadataName(toFieldMetadata.name),
|
||||
);
|
||||
|
||||
if (!relationFieldMetadata) {
|
||||
issues.push({
|
||||
type: WorkspaceHealthIssueType.RELATION_FOREIGN_KEY_NOT_VALID,
|
||||
fromFieldMetadata,
|
||||
toFieldMetadata,
|
||||
relationMetadata,
|
||||
message: `Relation ${
|
||||
relationMetadata.id
|
||||
} doesn't have a valid foreign key (expected fieldMetadata.name to be ${createRelationForeignKeyFieldMetadataName(
|
||||
toFieldMetadata.name,
|
||||
)}`,
|
||||
});
|
||||
|
||||
return issues;
|
||||
}
|
||||
|
||||
if (!relationColumn) {
|
||||
issues.push({
|
||||
type: WorkspaceHealthIssueType.RELATION_FOREIGN_KEY_NOT_VALID,
|
||||
fromFieldMetadata,
|
||||
toFieldMetadata,
|
||||
relationMetadata,
|
||||
message: `Relation ${relationMetadata.id} doesn't have a valid foreign key (expected column name to be ${foreignKeyColumnName}`,
|
||||
});
|
||||
|
||||
return issues;
|
||||
}
|
||||
|
||||
if (!relationColumn.isForeignKey) {
|
||||
issues.push({
|
||||
type: WorkspaceHealthIssueType.RELATION_FOREIGN_KEY_CONFLICT,
|
||||
fromFieldMetadata,
|
||||
toFieldMetadata,
|
||||
relationMetadata,
|
||||
message: `Relation ${relationMetadata.id} foreign key is not properly set`,
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
relationMetadata.relationType === RelationMetadataType.ONE_TO_ONE &&
|
||||
!relationColumn.isUnique
|
||||
) {
|
||||
issues.push({
|
||||
type: WorkspaceHealthIssueType.RELATION_FOREIGN_KEY_CONFLICT,
|
||||
fromFieldMetadata,
|
||||
toFieldMetadata,
|
||||
relationMetadata,
|
||||
message: `Relation ${relationMetadata.id} foreign key is not marked as unique and relation type is one-to-one`,
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
convertOnDeleteActionToOnDelete(relationMetadata.onDeleteAction) !==
|
||||
relationColumn.onDeleteAction
|
||||
) {
|
||||
issues.push({
|
||||
type: WorkspaceHealthIssueType.RELATION_FOREIGN_KEY_ON_DELETE_ACTION_CONFLICT,
|
||||
fromFieldMetadata,
|
||||
toFieldMetadata,
|
||||
relationMetadata,
|
||||
columnStructure: relationColumn,
|
||||
message: `Relation ${relationMetadata.id} foreign key onDeleteAction is not properly set`,
|
||||
});
|
||||
}
|
||||
|
||||
return issues;
|
||||
}
|
||||
|
||||
private metadataRelationCheck(
|
||||
fromFieldMetadata: FieldMetadataEntity,
|
||||
toFieldMetadata: FieldMetadataEntity,
|
||||
relationDirection: RelationDirection,
|
||||
relationMetadata: RelationMetadataEntity,
|
||||
): WorkspaceHealthIssue[] {
|
||||
const issues: WorkspaceHealthIssue[] = [];
|
||||
|
||||
if (
|
||||
!Object.values(RelationMetadataType).includes(
|
||||
relationMetadata.relationType,
|
||||
)
|
||||
) {
|
||||
issues.push({
|
||||
type: WorkspaceHealthIssueType.RELATION_TYPE_NOT_VALID,
|
||||
fromFieldMetadata,
|
||||
toFieldMetadata,
|
||||
relationMetadata,
|
||||
message: `Relation ${relationMetadata.id} has invalid relation type`,
|
||||
});
|
||||
}
|
||||
|
||||
return issues;
|
||||
}
|
||||
}
|
||||
@ -7,7 +7,6 @@ import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/works
|
||||
import { DatabaseStructureService } from 'src/engine/workspace-manager/workspace-health/services/database-structure.service';
|
||||
import { FieldMetadataHealthService } from 'src/engine/workspace-manager/workspace-health/services/field-metadata-health.service';
|
||||
import { ObjectMetadataHealthService } from 'src/engine/workspace-manager/workspace-health/services/object-metadata-health.service';
|
||||
import { RelationMetadataHealthService } from 'src/engine/workspace-manager/workspace-health/services/relation-metadata.health.service';
|
||||
import { WorkspaceHealthService } from 'src/engine/workspace-manager/workspace-health/workspace-health.service';
|
||||
import { WorkspaceMigrationBuilderModule } from 'src/engine/workspace-manager/workspace-migration-builder/workspace-migration-builder.module';
|
||||
import { WorkspaceMigrationRunnerModule } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.module';
|
||||
@ -31,7 +30,6 @@ import { WorkspaceFixService } from './services/workspace-fix.service';
|
||||
DatabaseStructureService,
|
||||
ObjectMetadataHealthService,
|
||||
FieldMetadataHealthService,
|
||||
RelationMetadataHealthService,
|
||||
WorkspaceFixService,
|
||||
],
|
||||
exports: [WorkspaceHealthService],
|
||||
|
||||
@ -18,7 +18,6 @@ import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/work
|
||||
import { DatabaseStructureService } from 'src/engine/workspace-manager/workspace-health/services/database-structure.service';
|
||||
import { FieldMetadataHealthService } from 'src/engine/workspace-manager/workspace-health/services/field-metadata-health.service';
|
||||
import { ObjectMetadataHealthService } from 'src/engine/workspace-manager/workspace-health/services/object-metadata-health.service';
|
||||
import { RelationMetadataHealthService } from 'src/engine/workspace-manager/workspace-health/services/relation-metadata.health.service';
|
||||
import { WorkspaceFixService } from 'src/engine/workspace-manager/workspace-health/services/workspace-fix.service';
|
||||
import { WorkspaceMigrationRunnerService } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.service';
|
||||
|
||||
@ -27,15 +26,14 @@ export class WorkspaceHealthService {
|
||||
private readonly logger = new Logger(WorkspaceHealthService.name);
|
||||
|
||||
constructor(
|
||||
@InjectDataSource('metadata')
|
||||
private readonly metadataDataSource: DataSource,
|
||||
@InjectDataSource('core')
|
||||
private readonly coreDataSource: DataSource,
|
||||
private readonly dataSourceService: DataSourceService,
|
||||
private readonly objectMetadataService: ObjectMetadataService,
|
||||
private readonly databaseStructureService: DatabaseStructureService,
|
||||
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
||||
private readonly objectMetadataHealthService: ObjectMetadataHealthService,
|
||||
private readonly fieldMetadataHealthService: FieldMetadataHealthService,
|
||||
private readonly relationMetadataHealthService: RelationMetadataHealthService,
|
||||
private readonly workspaceMigrationRunnerService: WorkspaceMigrationRunnerService,
|
||||
private readonly workspaceFixService: WorkspaceFixService,
|
||||
) {}
|
||||
@ -100,16 +98,6 @@ export class WorkspaceHealthService {
|
||||
);
|
||||
|
||||
issues.push(...fieldIssues);
|
||||
|
||||
// Check relation metadata health
|
||||
const relationIssues = this.relationMetadataHealthService.healthCheck(
|
||||
workspaceTableColumns,
|
||||
objectMetadataCollection,
|
||||
objectMetadata,
|
||||
options,
|
||||
);
|
||||
|
||||
issues.push(...relationIssues);
|
||||
}
|
||||
|
||||
return issues;
|
||||
@ -132,7 +120,7 @@ export class WorkspaceHealthService {
|
||||
// Set default options
|
||||
options.applyChanges ??= true;
|
||||
|
||||
const queryRunner = this.metadataDataSource.createQueryRunner();
|
||||
const queryRunner = this.coreDataSource.createQueryRunner();
|
||||
|
||||
await queryRunner.connect();
|
||||
await queryRunner.startTransaction();
|
||||
|
||||
@ -8,14 +8,13 @@ import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-s
|
||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadata/object-metadata.module';
|
||||
import { PermissionsModule } from 'src/engine/metadata-modules/permissions/permissions.module';
|
||||
import { RelationMetadataEntity } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity';
|
||||
import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
|
||||
import { RoleModule } from 'src/engine/metadata-modules/role/role.module';
|
||||
import { UserWorkspaceRoleEntity } from 'src/engine/metadata-modules/role/user-workspace-role.entity';
|
||||
import { UserRoleModule } from 'src/engine/metadata-modules/user-role/user-role.module';
|
||||
import { WorkspaceMigrationModule } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.module';
|
||||
import { SeederModule } from 'src/engine/seeder/seeder.module';
|
||||
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
||||
import { DevSeederModule } from 'src/engine/workspace-manager/dev-seeder/dev-seeder.module';
|
||||
import { WorkspaceHealthModule } from 'src/engine/workspace-manager/workspace-health/workspace-health.module';
|
||||
import { WorkspaceSyncMetadataModule } from 'src/engine/workspace-manager/workspace-sync-metadata/workspace-sync-metadata.module';
|
||||
|
||||
@ -26,7 +25,7 @@ import { WorkspaceManagerService } from './workspace-manager.service';
|
||||
WorkspaceDataSourceModule,
|
||||
WorkspaceMigrationModule,
|
||||
ObjectMetadataModule,
|
||||
SeederModule,
|
||||
DevSeederModule,
|
||||
DataSourceModule,
|
||||
WorkspaceSyncMetadataModule,
|
||||
WorkspaceHealthModule,
|
||||
@ -36,13 +35,8 @@ import { WorkspaceManagerService } from './workspace-manager.service';
|
||||
RoleModule,
|
||||
UserRoleModule,
|
||||
TypeOrmModule.forFeature(
|
||||
[
|
||||
FieldMetadataEntity,
|
||||
RelationMetadataEntity,
|
||||
UserWorkspaceRoleEntity,
|
||||
RoleEntity,
|
||||
],
|
||||
'metadata',
|
||||
[FieldMetadataEntity, UserWorkspaceRoleEntity, RoleEntity],
|
||||
'core',
|
||||
),
|
||||
],
|
||||
exports: [WorkspaceManagerService],
|
||||
|
||||
@ -1,14 +1,8 @@
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { WorkspaceActivationStatus } from 'twenty-shared/workspace';
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import { DEV_SEED_USER_WORKSPACE_IDS } from 'src/database/typeorm-seeds/core/user-workspaces';
|
||||
import {
|
||||
SEED_ACME_WORKSPACE_ID,
|
||||
SEED_APPLE_WORKSPACE_ID,
|
||||
} from 'src/database/typeorm-seeds/core/workspaces';
|
||||
import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service';
|
||||
import { UserWorkspace } from 'src/engine/core-modules/user-workspace/user-workspace.entity';
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
@ -16,20 +10,12 @@ import { DataSourceEntity } from 'src/engine/metadata-modules/data-source/data-s
|
||||
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service';
|
||||
import { PermissionsService } from 'src/engine/metadata-modules/permissions/permissions.service';
|
||||
import { RelationMetadataEntity } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity';
|
||||
import { RoleEntity } from 'src/engine/metadata-modules/role/role.entity';
|
||||
import { RoleService } from 'src/engine/metadata-modules/role/role.service';
|
||||
import { UserWorkspaceRoleEntity } from 'src/engine/metadata-modules/role/user-workspace-role.entity';
|
||||
import { UserRoleService } from 'src/engine/metadata-modules/user-role/user-role.service';
|
||||
import { WorkspaceMigrationService } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.service';
|
||||
import { PETS_DATA_SEEDS } from 'src/engine/seeder/data-seeds/pets-data-seeds';
|
||||
import { SURVEY_RESULTS_DATA_SEEDS } from 'src/engine/seeder/data-seeds/survey-results-data-seeds';
|
||||
import { PETS_METADATA_SEEDS } from 'src/engine/seeder/metadata-seeds/pets-metadata-seeds';
|
||||
import { SURVEY_RESULTS_METADATA_SEEDS } from 'src/engine/seeder/metadata-seeds/survey-results-metadata-seeds';
|
||||
import { SeederService } from 'src/engine/seeder/seeder.service';
|
||||
import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service';
|
||||
import { seedWorkspaceWithDemoData } from 'src/engine/workspace-manager/demo-objects-prefill-data/seed-workspace-with-demo-data';
|
||||
import { standardObjectsPrefillData } from 'src/engine/workspace-manager/standard-objects-prefill-data/standard-objects-prefill-data';
|
||||
import { WorkspaceSyncMetadataService } from 'src/engine/workspace-manager/workspace-sync-metadata/workspace-sync-metadata.service';
|
||||
|
||||
@ -41,14 +27,10 @@ export class WorkspaceManagerService {
|
||||
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
||||
private readonly workspaceMigrationService: WorkspaceMigrationService,
|
||||
private readonly objectMetadataService: ObjectMetadataService,
|
||||
private readonly seederService: SeederService,
|
||||
private readonly dataSourceService: DataSourceService,
|
||||
private readonly workspaceSyncMetadataService: WorkspaceSyncMetadataService,
|
||||
private readonly permissionsService: PermissionsService,
|
||||
@InjectRepository(FieldMetadataEntity, 'metadata')
|
||||
@InjectRepository(FieldMetadataEntity, 'core')
|
||||
private readonly fieldMetadataRepository: Repository<FieldMetadataEntity>,
|
||||
@InjectRepository(RelationMetadataEntity, 'metadata')
|
||||
private readonly relationMetadataRepository: Repository<RelationMetadataEntity>,
|
||||
@InjectRepository(UserWorkspace, 'core')
|
||||
private readonly userWorkspaceRepository: Repository<UserWorkspace>,
|
||||
private readonly roleService: RoleService,
|
||||
@ -56,17 +38,12 @@ export class WorkspaceManagerService {
|
||||
private readonly featureFlagService: FeatureFlagService,
|
||||
@InjectRepository(Workspace, 'core')
|
||||
private readonly workspaceRepository: Repository<Workspace>,
|
||||
@InjectRepository(UserWorkspaceRoleEntity, 'metadata')
|
||||
@InjectRepository(UserWorkspaceRoleEntity, 'core')
|
||||
private readonly userWorkspaceRoleRepository: Repository<UserWorkspaceRoleEntity>,
|
||||
@InjectRepository(RoleEntity, 'metadata')
|
||||
@InjectRepository(RoleEntity, 'core')
|
||||
private readonly roleRepository: Repository<RoleEntity>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Init a workspace by creating a new data source and running all migrations
|
||||
* @param workspaceId
|
||||
* @returns Promise<void>
|
||||
*/
|
||||
public async init({
|
||||
workspaceId,
|
||||
userId,
|
||||
@ -120,7 +97,7 @@ export class WorkspaceManagerService {
|
||||
|
||||
const prefillStandardObjectsStart = performance.now();
|
||||
|
||||
await this.prefillWorkspaceWithStandardObjects(
|
||||
await this.prefillWorkspaceWithStandardObjectsRecords(
|
||||
dataSourceMetadata,
|
||||
workspaceId,
|
||||
);
|
||||
@ -132,67 +109,7 @@ export class WorkspaceManagerService {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* InitDemo a workspace by creating a new data source and running all migrations
|
||||
* @param workspaceId
|
||||
* @returns Promise<void>
|
||||
*/
|
||||
public async initDemo(workspaceId: string): Promise<void> {
|
||||
const schemaName =
|
||||
await this.workspaceDataSourceService.createWorkspaceDBSchema(
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
const dataSourceMetadata =
|
||||
await this.dataSourceService.createDataSourceMetadata(
|
||||
workspaceId,
|
||||
schemaName,
|
||||
);
|
||||
|
||||
const featureFlags =
|
||||
await this.featureFlagService.getWorkspaceFeatureFlagsMap(workspaceId);
|
||||
|
||||
await this.workspaceSyncMetadataService.synchronize({
|
||||
workspaceId,
|
||||
dataSourceId: dataSourceMetadata.id,
|
||||
featureFlags,
|
||||
});
|
||||
|
||||
await this.prefillWorkspaceWithDemoObjects(dataSourceMetadata, workspaceId);
|
||||
}
|
||||
|
||||
public async initDev(workspaceId: string): Promise<void> {
|
||||
const schemaName =
|
||||
await this.workspaceDataSourceService.createWorkspaceDBSchema(
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
const dataSourceMetadata =
|
||||
await this.dataSourceService.createDataSourceMetadata(
|
||||
workspaceId,
|
||||
schemaName,
|
||||
);
|
||||
|
||||
const featureFlags =
|
||||
await this.featureFlagService.getWorkspaceFeatureFlagsMap(workspaceId);
|
||||
|
||||
await this.workspaceSyncMetadataService.synchronize({
|
||||
workspaceId: workspaceId,
|
||||
dataSourceId: dataSourceMetadata.id,
|
||||
featureFlags,
|
||||
});
|
||||
|
||||
await this.initPermissionsDev(workspaceId);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* We are prefilling a few standard objects with data to make it easier for the user to get started.
|
||||
*
|
||||
* @param dataSourceMetadata
|
||||
* @param workspaceId
|
||||
*/
|
||||
private async prefillWorkspaceWithStandardObjects(
|
||||
private async prefillWorkspaceWithStandardObjectsRecords(
|
||||
dataSourceMetadata: DataSourceEntity,
|
||||
workspaceId: string,
|
||||
) {
|
||||
@ -213,74 +130,10 @@ export class WorkspaceManagerService {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* We are prefilling a few demo objects with data to make it easier for the user to get started.
|
||||
*
|
||||
* @param dataSourceMetadata
|
||||
* @param workspaceId
|
||||
*/
|
||||
private async prefillWorkspaceWithDemoObjects(
|
||||
dataSourceMetadata: DataSourceEntity,
|
||||
workspaceId: string,
|
||||
) {
|
||||
const mainDataSource =
|
||||
await this.workspaceDataSourceService.connectToMainDataSource();
|
||||
|
||||
if (!mainDataSource) {
|
||||
throw new Error('Could not connect to main data source');
|
||||
}
|
||||
|
||||
const createdObjectMetadata =
|
||||
await this.objectMetadataService.findManyWithinWorkspace(workspaceId);
|
||||
|
||||
await seedWorkspaceWithDemoData(
|
||||
mainDataSource,
|
||||
dataSourceMetadata.schema,
|
||||
createdObjectMetadata,
|
||||
);
|
||||
|
||||
await this.seederService.seedCustomObjects(
|
||||
dataSourceMetadata.id,
|
||||
workspaceId,
|
||||
PETS_METADATA_SEEDS,
|
||||
);
|
||||
|
||||
await this.seederService.seedCustomObjectRecords(
|
||||
workspaceId,
|
||||
PETS_METADATA_SEEDS,
|
||||
PETS_DATA_SEEDS,
|
||||
);
|
||||
|
||||
await this.seederService.seedCustomObjects(
|
||||
dataSourceMetadata.id,
|
||||
workspaceId,
|
||||
SURVEY_RESULTS_METADATA_SEEDS,
|
||||
);
|
||||
|
||||
await this.seederService.seedCustomObjectRecords(
|
||||
workspaceId,
|
||||
SURVEY_RESULTS_METADATA_SEEDS,
|
||||
SURVEY_RESULTS_DATA_SEEDS,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Delete a workspace by deleting all metadata and the schema
|
||||
*
|
||||
* @param workspaceId
|
||||
*/
|
||||
public async delete(workspaceId: string): Promise<void> {
|
||||
//TODO: delete all logs when #611 closed
|
||||
this.logger.log(`Deleting workspace ${workspaceId} ...`);
|
||||
|
||||
// Delete data from metadata tables
|
||||
await this.relationMetadataRepository.delete({
|
||||
workspaceId,
|
||||
});
|
||||
this.logger.log(`workspace ${workspaceId} relation metadata deleted`);
|
||||
|
||||
await this.fieldMetadataRepository.delete({
|
||||
workspaceId,
|
||||
});
|
||||
@ -341,56 +194,4 @@ export class WorkspaceManagerService {
|
||||
defaultRoleId: memberRole.id,
|
||||
});
|
||||
}
|
||||
|
||||
private async initPermissionsDev(workspaceId: string) {
|
||||
const adminRole = await this.roleService.createAdminRole({
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
let adminUserWorkspaceId: string | undefined;
|
||||
let memberUserWorkspaceId: string | undefined;
|
||||
|
||||
if (workspaceId === SEED_APPLE_WORKSPACE_ID) {
|
||||
adminUserWorkspaceId = DEV_SEED_USER_WORKSPACE_IDS.TIM;
|
||||
memberUserWorkspaceId = DEV_SEED_USER_WORKSPACE_IDS.JONY;
|
||||
|
||||
// Create guest role only in this workspace
|
||||
const guestRole = await this.roleService.createGuestRole({
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
await this.userRoleService.assignRoleToUserWorkspace({
|
||||
workspaceId,
|
||||
userWorkspaceId: DEV_SEED_USER_WORKSPACE_IDS.PHIL,
|
||||
roleId: guestRole.id,
|
||||
});
|
||||
} else if (workspaceId === SEED_ACME_WORKSPACE_ID) {
|
||||
adminUserWorkspaceId = DEV_SEED_USER_WORKSPACE_IDS.TIM_ACME;
|
||||
}
|
||||
|
||||
if (adminUserWorkspaceId) {
|
||||
await this.userRoleService.assignRoleToUserWorkspace({
|
||||
workspaceId,
|
||||
userWorkspaceId: adminUserWorkspaceId,
|
||||
roleId: adminRole.id,
|
||||
});
|
||||
}
|
||||
|
||||
const memberRole = await this.roleService.createMemberRole({
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
await this.workspaceRepository.update(workspaceId, {
|
||||
defaultRoleId: memberRole.id,
|
||||
activationStatus: WorkspaceActivationStatus.ACTIVE,
|
||||
});
|
||||
|
||||
if (memberUserWorkspaceId) {
|
||||
await this.userRoleService.assignRoleToUserWorkspace({
|
||||
workspaceId,
|
||||
userWorkspaceId: memberUserWorkspaceId,
|
||||
roleId: memberRole.id,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,12 +3,10 @@ import { WorkspaceMigrationIndexFactory } from 'src/engine/workspace-manager/wor
|
||||
import { WorkspaceMigrationFieldRelationFactory } from './workspace-migration-field-relation.factory';
|
||||
import { WorkspaceMigrationFieldFactory } from './workspace-migration-field.factory';
|
||||
import { WorkspaceMigrationObjectFactory } from './workspace-migration-object.factory';
|
||||
import { WorkspaceMigrationRelationFactory } from './workspace-migration-relation.factory';
|
||||
|
||||
export const workspaceMigrationBuilderFactories = [
|
||||
WorkspaceMigrationObjectFactory,
|
||||
WorkspaceMigrationFieldFactory,
|
||||
WorkspaceMigrationFieldRelationFactory,
|
||||
WorkspaceMigrationRelationFactory,
|
||||
WorkspaceMigrationIndexFactory,
|
||||
];
|
||||
|
||||
@ -5,7 +5,6 @@ import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { WorkspaceMigrationBuilderAction } from 'src/engine/workspace-manager/workspace-migration-builder/interfaces/workspace-migration-builder-action.interface';
|
||||
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { RelationMetadataEntity } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity';
|
||||
import { generateMigrationName } from 'src/engine/metadata-modules/workspace-migration/utils/generate-migration-name.util';
|
||||
import {
|
||||
WorkspaceMigrationColumnActionType,
|
||||
@ -40,10 +39,6 @@ export class WorkspaceMigrationObjectFactory {
|
||||
async create(
|
||||
objectMetadataCollection: ObjectMetadataEntity[],
|
||||
action: WorkspaceMigrationBuilderAction.DELETE,
|
||||
relationMetadataByFromObjectMetadataId: Record<
|
||||
string,
|
||||
RelationMetadataEntity[]
|
||||
>,
|
||||
): Promise<Partial<WorkspaceMigrationEntity>[]>;
|
||||
|
||||
async create(
|
||||
@ -51,10 +46,6 @@ export class WorkspaceMigrationObjectFactory {
|
||||
| ObjectMetadataEntity[]
|
||||
| ObjectMetadataUpdate[],
|
||||
action: WorkspaceMigrationBuilderAction,
|
||||
relationMetadataByFromObjectMetadataId?: Record<
|
||||
string,
|
||||
RelationMetadataEntity[]
|
||||
>,
|
||||
): Promise<Partial<WorkspaceMigrationEntity>[]> {
|
||||
switch (action) {
|
||||
case WorkspaceMigrationBuilderAction.CREATE:
|
||||
@ -68,10 +59,6 @@ export class WorkspaceMigrationObjectFactory {
|
||||
case WorkspaceMigrationBuilderAction.DELETE:
|
||||
return this.deleteObjectMigration(
|
||||
objectMetadataCollectionOrObjectMetadataUpdateCollection as ObjectMetadataEntity[],
|
||||
relationMetadataByFromObjectMetadataId as Record<
|
||||
string,
|
||||
RelationMetadataEntity[]
|
||||
>,
|
||||
);
|
||||
default:
|
||||
return [];
|
||||
@ -153,37 +140,15 @@ export class WorkspaceMigrationObjectFactory {
|
||||
|
||||
private async deleteObjectMigration(
|
||||
objectMetadataCollection: ObjectMetadataEntity[],
|
||||
relationMetadataByFromObjectMetadataId: Record<
|
||||
string,
|
||||
RelationMetadataEntity[]
|
||||
>,
|
||||
): Promise<Partial<WorkspaceMigrationEntity>[]> {
|
||||
const workspaceMigrations: Partial<WorkspaceMigrationEntity>[] = [];
|
||||
|
||||
for (const objectMetadata of objectMetadataCollection) {
|
||||
const relationMetadataCollection =
|
||||
relationMetadataByFromObjectMetadataId[objectMetadata.id];
|
||||
|
||||
workspaceMigrations.push({
|
||||
workspaceId: objectMetadata.workspaceId,
|
||||
name: generateMigrationName(`delete-${objectMetadata.nameSingular}`),
|
||||
isCustom: objectMetadata.isCustom,
|
||||
migrations: [
|
||||
...(relationMetadataCollection ?? []).map(
|
||||
(relationMetadata) =>
|
||||
({
|
||||
name: computeObjectTargetTable(
|
||||
relationMetadata.toObjectMetadata,
|
||||
),
|
||||
action: WorkspaceMigrationTableActionType.ALTER,
|
||||
columns: [
|
||||
{
|
||||
action: WorkspaceMigrationColumnActionType.DROP_FOREIGN_KEY,
|
||||
columnName: `${relationMetadata.toFieldMetadata.name}Id`,
|
||||
},
|
||||
],
|
||||
}) satisfies WorkspaceMigrationTableAction,
|
||||
),
|
||||
{
|
||||
name: computeObjectTargetTable(objectMetadata),
|
||||
action: WorkspaceMigrationTableActionType.DROP,
|
||||
|
||||
@ -1,198 +0,0 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { WorkspaceMigrationBuilderAction } from 'src/engine/workspace-manager/workspace-migration-builder/interfaces/workspace-migration-builder-action.interface';
|
||||
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import {
|
||||
WorkspaceMigrationColumnActionType,
|
||||
WorkspaceMigrationEntity,
|
||||
WorkspaceMigrationTableAction,
|
||||
WorkspaceMigrationTableActionType,
|
||||
} from 'src/engine/metadata-modules/workspace-migration/workspace-migration.entity';
|
||||
import { computeObjectTargetTable } from 'src/engine/utils/compute-object-target-table.util';
|
||||
import {
|
||||
RelationMetadataEntity,
|
||||
RelationMetadataType,
|
||||
} from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity';
|
||||
import { camelCase } from 'src/utils/camel-case';
|
||||
import { generateMigrationName } from 'src/engine/metadata-modules/workspace-migration/utils/generate-migration-name.util';
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceMigrationRelationFactory {
|
||||
constructor() {}
|
||||
|
||||
/**
|
||||
* Deletion of the relation is handled by field deletion
|
||||
*/
|
||||
async create(
|
||||
originalObjectMetadataCollection: ObjectMetadataEntity[],
|
||||
relationMetadataCollection: RelationMetadataEntity[],
|
||||
action: WorkspaceMigrationBuilderAction,
|
||||
): Promise<Partial<WorkspaceMigrationEntity>[]> {
|
||||
const originalObjectMetadataMap = originalObjectMetadataCollection.reduce(
|
||||
(result, currentObject) => {
|
||||
result[currentObject.id] = currentObject;
|
||||
|
||||
return result;
|
||||
},
|
||||
{} as Record<string, ObjectMetadataEntity>,
|
||||
);
|
||||
|
||||
switch (action) {
|
||||
case WorkspaceMigrationBuilderAction.CREATE:
|
||||
return this.createRelationMigration(
|
||||
originalObjectMetadataMap,
|
||||
relationMetadataCollection,
|
||||
);
|
||||
case WorkspaceMigrationBuilderAction.UPDATE:
|
||||
return this.updateRelationMigration(
|
||||
originalObjectMetadataMap,
|
||||
relationMetadataCollection,
|
||||
);
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
private async updateRelationMigration(
|
||||
originalObjectMetadataMap: Record<string, ObjectMetadataEntity>,
|
||||
relationMetadataCollection: RelationMetadataEntity[],
|
||||
): Promise<Partial<WorkspaceMigrationEntity>[]> {
|
||||
const workspaceMigrations: Partial<WorkspaceMigrationEntity>[] = [];
|
||||
|
||||
for (const relationMetadata of relationMetadataCollection) {
|
||||
const toObjectMetadata =
|
||||
originalObjectMetadataMap[relationMetadata.toObjectMetadataId];
|
||||
const fromObjectMetadata =
|
||||
originalObjectMetadataMap[relationMetadata.fromObjectMetadataId];
|
||||
|
||||
if (!toObjectMetadata) {
|
||||
throw new Error(
|
||||
`ObjectMetadata with id ${relationMetadata.toObjectMetadataId} not found`,
|
||||
);
|
||||
}
|
||||
|
||||
if (!fromObjectMetadata) {
|
||||
throw new Error(
|
||||
`ObjectMetadata with id ${relationMetadata.fromObjectMetadataId} not found`,
|
||||
);
|
||||
}
|
||||
|
||||
const toFieldMetadata = toObjectMetadata.fields.find(
|
||||
(field) => field.id === relationMetadata.toFieldMetadataId,
|
||||
);
|
||||
|
||||
if (!toFieldMetadata) {
|
||||
throw new Error(
|
||||
`FieldMetadata with id ${relationMetadata.toFieldMetadataId} not found`,
|
||||
);
|
||||
}
|
||||
|
||||
const migrations: WorkspaceMigrationTableAction[] = [
|
||||
{
|
||||
name: computeObjectTargetTable(toObjectMetadata),
|
||||
action: WorkspaceMigrationTableActionType.ALTER,
|
||||
columns: [
|
||||
{
|
||||
action: WorkspaceMigrationColumnActionType.DROP_FOREIGN_KEY,
|
||||
columnName: `${camelCase(toFieldMetadata.name)}Id`,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: computeObjectTargetTable(toObjectMetadata),
|
||||
action: WorkspaceMigrationTableActionType.ALTER,
|
||||
columns: [
|
||||
{
|
||||
action: WorkspaceMigrationColumnActionType.CREATE_FOREIGN_KEY,
|
||||
columnName: `${camelCase(toFieldMetadata.name)}Id`,
|
||||
referencedTableName: computeObjectTargetTable(fromObjectMetadata),
|
||||
referencedTableColumnName: 'id',
|
||||
isUnique:
|
||||
relationMetadata.relationType ===
|
||||
RelationMetadataType.ONE_TO_ONE,
|
||||
onDelete: relationMetadata.onDeleteAction,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
workspaceMigrations.push({
|
||||
workspaceId: relationMetadata.workspaceId,
|
||||
name: generateMigrationName(
|
||||
`update-relation-from-${fromObjectMetadata.nameSingular}-to-${toObjectMetadata.nameSingular}`,
|
||||
),
|
||||
isCustom: false,
|
||||
migrations,
|
||||
});
|
||||
}
|
||||
|
||||
return workspaceMigrations;
|
||||
}
|
||||
|
||||
private async createRelationMigration(
|
||||
originalObjectMetadataMap: Record<string, ObjectMetadataEntity>,
|
||||
relationMetadataCollection: RelationMetadataEntity[],
|
||||
): Promise<Partial<WorkspaceMigrationEntity>[]> {
|
||||
const workspaceMigrations: Partial<WorkspaceMigrationEntity>[] = [];
|
||||
|
||||
for (const relationMetadata of relationMetadataCollection) {
|
||||
const toObjectMetadata =
|
||||
originalObjectMetadataMap[relationMetadata.toObjectMetadataId];
|
||||
const fromObjectMetadata =
|
||||
originalObjectMetadataMap[relationMetadata.fromObjectMetadataId];
|
||||
|
||||
if (!toObjectMetadata) {
|
||||
throw new Error(
|
||||
`ObjectMetadata with id ${relationMetadata.toObjectMetadataId} not found`,
|
||||
);
|
||||
}
|
||||
|
||||
if (!fromObjectMetadata) {
|
||||
throw new Error(
|
||||
`ObjectMetadata with id ${relationMetadata.fromObjectMetadataId} not found`,
|
||||
);
|
||||
}
|
||||
|
||||
const toFieldMetadata = toObjectMetadata.fields.find(
|
||||
(field) => field.id === relationMetadata.toFieldMetadataId,
|
||||
);
|
||||
|
||||
if (!toFieldMetadata) {
|
||||
throw new Error(
|
||||
`FieldMetadata with id ${relationMetadata.toFieldMetadataId} not found`,
|
||||
);
|
||||
}
|
||||
|
||||
const migrations: WorkspaceMigrationTableAction[] = [
|
||||
{
|
||||
name: computeObjectTargetTable(toObjectMetadata),
|
||||
action: WorkspaceMigrationTableActionType.ALTER,
|
||||
columns: [
|
||||
{
|
||||
action: WorkspaceMigrationColumnActionType.CREATE_FOREIGN_KEY,
|
||||
columnName: `${camelCase(toFieldMetadata.name)}Id`,
|
||||
referencedTableName: computeObjectTargetTable(fromObjectMetadata),
|
||||
referencedTableColumnName: 'id',
|
||||
isUnique:
|
||||
relationMetadata.relationType ===
|
||||
RelationMetadataType.ONE_TO_ONE,
|
||||
onDelete: relationMetadata.onDeleteAction,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
workspaceMigrations.push({
|
||||
workspaceId: relationMetadata.workspaceId,
|
||||
name: generateMigrationName(
|
||||
`create-relation-from-${fromObjectMetadata.nameSingular}-to-${toObjectMetadata.nameSingular}`,
|
||||
),
|
||||
isCustom: false,
|
||||
migrations,
|
||||
});
|
||||
}
|
||||
|
||||
return workspaceMigrations;
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity';
|
||||
import { RelationOnDeleteAction } from 'src/engine/metadata-modules/relation-metadata/relation-on-delete-action.type';
|
||||
|
||||
export const convertOnDeleteActionToOnDelete = (
|
||||
onDeleteAction: RelationOnDeleteAction | undefined,
|
||||
|
||||
@ -61,23 +61,5 @@ export class SyncWorkspaceLoggerService {
|
||||
`${workspaceId}/field-metadata-delete-collection`,
|
||||
storage.fieldMetadataDeleteCollection,
|
||||
);
|
||||
|
||||
// Save relation metadata create collection
|
||||
await this.commandLogger.writeLog(
|
||||
`${workspaceId}/relation-metadata-create-collection`,
|
||||
storage.relationMetadataCreateCollection,
|
||||
);
|
||||
|
||||
// Save relation metadata update collection
|
||||
await this.commandLogger.writeLog(
|
||||
`${workspaceId}/relation-metadata-update-collection`,
|
||||
storage.relationMetadataUpdateCollection,
|
||||
);
|
||||
|
||||
// Save relation metadata delete collection
|
||||
await this.commandLogger.writeLog(
|
||||
`${workspaceId}/relation-metadata-delete-collection`,
|
||||
storage.relationMetadataDeleteCollection,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,86 +0,0 @@
|
||||
import { ComparatorAction } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/comparator.interface';
|
||||
|
||||
import { WorkspaceRelationComparator } from 'src/engine/workspace-manager/workspace-sync-metadata/comparators/workspace-relation.comparator';
|
||||
|
||||
describe('WorkspaceRelationComparator', () => {
|
||||
let comparator: WorkspaceRelationComparator;
|
||||
|
||||
beforeEach(() => {
|
||||
comparator = new WorkspaceRelationComparator();
|
||||
});
|
||||
|
||||
function createMockRelationMetadata(values: any) {
|
||||
return {
|
||||
fromObjectMetadataId: 'object-1',
|
||||
fromFieldMetadataId: 'field-1',
|
||||
...values,
|
||||
};
|
||||
}
|
||||
|
||||
it('should generate CREATE action for new relations', () => {
|
||||
// @ts-expect-error legacy noImplicitAny
|
||||
const original = [];
|
||||
const standard = [createMockRelationMetadata({})];
|
||||
|
||||
// @ts-expect-error legacy noImplicitAny
|
||||
const result = comparator.compare(original, standard);
|
||||
|
||||
expect(result).toEqual([
|
||||
{
|
||||
action: ComparatorAction.CREATE,
|
||||
object: expect.objectContaining({
|
||||
fromObjectMetadataId: 'object-1',
|
||||
fromFieldMetadataId: 'field-1',
|
||||
}),
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('should generate DELETE action for removed relations', () => {
|
||||
const original = [createMockRelationMetadata({ id: '1' })];
|
||||
// @ts-expect-error legacy noImplicitAny
|
||||
const standard = [];
|
||||
|
||||
// @ts-expect-error legacy noImplicitAny
|
||||
const result = comparator.compare(original, standard);
|
||||
|
||||
expect(result).toEqual([
|
||||
{
|
||||
action: ComparatorAction.DELETE,
|
||||
object: expect.objectContaining({ id: '1' }),
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('should generate UPDATE action for changed relations', () => {
|
||||
const original = [
|
||||
createMockRelationMetadata({ onDeleteAction: 'CASCADE' }),
|
||||
];
|
||||
const standard = [
|
||||
createMockRelationMetadata({ onDeleteAction: 'SET_NULL' }),
|
||||
];
|
||||
|
||||
const result = comparator.compare(original, standard);
|
||||
|
||||
expect(result).toEqual([
|
||||
{
|
||||
action: ComparatorAction.UPDATE,
|
||||
object: expect.objectContaining({
|
||||
fromObjectMetadataId: 'object-1',
|
||||
fromFieldMetadataId: 'field-1',
|
||||
onDeleteAction: 'SET_NULL',
|
||||
}),
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('should not generate any action for identical relations', () => {
|
||||
const relation = createMockRelationMetadata({});
|
||||
const original = [{ id: '1', ...relation }];
|
||||
const standard = [relation];
|
||||
|
||||
const result = comparator.compare(original, standard);
|
||||
|
||||
expect(result).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
@ -3,12 +3,10 @@ import { WorkspaceIndexComparator } from 'src/engine/workspace-manager/workspace
|
||||
|
||||
import { WorkspaceFieldComparator } from './workspace-field.comparator';
|
||||
import { WorkspaceObjectComparator } from './workspace-object.comparator';
|
||||
import { WorkspaceRelationComparator } from './workspace-relation.comparator';
|
||||
|
||||
export const workspaceSyncMetadataComparators = [
|
||||
WorkspaceFieldComparator,
|
||||
WorkspaceFieldRelationComparator,
|
||||
WorkspaceObjectComparator,
|
||||
WorkspaceRelationComparator,
|
||||
WorkspaceIndexComparator,
|
||||
];
|
||||
|
||||
@ -1,112 +0,0 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import diff from 'microdiff';
|
||||
|
||||
import {
|
||||
ComparatorAction,
|
||||
RelationComparatorResult,
|
||||
} from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/comparator.interface';
|
||||
|
||||
import { RelationMetadataEntity } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity';
|
||||
import { transformMetadataForComparison } from 'src/engine/workspace-manager/workspace-sync-metadata/comparators/utils/transform-metadata-for-comparison.util';
|
||||
|
||||
const relationPropertiesToIgnore = ['createdAt', 'updatedAt'];
|
||||
const relationPropertiesToUpdate = ['onDeleteAction'];
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceRelationComparator {
|
||||
constructor() {}
|
||||
|
||||
compare(
|
||||
originalRelationMetadataCollection: RelationMetadataEntity[],
|
||||
standardRelationMetadataCollection: Partial<RelationMetadataEntity>[],
|
||||
): RelationComparatorResult[] {
|
||||
const results: RelationComparatorResult[] = [];
|
||||
|
||||
// Create a map of standard relations
|
||||
const standardRelationMetadataMap = transformMetadataForComparison(
|
||||
standardRelationMetadataCollection,
|
||||
{
|
||||
keyFactory(relationMetadata) {
|
||||
return `${relationMetadata.fromObjectMetadataId}->${relationMetadata.fromFieldMetadataId}`;
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
// Create a filtered map of original relations
|
||||
// We filter out 'id' later because we need it to remove the relation from DB
|
||||
const originalRelationMetadataMap = transformMetadataForComparison(
|
||||
originalRelationMetadataCollection,
|
||||
{
|
||||
shouldIgnoreProperty: (property) =>
|
||||
relationPropertiesToIgnore.includes(property),
|
||||
keyFactory(relationMetadata) {
|
||||
return `${relationMetadata.fromObjectMetadataId}->${relationMetadata.fromFieldMetadataId}`;
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
// Compare relations
|
||||
const relationMetadataDifference = diff(
|
||||
originalRelationMetadataMap,
|
||||
standardRelationMetadataMap,
|
||||
);
|
||||
|
||||
for (const difference of relationMetadataDifference) {
|
||||
switch (difference.type) {
|
||||
case 'CREATE': {
|
||||
results.push({
|
||||
action: ComparatorAction.CREATE,
|
||||
object: difference.value,
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 'REMOVE': {
|
||||
if (difference.path[difference.path.length - 1] !== 'id') {
|
||||
results.push({
|
||||
action: ComparatorAction.DELETE,
|
||||
object: difference.oldValue,
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'CHANGE': {
|
||||
const fieldName = difference.path[0];
|
||||
const property = difference.path[difference.path.length - 1];
|
||||
|
||||
if (!relationPropertiesToUpdate.includes(property as string)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const originalRelationMetadata =
|
||||
originalRelationMetadataMap[fieldName];
|
||||
|
||||
if (!originalRelationMetadata) {
|
||||
throw new Error(
|
||||
`Relation ${fieldName} not found in originalRelationMetadataMap`,
|
||||
);
|
||||
}
|
||||
|
||||
results.push({
|
||||
action: ComparatorAction.UPDATE,
|
||||
object: {
|
||||
id: originalRelationMetadata.id,
|
||||
fromObjectMetadataId:
|
||||
originalRelationMetadata.fromObjectMetadataId,
|
||||
fromFieldMetadataId: originalRelationMetadata.fromFieldMetadataId,
|
||||
toObjectMetadataId: originalRelationMetadata.toObjectMetadataId,
|
||||
toFieldMetadataId: originalRelationMetadata.toFieldMetadataId,
|
||||
workspaceId: originalRelationMetadata.workspaceId,
|
||||
...{
|
||||
[property]: difference.value,
|
||||
},
|
||||
},
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
}
|
||||
@ -3,12 +3,10 @@ import { StandardIndexFactory } from 'src/engine/workspace-manager/workspace-syn
|
||||
import { StandardFieldRelationFactory } from './standard-field-relation.factory';
|
||||
import { StandardFieldFactory } from './standard-field.factory';
|
||||
import { StandardObjectFactory } from './standard-object.factory';
|
||||
import { StandardRelationFactory } from './standard-relation.factory';
|
||||
|
||||
export const workspaceSyncMetadataFactories = [
|
||||
StandardFieldFactory,
|
||||
StandardObjectFactory,
|
||||
StandardRelationFactory,
|
||||
StandardFieldRelationFactory,
|
||||
StandardIndexFactory,
|
||||
];
|
||||
|
||||
@ -2,7 +2,6 @@ import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
import { WorkspaceDynamicRelationMetadataArgs } from 'src/engine/twenty-orm/interfaces/workspace-dynamic-relation-metadata-args.interface';
|
||||
import { WorkspaceEntityMetadataArgs } from 'src/engine/twenty-orm/interfaces/workspace-entity-metadata-args.interface';
|
||||
import { WorkspaceFieldMetadataArgs } from 'src/engine/twenty-orm/interfaces/workspace-field-metadata-args.interface';
|
||||
@ -190,7 +189,7 @@ export class StandardFieldFactory {
|
||||
workspaceEntityMetadataArgs?.isSystem ||
|
||||
workspaceRelationMetadataArgs.isSystem,
|
||||
isNullable: true,
|
||||
isUnique: workspaceRelationMetadataArgs.type === RelationType.ONE_TO_ONE,
|
||||
isUnique: false,
|
||||
isActive: workspaceRelationMetadataArgs.isActive ?? true,
|
||||
});
|
||||
|
||||
|
||||
@ -1,170 +0,0 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
import { WorkspaceSyncContext } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/workspace-sync-context.interface';
|
||||
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import {
|
||||
RelationMetadataEntity,
|
||||
RelationMetadataType,
|
||||
} from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity';
|
||||
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
|
||||
import { metadataArgsStorage } from 'src/engine/twenty-orm/storage/metadata-args.storage';
|
||||
import { convertClassNameToObjectMetadataName } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/convert-class-to-object-metadata-name.util';
|
||||
import { isGatedAndNotEnabled } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/is-gate-and-not-enabled.util';
|
||||
import { assert } from 'src/utils/assert';
|
||||
|
||||
interface CustomRelationFactory {
|
||||
object: ObjectMetadataEntity;
|
||||
metadata: typeof BaseWorkspaceEntity;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class StandardRelationFactory {
|
||||
create(
|
||||
customObjectFactories: CustomRelationFactory[],
|
||||
context: WorkspaceSyncContext,
|
||||
originalObjectMetadataMap: Record<string, ObjectMetadataEntity>,
|
||||
): Partial<RelationMetadataEntity>[];
|
||||
|
||||
create(
|
||||
standardObjectMetadataDefinitions: (typeof BaseWorkspaceEntity)[],
|
||||
context: WorkspaceSyncContext,
|
||||
originalObjectMetadataMap: Record<string, ObjectMetadataEntity>,
|
||||
): Partial<RelationMetadataEntity>[];
|
||||
|
||||
create(
|
||||
standardObjectMetadataDefinitionsOrCustomObjectFactories:
|
||||
| (typeof BaseWorkspaceEntity)[]
|
||||
| {
|
||||
object: ObjectMetadataEntity;
|
||||
metadata: typeof BaseWorkspaceEntity;
|
||||
}[],
|
||||
context: WorkspaceSyncContext,
|
||||
originalObjectMetadataMap: Record<string, ObjectMetadataEntity>,
|
||||
): Partial<RelationMetadataEntity>[] {
|
||||
return standardObjectMetadataDefinitionsOrCustomObjectFactories.flatMap(
|
||||
(
|
||||
standardObjectMetadata:
|
||||
| typeof BaseWorkspaceEntity
|
||||
| CustomRelationFactory,
|
||||
) =>
|
||||
this.createRelationMetadata(
|
||||
standardObjectMetadata,
|
||||
context,
|
||||
originalObjectMetadataMap,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
private createRelationMetadata(
|
||||
workspaceEntityOrCustomRelationFactory:
|
||||
| typeof BaseWorkspaceEntity
|
||||
| CustomRelationFactory,
|
||||
context: WorkspaceSyncContext,
|
||||
originalObjectMetadataMap: Record<string, ObjectMetadataEntity>,
|
||||
): Partial<RelationMetadataEntity>[] {
|
||||
const target =
|
||||
'metadata' in workspaceEntityOrCustomRelationFactory
|
||||
? workspaceEntityOrCustomRelationFactory.metadata
|
||||
: workspaceEntityOrCustomRelationFactory;
|
||||
const workspaceEntity =
|
||||
'metadata' in workspaceEntityOrCustomRelationFactory
|
||||
? metadataArgsStorage.filterExtendedEntities(target)
|
||||
: metadataArgsStorage.filterEntities(target);
|
||||
const workspaceRelationMetadataArgsCollection =
|
||||
metadataArgsStorage.filterRelations(target);
|
||||
|
||||
if (!workspaceEntity) {
|
||||
throw new Error(
|
||||
`Object metadata decorator not found, can't parse ${target.name}`,
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
!workspaceRelationMetadataArgsCollection ||
|
||||
isGatedAndNotEnabled(workspaceEntity?.gate, context.featureFlags)
|
||||
) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return workspaceRelationMetadataArgsCollection
|
||||
.filter((workspaceRelationMetadataArgs) => {
|
||||
// We're not storing many-to-one relations in the DB for the moment
|
||||
if (workspaceRelationMetadataArgs.type === RelationType.MANY_TO_ONE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !isGatedAndNotEnabled(
|
||||
workspaceRelationMetadataArgs.gate,
|
||||
context.featureFlags,
|
||||
);
|
||||
})
|
||||
.map((workspaceRelationMetadataArgs) => {
|
||||
// Compute reflect relation metadata
|
||||
const fromObjectNameSingular =
|
||||
'object' in workspaceEntityOrCustomRelationFactory
|
||||
? workspaceEntityOrCustomRelationFactory.object.nameSingular
|
||||
: convertClassNameToObjectMetadataName(
|
||||
workspaceRelationMetadataArgs.target.name,
|
||||
);
|
||||
const toObjectNameSingular = convertClassNameToObjectMetadataName(
|
||||
workspaceRelationMetadataArgs.inverseSideTarget().name,
|
||||
);
|
||||
const fromFieldMetadataName = workspaceRelationMetadataArgs.name;
|
||||
const toFieldMetadataName =
|
||||
(workspaceRelationMetadataArgs.inverseSideFieldKey as
|
||||
| string
|
||||
| undefined) ?? fromObjectNameSingular;
|
||||
const fromObjectMetadata =
|
||||
originalObjectMetadataMap[fromObjectNameSingular];
|
||||
|
||||
assert(
|
||||
fromObjectMetadata,
|
||||
`Object ${fromObjectNameSingular} not found in DB
|
||||
for relation FROM defined in class ${fromObjectNameSingular}`,
|
||||
);
|
||||
|
||||
const toObjectMetadata =
|
||||
originalObjectMetadataMap[toObjectNameSingular];
|
||||
|
||||
assert(
|
||||
toObjectMetadata,
|
||||
`Object ${toObjectNameSingular} not found in DB
|
||||
for relation TO defined in class ${fromObjectNameSingular}`,
|
||||
);
|
||||
|
||||
const fromFieldMetadata = fromObjectMetadata?.fields.find(
|
||||
(field) => field.name === fromFieldMetadataName,
|
||||
);
|
||||
|
||||
assert(
|
||||
fromFieldMetadata,
|
||||
`Field ${fromFieldMetadataName} not found in object ${fromObjectNameSingular}
|
||||
for relation FROM defined in class ${fromObjectNameSingular}`,
|
||||
);
|
||||
|
||||
const toFieldMetadata = toObjectMetadata?.fields.find(
|
||||
(field) => field.name === toFieldMetadataName,
|
||||
);
|
||||
|
||||
assert(
|
||||
toFieldMetadata,
|
||||
`Field ${toFieldMetadataName} not found in object ${toObjectNameSingular}
|
||||
for relation TO defined in class ${fromObjectNameSingular}`,
|
||||
);
|
||||
|
||||
return {
|
||||
// TODO: Will be removed when we drop RelationMetadata
|
||||
relationType:
|
||||
workspaceRelationMetadataArgs.type as unknown as RelationMetadataType,
|
||||
fromObjectMetadataId: fromObjectMetadata?.id,
|
||||
toObjectMetadataId: toObjectMetadata?.id,
|
||||
fromFieldMetadataId: fromFieldMetadata?.id,
|
||||
toFieldMetadataId: toFieldMetadata?.id,
|
||||
workspaceId: context.workspaceId,
|
||||
onDeleteAction: workspaceRelationMetadataArgs.onDelete,
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -2,7 +2,6 @@ import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { IndexMetadataEntity } from 'src/engine/metadata-modules/index-metadata/index-metadata.entity';
|
||||
import { RelationMetadataEntity } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity';
|
||||
|
||||
import { ComputedPartialFieldMetadata } from './partial-field-metadata.interface';
|
||||
import { ComputedPartialWorkspaceEntity } from './partial-object-metadata.interface';
|
||||
@ -68,11 +67,6 @@ export type FieldRelationComparatorResult =
|
||||
>
|
||||
| ComparatorDeleteResult<FieldMetadataEntity<FieldMetadataType.RELATION>>;
|
||||
|
||||
export type RelationComparatorResult =
|
||||
| ComparatorCreateResult<Partial<RelationMetadataEntity>>
|
||||
| ComparatorDeleteResult<RelationMetadataEntity>
|
||||
| ComparatorUpdateResult<Partial<RelationMetadataEntity>>;
|
||||
|
||||
export type IndexComparatorResult =
|
||||
| ComparatorCreateResult<Partial<IndexMetadataEntity>>
|
||||
| ComparatorUpdateResult<Partial<IndexMetadataEntity>>
|
||||
|
||||
@ -7,7 +7,7 @@ import {
|
||||
|
||||
export type PartialWorkspaceEntity = Omit<
|
||||
ObjectMetadataInterface,
|
||||
'id' | 'standardId' | 'fromRelations' | 'toRelations' | 'fields' | 'isActive'
|
||||
'id' | 'standardId' | 'fields' | 'isActive'
|
||||
> & {
|
||||
standardId: string;
|
||||
icon?: string;
|
||||
|
||||
@ -25,7 +25,6 @@ import { isCompositeFieldMetadataType } from 'src/engine/metadata-modules/field-
|
||||
import { IndexFieldMetadataEntity } from 'src/engine/metadata-modules/index-metadata/index-field-metadata.entity';
|
||||
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 { RelationMetadataEntity } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity';
|
||||
import { CompositeFieldMetadataType } from 'src/engine/metadata-modules/workspace-migration/factories/composite-column-action.factory';
|
||||
import { isFieldMetadataEntityOfType } from 'src/engine/utils/is-field-metadata-of-type.util';
|
||||
import { FieldMetadataUpdate } from 'src/engine/workspace-manager/workspace-migration-builder/factories/workspace-migration-field.factory';
|
||||
@ -300,66 +299,6 @@ export class WorkspaceMetadataUpdaterService {
|
||||
}
|
||||
}
|
||||
|
||||
async updateRelationMetadata(
|
||||
manager: EntityManager,
|
||||
storage: WorkspaceSyncStorage,
|
||||
): Promise<{
|
||||
createdRelationMetadataCollection: RelationMetadataEntity[];
|
||||
updatedRelationMetadataCollection: RelationMetadataEntity[];
|
||||
}> {
|
||||
const relationMetadataRepository = manager.getRepository(
|
||||
RelationMetadataEntity,
|
||||
);
|
||||
const fieldMetadataRepository = manager.getRepository(FieldMetadataEntity);
|
||||
|
||||
/**
|
||||
* Create relation metadata
|
||||
*/
|
||||
const createdRelationMetadataCollection =
|
||||
await relationMetadataRepository.save(
|
||||
storage.relationMetadataCreateCollection,
|
||||
);
|
||||
|
||||
/**
|
||||
* Update relation metadata
|
||||
*/
|
||||
|
||||
const updatedRelationMetadataCollection =
|
||||
await relationMetadataRepository.save(
|
||||
storage.relationMetadataUpdateCollection,
|
||||
);
|
||||
|
||||
/**
|
||||
* Delete relation metadata
|
||||
*/
|
||||
if (storage.relationMetadataDeleteCollection.length > 0) {
|
||||
await relationMetadataRepository.delete(
|
||||
storage.relationMetadataDeleteCollection.map(
|
||||
(relationMetadata) => relationMetadata.id,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete related field metadata
|
||||
*/
|
||||
const fieldMetadataDeleteCollectionOnlyRelation =
|
||||
storage.fieldMetadataDeleteCollection.filter(
|
||||
(field) => field.type === FieldMetadataType.RELATION,
|
||||
);
|
||||
|
||||
if (fieldMetadataDeleteCollectionOnlyRelation.length > 0) {
|
||||
await fieldMetadataRepository.delete(
|
||||
fieldMetadataDeleteCollectionOnlyRelation.map((field) => field.id),
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
createdRelationMetadataCollection,
|
||||
updatedRelationMetadataCollection,
|
||||
};
|
||||
}
|
||||
|
||||
async updateIndexMetadata(
|
||||
manager: EntityManager,
|
||||
storage: WorkspaceSyncStorage,
|
||||
|
||||
@ -7,7 +7,6 @@ import { ComparatorAction } from 'src/engine/workspace-manager/workspace-sync-me
|
||||
import { WorkspaceSyncContext } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/workspace-sync-context.interface';
|
||||
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { RelationMetadataEntity } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity';
|
||||
import { WorkspaceMigrationEntity } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.entity';
|
||||
import { WorkspaceMigrationObjectFactory } from 'src/engine/workspace-manager/workspace-migration-builder/factories/workspace-migration-object.factory';
|
||||
import { WorkspaceObjectComparator } from 'src/engine/workspace-manager/workspace-sync-metadata/comparators/workspace-object.comparator';
|
||||
@ -36,10 +35,6 @@ export class WorkspaceSyncObjectMetadataService {
|
||||
const objectMetadataRepository =
|
||||
manager.getRepository(ObjectMetadataEntity);
|
||||
|
||||
const relationMetadataRepository = manager.getRepository(
|
||||
RelationMetadataEntity,
|
||||
);
|
||||
|
||||
// Retrieve object metadata collection from DB
|
||||
const originalObjectMetadataCollection =
|
||||
await objectMetadataRepository.find({
|
||||
@ -50,33 +45,6 @@ export class WorkspaceSyncObjectMetadataService {
|
||||
relations: ['dataSource', 'fields'],
|
||||
});
|
||||
|
||||
// Retrieve relation metadata collection from DB
|
||||
const originalRelationMetadataCollection =
|
||||
await relationMetadataRepository.find({
|
||||
where: {
|
||||
workspaceId: context.workspaceId,
|
||||
},
|
||||
relations: ['toObjectMetadata', 'toFieldMetadata'],
|
||||
});
|
||||
|
||||
const relationMetadataByFromObjectMetadataId: Record<
|
||||
string,
|
||||
RelationMetadataEntity[]
|
||||
> = originalRelationMetadataCollection.reduce(
|
||||
(acc, relationMetadata) => {
|
||||
const fromObjectMetadataId = relationMetadata.fromObjectMetadataId;
|
||||
|
||||
if (!acc[fromObjectMetadataId]) {
|
||||
acc[fromObjectMetadataId] = [];
|
||||
}
|
||||
|
||||
acc[fromObjectMetadataId].push(relationMetadata);
|
||||
|
||||
return acc;
|
||||
},
|
||||
{} as Record<string, RelationMetadataEntity[]>,
|
||||
);
|
||||
|
||||
// Create standard object metadata collection
|
||||
const standardObjectMetadataCollection = this.standardObjectFactory.create(
|
||||
standardObjectMetadataDefinitions,
|
||||
@ -158,7 +126,6 @@ export class WorkspaceSyncObjectMetadataService {
|
||||
await this.workspaceMigrationObjectFactory.create(
|
||||
storage.objectMetadataDeleteCollection,
|
||||
WorkspaceMigrationBuilderAction.DELETE,
|
||||
relationMetadataByFromObjectMetadataId,
|
||||
);
|
||||
|
||||
this.logger.log('Saving migrations');
|
||||
|
||||
@ -1,133 +0,0 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { EntityManager } from 'typeorm';
|
||||
|
||||
import { WorkspaceMigrationBuilderAction } from 'src/engine/workspace-manager/workspace-migration-builder/interfaces/workspace-migration-builder-action.interface';
|
||||
import { ComparatorAction } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/comparator.interface';
|
||||
import { WorkspaceSyncContext } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/workspace-sync-context.interface';
|
||||
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { RelationMetadataEntity } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity';
|
||||
import { WorkspaceMigrationEntity } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.entity';
|
||||
import { CustomWorkspaceEntity } from 'src/engine/twenty-orm/custom.workspace-entity';
|
||||
import { WorkspaceMigrationRelationFactory } from 'src/engine/workspace-manager/workspace-migration-builder/factories/workspace-migration-relation.factory';
|
||||
import { WorkspaceRelationComparator } from 'src/engine/workspace-manager/workspace-sync-metadata/comparators/workspace-relation.comparator';
|
||||
import { StandardRelationFactory } from 'src/engine/workspace-manager/workspace-sync-metadata/factories/standard-relation.factory';
|
||||
import { WorkspaceMetadataUpdaterService } from 'src/engine/workspace-manager/workspace-sync-metadata/services/workspace-metadata-updater.service';
|
||||
import { standardObjectMetadataDefinitions } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-objects';
|
||||
import { WorkspaceSyncStorage } from 'src/engine/workspace-manager/workspace-sync-metadata/storage/workspace-sync.storage';
|
||||
import { mapObjectMetadataByUniqueIdentifier } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/sync-metadata.util';
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceSyncRelationMetadataService {
|
||||
constructor(
|
||||
private readonly standardRelationFactory: StandardRelationFactory,
|
||||
private readonly workspaceRelationComparator: WorkspaceRelationComparator,
|
||||
private readonly workspaceMetadataUpdaterService: WorkspaceMetadataUpdaterService,
|
||||
private readonly workspaceMigrationRelationFactory: WorkspaceMigrationRelationFactory,
|
||||
) {}
|
||||
|
||||
async synchronize(
|
||||
context: WorkspaceSyncContext,
|
||||
manager: EntityManager,
|
||||
storage: WorkspaceSyncStorage,
|
||||
): Promise<Partial<WorkspaceMigrationEntity>[]> {
|
||||
const objectMetadataRepository =
|
||||
manager.getRepository(ObjectMetadataEntity);
|
||||
|
||||
// Retrieve object metadata collection from DB
|
||||
const originalObjectMetadataCollection =
|
||||
await objectMetadataRepository.find({
|
||||
where: {
|
||||
workspaceId: context.workspaceId,
|
||||
},
|
||||
relations: ['dataSource', 'fields'],
|
||||
});
|
||||
const customObjectMetadataCollection =
|
||||
originalObjectMetadataCollection.filter(
|
||||
(objectMetadata) => objectMetadata.isCustom,
|
||||
);
|
||||
|
||||
// Create map of object metadata & field metadata by unique identifier
|
||||
const originalObjectMetadataMap = mapObjectMetadataByUniqueIdentifier(
|
||||
originalObjectMetadataCollection,
|
||||
// Relation are based on the singular name
|
||||
(objectMetadata) => objectMetadata.nameSingular,
|
||||
);
|
||||
|
||||
const relationMetadataRepository = manager.getRepository(
|
||||
RelationMetadataEntity,
|
||||
);
|
||||
|
||||
// Retrieve relation metadata collection from DB
|
||||
const originalRelationMetadataCollection =
|
||||
await relationMetadataRepository.find({
|
||||
where: {
|
||||
workspaceId: context.workspaceId,
|
||||
fromFieldMetadata: { isCustom: false },
|
||||
},
|
||||
});
|
||||
|
||||
// Create standard relation metadata collection
|
||||
const standardRelationMetadataCollection =
|
||||
this.standardRelationFactory.create(
|
||||
standardObjectMetadataDefinitions,
|
||||
context,
|
||||
originalObjectMetadataMap,
|
||||
);
|
||||
|
||||
const customRelationMetadataCollection =
|
||||
this.standardRelationFactory.create(
|
||||
customObjectMetadataCollection.map((objectMetadata) => ({
|
||||
object: objectMetadata,
|
||||
metadata: CustomWorkspaceEntity,
|
||||
})),
|
||||
context,
|
||||
originalObjectMetadataMap,
|
||||
);
|
||||
|
||||
const relationComparatorResults = this.workspaceRelationComparator.compare(
|
||||
originalRelationMetadataCollection,
|
||||
[
|
||||
...standardRelationMetadataCollection,
|
||||
...customRelationMetadataCollection,
|
||||
],
|
||||
);
|
||||
|
||||
for (const relationComparatorResult of relationComparatorResults) {
|
||||
if (relationComparatorResult.action === ComparatorAction.CREATE) {
|
||||
storage.addCreateRelationMetadata(relationComparatorResult.object);
|
||||
} else if (relationComparatorResult.action === ComparatorAction.UPDATE) {
|
||||
storage.addUpdateRelationMetadata(relationComparatorResult.object);
|
||||
} else if (relationComparatorResult.action === ComparatorAction.DELETE) {
|
||||
storage.addDeleteRelationMetadata(relationComparatorResult.object);
|
||||
}
|
||||
}
|
||||
|
||||
const metadataRelationUpdaterResult =
|
||||
await this.workspaceMetadataUpdaterService.updateRelationMetadata(
|
||||
manager,
|
||||
storage,
|
||||
);
|
||||
|
||||
// Create migrations
|
||||
const createRelationWorkspaceMigrations =
|
||||
await this.workspaceMigrationRelationFactory.create(
|
||||
originalObjectMetadataCollection,
|
||||
metadataRelationUpdaterResult.createdRelationMetadataCollection,
|
||||
WorkspaceMigrationBuilderAction.CREATE,
|
||||
);
|
||||
|
||||
const updateRelationWorkspaceMigrations =
|
||||
await this.workspaceMigrationRelationFactory.create(
|
||||
originalObjectMetadataCollection,
|
||||
metadataRelationUpdaterResult.updatedRelationMetadataCollection,
|
||||
WorkspaceMigrationBuilderAction.UPDATE,
|
||||
);
|
||||
|
||||
return [
|
||||
...createRelationWorkspaceMigrations,
|
||||
...updateRelationWorkspaceMigrations,
|
||||
];
|
||||
}
|
||||
}
|
||||
@ -6,7 +6,6 @@ import { ComputedPartialWorkspaceEntity } from 'src/engine/workspace-manager/wor
|
||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
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 { RelationMetadataEntity } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity';
|
||||
|
||||
export class WorkspaceSyncStorage {
|
||||
// Object metadata
|
||||
@ -43,14 +42,6 @@ export class WorkspaceSyncStorage {
|
||||
private readonly _fieldRelationMetadataDeleteCollection: FieldMetadataEntity<FieldMetadataType.RELATION>[] =
|
||||
[];
|
||||
|
||||
// Relation metadata
|
||||
private readonly _relationMetadataCreateCollection: Partial<RelationMetadataEntity>[] =
|
||||
[];
|
||||
private readonly _relationMetadataUpdateCollection: Partial<RelationMetadataEntity>[] =
|
||||
[];
|
||||
private readonly _relationMetadataDeleteCollection: RelationMetadataEntity[] =
|
||||
[];
|
||||
|
||||
// Index metadata
|
||||
private readonly _indexMetadataCreateCollection: Partial<IndexMetadataEntity>[] =
|
||||
[];
|
||||
@ -96,18 +87,6 @@ export class WorkspaceSyncStorage {
|
||||
return this._fieldRelationMetadataDeleteCollection;
|
||||
}
|
||||
|
||||
get relationMetadataCreateCollection() {
|
||||
return this._relationMetadataCreateCollection;
|
||||
}
|
||||
|
||||
get relationMetadataUpdateCollection() {
|
||||
return this._relationMetadataUpdateCollection;
|
||||
}
|
||||
|
||||
get relationMetadataDeleteCollection() {
|
||||
return this._relationMetadataDeleteCollection;
|
||||
}
|
||||
|
||||
get indexMetadataCreateCollection() {
|
||||
return this._indexMetadataCreateCollection;
|
||||
}
|
||||
@ -168,18 +147,6 @@ export class WorkspaceSyncStorage {
|
||||
this._fieldRelationMetadataDeleteCollection.push(field);
|
||||
}
|
||||
|
||||
addCreateRelationMetadata(relation: Partial<RelationMetadataEntity>) {
|
||||
this._relationMetadataCreateCollection.push(relation);
|
||||
}
|
||||
|
||||
addUpdateRelationMetadata(relation: Partial<RelationMetadataEntity>) {
|
||||
this._relationMetadataUpdateCollection.push(relation);
|
||||
}
|
||||
|
||||
addDeleteRelationMetadata(relation: RelationMetadataEntity) {
|
||||
this._relationMetadataDeleteCollection.push(relation);
|
||||
}
|
||||
|
||||
addCreateIndexMetadata(index: Partial<IndexMetadataEntity>) {
|
||||
this._indexMetadataCreateCollection.push(index);
|
||||
}
|
||||
|
||||
@ -7,7 +7,6 @@ import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module';
|
||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { RelationMetadataEntity } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity';
|
||||
import { WorkspaceMetadataVersionModule } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module';
|
||||
import { WorkspaceMigrationEntity } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.entity';
|
||||
import { WorkspaceMigrationBuilderModule } from 'src/engine/workspace-manager/workspace-migration-builder/workspace-migration-builder.module';
|
||||
@ -22,7 +21,6 @@ import { WorkspaceSyncFieldMetadataService } from 'src/engine/workspace-manager/
|
||||
import { WorkspaceSyncIndexMetadataService } from 'src/engine/workspace-manager/workspace-sync-metadata/services/workspace-sync-index-metadata.service';
|
||||
import { WorkspaceSyncObjectMetadataIdentifiersService } from 'src/engine/workspace-manager/workspace-sync-metadata/services/workspace-sync-object-metadata-identifiers.service';
|
||||
import { WorkspaceSyncObjectMetadataService } from 'src/engine/workspace-manager/workspace-sync-metadata/services/workspace-sync-object-metadata.service';
|
||||
import { WorkspaceSyncRelationMetadataService } from 'src/engine/workspace-manager/workspace-sync-metadata/services/workspace-sync-relation-metadata.service';
|
||||
import { WorkspaceSyncMetadataService } from 'src/engine/workspace-manager/workspace-sync-metadata/workspace-sync-metadata.service';
|
||||
|
||||
@Module({
|
||||
@ -31,13 +29,8 @@ import { WorkspaceSyncMetadataService } from 'src/engine/workspace-manager/works
|
||||
WorkspaceMigrationBuilderModule,
|
||||
WorkspaceMigrationRunnerModule,
|
||||
TypeOrmModule.forFeature(
|
||||
[
|
||||
FieldMetadataEntity,
|
||||
ObjectMetadataEntity,
|
||||
RelationMetadataEntity,
|
||||
WorkspaceMigrationEntity,
|
||||
],
|
||||
'metadata',
|
||||
[FieldMetadataEntity, ObjectMetadataEntity, WorkspaceMigrationEntity],
|
||||
'core',
|
||||
),
|
||||
DataSourceModule,
|
||||
TypeOrmModule.forFeature([Workspace, FeatureFlag], 'core'),
|
||||
@ -49,7 +42,6 @@ import { WorkspaceSyncMetadataService } from 'src/engine/workspace-manager/works
|
||||
WorkspaceMetadataUpdaterService,
|
||||
WorkspaceSyncObjectMetadataService,
|
||||
WorkspaceSyncObjectMetadataIdentifiersService,
|
||||
WorkspaceSyncRelationMetadataService,
|
||||
WorkspaceSyncFieldMetadataService,
|
||||
WorkspaceSyncFieldMetadataRelationService,
|
||||
WorkspaceSyncMetadataService,
|
||||
|
||||
@ -17,7 +17,6 @@ import { WorkspaceSyncFieldMetadataService } from 'src/engine/workspace-manager/
|
||||
import { WorkspaceSyncIndexMetadataService } from 'src/engine/workspace-manager/workspace-sync-metadata/services/workspace-sync-index-metadata.service';
|
||||
import { WorkspaceSyncObjectMetadataIdentifiersService } from 'src/engine/workspace-manager/workspace-sync-metadata/services/workspace-sync-object-metadata-identifiers.service';
|
||||
import { WorkspaceSyncObjectMetadataService } from 'src/engine/workspace-manager/workspace-sync-metadata/services/workspace-sync-object-metadata.service';
|
||||
import { WorkspaceSyncRelationMetadataService } from 'src/engine/workspace-manager/workspace-sync-metadata/services/workspace-sync-relation-metadata.service';
|
||||
import { WorkspaceSyncStorage } from 'src/engine/workspace-manager/workspace-sync-metadata/storage/workspace-sync.storage';
|
||||
|
||||
interface SynchronizeOptions {
|
||||
@ -29,11 +28,10 @@ export class WorkspaceSyncMetadataService {
|
||||
private readonly logger = new Logger(WorkspaceSyncMetadataService.name);
|
||||
|
||||
constructor(
|
||||
@InjectDataSource('metadata')
|
||||
private readonly metadataDataSource: DataSource,
|
||||
@InjectDataSource('core')
|
||||
private readonly coreDataSource: DataSource,
|
||||
private readonly workspaceMigrationRunnerService: WorkspaceMigrationRunnerService,
|
||||
private readonly workspaceSyncObjectMetadataService: WorkspaceSyncObjectMetadataService,
|
||||
private readonly workspaceSyncRelationMetadataService: WorkspaceSyncRelationMetadataService,
|
||||
private readonly workspaceSyncFieldMetadataService: WorkspaceSyncFieldMetadataService,
|
||||
private readonly workspaceSyncFieldMetadataRelationService: WorkspaceSyncFieldMetadataRelationService,
|
||||
private readonly workspaceSyncIndexMetadataService: WorkspaceSyncIndexMetadataService,
|
||||
@ -59,7 +57,7 @@ export class WorkspaceSyncMetadataService {
|
||||
}> {
|
||||
let workspaceMigrations: WorkspaceMigrationEntity[] = [];
|
||||
const storage = new WorkspaceSyncStorage();
|
||||
const queryRunner = this.metadataDataSource.createQueryRunner();
|
||||
const queryRunner = this.coreDataSource.createQueryRunner();
|
||||
|
||||
this.logger.log('Syncing standard objects and fields metadata');
|
||||
|
||||
|
||||
Reference in New Issue
Block a user