Metadata api create entity in workspace custom app (#15911)

# Introduction
Cleaner and fewer scope version of
https://github.com/twentyhq/twenty/pull/15745 ( removed sync-metadata
hack through, too ambitious migration and upgrade )

Please note that this PR won't have any interaction with the existing
sync-metadata
Which mean that the sync metadata does not update the standard entities
applicationId and universalIdentifier, and it won't we will deprecate it
on favor of a workspace migration aka twenty-standard app installation

## API Metadata
Any operation going through the api metadata nows automatically scope
the related entity to the workspace custom application instance. (
optionally passing an applicationId to allow current hacky implem of app
sync service )

We need to either ignore the tests or remove the cli status check from
the blocking status badges for a PR to be merged

## New workspace
Already handled in previous
https://github.com/twentyhq/twenty/pull/15625, when a workspace is
created it gets created a twenty standard and custom workspace instance

All his views and permissions will be prefilled to the its twenty
standard app instance with a specific universalIdentifier

## New universalIdentifier
At the contrary as before with standardIds, universalIdentifier are
unique for a given workspace
This means that createdAt field of both object company and opportunity
will have a unique universalIdentifier whereas they share the same
standardId

## FlatApplication
Introduced the flatApplication and cache. Will migrate existing
`MetadataName` to be `SyncableMetadataName` in a following PR

## What's next
Next we will describe a twenty standard app configuration as json that
will be used to generate a workspace migration that will be run instead
of the sync metadata, in a nutshell we aim to deprecated the sync
metadata
So we can standardize any entity to have a non nullable applicationId
and universalIdentifier

