Remove sync-metadata and IS_WORKSPACE_CREATION_V2_ENABLED feature flag (#16997)

# Introduction
Followup of
https://github.com/twentyhq/twenty/pull/17001#pullrequestreview-3638508738
close https://github.com/twentyhq/core-team-issues/issues/1910

We've completely decom the `sync-metadata` in production. We're now then
removing its implementation in favor of the v2.

## TODO:
- [x] Remove sync-metadata implem and commands
- [x] Remove workspace decorators 
- [x] Type each deprecated field to deprecated on their workspaceEntity
- [x] Remove the `workspace-sync-metadata` folder entirely
- [x] remove workspace migration
- [x] workspace migration removal migration
- [x] remove the `v2` references from workspace manager file names
- [x] remove the `v2` references from workspace manager modules
- [ ] Double check impact on translation file path updates


## Note
- Removed the gate logic
- Remains some service v2 naming, serverless needs to be migrated on v2
fully
- Removed workspaceMigration service app health consumption, making it
always returning up ( no more down ) cc @FelixMalfait ( quite obsolete
health check now, will require complete refactor once we introduce inter
app dependency etc )
This commit is contained in:
Paul Rastoin
2026-01-08 16:45:12 +01:00
committed by GitHub
parent f1aee7fd18
commit 942d2fef83
629 changed files with 1985 additions and 21492 deletions
@@ -1,314 +1,41 @@
import { msg } from '@lingui/core/macro';
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
import {
ActorMetadata,
FieldMetadataType,
RelationOnDeleteAction,
} from 'twenty-shared/types';
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
import { type ActorMetadata } from 'twenty-shared/types';
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
import { CustomWorkspaceEntity } from 'src/engine/twenty-orm/custom.workspace-entity';
import { WorkspaceDynamicRelation } from 'src/engine/twenty-orm/decorators/workspace-dynamic-relation.decorator';
import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator';
import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator';
import { WorkspaceIsDeprecated } from 'src/engine/twenty-orm/decorators/workspace-is-deprecated.decorator';
import { WorkspaceIsFieldUIReadOnly } from 'src/engine/twenty-orm/decorators/workspace-is-field-ui-readonly.decorator';
import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator';
import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator';
import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator';
import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator';
import { ATTACHMENT_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons';
import { CompanyWorkspaceEntity } from 'src/modules/company/standard-objects/company.workspace-entity';
import { DashboardWorkspaceEntity } from 'src/modules/dashboard/standard-objects/dashboard.workspace-entity';
import { NoteWorkspaceEntity } from 'src/modules/note/standard-objects/note.workspace-entity';
import { OpportunityWorkspaceEntity } from 'src/modules/opportunity/standard-objects/opportunity.workspace-entity';
import { PersonWorkspaceEntity } from 'src/modules/person/standard-objects/person.workspace-entity';
import { TaskWorkspaceEntity } from 'src/modules/task/standard-objects/task.workspace-entity';
import { WorkflowWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow.workspace-entity';
import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
import { type CustomWorkspaceEntity } from 'src/engine/twenty-orm/custom.workspace-entity';
import { type EntityRelation } from 'src/engine/workspace-manager/workspace-migration/types/entity-relation.interface';
import { type CompanyWorkspaceEntity } from 'src/modules/company/standard-objects/company.workspace-entity';
import { type DashboardWorkspaceEntity } from 'src/modules/dashboard/standard-objects/dashboard.workspace-entity';
import { type NoteWorkspaceEntity } from 'src/modules/note/standard-objects/note.workspace-entity';
import { type OpportunityWorkspaceEntity } from 'src/modules/opportunity/standard-objects/opportunity.workspace-entity';
import { type PersonWorkspaceEntity } from 'src/modules/person/standard-objects/person.workspace-entity';
import { type TaskWorkspaceEntity } from 'src/modules/task/standard-objects/task.workspace-entity';
import { type WorkflowWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow.workspace-entity';
import { type WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
@WorkspaceEntity({
standardId: STANDARD_OBJECT_IDS.attachment,
namePlural: 'attachments',
labelSingular: msg`Attachment`,
labelPlural: msg`Attachments`,
description: msg`An attachment`,
icon: STANDARD_OBJECT_ICONS.attachment,
labelIdentifierStandardId: ATTACHMENT_STANDARD_FIELD_IDS.name,
})
@WorkspaceIsSystem()
export class AttachmentWorkspaceEntity extends BaseWorkspaceEntity {
@WorkspaceField({
standardId: ATTACHMENT_STANDARD_FIELD_IDS.name,
type: FieldMetadataType.TEXT,
label: msg`Name`,
description: msg`Attachment name`,
icon: 'IconFileUpload',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
name: string | null;
@WorkspaceField({
standardId: ATTACHMENT_STANDARD_FIELD_IDS.fullPath,
type: FieldMetadataType.TEXT,
label: msg`Full path`,
description: msg`Attachment full path`,
icon: 'IconLink',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
fullPath: string | null;
@WorkspaceField({
standardId: ATTACHMENT_STANDARD_FIELD_IDS.type,
type: FieldMetadataType.TEXT,
label: msg`Type (deprecated)`,
description: msg`Attachment type (deprecated - use fileCategory)`,
icon: 'IconList',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
@WorkspaceIsDeprecated()
/** @deprecated Use `fileCategory` field instead */
type: string | null;
@WorkspaceField({
standardId: ATTACHMENT_STANDARD_FIELD_IDS.fileCategory,
type: FieldMetadataType.SELECT,
label: msg`File category`,
description: msg`Attachment file category`,
icon: 'IconList',
options: [
{
value: 'ARCHIVE',
label: 'Archive',
position: 0,
color: 'gray',
},
{
value: 'AUDIO',
label: 'Audio',
position: 1,
color: 'pink',
},
{
value: 'IMAGE',
label: 'Image',
position: 2,
color: 'yellow',
},
{
value: 'PRESENTATION',
label: 'Presentation',
position: 3,
color: 'orange',
},
{
value: 'SPREADSHEET',
label: 'Spreadsheet',
position: 4,
color: 'turquoise',
},
{
value: 'TEXT_DOCUMENT',
label: 'Text Document',
position: 5,
color: 'blue',
},
{
value: 'VIDEO',
label: 'Video',
position: 6,
color: 'purple',
},
{
value: 'OTHER',
label: 'Other',
position: 7,
color: 'gray',
},
],
defaultValue: "'OTHER'",
})
@WorkspaceIsFieldUIReadOnly()
fileCategory: string;
@WorkspaceField({
standardId: ATTACHMENT_STANDARD_FIELD_IDS.createdBy,
type: FieldMetadataType.ACTOR,
label: msg`Created by`,
icon: 'IconCreativeCommonsSa',
description: msg`The creator of the record`,
})
@WorkspaceIsFieldUIReadOnly()
createdBy: ActorMetadata;
@WorkspaceField({
standardId: ATTACHMENT_STANDARD_FIELD_IDS.updatedBy,
type: FieldMetadataType.ACTOR,
label: msg`Updated by`,
icon: 'IconUserCircle',
description: msg`The workspace member who last updated the record`,
})
@WorkspaceIsFieldUIReadOnly()
updatedBy: ActorMetadata;
@WorkspaceRelation({
standardId: ATTACHMENT_STANDARD_FIELD_IDS.author,
type: RelationType.MANY_TO_ONE,
label: msg`Author`,
description: msg`Attachment author (deprecated - use createdBy)`,
icon: 'IconCircleUser',
inverseSideTarget: () => WorkspaceMemberWorkspaceEntity,
inverseSideFieldKey: 'authoredAttachments',
onDelete: RelationOnDeleteAction.SET_NULL,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
@WorkspaceIsDeprecated()
author: Relation<WorkspaceMemberWorkspaceEntity> | null;
@WorkspaceJoinColumn('author')
/** @deprecated */
author: EntityRelation<WorkspaceMemberWorkspaceEntity> | null;
authorId: string | null;
@WorkspaceRelation({
standardId: ATTACHMENT_STANDARD_FIELD_IDS.task,
type: RelationType.MANY_TO_ONE,
label: msg`Task`,
description: msg`Attachment task`,
icon: 'IconNotes',
inverseSideTarget: () => TaskWorkspaceEntity,
inverseSideFieldKey: 'attachments',
onDelete: RelationOnDeleteAction.SET_NULL,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
task: Relation<TaskWorkspaceEntity> | null;
@WorkspaceJoinColumn('task')
task: EntityRelation<TaskWorkspaceEntity> | null;
taskId: string | null;
@WorkspaceRelation({
standardId: ATTACHMENT_STANDARD_FIELD_IDS.note,
type: RelationType.MANY_TO_ONE,
label: msg`Note`,
description: msg`Attachment note`,
icon: 'IconNotes',
inverseSideTarget: () => NoteWorkspaceEntity,
inverseSideFieldKey: 'attachments',
onDelete: RelationOnDeleteAction.SET_NULL,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
note: Relation<NoteWorkspaceEntity> | null;
@WorkspaceJoinColumn('note')
note: EntityRelation<NoteWorkspaceEntity> | null;
noteId: string | null;
@WorkspaceRelation({
standardId: ATTACHMENT_STANDARD_FIELD_IDS.person,
type: RelationType.MANY_TO_ONE,
label: msg`Person`,
description: msg`Attachment person`,
icon: 'IconUser',
inverseSideTarget: () => PersonWorkspaceEntity,
inverseSideFieldKey: 'attachments',
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
person: Relation<PersonWorkspaceEntity> | null;
@WorkspaceJoinColumn('person')
person: EntityRelation<PersonWorkspaceEntity> | null;
personId: string | null;
@WorkspaceRelation({
standardId: ATTACHMENT_STANDARD_FIELD_IDS.company,
type: RelationType.MANY_TO_ONE,
label: msg`Company`,
description: msg`Attachment company`,
icon: 'IconBuildingSkyscraper',
inverseSideTarget: () => CompanyWorkspaceEntity,
inverseSideFieldKey: 'attachments',
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
company: Relation<CompanyWorkspaceEntity> | null;
@WorkspaceJoinColumn('company')
company: EntityRelation<CompanyWorkspaceEntity> | null;
companyId: string | null;
@WorkspaceRelation({
standardId: ATTACHMENT_STANDARD_FIELD_IDS.opportunity,
type: RelationType.MANY_TO_ONE,
label: msg`Opportunity`,
description: msg`Attachment opportunity`,
icon: 'IconBuildingSkyscraper',
inverseSideTarget: () => OpportunityWorkspaceEntity,
inverseSideFieldKey: 'attachments',
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
opportunity: Relation<OpportunityWorkspaceEntity> | null;
@WorkspaceJoinColumn('opportunity')
opportunity: EntityRelation<OpportunityWorkspaceEntity> | null;
opportunityId: string | null;
@WorkspaceRelation({
standardId: ATTACHMENT_STANDARD_FIELD_IDS.dashboard,
type: RelationType.MANY_TO_ONE,
label: msg`Dashboard`,
description: msg`Attachment dashboard`,
icon: 'IconLayout',
inverseSideTarget: () => DashboardWorkspaceEntity,
inverseSideFieldKey: 'attachments',
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
dashboard: Relation<DashboardWorkspaceEntity> | null;
@WorkspaceJoinColumn('dashboard')
dashboard: EntityRelation<DashboardWorkspaceEntity> | null;
dashboardId: string | null;
@WorkspaceRelation({
standardId: ATTACHMENT_STANDARD_FIELD_IDS.workflow,
type: RelationType.MANY_TO_ONE,
label: msg`Workflow`,
description: msg`Attachment workflow`,
icon: 'IconSettingsAutomation',
inverseSideTarget: () => WorkflowWorkspaceEntity,
inverseSideFieldKey: 'attachments',
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
workflow: Relation<WorkflowWorkspaceEntity> | null;
@WorkspaceJoinColumn('workflow')
workflow: EntityRelation<WorkflowWorkspaceEntity> | null;
workflowId: string | null;
// todo: remove this decorator and the custom field
@WorkspaceDynamicRelation({
type: RelationType.MANY_TO_ONE,
argsFactory: (oppositeObjectMetadata) => ({
standardId: ATTACHMENT_STANDARD_FIELD_IDS.custom,
name: oppositeObjectMetadata.nameSingular,
label: oppositeObjectMetadata.labelSingular,
description: `Attachment ${oppositeObjectMetadata.labelSingular}`,
joinColumn: `${oppositeObjectMetadata.nameSingular}Id`,
icon: 'IconBuildingSkyscraper',
}),
inverseSideTarget: () => CustomWorkspaceEntity,
inverseSideFieldKey: 'attachments',
onDelete: RelationOnDeleteAction.CASCADE,
})
custom: Relation<CustomWorkspaceEntity>;
custom: EntityRelation<CustomWorkspaceEntity>;
}
@@ -1,58 +1,9 @@
import { msg } from '@lingui/core/macro';
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
import { FieldMetadataType, RelationOnDeleteAction } from 'twenty-shared/types';
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator';
import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator';
import { WorkspaceIsFieldUIReadOnly } from 'src/engine/twenty-orm/decorators/workspace-is-field-ui-readonly.decorator';
import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator';
import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator';
import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator';
import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator';
import { BLOCKLIST_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons';
import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
import { type EntityRelation } from 'src/engine/workspace-manager/workspace-migration/types/entity-relation.interface';
import { type WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
@WorkspaceEntity({
standardId: STANDARD_OBJECT_IDS.blocklist,
namePlural: 'blocklists',
labelSingular: msg`Blocklist`,
labelPlural: msg`Blocklists`,
description: msg`Blocklist`,
icon: STANDARD_OBJECT_ICONS.blocklist,
labelIdentifierStandardId: BLOCKLIST_STANDARD_FIELD_IDS.handle,
})
@WorkspaceIsSystem()
export class BlocklistWorkspaceEntity extends BaseWorkspaceEntity {
@WorkspaceField({
standardId: BLOCKLIST_STANDARD_FIELD_IDS.handle,
type: FieldMetadataType.TEXT,
label: msg`Handle`,
description: msg`Handle`,
icon: 'IconAt',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
handle: string | null;
@WorkspaceRelation({
standardId: BLOCKLIST_STANDARD_FIELD_IDS.workspaceMember,
type: RelationType.MANY_TO_ONE,
label: msg`WorkspaceMember`,
description: msg`WorkspaceMember`,
icon: 'IconCircleUser',
inverseSideTarget: () => WorkspaceMemberWorkspaceEntity,
inverseSideFieldKey: 'blocklist',
onDelete: RelationOnDeleteAction.SET_NULL,
})
@WorkspaceIsFieldUIReadOnly()
workspaceMember: Relation<WorkspaceMemberWorkspaceEntity>;
@WorkspaceJoinColumn('workspaceMember')
workspaceMember: EntityRelation<WorkspaceMemberWorkspaceEntity>;
workspaceMemberId: string;
}
@@ -1,96 +1,13 @@
import { msg } from '@lingui/core/macro';
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
import { FieldMetadataType, RelationOnDeleteAction } from 'twenty-shared/types';
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator';
import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator';
import { WorkspaceIsFieldUIReadOnly } from 'src/engine/twenty-orm/decorators/workspace-is-field-ui-readonly.decorator';
import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator';
import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator';
import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator';
import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator';
import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator';
import { CALENDAR_CHANNEL_EVENT_ASSOCIATION_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons';
import { CalendarChannelWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity';
import { CalendarEventWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-event.workspace-entity';
import { type EntityRelation } from 'src/engine/workspace-manager/workspace-migration/types/entity-relation.interface';
import { type CalendarChannelWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity';
import { type CalendarEventWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-event.workspace-entity';
@WorkspaceEntity({
standardId: STANDARD_OBJECT_IDS.calendarChannelEventAssociation,
namePlural: 'calendarChannelEventAssociations',
labelSingular: msg`Calendar Channel Event Association`,
labelPlural: msg`Calendar Channel Event Associations`,
description: msg`Calendar Channel Event Associations`,
icon: STANDARD_OBJECT_ICONS.calendarChannelEventAssociation,
})
@WorkspaceIsSystem()
@WorkspaceIsNotAuditLogged()
export class CalendarChannelEventAssociationWorkspaceEntity extends BaseWorkspaceEntity {
/**
* External ID of the calendar event. Comes from the provider's API, is unique per connected account.
* Used by the provider to identify the event in their system.
* So two External ID can be related to the same event sharing the same iCalUID.
*/
@WorkspaceField({
standardId:
CALENDAR_CHANNEL_EVENT_ASSOCIATION_STANDARD_FIELD_IDS.eventExternalId,
type: FieldMetadataType.TEXT,
label: msg`Event external ID`,
description: msg`Event external ID`,
icon: 'IconCalendar',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
eventExternalId: string | null;
@WorkspaceField({
standardId:
CALENDAR_CHANNEL_EVENT_ASSOCIATION_STANDARD_FIELD_IDS.recurringEventExternalId,
type: FieldMetadataType.TEXT,
label: msg`Recurring Event ID`,
description: msg`Recurring Event ID`,
icon: 'IconHistory',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
recurringEventExternalId: string | null;
@WorkspaceRelation({
standardId:
CALENDAR_CHANNEL_EVENT_ASSOCIATION_STANDARD_FIELD_IDS.calendarChannel,
type: RelationType.MANY_TO_ONE,
label: msg`Channel ID`,
description: msg`Channel ID`,
icon: 'IconCalendar',
inverseSideTarget: () => CalendarChannelWorkspaceEntity,
inverseSideFieldKey: 'calendarChannelEventAssociations',
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
calendarChannel: Relation<CalendarChannelWorkspaceEntity>;
@WorkspaceJoinColumn('calendarChannel')
calendarChannel: EntityRelation<CalendarChannelWorkspaceEntity>;
calendarChannelId: string;
@WorkspaceRelation({
standardId:
CALENDAR_CHANNEL_EVENT_ASSOCIATION_STANDARD_FIELD_IDS.calendarEvent,
type: RelationType.MANY_TO_ONE,
label: msg`Event ID`,
description: msg`Event ID`,
icon: 'IconCalendar',
inverseSideTarget: () => CalendarEventWorkspaceEntity,
inverseSideFieldKey: 'calendarChannelEventAssociations',
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
calendarEvent: Relation<CalendarEventWorkspaceEntity>;
@WorkspaceJoinColumn('calendarEvent')
calendarEvent: EntityRelation<CalendarEventWorkspaceEntity>;
calendarEventId: string;
}
@@ -1,25 +1,9 @@
import { registerEnumType } from '@nestjs/graphql';
import { msg } from '@lingui/core/macro';
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
import { FieldMetadataType, RelationOnDeleteAction } from 'twenty-shared/types';
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator';
import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator';
import { WorkspaceIsFieldUIReadOnly } from 'src/engine/twenty-orm/decorators/workspace-is-field-ui-readonly.decorator';
import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator';
import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator';
import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator';
import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator';
import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator';
import { CALENDAR_CHANNEL_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons';
import { CalendarChannelEventAssociationWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-channel-event-association.workspace-entity';
import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
import { type EntityRelation } from 'src/engine/workspace-manager/workspace-migration/types/entity-relation.interface';
import { type CalendarChannelEventAssociationWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-channel-event-association.workspace-entity';
import { type ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
export enum CalendarChannelVisibility {
METADATA = 'METADATA',
@@ -68,292 +52,21 @@ registerEnumType(CalendarChannelContactAutoCreationPolicy, {
name: 'CalendarChannelContactAutoCreationPolicy',
});
@WorkspaceEntity({
standardId: STANDARD_OBJECT_IDS.calendarChannel,
namePlural: 'calendarChannels',
labelSingular: msg`Calendar Channel`,
labelPlural: msg`Calendar Channels`,
description: msg`Calendar Channels`,
icon: STANDARD_OBJECT_ICONS.calendarChannel,
labelIdentifierStandardId: CALENDAR_CHANNEL_STANDARD_FIELD_IDS.handle,
})
@WorkspaceIsSystem()
@WorkspaceIsNotAuditLogged()
export class CalendarChannelWorkspaceEntity extends BaseWorkspaceEntity {
@WorkspaceField({
standardId: CALENDAR_CHANNEL_STANDARD_FIELD_IDS.handle,
type: FieldMetadataType.TEXT,
label: msg`Handle`,
description: msg`Handle`,
icon: 'IconAt',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
handle: string | null;
@WorkspaceField({
standardId: CALENDAR_CHANNEL_STANDARD_FIELD_IDS.syncStatus,
type: FieldMetadataType.SELECT,
label: msg`Sync status`,
description: msg`Sync status`,
icon: 'IconStatusChange',
options: [
{
value: CalendarChannelSyncStatus.ONGOING,
label: 'Ongoing',
position: 1,
color: 'yellow',
},
{
value: CalendarChannelSyncStatus.NOT_SYNCED,
label: 'Not Synced',
position: 2,
color: 'blue',
},
{
value: CalendarChannelSyncStatus.ACTIVE,
label: 'Active',
position: 3,
color: 'green',
},
{
value: CalendarChannelSyncStatus.FAILED_INSUFFICIENT_PERMISSIONS,
label: 'Failed Insufficient Permissions',
position: 4,
color: 'red',
},
{
value: CalendarChannelSyncStatus.FAILED_UNKNOWN,
label: 'Failed Unknown',
position: 5,
color: 'red',
},
],
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
syncStatus: CalendarChannelSyncStatus | null;
@WorkspaceField({
standardId: CALENDAR_CHANNEL_STANDARD_FIELD_IDS.syncStage,
type: FieldMetadataType.SELECT,
label: msg`Sync stage`,
description: msg`Sync stage`,
icon: 'IconStatusChange',
options: [
{
value: CalendarChannelSyncStage.CALENDAR_EVENT_LIST_FETCH_PENDING,
label: 'Calendar event list fetch pending',
position: 0,
color: 'blue',
},
{
value: CalendarChannelSyncStage.CALENDAR_EVENT_LIST_FETCH_SCHEDULED,
label: 'Calendar event list fetch scheduled',
position: 1,
color: 'green',
},
{
value: CalendarChannelSyncStage.CALENDAR_EVENT_LIST_FETCH_ONGOING,
label: 'Calendar event list fetch ongoing',
position: 2,
color: 'orange',
},
{
value: CalendarChannelSyncStage.CALENDAR_EVENTS_IMPORT_PENDING,
label: 'Calendar events import pending',
position: 3,
color: 'blue',
},
{
value: CalendarChannelSyncStage.CALENDAR_EVENTS_IMPORT_SCHEDULED,
label: 'Calendar events import scheduled',
position: 4,
color: 'green',
},
{
value: CalendarChannelSyncStage.CALENDAR_EVENTS_IMPORT_ONGOING,
label: 'Calendar events import ongoing',
position: 5,
color: 'orange',
},
{
value: CalendarChannelSyncStage.FAILED,
label: 'Failed',
position: 6,
color: 'red',
},
{
value: CalendarChannelSyncStage.PENDING_CONFIGURATION,
label: 'Pending configuration',
position: 9,
color: 'gray',
},
],
defaultValue: `'${CalendarChannelSyncStage.PENDING_CONFIGURATION}'`,
})
@WorkspaceIsFieldUIReadOnly()
syncStage: CalendarChannelSyncStage;
@WorkspaceField({
standardId: CALENDAR_CHANNEL_STANDARD_FIELD_IDS.visibility,
type: FieldMetadataType.SELECT,
label: msg`Visibility`,
description: msg`Visibility`,
icon: 'IconEyeglass',
options: [
{
value: CalendarChannelVisibility.METADATA,
label: 'Metadata',
position: 0,
color: 'green',
},
{
value: CalendarChannelVisibility.SHARE_EVERYTHING,
label: 'Share Everything',
position: 1,
color: 'orange',
},
],
defaultValue: `'${CalendarChannelVisibility.SHARE_EVERYTHING}'`,
})
@WorkspaceIsFieldUIReadOnly()
visibility: string;
@WorkspaceField({
standardId:
CALENDAR_CHANNEL_STANDARD_FIELD_IDS.isContactAutoCreationEnabled,
type: FieldMetadataType.BOOLEAN,
label: msg`Is Contact Auto Creation Enabled`,
description: msg`Is Contact Auto Creation Enabled`,
icon: 'IconUserCircle',
defaultValue: true,
})
@WorkspaceIsFieldUIReadOnly()
isContactAutoCreationEnabled: boolean;
@WorkspaceField({
standardId: CALENDAR_CHANNEL_STANDARD_FIELD_IDS.contactAutoCreationPolicy,
type: FieldMetadataType.SELECT,
label: msg`Contact auto creation policy`,
description: msg`Automatically create records for people you participated with in an event.`,
icon: 'IconUserCircle',
options: [
{
value:
CalendarChannelContactAutoCreationPolicy.AS_PARTICIPANT_AND_ORGANIZER,
label: 'As Participant and Organizer',
color: 'green',
position: 0,
},
{
value: CalendarChannelContactAutoCreationPolicy.AS_PARTICIPANT,
label: 'As Participant',
color: 'orange',
position: 1,
},
{
value: CalendarChannelContactAutoCreationPolicy.AS_ORGANIZER,
label: 'As Organizer',
color: 'blue',
position: 2,
},
{
value: CalendarChannelContactAutoCreationPolicy.NONE,
label: 'None',
color: 'red',
position: 3,
},
],
defaultValue: `'${CalendarChannelContactAutoCreationPolicy.AS_PARTICIPANT_AND_ORGANIZER}'`,
})
@WorkspaceIsFieldUIReadOnly()
contactAutoCreationPolicy: CalendarChannelContactAutoCreationPolicy;
@WorkspaceField({
standardId: CALENDAR_CHANNEL_STANDARD_FIELD_IDS.isSyncEnabled,
type: FieldMetadataType.BOOLEAN,
label: msg`Is Sync Enabled`,
description: msg`Is Sync Enabled`,
icon: 'IconRefresh',
defaultValue: true,
})
@WorkspaceIsFieldUIReadOnly()
isSyncEnabled: boolean;
@WorkspaceField({
standardId: CALENDAR_CHANNEL_STANDARD_FIELD_IDS.syncCursor,
type: FieldMetadataType.TEXT,
label: msg`Sync Cursor`,
description: msg`Sync Cursor. Used for syncing events from the calendar provider`,
icon: 'IconReload',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
syncCursor: string | null;
@WorkspaceField({
standardId: CALENDAR_CHANNEL_STANDARD_FIELD_IDS.syncedAt,
type: FieldMetadataType.DATE_TIME,
label: msg`Last sync date`,
description: msg`Last sync date`,
icon: 'IconHistory',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
syncedAt: string | null;
@WorkspaceField({
standardId: CALENDAR_CHANNEL_STANDARD_FIELD_IDS.syncStageStartedAt,
type: FieldMetadataType.DATE_TIME,
label: msg`Sync stage started at`,
description: msg`Sync stage started at`,
icon: 'IconHistory',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
syncStageStartedAt: string | null;
@WorkspaceField({
standardId: CALENDAR_CHANNEL_STANDARD_FIELD_IDS.throttleFailureCount,
type: FieldMetadataType.NUMBER,
label: msg`Throttle Failure Count`,
description: msg`Throttle Failure Count`,
icon: 'IconX',
defaultValue: 0,
})
@WorkspaceIsFieldUIReadOnly()
throttleFailureCount: number;
@WorkspaceRelation({
standardId: CALENDAR_CHANNEL_STANDARD_FIELD_IDS.connectedAccount,
type: RelationType.MANY_TO_ONE,
label: msg`Connected Account`,
description: msg`Connected Account`,
icon: 'IconUserCircle',
inverseSideTarget: () => ConnectedAccountWorkspaceEntity,
inverseSideFieldKey: 'calendarChannels',
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
connectedAccount: Relation<ConnectedAccountWorkspaceEntity>;
@WorkspaceJoinColumn('connectedAccount')
connectedAccount: EntityRelation<ConnectedAccountWorkspaceEntity>;
connectedAccountId: string;
@WorkspaceRelation({
standardId:
CALENDAR_CHANNEL_STANDARD_FIELD_IDS.calendarChannelEventAssociations,
type: RelationType.ONE_TO_MANY,
label: msg`Calendar Channel Event Associations`,
description: msg`Calendar Channel Event Associations`,
icon: 'IconCalendar',
inverseSideTarget: () => CalendarChannelEventAssociationWorkspaceEntity,
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
calendarChannelEventAssociations: Relation<
calendarChannelEventAssociations: EntityRelation<
CalendarChannelEventAssociationWorkspaceEntity[]
>;
}
@@ -1,24 +1,8 @@
import { msg } from '@lingui/core/macro';
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
import { FieldMetadataType, RelationOnDeleteAction } from 'twenty-shared/types';
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator';
import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator';
import { WorkspaceIsFieldUIReadOnly } from 'src/engine/twenty-orm/decorators/workspace-is-field-ui-readonly.decorator';
import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator';
import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator';
import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator';
import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator';
import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator';
import { CALENDAR_EVENT_PARTICIPANT_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons';
import { CalendarEventWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-event.workspace-entity';
import { PersonWorkspaceEntity } from 'src/modules/person/standard-objects/person.workspace-entity';
import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
import { type EntityRelation } from 'src/engine/workspace-manager/workspace-migration/types/entity-relation.interface';
import { type CalendarEventWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-event.workspace-entity';
import { type PersonWorkspaceEntity } from 'src/modules/person/standard-objects/person.workspace-entity';
import { type WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
export enum CalendarEventParticipantResponseStatus {
NEEDS_ACTION = 'NEEDS_ACTION',
@@ -27,137 +11,15 @@ export enum CalendarEventParticipantResponseStatus {
ACCEPTED = 'ACCEPTED',
}
@WorkspaceEntity({
standardId: STANDARD_OBJECT_IDS.calendarEventParticipant,
namePlural: 'calendarEventParticipants',
labelSingular: msg`Calendar event participant`,
labelPlural: msg`Calendar event participants`,
description: msg`Calendar event participants`,
icon: STANDARD_OBJECT_ICONS.calendarEventParticipant,
labelIdentifierStandardId:
CALENDAR_EVENT_PARTICIPANT_STANDARD_FIELD_IDS.handle,
})
@WorkspaceIsSystem()
@WorkspaceIsNotAuditLogged()
export class CalendarEventParticipantWorkspaceEntity extends BaseWorkspaceEntity {
@WorkspaceField({
standardId: CALENDAR_EVENT_PARTICIPANT_STANDARD_FIELD_IDS.handle,
type: FieldMetadataType.TEXT,
label: msg`Handle`,
description: msg`Handle`,
icon: 'IconMail',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
handle: string | null;
@WorkspaceField({
standardId: CALENDAR_EVENT_PARTICIPANT_STANDARD_FIELD_IDS.displayName,
type: FieldMetadataType.TEXT,
label: msg`Display Name`,
description: msg`Display Name`,
icon: 'IconUser',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
displayName: string | null;
@WorkspaceField({
standardId: CALENDAR_EVENT_PARTICIPANT_STANDARD_FIELD_IDS.isOrganizer,
type: FieldMetadataType.BOOLEAN,
label: msg`Is Organizer`,
description: msg`Is Organizer`,
icon: 'IconUser',
defaultValue: false,
})
@WorkspaceIsFieldUIReadOnly()
isOrganizer: boolean;
@WorkspaceField({
standardId: CALENDAR_EVENT_PARTICIPANT_STANDARD_FIELD_IDS.responseStatus,
type: FieldMetadataType.SELECT,
label: msg`Response Status`,
description: msg`Response Status`,
icon: 'IconUser',
options: [
{
value: CalendarEventParticipantResponseStatus.NEEDS_ACTION,
label: 'Needs Action',
position: 0,
color: 'orange',
},
{
value: CalendarEventParticipantResponseStatus.DECLINED,
label: 'Declined',
position: 1,
color: 'red',
},
{
value: CalendarEventParticipantResponseStatus.TENTATIVE,
label: 'Tentative',
position: 2,
color: 'yellow',
},
{
value: CalendarEventParticipantResponseStatus.ACCEPTED,
label: 'Accepted',
position: 3,
color: 'green',
},
],
defaultValue: `'${CalendarEventParticipantResponseStatus.NEEDS_ACTION}'`,
})
@WorkspaceIsFieldUIReadOnly()
responseStatus: string;
@WorkspaceRelation({
standardId: CALENDAR_EVENT_PARTICIPANT_STANDARD_FIELD_IDS.calendarEvent,
type: RelationType.MANY_TO_ONE,
label: msg`Event ID`,
description: msg`Event ID`,
icon: 'IconCalendar',
inverseSideTarget: () => CalendarEventWorkspaceEntity,
inverseSideFieldKey: 'calendarEventParticipants',
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
calendarEvent: Relation<CalendarEventWorkspaceEntity>;
@WorkspaceJoinColumn('calendarEvent')
calendarEvent: EntityRelation<CalendarEventWorkspaceEntity>;
calendarEventId: string;
@WorkspaceRelation({
standardId: CALENDAR_EVENT_PARTICIPANT_STANDARD_FIELD_IDS.person,
type: RelationType.MANY_TO_ONE,
label: msg`Person`,
description: msg`Person`,
icon: 'IconUser',
inverseSideTarget: () => PersonWorkspaceEntity,
inverseSideFieldKey: 'calendarEventParticipants',
onDelete: RelationOnDeleteAction.SET_NULL,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
person: Relation<PersonWorkspaceEntity> | null;
@WorkspaceJoinColumn('person')
person: EntityRelation<PersonWorkspaceEntity> | null;
personId: string | null;
@WorkspaceRelation({
standardId: CALENDAR_EVENT_PARTICIPANT_STANDARD_FIELD_IDS.workspaceMember,
type: RelationType.MANY_TO_ONE,
label: msg`Workspace Member`,
description: msg`Workspace Member`,
icon: 'IconUser',
inverseSideTarget: () => WorkspaceMemberWorkspaceEntity,
inverseSideFieldKey: 'calendarEventParticipants',
onDelete: RelationOnDeleteAction.SET_NULL,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
workspaceMember: Relation<WorkspaceMemberWorkspaceEntity> | null;
@WorkspaceJoinColumn('workspaceMember')
workspaceMember: EntityRelation<WorkspaceMemberWorkspaceEntity> | null;
workspaceMemberId: string | null;
}
@@ -1,198 +1,27 @@
import { msg } from '@lingui/core/macro';
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
import {
FieldMetadataType,
LinksMetadata,
RelationOnDeleteAction,
} from 'twenty-shared/types';
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
import { type LinksMetadata } from 'twenty-shared/types';
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator';
import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator';
import { WorkspaceIsFieldUIReadOnly } from 'src/engine/twenty-orm/decorators/workspace-is-field-ui-readonly.decorator';
import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator';
import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator';
import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator';
import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator';
import { CALENDAR_EVENT_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons';
import { CalendarChannelEventAssociationWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-channel-event-association.workspace-entity';
import { CalendarEventParticipantWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-event-participant.workspace-entity';
import { type EntityRelation } from 'src/engine/workspace-manager/workspace-migration/types/entity-relation.interface';
import { type CalendarChannelEventAssociationWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-channel-event-association.workspace-entity';
import { type CalendarEventParticipantWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-event-participant.workspace-entity';
@WorkspaceEntity({
standardId: STANDARD_OBJECT_IDS.calendarEvent,
namePlural: 'calendarEvents',
labelSingular: msg`Calendar event`,
labelPlural: msg`Calendar events`,
description: msg`Calendar events`,
icon: STANDARD_OBJECT_ICONS.calendarEvent,
labelIdentifierStandardId: CALENDAR_EVENT_STANDARD_FIELD_IDS.title,
})
@WorkspaceIsSystem()
@WorkspaceIsNotAuditLogged()
export class CalendarEventWorkspaceEntity extends BaseWorkspaceEntity {
@WorkspaceField({
standardId: CALENDAR_EVENT_STANDARD_FIELD_IDS.title,
type: FieldMetadataType.TEXT,
label: msg`Title`,
description: msg`Title`,
icon: 'IconH1',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
title: string | null;
@WorkspaceField({
standardId: CALENDAR_EVENT_STANDARD_FIELD_IDS.isCanceled,
type: FieldMetadataType.BOOLEAN,
label: msg`Is canceled`,
description: msg`Is canceled`,
icon: 'IconCalendarCancel',
defaultValue: false,
})
@WorkspaceIsFieldUIReadOnly()
isCanceled: boolean;
@WorkspaceField({
standardId: CALENDAR_EVENT_STANDARD_FIELD_IDS.isFullDay,
type: FieldMetadataType.BOOLEAN,
label: msg`Is Full Day`,
description: msg`Is Full Day`,
icon: 'IconHours24',
defaultValue: false,
})
@WorkspaceIsFieldUIReadOnly()
isFullDay: boolean;
@WorkspaceField({
standardId: CALENDAR_EVENT_STANDARD_FIELD_IDS.startsAt,
type: FieldMetadataType.DATE_TIME,
label: msg`Start Date`,
description: msg`Start Date`,
icon: 'IconCalendarClock',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
startsAt: string | null;
@WorkspaceField({
standardId: CALENDAR_EVENT_STANDARD_FIELD_IDS.endsAt,
type: FieldMetadataType.DATE_TIME,
label: msg`End Date`,
description: msg`End Date`,
icon: 'IconCalendarClock',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
endsAt: string | null;
@WorkspaceField({
standardId: CALENDAR_EVENT_STANDARD_FIELD_IDS.externalCreatedAt,
type: FieldMetadataType.DATE_TIME,
label: msg`Creation DateTime`,
description: msg`Creation DateTime`,
icon: 'IconCalendarPlus',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
externalCreatedAt: string | null;
@WorkspaceField({
standardId: CALENDAR_EVENT_STANDARD_FIELD_IDS.externalUpdatedAt,
type: FieldMetadataType.DATE_TIME,
label: msg`Update DateTime`,
description: msg`Update DateTime`,
icon: 'IconCalendarCog',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
externalUpdatedAt: string | null;
@WorkspaceField({
standardId: CALENDAR_EVENT_STANDARD_FIELD_IDS.description,
type: FieldMetadataType.TEXT,
label: msg`Description`,
description: msg`Description`,
icon: 'IconFileDescription',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
description: string | null;
@WorkspaceField({
standardId: CALENDAR_EVENT_STANDARD_FIELD_IDS.location,
type: FieldMetadataType.TEXT,
label: msg`Location`,
description: msg`Location`,
icon: 'IconMapPin',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
location: string | null;
@WorkspaceField({
standardId: CALENDAR_EVENT_STANDARD_FIELD_IDS.iCalUid,
type: FieldMetadataType.TEXT,
label: msg`iCal UID`,
description: msg`iCal UID`,
icon: 'IconKey',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
iCalUid: string | null;
@WorkspaceField({
standardId: CALENDAR_EVENT_STANDARD_FIELD_IDS.conferenceSolution,
type: FieldMetadataType.TEXT,
label: msg`Conference Solution`,
description: msg`Conference Solution`,
icon: 'IconScreenShare',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
conferenceSolution: string | null;
@WorkspaceField({
standardId: CALENDAR_EVENT_STANDARD_FIELD_IDS.conferenceLink,
type: FieldMetadataType.LINKS,
label: msg`Meet Link`,
description: msg`Meet Link`,
icon: 'IconLink',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
conferenceLink: LinksMetadata;
@WorkspaceRelation({
standardId:
CALENDAR_EVENT_STANDARD_FIELD_IDS.calendarChannelEventAssociations,
type: RelationType.ONE_TO_MANY,
label: msg`Calendar Channel Event Associations`,
description: msg`Calendar Channel Event Associations`,
icon: 'IconCalendar',
inverseSideTarget: () => CalendarChannelEventAssociationWorkspaceEntity,
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
calendarChannelEventAssociations: Relation<
calendarChannelEventAssociations: EntityRelation<
CalendarChannelEventAssociationWorkspaceEntity[]
>;
@WorkspaceRelation({
standardId: CALENDAR_EVENT_STANDARD_FIELD_IDS.calendarEventParticipants,
type: RelationType.ONE_TO_MANY,
label: msg`Event Participants`,
description: msg`Event Participants`,
icon: 'IconUserCircle',
inverseSideTarget: () => CalendarEventParticipantWorkspaceEntity,
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
calendarEventParticipants: Relation<
calendarEventParticipants: EntityRelation<
CalendarEventParticipantWorkspaceEntity[]
>;
}
@@ -1,46 +1,21 @@
import { msg } from '@lingui/core/macro';
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
import {
ActorMetadata,
AddressMetadata,
FieldMetadataType,
LinksMetadata,
RelationOnDeleteAction,
type ActorMetadata,
type AddressMetadata,
type CurrencyMetadata,
type LinksMetadata,
} from 'twenty-shared/types';
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
import { IndexType } from 'src/engine/metadata-modules/index-metadata/types/indexType.types';
import { SEARCH_VECTOR_FIELD } from 'src/engine/metadata-modules/search-field-metadata/constants/search-vector-field.constants';
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
import { WorkspaceDuplicateCriteria } from 'src/engine/twenty-orm/decorators/workspace-duplicate-criteria.decorator';
import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator';
import { WorkspaceFieldIndex } from 'src/engine/twenty-orm/decorators/workspace-field-index.decorator';
import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator';
import { WorkspaceIsDeprecated } from 'src/engine/twenty-orm/decorators/workspace-is-deprecated.decorator';
import { WorkspaceIsFieldUIReadOnly } from 'src/engine/twenty-orm/decorators/workspace-is-field-ui-readonly.decorator';
import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator';
import { WorkspaceIsSearchable } from 'src/engine/twenty-orm/decorators/workspace-is-searchable.decorator';
import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator';
import { WorkspaceIsUnique } from 'src/engine/twenty-orm/decorators/workspace-is-unique.decorator';
import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator';
import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator';
import { COMPANY_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons';
import {
getTsVectorColumnExpressionFromFields,
type FieldTypeAndNameMetadata,
} from 'src/engine/workspace-manager/workspace-sync-metadata/utils/get-ts-vector-column-expression.util';
import { AttachmentWorkspaceEntity } from 'src/modules/attachment/standard-objects/attachment.workspace-entity';
import { FavoriteWorkspaceEntity } from 'src/modules/favorite/standard-objects/favorite.workspace-entity';
import { NoteTargetWorkspaceEntity } from 'src/modules/note/standard-objects/note-target.workspace-entity';
import { OpportunityWorkspaceEntity } from 'src/modules/opportunity/standard-objects/opportunity.workspace-entity';
import { PersonWorkspaceEntity } from 'src/modules/person/standard-objects/person.workspace-entity';
import { TaskTargetWorkspaceEntity } from 'src/modules/task/standard-objects/task-target.workspace-entity';
import { TimelineActivityWorkspaceEntity } from 'src/modules/timeline/standard-objects/timeline-activity.workspace-entity';
import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
import { type FieldTypeAndNameMetadata } from 'src/engine/workspace-manager/utils/get-ts-vector-column-expression.util';
import { type EntityRelation } from 'src/engine/workspace-manager/workspace-migration/types/entity-relation.interface';
import { type AttachmentWorkspaceEntity } from 'src/modules/attachment/standard-objects/attachment.workspace-entity';
import { type FavoriteWorkspaceEntity } from 'src/modules/favorite/standard-objects/favorite.workspace-entity';
import { type NoteTargetWorkspaceEntity } from 'src/modules/note/standard-objects/note-target.workspace-entity';
import { type OpportunityWorkspaceEntity } from 'src/modules/opportunity/standard-objects/opportunity.workspace-entity';
import { type PersonWorkspaceEntity } from 'src/modules/person/standard-objects/person.workspace-entity';
import { type TaskTargetWorkspaceEntity } from 'src/modules/task/standard-objects/task-target.workspace-entity';
import { type TimelineActivityWorkspaceEntity } from 'src/modules/timeline/standard-objects/timeline-activity.workspace-entity';
import { type WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
const NAME_FIELD_NAME = 'name';
const DOMAIN_NAME_FIELD_NAME = 'domainName';
@@ -50,263 +25,37 @@ export const SEARCH_FIELDS_FOR_COMPANY: FieldTypeAndNameMetadata[] = [
{ name: DOMAIN_NAME_FIELD_NAME, type: FieldMetadataType.LINKS },
];
@WorkspaceEntity({
standardId: STANDARD_OBJECT_IDS.company,
namePlural: 'companies',
labelSingular: msg`Company`,
labelPlural: msg`Companies`,
description: msg`A company`,
icon: STANDARD_OBJECT_ICONS.company,
shortcut: 'C',
labelIdentifierStandardId: COMPANY_STANDARD_FIELD_IDS.name,
})
@WorkspaceDuplicateCriteria([['name'], ['domainNamePrimaryLinkUrl']])
@WorkspaceIsSearchable()
export class CompanyWorkspaceEntity extends BaseWorkspaceEntity {
@WorkspaceField({
standardId: COMPANY_STANDARD_FIELD_IDS.name,
type: FieldMetadataType.TEXT,
label: msg`Name`,
description: msg`The company name`,
icon: 'IconBuildingSkyscraper',
})
@WorkspaceIsNullable()
export class CompanyWorkspaceEntity {
// Base fields
id: string;
createdAt: string;
updatedAt: string;
deletedAt: string | null;
// Company-specific fields
name: string | null;
@WorkspaceField({
standardId: COMPANY_STANDARD_FIELD_IDS.domainName,
type: FieldMetadataType.LINKS,
label: msg`Domain Name`,
description: msg`The company website URL. We use this url to fetch the company icon`,
icon: 'IconLink',
settings: {
maxNumberOfValues: 1,
},
})
@WorkspaceIsUnique()
@WorkspaceIsNullable()
domainName: LinksMetadata;
@WorkspaceField({
standardId: COMPANY_STANDARD_FIELD_IDS.employees,
type: FieldMetadataType.NUMBER,
label: msg`Employees`,
description: msg`Number of employees in the company`,
icon: 'IconUsers',
})
@WorkspaceIsNullable()
employees: number | null;
@WorkspaceField({
standardId: COMPANY_STANDARD_FIELD_IDS.linkedinLink,
type: FieldMetadataType.LINKS,
label: msg`Linkedin`,
description: msg`The company Linkedin account`,
icon: 'IconBrandLinkedin',
})
@WorkspaceIsNullable()
linkedinLink: LinksMetadata | null;
@WorkspaceField({
standardId: COMPANY_STANDARD_FIELD_IDS.xLink,
type: FieldMetadataType.LINKS,
label: msg`X`,
description: msg`The company Twitter/X account`,
icon: 'IconBrandX',
})
@WorkspaceIsNullable()
xLink: LinksMetadata | null;
@WorkspaceField({
standardId: COMPANY_STANDARD_FIELD_IDS.annualRecurringRevenue,
type: FieldMetadataType.CURRENCY,
label: msg`ARR`,
description: msg`Annual Recurring Revenue: The actual or estimated annual revenue of the company`,
icon: 'IconMoneybag',
})
@WorkspaceIsNullable()
annualRecurringRevenue: CurrencyMetadata | null;
@WorkspaceField({
standardId: COMPANY_STANDARD_FIELD_IDS.address,
type: FieldMetadataType.ADDRESS,
label: msg`Address`,
description: msg`Address of the company`,
icon: 'IconMap',
})
@WorkspaceIsNullable()
address: AddressMetadata;
@WorkspaceField({
standardId: COMPANY_STANDARD_FIELD_IDS.idealCustomerProfile,
type: FieldMetadataType.BOOLEAN,
label: msg`ICP`,
description: msg`Ideal Customer Profile: Indicates whether the company is the most suitable and valuable customer for you`,
icon: 'IconTarget',
defaultValue: false,
})
idealCustomerProfile: boolean;
@WorkspaceField({
standardId: COMPANY_STANDARD_FIELD_IDS.position,
type: FieldMetadataType.POSITION,
label: msg`Position`,
description: msg`Company record position`,
icon: 'IconHierarchy2',
defaultValue: 0,
})
@WorkspaceIsSystem()
position: number;
@WorkspaceField({
standardId: COMPANY_STANDARD_FIELD_IDS.createdBy,
type: FieldMetadataType.ACTOR,
label: msg`Created by`,
icon: 'IconCreativeCommonsSa',
description: msg`The creator of the record`,
})
@WorkspaceIsFieldUIReadOnly()
createdBy: ActorMetadata;
@WorkspaceField({
standardId: COMPANY_STANDARD_FIELD_IDS.updatedBy,
type: FieldMetadataType.ACTOR,
label: msg`Updated by`,
icon: 'IconUserCircle',
description: msg`The workspace member who last updated the record`,
})
@WorkspaceIsFieldUIReadOnly()
updatedBy: ActorMetadata;
/** @deprecated Use `address` field instead */
addressOld: string | null;
searchVector: string;
// Relations
@WorkspaceRelation({
standardId: COMPANY_STANDARD_FIELD_IDS.people,
type: RelationType.ONE_TO_MANY,
label: msg`People`,
description: msg`People linked to the company.`,
icon: 'IconUsers',
inverseSideTarget: () => PersonWorkspaceEntity,
onDelete: RelationOnDeleteAction.SET_NULL,
})
@WorkspaceIsNullable()
people: Relation<PersonWorkspaceEntity[]>;
@WorkspaceRelation({
standardId: COMPANY_STANDARD_FIELD_IDS.accountOwner,
type: RelationType.MANY_TO_ONE,
label: msg`Account Owner`,
description: msg`Your team member responsible for managing the company account`,
icon: 'IconUserCircle',
inverseSideTarget: () => WorkspaceMemberWorkspaceEntity,
inverseSideFieldKey: 'accountOwnerForCompanies',
onDelete: RelationOnDeleteAction.SET_NULL,
})
@WorkspaceIsNullable()
accountOwner: Relation<WorkspaceMemberWorkspaceEntity> | null;
@WorkspaceJoinColumn('accountOwner')
people: EntityRelation<PersonWorkspaceEntity[]>;
accountOwner: EntityRelation<WorkspaceMemberWorkspaceEntity> | null;
accountOwnerId: string | null;
@WorkspaceRelation({
standardId: COMPANY_STANDARD_FIELD_IDS.taskTargets,
type: RelationType.ONE_TO_MANY,
label: msg`Tasks`,
description: msg`Tasks tied to the company`,
icon: 'IconCheckbox',
inverseSideTarget: () => TaskTargetWorkspaceEntity,
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
taskTargets: Relation<TaskTargetWorkspaceEntity[]>;
@WorkspaceRelation({
standardId: COMPANY_STANDARD_FIELD_IDS.noteTargets,
type: RelationType.ONE_TO_MANY,
label: msg`Notes`,
description: msg`Notes tied to the company`,
icon: 'IconNotes',
inverseSideTarget: () => NoteTargetWorkspaceEntity,
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
noteTargets: Relation<NoteTargetWorkspaceEntity[]>;
@WorkspaceRelation({
standardId: COMPANY_STANDARD_FIELD_IDS.opportunities,
type: RelationType.ONE_TO_MANY,
label: msg`Opportunities`,
description: msg`Opportunities linked to the company.`,
icon: 'IconTargetArrow',
inverseSideTarget: () => OpportunityWorkspaceEntity,
onDelete: RelationOnDeleteAction.SET_NULL,
})
@WorkspaceIsNullable()
opportunities: Relation<OpportunityWorkspaceEntity[]>;
@WorkspaceRelation({
standardId: COMPANY_STANDARD_FIELD_IDS.favorites,
type: RelationType.ONE_TO_MANY,
label: msg`Favorites`,
description: msg`Favorites linked to the company`,
icon: 'IconHeart',
inverseSideTarget: () => FavoriteWorkspaceEntity,
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsNullable()
@WorkspaceIsSystem()
favorites: Relation<FavoriteWorkspaceEntity[]>;
@WorkspaceRelation({
standardId: COMPANY_STANDARD_FIELD_IDS.attachments,
type: RelationType.ONE_TO_MANY,
label: msg`Attachments`,
description: msg`Attachments linked to the company`,
icon: 'IconFileImport',
inverseSideTarget: () => AttachmentWorkspaceEntity,
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsNullable()
@WorkspaceIsSystem()
attachments: Relation<AttachmentWorkspaceEntity[]>;
@WorkspaceRelation({
standardId: COMPANY_STANDARD_FIELD_IDS.timelineActivities,
type: RelationType.ONE_TO_MANY,
label: msg`Timeline Activities`,
description: msg`Timeline Activities linked to the company`,
icon: 'IconIconTimelineEvent',
inverseSideTarget: () => TimelineActivityWorkspaceEntity,
inverseSideFieldKey: 'targetCompany',
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsNullable()
@WorkspaceIsSystem()
timelineActivities: Relation<TimelineActivityWorkspaceEntity[]>;
@WorkspaceField({
standardId: COMPANY_STANDARD_FIELD_IDS.address_deprecated,
type: FieldMetadataType.TEXT,
label: msg`Address (deprecated) `,
description: msg`Address of the company - deprecated in favor of new address field`,
icon: 'IconMap',
})
@WorkspaceIsDeprecated()
@WorkspaceIsNullable()
addressOld: string | null;
@WorkspaceField({
standardId: COMPANY_STANDARD_FIELD_IDS.searchVector,
type: FieldMetadataType.TS_VECTOR,
label: SEARCH_VECTOR_FIELD.label,
description: SEARCH_VECTOR_FIELD.description,
icon: 'IconUser',
generatedType: 'STORED',
asExpression: getTsVectorColumnExpressionFromFields(
SEARCH_FIELDS_FOR_COMPANY,
),
})
@WorkspaceIsNullable()
@WorkspaceIsSystem()
@WorkspaceFieldIndex({ indexType: IndexType.GIN })
searchVector: string;
taskTargets: EntityRelation<TaskTargetWorkspaceEntity[]>;
noteTargets: EntityRelation<NoteTargetWorkspaceEntity[]>;
opportunities: EntityRelation<OpportunityWorkspaceEntity[]>;
favorites: EntityRelation<FavoriteWorkspaceEntity[]>;
attachments: EntityRelation<AttachmentWorkspaceEntity[]>;
timelineActivities: EntityRelation<TimelineActivityWorkspaceEntity[]>;
}
@@ -1,188 +1,25 @@
import { msg } from '@lingui/core/macro';
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
import {
ConnectedAccountProvider,
FieldMetadataType,
RelationOnDeleteAction,
} from 'twenty-shared/types';
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
import { type ConnectedAccountProvider } from 'twenty-shared/types';
import { type ImapSmtpCaldavParams } from 'src/engine/core-modules/imap-smtp-caldav-connection/types/imap-smtp-caldav-connection.type';
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator';
import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator';
import { WorkspaceIsFieldUIReadOnly } from 'src/engine/twenty-orm/decorators/workspace-is-field-ui-readonly.decorator';
import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator';
import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator';
import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator';
import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator';
import { CONNECTED_ACCOUNT_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons';
import { CalendarChannelWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity';
import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
import { type EntityRelation } from 'src/engine/workspace-manager/workspace-migration/types/entity-relation.interface';
import { type CalendarChannelWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-channel.workspace-entity';
import { type MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
import { type WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
@WorkspaceEntity({
standardId: STANDARD_OBJECT_IDS.connectedAccount,
namePlural: 'connectedAccounts',
labelSingular: msg`Connected Account`,
labelPlural: msg`Connected Accounts`,
description: msg`A connected account`,
icon: STANDARD_OBJECT_ICONS.connectedAccount,
labelIdentifierStandardId: CONNECTED_ACCOUNT_STANDARD_FIELD_IDS.handle,
})
@WorkspaceIsSystem()
export class ConnectedAccountWorkspaceEntity extends BaseWorkspaceEntity {
@WorkspaceField({
standardId: CONNECTED_ACCOUNT_STANDARD_FIELD_IDS.handle,
type: FieldMetadataType.TEXT,
label: msg`handle`,
description: msg`The account handle (email, username, phone number, etc.)`,
icon: 'IconMail',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
handle: string | null;
@WorkspaceField({
standardId: CONNECTED_ACCOUNT_STANDARD_FIELD_IDS.provider,
type: FieldMetadataType.TEXT,
label: msg`provider`,
description: msg`The account provider`,
icon: 'IconSettings',
defaultValue: `'${ConnectedAccountProvider.GOOGLE}'`,
})
@WorkspaceIsFieldUIReadOnly()
provider: ConnectedAccountProvider; // field metadata should be a SELECT
@WorkspaceField({
standardId: CONNECTED_ACCOUNT_STANDARD_FIELD_IDS.accessToken,
type: FieldMetadataType.TEXT,
label: msg`Access Token`,
description: msg`Messaging provider access token`,
icon: 'IconKey',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
provider: ConnectedAccountProvider;
accessToken: string | null;
@WorkspaceField({
standardId: CONNECTED_ACCOUNT_STANDARD_FIELD_IDS.refreshToken,
type: FieldMetadataType.TEXT,
label: msg`Refresh Token`,
description: msg`Messaging provider refresh token`,
icon: 'IconKey',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
refreshToken: string | null;
@WorkspaceField({
standardId: CONNECTED_ACCOUNT_STANDARD_FIELD_IDS.lastCredentialsRefreshedAt,
type: FieldMetadataType.DATE_TIME,
label: msg`Last credentials refreshed at`,
description: msg`Last credentials refreshed at`,
icon: 'IconHistory',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
lastCredentialsRefreshedAt: Date | null;
@WorkspaceField({
standardId: CONNECTED_ACCOUNT_STANDARD_FIELD_IDS.lastSyncHistoryId,
type: FieldMetadataType.TEXT,
label: msg`Last sync history ID`,
description: msg`Last sync history ID`,
icon: 'IconHistory',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
lastSyncHistoryId: string | null;
@WorkspaceField({
standardId: CONNECTED_ACCOUNT_STANDARD_FIELD_IDS.authFailedAt,
type: FieldMetadataType.DATE_TIME,
label: msg`Auth failed at`,
description: msg`Auth failed at`,
icon: 'IconX',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
authFailedAt: Date | null;
@WorkspaceField({
standardId: CONNECTED_ACCOUNT_STANDARD_FIELD_IDS.handleAliases,
type: FieldMetadataType.TEXT,
label: msg`Handle Aliases`,
description: msg`Handle Aliases`,
icon: 'IconMail',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
handleAliases: string | null;
@WorkspaceField({
standardId: CONNECTED_ACCOUNT_STANDARD_FIELD_IDS.scopes,
type: FieldMetadataType.ARRAY,
label: msg`Scopes`,
description: msg`Scopes`,
icon: 'IconSettings',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
scopes: string[] | null;
@WorkspaceField({
standardId: CONNECTED_ACCOUNT_STANDARD_FIELD_IDS.connectionParameters,
type: FieldMetadataType.RAW_JSON,
label: msg`Custom Connection Parameters`,
description: msg`JSON object containing custom connection parameters`,
icon: 'IconSettings',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
connectionParameters: ImapSmtpCaldavParams | null;
@WorkspaceRelation({
standardId: CONNECTED_ACCOUNT_STANDARD_FIELD_IDS.accountOwner,
type: RelationType.MANY_TO_ONE,
label: msg`Account Owner`,
description: msg`Account Owner`,
icon: 'IconUserCircle',
inverseSideTarget: () => WorkspaceMemberWorkspaceEntity,
inverseSideFieldKey: 'connectedAccounts',
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
accountOwner: Relation<WorkspaceMemberWorkspaceEntity>;
@WorkspaceJoinColumn('accountOwner')
accountOwner: EntityRelation<WorkspaceMemberWorkspaceEntity>;
accountOwnerId: string;
@WorkspaceRelation({
standardId: CONNECTED_ACCOUNT_STANDARD_FIELD_IDS.messageChannels,
type: RelationType.ONE_TO_MANY,
label: msg`Message Channels`,
description: msg`Message Channels`,
icon: 'IconMessage',
inverseSideTarget: () => MessageChannelWorkspaceEntity,
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
messageChannels: Relation<MessageChannelWorkspaceEntity[]>;
@WorkspaceRelation({
standardId: CONNECTED_ACCOUNT_STANDARD_FIELD_IDS.calendarChannels,
type: RelationType.ONE_TO_MANY,
label: msg`Calendar Channels`,
description: msg`Calendar Channels`,
icon: 'IconCalendar',
inverseSideTarget: () => CalendarChannelWorkspaceEntity,
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
calendarChannels: Relation<CalendarChannelWorkspaceEntity[]>;
messageChannels: EntityRelation<MessageChannelWorkspaceEntity[]>;
calendarChannels: EntityRelation<CalendarChannelWorkspaceEntity[]>;
}
@@ -1,34 +1,11 @@
import { msg } from '@lingui/core/macro';
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
import {
ActorMetadata,
FieldMetadataType,
RelationOnDeleteAction,
} from 'twenty-shared/types';
import { type ActorMetadata, FieldMetadataType } from 'twenty-shared/types';
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
import { IndexType } from 'src/engine/metadata-modules/index-metadata/types/indexType.types';
import { SEARCH_VECTOR_FIELD } from 'src/engine/metadata-modules/search-field-metadata/constants/search-vector-field.constants';
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator';
import { WorkspaceFieldIndex } from 'src/engine/twenty-orm/decorators/workspace-field-index.decorator';
import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator';
import { WorkspaceIsFieldUIReadOnly } from 'src/engine/twenty-orm/decorators/workspace-is-field-ui-readonly.decorator';
import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator';
import { WorkspaceIsSearchable } from 'src/engine/twenty-orm/decorators/workspace-is-searchable.decorator';
import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator';
import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator';
import { DASHBOARD_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons';
import {
type FieldTypeAndNameMetadata,
getTsVectorColumnExpressionFromFields,
} from 'src/engine/workspace-manager/workspace-sync-metadata/utils/get-ts-vector-column-expression.util';
import { AttachmentWorkspaceEntity } from 'src/modules/attachment/standard-objects/attachment.workspace-entity';
import { FavoriteWorkspaceEntity } from 'src/modules/favorite/standard-objects/favorite.workspace-entity';
import { TimelineActivityWorkspaceEntity } from 'src/modules/timeline/standard-objects/timeline-activity.workspace-entity';
import { type FieldTypeAndNameMetadata } from 'src/engine/workspace-manager/utils/get-ts-vector-column-expression.util';
import { type EntityRelation } from 'src/engine/workspace-manager/workspace-migration/types/entity-relation.interface';
import { type AttachmentWorkspaceEntity } from 'src/modules/attachment/standard-objects/attachment.workspace-entity';
import { type FavoriteWorkspaceEntity } from 'src/modules/favorite/standard-objects/favorite.workspace-entity';
import { type TimelineActivityWorkspaceEntity } from 'src/modules/timeline/standard-objects/timeline-activity.workspace-entity';
const TITLE_FIELD_NAME = 'title';
@@ -36,120 +13,14 @@ export const SEARCH_FIELDS_FOR_DASHBOARD: FieldTypeAndNameMetadata[] = [
{ name: TITLE_FIELD_NAME, type: FieldMetadataType.TEXT },
];
@WorkspaceEntity({
standardId: STANDARD_OBJECT_IDS.dashboard,
namePlural: 'dashboards',
labelSingular: msg`Dashboard`,
labelPlural: msg`Dashboards`,
description: msg`A dashboard`,
icon: STANDARD_OBJECT_ICONS.dashboard,
shortcut: 'D',
labelIdentifierStandardId: DASHBOARD_STANDARD_FIELD_IDS.title,
})
@WorkspaceIsSearchable()
export class DashboardWorkspaceEntity extends BaseWorkspaceEntity {
@WorkspaceField({
standardId: DASHBOARD_STANDARD_FIELD_IDS.title,
type: FieldMetadataType.TEXT,
label: msg`Title`,
description: msg`Dashboard title`,
icon: 'IconNotes',
})
@WorkspaceIsNullable()
title: string | null;
@WorkspaceField({
standardId: DASHBOARD_STANDARD_FIELD_IDS.pageLayoutId,
type: FieldMetadataType.UUID,
label: msg`Page Layout ID`,
description: msg`Dashboard page layout`,
icon: 'IconLayout',
})
@WorkspaceIsNullable()
@WorkspaceIsFieldUIReadOnly()
pageLayoutId: string | null;
@WorkspaceField({
standardId: DASHBOARD_STANDARD_FIELD_IDS.position,
type: FieldMetadataType.POSITION,
label: msg`Position`,
description: msg`Dashboard record Position`,
icon: 'IconHierarchy2',
defaultValue: 0,
})
@WorkspaceIsSystem()
position: number;
@WorkspaceField({
standardId: DASHBOARD_STANDARD_FIELD_IDS.createdBy,
type: FieldMetadataType.ACTOR,
label: msg`Created by`,
icon: 'IconCreativeCommonsSa',
description: msg`The creator of the record`,
})
@WorkspaceIsFieldUIReadOnly()
createdBy: ActorMetadata;
@WorkspaceField({
standardId: DASHBOARD_STANDARD_FIELD_IDS.updatedBy,
type: FieldMetadataType.ACTOR,
label: msg`Updated by`,
icon: 'IconUserCircle',
description: msg`The workspace member who last updated the record`,
})
@WorkspaceIsFieldUIReadOnly()
updatedBy: ActorMetadata;
@WorkspaceRelation({
standardId: DASHBOARD_STANDARD_FIELD_IDS.timelineActivities,
type: RelationType.ONE_TO_MANY,
label: msg`Timeline Activities`,
description: msg`Timeline activities linked to the dashboard`,
inverseSideTarget: () => TimelineActivityWorkspaceEntity,
inverseSideFieldKey: 'targetDashboard',
onDelete: RelationOnDeleteAction.SET_NULL,
})
@WorkspaceIsNullable()
@WorkspaceIsSystem()
timelineActivities: Relation<TimelineActivityWorkspaceEntity[]>;
@WorkspaceRelation({
standardId: DASHBOARD_STANDARD_FIELD_IDS.favorites,
type: RelationType.ONE_TO_MANY,
label: msg`Favorites`,
description: msg`Favorites linked to the dashboard`,
inverseSideTarget: () => FavoriteWorkspaceEntity,
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsSystem()
favorites: Relation<FavoriteWorkspaceEntity[]>;
@WorkspaceRelation({
standardId: DASHBOARD_STANDARD_FIELD_IDS.attachments,
type: RelationType.ONE_TO_MANY,
label: msg`Attachments`,
description: msg`Attachments linked to the dashboard`,
inverseSideTarget: () => AttachmentWorkspaceEntity,
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsNullable()
@WorkspaceIsSystem()
attachments: Relation<AttachmentWorkspaceEntity[]>;
@WorkspaceField({
standardId: DASHBOARD_STANDARD_FIELD_IDS.searchVector,
type: FieldMetadataType.TS_VECTOR,
label: SEARCH_VECTOR_FIELD.label,
description: SEARCH_VECTOR_FIELD.description,
icon: 'IconUser',
generatedType: 'STORED',
asExpression: getTsVectorColumnExpressionFromFields(
SEARCH_FIELDS_FOR_DASHBOARD,
),
})
@WorkspaceIsNullable()
@WorkspaceIsSystem()
@WorkspaceFieldIndex({ indexType: IndexType.GIN })
timelineActivities: EntityRelation<TimelineActivityWorkspaceEntity[]>;
favorites: EntityRelation<FavoriteWorkspaceEntity[]>;
attachments: EntityRelation<AttachmentWorkspaceEntity[]>;
searchVector: string;
}
@@ -1,64 +1,9 @@
import { msg } from '@lingui/core/macro';
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
import { FieldMetadataType, RelationOnDeleteAction } from 'twenty-shared/types';
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator';
import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator';
import { WorkspaceIsFieldUIReadOnly } from 'src/engine/twenty-orm/decorators/workspace-is-field-ui-readonly.decorator';
import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator';
import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator';
import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator';
import { FAVORITE_FOLDER_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
import { FavoriteWorkspaceEntity } from 'src/modules/favorite/standard-objects/favorite.workspace-entity';
import { type EntityRelation } from 'src/engine/workspace-manager/workspace-migration/types/entity-relation.interface';
import { type FavoriteWorkspaceEntity } from 'src/modules/favorite/standard-objects/favorite.workspace-entity';
@WorkspaceEntity({
standardId: STANDARD_OBJECT_IDS.favoriteFolder,
namePlural: 'favoriteFolders',
labelSingular: msg`Favorite Folder`,
labelPlural: msg`Favorite Folders`,
description: msg`A Folder of favorites`,
icon: 'IconFolder',
})
@WorkspaceIsSystem()
export class FavoriteFolderWorkspaceEntity extends BaseWorkspaceEntity {
@WorkspaceField({
standardId: FAVORITE_FOLDER_STANDARD_FIELD_IDS.position,
type: FieldMetadataType.NUMBER,
label: msg`Position`,
description: msg`Favorite folder position`,
icon: 'IconList',
defaultValue: 0,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsSystem()
position: number;
@WorkspaceField({
standardId: FAVORITE_FOLDER_STANDARD_FIELD_IDS.name,
type: FieldMetadataType.TEXT,
label: msg`Name`,
description: msg`Name of the favorite folder`,
icon: 'IconText',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
name: string | null;
@WorkspaceRelation({
standardId: FAVORITE_FOLDER_STANDARD_FIELD_IDS.favorites,
type: RelationType.ONE_TO_MANY,
label: msg`Favorites`,
description: msg`Favorites in this folder`,
icon: 'IconHeart',
inverseSideFieldKey: 'favoriteFolder',
inverseSideTarget: () => FavoriteWorkspaceEntity,
onDelete: RelationOnDeleteAction.SET_NULL,
})
@WorkspaceIsFieldUIReadOnly()
favorites: Relation<FavoriteWorkspaceEntity[]>;
favorites: EntityRelation<FavoriteWorkspaceEntity[]>;
}
@@ -1,270 +1,42 @@
import { msg } from '@lingui/core/macro';
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
import { FieldMetadataType, RelationOnDeleteAction } from 'twenty-shared/types';
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
import { CustomWorkspaceEntity } from 'src/engine/twenty-orm/custom.workspace-entity';
import { WorkspaceDynamicRelation } from 'src/engine/twenty-orm/decorators/workspace-dynamic-relation.decorator';
import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator';
import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator';
import { WorkspaceIsFieldUIReadOnly } from 'src/engine/twenty-orm/decorators/workspace-is-field-ui-readonly.decorator';
import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator';
import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator';
import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator';
import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator';
import { FAVORITE_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons';
import { CompanyWorkspaceEntity } from 'src/modules/company/standard-objects/company.workspace-entity';
import { DashboardWorkspaceEntity } from 'src/modules/dashboard/standard-objects/dashboard.workspace-entity';
import { FavoriteFolderWorkspaceEntity } from 'src/modules/favorite-folder/standard-objects/favorite-folder.workspace-entity';
import { NoteWorkspaceEntity } from 'src/modules/note/standard-objects/note.workspace-entity';
import { OpportunityWorkspaceEntity } from 'src/modules/opportunity/standard-objects/opportunity.workspace-entity';
import { PersonWorkspaceEntity } from 'src/modules/person/standard-objects/person.workspace-entity';
import { TaskWorkspaceEntity } from 'src/modules/task/standard-objects/task.workspace-entity';
import { WorkflowRunWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow-run.workspace-entity';
import { WorkflowVersionWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow-version.workspace-entity';
import { WorkflowWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow.workspace-entity';
import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
import { type CustomWorkspaceEntity } from 'src/engine/twenty-orm/custom.workspace-entity';
import { type EntityRelation } from 'src/engine/workspace-manager/workspace-migration/types/entity-relation.interface';
import { type CompanyWorkspaceEntity } from 'src/modules/company/standard-objects/company.workspace-entity';
import { type DashboardWorkspaceEntity } from 'src/modules/dashboard/standard-objects/dashboard.workspace-entity';
import { type FavoriteFolderWorkspaceEntity } from 'src/modules/favorite-folder/standard-objects/favorite-folder.workspace-entity';
import { type NoteWorkspaceEntity } from 'src/modules/note/standard-objects/note.workspace-entity';
import { type OpportunityWorkspaceEntity } from 'src/modules/opportunity/standard-objects/opportunity.workspace-entity';
import { type PersonWorkspaceEntity } from 'src/modules/person/standard-objects/person.workspace-entity';
import { type TaskWorkspaceEntity } from 'src/modules/task/standard-objects/task.workspace-entity';
import { type WorkflowRunWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow-run.workspace-entity';
import { type WorkflowVersionWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow-version.workspace-entity';
import { type WorkflowWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow.workspace-entity';
import { type WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
@WorkspaceEntity({
standardId: STANDARD_OBJECT_IDS.favorite,
namePlural: 'favorites',
labelSingular: msg`Favorite`,
labelPlural: msg`Favorites`,
description: msg`A favorite that can be accessed from the left menu`,
icon: STANDARD_OBJECT_ICONS.favorite,
})
@WorkspaceIsSystem()
export class FavoriteWorkspaceEntity extends BaseWorkspaceEntity {
@WorkspaceField({
standardId: FAVORITE_STANDARD_FIELD_IDS.position,
type: FieldMetadataType.NUMBER,
label: msg`Position`,
description: msg`Favorite position`,
icon: 'IconList',
defaultValue: 0,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsSystem()
position: number;
// Relations
@WorkspaceRelation({
standardId: FAVORITE_STANDARD_FIELD_IDS.forWorkspaceMember,
type: RelationType.MANY_TO_ONE,
label: msg`Workspace Member`,
description: msg`Favorite workspace member`,
icon: 'IconCircleUser',
inverseSideFieldKey: 'favorites',
inverseSideTarget: () => WorkspaceMemberWorkspaceEntity,
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
forWorkspaceMember: Relation<WorkspaceMemberWorkspaceEntity>;
@WorkspaceJoinColumn('forWorkspaceMember')
forWorkspaceMember: EntityRelation<WorkspaceMemberWorkspaceEntity>;
forWorkspaceMemberId: string;
@WorkspaceRelation({
standardId: FAVORITE_STANDARD_FIELD_IDS.person,
type: RelationType.MANY_TO_ONE,
label: msg`Person`,
description: msg`Favorite person`,
icon: 'IconUser',
inverseSideTarget: () => PersonWorkspaceEntity,
inverseSideFieldKey: 'favorites',
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
person: Relation<PersonWorkspaceEntity> | null;
@WorkspaceJoinColumn('person')
person: EntityRelation<PersonWorkspaceEntity> | null;
personId: string;
@WorkspaceRelation({
standardId: FAVORITE_STANDARD_FIELD_IDS.company,
type: RelationType.MANY_TO_ONE,
label: msg`Company`,
description: msg`Favorite company`,
icon: 'IconBuildingSkyscraper',
inverseSideTarget: () => CompanyWorkspaceEntity,
inverseSideFieldKey: 'favorites',
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
company: Relation<CompanyWorkspaceEntity> | null;
@WorkspaceJoinColumn('company')
company: EntityRelation<CompanyWorkspaceEntity> | null;
companyId: string;
@WorkspaceRelation({
standardId: FAVORITE_STANDARD_FIELD_IDS.favoriteFolder,
type: RelationType.MANY_TO_ONE,
label: msg`Favorite Folder`,
description: msg`The folder this favorite belongs to`,
icon: 'IconFolder',
inverseSideTarget: () => FavoriteFolderWorkspaceEntity,
inverseSideFieldKey: 'favorites',
onDelete: RelationOnDeleteAction.SET_NULL,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
favoriteFolder: Relation<FavoriteFolderWorkspaceEntity> | null;
@WorkspaceJoinColumn('favoriteFolder')
favoriteFolder: EntityRelation<FavoriteFolderWorkspaceEntity> | null;
favoriteFolderId: string;
@WorkspaceRelation({
standardId: FAVORITE_STANDARD_FIELD_IDS.opportunity,
type: RelationType.MANY_TO_ONE,
label: msg`Opportunity`,
description: msg`Favorite opportunity`,
icon: 'IconTargetArrow',
inverseSideTarget: () => OpportunityWorkspaceEntity,
inverseSideFieldKey: 'favorites',
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
opportunity: Relation<OpportunityWorkspaceEntity> | null;
@WorkspaceJoinColumn('opportunity')
opportunity: EntityRelation<OpportunityWorkspaceEntity> | null;
opportunityId: string;
@WorkspaceRelation({
standardId: FAVORITE_STANDARD_FIELD_IDS.workflow,
type: RelationType.MANY_TO_ONE,
label: msg`Workflow`,
description: msg`Favorite workflow`,
icon: 'IconSettingsAutomation',
inverseSideTarget: () => WorkflowWorkspaceEntity,
inverseSideFieldKey: 'favorites',
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
workflow: Relation<WorkflowWorkspaceEntity> | null;
@WorkspaceJoinColumn('workflow')
workflow: EntityRelation<WorkflowWorkspaceEntity> | null;
workflowId: string;
@WorkspaceRelation({
standardId: FAVORITE_STANDARD_FIELD_IDS.workflowVersion,
type: RelationType.MANY_TO_ONE,
label: msg`Workflow`,
description: msg`Favorite workflow version`,
icon: 'IconSettingsAutomation',
inverseSideTarget: () => WorkflowVersionWorkspaceEntity,
inverseSideFieldKey: 'favorites',
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
workflowVersion: Relation<WorkflowVersionWorkspaceEntity> | null;
@WorkspaceJoinColumn('workflowVersion')
workflowVersion: EntityRelation<WorkflowVersionWorkspaceEntity> | null;
workflowVersionId: string;
@WorkspaceRelation({
standardId: FAVORITE_STANDARD_FIELD_IDS.workflowRun,
type: RelationType.MANY_TO_ONE,
label: msg`Workflow`,
description: msg`Favorite workflow run`,
icon: 'IconSettingsAutomation',
inverseSideTarget: () => WorkflowRunWorkspaceEntity,
inverseSideFieldKey: 'favorites',
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
workflowRun: Relation<WorkflowRunWorkspaceEntity> | null;
@WorkspaceJoinColumn('workflowRun')
workflowRun: EntityRelation<WorkflowRunWorkspaceEntity> | null;
workflowRunId: string;
@WorkspaceRelation({
standardId: FAVORITE_STANDARD_FIELD_IDS.task,
type: RelationType.MANY_TO_ONE,
label: msg`Task`,
description: msg`Favorite task`,
icon: 'IconCheckbox',
inverseSideTarget: () => TaskWorkspaceEntity,
inverseSideFieldKey: 'favorites',
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
task: Relation<TaskWorkspaceEntity> | null;
@WorkspaceJoinColumn('task')
task: EntityRelation<TaskWorkspaceEntity> | null;
taskId: string;
@WorkspaceRelation({
standardId: FAVORITE_STANDARD_FIELD_IDS.note,
type: RelationType.MANY_TO_ONE,
label: msg`Note`,
description: msg`Favorite note`,
icon: 'IconNotes',
inverseSideTarget: () => NoteWorkspaceEntity,
inverseSideFieldKey: 'favorites',
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
note: Relation<NoteWorkspaceEntity> | null;
@WorkspaceJoinColumn('note')
note: EntityRelation<NoteWorkspaceEntity> | null;
noteId: string;
@WorkspaceRelation({
standardId: FAVORITE_STANDARD_FIELD_IDS.dashboard,
type: RelationType.MANY_TO_ONE,
label: msg`Dashboard`,
description: msg`Favorite dashboard`,
icon: 'IconLayoutDashboard',
inverseSideTarget: () => DashboardWorkspaceEntity,
inverseSideFieldKey: 'favorites',
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
dashboard: Relation<DashboardWorkspaceEntity> | null;
@WorkspaceJoinColumn('dashboard')
dashboard: EntityRelation<DashboardWorkspaceEntity> | null;
dashboardId: string;
@WorkspaceField({
standardId: FAVORITE_STANDARD_FIELD_IDS.view,
type: FieldMetadataType.UUID,
label: msg`ViewId`,
description: msg`ViewId`,
icon: 'IconView',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
viewId: string;
// todo: remove this decorator and the custom field
@WorkspaceDynamicRelation({
type: RelationType.MANY_TO_ONE,
argsFactory: (oppositeObjectMetadata) => ({
standardId: FAVORITE_STANDARD_FIELD_IDS.custom,
name: oppositeObjectMetadata.nameSingular,
label: oppositeObjectMetadata.labelSingular,
description: `Favorite ${oppositeObjectMetadata.labelSingular}`,
joinColumn: `${oppositeObjectMetadata.nameSingular}Id`,
icon: 'IconHeart',
}),
inverseSideTarget: () => CustomWorkspaceEntity,
inverseSideFieldKey: 'favorites',
onDelete: RelationOnDeleteAction.CASCADE,
})
custom: Relation<CustomWorkspaceEntity>;
custom: EntityRelation<CustomWorkspaceEntity>;
}
@@ -1,126 +1,15 @@
import { msg } from '@lingui/core/macro';
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
import { FieldMetadataType, RelationOnDeleteAction } from 'twenty-shared/types';
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { type Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator';
import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator';
import { WorkspaceIndex } from 'src/engine/twenty-orm/decorators/workspace-index.decorator';
import { WorkspaceIsFieldUIReadOnly } from 'src/engine/twenty-orm/decorators/workspace-is-field-ui-readonly.decorator';
import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator';
import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator';
import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator';
import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator';
import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator';
import {
MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_STANDARD_FIELD_IDS,
MESSAGE_STANDARD_FIELD_IDS,
} from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons';
import { MessageDirection } from 'src/modules/messaging/common/enums/message-direction.enum';
import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
import { MessageWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message.workspace-entity';
import { type EntityRelation } from 'src/engine/workspace-manager/workspace-migration/types/entity-relation.interface';
import { type MessageDirection } from 'src/modules/messaging/common/enums/message-direction.enum';
import { type MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
import { type MessageWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message.workspace-entity';
@WorkspaceEntity({
standardId: STANDARD_OBJECT_IDS.messageChannelMessageAssociation,
namePlural: 'messageChannelMessageAssociations',
labelSingular: msg`Message Channel Message Association`,
labelPlural: msg`Message Channel Message Associations`,
description: msg`Message Synced with a Message Channel`,
icon: STANDARD_OBJECT_ICONS.messageChannelMessageAssociation,
})
@WorkspaceIsNotAuditLogged()
@WorkspaceIsSystem()
@WorkspaceIndex(['messageChannelId', 'messageId'], {
isUnique: true,
indexWhereClause: '"deletedAt" IS NULL',
})
export class MessageChannelMessageAssociationWorkspaceEntity extends BaseWorkspaceEntity {
@WorkspaceField({
standardId:
MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_STANDARD_FIELD_IDS.messageExternalId,
type: FieldMetadataType.TEXT,
label: msg`Message External Id`,
description: msg`Message id from the messaging provider`,
icon: 'IconHash',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
messageExternalId: string | null;
@WorkspaceField({
standardId:
MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_STANDARD_FIELD_IDS.messageThreadExternalId,
type: FieldMetadataType.TEXT,
label: msg`Thread External Id`,
description: msg`Thread id from the messaging provider`,
icon: 'IconHash',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
messageThreadExternalId: string | null;
@WorkspaceField({
standardId: MESSAGE_STANDARD_FIELD_IDS.direction,
type: FieldMetadataType.SELECT,
label: msg`Direction`,
description: msg`Message Direction`,
icon: 'IconDirection',
options: [
{
value: MessageDirection.INCOMING,
label: 'Incoming',
position: 0,
color: 'green',
},
{
value: MessageDirection.OUTGOING,
label: 'Outgoing',
position: 1,
color: 'blue',
},
],
defaultValue: `'${MessageDirection.INCOMING}'`,
})
@WorkspaceIsFieldUIReadOnly()
direction: MessageDirection;
@WorkspaceRelation({
standardId:
MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_STANDARD_FIELD_IDS.messageChannel,
type: RelationType.MANY_TO_ONE,
label: msg`Message Channel Id`,
description: msg`Message Channel Id`,
icon: 'IconHash',
inverseSideTarget: () => MessageChannelWorkspaceEntity,
inverseSideFieldKey: 'messageChannelMessageAssociations',
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
messageChannel: Relation<MessageChannelWorkspaceEntity> | null;
@WorkspaceJoinColumn('messageChannel')
messageChannel: EntityRelation<MessageChannelWorkspaceEntity> | null;
messageChannelId: string;
@WorkspaceRelation({
standardId: MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_STANDARD_FIELD_IDS.message,
type: RelationType.MANY_TO_ONE,
label: msg`Message Id`,
description: msg`Message Id`,
icon: 'IconHash',
inverseSideTarget: () => MessageWorkspaceEntity,
inverseSideFieldKey: 'messageChannelMessageAssociations',
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
message: Relation<MessageWorkspaceEntity> | null;
@WorkspaceJoinColumn('message')
message: EntityRelation<MessageWorkspaceEntity> | null;
messageId: string;
}
@@ -1,26 +1,10 @@
import { registerEnumType } from '@nestjs/graphql';
import { msg } from '@lingui/core/macro';
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
import { FieldMetadataType, RelationOnDeleteAction } from 'twenty-shared/types';
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator';
import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator';
import { WorkspaceIsFieldUIReadOnly } from 'src/engine/twenty-orm/decorators/workspace-is-field-ui-readonly.decorator';
import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator';
import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator';
import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator';
import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator';
import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator';
import { MESSAGE_CHANNEL_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons';
import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity';
import { MessageFolderWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-folder.workspace-entity';
import { type EntityRelation } from 'src/engine/workspace-manager/workspace-migration/types/entity-relation.interface';
import { type ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
import { type MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity';
import { type MessageFolderWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-folder.workspace-entity';
export enum MessageChannelSyncStatus {
NOT_SYNCED = 'NOT_SYNCED',
@@ -97,408 +81,27 @@ registerEnumType(MessageChannelPendingGroupEmailsAction, {
name: 'MessageChannelPendingGroupEmailsAction',
});
@WorkspaceEntity({
standardId: STANDARD_OBJECT_IDS.messageChannel,
namePlural: 'messageChannels',
labelSingular: msg`Message Channel`,
labelPlural: msg`Message Channels`,
description: msg`Message Channels`,
icon: STANDARD_OBJECT_ICONS.messageChannel,
labelIdentifierStandardId: MESSAGE_CHANNEL_STANDARD_FIELD_IDS.handle,
})
@WorkspaceIsNotAuditLogged()
@WorkspaceIsSystem()
export class MessageChannelWorkspaceEntity extends BaseWorkspaceEntity {
@WorkspaceField({
standardId: MESSAGE_CHANNEL_STANDARD_FIELD_IDS.visibility,
type: FieldMetadataType.SELECT,
label: msg`Visibility`,
description: msg`Visibility`,
icon: 'IconEyeglass',
options: [
{
value: MessageChannelVisibility.METADATA,
label: 'Metadata',
position: 0,
color: 'green',
},
{
value: MessageChannelVisibility.SUBJECT,
label: 'Subject',
position: 1,
color: 'blue',
},
{
value: MessageChannelVisibility.SHARE_EVERYTHING,
label: 'Share Everything',
position: 2,
color: 'orange',
},
],
defaultValue: `'${MessageChannelVisibility.SHARE_EVERYTHING}'`,
})
@WorkspaceIsFieldUIReadOnly()
visibility: string;
@WorkspaceField({
standardId: MESSAGE_CHANNEL_STANDARD_FIELD_IDS.handle,
type: FieldMetadataType.TEXT,
label: msg`Handle`,
description: msg`Handle`,
icon: 'IconAt',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
handle: string | null;
@WorkspaceField({
standardId: MESSAGE_CHANNEL_STANDARD_FIELD_IDS.type,
type: FieldMetadataType.SELECT,
label: msg`Type`,
description: msg`Channel Type`,
icon: 'IconMessage',
options: [
{
value: MessageChannelType.EMAIL,
label: 'Email',
position: 0,
color: 'green',
},
{
value: MessageChannelType.SMS,
label: 'SMS',
position: 1,
color: 'blue',
},
],
defaultValue: `'${MessageChannelType.EMAIL}'`,
})
@WorkspaceIsFieldUIReadOnly()
type: string;
// TODO: Deprecate this field and migrate data to contactAutoCreationFor
@WorkspaceField({
standardId: MESSAGE_CHANNEL_STANDARD_FIELD_IDS.isContactAutoCreationEnabled,
type: FieldMetadataType.BOOLEAN,
label: msg`Is Contact Auto Creation Enabled`,
description: msg`Is Contact Auto Creation Enabled`,
icon: 'IconUserCircle',
defaultValue: true,
})
@WorkspaceIsFieldUIReadOnly()
isContactAutoCreationEnabled: boolean;
@WorkspaceField({
standardId: MESSAGE_CHANNEL_STANDARD_FIELD_IDS.contactAutoCreationPolicy,
type: FieldMetadataType.SELECT,
label: msg`Contact auto creation policy`,
description: msg`Automatically create People records when receiving or sending emails`,
icon: 'IconUserCircle',
options: [
{
value: MessageChannelContactAutoCreationPolicy.SENT_AND_RECEIVED,
label: 'Sent and Received',
position: 0,
color: 'green',
},
{
value: MessageChannelContactAutoCreationPolicy.SENT,
label: 'Sent',
position: 1,
color: 'blue',
},
{
value: MessageChannelContactAutoCreationPolicy.NONE,
label: 'None',
position: 2,
color: 'red',
},
],
defaultValue: `'${MessageChannelContactAutoCreationPolicy.SENT}'`,
})
@WorkspaceIsFieldUIReadOnly()
contactAutoCreationPolicy: MessageChannelContactAutoCreationPolicy;
@WorkspaceField({
standardId: MESSAGE_CHANNEL_STANDARD_FIELD_IDS.messageFolderImportPolicy,
type: FieldMetadataType.SELECT,
label: msg`Message folder import policy`,
description: msg`Message folder import policy`,
icon: 'IconFolder',
options: [
{
value: MessageFolderImportPolicy.ALL_FOLDERS,
label: 'All folders',
position: 0,
color: 'green',
},
{
value: MessageFolderImportPolicy.SELECTED_FOLDERS,
label: 'Selected folders',
position: 1,
color: 'blue',
},
],
defaultValue: `'${MessageFolderImportPolicy.ALL_FOLDERS}'`,
})
@WorkspaceIsFieldUIReadOnly()
messageFolderImportPolicy: MessageFolderImportPolicy;
@WorkspaceField({
standardId: MESSAGE_CHANNEL_STANDARD_FIELD_IDS.excludeNonProfessionalEmails,
type: FieldMetadataType.BOOLEAN,
label: msg`Exclude non professional emails`,
description: msg`Exclude non professional emails`,
icon: 'IconBriefcase',
defaultValue: true,
})
@WorkspaceIsFieldUIReadOnly()
excludeNonProfessionalEmails: boolean;
@WorkspaceField({
standardId: MESSAGE_CHANNEL_STANDARD_FIELD_IDS.excludeGroupEmails,
type: FieldMetadataType.BOOLEAN,
label: msg`Exclude group emails`,
description: msg`Exclude group emails`,
icon: 'IconUsersGroup',
defaultValue: true,
})
@WorkspaceIsFieldUIReadOnly()
excludeGroupEmails: boolean;
@WorkspaceField({
standardId: MESSAGE_CHANNEL_STANDARD_FIELD_IDS.pendingGroupEmailsAction,
type: FieldMetadataType.SELECT,
label: msg`Pending group emails action`,
description: msg`Pending action for group emails`,
icon: 'IconUsersGroup',
options: [
{
value: MessageChannelPendingGroupEmailsAction.GROUP_EMAILS_DELETION,
label: 'Group emails deletion',
position: 0,
color: 'red',
},
{
value: MessageChannelPendingGroupEmailsAction.GROUP_EMAILS_IMPORT,
label: 'Group emails import',
position: 1,
color: 'green',
},
{
value: MessageChannelPendingGroupEmailsAction.NONE,
label: 'None',
position: 2,
color: 'blue',
},
],
defaultValue: `'${MessageChannelPendingGroupEmailsAction.NONE}'`,
})
@WorkspaceIsFieldUIReadOnly()
pendingGroupEmailsAction: MessageChannelPendingGroupEmailsAction;
@WorkspaceField({
standardId: MESSAGE_CHANNEL_STANDARD_FIELD_IDS.isSyncEnabled,
type: FieldMetadataType.BOOLEAN,
label: msg`Is Sync Enabled`,
description: msg`Is Sync Enabled`,
icon: 'IconRefresh',
defaultValue: true,
})
@WorkspaceIsFieldUIReadOnly()
isSyncEnabled: boolean;
@WorkspaceField({
standardId: MESSAGE_CHANNEL_STANDARD_FIELD_IDS.syncCursor,
type: FieldMetadataType.TEXT,
label: msg`Last sync cursor`,
description: msg`Last sync cursor`,
icon: 'IconHistory',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
syncCursor: string | null;
@WorkspaceField({
standardId: MESSAGE_CHANNEL_STANDARD_FIELD_IDS.syncedAt,
type: FieldMetadataType.DATE_TIME,
label: msg`Last sync date`,
description: msg`Last sync date`,
icon: 'IconHistory',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
syncedAt: string | null;
@WorkspaceField({
standardId: MESSAGE_CHANNEL_STANDARD_FIELD_IDS.syncStatus,
type: FieldMetadataType.SELECT,
label: msg`Sync status`,
description: msg`Sync status`,
icon: 'IconStatusChange',
options: [
{
value: MessageChannelSyncStatus.ONGOING,
label: 'Ongoing',
position: 1,
color: 'yellow',
},
{
value: MessageChannelSyncStatus.NOT_SYNCED,
label: 'Not Synced',
position: 2,
color: 'blue',
},
{
value: MessageChannelSyncStatus.ACTIVE,
label: 'Active',
position: 3,
color: 'green',
},
{
value: MessageChannelSyncStatus.FAILED_INSUFFICIENT_PERMISSIONS,
label: 'Failed Insufficient Permissions',
position: 4,
color: 'red',
},
{
value: MessageChannelSyncStatus.FAILED_UNKNOWN,
label: 'Failed Unknown',
position: 5,
color: 'red',
},
],
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
syncStatus: MessageChannelSyncStatus | null;
@WorkspaceField({
standardId: MESSAGE_CHANNEL_STANDARD_FIELD_IDS.syncStage,
type: FieldMetadataType.SELECT,
label: msg`Sync stage`,
description: msg`Sync stage`,
icon: 'IconStatusChange',
options: [
{
value: MessageChannelSyncStage.MESSAGE_LIST_FETCH_PENDING,
label: 'Messages list fetch pending',
position: 0,
color: 'blue',
},
{
value: MessageChannelSyncStage.MESSAGE_LIST_FETCH_SCHEDULED,
label: 'Messages list fetch scheduled',
position: 1,
color: 'green',
},
{
value: MessageChannelSyncStage.MESSAGE_LIST_FETCH_ONGOING,
label: 'Messages list fetch ongoing',
position: 2,
color: 'orange',
},
{
value: MessageChannelSyncStage.MESSAGES_IMPORT_PENDING,
label: 'Messages import pending',
position: 3,
color: 'blue',
},
{
value: MessageChannelSyncStage.MESSAGES_IMPORT_SCHEDULED,
label: 'Messages import scheduled',
position: 4,
color: 'green',
},
{
value: MessageChannelSyncStage.MESSAGES_IMPORT_ONGOING,
label: 'Messages import ongoing',
position: 5,
color: 'orange',
},
{
value: MessageChannelSyncStage.FAILED,
label: 'Failed',
position: 6,
color: 'red',
},
{
value: MessageChannelSyncStage.PENDING_CONFIGURATION,
label: 'Pending configuration',
position: 7,
color: 'gray',
},
],
defaultValue: `'${MessageChannelSyncStage.PENDING_CONFIGURATION}'`,
})
@WorkspaceIsFieldUIReadOnly()
syncStage: MessageChannelSyncStage;
@WorkspaceField({
standardId: MESSAGE_CHANNEL_STANDARD_FIELD_IDS.syncStageStartedAt,
type: FieldMetadataType.DATE_TIME,
label: msg`Sync stage started at`,
description: msg`Sync stage started at`,
icon: 'IconHistory',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
syncStageStartedAt: string | null;
@WorkspaceField({
standardId: MESSAGE_CHANNEL_STANDARD_FIELD_IDS.throttleFailureCount,
type: FieldMetadataType.NUMBER,
label: msg`Throttle Failure Count`,
description: msg`Throttle Failure Count`,
icon: 'IconX',
defaultValue: 0,
})
@WorkspaceIsFieldUIReadOnly()
throttleFailureCount: number;
@WorkspaceRelation({
standardId: MESSAGE_CHANNEL_STANDARD_FIELD_IDS.connectedAccount,
type: RelationType.MANY_TO_ONE,
label: msg`Connected Account`,
description: msg`Connected Account`,
icon: 'IconUserCircle',
inverseSideTarget: () => ConnectedAccountWorkspaceEntity,
inverseSideFieldKey: 'messageChannels',
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
connectedAccount: Relation<ConnectedAccountWorkspaceEntity>;
@WorkspaceJoinColumn('connectedAccount')
connectedAccount: EntityRelation<ConnectedAccountWorkspaceEntity>;
connectedAccountId: string;
@WorkspaceRelation({
standardId:
MESSAGE_CHANNEL_STANDARD_FIELD_IDS.messageChannelMessageAssociations,
type: RelationType.ONE_TO_MANY,
label: msg`Message Channel Association`,
description: msg`Messages from the channel.`,
icon: 'IconMessage',
inverseSideTarget: () => MessageChannelMessageAssociationWorkspaceEntity,
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
messageChannelMessageAssociations: Relation<
messageChannelMessageAssociations: EntityRelation<
MessageChannelMessageAssociationWorkspaceEntity[]
>;
@WorkspaceRelation({
standardId: MESSAGE_CHANNEL_STANDARD_FIELD_IDS.messageFolders,
type: RelationType.ONE_TO_MANY,
label: msg`Message Folders`,
description: msg`Message Folders`,
icon: 'IconFolder',
inverseSideTarget: () => MessageFolderWorkspaceEntity,
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
messageFolders: Relation<MessageFolderWorkspaceEntity[]>;
messageFolders: EntityRelation<MessageFolderWorkspaceEntity[]>;
}
@@ -1,25 +1,8 @@
import { registerEnumType } from '@nestjs/graphql';
import { msg } from '@lingui/core/macro';
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
import { FieldMetadataType, RelationOnDeleteAction } from 'twenty-shared/types';
import { Relation } from 'typeorm';
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator';
import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator';
import { WorkspaceIndex } from 'src/engine/twenty-orm/decorators/workspace-index.decorator';
import { WorkspaceIsFieldUIReadOnly } from 'src/engine/twenty-orm/decorators/workspace-is-field-ui-readonly.decorator';
import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator';
import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator';
import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator';
import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator';
import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator';
import { MESSAGE_FOLDER_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons';
import { MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
import { type EntityRelation } from 'src/engine/workspace-manager/workspace-migration/types/entity-relation.interface';
import { type MessageChannelWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel.workspace-entity';
export enum MessageFolderPendingSyncAction {
FOLDER_DELETION = 'FOLDER_DELETION',
@@ -30,128 +13,14 @@ registerEnumType(MessageFolderPendingSyncAction, {
name: 'MessageFolderPendingSyncAction',
});
@WorkspaceEntity({
standardId: STANDARD_OBJECT_IDS.messageFolder,
namePlural: 'messageFolders',
labelSingular: msg`Message Folder`,
labelPlural: msg`Message Folders`,
description: msg`Folder for Message Channel`,
icon: STANDARD_OBJECT_ICONS.messageFolder,
})
@WorkspaceIsNotAuditLogged()
@WorkspaceIsSystem()
@WorkspaceIndex(['messageChannelId', 'externalId'], {
isUnique: true,
indexWhereClause: '"deletedAt" IS NULL',
})
export class MessageFolderWorkspaceEntity extends BaseWorkspaceEntity {
@WorkspaceField({
standardId: MESSAGE_FOLDER_STANDARD_FIELD_IDS.name,
type: FieldMetadataType.TEXT,
label: msg`Name`,
description: msg`Folder name`,
icon: 'IconFolder',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
name: string | null;
@WorkspaceRelation({
standardId: MESSAGE_FOLDER_STANDARD_FIELD_IDS.messageChannel,
type: RelationType.MANY_TO_ONE,
label: msg`Message Channel`,
description: msg`Message Channel`,
icon: 'IconMessage',
inverseSideTarget: () => MessageChannelWorkspaceEntity,
inverseSideFieldKey: 'messageFolders',
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
messageChannel: Relation<MessageChannelWorkspaceEntity>;
@WorkspaceField({
standardId: MESSAGE_FOLDER_STANDARD_FIELD_IDS.syncCursor,
type: FieldMetadataType.TEXT,
label: msg`Sync Cursor`,
description: msg`Sync Cursor`,
icon: 'IconHash',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
messageChannel: EntityRelation<MessageChannelWorkspaceEntity>;
syncCursor: string | null;
@WorkspaceField({
standardId: MESSAGE_FOLDER_STANDARD_FIELD_IDS.isSentFolder,
type: FieldMetadataType.BOOLEAN,
label: msg`Is Sent Folder`,
description: msg`Is Sent Folder`,
icon: 'IconCheck',
defaultValue: false,
})
@WorkspaceIsFieldUIReadOnly()
isSentFolder: boolean;
@WorkspaceField({
standardId: MESSAGE_FOLDER_STANDARD_FIELD_IDS.isSynced,
type: FieldMetadataType.BOOLEAN,
label: msg`Is Synced`,
description: msg`Is Synced`,
icon: 'IconCheck',
defaultValue: false,
})
@WorkspaceIsFieldUIReadOnly()
isSynced: boolean;
@WorkspaceField({
standardId: MESSAGE_FOLDER_STANDARD_FIELD_IDS.parentFolderId,
type: FieldMetadataType.TEXT,
label: msg`Parent Folder ID`,
description: msg`Parent Folder ID`,
icon: 'IconFolder',
defaultValue: null,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
parentFolderId: string | null;
@WorkspaceField({
standardId: MESSAGE_FOLDER_STANDARD_FIELD_IDS.externalId,
type: FieldMetadataType.TEXT,
label: msg`External ID`,
description: msg`External ID`,
icon: 'IconHash',
defaultValue: null,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
externalId: string | null;
@WorkspaceField({
standardId: MESSAGE_FOLDER_STANDARD_FIELD_IDS.pendingSyncAction,
type: FieldMetadataType.SELECT,
label: msg`Pending Sync Action`,
description: msg`Pending action for folder sync`,
icon: 'IconReload',
options: [
{
value: MessageFolderPendingSyncAction.FOLDER_DELETION,
label: 'Folder deletion',
position: 0,
color: 'red',
},
{
value: MessageFolderPendingSyncAction.NONE,
label: 'None',
position: 1,
color: 'blue',
},
],
defaultValue: `'${MessageFolderPendingSyncAction.NONE}'`,
})
@WorkspaceIsFieldUIReadOnly()
pendingSyncAction: MessageFolderPendingSyncAction;
@WorkspaceJoinColumn('messageChannel')
messageChannelId: string;
}
@@ -1,148 +1,19 @@
import { msg } from '@lingui/core/macro';
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
import {
FieldMetadataType,
MessageParticipantRole,
RelationOnDeleteAction,
} from 'twenty-shared/types';
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
import { type MessageParticipantRole } from 'twenty-shared/types';
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator';
import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator';
import { WorkspaceIsFieldUIReadOnly } from 'src/engine/twenty-orm/decorators/workspace-is-field-ui-readonly.decorator';
import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator';
import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator';
import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator';
import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator';
import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator';
import { MESSAGE_PARTICIPANT_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons';
import { MessageWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message.workspace-entity';
import { PersonWorkspaceEntity } from 'src/modules/person/standard-objects/person.workspace-entity';
import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
import { type EntityRelation } from 'src/engine/workspace-manager/workspace-migration/types/entity-relation.interface';
import { type MessageWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message.workspace-entity';
import { type PersonWorkspaceEntity } from 'src/modules/person/standard-objects/person.workspace-entity';
import { type WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
@WorkspaceEntity({
standardId: STANDARD_OBJECT_IDS.messageParticipant,
namePlural: 'messageParticipants',
labelSingular: msg`Message Participant`,
labelPlural: msg`Message Participants`,
description: msg`Message Participants`,
icon: STANDARD_OBJECT_ICONS.messageParticipant,
labelIdentifierStandardId: MESSAGE_PARTICIPANT_STANDARD_FIELD_IDS.handle,
})
@WorkspaceIsNotAuditLogged()
@WorkspaceIsSystem()
export class MessageParticipantWorkspaceEntity extends BaseWorkspaceEntity {
@WorkspaceField({
standardId: MESSAGE_PARTICIPANT_STANDARD_FIELD_IDS.role,
type: FieldMetadataType.SELECT,
label: msg`Role`,
description: msg`Role`,
icon: 'IconAt',
options: [
{
value: MessageParticipantRole.FROM,
label: 'From',
position: 0,
color: 'green',
},
{
value: MessageParticipantRole.TO,
label: 'To',
position: 1,
color: 'blue',
},
{
value: MessageParticipantRole.CC,
label: 'Cc',
position: 2,
color: 'orange',
},
{
value: MessageParticipantRole.BCC,
label: 'Bcc',
position: 3,
color: 'red',
},
],
defaultValue: `'${MessageParticipantRole.FROM}'`,
})
@WorkspaceIsFieldUIReadOnly()
role: MessageParticipantRole;
@WorkspaceField({
standardId: MESSAGE_PARTICIPANT_STANDARD_FIELD_IDS.handle,
type: FieldMetadataType.TEXT,
label: msg`Handle`,
description: msg`Handle`,
icon: 'IconAt',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
handle: string | null;
@WorkspaceField({
standardId: MESSAGE_PARTICIPANT_STANDARD_FIELD_IDS.displayName,
type: FieldMetadataType.TEXT,
label: msg`Display Name`,
description: msg`Display Name`,
icon: 'IconUser',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
displayName: string | null;
@WorkspaceRelation({
standardId: MESSAGE_PARTICIPANT_STANDARD_FIELD_IDS.message,
type: RelationType.MANY_TO_ONE,
label: msg`Message`,
description: msg`Message`,
icon: 'IconMessage',
inverseSideTarget: () => MessageWorkspaceEntity,
inverseSideFieldKey: 'messageParticipants',
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
message: Relation<MessageWorkspaceEntity>;
@WorkspaceJoinColumn('message')
message: EntityRelation<MessageWorkspaceEntity>;
messageId: string;
@WorkspaceRelation({
standardId: MESSAGE_PARTICIPANT_STANDARD_FIELD_IDS.person,
type: RelationType.MANY_TO_ONE,
label: msg`Person`,
description: msg`Person`,
icon: 'IconUser',
inverseSideTarget: () => PersonWorkspaceEntity,
inverseSideFieldKey: 'messageParticipants',
onDelete: RelationOnDeleteAction.SET_NULL,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
person: Relation<PersonWorkspaceEntity> | null;
@WorkspaceJoinColumn('person')
person: EntityRelation<PersonWorkspaceEntity> | null;
personId: string | null;
@WorkspaceRelation({
standardId: MESSAGE_PARTICIPANT_STANDARD_FIELD_IDS.workspaceMember,
type: RelationType.MANY_TO_ONE,
label: msg`Workspace Member`,
description: msg`Workspace member`,
icon: 'IconCircleUser',
inverseSideTarget: () => WorkspaceMemberWorkspaceEntity,
inverseSideFieldKey: 'messageParticipants',
onDelete: RelationOnDeleteAction.SET_NULL,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
workspaceMember: Relation<WorkspaceMemberWorkspaceEntity> | null;
@WorkspaceJoinColumn('workspaceMember')
workspaceMember: EntityRelation<WorkspaceMemberWorkspaceEntity> | null;
workspaceMemberId: string | null;
}
@@ -1,43 +1,7 @@
import { msg } from '@lingui/core/macro';
import { RelationOnDeleteAction } from 'twenty-shared/types';
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator';
import { WorkspaceIsFieldUIReadOnly } from 'src/engine/twenty-orm/decorators/workspace-is-field-ui-readonly.decorator';
import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator';
import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator';
import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator';
import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator';
import { MESSAGE_THREAD_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons';
import { MessageWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message.workspace-entity';
import { type EntityRelation } from 'src/engine/workspace-manager/workspace-migration/types/entity-relation.interface';
import { type MessageWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message.workspace-entity';
@WorkspaceEntity({
standardId: STANDARD_OBJECT_IDS.messageThread,
namePlural: 'messageThreads',
labelSingular: msg`Message Thread`,
labelPlural: msg`Message Threads`,
description: msg`A group of related messages (e.g. email thread, chat thread)`,
icon: STANDARD_OBJECT_ICONS.messageThread,
})
@WorkspaceIsNotAuditLogged()
@WorkspaceIsSystem()
export class MessageThreadWorkspaceEntity extends BaseWorkspaceEntity {
@WorkspaceRelation({
standardId: MESSAGE_THREAD_STANDARD_FIELD_IDS.messages,
type: RelationType.ONE_TO_MANY,
label: msg`Messages`,
description: msg`Messages from the thread.`,
icon: 'IconMessage',
inverseSideTarget: () => MessageWorkspaceEntity,
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
messages: Relation<MessageWorkspaceEntity[]>;
messages: EntityRelation<MessageWorkspaceEntity[]>;
}
@@ -1,124 +1,18 @@
import { msg } from '@lingui/core/macro';
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
import { FieldMetadataType, RelationOnDeleteAction } from 'twenty-shared/types';
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator';
import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator';
import { WorkspaceIsFieldUIReadOnly } from 'src/engine/twenty-orm/decorators/workspace-is-field-ui-readonly.decorator';
import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator';
import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator';
import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator';
import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator';
import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator';
import { MESSAGE_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons';
import { MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity';
import { MessageParticipantWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-participant.workspace-entity';
import { MessageThreadWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-thread.workspace-entity';
import { type EntityRelation } from 'src/engine/workspace-manager/workspace-migration/types/entity-relation.interface';
import { type MessageChannelMessageAssociationWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-channel-message-association.workspace-entity';
import { type MessageParticipantWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-participant.workspace-entity';
import { type MessageThreadWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-thread.workspace-entity';
@WorkspaceEntity({
standardId: STANDARD_OBJECT_IDS.message,
namePlural: 'messages',
labelSingular: msg`Message`,
labelPlural: msg`Messages`,
description: msg`A message sent or received through a messaging channel (email, chat, etc.)`,
icon: STANDARD_OBJECT_ICONS.message,
labelIdentifierStandardId: MESSAGE_STANDARD_FIELD_IDS.subject,
})
@WorkspaceIsNotAuditLogged()
@WorkspaceIsSystem()
export class MessageWorkspaceEntity extends BaseWorkspaceEntity {
@WorkspaceField({
standardId: MESSAGE_STANDARD_FIELD_IDS.headerMessageId,
type: FieldMetadataType.TEXT,
label: msg`Header message Id`,
description: msg`Message id from the message header`,
icon: 'IconHash',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
headerMessageId: string | null;
@WorkspaceField({
standardId: MESSAGE_STANDARD_FIELD_IDS.subject,
type: FieldMetadataType.TEXT,
label: msg`Subject`,
description: msg`Subject`,
icon: 'IconMessage',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
subject: string | null;
@WorkspaceField({
standardId: MESSAGE_STANDARD_FIELD_IDS.text,
type: FieldMetadataType.TEXT,
label: msg`Text`,
description: msg`Text`,
icon: 'IconMessage',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
text: string | null;
@WorkspaceField({
standardId: MESSAGE_STANDARD_FIELD_IDS.receivedAt,
type: FieldMetadataType.DATE_TIME,
label: msg`Received At`,
description: msg`The date the message was received`,
icon: 'IconCalendar',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
receivedAt: Date | null;
@WorkspaceRelation({
standardId: MESSAGE_STANDARD_FIELD_IDS.messageThread,
type: RelationType.MANY_TO_ONE,
label: msg`Message Thread Id`,
description: msg`Message Thread Id`,
icon: 'IconHash',
inverseSideTarget: () => MessageThreadWorkspaceEntity,
inverseSideFieldKey: 'messages',
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
messageThread: Relation<MessageThreadWorkspaceEntity> | null;
@WorkspaceJoinColumn('messageThread')
messageThread: EntityRelation<MessageThreadWorkspaceEntity> | null;
messageThreadId: string | null;
@WorkspaceRelation({
standardId: MESSAGE_STANDARD_FIELD_IDS.messageParticipants,
type: RelationType.ONE_TO_MANY,
label: msg`Message Participants`,
description: msg`Message Participants`,
icon: 'IconUserCircle',
inverseSideTarget: () => MessageParticipantWorkspaceEntity,
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
messageParticipants: Relation<MessageParticipantWorkspaceEntity[]>;
@WorkspaceRelation({
standardId: MESSAGE_STANDARD_FIELD_IDS.messageChannelMessageAssociations,
type: RelationType.ONE_TO_MANY,
label: msg`Message Channel Association`,
description: msg`Messages from the channel.`,
icon: 'IconMessage',
inverseSideTarget: () => MessageChannelMessageAssociationWorkspaceEntity,
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
messageChannelMessageAssociations: Relation<
messageParticipants: EntityRelation<MessageParticipantWorkspaceEntity[]>;
messageChannelMessageAssociations: EntityRelation<
MessageChannelMessageAssociationWorkspaceEntity[]
>;
}
@@ -1,119 +1,19 @@
import { msg } from '@lingui/core/macro';
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
import { RelationOnDeleteAction } from 'twenty-shared/types';
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
import { CustomWorkspaceEntity } from 'src/engine/twenty-orm/custom.workspace-entity';
import { WorkspaceDynamicRelation } from 'src/engine/twenty-orm/decorators/workspace-dynamic-relation.decorator';
import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator';
import { WorkspaceIsFieldUIReadOnly } from 'src/engine/twenty-orm/decorators/workspace-is-field-ui-readonly.decorator';
import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator';
import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator';
import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator';
import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator';
import { NOTE_TARGET_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons';
import { CompanyWorkspaceEntity } from 'src/modules/company/standard-objects/company.workspace-entity';
import { NoteWorkspaceEntity } from 'src/modules/note/standard-objects/note.workspace-entity';
import { OpportunityWorkspaceEntity } from 'src/modules/opportunity/standard-objects/opportunity.workspace-entity';
import { PersonWorkspaceEntity } from 'src/modules/person/standard-objects/person.workspace-entity';
import { type CustomWorkspaceEntity } from 'src/engine/twenty-orm/custom.workspace-entity';
import { type EntityRelation } from 'src/engine/workspace-manager/workspace-migration/types/entity-relation.interface';
import { type CompanyWorkspaceEntity } from 'src/modules/company/standard-objects/company.workspace-entity';
import { type NoteWorkspaceEntity } from 'src/modules/note/standard-objects/note.workspace-entity';
import { type OpportunityWorkspaceEntity } from 'src/modules/opportunity/standard-objects/opportunity.workspace-entity';
import { type PersonWorkspaceEntity } from 'src/modules/person/standard-objects/person.workspace-entity';
@WorkspaceEntity({
standardId: STANDARD_OBJECT_IDS.noteTarget,
namePlural: 'noteTargets',
labelSingular: msg`Note Target`,
labelPlural: msg`Note Targets`,
description: msg`A note target`,
icon: STANDARD_OBJECT_ICONS.noteTarget,
})
@WorkspaceIsSystem()
export class NoteTargetWorkspaceEntity extends BaseWorkspaceEntity {
@WorkspaceRelation({
standardId: NOTE_TARGET_STANDARD_FIELD_IDS.note,
type: RelationType.MANY_TO_ONE,
label: msg`Note`,
description: msg`NoteTarget note`,
icon: 'IconNotes',
inverseSideTarget: () => NoteWorkspaceEntity,
inverseSideFieldKey: 'noteTargets',
onDelete: RelationOnDeleteAction.SET_NULL,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
note: Relation<NoteWorkspaceEntity> | null;
@WorkspaceJoinColumn('note')
note: EntityRelation<NoteWorkspaceEntity> | null;
noteId: string | null;
@WorkspaceRelation({
standardId: NOTE_TARGET_STANDARD_FIELD_IDS.person,
type: RelationType.MANY_TO_ONE,
label: msg`Person`,
description: msg`NoteTarget person`,
icon: 'IconUser',
inverseSideTarget: () => PersonWorkspaceEntity,
inverseSideFieldKey: 'noteTargets',
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
person: Relation<PersonWorkspaceEntity> | null;
@WorkspaceJoinColumn('person')
person: EntityRelation<PersonWorkspaceEntity> | null;
personId: string | null;
@WorkspaceRelation({
standardId: NOTE_TARGET_STANDARD_FIELD_IDS.company,
type: RelationType.MANY_TO_ONE,
label: msg`Company`,
description: msg`NoteTarget company`,
icon: 'IconBuildingSkyscraper',
inverseSideTarget: () => CompanyWorkspaceEntity,
inverseSideFieldKey: 'noteTargets',
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
company: Relation<CompanyWorkspaceEntity> | null;
@WorkspaceJoinColumn('company')
company: EntityRelation<CompanyWorkspaceEntity> | null;
companyId: string | null;
@WorkspaceRelation({
standardId: NOTE_TARGET_STANDARD_FIELD_IDS.opportunity,
type: RelationType.MANY_TO_ONE,
label: msg`Opportunity`,
description: msg`NoteTarget opportunity`,
icon: 'IconTargetArrow',
inverseSideTarget: () => OpportunityWorkspaceEntity,
inverseSideFieldKey: 'noteTargets',
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
opportunity: Relation<OpportunityWorkspaceEntity> | null;
@WorkspaceJoinColumn('opportunity')
opportunity: EntityRelation<OpportunityWorkspaceEntity> | null;
opportunityId: string | null;
// todo: remove this decorator and the custom field
@WorkspaceDynamicRelation({
type: RelationType.MANY_TO_ONE,
argsFactory: (oppositeObjectMetadata) => ({
standardId: NOTE_TARGET_STANDARD_FIELD_IDS.custom,
name: oppositeObjectMetadata.nameSingular,
label: oppositeObjectMetadata.labelSingular,
description: `NoteTarget ${oppositeObjectMetadata.labelSingular}`,
joinColumn: `${oppositeObjectMetadata.nameSingular}Id`,
icon: 'IconBuildingSkyscraper',
}),
inverseSideTarget: () => CustomWorkspaceEntity,
inverseSideFieldKey: 'noteTargets',
onDelete: RelationOnDeleteAction.CASCADE,
})
custom: Relation<CustomWorkspaceEntity>;
custom: EntityRelation<CustomWorkspaceEntity>;
}
@@ -1,36 +1,16 @@
import { msg } from '@lingui/core/macro';
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
import {
ActorMetadata,
type ActorMetadata,
FieldMetadataType,
RelationOnDeleteAction,
type RichTextV2Metadata,
} from 'twenty-shared/types';
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
import { IndexType } from 'src/engine/metadata-modules/index-metadata/types/indexType.types';
import { SEARCH_VECTOR_FIELD } from 'src/engine/metadata-modules/search-field-metadata/constants/search-vector-field.constants';
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator';
import { WorkspaceFieldIndex } from 'src/engine/twenty-orm/decorators/workspace-field-index.decorator';
import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator';
import { WorkspaceIsFieldUIReadOnly } from 'src/engine/twenty-orm/decorators/workspace-is-field-ui-readonly.decorator';
import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator';
import { WorkspaceIsSearchable } from 'src/engine/twenty-orm/decorators/workspace-is-searchable.decorator';
import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator';
import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator';
import { NOTE_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons';
import {
type FieldTypeAndNameMetadata,
getTsVectorColumnExpressionFromFields,
} from 'src/engine/workspace-manager/workspace-sync-metadata/utils/get-ts-vector-column-expression.util';
import { AttachmentWorkspaceEntity } from 'src/modules/attachment/standard-objects/attachment.workspace-entity';
import { FavoriteWorkspaceEntity } from 'src/modules/favorite/standard-objects/favorite.workspace-entity';
import { NoteTargetWorkspaceEntity } from 'src/modules/note/standard-objects/note-target.workspace-entity';
import { TimelineActivityWorkspaceEntity } from 'src/modules/timeline/standard-objects/timeline-activity.workspace-entity';
import { type FieldTypeAndNameMetadata } from 'src/engine/workspace-manager/utils/get-ts-vector-column-expression.util';
import { type EntityRelation } from 'src/engine/workspace-manager/workspace-migration/types/entity-relation.interface';
import { type AttachmentWorkspaceEntity } from 'src/modules/attachment/standard-objects/attachment.workspace-entity';
import { type FavoriteWorkspaceEntity } from 'src/modules/favorite/standard-objects/favorite.workspace-entity';
import { type NoteTargetWorkspaceEntity } from 'src/modules/note/standard-objects/note-target.workspace-entity';
import { type TimelineActivityWorkspaceEntity } from 'src/modules/timeline/standard-objects/timeline-activity.workspace-entity';
const TITLE_FIELD_NAME = 'title';
const BODY_V2_FIELD_NAME = 'bodyV2';
@@ -40,135 +20,15 @@ export const SEARCH_FIELDS_FOR_NOTES: FieldTypeAndNameMetadata[] = [
{ name: BODY_V2_FIELD_NAME, type: FieldMetadataType.RICH_TEXT_V2 },
];
@WorkspaceEntity({
standardId: STANDARD_OBJECT_IDS.note,
namePlural: 'notes',
labelSingular: msg`Note`,
labelPlural: msg`Notes`,
description: msg`A note`,
icon: STANDARD_OBJECT_ICONS.note,
shortcut: 'N',
labelIdentifierStandardId: NOTE_STANDARD_FIELD_IDS.title,
})
@WorkspaceIsSearchable()
export class NoteWorkspaceEntity extends BaseWorkspaceEntity {
@WorkspaceField({
standardId: NOTE_STANDARD_FIELD_IDS.position,
type: FieldMetadataType.POSITION,
label: msg`Position`,
description: msg`Note record position`,
icon: 'IconHierarchy2',
defaultValue: 0,
})
@WorkspaceIsSystem()
position: number;
@WorkspaceField({
standardId: NOTE_STANDARD_FIELD_IDS.title,
type: FieldMetadataType.TEXT,
label: msg`Title`,
description: msg`Note title`,
icon: 'IconNotes',
})
@WorkspaceIsNullable()
title: string;
@WorkspaceField({
standardId: NOTE_STANDARD_FIELD_IDS.bodyV2,
type: FieldMetadataType.RICH_TEXT_V2,
label: msg`Body`,
description: msg`Note body`,
icon: 'IconFilePencil',
})
@WorkspaceIsNullable()
bodyV2: RichTextV2Metadata | null;
@WorkspaceField({
standardId: NOTE_STANDARD_FIELD_IDS.createdBy,
type: FieldMetadataType.ACTOR,
label: msg`Created by`,
icon: 'IconCreativeCommonsSa',
description: msg`The creator of the record`,
})
@WorkspaceIsFieldUIReadOnly()
createdBy: ActorMetadata;
@WorkspaceField({
standardId: NOTE_STANDARD_FIELD_IDS.updatedBy,
type: FieldMetadataType.ACTOR,
label: msg`Updated by`,
icon: 'IconUserCircle',
description: msg`The workspace member who last updated the record`,
})
@WorkspaceIsFieldUIReadOnly()
updatedBy: ActorMetadata;
@WorkspaceRelation({
standardId: NOTE_STANDARD_FIELD_IDS.noteTargets,
label: msg`Relations`,
description: msg`Note targets`,
icon: 'IconArrowUpRight',
type: RelationType.ONE_TO_MANY,
inverseSideTarget: () => NoteTargetWorkspaceEntity,
onDelete: RelationOnDeleteAction.SET_NULL,
})
@WorkspaceIsNullable()
@WorkspaceIsSystem()
noteTargets: Relation<NoteTargetWorkspaceEntity[]>;
@WorkspaceRelation({
standardId: NOTE_STANDARD_FIELD_IDS.attachments,
label: msg`Attachments`,
description: msg`Note attachments`,
icon: 'IconFileImport',
type: RelationType.ONE_TO_MANY,
inverseSideTarget: () => AttachmentWorkspaceEntity,
onDelete: RelationOnDeleteAction.SET_NULL,
})
@WorkspaceIsNullable()
@WorkspaceIsSystem()
attachments: Relation<AttachmentWorkspaceEntity[]>;
@WorkspaceRelation({
standardId: NOTE_STANDARD_FIELD_IDS.timelineActivities,
type: RelationType.ONE_TO_MANY,
label: msg`Timeline Activities`,
description: msg`Timeline Activities linked to the note.`,
icon: 'IconTimelineEvent',
inverseSideTarget: () => TimelineActivityWorkspaceEntity,
inverseSideFieldKey: 'targetNote',
onDelete: RelationOnDeleteAction.SET_NULL,
})
@WorkspaceIsNullable()
@WorkspaceIsSystem()
timelineActivities: Relation<TimelineActivityWorkspaceEntity[]>;
@WorkspaceRelation({
standardId: NOTE_STANDARD_FIELD_IDS.favorites,
type: RelationType.ONE_TO_MANY,
label: msg`Favorites`,
description: msg`Favorites linked to the note`,
icon: 'IconHeart',
inverseSideTarget: () => FavoriteWorkspaceEntity,
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsSystem()
favorites: Relation<FavoriteWorkspaceEntity[]>;
@WorkspaceField({
standardId: NOTE_STANDARD_FIELD_IDS.searchVector,
type: FieldMetadataType.TS_VECTOR,
label: SEARCH_VECTOR_FIELD.label,
description: SEARCH_VECTOR_FIELD.description,
icon: 'IconUser',
generatedType: 'STORED',
asExpression: getTsVectorColumnExpressionFromFields(
SEARCH_FIELDS_FOR_NOTES,
),
})
@WorkspaceIsNullable()
@WorkspaceIsSystem()
@WorkspaceFieldIndex({ indexType: IndexType.GIN })
noteTargets: EntityRelation<NoteTargetWorkspaceEntity[]>;
attachments: EntityRelation<AttachmentWorkspaceEntity[]>;
timelineActivities: EntityRelation<TimelineActivityWorkspaceEntity[]>;
favorites: EntityRelation<FavoriteWorkspaceEntity[]>;
searchVector: string;
}
@@ -1,41 +1,19 @@
import { msg } from '@lingui/core/macro';
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
import {
ActorMetadata,
type ActorMetadata,
type CurrencyMetadata,
FieldMetadataType,
RelationOnDeleteAction,
} from 'twenty-shared/types';
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
import { IndexType } from 'src/engine/metadata-modules/index-metadata/types/indexType.types';
import { SEARCH_VECTOR_FIELD } from 'src/engine/metadata-modules/search-field-metadata/constants/search-vector-field.constants';
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator';
import { WorkspaceFieldIndex } from 'src/engine/twenty-orm/decorators/workspace-field-index.decorator';
import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator';
import { WorkspaceIsDeprecated } from 'src/engine/twenty-orm/decorators/workspace-is-deprecated.decorator';
import { WorkspaceIsFieldUIReadOnly } from 'src/engine/twenty-orm/decorators/workspace-is-field-ui-readonly.decorator';
import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator';
import { WorkspaceIsSearchable } from 'src/engine/twenty-orm/decorators/workspace-is-searchable.decorator';
import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator';
import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator';
import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator';
import { OPPORTUNITY_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons';
import {
type FieldTypeAndNameMetadata,
getTsVectorColumnExpressionFromFields,
} from 'src/engine/workspace-manager/workspace-sync-metadata/utils/get-ts-vector-column-expression.util';
import { AttachmentWorkspaceEntity } from 'src/modules/attachment/standard-objects/attachment.workspace-entity';
import { CompanyWorkspaceEntity } from 'src/modules/company/standard-objects/company.workspace-entity';
import { FavoriteWorkspaceEntity } from 'src/modules/favorite/standard-objects/favorite.workspace-entity';
import { NoteTargetWorkspaceEntity } from 'src/modules/note/standard-objects/note-target.workspace-entity';
import { PersonWorkspaceEntity } from 'src/modules/person/standard-objects/person.workspace-entity';
import { TaskTargetWorkspaceEntity } from 'src/modules/task/standard-objects/task-target.workspace-entity';
import { TimelineActivityWorkspaceEntity } from 'src/modules/timeline/standard-objects/timeline-activity.workspace-entity';
import { type FieldTypeAndNameMetadata } from 'src/engine/workspace-manager/utils/get-ts-vector-column-expression.util';
import { type EntityRelation } from 'src/engine/workspace-manager/workspace-migration/types/entity-relation.interface';
import { type AttachmentWorkspaceEntity } from 'src/modules/attachment/standard-objects/attachment.workspace-entity';
import { type CompanyWorkspaceEntity } from 'src/modules/company/standard-objects/company.workspace-entity';
import { type FavoriteWorkspaceEntity } from 'src/modules/favorite/standard-objects/favorite.workspace-entity';
import { type NoteTargetWorkspaceEntity } from 'src/modules/note/standard-objects/note-target.workspace-entity';
import { type PersonWorkspaceEntity } from 'src/modules/person/standard-objects/person.workspace-entity';
import { type TaskTargetWorkspaceEntity } from 'src/modules/task/standard-objects/task-target.workspace-entity';
import { type TimelineActivityWorkspaceEntity } from 'src/modules/timeline/standard-objects/timeline-activity.workspace-entity';
const NAME_FIELD_NAME = 'name';
@@ -43,223 +21,24 @@ export const SEARCH_FIELDS_FOR_OPPORTUNITY: FieldTypeAndNameMetadata[] = [
{ name: NAME_FIELD_NAME, type: FieldMetadataType.TEXT },
];
@WorkspaceEntity({
standardId: STANDARD_OBJECT_IDS.opportunity,
namePlural: 'opportunities',
labelSingular: msg`Opportunity`,
labelPlural: msg`Opportunities`,
description: msg`An opportunity`,
icon: STANDARD_OBJECT_ICONS.opportunity,
shortcut: 'O',
labelIdentifierStandardId: OPPORTUNITY_STANDARD_FIELD_IDS.name,
})
@WorkspaceIsSearchable()
export class OpportunityWorkspaceEntity extends BaseWorkspaceEntity {
@WorkspaceField({
standardId: OPPORTUNITY_STANDARD_FIELD_IDS.name,
type: FieldMetadataType.TEXT,
label: msg`Name`,
description: msg`The opportunity name`,
icon: 'IconTargetArrow',
})
@WorkspaceIsNullable()
name: string;
@WorkspaceField({
standardId: OPPORTUNITY_STANDARD_FIELD_IDS.amount,
type: FieldMetadataType.CURRENCY,
label: msg`Amount`,
description: msg`Opportunity amount`,
icon: 'IconCurrencyDollar',
})
@WorkspaceIsNullable()
amount: CurrencyMetadata | null;
@WorkspaceField({
standardId: OPPORTUNITY_STANDARD_FIELD_IDS.closeDate,
type: FieldMetadataType.DATE_TIME,
label: msg`Close date`,
description: msg`Opportunity close date`,
icon: 'IconCalendarEvent',
})
@WorkspaceIsNullable()
closeDate: Date | null;
@WorkspaceField({
standardId: OPPORTUNITY_STANDARD_FIELD_IDS.stage,
type: FieldMetadataType.SELECT,
label: msg`Stage`,
description: msg`Opportunity stage`,
icon: 'IconProgressCheck',
options: [
{ value: 'NEW', label: 'New', position: 0, color: 'red' },
{ value: 'SCREENING', label: 'Screening', position: 1, color: 'purple' },
{ value: 'MEETING', label: 'Meeting', position: 2, color: 'sky' },
{
value: 'PROPOSAL',
label: 'Proposal',
position: 3,
color: 'turquoise',
},
{ value: 'CUSTOMER', label: 'Customer', position: 4, color: 'yellow' },
],
defaultValue: "'NEW'",
})
@WorkspaceFieldIndex()
stage: string;
@WorkspaceField({
standardId: OPPORTUNITY_STANDARD_FIELD_IDS.position,
type: FieldMetadataType.POSITION,
label: msg`Position`,
description: msg`Opportunity record position`,
icon: 'IconHierarchy2',
defaultValue: 0,
})
@WorkspaceIsSystem()
position: number;
@WorkspaceField({
standardId: OPPORTUNITY_STANDARD_FIELD_IDS.createdBy,
type: FieldMetadataType.ACTOR,
label: msg`Created by`,
icon: 'IconCreativeCommonsSa',
description: msg`The creator of the record`,
})
@WorkspaceIsFieldUIReadOnly()
createdBy: ActorMetadata;
@WorkspaceField({
standardId: OPPORTUNITY_STANDARD_FIELD_IDS.updatedBy,
type: FieldMetadataType.ACTOR,
label: msg`Updated by`,
icon: 'IconUserCircle',
description: msg`The workspace member who last updated the record`,
})
@WorkspaceIsFieldUIReadOnly()
updatedBy: ActorMetadata;
@WorkspaceRelation({
standardId: OPPORTUNITY_STANDARD_FIELD_IDS.pointOfContact,
type: RelationType.MANY_TO_ONE,
label: msg`Point of Contact`,
description: msg`Opportunity point of contact`,
icon: 'IconUser',
inverseSideTarget: () => PersonWorkspaceEntity,
inverseSideFieldKey: 'pointOfContactForOpportunities',
onDelete: RelationOnDeleteAction.SET_NULL,
})
@WorkspaceIsNullable()
pointOfContact: Relation<PersonWorkspaceEntity> | null;
@WorkspaceJoinColumn('pointOfContact')
pointOfContact: EntityRelation<PersonWorkspaceEntity> | null;
pointOfContactId: string | null;
@WorkspaceRelation({
standardId: OPPORTUNITY_STANDARD_FIELD_IDS.company,
type: RelationType.MANY_TO_ONE,
label: msg`Company`,
description: msg`Opportunity company`,
icon: 'IconBuildingSkyscraper',
inverseSideTarget: () => CompanyWorkspaceEntity,
inverseSideFieldKey: 'opportunities',
onDelete: RelationOnDeleteAction.SET_NULL,
})
@WorkspaceIsNullable()
company: Relation<CompanyWorkspaceEntity> | null;
@WorkspaceJoinColumn('company')
company: EntityRelation<CompanyWorkspaceEntity> | null;
companyId: string | null;
@WorkspaceRelation({
standardId: OPPORTUNITY_STANDARD_FIELD_IDS.favorites,
type: RelationType.ONE_TO_MANY,
label: msg`Favorites`,
description: msg`Favorites linked to the opportunity`,
icon: 'IconHeart',
inverseSideTarget: () => FavoriteWorkspaceEntity,
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsNullable()
@WorkspaceIsSystem()
favorites: Relation<FavoriteWorkspaceEntity[]>;
@WorkspaceRelation({
standardId: OPPORTUNITY_STANDARD_FIELD_IDS.taskTargets,
type: RelationType.ONE_TO_MANY,
label: msg`Tasks`,
description: msg`Tasks tied to the opportunity`,
icon: 'IconCheckbox',
inverseSideTarget: () => TaskTargetWorkspaceEntity,
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
taskTargets: Relation<TaskTargetWorkspaceEntity[]>;
@WorkspaceRelation({
standardId: OPPORTUNITY_STANDARD_FIELD_IDS.noteTargets,
type: RelationType.ONE_TO_MANY,
label: msg`Notes`,
description: msg`Notes tied to the opportunity`,
icon: 'IconNotes',
inverseSideTarget: () => NoteTargetWorkspaceEntity,
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
noteTargets: Relation<NoteTargetWorkspaceEntity[]>;
@WorkspaceRelation({
standardId: OPPORTUNITY_STANDARD_FIELD_IDS.attachments,
type: RelationType.ONE_TO_MANY,
label: msg`Attachments`,
description: msg`Attachments linked to the opportunity`,
icon: 'IconFileImport',
inverseSideTarget: () => AttachmentWorkspaceEntity,
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsNullable()
@WorkspaceIsSystem()
attachments: Relation<AttachmentWorkspaceEntity[]>;
@WorkspaceRelation({
standardId: OPPORTUNITY_STANDARD_FIELD_IDS.timelineActivities,
type: RelationType.ONE_TO_MANY,
label: msg`Timeline Activities`,
description: msg`Timeline Activities linked to the opportunity.`,
icon: 'IconTimelineEvent',
inverseSideTarget: () => TimelineActivityWorkspaceEntity,
inverseSideFieldKey: 'targetOpportunity',
onDelete: RelationOnDeleteAction.SET_NULL,
})
@WorkspaceIsNullable()
@WorkspaceIsSystem()
timelineActivities: Relation<TimelineActivityWorkspaceEntity[]>;
@WorkspaceField({
standardId: OPPORTUNITY_STANDARD_FIELD_IDS.probabilityDeprecated,
type: FieldMetadataType.TEXT,
label: msg`Probability`,
description: msg`Opportunity probability`,
icon: 'IconProgressCheck',
defaultValue: "'0'",
})
@WorkspaceIsDeprecated()
favorites: EntityRelation<FavoriteWorkspaceEntity[]>;
taskTargets: EntityRelation<TaskTargetWorkspaceEntity[]>;
noteTargets: EntityRelation<NoteTargetWorkspaceEntity[]>;
attachments: EntityRelation<AttachmentWorkspaceEntity[]>;
timelineActivities: EntityRelation<TimelineActivityWorkspaceEntity[]>;
/** @deprecated */
probability: string;
@WorkspaceField({
standardId: OPPORTUNITY_STANDARD_FIELD_IDS.searchVector,
type: FieldMetadataType.TS_VECTOR,
label: SEARCH_VECTOR_FIELD.label,
description: SEARCH_VECTOR_FIELD.description,
icon: 'IconUser',
generatedType: 'STORED',
asExpression: getTsVectorColumnExpressionFromFields(
SEARCH_FIELDS_FOR_OPPORTUNITY,
),
})
@WorkspaceIsNullable()
@WorkspaceIsSystem()
@WorkspaceFieldIndex({ indexType: IndexType.GIN })
searchVector: string;
}
@@ -1,48 +1,24 @@
import { msg } from '@lingui/core/macro';
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
import {
ActorMetadata,
EmailsMetadata,
type ActorMetadata,
type EmailsMetadata,
FieldMetadataType,
PhonesMetadata,
RelationOnDeleteAction,
type FullNameMetadata,
type LinksMetadata,
type PhonesMetadata,
} from 'twenty-shared/types';
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
import { IndexType } from 'src/engine/metadata-modules/index-metadata/types/indexType.types';
import { SEARCH_VECTOR_FIELD } from 'src/engine/metadata-modules/search-field-metadata/constants/search-vector-field.constants';
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
import { WorkspaceDuplicateCriteria } from 'src/engine/twenty-orm/decorators/workspace-duplicate-criteria.decorator';
import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator';
import { WorkspaceFieldIndex } from 'src/engine/twenty-orm/decorators/workspace-field-index.decorator';
import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator';
import { WorkspaceIsDeprecated } from 'src/engine/twenty-orm/decorators/workspace-is-deprecated.decorator';
import { WorkspaceIsFieldUIReadOnly } from 'src/engine/twenty-orm/decorators/workspace-is-field-ui-readonly.decorator';
import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator';
import { WorkspaceIsSearchable } from 'src/engine/twenty-orm/decorators/workspace-is-searchable.decorator';
import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator';
import { WorkspaceIsUnique } from 'src/engine/twenty-orm/decorators/workspace-is-unique.decorator';
import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator';
import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator';
import { PERSON_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons';
import {
getTsVectorColumnExpressionFromFields,
type FieldTypeAndNameMetadata,
} from 'src/engine/workspace-manager/workspace-sync-metadata/utils/get-ts-vector-column-expression.util';
import { AttachmentWorkspaceEntity } from 'src/modules/attachment/standard-objects/attachment.workspace-entity';
import { CalendarEventParticipantWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-event-participant.workspace-entity';
import { CompanyWorkspaceEntity } from 'src/modules/company/standard-objects/company.workspace-entity';
import { FavoriteWorkspaceEntity } from 'src/modules/favorite/standard-objects/favorite.workspace-entity';
import { MessageParticipantWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-participant.workspace-entity';
import { NoteTargetWorkspaceEntity } from 'src/modules/note/standard-objects/note-target.workspace-entity';
import { OpportunityWorkspaceEntity } from 'src/modules/opportunity/standard-objects/opportunity.workspace-entity';
import { TaskTargetWorkspaceEntity } from 'src/modules/task/standard-objects/task-target.workspace-entity';
import { TimelineActivityWorkspaceEntity } from 'src/modules/timeline/standard-objects/timeline-activity.workspace-entity';
import { type FieldTypeAndNameMetadata } from 'src/engine/workspace-manager/utils/get-ts-vector-column-expression.util';
import { type EntityRelation } from 'src/engine/workspace-manager/workspace-migration/types/entity-relation.interface';
import { type AttachmentWorkspaceEntity } from 'src/modules/attachment/standard-objects/attachment.workspace-entity';
import { type CalendarEventParticipantWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-event-participant.workspace-entity';
import { type CompanyWorkspaceEntity } from 'src/modules/company/standard-objects/company.workspace-entity';
import { type FavoriteWorkspaceEntity } from 'src/modules/favorite/standard-objects/favorite.workspace-entity';
import { type MessageParticipantWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-participant.workspace-entity';
import { type NoteTargetWorkspaceEntity } from 'src/modules/note/standard-objects/note-target.workspace-entity';
import { type OpportunityWorkspaceEntity } from 'src/modules/opportunity/standard-objects/opportunity.workspace-entity';
import { type TaskTargetWorkspaceEntity } from 'src/modules/task/standard-objects/task-target.workspace-entity';
import { type TimelineActivityWorkspaceEntity } from 'src/modules/timeline/standard-objects/timeline-activity.workspace-entity';
const NAME_FIELD_NAME = 'name';
const EMAILS_FIELD_NAME = 'emails';
@@ -56,286 +32,31 @@ export const SEARCH_FIELDS_FOR_PERSON: FieldTypeAndNameMetadata[] = [
{ name: JOB_TITLE_FIELD_NAME, type: FieldMetadataType.TEXT },
];
@WorkspaceEntity({
standardId: STANDARD_OBJECT_IDS.person,
namePlural: 'people',
labelSingular: msg`Person`,
labelPlural: msg`People`,
description: msg`A person`,
icon: STANDARD_OBJECT_ICONS.person,
shortcut: 'P',
labelIdentifierStandardId: PERSON_STANDARD_FIELD_IDS.name,
imageIdentifierStandardId: PERSON_STANDARD_FIELD_IDS.avatarUrl,
})
@WorkspaceDuplicateCriteria([
['nameFirstName', 'nameLastName'],
['linkedinLinkPrimaryLinkUrl'],
['emailsPrimaryEmail'],
])
@WorkspaceIsSearchable()
export class PersonWorkspaceEntity extends BaseWorkspaceEntity {
@WorkspaceField({
standardId: PERSON_STANDARD_FIELD_IDS.name,
type: FieldMetadataType.FULL_NAME,
label: msg`Name`,
description: msg`Contacts name`,
icon: 'IconUser',
})
@WorkspaceIsNullable()
name: FullNameMetadata | null;
@WorkspaceField({
standardId: PERSON_STANDARD_FIELD_IDS.emails,
type: FieldMetadataType.EMAILS,
label: msg`Emails`,
description: msg`Contacts Emails`,
icon: 'IconMail',
settings: {
maxNumberOfValues: 1,
},
})
@WorkspaceIsUnique()
@WorkspaceIsNullable()
emails: EmailsMetadata;
@WorkspaceField({
standardId: PERSON_STANDARD_FIELD_IDS.linkedinLink,
type: FieldMetadataType.LINKS,
label: msg`Linkedin`,
description: msg`Contacts Linkedin account`,
icon: 'IconBrandLinkedin',
})
@WorkspaceIsNullable()
linkedinLink: LinksMetadata | null;
@WorkspaceField({
standardId: PERSON_STANDARD_FIELD_IDS.xLink,
type: FieldMetadataType.LINKS,
label: msg`X`,
description: msg`Contacts X/Twitter account`,
icon: 'IconBrandX',
})
@WorkspaceIsNullable()
xLink: LinksMetadata | null;
@WorkspaceField({
standardId: PERSON_STANDARD_FIELD_IDS.jobTitle,
type: FieldMetadataType.TEXT,
label: msg`Job Title`,
description: msg`Contacts job title`,
icon: 'IconBriefcase',
})
@WorkspaceIsNullable()
jobTitle: string | null;
@WorkspaceField({
standardId: PERSON_STANDARD_FIELD_IDS.phone,
type: FieldMetadataType.TEXT,
label: msg`Phone`,
description: msg`Contacts phone number`,
icon: 'IconPhone',
})
@WorkspaceIsDeprecated()
@WorkspaceIsNullable()
/** @deprecated Use `phones` field instead */
phone: string | null;
@WorkspaceField({
standardId: PERSON_STANDARD_FIELD_IDS.phones,
type: FieldMetadataType.PHONES,
label: msg`Phones`,
description: msg`Contacts phone numbers`,
icon: 'IconPhone',
settings: {
maxNumberOfValues: 1,
},
})
@WorkspaceIsNullable()
phones: PhonesMetadata;
@WorkspaceField({
standardId: PERSON_STANDARD_FIELD_IDS.city,
type: FieldMetadataType.TEXT,
label: msg`City`,
description: msg`Contacts city`,
icon: 'IconMap',
})
@WorkspaceIsNullable()
city: string | null;
@WorkspaceField({
standardId: PERSON_STANDARD_FIELD_IDS.avatarUrl,
type: FieldMetadataType.TEXT,
label: msg`Avatar`,
description: msg`Contacts avatar`,
icon: 'IconFileUpload',
})
@WorkspaceIsSystem()
@WorkspaceIsNullable()
avatarUrl: string | null;
@WorkspaceField({
standardId: PERSON_STANDARD_FIELD_IDS.position,
type: FieldMetadataType.POSITION,
label: msg`Position`,
description: msg`Person record Position`,
icon: 'IconHierarchy2',
defaultValue: 0,
})
@WorkspaceIsSystem()
position: number;
@WorkspaceField({
standardId: PERSON_STANDARD_FIELD_IDS.createdBy,
type: FieldMetadataType.ACTOR,
label: msg`Created by`,
icon: 'IconCreativeCommonsSa',
description: msg`The creator of the record`,
})
@WorkspaceIsFieldUIReadOnly()
createdBy: ActorMetadata;
@WorkspaceField({
standardId: PERSON_STANDARD_FIELD_IDS.updatedBy,
type: FieldMetadataType.ACTOR,
label: msg`Updated by`,
icon: 'IconUserCircle',
description: msg`The workspace member who last updated the record`,
})
@WorkspaceIsFieldUIReadOnly()
updatedBy: ActorMetadata;
// Relations
@WorkspaceRelation({
standardId: PERSON_STANDARD_FIELD_IDS.company,
type: RelationType.MANY_TO_ONE,
label: msg`Company`,
description: msg`Contacts company`,
icon: 'IconBuildingSkyscraper',
inverseSideTarget: () => CompanyWorkspaceEntity,
inverseSideFieldKey: 'people',
onDelete: RelationOnDeleteAction.SET_NULL,
})
@WorkspaceIsNullable()
company: Relation<CompanyWorkspaceEntity> | null;
@WorkspaceJoinColumn('company')
company: EntityRelation<CompanyWorkspaceEntity> | null;
companyId: string | null;
@WorkspaceRelation({
standardId: PERSON_STANDARD_FIELD_IDS.pointOfContactForOpportunities,
type: RelationType.ONE_TO_MANY,
label: msg`Opportunities`,
description: msg`List of opportunities for which that person is the point of contact`,
icon: 'IconTargetArrow',
inverseSideTarget: () => OpportunityWorkspaceEntity,
inverseSideFieldKey: 'pointOfContact',
onDelete: RelationOnDeleteAction.SET_NULL,
})
pointOfContactForOpportunities: Relation<OpportunityWorkspaceEntity[]>;
@WorkspaceRelation({
standardId: PERSON_STANDARD_FIELD_IDS.taskTargets,
type: RelationType.ONE_TO_MANY,
label: msg`Tasks`,
description: msg`Tasks tied to the contact`,
icon: 'IconCheckbox',
inverseSideTarget: () => TaskTargetWorkspaceEntity,
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
taskTargets: Relation<TaskTargetWorkspaceEntity[]>;
@WorkspaceRelation({
standardId: PERSON_STANDARD_FIELD_IDS.noteTargets,
type: RelationType.ONE_TO_MANY,
label: msg`Notes`,
description: msg`Notes tied to the contact`,
icon: 'IconNotes',
inverseSideTarget: () => NoteTargetWorkspaceEntity,
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
noteTargets: Relation<NoteTargetWorkspaceEntity[]>;
@WorkspaceRelation({
standardId: PERSON_STANDARD_FIELD_IDS.favorites,
type: RelationType.ONE_TO_MANY,
label: msg`Favorites`,
description: msg`Favorites linked to the contact`,
icon: 'IconHeart',
inverseSideTarget: () => FavoriteWorkspaceEntity,
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsSystem()
favorites: Relation<FavoriteWorkspaceEntity[]>;
@WorkspaceRelation({
standardId: PERSON_STANDARD_FIELD_IDS.attachments,
type: RelationType.ONE_TO_MANY,
label: msg`Attachments`,
description: msg`Attachments linked to the contact.`,
icon: 'IconFileImport',
inverseSideTarget: () => AttachmentWorkspaceEntity,
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsSystem()
attachments: Relation<AttachmentWorkspaceEntity[]>;
@WorkspaceRelation({
standardId: PERSON_STANDARD_FIELD_IDS.messageParticipants,
type: RelationType.ONE_TO_MANY,
label: msg`Message Participants`,
description: msg`Message Participants`,
icon: 'IconUserCircle',
inverseSideTarget: () => MessageParticipantWorkspaceEntity,
inverseSideFieldKey: 'person',
onDelete: RelationOnDeleteAction.SET_NULL,
})
@WorkspaceIsSystem()
messageParticipants: Relation<MessageParticipantWorkspaceEntity[]>;
@WorkspaceRelation({
standardId: PERSON_STANDARD_FIELD_IDS.calendarEventParticipants,
type: RelationType.ONE_TO_MANY,
label: msg`Calendar Event Participants`,
description: msg`Calendar Event Participants`,
icon: 'IconCalendar',
inverseSideTarget: () => CalendarEventParticipantWorkspaceEntity,
onDelete: RelationOnDeleteAction.SET_NULL,
})
@WorkspaceIsSystem()
calendarEventParticipants: Relation<
pointOfContactForOpportunities: EntityRelation<OpportunityWorkspaceEntity[]>;
taskTargets: EntityRelation<TaskTargetWorkspaceEntity[]>;
noteTargets: EntityRelation<NoteTargetWorkspaceEntity[]>;
favorites: EntityRelation<FavoriteWorkspaceEntity[]>;
attachments: EntityRelation<AttachmentWorkspaceEntity[]>;
messageParticipants: EntityRelation<MessageParticipantWorkspaceEntity[]>;
calendarEventParticipants: EntityRelation<
CalendarEventParticipantWorkspaceEntity[]
>;
@WorkspaceRelation({
standardId: PERSON_STANDARD_FIELD_IDS.timelineActivities,
type: RelationType.ONE_TO_MANY,
label: msg`Events`,
description: msg`Events linked to the person`,
icon: 'IconTimelineEvent',
inverseSideTarget: () => TimelineActivityWorkspaceEntity,
inverseSideFieldKey: 'targetPerson',
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsNullable()
@WorkspaceIsSystem()
timelineActivities: Relation<TimelineActivityWorkspaceEntity[]>;
@WorkspaceField({
standardId: PERSON_STANDARD_FIELD_IDS.searchVector,
type: FieldMetadataType.TS_VECTOR,
label: SEARCH_VECTOR_FIELD.label,
description: SEARCH_VECTOR_FIELD.description,
icon: 'IconUser',
generatedType: 'STORED',
asExpression: getTsVectorColumnExpressionFromFields(
SEARCH_FIELDS_FOR_PERSON,
),
})
@WorkspaceIsNullable()
@WorkspaceIsSystem()
@WorkspaceFieldIndex({ indexType: IndexType.GIN })
timelineActivities: EntityRelation<TimelineActivityWorkspaceEntity[]>;
searchVector: string;
}
@@ -1,119 +1,19 @@
import { msg } from '@lingui/core/macro';
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
import { RelationOnDeleteAction } from 'twenty-shared/types';
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
import { CustomWorkspaceEntity } from 'src/engine/twenty-orm/custom.workspace-entity';
import { WorkspaceDynamicRelation } from 'src/engine/twenty-orm/decorators/workspace-dynamic-relation.decorator';
import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator';
import { WorkspaceIsFieldUIReadOnly } from 'src/engine/twenty-orm/decorators/workspace-is-field-ui-readonly.decorator';
import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator';
import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator';
import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator';
import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator';
import { TASK_TARGET_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons';
import { CompanyWorkspaceEntity } from 'src/modules/company/standard-objects/company.workspace-entity';
import { OpportunityWorkspaceEntity } from 'src/modules/opportunity/standard-objects/opportunity.workspace-entity';
import { PersonWorkspaceEntity } from 'src/modules/person/standard-objects/person.workspace-entity';
import { TaskWorkspaceEntity } from 'src/modules/task/standard-objects/task.workspace-entity';
import { type CustomWorkspaceEntity } from 'src/engine/twenty-orm/custom.workspace-entity';
import { type EntityRelation } from 'src/engine/workspace-manager/workspace-migration/types/entity-relation.interface';
import { type CompanyWorkspaceEntity } from 'src/modules/company/standard-objects/company.workspace-entity';
import { type OpportunityWorkspaceEntity } from 'src/modules/opportunity/standard-objects/opportunity.workspace-entity';
import { type PersonWorkspaceEntity } from 'src/modules/person/standard-objects/person.workspace-entity';
import { type TaskWorkspaceEntity } from 'src/modules/task/standard-objects/task.workspace-entity';
@WorkspaceEntity({
standardId: STANDARD_OBJECT_IDS.taskTarget,
namePlural: 'taskTargets',
labelSingular: msg`Task Target`,
labelPlural: msg`Task Targets`,
description: msg`A task target`,
icon: STANDARD_OBJECT_ICONS.taskTarget,
})
@WorkspaceIsSystem()
export class TaskTargetWorkspaceEntity extends BaseWorkspaceEntity {
@WorkspaceRelation({
standardId: TASK_TARGET_STANDARD_FIELD_IDS.task,
type: RelationType.MANY_TO_ONE,
label: msg`Task`,
description: msg`TaskTarget task`,
icon: 'IconCheckbox',
inverseSideTarget: () => TaskWorkspaceEntity,
inverseSideFieldKey: 'taskTargets',
onDelete: RelationOnDeleteAction.SET_NULL,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
task: Relation<TaskWorkspaceEntity> | null;
@WorkspaceJoinColumn('task')
task: EntityRelation<TaskWorkspaceEntity> | null;
taskId: string | null;
@WorkspaceRelation({
standardId: TASK_TARGET_STANDARD_FIELD_IDS.person,
type: RelationType.MANY_TO_ONE,
label: msg`Person`,
description: msg`TaskTarget person`,
icon: 'IconUser',
inverseSideTarget: () => PersonWorkspaceEntity,
inverseSideFieldKey: 'taskTargets',
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
person: Relation<PersonWorkspaceEntity> | null;
@WorkspaceJoinColumn('person')
person: EntityRelation<PersonWorkspaceEntity> | null;
personId: string | null;
@WorkspaceRelation({
standardId: TASK_TARGET_STANDARD_FIELD_IDS.company,
type: RelationType.MANY_TO_ONE,
label: msg`Company`,
description: msg`TaskTarget company`,
icon: 'IconBuildingSkyscraper',
inverseSideTarget: () => CompanyWorkspaceEntity,
inverseSideFieldKey: 'taskTargets',
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
company: Relation<CompanyWorkspaceEntity> | null;
@WorkspaceJoinColumn('company')
company: EntityRelation<CompanyWorkspaceEntity> | null;
companyId: string | null;
@WorkspaceRelation({
standardId: TASK_TARGET_STANDARD_FIELD_IDS.opportunity,
type: RelationType.MANY_TO_ONE,
label: msg`Opportunity`,
description: msg`TaskTarget opportunity`,
icon: 'IconTargetArrow',
inverseSideTarget: () => OpportunityWorkspaceEntity,
inverseSideFieldKey: 'taskTargets',
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
opportunity: Relation<OpportunityWorkspaceEntity> | null;
@WorkspaceJoinColumn('opportunity')
opportunity: EntityRelation<OpportunityWorkspaceEntity> | null;
opportunityId: string | null;
// todo: remove this decorator and the custom field
@WorkspaceDynamicRelation({
type: RelationType.MANY_TO_ONE,
argsFactory: (oppositeObjectMetadata) => ({
standardId: TASK_TARGET_STANDARD_FIELD_IDS.custom,
name: oppositeObjectMetadata.nameSingular,
label: oppositeObjectMetadata.labelSingular,
description: `TaskTarget ${oppositeObjectMetadata.labelSingular}`,
joinColumn: `${oppositeObjectMetadata.nameSingular}Id`,
icon: 'IconBuildingSkyscraper',
}),
inverseSideTarget: () => CustomWorkspaceEntity,
inverseSideFieldKey: 'taskTargets',
onDelete: RelationOnDeleteAction.CASCADE,
})
custom: Relation<CustomWorkspaceEntity>;
custom: EntityRelation<CustomWorkspaceEntity>;
}
@@ -1,41 +1,19 @@
import { msg } from '@lingui/core/macro';
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
import {
ActorMetadata,
type ActorMetadata,
FieldMetadataType,
RelationOnDeleteAction,
type RichTextV2Metadata,
} from 'twenty-shared/types';
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
import { IndexType } from 'src/engine/metadata-modules/index-metadata/types/indexType.types';
import { SEARCH_VECTOR_FIELD } from 'src/engine/metadata-modules/search-field-metadata/constants/search-vector-field.constants';
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator';
import { WorkspaceFieldIndex } from 'src/engine/twenty-orm/decorators/workspace-field-index.decorator';
import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator';
import { WorkspaceIsFieldUIReadOnly } from 'src/engine/twenty-orm/decorators/workspace-is-field-ui-readonly.decorator';
import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator';
import { WorkspaceIsSearchable } from 'src/engine/twenty-orm/decorators/workspace-is-searchable.decorator';
import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator';
import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator';
import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator';
import { TASK_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons';
import {
type FieldTypeAndNameMetadata,
getTsVectorColumnExpressionFromFields,
} from 'src/engine/workspace-manager/workspace-sync-metadata/utils/get-ts-vector-column-expression.util';
import { AttachmentWorkspaceEntity } from 'src/modules/attachment/standard-objects/attachment.workspace-entity';
import { FavoriteWorkspaceEntity } from 'src/modules/favorite/standard-objects/favorite.workspace-entity';
import { TaskTargetWorkspaceEntity } from 'src/modules/task/standard-objects/task-target.workspace-entity';
import { TimelineActivityWorkspaceEntity } from 'src/modules/timeline/standard-objects/timeline-activity.workspace-entity';
import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
import { type FieldTypeAndNameMetadata } from 'src/engine/workspace-manager/utils/get-ts-vector-column-expression.util';
import { type EntityRelation } from 'src/engine/workspace-manager/workspace-migration/types/entity-relation.interface';
import { type AttachmentWorkspaceEntity } from 'src/modules/attachment/standard-objects/attachment.workspace-entity';
import { type FavoriteWorkspaceEntity } from 'src/modules/favorite/standard-objects/favorite.workspace-entity';
import { type TaskTargetWorkspaceEntity } from 'src/modules/task/standard-objects/task-target.workspace-entity';
import { type TimelineActivityWorkspaceEntity } from 'src/modules/timeline/standard-objects/timeline-activity.workspace-entity';
import { type WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
const TITLE_FIELD_NAME = 'title';
const BODY_V2_FIELD_NAME = 'bodyV2';
export const SEARCH_FIELDS_FOR_TASKS: FieldTypeAndNameMetadata[] = [
@@ -43,187 +21,19 @@ export const SEARCH_FIELDS_FOR_TASKS: FieldTypeAndNameMetadata[] = [
{ name: BODY_V2_FIELD_NAME, type: FieldMetadataType.RICH_TEXT_V2 },
];
@WorkspaceEntity({
standardId: STANDARD_OBJECT_IDS.task,
namePlural: 'tasks',
labelSingular: msg`Task`,
labelPlural: msg`Tasks`,
description: msg`A task`,
icon: STANDARD_OBJECT_ICONS.task,
shortcut: 'T',
labelIdentifierStandardId: TASK_STANDARD_FIELD_IDS.title,
})
@WorkspaceIsSearchable()
export class TaskWorkspaceEntity extends BaseWorkspaceEntity {
@WorkspaceField({
standardId: TASK_STANDARD_FIELD_IDS.position,
type: FieldMetadataType.POSITION,
label: msg`Position`,
description: msg`Task record position`,
icon: 'IconHierarchy2',
defaultValue: 0,
})
@WorkspaceIsSystem()
position: number;
@WorkspaceField({
standardId: TASK_STANDARD_FIELD_IDS.title,
type: FieldMetadataType.TEXT,
label: msg`Title`,
description: msg`Task title`,
icon: 'IconNotes',
})
@WorkspaceIsNullable()
title: string | null;
@WorkspaceField({
standardId: TASK_STANDARD_FIELD_IDS.bodyV2,
type: FieldMetadataType.RICH_TEXT_V2,
label: msg`Body`,
description: msg`Task body`,
icon: 'IconFilePencil',
})
@WorkspaceIsNullable()
bodyV2: RichTextV2Metadata | null;
@WorkspaceField({
standardId: TASK_STANDARD_FIELD_IDS.dueAt,
type: FieldMetadataType.DATE_TIME,
label: msg`Due Date`,
description: msg`Task due date`,
icon: 'IconCalendarEvent',
})
@WorkspaceIsNullable()
dueAt: Date | null;
@WorkspaceField({
standardId: TASK_STANDARD_FIELD_IDS.status,
type: FieldMetadataType.SELECT,
label: msg`Status`,
description: msg`Task status`,
icon: 'IconCheck',
defaultValue: "'TODO'",
options: [
{ value: 'TODO', label: 'To do', position: 0, color: 'sky' },
{
value: 'IN_PROGRESS',
label: 'In progress',
position: 1,
color: 'purple',
},
{
value: 'DONE',
label: 'Done',
position: 2,
color: 'green',
},
],
})
@WorkspaceIsNullable()
status: string | null;
@WorkspaceField({
standardId: TASK_STANDARD_FIELD_IDS.createdBy,
type: FieldMetadataType.ACTOR,
label: msg`Created by`,
icon: 'IconCreativeCommonsSa',
description: msg`The creator of the record`,
})
@WorkspaceIsFieldUIReadOnly()
createdBy: ActorMetadata;
@WorkspaceField({
standardId: TASK_STANDARD_FIELD_IDS.updatedBy,
type: FieldMetadataType.ACTOR,
label: msg`Updated by`,
icon: 'IconUserCircle',
description: msg`The workspace member who last updated the record`,
})
@WorkspaceIsFieldUIReadOnly()
updatedBy: ActorMetadata;
@WorkspaceRelation({
standardId: TASK_STANDARD_FIELD_IDS.taskTargets,
label: msg`Relations`,
description: msg`Task targets`,
icon: 'IconArrowUpRight',
type: RelationType.ONE_TO_MANY,
inverseSideTarget: () => TaskTargetWorkspaceEntity,
onDelete: RelationOnDeleteAction.SET_NULL,
})
@WorkspaceIsNullable()
@WorkspaceIsSystem()
taskTargets: Relation<TaskTargetWorkspaceEntity[]>;
@WorkspaceRelation({
standardId: TASK_STANDARD_FIELD_IDS.attachments,
label: msg`Attachments`,
description: msg`Task attachments`,
icon: 'IconFileImport',
type: RelationType.ONE_TO_MANY,
inverseSideTarget: () => AttachmentWorkspaceEntity,
onDelete: RelationOnDeleteAction.SET_NULL,
})
@WorkspaceIsNullable()
@WorkspaceIsSystem()
attachments: Relation<AttachmentWorkspaceEntity[]>;
@WorkspaceRelation({
standardId: TASK_STANDARD_FIELD_IDS.assignee,
label: msg`Assignee`,
description: msg`Task assignee`,
icon: 'IconUserCircle',
type: RelationType.MANY_TO_ONE,
inverseSideTarget: () => WorkspaceMemberWorkspaceEntity,
inverseSideFieldKey: 'assignedTasks',
onDelete: RelationOnDeleteAction.SET_NULL,
})
@WorkspaceIsNullable()
assignee: Relation<WorkspaceMemberWorkspaceEntity> | null;
@WorkspaceJoinColumn('assignee')
taskTargets: EntityRelation<TaskTargetWorkspaceEntity[]>;
attachments: EntityRelation<AttachmentWorkspaceEntity[]>;
assignee: EntityRelation<WorkspaceMemberWorkspaceEntity> | null;
assigneeId: string | null;
@WorkspaceRelation({
standardId: TASK_STANDARD_FIELD_IDS.timelineActivities,
type: RelationType.ONE_TO_MANY,
label: msg`Timeline Activities`,
description: msg`Timeline Activities linked to the task.`,
icon: 'IconTimelineEvent',
inverseSideTarget: () => TimelineActivityWorkspaceEntity,
inverseSideFieldKey: 'targetTask',
onDelete: RelationOnDeleteAction.SET_NULL,
})
@WorkspaceIsNullable()
@WorkspaceIsSystem()
timelineActivities: Relation<TimelineActivityWorkspaceEntity[]>;
@WorkspaceRelation({
standardId: TASK_STANDARD_FIELD_IDS.favorites,
type: RelationType.ONE_TO_MANY,
label: msg`Favorites`,
description: msg`Favorites linked to the task`,
icon: 'IconHeart',
inverseSideTarget: () => FavoriteWorkspaceEntity,
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsSystem()
favorites: Relation<FavoriteWorkspaceEntity[]>;
@WorkspaceField({
standardId: TASK_STANDARD_FIELD_IDS.searchVector,
type: FieldMetadataType.TS_VECTOR,
label: SEARCH_VECTOR_FIELD.label,
description: SEARCH_VECTOR_FIELD.description,
icon: 'IconUser',
generatedType: 'STORED',
asExpression: getTsVectorColumnExpressionFromFields(
SEARCH_FIELDS_FOR_TASKS,
),
})
@WorkspaceIsNullable()
@WorkspaceIsSystem()
@WorkspaceFieldIndex({ indexType: IndexType.GIN })
timelineActivities: EntityRelation<TimelineActivityWorkspaceEntity[]>;
favorites: EntityRelation<FavoriteWorkspaceEntity[]>;
searchVector: string;
}
@@ -1,334 +1,44 @@
import { msg } from '@lingui/core/macro';
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
import { FieldMetadataType, RelationOnDeleteAction } from 'twenty-shared/types';
import { capitalize } from 'twenty-shared/utils';
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
import { CustomWorkspaceEntity } from 'src/engine/twenty-orm/custom.workspace-entity';
import { WorkspaceDynamicRelation } from 'src/engine/twenty-orm/decorators/workspace-dynamic-relation.decorator';
import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator';
import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator';
import { WorkspaceIsFieldUIReadOnly } from 'src/engine/twenty-orm/decorators/workspace-is-field-ui-readonly.decorator';
import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator';
import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator';
import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator';
import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator';
import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator';
import { TIMELINE_ACTIVITY_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons';
import { CompanyWorkspaceEntity } from 'src/modules/company/standard-objects/company.workspace-entity';
import { DashboardWorkspaceEntity } from 'src/modules/dashboard/standard-objects/dashboard.workspace-entity';
import { NoteWorkspaceEntity } from 'src/modules/note/standard-objects/note.workspace-entity';
import { OpportunityWorkspaceEntity } from 'src/modules/opportunity/standard-objects/opportunity.workspace-entity';
import { PersonWorkspaceEntity } from 'src/modules/person/standard-objects/person.workspace-entity';
import { TaskWorkspaceEntity } from 'src/modules/task/standard-objects/task.workspace-entity';
import { WorkflowRunWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow-run.workspace-entity';
import { WorkflowVersionWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow-version.workspace-entity';
import { WorkflowWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow.workspace-entity';
import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
import { type CustomWorkspaceEntity } from 'src/engine/twenty-orm/custom.workspace-entity';
import { type EntityRelation } from 'src/engine/workspace-manager/workspace-migration/types/entity-relation.interface';
import { type CompanyWorkspaceEntity } from 'src/modules/company/standard-objects/company.workspace-entity';
import { type DashboardWorkspaceEntity } from 'src/modules/dashboard/standard-objects/dashboard.workspace-entity';
import { type NoteWorkspaceEntity } from 'src/modules/note/standard-objects/note.workspace-entity';
import { type OpportunityWorkspaceEntity } from 'src/modules/opportunity/standard-objects/opportunity.workspace-entity';
import { type PersonWorkspaceEntity } from 'src/modules/person/standard-objects/person.workspace-entity';
import { type TaskWorkspaceEntity } from 'src/modules/task/standard-objects/task.workspace-entity';
import { type WorkflowRunWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow-run.workspace-entity';
import { type WorkflowVersionWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow-version.workspace-entity';
import { type WorkflowWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow.workspace-entity';
import { type WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
@WorkspaceEntity({
standardId: STANDARD_OBJECT_IDS.timelineActivity,
namePlural: 'timelineActivities',
labelSingular: msg`Timeline Activity`,
labelPlural: msg`Timeline Activities`,
description: msg`Aggregated / filtered event to be displayed on the timeline`,
icon: STANDARD_OBJECT_ICONS.timelineActivity,
labelIdentifierStandardId: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.name,
})
@WorkspaceIsSystem()
@WorkspaceIsNotAuditLogged()
export class TimelineActivityWorkspaceEntity extends BaseWorkspaceEntity {
@WorkspaceField({
standardId: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.happensAt,
type: FieldMetadataType.DATE_TIME,
label: msg`Creation date`,
description: msg`Creation date`,
icon: 'IconCalendar',
defaultValue: 'now',
})
@WorkspaceIsFieldUIReadOnly()
happensAt: Date;
@WorkspaceField({
standardId: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.name,
type: FieldMetadataType.TEXT,
label: msg`Event name`,
description: msg`Event name`,
icon: 'IconAbc',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
name: string | null;
@WorkspaceField({
standardId: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.properties,
type: FieldMetadataType.RAW_JSON,
label: msg`Event details`,
description: msg`Json value for event details`,
icon: 'IconListDetails',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
properties: JSON | null;
// Special objects that don't have their own timeline and are 'link' to the main object
@WorkspaceField({
standardId: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.linkedRecordCachedName,
type: FieldMetadataType.TEXT,
label: msg`Linked Record cached name`,
description: msg`Cached record name`,
icon: 'IconAbc',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
linkedRecordCachedName: string | null;
@WorkspaceField({
standardId: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.linkedRecordId,
type: FieldMetadataType.UUID,
label: msg`Linked Record id`,
description: msg`Linked Record id`,
icon: 'IconAbc',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
linkedRecordId: string | null;
@WorkspaceField({
standardId: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.linkedObjectMetadataId,
type: FieldMetadataType.UUID,
label: msg`Linked Object Metadata Id`,
description: msg`Linked Object Metadata Id`,
icon: 'IconAbc',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
linkedObjectMetadataId: string | null;
// Who made the action
@WorkspaceRelation({
standardId: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.workspaceMember,
type: RelationType.MANY_TO_ONE,
label: msg`Workspace Member`,
description: msg`Event workspace member`,
icon: 'IconCircleUser',
inverseSideTarget: () => WorkspaceMemberWorkspaceEntity,
inverseSideFieldKey: 'timelineActivities',
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
workspaceMember: Relation<WorkspaceMemberWorkspaceEntity> | null;
@WorkspaceJoinColumn('workspaceMember')
workspaceMember: EntityRelation<WorkspaceMemberWorkspaceEntity> | null;
workspaceMemberId: string | null;
@WorkspaceRelation({
standardId: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.targetPerson,
type: RelationType.MANY_TO_ONE,
label: msg`Person`,
description: msg`Event person`,
icon: 'IconUser',
inverseSideTarget: () => PersonWorkspaceEntity,
inverseSideFieldKey: 'timelineActivities',
onDelete: RelationOnDeleteAction.CASCADE,
isMorphRelation: true,
morphId: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.targetMorphId,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
targetPerson: Relation<PersonWorkspaceEntity> | null;
@WorkspaceJoinColumn('targetPerson')
targetPerson: EntityRelation<PersonWorkspaceEntity> | null;
targetPersonId: string | null;
@WorkspaceRelation({
standardId: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.targetCompany,
type: RelationType.MANY_TO_ONE,
label: msg`Company`,
description: msg`Event company`,
icon: 'IconBuildingSkyscraper',
inverseSideTarget: () => CompanyWorkspaceEntity,
inverseSideFieldKey: 'timelineActivities',
onDelete: RelationOnDeleteAction.CASCADE,
isMorphRelation: true,
morphId: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.targetMorphId,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
targetCompany: Relation<CompanyWorkspaceEntity> | null;
@WorkspaceJoinColumn('targetCompany')
targetCompany: EntityRelation<CompanyWorkspaceEntity> | null;
targetCompanyId: string | null;
@WorkspaceRelation({
standardId: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.targetOpportunity,
type: RelationType.MANY_TO_ONE,
label: msg`Opportunity`,
description: msg`Event opportunity`,
icon: 'IconTargetArrow',
inverseSideTarget: () => OpportunityWorkspaceEntity,
inverseSideFieldKey: 'timelineActivities',
onDelete: RelationOnDeleteAction.SET_NULL,
isMorphRelation: true,
morphId: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.targetMorphId,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
targetOpportunity: Relation<OpportunityWorkspaceEntity> | null;
@WorkspaceJoinColumn('targetOpportunity')
targetOpportunity: EntityRelation<OpportunityWorkspaceEntity> | null;
targetOpportunityId: string | null;
@WorkspaceRelation({
standardId: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.targetNote,
type: RelationType.MANY_TO_ONE,
label: msg`Note`,
description: msg`Event note`,
icon: 'IconTargetArrow',
inverseSideTarget: () => NoteWorkspaceEntity,
inverseSideFieldKey: 'timelineActivities',
onDelete: RelationOnDeleteAction.SET_NULL,
isMorphRelation: true,
morphId: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.targetMorphId,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
targetNote: Relation<NoteWorkspaceEntity> | null;
@WorkspaceJoinColumn('targetNote')
targetNote: EntityRelation<NoteWorkspaceEntity> | null;
targetNoteId: string | null;
@WorkspaceRelation({
standardId: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.targetTask,
type: RelationType.MANY_TO_ONE,
label: msg`Task`,
description: msg`Event task`,
icon: 'IconTargetArrow',
inverseSideTarget: () => TaskWorkspaceEntity,
inverseSideFieldKey: 'timelineActivities',
onDelete: RelationOnDeleteAction.SET_NULL,
isMorphRelation: true,
morphId: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.targetMorphId,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
targetTask: Relation<TaskWorkspaceEntity> | null;
@WorkspaceJoinColumn('targetTask')
targetTask: EntityRelation<TaskWorkspaceEntity> | null;
targetTaskId: string | null;
@WorkspaceRelation({
standardId: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.targetWorkflow,
type: RelationType.MANY_TO_ONE,
label: msg`Workflow`,
description: msg`Event workflow`,
icon: 'IconTargetArrow',
inverseSideTarget: () => WorkflowWorkspaceEntity,
inverseSideFieldKey: 'timelineActivities',
onDelete: RelationOnDeleteAction.CASCADE,
isMorphRelation: true,
morphId: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.targetMorphId,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
targetWorkflow: Relation<WorkflowWorkspaceEntity> | null;
@WorkspaceJoinColumn('targetWorkflow')
targetWorkflow: EntityRelation<WorkflowWorkspaceEntity> | null;
targetWorkflowId: string | null;
@WorkspaceRelation({
standardId: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.targetWorkflowVersion,
type: RelationType.MANY_TO_ONE,
label: msg`WorkflowVersion`,
description: msg`Event workflow version`,
icon: 'IconTargetArrow',
inverseSideTarget: () => WorkflowVersionWorkspaceEntity,
inverseSideFieldKey: 'timelineActivities',
onDelete: RelationOnDeleteAction.CASCADE,
isMorphRelation: true,
morphId: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.targetMorphId,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
targetWorkflowVersion: Relation<WorkflowVersionWorkspaceEntity> | null;
@WorkspaceJoinColumn('targetWorkflowVersion')
targetWorkflowVersion: EntityRelation<WorkflowVersionWorkspaceEntity> | null;
targetWorkflowVersionId: string | null;
@WorkspaceRelation({
standardId: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.targetWorkflowRun,
type: RelationType.MANY_TO_ONE,
label: msg`Workflow Run`,
description: msg`Event workflow run`,
icon: 'IconTargetArrow',
inverseSideTarget: () => WorkflowRunWorkspaceEntity,
inverseSideFieldKey: 'timelineActivities',
onDelete: RelationOnDeleteAction.CASCADE,
isMorphRelation: true,
morphId: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.targetMorphId,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
targetWorkflowRun: Relation<WorkflowRunWorkspaceEntity> | null;
@WorkspaceJoinColumn('targetWorkflowRun')
targetWorkflowRun: EntityRelation<WorkflowRunWorkspaceEntity> | null;
targetWorkflowRunId: string | null;
@WorkspaceRelation({
standardId: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.targetDashboard,
type: RelationType.MANY_TO_ONE,
label: msg`Dashboard`,
description: msg`Event dashboard`,
icon: 'IconTargetArrow',
inverseSideTarget: () => DashboardWorkspaceEntity,
inverseSideFieldKey: 'timelineActivities',
onDelete: RelationOnDeleteAction.SET_NULL,
isMorphRelation: true,
morphId: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.targetMorphId,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
targetDashboard: Relation<DashboardWorkspaceEntity> | null;
@WorkspaceJoinColumn('targetDashboard')
targetDashboard: EntityRelation<DashboardWorkspaceEntity> | null;
targetDashboardId: string | null;
// todo: remove this decorator and the custom field
@WorkspaceDynamicRelation({
type: RelationType.MANY_TO_ONE,
argsFactory: (oppositeObjectMetadata) => ({
standardId: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.targetCustom,
name: oppositeObjectMetadata.nameSingular,
label: oppositeObjectMetadata.labelSingular,
description: `Timeline Activity ${oppositeObjectMetadata.labelSingular}`,
joinColumn: `${oppositeObjectMetadata.nameSingular}Id`,
icon: 'IconTimeline',
}),
inverseSideTarget: () => CustomWorkspaceEntity,
inverseSideFieldKey: 'timelineActivities',
onDelete: RelationOnDeleteAction.CASCADE,
})
custom: Relation<CustomWorkspaceEntity>;
@WorkspaceDynamicRelation({
type: RelationType.MANY_TO_ONE,
argsFactory: (oppositeObjectMetadata) => ({
standardId: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.targetCustom,
name: oppositeObjectMetadata.nameSingular,
label: oppositeObjectMetadata.labelSingular,
description: `Timeline Activity ${oppositeObjectMetadata.labelSingular}`,
joinColumn: `target${capitalize(oppositeObjectMetadata.nameSingular)}Id`,
icon: 'IconTimeline',
}),
inverseSideTarget: () => CustomWorkspaceEntity,
inverseSideFieldKey: 'timelineActivities',
onDelete: RelationOnDeleteAction.CASCADE,
})
targetCustom: Relation<CustomWorkspaceEntity>;
custom: EntityRelation<CustomWorkspaceEntity>;
targetCustom: EntityRelation<CustomWorkspaceEntity>;
}
@@ -1,84 +1,17 @@
import { msg } from '@lingui/core/macro';
import { FieldMetadataType, RelationOnDeleteAction } from 'twenty-shared/types';
import { Relation } from 'typeorm';
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator';
import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator';
import { WorkspaceIsFieldUIReadOnly } from 'src/engine/twenty-orm/decorators/workspace-is-field-ui-readonly.decorator';
import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator';
import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator';
import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator';
import { WORKFLOW_AUTOMATED_TRIGGER_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons';
import { AutomatedTriggerSettings } from 'src/modules/workflow/workflow-trigger/automated-trigger/constants/automated-trigger-settings';
import { type EntityRelation } from 'src/engine/workspace-manager/workspace-migration/types/entity-relation.interface';
import { type AutomatedTriggerSettings } from 'src/modules/workflow/workflow-trigger/automated-trigger/constants/automated-trigger-settings';
import { WorkflowWorkspaceEntity } from './workflow.workspace-entity';
import { type WorkflowWorkspaceEntity } from './workflow.workspace-entity';
export enum AutomatedTriggerType {
DATABASE_EVENT = 'DATABASE_EVENT',
CRON = 'CRON',
}
@WorkspaceEntity({
standardId: STANDARD_OBJECT_IDS.workflowAutomatedTrigger,
namePlural: 'workflowAutomatedTriggers',
labelSingular: msg`WorkflowAutomatedTrigger`,
labelPlural: msg`WorkflowAutomatedTriggers`,
description: msg`A workflow automated trigger`,
icon: STANDARD_OBJECT_ICONS.workflowAutomatedTrigger,
})
@WorkspaceIsSystem()
export class WorkflowAutomatedTriggerWorkspaceEntity extends BaseWorkspaceEntity {
@WorkspaceField({
standardId: WORKFLOW_AUTOMATED_TRIGGER_STANDARD_FIELD_IDS.type,
type: FieldMetadataType.SELECT,
label: msg`Automated Trigger Type`,
description: msg`The workflow automated trigger type`,
options: [
{
value: AutomatedTriggerType.DATABASE_EVENT,
label: 'Database Event',
position: 0,
color: 'green',
},
{
value: AutomatedTriggerType.CRON,
label: 'Cron',
position: 1,
color: 'blue',
},
],
})
@WorkspaceIsFieldUIReadOnly()
type: AutomatedTriggerType;
@WorkspaceField({
standardId: WORKFLOW_AUTOMATED_TRIGGER_STANDARD_FIELD_IDS.settings,
type: FieldMetadataType.RAW_JSON,
label: msg`Settings`,
description: msg`The workflow automated trigger settings`,
})
@WorkspaceIsFieldUIReadOnly()
settings: AutomatedTriggerSettings;
@WorkspaceRelation({
standardId: WORKFLOW_AUTOMATED_TRIGGER_STANDARD_FIELD_IDS.workflow,
type: RelationType.MANY_TO_ONE,
label: msg`Workflow`,
description: msg`WorkflowAutomatedTrigger workflow`,
icon: 'IconSettingsAutomation',
inverseSideTarget: () => WorkflowWorkspaceEntity,
inverseSideFieldKey: 'automatedTriggers',
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
workflow: Relation<WorkflowWorkspaceEntity>;
@WorkspaceJoinColumn('workflow')
workflow: EntityRelation<WorkflowWorkspaceEntity>;
workflowId: string;
}
@@ -1,39 +1,15 @@
import { registerEnumType } from '@nestjs/graphql';
import { msg } from '@lingui/core/macro';
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
import {
ActorMetadata,
FieldMetadataType,
RelationOnDeleteAction,
} from 'twenty-shared/types';
import { type ActorMetadata, FieldMetadataType } from 'twenty-shared/types';
import { type WorkflowRunStepInfos } from 'twenty-shared/workflow';
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
import { IndexType } from 'src/engine/metadata-modules/index-metadata/types/indexType.types';
import { SEARCH_VECTOR_FIELD } from 'src/engine/metadata-modules/search-field-metadata/constants/search-vector-field.constants';
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator';
import { WorkspaceFieldIndex } from 'src/engine/twenty-orm/decorators/workspace-field-index.decorator';
import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator';
import { WorkspaceIsFieldUIReadOnly } from 'src/engine/twenty-orm/decorators/workspace-is-field-ui-readonly.decorator';
import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator';
import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator';
import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator';
import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator';
import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator';
import { WORKFLOW_RUN_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons';
import {
type FieldTypeAndNameMetadata,
getTsVectorColumnExpressionFromFields,
} from 'src/engine/workspace-manager/workspace-sync-metadata/utils/get-ts-vector-column-expression.util';
import { FavoriteWorkspaceEntity } from 'src/modules/favorite/standard-objects/favorite.workspace-entity';
import { TimelineActivityWorkspaceEntity } from 'src/modules/timeline/standard-objects/timeline-activity.workspace-entity';
import { WorkflowVersionWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow-version.workspace-entity';
import { WorkflowWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow.workspace-entity';
import { type FieldTypeAndNameMetadata } from 'src/engine/workspace-manager/utils/get-ts-vector-column-expression.util';
import { type EntityRelation } from 'src/engine/workspace-manager/workspace-migration/types/entity-relation.interface';
import { type FavoriteWorkspaceEntity } from 'src/modules/favorite/standard-objects/favorite.workspace-entity';
import { type TimelineActivityWorkspaceEntity } from 'src/modules/timeline/standard-objects/timeline-activity.workspace-entity';
import { type WorkflowVersionWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow-version.workspace-entity';
import { type WorkflowWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow.workspace-entity';
import { type WorkflowActionOutput } from 'src/modules/workflow/workflow-executor/types/workflow-action-output.type';
import { type WorkflowAction } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
import { type WorkflowTrigger } from 'src/modules/workflow/workflow-trigger/types/workflow-trigger.type';
@@ -82,233 +58,21 @@ export const SEARCH_FIELDS_FOR_WORKFLOW_RUNS: FieldTypeAndNameMetadata[] = [
{ name: NAME_FIELD_NAME, type: FieldMetadataType.TEXT },
];
@WorkspaceEntity({
standardId: STANDARD_OBJECT_IDS.workflowRun,
namePlural: 'workflowRuns',
labelSingular: msg`Workflow Run`,
labelPlural: msg`Workflow Runs`,
description: msg`A workflow run`,
labelIdentifierStandardId: WORKFLOW_RUN_STANDARD_FIELD_IDS.name,
icon: STANDARD_OBJECT_ICONS.workflowRun,
})
@WorkspaceIsSystem()
@WorkspaceIsNotAuditLogged()
export class WorkflowRunWorkspaceEntity extends BaseWorkspaceEntity {
@WorkspaceField({
standardId: WORKFLOW_RUN_STANDARD_FIELD_IDS.name,
type: FieldMetadataType.TEXT,
label: msg`Name`,
description: msg`Name of the workflow run`,
icon: 'IconSettingsAutomation',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
name: string | null;
@WorkspaceField({
standardId: WORKFLOW_RUN_STANDARD_FIELD_IDS.enqueuedAt,
type: FieldMetadataType.DATE_TIME,
label: msg`Workflow run enqueued at`,
description: msg`Workflow run enqueued at`,
icon: 'IconHistory',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
enqueuedAt: Date | null;
@WorkspaceField({
standardId: WORKFLOW_RUN_STANDARD_FIELD_IDS.startedAt,
type: FieldMetadataType.DATE_TIME,
label: msg`Workflow run started at`,
description: msg`Workflow run started at`,
icon: 'IconHistory',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
startedAt: string | null;
@WorkspaceField({
standardId: WORKFLOW_RUN_STANDARD_FIELD_IDS.endedAt,
type: FieldMetadataType.DATE_TIME,
label: msg`Workflow run ended at`,
description: msg`Workflow run ended at`,
icon: 'IconHistory',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
endedAt: string | null;
@WorkspaceField({
standardId: WORKFLOW_RUN_STANDARD_FIELD_IDS.status,
type: FieldMetadataType.SELECT,
label: msg`Workflow run status`,
description: msg`Workflow run status`,
icon: 'IconStatusChange',
options: [
{
value: WorkflowRunStatus.NOT_STARTED,
label: 'Not started',
position: 0,
color: 'gray',
},
{
value: WorkflowRunStatus.RUNNING,
label: 'Running',
position: 1,
color: 'yellow',
},
{
value: WorkflowRunStatus.COMPLETED,
label: 'Completed',
position: 2,
color: 'green',
},
{
value: WorkflowRunStatus.FAILED,
label: 'Failed',
position: 3,
color: 'red',
},
{
value: WorkflowRunStatus.ENQUEUED,
label: 'Enqueued',
position: 4,
color: 'blue',
},
{
value: WorkflowRunStatus.STOPPING,
label: 'Stopping',
position: 5,
color: 'orange',
},
{
value: WorkflowRunStatus.STOPPED,
label: 'Stopped',
position: 6,
color: 'gray',
},
],
defaultValue: "'NOT_STARTED'",
})
@WorkspaceIsFieldUIReadOnly()
status: WorkflowRunStatus;
@WorkspaceField({
standardId: WORKFLOW_RUN_STANDARD_FIELD_IDS.createdBy,
type: FieldMetadataType.ACTOR,
label: msg`Executed by`,
icon: 'IconCreativeCommonsSa',
description: msg`The executor of the workflow`,
})
@WorkspaceIsFieldUIReadOnly()
createdBy: ActorMetadata;
@WorkspaceField({
standardId: WORKFLOW_RUN_STANDARD_FIELD_IDS.updatedBy,
type: FieldMetadataType.ACTOR,
label: msg`Updated by`,
icon: 'IconUserCircle',
description: msg`The workspace member who last updated the record`,
})
@WorkspaceIsFieldUIReadOnly()
updatedBy: ActorMetadata;
@WorkspaceField({
standardId: WORKFLOW_RUN_STANDARD_FIELD_IDS.state,
type: FieldMetadataType.RAW_JSON,
label: msg`State`,
description: msg`State of the workflow run`,
icon: 'IconHierarchy2',
})
@WorkspaceIsFieldUIReadOnly()
state: WorkflowRunState;
@WorkspaceField({
standardId: WORKFLOW_RUN_STANDARD_FIELD_IDS.position,
type: FieldMetadataType.POSITION,
label: msg`Position`,
description: msg`Workflow run position`,
icon: 'IconHierarchy2',
defaultValue: 0,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsSystem()
position: number;
@WorkspaceField({
standardId: WORKFLOW_RUN_STANDARD_FIELD_IDS.searchVector,
type: FieldMetadataType.TS_VECTOR,
label: SEARCH_VECTOR_FIELD.label,
description: SEARCH_VECTOR_FIELD.description,
icon: 'IconUser',
generatedType: 'STORED',
asExpression: getTsVectorColumnExpressionFromFields(
SEARCH_FIELDS_FOR_WORKFLOW_RUNS,
),
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
@WorkspaceIsSystem()
@WorkspaceFieldIndex({ indexType: IndexType.GIN })
searchVector: string;
// Relations
@WorkspaceRelation({
standardId: WORKFLOW_RUN_STANDARD_FIELD_IDS.workflowVersion,
type: RelationType.MANY_TO_ONE,
label: msg`Workflow version`,
description: msg`Workflow version linked to the run.`,
icon: 'IconVersions',
inverseSideTarget: () => WorkflowVersionWorkspaceEntity,
inverseSideFieldKey: 'runs',
onDelete: RelationOnDeleteAction.SET_NULL,
})
@WorkspaceIsFieldUIReadOnly()
workflowVersion: Relation<WorkflowVersionWorkspaceEntity>;
@WorkspaceJoinColumn('workflowVersion')
workflowVersion: EntityRelation<WorkflowVersionWorkspaceEntity>;
workflowVersionId: string;
@WorkspaceRelation({
standardId: WORKFLOW_RUN_STANDARD_FIELD_IDS.workflow,
type: RelationType.MANY_TO_ONE,
label: msg`Workflow`,
description: msg`Workflow linked to the run.`,
icon: 'IconSettingsAutomation',
inverseSideTarget: () => WorkflowWorkspaceEntity,
inverseSideFieldKey: 'runs',
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
workflow: Relation<WorkflowWorkspaceEntity>;
@WorkspaceJoinColumn('workflow')
workflow: EntityRelation<WorkflowWorkspaceEntity>;
workflowId: string;
@WorkspaceRelation({
standardId: WORKFLOW_RUN_STANDARD_FIELD_IDS.favorites,
type: RelationType.ONE_TO_MANY,
label: msg`Favorites`,
description: msg`Favorites linked to the workflow run`,
icon: 'IconHeart',
inverseSideTarget: () => FavoriteWorkspaceEntity,
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsSystem()
favorites: Relation<FavoriteWorkspaceEntity[]>;
@WorkspaceRelation({
standardId: WORKFLOW_RUN_STANDARD_FIELD_IDS.timelineActivities,
type: RelationType.ONE_TO_MANY,
label: msg`Timeline Activities`,
description: msg`Timeline activities linked to the run`,
inverseSideTarget: () => TimelineActivityWorkspaceEntity,
inverseSideFieldKey: 'targetWorkflowRun',
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsSystem()
timelineActivities: Relation<TimelineActivityWorkspaceEntity[]>;
favorites: EntityRelation<FavoriteWorkspaceEntity[]>;
timelineActivities: EntityRelation<TimelineActivityWorkspaceEntity[]>;
}
@@ -1,32 +1,12 @@
import { msg } from '@lingui/core/macro';
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
import { FieldMetadataType, RelationOnDeleteAction } from 'twenty-shared/types';
import { FieldMetadataType } from 'twenty-shared/types';
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
import { type FieldMetadataComplexOption } from 'src/engine/metadata-modules/field-metadata/dtos/options.input';
import { IndexType } from 'src/engine/metadata-modules/index-metadata/types/indexType.types';
import { SEARCH_VECTOR_FIELD } from 'src/engine/metadata-modules/search-field-metadata/constants/search-vector-field.constants';
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator';
import { WorkspaceFieldIndex } from 'src/engine/twenty-orm/decorators/workspace-field-index.decorator';
import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator';
import { WorkspaceIsFieldUIReadOnly } from 'src/engine/twenty-orm/decorators/workspace-is-field-ui-readonly.decorator';
import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator';
import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator';
import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator';
import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator';
import { WORKFLOW_VERSION_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons';
import {
type FieldTypeAndNameMetadata,
getTsVectorColumnExpressionFromFields,
} from 'src/engine/workspace-manager/workspace-sync-metadata/utils/get-ts-vector-column-expression.util';
import { FavoriteWorkspaceEntity } from 'src/modules/favorite/standard-objects/favorite.workspace-entity';
import { TimelineActivityWorkspaceEntity } from 'src/modules/timeline/standard-objects/timeline-activity.workspace-entity';
import { WorkflowRunWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow-run.workspace-entity';
import { WorkflowWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow.workspace-entity';
import { type FieldTypeAndNameMetadata } from 'src/engine/workspace-manager/utils/get-ts-vector-column-expression.util';
import { type EntityRelation } from 'src/engine/workspace-manager/workspace-migration/types/entity-relation.interface';
import { type FavoriteWorkspaceEntity } from 'src/modules/favorite/standard-objects/favorite.workspace-entity';
import { type TimelineActivityWorkspaceEntity } from 'src/modules/timeline/standard-objects/timeline-activity.workspace-entity';
import { type WorkflowRunWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow-run.workspace-entity';
import { type WorkflowWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow.workspace-entity';
import { type WorkflowAction } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
import { type WorkflowTrigger } from 'src/modules/workflow/workflow-trigger/types/workflow-trigger.type';
@@ -37,179 +17,22 @@ export enum WorkflowVersionStatus {
ARCHIVED = 'ARCHIVED',
}
const WorkflowVersionStatusOptions: FieldMetadataComplexOption[] = [
{
value: WorkflowVersionStatus.DRAFT,
label: 'Draft',
position: 0,
color: 'yellow',
},
{
value: WorkflowVersionStatus.ACTIVE,
label: 'Active',
position: 1,
color: 'green',
},
{
value: WorkflowVersionStatus.DEACTIVATED,
label: 'Deactivated',
position: 2,
color: 'orange',
},
{
value: WorkflowVersionStatus.ARCHIVED,
label: 'Archived',
position: 3,
color: 'gray',
},
];
const NAME_FIELD_NAME = 'name';
export const SEARCH_FIELDS_FOR_WORKFLOW_VERSIONS: FieldTypeAndNameMetadata[] = [
{ name: NAME_FIELD_NAME, type: FieldMetadataType.TEXT },
];
@WorkspaceEntity({
standardId: STANDARD_OBJECT_IDS.workflowVersion,
namePlural: 'workflowVersions',
labelSingular: msg`Workflow Version`,
labelPlural: msg`Workflow Versions`,
description: msg`A workflow version`,
icon: STANDARD_OBJECT_ICONS.workflowVersion,
labelIdentifierStandardId: WORKFLOW_VERSION_STANDARD_FIELD_IDS.name,
})
@WorkspaceIsSystem()
export class WorkflowVersionWorkspaceEntity extends BaseWorkspaceEntity {
@WorkspaceField({
standardId: WORKFLOW_VERSION_STANDARD_FIELD_IDS.name,
type: FieldMetadataType.TEXT,
label: msg`Name`,
description: msg`The workflow version name`,
icon: 'IconSettingsAutomation',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
name: string | null;
@WorkspaceField({
standardId: WORKFLOW_VERSION_STANDARD_FIELD_IDS.trigger,
type: FieldMetadataType.RAW_JSON,
label: msg`Version trigger`,
description: msg`Json object to provide trigger`,
icon: 'IconSettingsAutomation',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
trigger: WorkflowTrigger | null;
@WorkspaceField({
standardId: WORKFLOW_VERSION_STANDARD_FIELD_IDS.steps,
type: FieldMetadataType.RAW_JSON,
label: msg`Version steps`,
description: msg`Json object to provide steps`,
icon: 'IconSettingsAutomation',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
steps: WorkflowAction[] | null;
@WorkspaceField({
standardId: WORKFLOW_VERSION_STANDARD_FIELD_IDS.status,
type: FieldMetadataType.SELECT,
label: msg`Version status`,
description: msg`The workflow version status`,
icon: 'IconStatusChange',
options: WorkflowVersionStatusOptions,
defaultValue: "'DRAFT'",
})
@WorkspaceIsFieldUIReadOnly()
status: WorkflowVersionStatus;
@WorkspaceField({
standardId: WORKFLOW_VERSION_STANDARD_FIELD_IDS.position,
type: FieldMetadataType.POSITION,
label: msg`Position`,
description: msg`Workflow version position`,
icon: 'IconHierarchy2',
defaultValue: 0,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsSystem()
position: number;
@WorkspaceField({
standardId: WORKFLOW_VERSION_STANDARD_FIELD_IDS.searchVector,
type: FieldMetadataType.TS_VECTOR,
label: SEARCH_VECTOR_FIELD.label,
description: SEARCH_VECTOR_FIELD.description,
icon: 'IconUser',
generatedType: 'STORED',
asExpression: getTsVectorColumnExpressionFromFields(
SEARCH_FIELDS_FOR_WORKFLOW_VERSIONS,
),
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
@WorkspaceIsSystem()
@WorkspaceFieldIndex({ indexType: IndexType.GIN })
searchVector: string;
// Relations
@WorkspaceRelation({
standardId: WORKFLOW_VERSION_STANDARD_FIELD_IDS.workflow,
type: RelationType.MANY_TO_ONE,
label: msg`Workflow`,
description: msg`WorkflowVersion workflow`,
icon: 'IconSettingsAutomation',
inverseSideTarget: () => WorkflowWorkspaceEntity,
inverseSideFieldKey: 'versions',
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
workflow: Relation<WorkflowWorkspaceEntity>;
@WorkspaceJoinColumn('workflow')
workflow: EntityRelation<WorkflowWorkspaceEntity>;
workflowId: string;
@WorkspaceRelation({
standardId: WORKFLOW_VERSION_STANDARD_FIELD_IDS.runs,
type: RelationType.ONE_TO_MANY,
label: msg`Runs`,
description: msg`Workflow runs linked to the version.`,
icon: 'IconRun',
inverseSideTarget: () => WorkflowRunWorkspaceEntity,
onDelete: RelationOnDeleteAction.SET_NULL,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
runs: Relation<WorkflowRunWorkspaceEntity>;
@WorkspaceRelation({
standardId: WORKFLOW_VERSION_STANDARD_FIELD_IDS.favorites,
type: RelationType.ONE_TO_MANY,
label: msg`Favorites`,
description: msg`Favorites linked to the workflow version`,
icon: 'IconHeart',
inverseSideTarget: () => FavoriteWorkspaceEntity,
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsSystem()
favorites: Relation<FavoriteWorkspaceEntity[]>;
@WorkspaceRelation({
standardId: WORKFLOW_VERSION_STANDARD_FIELD_IDS.timelineActivities,
type: RelationType.ONE_TO_MANY,
label: msg`Timeline Activities`,
description: msg`Timeline activities linked to the version`,
inverseSideTarget: () => TimelineActivityWorkspaceEntity,
inverseSideFieldKey: 'targetWorkflowVersion',
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsSystem()
timelineActivities: Relation<TimelineActivityWorkspaceEntity[]>;
runs: EntityRelation<WorkflowRunWorkspaceEntity>;
favorites: EntityRelation<FavoriteWorkspaceEntity[]>;
timelineActivities: EntityRelation<TimelineActivityWorkspaceEntity[]>;
}
@@ -1,37 +1,14 @@
import { msg } from '@lingui/core/macro';
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
import {
ActorMetadata,
FieldMetadataType,
RelationOnDeleteAction,
} from 'twenty-shared/types';
import { type ActorMetadata, FieldMetadataType } from 'twenty-shared/types';
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
import { type FieldMetadataComplexOption } from 'src/engine/metadata-modules/field-metadata/dtos/options.input';
import { IndexType } from 'src/engine/metadata-modules/index-metadata/types/indexType.types';
import { SEARCH_VECTOR_FIELD } from 'src/engine/metadata-modules/search-field-metadata/constants/search-vector-field.constants';
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator';
import { WorkspaceFieldIndex } from 'src/engine/twenty-orm/decorators/workspace-field-index.decorator';
import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator';
import { WorkspaceIsFieldUIReadOnly } from 'src/engine/twenty-orm/decorators/workspace-is-field-ui-readonly.decorator';
import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator';
import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator';
import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator';
import { WORKFLOW_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons';
import {
type FieldTypeAndNameMetadata,
getTsVectorColumnExpressionFromFields,
} from 'src/engine/workspace-manager/workspace-sync-metadata/utils/get-ts-vector-column-expression.util';
import { AttachmentWorkspaceEntity } from 'src/modules/attachment/standard-objects/attachment.workspace-entity';
import { FavoriteWorkspaceEntity } from 'src/modules/favorite/standard-objects/favorite.workspace-entity';
import { TimelineActivityWorkspaceEntity } from 'src/modules/timeline/standard-objects/timeline-activity.workspace-entity';
import { WorkflowAutomatedTriggerWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow-automated-trigger.workspace-entity';
import { WorkflowRunWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow-run.workspace-entity';
import { WorkflowVersionWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow-version.workspace-entity';
import { type FieldTypeAndNameMetadata } from 'src/engine/workspace-manager/utils/get-ts-vector-column-expression.util';
import { type EntityRelation } from 'src/engine/workspace-manager/workspace-migration/types/entity-relation.interface';
import { type AttachmentWorkspaceEntity } from 'src/modules/attachment/standard-objects/attachment.workspace-entity';
import { type FavoriteWorkspaceEntity } from 'src/modules/favorite/standard-objects/favorite.workspace-entity';
import { type TimelineActivityWorkspaceEntity } from 'src/modules/timeline/standard-objects/timeline-activity.workspace-entity';
import { type WorkflowAutomatedTriggerWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow-automated-trigger.workspace-entity';
import { type WorkflowRunWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow-run.workspace-entity';
import { type WorkflowVersionWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow-version.workspace-entity';
export enum WorkflowStatus {
DRAFT = 'DRAFT',
@@ -39,195 +16,24 @@ export enum WorkflowStatus {
DEACTIVATED = 'DEACTIVATED',
}
const WorkflowStatusOptions: FieldMetadataComplexOption[] = [
{
value: WorkflowStatus.DRAFT,
label: 'Draft',
position: 0,
color: 'yellow',
},
{
value: WorkflowStatus.ACTIVE,
label: 'Active',
position: 1,
color: 'green',
},
{
value: WorkflowStatus.DEACTIVATED,
label: 'Deactivated',
position: 2,
color: 'gray',
},
];
const NAME_FIELD_NAME = 'name';
export const SEARCH_FIELDS_FOR_WORKFLOWS: FieldTypeAndNameMetadata[] = [
{ name: NAME_FIELD_NAME, type: FieldMetadataType.TEXT },
];
@WorkspaceEntity({
standardId: STANDARD_OBJECT_IDS.workflow,
namePlural: 'workflows',
labelSingular: msg`Workflow`,
labelPlural: msg`Workflows`,
description: msg`A workflow`,
icon: STANDARD_OBJECT_ICONS.workflow,
shortcut: 'W',
labelIdentifierStandardId: WORKFLOW_STANDARD_FIELD_IDS.name,
})
export class WorkflowWorkspaceEntity extends BaseWorkspaceEntity {
@WorkspaceField({
standardId: WORKFLOW_STANDARD_FIELD_IDS.name,
type: FieldMetadataType.TEXT,
label: msg`Name`,
description: msg`The workflow name`,
icon: 'IconSettingsAutomation',
})
@WorkspaceIsNullable()
name: string | null;
@WorkspaceField({
standardId: WORKFLOW_STANDARD_FIELD_IDS.lastPublishedVersionId,
type: FieldMetadataType.TEXT,
label: msg`Last published Version Id`,
description: msg`The workflow last published version id`,
icon: 'IconVersions',
})
@WorkspaceIsNullable()
@WorkspaceIsFieldUIReadOnly()
lastPublishedVersionId: string | null;
@WorkspaceField({
standardId: WORKFLOW_STANDARD_FIELD_IDS.statuses,
type: FieldMetadataType.MULTI_SELECT,
label: msg`Statuses`,
description: msg`The current statuses of the workflow versions`,
icon: 'IconStatusChange',
options: WorkflowStatusOptions,
})
@WorkspaceIsNullable()
@WorkspaceIsFieldUIReadOnly()
statuses: WorkflowStatus[] | null;
@WorkspaceField({
standardId: WORKFLOW_STANDARD_FIELD_IDS.position,
type: FieldMetadataType.POSITION,
label: msg`Position`,
description: msg`Workflow record position`,
icon: 'IconHierarchy2',
defaultValue: 0,
})
@WorkspaceIsSystem()
position: number;
@WorkspaceField({
standardId: WORKFLOW_STANDARD_FIELD_IDS.searchVector,
type: FieldMetadataType.TS_VECTOR,
label: SEARCH_VECTOR_FIELD.label,
description: SEARCH_VECTOR_FIELD.description,
icon: 'IconUser',
generatedType: 'STORED',
asExpression: getTsVectorColumnExpressionFromFields(
SEARCH_FIELDS_FOR_WORKFLOWS,
),
})
@WorkspaceIsNullable()
@WorkspaceIsSystem()
@WorkspaceFieldIndex({ indexType: IndexType.GIN })
searchVector: string;
// Relations
@WorkspaceRelation({
standardId: WORKFLOW_STANDARD_FIELD_IDS.versions,
type: RelationType.ONE_TO_MANY,
label: msg`Versions`,
description: msg`Workflow versions linked to the workflow.`,
icon: 'IconVersions',
inverseSideTarget: () => WorkflowVersionWorkspaceEntity,
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
versions: Relation<WorkflowVersionWorkspaceEntity[]>;
@WorkspaceRelation({
standardId: WORKFLOW_STANDARD_FIELD_IDS.runs,
type: RelationType.ONE_TO_MANY,
label: msg`Runs`,
description: msg`Workflow runs linked to the workflow.`,
icon: 'IconRun',
inverseSideTarget: () => WorkflowRunWorkspaceEntity,
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
runs: Relation<WorkflowRunWorkspaceEntity[]>;
@WorkspaceRelation({
standardId: WORKFLOW_STANDARD_FIELD_IDS.automatedTriggers,
type: RelationType.ONE_TO_MANY,
label: msg`Automated Triggers`,
description: msg`Workflow automated triggers linked to the workflow.`,
inverseSideTarget: () => WorkflowAutomatedTriggerWorkspaceEntity,
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsSystem()
@WorkspaceIsFieldUIReadOnly()
automatedTriggers: Relation<WorkflowAutomatedTriggerWorkspaceEntity[]>;
@WorkspaceRelation({
standardId: WORKFLOW_STANDARD_FIELD_IDS.favorites,
type: RelationType.ONE_TO_MANY,
label: msg`Favorites`,
description: msg`Favorites linked to the workflow`,
icon: 'IconHeart',
inverseSideTarget: () => FavoriteWorkspaceEntity,
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsSystem()
favorites: Relation<FavoriteWorkspaceEntity[]>;
@WorkspaceRelation({
standardId: WORKFLOW_STANDARD_FIELD_IDS.timelineActivities,
type: RelationType.ONE_TO_MANY,
label: msg`Timeline Activities`,
description: msg`Timeline activities linked to the workflow`,
inverseSideTarget: () => TimelineActivityWorkspaceEntity,
inverseSideFieldKey: 'targetWorkflow',
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsSystem()
timelineActivities: Relation<TimelineActivityWorkspaceEntity[]>;
@WorkspaceRelation({
standardId: WORKFLOW_STANDARD_FIELD_IDS.attachments,
type: RelationType.ONE_TO_MANY,
label: msg`Attachments`,
description: msg`Attachments linked to the workflow`,
icon: 'IconFileUpload',
inverseSideTarget: () => AttachmentWorkspaceEntity,
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsSystem()
attachments: Relation<AttachmentWorkspaceEntity[]>;
@WorkspaceField({
standardId: WORKFLOW_STANDARD_FIELD_IDS.createdBy,
type: FieldMetadataType.ACTOR,
label: msg`Created by`,
icon: 'IconCreativeCommonsSa',
description: msg`The creator of the record`,
})
@WorkspaceIsFieldUIReadOnly()
versions: EntityRelation<WorkflowVersionWorkspaceEntity[]>;
runs: EntityRelation<WorkflowRunWorkspaceEntity[]>;
automatedTriggers: EntityRelation<WorkflowAutomatedTriggerWorkspaceEntity[]>;
favorites: EntityRelation<FavoriteWorkspaceEntity[]>;
timelineActivities: EntityRelation<TimelineActivityWorkspaceEntity[]>;
attachments: EntityRelation<AttachmentWorkspaceEntity[]>;
createdBy: ActorMetadata;
@WorkspaceField({
standardId: WORKFLOW_STANDARD_FIELD_IDS.updatedBy,
type: FieldMetadataType.ACTOR,
label: msg`Updated by`,
icon: 'IconUserCircle',
description: msg`The workspace member who last updated the record`,
})
@WorkspaceIsFieldUIReadOnly()
updatedBy: ActorMetadata;
}
@@ -7,9 +7,9 @@ import { type WorkspaceAuthContext } from 'src/engine/api/common/interfaces/work
import { ApplicationService } from 'src/engine/core-modules/application/application.service';
import { UserWorkspaceService } from 'src/engine/core-modules/user-workspace/user-workspace.service';
import { ADMIN_ROLE } from 'src/engine/metadata-modules/role/constants/admin-role';
import { RoleService } from 'src/engine/metadata-modules/role/role.service';
import { UserRoleService } from 'src/engine/metadata-modules/user-role/user-role.service';
import { ADMIN_ROLE } from 'src/engine/workspace-manager/workspace-sync-metadata/standard-roles/roles/admin-role';
import { type WorkflowRunWorkspaceEntity } from 'src/modules/workflow/common/standard-objects/workflow-run.workspace-entity';
import { type WorkflowExecutionContext } from 'src/modules/workflow/workflow-executor/types/workflow-execution-context.type';
import { WorkflowRunWorkspaceService as WorkflowRunService } from 'src/modules/workflow/workflow-runner/workflow-run/workflow-run.workspace-service';
@@ -1,45 +1,20 @@
import { registerEnumType } from '@nestjs/graphql';
import { msg } from '@lingui/core/macro';
import { STANDARD_OBJECT_IDS } from 'twenty-shared/metadata';
import { type APP_LOCALES, SOURCE_LOCALE } from 'twenty-shared/translations';
import {
FieldMetadataType,
FullNameMetadata,
NumberDataType,
RelationOnDeleteAction,
} from 'twenty-shared/types';
import { type APP_LOCALES } from 'twenty-shared/translations';
import { FieldMetadataType, type FullNameMetadata } from 'twenty-shared/types';
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface';
import { IndexType } from 'src/engine/metadata-modules/index-metadata/types/indexType.types';
import { SEARCH_VECTOR_FIELD } from 'src/engine/metadata-modules/search-field-metadata/constants/search-vector-field.constants';
import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity';
import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator';
import { WorkspaceFieldIndex } from 'src/engine/twenty-orm/decorators/workspace-field-index.decorator';
import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator';
import { WorkspaceIsFieldUIReadOnly } from 'src/engine/twenty-orm/decorators/workspace-is-field-ui-readonly.decorator';
import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator';
import { WorkspaceIsSearchable } from 'src/engine/twenty-orm/decorators/workspace-is-searchable.decorator';
import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator';
import { WorkspaceIsUnique } from 'src/engine/twenty-orm/decorators/workspace-is-unique.decorator';
import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator';
import { WORKSPACE_MEMBER_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids';
import { STANDARD_OBJECT_ICONS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-icons';
import {
type FieldTypeAndNameMetadata,
getTsVectorColumnExpressionFromFields,
} from 'src/engine/workspace-manager/workspace-sync-metadata/utils/get-ts-vector-column-expression.util';
import { AttachmentWorkspaceEntity } from 'src/modules/attachment/standard-objects/attachment.workspace-entity';
import { BlocklistWorkspaceEntity } from 'src/modules/blocklist/standard-objects/blocklist.workspace-entity';
import { CalendarEventParticipantWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-event-participant.workspace-entity';
import { CompanyWorkspaceEntity } from 'src/modules/company/standard-objects/company.workspace-entity';
import { ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
import { FavoriteWorkspaceEntity } from 'src/modules/favorite/standard-objects/favorite.workspace-entity';
import { MessageParticipantWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-participant.workspace-entity';
import { TaskWorkspaceEntity } from 'src/modules/task/standard-objects/task.workspace-entity';
import { TimelineActivityWorkspaceEntity } from 'src/modules/timeline/standard-objects/timeline-activity.workspace-entity';
import { type FieldTypeAndNameMetadata } from 'src/engine/workspace-manager/utils/get-ts-vector-column-expression.util';
import { type EntityRelation } from 'src/engine/workspace-manager/workspace-migration/types/entity-relation.interface';
import { type AttachmentWorkspaceEntity } from 'src/modules/attachment/standard-objects/attachment.workspace-entity';
import { type BlocklistWorkspaceEntity } from 'src/modules/blocklist/standard-objects/blocklist.workspace-entity';
import { type CalendarEventParticipantWorkspaceEntity } from 'src/modules/calendar/common/standard-objects/calendar-event-participant.workspace-entity';
import { type CompanyWorkspaceEntity } from 'src/modules/company/standard-objects/company.workspace-entity';
import { type ConnectedAccountWorkspaceEntity } from 'src/modules/connected-account/standard-objects/connected-account.workspace-entity';
import { type FavoriteWorkspaceEntity } from 'src/modules/favorite/standard-objects/favorite.workspace-entity';
import { type MessageParticipantWorkspaceEntity } from 'src/modules/messaging/common/standard-objects/message-participant.workspace-entity';
import { type TaskWorkspaceEntity } from 'src/modules/task/standard-objects/task.workspace-entity';
import { type TimelineActivityWorkspaceEntity } from 'src/modules/timeline/standard-objects/timeline-activity.workspace-entity';
export enum WorkspaceMemberDateFormatEnum {
SYSTEM = 'SYSTEM',
@@ -86,378 +61,29 @@ export const SEARCH_FIELDS_FOR_WORKSPACE_MEMBER: FieldTypeAndNameMetadata[] = [
{ name: USER_EMAIL_FIELD_NAME, type: FieldMetadataType.TEXT },
];
@WorkspaceEntity({
standardId: STANDARD_OBJECT_IDS.workspaceMember,
namePlural: 'workspaceMembers',
labelSingular: msg`Workspace Member`,
labelPlural: msg`Workspace Members`,
description: msg`A workspace member`,
icon: STANDARD_OBJECT_ICONS.workspaceMember,
labelIdentifierStandardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.name,
imageIdentifierStandardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.avatarUrl,
})
@WorkspaceIsSystem()
@WorkspaceIsSearchable()
export class WorkspaceMemberWorkspaceEntity extends BaseWorkspaceEntity {
@WorkspaceField({
standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.position,
type: FieldMetadataType.POSITION,
label: msg`Position`,
description: msg`Workspace member position`,
icon: 'IconHierarchy2',
defaultValue: 0,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsSystem()
position: number;
@WorkspaceField({
standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.name,
type: FieldMetadataType.FULL_NAME,
label: msg`Name`,
description: msg`Workspace member name`,
icon: 'IconCircleUser',
})
@WorkspaceIsFieldUIReadOnly()
name: FullNameMetadata;
@WorkspaceField({
standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.colorScheme,
type: FieldMetadataType.TEXT,
label: msg`Color Scheme`,
description: msg`Preferred color scheme`,
icon: 'IconColorSwatch',
defaultValue: "'System'",
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsSystem()
colorScheme: string;
@WorkspaceField({
standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.locale,
type: FieldMetadataType.TEXT,
label: msg`Language`,
description: msg`Preferred language`,
icon: 'IconLanguage',
defaultValue: `'${SOURCE_LOCALE}'`,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsSystem()
locale: keyof typeof APP_LOCALES;
@WorkspaceField({
standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.avatarUrl,
type: FieldMetadataType.TEXT,
label: msg`Avatar Url`,
description: msg`Workspace member avatar`,
icon: 'IconFileUpload',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
@WorkspaceIsSystem()
avatarUrl: string | null;
@WorkspaceIsUnique()
@WorkspaceField({
standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.userEmail,
type: FieldMetadataType.TEXT,
label: msg`User Email`,
description: msg`Related user email address`,
icon: 'IconMail',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
@WorkspaceIsSystem()
userEmail: string | null;
@WorkspaceField({
standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.calendarStartDay,
type: FieldMetadataType.NUMBER,
label: msg`Start of the week`,
defaultValue: 7,
description: msg`User's preferred start day of the week`,
settings: {
dataType: NumberDataType.INT,
},
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsSystem()
calendarStartDay: number;
@WorkspaceField({
standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.userId,
type: FieldMetadataType.UUID,
label: msg`User Id`,
description: msg`Associated User Id`,
icon: 'IconCircleUsers',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsSystem()
userId: string;
@WorkspaceField({
standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.timeZone,
type: FieldMetadataType.TEXT,
label: msg`Time zone`,
defaultValue: "'system'",
description: msg`User time zone`,
icon: 'IconTimezone',
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsSystem()
timeZone: string;
@WorkspaceField({
standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.dateFormat,
type: FieldMetadataType.SELECT,
label: msg`Date format`,
description: msg`User's preferred date format`,
icon: 'IconCalendarEvent',
options: [
{
value: WorkspaceMemberDateFormatEnum.SYSTEM,
label: 'System',
position: 0,
color: 'turquoise',
},
{
value: WorkspaceMemberDateFormatEnum.MONTH_FIRST,
label: 'Month First',
position: 1,
color: 'red',
},
{
value: WorkspaceMemberDateFormatEnum.DAY_FIRST,
label: 'Day First',
position: 2,
color: 'purple',
},
{
value: WorkspaceMemberDateFormatEnum.YEAR_FIRST,
label: 'Year First',
position: 3,
color: 'sky',
},
],
defaultValue: `'${WorkspaceMemberDateFormatEnum.SYSTEM}'`,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsSystem()
dateFormat: string;
@WorkspaceField({
standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.timeFormat,
type: FieldMetadataType.SELECT,
label: msg`Time format`,
description: msg`User's preferred time format`,
icon: 'IconClock2',
options: [
{
value: WorkspaceMemberTimeFormatEnum.SYSTEM,
label: 'System',
position: 0,
color: 'sky',
},
{
value: WorkspaceMemberTimeFormatEnum.HOUR_24,
label: '24HRS',
position: 1,
color: 'red',
},
{
value: WorkspaceMemberTimeFormatEnum.HOUR_12,
label: '12HRS',
position: 2,
color: 'purple',
},
],
defaultValue: `'${WorkspaceMemberTimeFormatEnum.SYSTEM}'`,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsSystem()
timeFormat: string;
// Relations
@WorkspaceRelation({
standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.assignedTasks,
type: RelationType.ONE_TO_MANY,
label: msg`Assigned tasks`,
description: msg`Tasks assigned to the workspace member`,
icon: 'IconCheckbox',
inverseSideTarget: () => TaskWorkspaceEntity,
inverseSideFieldKey: 'assignee',
onDelete: RelationOnDeleteAction.SET_NULL,
})
@WorkspaceIsFieldUIReadOnly()
assignedTasks: Relation<TaskWorkspaceEntity[]>;
@WorkspaceRelation({
standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.favorites,
type: RelationType.ONE_TO_MANY,
label: msg`Favorites`,
description: msg`Favorites linked to the workspace member`,
icon: 'IconHeart',
inverseSideTarget: () => FavoriteWorkspaceEntity,
inverseSideFieldKey: 'forWorkspaceMember',
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
favorites: Relation<FavoriteWorkspaceEntity[]>;
@WorkspaceRelation({
standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.accountOwnerForCompanies,
type: RelationType.ONE_TO_MANY,
label: msg`Account Owner For Companies`,
description: msg`Account owner for companies`,
icon: 'IconBriefcase',
inverseSideTarget: () => CompanyWorkspaceEntity,
inverseSideFieldKey: 'accountOwner',
onDelete: RelationOnDeleteAction.SET_NULL,
})
@WorkspaceIsFieldUIReadOnly()
accountOwnerForCompanies: Relation<CompanyWorkspaceEntity[]>;
@WorkspaceRelation({
standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.authoredAttachments,
type: RelationType.ONE_TO_MANY,
label: msg`Authored attachments`,
description: msg`Attachments created by the workspace member`,
icon: 'IconFileImport',
inverseSideTarget: () => AttachmentWorkspaceEntity,
inverseSideFieldKey: 'author',
onDelete: RelationOnDeleteAction.SET_NULL,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsSystem()
authoredAttachments: Relation<AttachmentWorkspaceEntity[]>;
@WorkspaceRelation({
standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.connectedAccounts,
type: RelationType.ONE_TO_MANY,
label: msg`Connected accounts`,
description: msg`Connected accounts`,
icon: 'IconAt',
inverseSideTarget: () => ConnectedAccountWorkspaceEntity,
inverseSideFieldKey: 'accountOwner',
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
connectedAccounts: Relation<ConnectedAccountWorkspaceEntity[]>;
@WorkspaceRelation({
standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.messageParticipants,
type: RelationType.ONE_TO_MANY,
label: msg`Message Participants`,
description: msg`Message Participants`,
icon: 'IconUserCircle',
inverseSideTarget: () => MessageParticipantWorkspaceEntity,
inverseSideFieldKey: 'workspaceMember',
onDelete: RelationOnDeleteAction.SET_NULL,
})
@WorkspaceIsFieldUIReadOnly()
messageParticipants: Relation<MessageParticipantWorkspaceEntity[]>;
@WorkspaceRelation({
standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.blocklist,
type: RelationType.ONE_TO_MANY,
label: msg`Blocklist`,
description: msg`Blocklisted handles`,
icon: 'IconForbid2',
inverseSideTarget: () => BlocklistWorkspaceEntity,
inverseSideFieldKey: 'workspaceMember',
onDelete: RelationOnDeleteAction.SET_NULL,
})
@WorkspaceIsFieldUIReadOnly()
blocklist: Relation<BlocklistWorkspaceEntity[]>;
@WorkspaceRelation({
standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.calendarEventParticipants,
type: RelationType.ONE_TO_MANY,
label: msg`Calendar Event Participants`,
description: msg`Calendar Event Participants`,
icon: 'IconCalendar',
inverseSideTarget: () => CalendarEventParticipantWorkspaceEntity,
inverseSideFieldKey: 'workspaceMember',
onDelete: RelationOnDeleteAction.SET_NULL,
})
@WorkspaceIsFieldUIReadOnly()
calendarEventParticipants: Relation<
assignedTasks: EntityRelation<TaskWorkspaceEntity[]>;
favorites: EntityRelation<FavoriteWorkspaceEntity[]>;
accountOwnerForCompanies: EntityRelation<CompanyWorkspaceEntity[]>;
authoredAttachments: EntityRelation<AttachmentWorkspaceEntity[]>;
connectedAccounts: EntityRelation<ConnectedAccountWorkspaceEntity[]>;
messageParticipants: EntityRelation<MessageParticipantWorkspaceEntity[]>;
blocklist: EntityRelation<BlocklistWorkspaceEntity[]>;
calendarEventParticipants: EntityRelation<
CalendarEventParticipantWorkspaceEntity[]
>;
@WorkspaceRelation({
standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.timelineActivities,
type: RelationType.ONE_TO_MANY,
label: msg`Events`,
description: msg`Events linked to the workspace member`,
icon: 'IconTimelineEvent',
inverseSideTarget: () => TimelineActivityWorkspaceEntity,
onDelete: RelationOnDeleteAction.CASCADE,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
@WorkspaceIsSystem()
timelineActivities: Relation<TimelineActivityWorkspaceEntity[]>;
@WorkspaceField({
standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.searchVector,
type: FieldMetadataType.TS_VECTOR,
label: SEARCH_VECTOR_FIELD.label,
description: SEARCH_VECTOR_FIELD.description,
icon: 'IconUser',
generatedType: 'STORED',
asExpression: getTsVectorColumnExpressionFromFields(
SEARCH_FIELDS_FOR_WORKSPACE_MEMBER,
),
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsNullable()
@WorkspaceIsSystem()
@WorkspaceFieldIndex({ indexType: IndexType.GIN })
timelineActivities: EntityRelation<TimelineActivityWorkspaceEntity[]>;
searchVector: string;
@WorkspaceField({
standardId: WORKSPACE_MEMBER_STANDARD_FIELD_IDS.numberFormat,
type: FieldMetadataType.SELECT,
label: msg`Number format`,
description: msg`User's preferred number format`,
icon: 'IconNumbers',
options: [
{
value: WorkspaceMemberNumberFormatEnum.SYSTEM,
label: 'System',
position: 0,
color: 'turquoise',
},
{
value: WorkspaceMemberNumberFormatEnum.COMMAS_AND_DOT,
label: 'Commas and dot',
position: 1,
color: 'blue',
},
{
value: WorkspaceMemberNumberFormatEnum.SPACES_AND_COMMA,
label: 'Spaces and comma',
position: 2,
color: 'green',
},
{
value: WorkspaceMemberNumberFormatEnum.DOTS_AND_COMMA,
label: 'Dots and comma',
position: 3,
color: 'orange',
},
{
value: WorkspaceMemberNumberFormatEnum.APOSTROPHE_AND_DOT,
label: 'Apostrophe and dot',
position: 4,
color: 'purple',
},
],
defaultValue: `'${WorkspaceMemberNumberFormatEnum.SYSTEM}'`,
})
@WorkspaceIsFieldUIReadOnly()
@WorkspaceIsSystem()
numberFormat: string;
}