## Upgrade command
Introduced an upgrade command that will create a custom workspace
instance for any workspace that do not have one in order to align with
the new behavior when creating a new workspace
This commit is contained in:
Paul Rastoin
2025-11-23 22:35:17 +01:00
committed by GitHub
parent 4848bc03f3
commit f9ab09c404
99 changed files with 3458 additions and 730 deletions
@@ -4,6 +4,7 @@ import { InjectDataSource, InjectRepository } from '@nestjs/typeorm';
import { WorkspaceActivationStatus } from 'twenty-shared/workspace';
import { DataSource, Repository } from 'typeorm';
import { ApplicationEntity } from 'src/engine/core-modules/application/application.entity';
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { FieldPermissionService } from 'src/engine/metadata-modules/object-permission/field-permission/field-permission.service';
@@ -41,7 +42,13 @@ export class DevSeederPermissionsService {
private readonly coreDataSource: DataSource,
) {}
public async initPermissions(workspaceId: string) {
public async initPermissions({
twentyStandardApplication,
workspaceId,
}: {
workspaceId: string;
twentyStandardApplication: ApplicationEntity;
}) {
const adminRole = await this.roleRepository.findOne({
where: {
standardId: ADMIN_ROLE.standardId,
@@ -100,6 +107,7 @@ export class DevSeederPermissionsService {
const guestRole = await this.roleService.createGuestRole({
workspaceId,
applicationId: twentyStandardApplication.id,
});
await this.userRoleService.assignRoleToUserWorkspace({
@@ -135,6 +143,7 @@ export class DevSeederPermissionsService {
const memberRole = await this.roleService.createMemberRole({
workspaceId,
applicationId: twentyStandardApplication.id,
});
await this.coreDataSource
@@ -13,7 +13,6 @@ import { seedFeatureFlags } from 'src/engine/workspace-manager/dev-seeder/core/u
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 { createWorkspace } from 'src/engine/workspace-manager/dev-seeder/core/utils/seed-workspace.util';
import { computeWorkspaceCustomCreateApplicationInput } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/compute-workspace-custom-create-application-input';
import { extractVersionMajorMinorPatch } from 'src/utils/version/extract-version-major-minor-patch';
type SeedCoreSchemaArgs = {
@@ -36,14 +35,6 @@ export const seedCoreSchema = async ({
const schemaName = 'core';
const createWorkspaceStaticInput = SEEDER_CREATE_WORKSPACE_INPUT[workspaceId];
const workspaceCustomApplicationCreateInput =
computeWorkspaceCustomCreateApplicationInput({
workspace: {
id: workspaceId,
displayName: createWorkspaceStaticInput.displayName,
},
});
const version = extractVersionMajorMinorPatch(appVersion);
const queryRunner = dataSource.createQueryRunner();
@@ -51,13 +42,14 @@ export const seedCoreSchema = async ({
await queryRunner.startTransaction();
try {
const customWorkspaceApplication = await applicationService.create(
{
...workspaceCustomApplicationCreateInput,
serverlessFunctionLayerId: null,
},
queryRunner,
);
const customWorkspaceApplication =
await applicationService.createWorkspaceCustomApplication(
{
workspaceId,
workspaceDisplayName: createWorkspaceStaticInput.displayName,
},
queryRunner,
);
await createWorkspace({
queryRunner,
@@ -76,6 +68,7 @@ export const seedCoreSchema = async ({
await applicationService.createTwentyStandardApplication(
{
workspaceId,
skipCacheInvalidation: true,
},
queryRunner,
);
@@ -4,6 +4,7 @@ import { InjectDataSource } from '@nestjs/typeorm';
import { isDefined } from 'twenty-shared/utils';
import { DataSource } from 'typeorm';
import { FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
import { type DataSourceEntity } from 'src/engine/metadata-modules/data-source/data-source.entity';
import { CreateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input';
import { FieldMetadataServiceV2 } from 'src/engine/metadata-modules/field-metadata/services/field-metadata.service-v2';
@@ -85,9 +86,11 @@ export class DevSeederMetadataService {
dataSourceMetadata,
workspaceId,
featureFlags,
twentyStandardFlatApplication,
}: {
dataSourceMetadata: DataSourceEntity;
workspaceId: string;
twentyStandardFlatApplication: FlatApplication;
featureFlags?: Record<string, boolean>;
}) {
const config = this.workspaceConfigs[workspaceId];
@@ -98,6 +101,7 @@ export class DevSeederMetadataService {
);
}
// TODO get
for (const obj of config.objects) {
await this.seedCustomObject({
dataSourceId: dataSourceMetadata.id,
@@ -126,6 +130,7 @@ export class DevSeederMetadataService {
workspaceId,
dataSourceMetadata,
featureFlags,
twentyStandardFlatApplication,
});
}
@@ -181,10 +186,12 @@ export class DevSeederMetadataService {
workspaceId,
dataSourceMetadata,
featureFlags,
twentyStandardFlatApplication,
}: {
workspaceId: string;
dataSourceMetadata: DataSourceEntity;
featureFlags?: Record<string, boolean>;
twentyStandardFlatApplication: FlatApplication;
}): Promise<void> {
const createdObjectMetadata =
await this.objectMetadataServiceV2.findManyWithinWorkspace(workspaceId);
@@ -195,6 +202,7 @@ export class DevSeederMetadataService {
objectMetadataItems: createdObjectMetadata,
workspaceSchemaName: dataSourceMetadata.schema,
featureFlags,
twentyStandardFlatApplication,
});
}
@@ -5,6 +5,8 @@ import { isDefined } from 'twenty-shared/utils';
import { DataSource } from 'typeorm';
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
import { TWENTY_STANDARD_APPLICATION } from 'src/engine/core-modules/application/constants/twenty-standard-applications';
import { WorkspaceFlatApplicationMapCacheService } from 'src/engine/core-modules/application/services/workspace-flat-application-map-cache.service';
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
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';
@@ -21,7 +23,6 @@ import { seedPageLayoutWidgets } from 'src/engine/workspace-manager/dev-seeder/c
import { seedPageLayouts } from 'src/engine/workspace-manager/dev-seeder/core/utils/seed-page-layouts.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 { TWENTY_STANDARD_APPLICATION } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/twenty-standard-applications';
import { WorkspaceSyncMetadataService } from 'src/engine/workspace-manager/workspace-sync-metadata/workspace-sync-metadata.service';
@Injectable()
@@ -38,6 +39,7 @@ export class DevSeederService {
private readonly flatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
private readonly devSeederDataService: DevSeederDataService,
private readonly applicationService: ApplicationService,
private readonly workspaceFlatApplicationMapCacheService: WorkspaceFlatApplicationMapCacheService,
@InjectDataSource()
private readonly coreDataSource: DataSource,
) {}
@@ -59,6 +61,10 @@ export class DevSeederService {
workspaceId,
);
await this.workspaceFlatApplicationMapCacheService.invalidateCache({
workspaceId,
});
const dataSourceMetadata =
await this.dataSourceService.createDataSourceMetadata(
workspaceId,
@@ -80,6 +86,13 @@ export class DevSeederService {
);
}
const { twentyStandardFlatApplication } =
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
{
workspaceId,
},
);
await this.workspaceSyncMetadataService.synchronize({
workspaceId: workspaceId,
dataSourceId: dataSourceMetadata.id,
@@ -90,13 +103,17 @@ export class DevSeederService {
dataSourceMetadata,
workspaceId,
featureFlags,
twentyStandardFlatApplication,
});
await this.devSeederMetadataService.seedRelations({
workspaceId,
});
await this.devSeederPermissionsService.initPermissions(workspaceId);
await this.devSeederPermissionsService.initPermissions({
workspaceId,
twentyStandardApplication,
});
await seedPageLayouts(this.coreDataSource, 'core', workspaceId);
await seedPageLayoutTabs(this.coreDataSource, 'core', workspaceId);
@@ -1,7 +1,7 @@
import { isString } from '@sniptt/guards';
import { type DataSource, type QueryRunner } from 'typeorm';
import { v4 } from 'uuid';
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { ViewFieldEntity } from 'src/engine/metadata-modules/view-field/entities/view-field.entity';
import { ViewFilterEntity } from 'src/engine/metadata-modules/view-filter/entities/view-filter.entity';
@@ -39,6 +39,7 @@ type PrefillCoreViewsArgs = {
objectMetadataItems: ObjectMetadataEntity[];
featureFlags?: Record<string, boolean>;
workspaceSchemaName: string;
twentyStandardFlatApplication: FlatApplication;
};
export const prefillCoreViews = async ({
@@ -46,25 +47,32 @@ export const prefillCoreViews = async ({
workspaceId,
objectMetadataItems,
workspaceSchemaName,
twentyStandardFlatApplication,
}: PrefillCoreViewsArgs): Promise<ViewEntity[]> => {
const views = [
companiesAllView(objectMetadataItems, true),
peopleAllView(objectMetadataItems, true),
opportunitiesAllView(objectMetadataItems, true),
opportunitiesByStageView(objectMetadataItems, true),
notesAllView(objectMetadataItems, true),
tasksAllView(objectMetadataItems, true),
tasksAssignedToMeView(objectMetadataItems, true),
tasksByStatusView(objectMetadataItems, true),
workflowsAllView(objectMetadataItems, true),
workflowVersionsAllView(objectMetadataItems, true),
workflowRunsAllView(objectMetadataItems, true),
dashboardsAllView(objectMetadataItems, true),
workspaceMembersAllView(objectMetadataItems, true),
messagesAllView(objectMetadataItems, true),
messageThreadsAllView(objectMetadataItems, true),
calendarEventsAllView(objectMetadataItems, true),
];
companiesAllView,
peopleAllView,
opportunitiesAllView,
opportunitiesByStageView,
notesAllView,
tasksAllView,
tasksAssignedToMeView,
tasksByStatusView,
workflowsAllView,
workflowVersionsAllView,
workflowRunsAllView,
dashboardsAllView,
workspaceMembersAllView,
messagesAllView,
messageThreadsAllView,
calendarEventsAllView,
].map((seeder) =>
seeder({
objectMetadataItems,
useCoreNaming: true,
twentyStandardFlatApplication,
}),
);
const queryRunner = coreDataSource.createQueryRunner();
@@ -73,7 +81,12 @@ export const prefillCoreViews = async ({
try {
await queryRunner.startTransaction();
const createdViews = await createCoreViews(queryRunner, workspaceId, views);
const createdViews = await createCoreViews(
queryRunner,
workspaceId,
views,
twentyStandardFlatApplication,
);
await prefillWorkspaceFavorites(
createdViews
@@ -112,13 +125,9 @@ export const createCoreViews = async (
queryRunner: QueryRunner,
workspaceId: string,
viewDefinitions: ViewDefinition[],
twentyStandardFlatApplication: FlatApplication,
): Promise<ViewEntity[]> => {
const viewDefinitionsWithId = viewDefinitions.map((viewDefinition) => ({
...viewDefinition,
id: v4(),
}));
const coreViews: Partial<ViewEntity>[] = viewDefinitionsWithId.map(
const coreViews: Partial<ViewEntity>[] = viewDefinitions.map(
({
id,
name,
@@ -131,6 +140,8 @@ export const createCoreViews = async (
openRecordIn,
kanbanAggregateOperation,
kanbanAggregateOperationFieldMetadataId,
applicationId,
universalIdentifier,
}) => ({
id,
name: isString(name) ? name : name.message || '',
@@ -150,13 +161,15 @@ export const createCoreViews = async (
workspaceId,
anyFieldFilterValue: null,
visibility: ViewVisibility.WORKSPACE,
applicationId,
universalIdentifier,
}),
);
const viewRepository = queryRunner.manager.getRepository(ViewEntity);
const createdViews = await viewRepository.save(coreViews);
for (const viewDefinition of viewDefinitionsWithId) {
for (const viewDefinition of viewDefinitions) {
if (viewDefinition.fields && viewDefinition.fields.length > 0) {
const coreViewFields: Partial<ViewFieldEntity>[] =
viewDefinition.fields.map((field) => ({
@@ -166,6 +179,8 @@ export const createCoreViews = async (
size: field.size,
viewId: viewDefinition.id,
workspaceId,
applicationId: twentyStandardFlatApplication.id,
universalIdentifier: field.universalIdentifier,
}));
const viewFieldRepository =
@@ -182,6 +197,8 @@ export const createCoreViews = async (
operand: filter.operand,
value: filter.value,
workspaceId,
applicationId: twentyStandardFlatApplication.id,
universalIdentifier: filter.universalIdentifier,
}));
const viewFilterRepository =
@@ -203,6 +220,8 @@ export const createCoreViews = async (
position: group.position,
viewId: viewDefinition.id,
workspaceId,
applicationId: twentyStandardFlatApplication.id,
universalIdentifier: group.universalIdentifier,
}));
const viewGroupRepository =
@@ -11,13 +11,18 @@ export interface ViewDefinition {
type: string;
key: string | null;
position: number;
applicationId: string;
universalIdentifier: string;
icon?: string;
isCustom?: boolean;
openRecordIn?: ViewOpenRecordInType;
kanbanFieldMetadataId?: string;
kanbanAggregateOperation?: AggregateOperations;
kanbanAggregateOperationFieldMetadataId?: string;
calendarFieldMetadataId?: string;
calendarLayout?: string;
fields?: {
universalIdentifier: string;
fieldMetadataId: string;
position: number;
isVisible: boolean;
@@ -25,12 +30,14 @@ export interface ViewDefinition {
aggregateOperation?: AggregateOperations;
}[];
filters?: {
universalIdentifier: string;
fieldMetadataId: string;
displayValue: string;
operand: ViewFilterOperand;
value: string;
}[];
groups?: {
universalIdentifier: string;
fieldMetadataId: string;
isVisible: boolean;
fieldValue: string;
@@ -1,17 +1,26 @@
import { msg } from '@lingui/core/macro';
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
import { v4 } from 'uuid';
import { STANDARD_OBJECTS } from 'src/engine/core-modules/application/constants/standard-object.constant';
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface';
import { DEFAULT_VIEW_FIELD_SIZE } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/constants/DEFAULT_VIEW_FIELD_SIZE';
import {
BASE_OBJECT_STANDARD_FIELD_IDS,
CALENDAR_EVENT_STANDARD_FIELD_IDS,
} from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
export const calendarEventsAllView = (
objectMetadataItems: ObjectMetadataEntity[],
useCoreNaming = false,
) => {
export const calendarEventsAllView = ({
objectMetadataItems,
twentyStandardFlatApplication,
useCoreNaming,
}: {
objectMetadataItems: ObjectMetadataEntity[];
useCoreNaming?: boolean;
twentyStandardFlatApplication: FlatApplication;
}): ViewDefinition => {
const calendarEventObjectMetadata = objectMetadataItems.find(
(object) => object.standardId === STANDARD_OBJECT_IDS.calendarEvent,
);
@@ -20,7 +29,13 @@ export const calendarEventsAllView = (
throw new Error('CalendarEvent object metadata not found');
}
const viewUniversalIdentifier =
STANDARD_OBJECTS.calendarEvent.views.allCalendarEvents.universalIdentifier;
return {
id: v4(),
universalIdentifier: viewUniversalIdentifier,
applicationId: twentyStandardFlatApplication.id,
name: useCoreNaming ? msg`All {objectLabelPlural}` : 'All Calendar Events',
objectMetadataId: calendarEventObjectMetadata.id ?? '',
type: 'calendar',
@@ -45,6 +60,9 @@ export const calendarEventsAllView = (
position: 0,
isVisible: true,
size: DEFAULT_VIEW_FIELD_SIZE,
universalIdentifier:
STANDARD_OBJECTS.calendarEvent.views.allCalendarEvents.viewFields
.title.universalIdentifier,
},
{
fieldMetadataId:
@@ -55,6 +73,9 @@ export const calendarEventsAllView = (
position: 1,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.calendarEvent.views.allCalendarEvents.viewFields
.startsAt.universalIdentifier,
},
{
fieldMetadataId:
@@ -65,6 +86,9 @@ export const calendarEventsAllView = (
position: 2,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.calendarEvent.views.allCalendarEvents.viewFields
.endsAt.universalIdentifier,
},
{
fieldMetadataId:
@@ -75,6 +99,9 @@ export const calendarEventsAllView = (
position: 3,
isVisible: true,
size: 100,
universalIdentifier:
STANDARD_OBJECTS.calendarEvent.views.allCalendarEvents.viewFields
.isFullDay.universalIdentifier,
},
{
fieldMetadataId:
@@ -85,6 +112,9 @@ export const calendarEventsAllView = (
position: 4,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.calendarEvent.views.allCalendarEvents.viewFields
.location.universalIdentifier,
},
{
fieldMetadataId:
@@ -96,6 +126,9 @@ export const calendarEventsAllView = (
position: 5,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.calendarEvent.views.allCalendarEvents.viewFields
.conferenceLink.universalIdentifier,
},
{
fieldMetadataId:
@@ -106,6 +139,9 @@ export const calendarEventsAllView = (
position: 6,
isVisible: true,
size: 100,
universalIdentifier:
STANDARD_OBJECTS.calendarEvent.views.allCalendarEvents.viewFields
.isCanceled.universalIdentifier,
},
{
fieldMetadataId:
@@ -116,6 +152,9 @@ export const calendarEventsAllView = (
position: 7,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.calendarEvent.views.allCalendarEvents.viewFields
.createdAt.universalIdentifier,
},
],
};
@@ -1,18 +1,27 @@
import { msg } from '@lingui/core/macro';
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
import { v4 } from 'uuid';
import { AggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/aggregate-operations.constant';
import { STANDARD_OBJECTS } from 'src/engine/core-modules/application/constants/standard-object.constant';
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface';
import { DEFAULT_VIEW_FIELD_SIZE } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/constants/DEFAULT_VIEW_FIELD_SIZE';
import {
BASE_OBJECT_STANDARD_FIELD_IDS,
COMPANY_STANDARD_FIELD_IDS,
} from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
export const companiesAllView = (
objectMetadataItems: ObjectMetadataEntity[],
export const companiesAllView = ({
objectMetadataItems,
useCoreNaming = false,
) => {
twentyStandardFlatApplication,
}: {
objectMetadataItems: ObjectMetadataEntity[];
useCoreNaming?: boolean;
twentyStandardFlatApplication: FlatApplication;
}): ViewDefinition => {
const companyObjectMetadata = objectMetadataItems.find(
(object) => object.standardId === STANDARD_OBJECT_IDS.company,
);
@@ -21,7 +30,13 @@ export const companiesAllView = (
throw new Error('Company object metadata not found');
}
const viewUniversalIdentifier =
STANDARD_OBJECTS.company.views.allCompanies.universalIdentifier;
return {
id: v4(),
universalIdentifier: viewUniversalIdentifier,
applicationId: twentyStandardFlatApplication.id,
name: useCoreNaming ? msg`All {objectLabelPlural}` : 'All Companies',
objectMetadataId: companyObjectMetadata.id ?? '',
type: 'table',
@@ -39,6 +54,9 @@ export const companiesAllView = (
position: 0,
isVisible: true,
size: DEFAULT_VIEW_FIELD_SIZE,
universalIdentifier:
STANDARD_OBJECTS.company.views.allCompanies.viewFields.name
.universalIdentifier,
},
{
fieldMetadataId:
@@ -50,6 +68,9 @@ export const companiesAllView = (
isVisible: true,
size: 100,
aggregateOperation: AggregateOperations.COUNT,
universalIdentifier:
STANDARD_OBJECTS.company.views.allCompanies.viewFields.domainName
.universalIdentifier,
},
{
fieldMetadataId:
@@ -60,6 +81,9 @@ export const companiesAllView = (
position: 2,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.company.views.allCompanies.viewFields.createdBy
.universalIdentifier,
},
{
fieldMetadataId:
@@ -70,6 +94,9 @@ export const companiesAllView = (
position: 3,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.company.views.allCompanies.viewFields.accountOwner
.universalIdentifier,
},
{
fieldMetadataId:
@@ -80,6 +107,9 @@ export const companiesAllView = (
position: 4,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.company.views.allCompanies.viewFields.createdAt
.universalIdentifier,
},
{
fieldMetadataId:
@@ -91,6 +121,9 @@ export const companiesAllView = (
isVisible: true,
size: 150,
aggregateOperation: AggregateOperations.MAX,
universalIdentifier:
STANDARD_OBJECTS.company.views.allCompanies.viewFields.employees
.universalIdentifier,
},
{
fieldMetadataId:
@@ -102,6 +135,9 @@ export const companiesAllView = (
isVisible: true,
size: 170,
aggregateOperation: AggregateOperations.PERCENTAGE_EMPTY,
universalIdentifier:
STANDARD_OBJECTS.company.views.allCompanies.viewFields.linkedinLink
.universalIdentifier,
},
{
fieldMetadataId:
@@ -112,6 +148,9 @@ export const companiesAllView = (
isVisible: true,
size: 170,
aggregateOperation: AggregateOperations.COUNT_NOT_EMPTY,
universalIdentifier:
STANDARD_OBJECTS.company.views.allCompanies.viewFields.address
.universalIdentifier,
},
],
};
@@ -1,53 +0,0 @@
import { msg } from '@lingui/core/macro';
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { DEFAULT_VIEW_FIELD_SIZE } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/constants/DEFAULT_VIEW_FIELD_SIZE';
export const customAllView = (
objectMetadataItem: ObjectMetadataEntity,
useCoreNaming = false,
) => {
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: useCoreNaming
? msg`All {objectLabelPlural}`
: `All ${objectMetadataItem.labelPlural}`,
objectMetadataId: objectMetadataItem.id,
type: 'table',
key: 'INDEX',
position: 0,
icon: 'IconList',
isCustom: false,
kanbanFieldMetadataId: '',
filters: [],
fields: [
{
fieldMetadataId:
objectMetadataItem.fields.find((field) => field.name === 'name')
?.id ?? '',
position: 0,
isVisible: true,
size: DEFAULT_VIEW_FIELD_SIZE,
},
...otherFields.map((field, index) => ({
fieldMetadataId: field.id,
position: index + 1,
isVisible: true,
size: DEFAULT_VIEW_FIELD_SIZE,
})),
],
};
};
@@ -1,17 +1,26 @@
import { msg } from '@lingui/core/macro';
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
import { v4 } from 'uuid';
import { STANDARD_OBJECTS } from 'src/engine/core-modules/application/constants/standard-object.constant';
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { ViewOpenRecordInType } from 'src/engine/metadata-modules/view/types/view-open-record-in-type.type';
import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface';
import {
BASE_OBJECT_STANDARD_FIELD_IDS,
DASHBOARD_STANDARD_FIELD_IDS,
} from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
export const dashboardsAllView = (
objectMetadataItems: ObjectMetadataEntity[],
export const dashboardsAllView = ({
objectMetadataItems,
useCoreNaming = false,
) => {
twentyStandardFlatApplication,
}: {
objectMetadataItems: ObjectMetadataEntity[];
useCoreNaming?: boolean;
twentyStandardFlatApplication: FlatApplication;
}): ViewDefinition => {
const dashboardObjectMetadata = objectMetadataItems.find(
(object) => object.standardId === STANDARD_OBJECT_IDS.dashboard,
);
@@ -20,7 +29,13 @@ export const dashboardsAllView = (
throw new Error('Dashboard object metadata not found');
}
const viewUniversalIdentifier =
STANDARD_OBJECTS.dashboard.views.allDashboards.universalIdentifier;
return {
id: v4(),
universalIdentifier: viewUniversalIdentifier,
applicationId: twentyStandardFlatApplication.id,
name: useCoreNaming ? msg`All {objectLabelPlural}` : 'All Dashboards',
objectMetadataId: dashboardObjectMetadata.id ?? '',
type: 'table',
@@ -39,6 +54,9 @@ export const dashboardsAllView = (
position: 0,
isVisible: true,
size: 200,
universalIdentifier:
STANDARD_OBJECTS.dashboard.views.allDashboards.viewFields.title
.universalIdentifier,
},
{
fieldMetadataId:
@@ -49,6 +67,9 @@ export const dashboardsAllView = (
position: 1,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.dashboard.views.allDashboards.viewFields.createdBy
.universalIdentifier,
},
{
fieldMetadataId:
@@ -59,6 +80,9 @@ export const dashboardsAllView = (
position: 2,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.dashboard.views.allDashboards.viewFields.createdAt
.universalIdentifier,
},
{
fieldMetadataId:
@@ -69,6 +93,9 @@ export const dashboardsAllView = (
position: 3,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.dashboard.views.allDashboards.viewFields.updatedAt
.universalIdentifier,
},
],
};
@@ -1,17 +1,26 @@
import { msg } from '@lingui/core/macro';
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
import { v4 } from 'uuid';
import { STANDARD_OBJECTS } from 'src/engine/core-modules/application/constants/standard-object.constant';
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface';
import { DEFAULT_VIEW_FIELD_SIZE } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/constants/DEFAULT_VIEW_FIELD_SIZE';
import {
BASE_OBJECT_STANDARD_FIELD_IDS,
MESSAGE_THREAD_STANDARD_FIELD_IDS,
} from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
export const messageThreadsAllView = (
objectMetadataItems: ObjectMetadataEntity[],
useCoreNaming = false,
) => {
export const messageThreadsAllView = ({
objectMetadataItems,
twentyStandardFlatApplication,
useCoreNaming,
}: {
objectMetadataItems: ObjectMetadataEntity[];
useCoreNaming?: boolean;
twentyStandardFlatApplication: FlatApplication;
}): ViewDefinition => {
const messageThreadObjectMetadata = objectMetadataItems.find(
(object) => object.standardId === STANDARD_OBJECT_IDS.messageThread,
);
@@ -20,7 +29,13 @@ export const messageThreadsAllView = (
throw new Error('MessageThread object metadata not found');
}
const viewUniversalIdentifier =
STANDARD_OBJECTS.messageThread.views.allMessageThreads.universalIdentifier;
return {
id: v4(),
universalIdentifier: viewUniversalIdentifier,
applicationId: twentyStandardFlatApplication.id,
name: useCoreNaming ? msg`All {objectLabelPlural}` : 'All Message Threads',
objectMetadataId: messageThreadObjectMetadata.id ?? '',
type: 'table',
@@ -39,6 +54,9 @@ export const messageThreadsAllView = (
position: 0,
isVisible: true,
size: DEFAULT_VIEW_FIELD_SIZE,
universalIdentifier:
STANDARD_OBJECTS.messageThread.views.allMessageThreads.viewFields
.messages.universalIdentifier,
},
{
fieldMetadataId:
@@ -49,6 +67,9 @@ export const messageThreadsAllView = (
position: 1,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.messageThread.views.allMessageThreads.viewFields
.createdAt.universalIdentifier,
},
],
};
@@ -1,17 +1,26 @@
import { msg } from '@lingui/core/macro';
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
import { v4 } from 'uuid';
import { STANDARD_OBJECTS } from 'src/engine/core-modules/application/constants/standard-object.constant';
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface';
import { DEFAULT_VIEW_FIELD_SIZE } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/constants/DEFAULT_VIEW_FIELD_SIZE';
import {
BASE_OBJECT_STANDARD_FIELD_IDS,
MESSAGE_STANDARD_FIELD_IDS,
} from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
export const messagesAllView = (
objectMetadataItems: ObjectMetadataEntity[],
useCoreNaming = false,
) => {
export const messagesAllView = ({
objectMetadataItems,
twentyStandardFlatApplication,
useCoreNaming,
}: {
objectMetadataItems: ObjectMetadataEntity[];
useCoreNaming?: boolean;
twentyStandardFlatApplication: FlatApplication;
}): ViewDefinition => {
const messageObjectMetadata = objectMetadataItems.find(
(object) => object.standardId === STANDARD_OBJECT_IDS.message,
);
@@ -20,7 +29,13 @@ export const messagesAllView = (
throw new Error('Message object metadata not found');
}
const viewUniversalIdentifier =
STANDARD_OBJECTS.message.views.allMessages.universalIdentifier;
return {
id: v4(),
universalIdentifier: viewUniversalIdentifier,
applicationId: twentyStandardFlatApplication.id,
name: useCoreNaming ? msg`All {objectLabelPlural}` : 'All Messages',
objectMetadataId: messageObjectMetadata.id ?? '',
type: 'table',
@@ -38,6 +53,9 @@ export const messagesAllView = (
position: 0,
isVisible: true,
size: DEFAULT_VIEW_FIELD_SIZE,
universalIdentifier:
STANDARD_OBJECTS.message.views.allMessages.viewFields.subject
.universalIdentifier,
},
{
fieldMetadataId:
@@ -48,6 +66,9 @@ export const messagesAllView = (
position: 1,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.message.views.allMessages.viewFields.messageThread
.universalIdentifier,
},
{
fieldMetadataId:
@@ -59,6 +80,9 @@ export const messagesAllView = (
position: 2,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.message.views.allMessages.viewFields
.messageParticipants.universalIdentifier,
},
{
fieldMetadataId:
@@ -69,6 +93,9 @@ export const messagesAllView = (
position: 3,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.message.views.allMessages.viewFields.receivedAt
.universalIdentifier,
},
{
fieldMetadataId:
@@ -79,6 +106,9 @@ export const messagesAllView = (
position: 4,
isVisible: true,
size: 180,
universalIdentifier:
STANDARD_OBJECTS.message.views.allMessages.viewFields.headerMessageId
.universalIdentifier,
},
{
fieldMetadataId:
@@ -88,6 +118,9 @@ export const messagesAllView = (
position: 5,
isVisible: true,
size: 200,
universalIdentifier:
STANDARD_OBJECTS.message.views.allMessages.viewFields.text
.universalIdentifier,
},
{
fieldMetadataId:
@@ -98,6 +131,9 @@ export const messagesAllView = (
position: 6,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.message.views.allMessages.viewFields.createdAt
.universalIdentifier,
},
],
};
@@ -1,16 +1,25 @@
import { msg } from '@lingui/core/macro';
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
import { v4 } from 'uuid';
import { STANDARD_OBJECTS } from 'src/engine/core-modules/application/constants/standard-object.constant';
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface';
import {
BASE_OBJECT_STANDARD_FIELD_IDS,
NOTE_STANDARD_FIELD_IDS,
} from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
export const notesAllView = (
objectMetadataItems: ObjectMetadataEntity[],
export const notesAllView = ({
objectMetadataItems,
useCoreNaming = false,
) => {
twentyStandardFlatApplication,
}: {
objectMetadataItems: ObjectMetadataEntity[];
useCoreNaming?: boolean;
twentyStandardFlatApplication: FlatApplication;
}): ViewDefinition => {
const noteObjectMetadata = objectMetadataItems.find(
(object) => object.standardId === STANDARD_OBJECT_IDS.note,
);
@@ -19,7 +28,13 @@ export const notesAllView = (
throw new Error('Note object metadata not found');
}
const viewUniversalIdentifier =
STANDARD_OBJECTS.note.views.allNotes.universalIdentifier;
return {
id: v4(),
universalIdentifier: viewUniversalIdentifier,
applicationId: twentyStandardFlatApplication.id,
name: useCoreNaming ? msg`All {objectLabelPlural}` : 'All Notes',
objectMetadataId: noteObjectMetadata.id,
type: 'table',
@@ -37,6 +52,9 @@ export const notesAllView = (
position: 0,
isVisible: true,
size: 210,
universalIdentifier:
STANDARD_OBJECTS.note.views.allNotes.viewFields.title
.universalIdentifier,
},
{
fieldMetadataId:
@@ -46,6 +64,9 @@ export const notesAllView = (
position: 1,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.note.views.allNotes.viewFields.noteTargets
.universalIdentifier,
},
{
fieldMetadataId:
@@ -55,6 +76,9 @@ export const notesAllView = (
position: 2,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.note.views.allNotes.viewFields.bodyV2
.universalIdentifier,
},
{
fieldMetadataId:
@@ -64,6 +88,9 @@ export const notesAllView = (
position: 3,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.note.views.allNotes.viewFields.createdBy
.universalIdentifier,
},
{
fieldMetadataId:
@@ -74,18 +101,19 @@ export const notesAllView = (
position: 4,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.note.views.allNotes.viewFields.createdAt
.universalIdentifier,
},
/*
TODO: Add later, since we don't have real-time it probably doesn't work well?
{
fieldMetadataId:
objectMetadataMap[STANDARD_OBJECT_IDS.note].fields[
BASE_OBJECT_STANDARD_FIELD_IDS.updatedAt
objectMetadataMap[STANDARD_OBJECT_IDS.note].fields[.updatedAt
],
position: 0,
isVisible: true,
size: 210,
},
size: 210},
*/
],
};
@@ -1,14 +1,23 @@
import { msg } from '@lingui/core/macro';
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
import { v4 } from 'uuid';
import { AggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/aggregate-operations.constant';
import { STANDARD_OBJECTS } from 'src/engine/core-modules/application/constants/standard-object.constant';
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface';
import { OPPORTUNITY_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
export const opportunitiesAllView = (
objectMetadataItems: ObjectMetadataEntity[],
export const opportunitiesAllView = ({
objectMetadataItems,
useCoreNaming = false,
) => {
twentyStandardFlatApplication,
}: {
objectMetadataItems: ObjectMetadataEntity[];
useCoreNaming?: boolean;
twentyStandardFlatApplication: FlatApplication;
}): ViewDefinition => {
const opportunityObjectMetadata = objectMetadataItems.find(
(object) => object.standardId === STANDARD_OBJECT_IDS.opportunity,
);
@@ -17,7 +26,13 @@ export const opportunitiesAllView = (
throw new Error('Opportunity object metadata not found');
}
const viewUniversalIdentifier =
STANDARD_OBJECTS.opportunity.views.allOpportunities.universalIdentifier;
return {
id: v4(),
universalIdentifier: viewUniversalIdentifier,
applicationId: twentyStandardFlatApplication.id,
name: useCoreNaming ? msg`All {objectLabelPlural}` : 'All Opportunities',
objectMetadataId: opportunityObjectMetadata.id,
type: 'table',
@@ -35,6 +50,9 @@ export const opportunitiesAllView = (
position: 0,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.opportunity.views.allOpportunities.viewFields.name
.universalIdentifier,
},
{
fieldMetadataId:
@@ -46,6 +64,9 @@ export const opportunitiesAllView = (
isVisible: true,
size: 150,
aggregateOperation: AggregateOperations.AVG,
universalIdentifier:
STANDARD_OBJECTS.opportunity.views.allOpportunities.viewFields.amount
.universalIdentifier,
},
{
fieldMetadataId:
@@ -56,6 +77,9 @@ export const opportunitiesAllView = (
position: 2,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.opportunity.views.allOpportunities.viewFields
.createdBy.universalIdentifier,
},
{
fieldMetadataId:
@@ -67,6 +91,9 @@ export const opportunitiesAllView = (
isVisible: true,
size: 150,
aggregateOperation: AggregateOperations.MIN,
universalIdentifier:
STANDARD_OBJECTS.opportunity.views.allOpportunities.viewFields
.closeDate.universalIdentifier,
},
{
fieldMetadataId:
@@ -77,6 +104,9 @@ export const opportunitiesAllView = (
position: 4,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.opportunity.views.allOpportunities.viewFields.company
.universalIdentifier,
},
{
fieldMetadataId:
@@ -88,6 +118,9 @@ export const opportunitiesAllView = (
position: 5,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.opportunity.views.allOpportunities.viewFields
.pointOfContact.universalIdentifier,
},
],
};
@@ -1,14 +1,23 @@
import { msg } from '@lingui/core/macro';
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
import { v4 } from 'uuid';
import { AggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/aggregate-operations.constant';
import { STANDARD_OBJECTS } from 'src/engine/core-modules/application/constants/standard-object.constant';
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface';
import { OPPORTUNITY_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
export const opportunitiesByStageView = (
objectMetadataItems: ObjectMetadataEntity[],
export const opportunitiesByStageView = ({
objectMetadataItems,
useCoreNaming = false,
) => {
twentyStandardFlatApplication,
}: {
objectMetadataItems: ObjectMetadataEntity[];
useCoreNaming?: boolean;
twentyStandardFlatApplication: FlatApplication;
}): ViewDefinition => {
const opportunityObjectMetadata = objectMetadataItems.find(
(object) => object.standardId === STANDARD_OBJECT_IDS.opportunity,
);
@@ -17,7 +26,13 @@ export const opportunitiesByStageView = (
throw new Error('Opportunity object metadata not found');
}
const viewUniversalIdentifier =
STANDARD_OBJECTS.opportunity.views.byStage.universalIdentifier;
return {
id: v4(),
universalIdentifier: viewUniversalIdentifier,
applicationId: twentyStandardFlatApplication.id,
name: useCoreNaming ? msg`By Stage` : 'By Stage',
objectMetadataId: opportunityObjectMetadata.id,
type: 'kanban',
@@ -43,6 +58,9 @@ export const opportunitiesByStageView = (
position: 0,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.opportunity.views.byStage.viewFields.name
.universalIdentifier,
},
{
fieldMetadataId:
@@ -53,6 +71,9 @@ export const opportunitiesByStageView = (
position: 1,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.opportunity.views.byStage.viewFields.amount
.universalIdentifier,
},
{
fieldMetadataId:
@@ -63,6 +84,9 @@ export const opportunitiesByStageView = (
position: 2,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.opportunity.views.byStage.viewFields.createdBy
.universalIdentifier,
},
{
fieldMetadataId:
@@ -73,6 +97,9 @@ export const opportunitiesByStageView = (
position: 3,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.opportunity.views.byStage.viewFields.closeDate
.universalIdentifier,
},
{
fieldMetadataId:
@@ -83,6 +110,9 @@ export const opportunitiesByStageView = (
position: 4,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.opportunity.views.byStage.viewFields.company
.universalIdentifier,
},
{
fieldMetadataId:
@@ -94,6 +124,9 @@ export const opportunitiesByStageView = (
position: 5,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.opportunity.views.byStage.viewFields.pointOfContact
.universalIdentifier,
},
],
groups: [
@@ -106,6 +139,9 @@ export const opportunitiesByStageView = (
isVisible: true,
fieldValue: 'NEW',
position: 0,
universalIdentifier:
STANDARD_OBJECTS.opportunity.views.byStage.viewGroups!.new
.universalIdentifier,
},
{
fieldMetadataId:
@@ -116,6 +152,9 @@ export const opportunitiesByStageView = (
isVisible: true,
fieldValue: 'SCREENING',
position: 1,
universalIdentifier:
STANDARD_OBJECTS.opportunity.views.byStage.viewGroups!.screening
.universalIdentifier,
},
{
fieldMetadataId:
@@ -126,6 +165,9 @@ export const opportunitiesByStageView = (
isVisible: true,
fieldValue: 'MEETING',
position: 2,
universalIdentifier:
STANDARD_OBJECTS.opportunity.views.byStage.viewGroups!.meeting
.universalIdentifier,
},
{
fieldMetadataId:
@@ -136,6 +178,9 @@ export const opportunitiesByStageView = (
isVisible: true,
fieldValue: 'PROPOSAL',
position: 3,
universalIdentifier:
STANDARD_OBJECTS.opportunity.views.byStage.viewGroups!.proposal
.universalIdentifier,
},
{
fieldMetadataId:
@@ -146,6 +191,9 @@ export const opportunitiesByStageView = (
isVisible: true,
fieldValue: 'CUSTOMER',
position: 4,
universalIdentifier:
STANDARD_OBJECTS.opportunity.views.byStage.viewGroups!.customer
.universalIdentifier,
},
],
};
@@ -1,150 +0,0 @@
import { msg } from '@lingui/core/macro';
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
import { AggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/aggregate-operations.constant';
import { type 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';
export const opportunitiesTableByStageView = (
objectMetadataItems: ObjectMetadataEntity[],
useCoreNaming = false,
) => {
const opportunityObjectMetadata = objectMetadataItems.find(
(object) => object.standardId === STANDARD_OBJECT_IDS.opportunity,
);
if (!opportunityObjectMetadata) {
throw new Error('Opportunity object metadata not found');
}
return {
name: useCoreNaming ? msg`By Stage` : 'By Stage',
objectMetadataId: opportunityObjectMetadata.id,
type: 'table',
key: null,
position: 1,
icon: 'IconList',
kanbanFieldMetadataId:
opportunityObjectMetadata.fields.find(
(field) => field.standardId === OPPORTUNITY_STANDARD_FIELD_IDS.stage,
)?.id ?? '',
filters: [],
fields: [
{
fieldMetadataId:
opportunityObjectMetadata.fields.find(
(field) => field.standardId === OPPORTUNITY_STANDARD_FIELD_IDS.name,
)?.id ?? '',
position: 0,
isVisible: true,
size: 150,
},
{
fieldMetadataId:
opportunityObjectMetadata.fields.find(
(field) =>
field.standardId === OPPORTUNITY_STANDARD_FIELD_IDS.amount,
)?.id ?? '',
position: 1,
isVisible: true,
size: 150,
aggregateOperation: AggregateOperations.AVG,
},
{
fieldMetadataId:
opportunityObjectMetadata.fields.find(
(field) =>
field.standardId === OPPORTUNITY_STANDARD_FIELD_IDS.createdBy,
)?.id ?? '',
position: 2,
isVisible: true,
size: 150,
},
{
fieldMetadataId:
opportunityObjectMetadata.fields.find(
(field) =>
field.standardId === OPPORTUNITY_STANDARD_FIELD_IDS.closeDate,
)?.id ?? '',
position: 3,
isVisible: true,
size: 150,
aggregateOperation: AggregateOperations.MAX,
},
{
fieldMetadataId:
opportunityObjectMetadata.fields.find(
(field) =>
field.standardId === OPPORTUNITY_STANDARD_FIELD_IDS.company,
)?.id ?? '',
position: 4,
isVisible: true,
size: 150,
aggregateOperation: AggregateOperations.COUNT,
},
{
fieldMetadataId:
opportunityObjectMetadata.fields.find(
(field) =>
field.standardId ===
OPPORTUNITY_STANDARD_FIELD_IDS.pointOfContact,
)?.id ?? '',
position: 5,
isVisible: true,
size: 150,
},
],
groups: [
{
fieldMetadataId:
opportunityObjectMetadata.fields.find(
(field) =>
field.standardId === OPPORTUNITY_STANDARD_FIELD_IDS.stage,
)?.id ?? '',
isVisible: true,
fieldValue: 'NEW',
position: 0,
},
{
fieldMetadataId:
opportunityObjectMetadata.fields.find(
(field) =>
field.standardId === OPPORTUNITY_STANDARD_FIELD_IDS.stage,
)?.id ?? '',
isVisible: true,
fieldValue: 'SCREENING',
position: 1,
},
{
fieldMetadataId:
opportunityObjectMetadata.fields.find(
(field) =>
field.standardId === OPPORTUNITY_STANDARD_FIELD_IDS.stage,
)?.id ?? '',
isVisible: true,
fieldValue: 'MEETING',
position: 2,
},
{
fieldMetadataId:
opportunityObjectMetadata.fields.find(
(field) =>
field.standardId === OPPORTUNITY_STANDARD_FIELD_IDS.stage,
)?.id ?? '',
isVisible: true,
fieldValue: 'PROPOSAL',
position: 3,
},
{
fieldMetadataId:
opportunityObjectMetadata.fields.find(
(field) =>
field.standardId === OPPORTUNITY_STANDARD_FIELD_IDS.stage,
)?.id ?? '',
isVisible: true,
fieldValue: 'CUSTOMER',
position: 4,
},
],
};
};
@@ -1,17 +1,26 @@
import { msg } from '@lingui/core/macro';
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
import { v4 } from 'uuid';
import { AggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/aggregate-operations.constant';
import { STANDARD_OBJECTS } from 'src/engine/core-modules/application/constants/standard-object.constant';
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface';
import {
BASE_OBJECT_STANDARD_FIELD_IDS,
PERSON_STANDARD_FIELD_IDS,
} from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
export const peopleAllView = (
objectMetadataItems: ObjectMetadataEntity[],
export const peopleAllView = ({
objectMetadataItems,
useCoreNaming = false,
) => {
twentyStandardFlatApplication,
}: {
objectMetadataItems: ObjectMetadataEntity[];
useCoreNaming?: boolean;
twentyStandardFlatApplication: FlatApplication;
}): ViewDefinition => {
const personObjectMetadata = objectMetadataItems.find(
(object) => object.standardId === STANDARD_OBJECT_IDS.person,
);
@@ -20,7 +29,13 @@ export const peopleAllView = (
throw new Error('Person object metadata not found');
}
const viewUniversalIdentifier =
STANDARD_OBJECTS.person.views.allPeople.universalIdentifier;
return {
id: v4(),
universalIdentifier: viewUniversalIdentifier,
applicationId: twentyStandardFlatApplication.id,
name: useCoreNaming ? msg`All {objectLabelPlural}` : 'All People',
objectMetadataId: personObjectMetadata.id,
type: 'table',
@@ -38,6 +53,9 @@ export const peopleAllView = (
position: 0,
isVisible: true,
size: 210,
universalIdentifier:
STANDARD_OBJECTS.person.views.allPeople.viewFields.name
.universalIdentifier,
},
{
fieldMetadataId:
@@ -48,6 +66,9 @@ export const peopleAllView = (
isVisible: true,
size: 150,
aggregateOperation: AggregateOperations.COUNT_UNIQUE_VALUES,
universalIdentifier:
STANDARD_OBJECTS.person.views.allPeople.viewFields.emails
.universalIdentifier,
},
{
fieldMetadataId:
@@ -57,6 +78,9 @@ export const peopleAllView = (
position: 2,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.person.views.allPeople.viewFields.createdBy
.universalIdentifier,
},
{
fieldMetadataId:
@@ -66,6 +90,9 @@ export const peopleAllView = (
position: 3,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.person.views.allPeople.viewFields.company
.universalIdentifier,
},
{
fieldMetadataId:
@@ -76,6 +103,9 @@ export const peopleAllView = (
isVisible: true,
size: 150,
aggregateOperation: AggregateOperations.PERCENTAGE_EMPTY,
universalIdentifier:
STANDARD_OBJECTS.person.views.allPeople.viewFields.phones
.universalIdentifier,
},
{
fieldMetadataId:
@@ -87,6 +117,9 @@ export const peopleAllView = (
isVisible: true,
size: 150,
aggregateOperation: AggregateOperations.MIN,
universalIdentifier:
STANDARD_OBJECTS.person.views.allPeople.viewFields.createdAt
.universalIdentifier,
},
{
fieldMetadataId:
@@ -96,6 +129,9 @@ export const peopleAllView = (
position: 6,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.person.views.allPeople.viewFields.city
.universalIdentifier,
},
{
fieldMetadataId:
@@ -105,6 +141,9 @@ export const peopleAllView = (
position: 7,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.person.views.allPeople.viewFields.jobTitle
.universalIdentifier,
},
{
fieldMetadataId:
@@ -115,6 +154,9 @@ export const peopleAllView = (
position: 8,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.person.views.allPeople.viewFields.linkedinLink
.universalIdentifier,
},
{
fieldMetadataId:
@@ -124,6 +166,9 @@ export const peopleAllView = (
position: 9,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.person.views.allPeople.viewFields.xLink
.universalIdentifier,
},
],
};
@@ -1,16 +1,25 @@
import { msg } from '@lingui/core/macro';
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
import { v4 } from 'uuid';
import { STANDARD_OBJECTS } from 'src/engine/core-modules/application/constants/standard-object.constant';
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface';
import {
BASE_OBJECT_STANDARD_FIELD_IDS,
TASK_STANDARD_FIELD_IDS,
} from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
export const tasksAllView = (
objectMetadataItems: ObjectMetadataEntity[],
export const tasksAllView = ({
objectMetadataItems,
useCoreNaming = false,
) => {
twentyStandardFlatApplication,
}: {
objectMetadataItems: ObjectMetadataEntity[];
useCoreNaming?: boolean;
twentyStandardFlatApplication: FlatApplication;
}): ViewDefinition => {
const taskObjectMetadata = objectMetadataItems.find(
(object) => object.standardId === STANDARD_OBJECT_IDS.task,
);
@@ -19,7 +28,13 @@ export const tasksAllView = (
throw new Error('Task object metadata not found');
}
const viewUniversalIdentifier =
STANDARD_OBJECTS.task.views.allTasks.universalIdentifier;
return {
id: v4(),
universalIdentifier: viewUniversalIdentifier,
applicationId: twentyStandardFlatApplication.id,
name: useCoreNaming ? msg`All {objectLabelPlural}` : 'All Tasks',
objectMetadataId: taskObjectMetadata.id,
type: 'table',
@@ -35,8 +50,7 @@ export const tasksAllView = (
],
displayValue: 'Task',
operand: 'is',
value: '["TASK"]',
},
value: '["TASK"]'},
],*/,
fields: [
{
@@ -47,6 +61,9 @@ export const tasksAllView = (
position: 0,
isVisible: true,
size: 210,
universalIdentifier:
STANDARD_OBJECTS.task.views.allTasks.viewFields.title
.universalIdentifier,
},
{
fieldMetadataId:
@@ -56,6 +73,9 @@ export const tasksAllView = (
position: 2,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.task.views.allTasks.viewFields.status
.universalIdentifier,
},
{
fieldMetadataId:
@@ -65,6 +85,9 @@ export const tasksAllView = (
position: 3,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.task.views.allTasks.viewFields.taskTargets
.universalIdentifier,
},
{
fieldMetadataId:
@@ -74,6 +97,9 @@ export const tasksAllView = (
position: 4,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.task.views.allTasks.viewFields.createdBy
.universalIdentifier,
},
{
fieldMetadataId:
@@ -83,6 +109,9 @@ export const tasksAllView = (
position: 5,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.task.views.allTasks.viewFields.dueAt
.universalIdentifier,
},
{
fieldMetadataId:
@@ -92,6 +121,9 @@ export const tasksAllView = (
position: 6,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.task.views.allTasks.viewFields.assignee
.universalIdentifier,
},
{
fieldMetadataId:
@@ -101,6 +133,9 @@ export const tasksAllView = (
position: 7,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.task.views.allTasks.viewFields.bodyV2
.universalIdentifier,
},
{
fieldMetadataId:
@@ -111,18 +146,19 @@ export const tasksAllView = (
position: 8,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.task.views.allTasks.viewFields.createdAt
.universalIdentifier,
},
/*
TODO: Add later, since we don't have real-time it probably doesn't work well?
{
fieldMetadataId:
objectMetadataMap[STANDARD_OBJECT_IDS.task].fields[
BASE_OBJECT_STANDARD_FIELD_IDS.updatedAt
objectMetadataMap[STANDARD_OBJECT_IDS.task].fields[.updatedAt
],
position: 0,
isVisible: true,
size: 210,
},
size: 210},
*/
],
};
@@ -1,17 +1,26 @@
import { msg } from '@lingui/core/macro';
import { ViewFilterOperand } from 'twenty-shared/types';
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
import { ViewFilterOperand } from 'twenty-shared/types';
import { v4 } from 'uuid';
import { STANDARD_OBJECTS } from 'src/engine/core-modules/application/constants/standard-object.constant';
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface';
import {
BASE_OBJECT_STANDARD_FIELD_IDS,
TASK_STANDARD_FIELD_IDS,
} from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
export const tasksAssignedToMeView = (
objectMetadataItems: ObjectMetadataEntity[],
export const tasksAssignedToMeView = ({
objectMetadataItems,
useCoreNaming = false,
) => {
twentyStandardFlatApplication,
}: {
objectMetadataItems: ObjectMetadataEntity[];
useCoreNaming?: boolean;
twentyStandardFlatApplication: FlatApplication;
}): ViewDefinition => {
const taskObjectMetadata = objectMetadataItems.find(
(object) => object.standardId === STANDARD_OBJECT_IDS.task,
);
@@ -20,7 +29,13 @@ export const tasksAssignedToMeView = (
throw new Error('Task object metadata not found');
}
const viewUniversalIdentifier =
STANDARD_OBJECTS.task.views.assignedToMe.universalIdentifier;
return {
id: v4(),
universalIdentifier: viewUniversalIdentifier,
applicationId: twentyStandardFlatApplication.id,
name: useCoreNaming ? msg`Assigned to Me` : 'Assigned to Me',
objectMetadataId: taskObjectMetadata.id,
type: 'table',
@@ -40,6 +55,9 @@ export const tasksAssignedToMeView = (
isCurrentWorkspaceMemberSelected: true,
selectedRecordIds: [],
}),
universalIdentifier:
STANDARD_OBJECTS.task.views.assignedToMe.viewFilters!.assigneeIsMe
.universalIdentifier,
},
],
fields: [
@@ -51,6 +69,9 @@ export const tasksAssignedToMeView = (
position: 0,
isVisible: true,
size: 210,
universalIdentifier:
STANDARD_OBJECTS.task.views.assignedToMe.viewFields.title
.universalIdentifier,
},
/*{
fieldMetadataId:
@@ -59,8 +80,7 @@ export const tasksAssignedToMeView = (
],
position: 2,
isVisible: true,
size: 150,
},*/
size: 150},*/
{
fieldMetadataId:
taskObjectMetadata.fields.find(
@@ -69,6 +89,9 @@ export const tasksAssignedToMeView = (
position: 3,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.task.views.assignedToMe.viewFields.taskTargets
.universalIdentifier,
},
{
fieldMetadataId:
@@ -78,6 +101,9 @@ export const tasksAssignedToMeView = (
position: 4,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.task.views.assignedToMe.viewFields.createdBy
.universalIdentifier,
},
{
fieldMetadataId:
@@ -87,6 +113,9 @@ export const tasksAssignedToMeView = (
position: 5,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.task.views.assignedToMe.viewFields.dueAt
.universalIdentifier,
},
{
fieldMetadataId:
@@ -96,6 +125,9 @@ export const tasksAssignedToMeView = (
position: 6,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.task.views.assignedToMe.viewFields.assignee
.universalIdentifier,
},
{
fieldMetadataId:
@@ -105,6 +137,9 @@ export const tasksAssignedToMeView = (
position: 7,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.task.views.assignedToMe.viewFields.bodyV2
.universalIdentifier,
},
{
fieldMetadataId:
@@ -115,6 +150,9 @@ export const tasksAssignedToMeView = (
position: 8,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.task.views.assignedToMe.viewFields.createdAt
.universalIdentifier,
},
],
groups: [
@@ -126,6 +164,9 @@ export const tasksAssignedToMeView = (
isVisible: true,
fieldValue: 'TODO',
position: 0,
universalIdentifier:
STANDARD_OBJECTS.task.views.assignedToMe.viewGroups!.todo
.universalIdentifier,
},
{
fieldMetadataId:
@@ -135,6 +176,9 @@ export const tasksAssignedToMeView = (
isVisible: true,
fieldValue: 'IN_PROGRESS',
position: 1,
universalIdentifier:
STANDARD_OBJECTS.task.views.assignedToMe.viewGroups!.inProgress
.universalIdentifier,
},
{
fieldMetadataId:
@@ -144,6 +188,9 @@ export const tasksAssignedToMeView = (
isVisible: true,
fieldValue: 'DONE',
position: 2,
universalIdentifier:
STANDARD_OBJECTS.task.views.assignedToMe.viewGroups!.done
.universalIdentifier,
},
{
fieldMetadataId:
@@ -153,6 +200,9 @@ export const tasksAssignedToMeView = (
isVisible: true,
fieldValue: '',
position: 3,
universalIdentifier:
STANDARD_OBJECTS.task.views.assignedToMe.viewGroups!.empty
.universalIdentifier,
},
],
};
@@ -1,16 +1,25 @@
import { msg } from '@lingui/core/macro';
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
import { v4 } from 'uuid';
import { STANDARD_OBJECTS } from 'src/engine/core-modules/application/constants/standard-object.constant';
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface';
import {
BASE_OBJECT_STANDARD_FIELD_IDS,
TASK_STANDARD_FIELD_IDS,
} from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
export const tasksByStatusView = (
objectMetadataItems: ObjectMetadataEntity[],
export const tasksByStatusView = ({
objectMetadataItems,
useCoreNaming = false,
) => {
twentyStandardFlatApplication,
}: {
objectMetadataItems: ObjectMetadataEntity[];
useCoreNaming?: boolean;
twentyStandardFlatApplication: FlatApplication;
}): ViewDefinition => {
const taskObjectMetadata = objectMetadataItems.find(
(object) => object.standardId === STANDARD_OBJECT_IDS.task,
);
@@ -19,7 +28,13 @@ export const tasksByStatusView = (
throw new Error('Task object metadata not found');
}
const viewUniversalIdentifier =
STANDARD_OBJECTS.task.views.byStatus.universalIdentifier;
return {
id: v4(),
universalIdentifier: viewUniversalIdentifier,
applicationId: twentyStandardFlatApplication.id,
name: useCoreNaming ? msg`By Status` : 'By Status',
objectMetadataId: taskObjectMetadata.id,
type: 'kanban',
@@ -38,8 +53,7 @@ export const tasksByStatusView = (
],
displayValue: 'Task',
operand: 'is',
value: '["TASK"]',
},
value: '["TASK"]'},
],*/,
fields: [
{
@@ -50,6 +64,9 @@ export const tasksByStatusView = (
position: 0,
isVisible: true,
size: 210,
universalIdentifier:
STANDARD_OBJECTS.task.views.byStatus.viewFields.title
.universalIdentifier,
},
{
fieldMetadataId:
@@ -59,6 +76,9 @@ export const tasksByStatusView = (
position: 2,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.task.views.byStatus.viewFields.status
.universalIdentifier,
},
{
fieldMetadataId:
@@ -68,6 +88,9 @@ export const tasksByStatusView = (
position: 3,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.task.views.byStatus.viewFields.dueAt
.universalIdentifier,
},
{
fieldMetadataId:
@@ -77,6 +100,9 @@ export const tasksByStatusView = (
position: 4,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.task.views.byStatus.viewFields.assignee
.universalIdentifier,
},
{
fieldMetadataId:
@@ -87,18 +113,19 @@ export const tasksByStatusView = (
position: 6,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.task.views.byStatus.viewFields.createdAt
.universalIdentifier,
},
/*
TODO: Add later, since we don't have real-time it probably doesn't work well?
{
fieldMetadataId:
objectMetadataMap[STANDARD_OBJECT_IDS.task].fields[
BASE_OBJECT_STANDARD_FIELD_IDS.updatedAt
objectMetadataMap[STANDARD_OBJECT_IDS.task].fields[.updatedAt
],
position: 0,
isVisible: true,
size: 210,
},
size: 210},
*/
],
groups: [
@@ -110,6 +137,9 @@ export const tasksByStatusView = (
isVisible: true,
fieldValue: 'TODO',
position: 0,
universalIdentifier:
STANDARD_OBJECTS.task.views.byStatus.viewGroups!.todo
.universalIdentifier,
},
{
fieldMetadataId:
@@ -119,6 +149,9 @@ export const tasksByStatusView = (
isVisible: true,
fieldValue: 'IN_PROGRESS',
position: 1,
universalIdentifier:
STANDARD_OBJECTS.task.views.byStatus.viewGroups!.inProgress
.universalIdentifier,
},
{
fieldMetadataId:
@@ -128,6 +161,9 @@ export const tasksByStatusView = (
isVisible: true,
fieldValue: 'DONE',
position: 2,
universalIdentifier:
STANDARD_OBJECTS.task.views.byStatus.viewGroups!.done
.universalIdentifier,
},
],
};
@@ -1,14 +1,23 @@
import { msg } from '@lingui/core/macro';
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
import { v4 } from 'uuid';
import { STANDARD_OBJECTS } from 'src/engine/core-modules/application/constants/standard-object.constant';
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { ViewOpenRecordInType } from 'src/engine/metadata-modules/view/types/view-open-record-in-type.type';
import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface';
import { WORKFLOW_RUN_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
export const workflowRunsAllView = (
objectMetadataItems: ObjectMetadataEntity[],
export const workflowRunsAllView = ({
objectMetadataItems,
useCoreNaming = false,
) => {
twentyStandardFlatApplication,
}: {
objectMetadataItems: ObjectMetadataEntity[];
useCoreNaming?: boolean;
twentyStandardFlatApplication: FlatApplication;
}): ViewDefinition => {
const workflowRunObjectMetadata = objectMetadataItems.find(
(object) => object.standardId === STANDARD_OBJECT_IDS.workflowRun,
);
@@ -17,7 +26,13 @@ export const workflowRunsAllView = (
throw new Error('Workflow run object metadata not found');
}
const viewUniversalIdentifier =
STANDARD_OBJECTS.workflowRun.views.allWorkflowRuns.universalIdentifier;
return {
id: v4(),
universalIdentifier: viewUniversalIdentifier,
applicationId: twentyStandardFlatApplication.id,
name: useCoreNaming ? msg`All {objectLabelPlural}` : 'All Workflow Runs',
objectMetadataId: workflowRunObjectMetadata.id,
type: 'table',
@@ -37,6 +52,9 @@ export const workflowRunsAllView = (
position: 0,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.workflowRun.views.allWorkflowRuns.viewFields.name
.universalIdentifier,
},
{
fieldMetadataId:
@@ -47,6 +65,9 @@ export const workflowRunsAllView = (
position: 1,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.workflowRun.views.allWorkflowRuns.viewFields.workflow
.universalIdentifier,
},
{
fieldMetadataId:
@@ -57,6 +78,9 @@ export const workflowRunsAllView = (
position: 2,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.workflowRun.views.allWorkflowRuns.viewFields.status
.universalIdentifier,
},
{
fieldMetadataId:
@@ -67,6 +91,9 @@ export const workflowRunsAllView = (
position: 3,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.workflowRun.views.allWorkflowRuns.viewFields
.startedAt.universalIdentifier,
},
{
fieldMetadataId:
@@ -77,6 +104,9 @@ export const workflowRunsAllView = (
position: 4,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.workflowRun.views.allWorkflowRuns.viewFields
.createdBy.universalIdentifier,
},
{
fieldMetadataId:
@@ -88,6 +118,9 @@ export const workflowRunsAllView = (
position: 5,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.workflowRun.views.allWorkflowRuns.viewFields
.workflowVersion.universalIdentifier,
},
],
};
@@ -1,17 +1,26 @@
import { msg } from '@lingui/core/macro';
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
import { v4 } from 'uuid';
import { STANDARD_OBJECTS } from 'src/engine/core-modules/application/constants/standard-object.constant';
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { ViewOpenRecordInType } from 'src/engine/metadata-modules/view/types/view-open-record-in-type.type';
import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface';
import {
BASE_OBJECT_STANDARD_FIELD_IDS,
WORKFLOW_VERSION_STANDARD_FIELD_IDS,
} from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
export const workflowVersionsAllView = (
objectMetadataItems: ObjectMetadataEntity[],
export const workflowVersionsAllView = ({
objectMetadataItems,
useCoreNaming = false,
) => {
twentyStandardFlatApplication,
}: {
objectMetadataItems: ObjectMetadataEntity[];
useCoreNaming?: boolean;
twentyStandardFlatApplication: FlatApplication;
}): ViewDefinition => {
const workflowVersionObjectMetadata = objectMetadataItems.find(
(object) => object.standardId === STANDARD_OBJECT_IDS.workflowVersion,
);
@@ -20,7 +29,14 @@ export const workflowVersionsAllView = (
throw new Error('Workflow version object metadata not found');
}
const viewUniversalIdentifier =
STANDARD_OBJECTS.workflowVersion.views.allWorkflowVersions
.universalIdentifier;
return {
id: v4(),
universalIdentifier: viewUniversalIdentifier,
applicationId: twentyStandardFlatApplication.id,
name: useCoreNaming
? msg`All {objectLabelPlural}`
: 'All Workflow Versions',
@@ -42,6 +58,9 @@ export const workflowVersionsAllView = (
position: 0,
isVisible: true,
size: 210,
universalIdentifier:
STANDARD_OBJECTS.workflowVersion.views.allWorkflowVersions.viewFields
.name.universalIdentifier,
},
{
fieldMetadataId:
@@ -52,6 +71,9 @@ export const workflowVersionsAllView = (
position: 1,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.workflowVersion.views.allWorkflowVersions.viewFields
.workflow.universalIdentifier,
},
{
fieldMetadataId:
@@ -62,6 +84,9 @@ export const workflowVersionsAllView = (
position: 2,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.workflowVersion.views.allWorkflowVersions.viewFields
.status.universalIdentifier,
},
{
fieldMetadataId:
@@ -72,6 +97,9 @@ export const workflowVersionsAllView = (
position: 3,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.workflowVersion.views.allWorkflowVersions.viewFields
.updatedAt.universalIdentifier,
},
{
fieldMetadataId:
@@ -82,6 +110,9 @@ export const workflowVersionsAllView = (
position: 4,
isVisible: false,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.workflowVersion.views.allWorkflowVersions.viewFields
.runs.universalIdentifier,
},
],
};
@@ -1,17 +1,26 @@
import { msg } from '@lingui/core/macro';
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
import { v4 } from 'uuid';
import { STANDARD_OBJECTS } from 'src/engine/core-modules/application/constants/standard-object.constant';
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { ViewOpenRecordInType } from 'src/engine/metadata-modules/view/types/view-open-record-in-type.type';
import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface';
import {
BASE_OBJECT_STANDARD_FIELD_IDS,
WORKFLOW_STANDARD_FIELD_IDS,
} from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
export const workflowsAllView = (
objectMetadataItems: ObjectMetadataEntity[],
export const workflowsAllView = ({
objectMetadataItems,
useCoreNaming = false,
) => {
twentyStandardFlatApplication,
}: {
objectMetadataItems: ObjectMetadataEntity[];
useCoreNaming?: boolean;
twentyStandardFlatApplication: FlatApplication;
}): ViewDefinition => {
const workflowObjectMetadata = objectMetadataItems.find(
(object) => object.standardId === STANDARD_OBJECT_IDS.workflow,
);
@@ -20,7 +29,13 @@ export const workflowsAllView = (
throw new Error('Workflow object metadata not found');
}
const viewUniversalIdentifier =
STANDARD_OBJECTS.workflow.views.allWorkflows.universalIdentifier;
return {
id: v4(),
universalIdentifier: viewUniversalIdentifier,
applicationId: twentyStandardFlatApplication.id,
name: useCoreNaming ? msg`All {objectLabelPlural}` : 'All Workflows',
objectMetadataId: workflowObjectMetadata.id,
type: 'table',
@@ -39,6 +54,9 @@ export const workflowsAllView = (
position: 0,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.workflow.views.allWorkflows.viewFields.name
.universalIdentifier,
},
{
fieldMetadataId:
@@ -49,6 +67,9 @@ export const workflowsAllView = (
position: 1,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.workflow.views.allWorkflows.viewFields.statuses
.universalIdentifier,
},
{
fieldMetadataId:
@@ -59,6 +80,9 @@ export const workflowsAllView = (
position: 2,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.workflow.views.allWorkflows.viewFields.updatedAt
.universalIdentifier,
},
{
fieldMetadataId:
@@ -69,6 +93,9 @@ export const workflowsAllView = (
position: 3,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.workflow.views.allWorkflows.viewFields.createdBy
.universalIdentifier,
},
{
fieldMetadataId:
@@ -79,6 +106,9 @@ export const workflowsAllView = (
position: 4,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.workflow.views.allWorkflows.viewFields.versions
.universalIdentifier,
},
{
fieldMetadataId:
@@ -88,6 +118,9 @@ export const workflowsAllView = (
position: 5,
isVisible: false,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.workflow.views.allWorkflows.viewFields.runs
.universalIdentifier,
},
],
};
@@ -1,17 +1,26 @@
import { msg } from '@lingui/core/macro';
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
import { v4 } from 'uuid';
import { STANDARD_OBJECTS } from 'src/engine/core-modules/application/constants/standard-object.constant';
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
import { type ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
import { type ViewDefinition } from 'src/engine/workspace-manager/standard-objects-prefill-data/types/view-definition.interface';
import { DEFAULT_VIEW_FIELD_SIZE } from 'src/engine/workspace-manager/standard-objects-prefill-data/views/constants/DEFAULT_VIEW_FIELD_SIZE';
import {
BASE_OBJECT_STANDARD_FIELD_IDS,
WORKSPACE_MEMBER_STANDARD_FIELD_IDS,
} from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
export const workspaceMembersAllView = (
objectMetadataItems: ObjectMetadataEntity[],
useCoreNaming = false,
) => {
export const workspaceMembersAllView = ({
objectMetadataItems,
twentyStandardFlatApplication,
useCoreNaming,
}: {
objectMetadataItems: ObjectMetadataEntity[];
useCoreNaming?: boolean;
twentyStandardFlatApplication: FlatApplication;
}): ViewDefinition => {
const workspaceMemberObjectMetadata = objectMetadataItems.find(
(object) => object.standardId === STANDARD_OBJECT_IDS.workspaceMember,
);
@@ -20,7 +29,14 @@ export const workspaceMembersAllView = (
throw new Error('WorkspaceMember object metadata not found');
}
const viewUniversalIdentifier =
STANDARD_OBJECTS.workspaceMember.views.allWorkspaceMembers
.universalIdentifier;
return {
id: v4(),
universalIdentifier: viewUniversalIdentifier,
applicationId: twentyStandardFlatApplication.id,
name: useCoreNaming
? msg`All {objectLabelPlural}`
: 'All Workspace Members',
@@ -41,6 +57,9 @@ export const workspaceMembersAllView = (
position: 0,
isVisible: true,
size: DEFAULT_VIEW_FIELD_SIZE,
universalIdentifier:
STANDARD_OBJECTS.workspaceMember.views.allWorkspaceMembers.viewFields
.name.universalIdentifier,
},
{
fieldMetadataId:
@@ -52,6 +71,9 @@ export const workspaceMembersAllView = (
position: 1,
isVisible: true,
size: 180,
universalIdentifier:
STANDARD_OBJECTS.workspaceMember.views.allWorkspaceMembers.viewFields
.userEmail.universalIdentifier,
},
{
fieldMetadataId:
@@ -63,6 +85,9 @@ export const workspaceMembersAllView = (
position: 2,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.workspaceMember.views.allWorkspaceMembers.viewFields
.avatarUrl.universalIdentifier,
},
{
fieldMetadataId:
@@ -74,6 +99,9 @@ export const workspaceMembersAllView = (
position: 3,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.workspaceMember.views.allWorkspaceMembers.viewFields
.colorScheme.universalIdentifier,
},
{
fieldMetadataId:
@@ -84,6 +112,9 @@ export const workspaceMembersAllView = (
position: 4,
isVisible: true,
size: 120,
universalIdentifier:
STANDARD_OBJECTS.workspaceMember.views.allWorkspaceMembers.viewFields
.locale.universalIdentifier,
},
{
fieldMetadataId:
@@ -94,6 +125,9 @@ export const workspaceMembersAllView = (
position: 5,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.workspaceMember.views.allWorkspaceMembers.viewFields
.timeZone.universalIdentifier,
},
{
fieldMetadataId:
@@ -105,6 +139,9 @@ export const workspaceMembersAllView = (
position: 6,
isVisible: true,
size: 120,
universalIdentifier:
STANDARD_OBJECTS.workspaceMember.views.allWorkspaceMembers.viewFields
.dateFormat.universalIdentifier,
},
{
fieldMetadataId:
@@ -116,6 +153,9 @@ export const workspaceMembersAllView = (
position: 7,
isVisible: true,
size: 120,
universalIdentifier:
STANDARD_OBJECTS.workspaceMember.views.allWorkspaceMembers.viewFields
.timeFormat.universalIdentifier,
},
{
fieldMetadataId:
@@ -126,6 +166,9 @@ export const workspaceMembersAllView = (
position: 8,
isVisible: true,
size: 150,
universalIdentifier:
STANDARD_OBJECTS.workspaceMember.views.allWorkspaceMembers.viewFields
.createdAt.universalIdentifier,
},
],
};
@@ -4,6 +4,7 @@ import { InjectDataSource, InjectRepository } from '@nestjs/typeorm';
import { DataSource, Repository } from 'typeorm';
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
import { FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service';
import { UserWorkspaceEntity } from 'src/engine/core-modules/user-workspace/user-workspace.entity';
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
@@ -79,9 +80,10 @@ export class WorkspaceManagerService {
const featureFlags =
await this.featureFlagService.getWorkspaceFeatureFlagsMap(workspaceId);
await this.applicationService.createTwentyStandardApplication({
workspaceId,
});
const twentyStandardApplication =
await this.applicationService.createTwentyStandardApplication({
workspaceId,
});
// TODO later replace by twenty-standard installation aka workspaceMigration run
await this.workspaceSyncMetadataService.synchronize({
@@ -96,7 +98,18 @@ export class WorkspaceManagerService {
`Metadata creation took ${dataSourceMetadataCreationEnd - dataSourceMetadataCreationStart}ms`,
);
await this.setupDefaultRoles(workspaceId, userId);
const { workspaceCustomFlatApplication } =
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
{
workspaceId,
},
);
await this.setupDefaultRoles({
workspaceId,
userId,
workspaceCustomFlatApplication,
});
const prefillStandardObjectsStart = performance.now();
@@ -104,6 +117,7 @@ export class WorkspaceManagerService {
dataSourceMetadata,
workspaceId,
featureFlags,
twentyStandardApplication,
);
const prefillStandardObjectsEnd = performance.now();
@@ -117,6 +131,7 @@ export class WorkspaceManagerService {
dataSourceMetadata: DataSourceEntity,
workspaceId: string,
featureFlags: Record<string, boolean>,
twentyStandardFlatApplication: FlatApplication,
) {
const createdObjectMetadata =
await this.objectMetadataServiceV2.findManyWithinWorkspace(workspaceId);
@@ -128,6 +143,7 @@ export class WorkspaceManagerService {
);
await prefillCoreViews({
twentyStandardFlatApplication,
coreDataSource: this.coreDataSource,
workspaceId,
objectMetadataItems: createdObjectMetadata,
@@ -155,10 +171,15 @@ export class WorkspaceManagerService {
await this.workspaceDataSourceService.deleteWorkspaceDBSchema(workspaceId);
}
private async setupDefaultRoles(
workspaceId: string,
userId: string,
): Promise<void> {
private async setupDefaultRoles({
userId,
workspaceId,
workspaceCustomFlatApplication,
}: {
workspaceId: string;
userId: string;
workspaceCustomFlatApplication: FlatApplication;
}): Promise<void> {
const adminRole = await this.roleRepository.findOne({
where: {
standardId: ADMIN_ROLE.standardId,
@@ -180,6 +201,7 @@ export class WorkspaceManagerService {
const memberRole = await this.roleService.createMemberRole({
workspaceId,
applicationId: workspaceCustomFlatApplication.id,
});
await this.workspaceRepository.update(workspaceId, {
@@ -18,7 +18,14 @@ type AgentComparatorResult = {
type WorkspaceAgentComparatorArgs = FromTo<FlatAgent[], 'FlatAgents'>;
const agentPropertiesToIgnore = ['id', 'createdAt', 'updatedAt', 'workspaceId'];
const agentPropertiesToIgnore = [
'id',
'createdAt',
'updatedAt',
'workspaceId',
'universalIdentifier',
'applicationId',
];
@Injectable()
export class WorkspaceAgentComparator {
@@ -29,6 +29,8 @@ const commonFieldPropertiesToIgnore = [
'relationTargetObjectMetadataId',
'relationTargetFieldMetadata',
'relationTargetObjectMetadata',
'universalIdentifier',
'applicationId',
];
const fieldPropertiesToStringify = ['defaultValue'] as const;
@@ -10,7 +10,13 @@ import {
import { type IndexMetadataEntity } from 'src/engine/metadata-modules/index-metadata/index-metadata.entity';
import { transformMetadataForComparison } from 'src/engine/workspace-manager/workspace-sync-metadata/comparators/utils/transform-metadata-for-comparison.util';
const propertiesToIgnore = ['createdAt', 'updatedAt', 'indexFieldMetadatas'];
const propertiesToIgnore = [
'createdAt',
'updatedAt',
'indexFieldMetadatas',
'universalIdentifier',
'applicationId',
];
@Injectable()
export class WorkspaceIndexComparator {
@@ -20,6 +20,8 @@ const objectPropertiesToIgnore = [
'imageIdentifierFieldMetadataId',
'isActive',
'fields',
'universalIdentifier',
'applicationId',
];
@Injectable()
@@ -37,6 +37,8 @@ const rolePropertiesToIgnore = [
'permissionFlags',
'objectPermissions',
'fieldPermissions',
'universalIdentifier',
'applicationId',
];
@Injectable()
@@ -157,33 +157,6 @@ export const CONNECTED_ACCOUNT_STANDARD_FIELD_IDS = {
connectionParameters: '20202020-a1b2-46be-814f-6228af16c481',
} as const;
export const EVENT_STANDARD_FIELD_IDS = {
properties: '20202020-f142-4b04-b91b-6a2b4af3bf10',
workspaceMember: '20202020-af23-4479-9a30-868edc474b35',
person: '20202020-c414-45b9-a60a-ac27aa96229e',
company: '20202020-04ad-4221-a744-7a8278a5ce20',
opportunity: '20202020-7664-4a35-a3df-580d389fd5f0',
custom: '20202020-4a71-41b0-9f83-9cdcca3f8b14',
} as const;
export const AUDIT_LOGS_STANDARD_FIELD_IDS = {
name: '20202020-2462-4b9d-b5d9-745febb3b095',
properties: '20202020-5d36-470e-8fad-d56ea3ab2fd0',
context: '20202020-b9d1-4058-9a75-7469cab5ca8c',
objectName: '20202020-76ba-4c47-b7e5-96034005d00a',
objectMetadataId: '20202020-127b-409d-9864-0ec44aa9ed98',
recordId: '20202020-c578-4acf-bf94-eb53b035cea2',
workspaceMember: '20202020-6e96-4300-b3f5-67a707147385',
} as const;
export const BEHAVIORAL_EVENT_STANDARD_FIELD_IDS = {
name: '20202020-2462-4b9d-b5d9-745febb3b095',
properties: '20202020-5d36-470e-8fad-d56ea3ab2fd0',
context: '20202020-bd62-4b5b-8385-6caeed8f8078',
objectName: '20202020-a744-406c-a2e1-9d83d74f4341',
recordId: '20202020-6d8b-4ca5-9869-f882cb335673',
} as const;
export const TIMELINE_ACTIVITY_STANDARD_FIELD_IDS = {
happensAt: '20202020-9526-4993-b339-c4318c4d39f0',
type: '20202020-5e7b-4ccd-8b8a-86b94b474134',
@@ -537,7 +510,6 @@ export const WORKSPACE_MEMBER_STANDARD_FIELD_IDS = {
calendarStartDay: '20202020-92d0-1d7f-a126-25ededa6b142',
numberFormat: '20202020-7f40-4e7f-b126-11c0eda6b141',
} as const;
export const CUSTOM_OBJECT_STANDARD_FIELD_IDS = {
name: '20202020-ba07-4ffd-ba63-009491f5749c',
position: '20202020-c2bd-4e16-bb9a-c8b0411bf49d',
@@ -568,7 +540,6 @@ export const STANDARD_OBJECT_FIELD_IDS = {
activity: ACTIVITY_STANDARD_FIELD_IDS,
attachment: ATTACHMENT_STANDARD_FIELD_IDS,
blocklist: BLOCKLIST_STANDARD_FIELD_IDS,
behavioralEvent: BEHAVIORAL_EVENT_STANDARD_FIELD_IDS,
calendarChannelEventAssociation:
CALENDAR_CHANNEL_EVENT_ASSOCIATION_STANDARD_FIELD_IDS,
calendarChannel: CALENDAR_CHANNEL_STANDARD_FIELD_IDS,
@@ -579,7 +550,6 @@ export const STANDARD_OBJECT_FIELD_IDS = {
connectedAccount: CONNECTED_ACCOUNT_STANDARD_FIELD_IDS,
dashboard: DASHBOARD_STANDARD_FIELD_IDS,
favorite: FAVORITE_STANDARD_FIELD_IDS,
auditLog: AUDIT_LOGS_STANDARD_FIELD_IDS,
messageChannelMessageAssociation:
MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_STANDARD_FIELD_IDS,
messageChannel: MESSAGE_CHANNEL_STANDARD_FIELD_IDS,
@@ -1,27 +0,0 @@
import { type ApplicationEntity } from 'src/engine/core-modules/application/application.entity';
export const TWENTY_STANDARD_APPLICATION = {
universalIdentifier: '20202020-64aa-4b6f-b003-9c74b97cee20',
name: 'Twenty Standard',
description:
'Twenty is an open-source CRM that allows you to manage your sales and customer relationships',
version: '1.0.0',
sourcePath: 'cli-sync',
sourceType: 'local',
canBeUninstalled: false,
} as const satisfies CreateApplicationInput;
export type CreateApplicationInput = Omit<
ApplicationEntity,
| 'workspaceId'
| 'serverlessFunctionLayerId'
| 'id'
| 'createdAt'
| 'updatedAt'
| 'deletedAt'
| 'workspace'
| 'agents'
| 'applicationVariables'
| 'objects'
| 'serverlessFunctions'
>;
@@ -1,5 +1,4 @@
import { type FeatureFlagMap } from 'src/engine/core-modules/feature-flag/interfaces/feature-flag-map.interface';
export interface WorkspaceSyncContext {
workspaceId: string;
dataSourceId: string;
@@ -1,27 +0,0 @@
import { isDefined } from 'twenty-shared/utils';
import { v4 } from 'uuid';
import { type WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
import { type CreateApplicationInput } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/twenty-standard-applications';
export const computeWorkspaceCustomCreateApplicationInput = ({
workspace,
applicationId = v4(),
}: {
applicationId?: string;
workspace: Pick<WorkspaceEntity, 'id' | 'displayName'>;
}) =>
({
description: 'Workspace custom application',
name: `${isDefined(workspace.displayName) ? `${workspace.displayName}'s ` : ''}custom application`,
sourcePath: 'workspace-custom',
sourceType: 'local',
version: '1.0.0',
universalIdentifier: applicationId,
workspaceId: workspace.id,
id: applicationId,
canBeUninstalled: false,
}) as const satisfies CreateApplicationInput & {
workspaceId: string;
id: string;
};