diff --git a/packages/twenty-server/src/database/commands/data-seed-dev-workspace.command.ts b/packages/twenty-server/src/database/commands/data-seed-dev-workspace.command.ts index f7d5475ee..d4edeeef8 100644 --- a/packages/twenty-server/src/database/commands/data-seed-dev-workspace.command.ts +++ b/packages/twenty-server/src/database/commands/data-seed-dev-workspace.command.ts @@ -29,6 +29,7 @@ import { DataSourceService } from 'src/engine/metadata-modules/data-source/data- import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service'; import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service'; import { viewPrefillData } from 'src/engine/workspace-manager/standard-objects-prefill-data/view'; +import { workflowPrefillData } from 'src/engine/workspace-manager/standard-objects-prefill-data/workflow'; import { WorkspaceSyncMetadataService } from 'src/engine/workspace-manager/workspace-sync-metadata/workspace-sync-metadata.service'; // TODO: implement dry-run @@ -124,6 +125,7 @@ export class DataSeedWorkspaceCommand extends CommandRunner { dataSourceMetadata.schema, workspaceId, ); + await workflowPrefillData(entityManager, dataSourceMetadata.schema); if (workspaceId === SEED_APPLE_WORKSPACE_ID) { await seedMessageThread(entityManager, dataSourceMetadata.schema); diff --git a/packages/twenty-server/src/database/typeorm-seeds/core/feature-flags.ts b/packages/twenty-server/src/database/typeorm-seeds/core/feature-flags.ts index a030ad88f..c4e42f81b 100644 --- a/packages/twenty-server/src/database/typeorm-seeds/core/feature-flags.ts +++ b/packages/twenty-server/src/database/typeorm-seeds/core/feature-flags.ts @@ -50,6 +50,11 @@ export const seedFeatureFlags = async ( workspaceId: workspaceId, value: true, }, + { + key: FeatureFlagKeys.IsWorkflowEnabled, + workspaceId: workspaceId, + value: false, + }, ]) .execute(); }; diff --git a/packages/twenty-server/src/engine/core-modules/feature-flag/feature-flag.entity.ts b/packages/twenty-server/src/engine/core-modules/feature-flag/feature-flag.entity.ts index b06466190..9ee46f127 100644 --- a/packages/twenty-server/src/engine/core-modules/feature-flag/feature-flag.entity.ts +++ b/packages/twenty-server/src/engine/core-modules/feature-flag/feature-flag.entity.ts @@ -25,6 +25,7 @@ export enum FeatureFlagKeys { IsMessagingAliasFetchingEnabled = 'IS_MESSAGING_ALIAS_FETCHING_ENABLED', IsGoogleCalendarSyncV2Enabled = 'IS_GOOGLE_CALENDAR_SYNC_V2_ENABLED', IsFreeAccessEnabled = 'IS_FREE_ACCESS_ENABLED', + IsWorkflowEnabled = 'IS_WORKFLOW_ENABLED', } @Entity({ name: 'featureFlag', schema: 'core' }) diff --git a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/standard-objects-prefill-data.ts b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/standard-objects-prefill-data.ts index 4e404878f..9bcbe8dde 100644 --- a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/standard-objects-prefill-data.ts +++ b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/standard-objects-prefill-data.ts @@ -1,9 +1,10 @@ import { DataSource, EntityManager } from 'typeorm'; import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; -import { viewPrefillData } from 'src/engine/workspace-manager/standard-objects-prefill-data/view'; import { companyPrefillData } from 'src/engine/workspace-manager/standard-objects-prefill-data/company'; import { personPrefillData } from 'src/engine/workspace-manager/standard-objects-prefill-data/person'; +import { viewPrefillData } from 'src/engine/workspace-manager/standard-objects-prefill-data/view'; +import { workflowPrefillData } from 'src/engine/workspace-manager/standard-objects-prefill-data/workflow'; export const standardObjectsPrefillData = async ( workspaceDataSource: DataSource, @@ -34,6 +35,7 @@ export const standardObjectsPrefillData = async ( workspaceDataSource.transaction(async (entityManager: EntityManager) => { await companyPrefillData(entityManager, schemaName); await personPrefillData(entityManager, schemaName); + await workflowPrefillData(entityManager, schemaName); await viewPrefillData(entityManager, schemaName, objectMetadataMap); }); }; diff --git a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/view-workflow-fields.ts b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/view-workflow-fields.ts new file mode 100644 index 000000000..d5ea0a7e1 --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/view-workflow-fields.ts @@ -0,0 +1,31 @@ +import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; +import { WORKFLOW_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; +import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; + +export const viewWorkflowFields = ( + viewId: string, + objectMetadataMap: Record, +) => { + return [ + { + fieldMetadataId: + objectMetadataMap[STANDARD_OBJECT_IDS.workflow].fields[ + WORKFLOW_STANDARD_FIELD_IDS.name + ], + viewId: viewId, + position: 0, + isVisible: true, + size: 210, + }, + { + fieldMetadataId: + objectMetadataMap[STANDARD_OBJECT_IDS.workflow].fields[ + WORKFLOW_STANDARD_FIELD_IDS.publishedVersionId + ], + viewId: viewId, + position: 1, + isVisible: true, + size: 150, + }, + ]; +}; diff --git a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/view.ts b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/view.ts index 242dfafed..b233e147e 100644 --- a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/view.ts +++ b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/view.ts @@ -2,10 +2,11 @@ import { EntityManager } from 'typeorm'; import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { viewCompanyFields } from 'src/engine/workspace-manager/standard-objects-prefill-data/view-company-fields'; -import { viewPersonFields } from 'src/engine/workspace-manager/standard-objects-prefill-data/view-person-fields'; import { viewOpportunityFields } from 'src/engine/workspace-manager/standard-objects-prefill-data/view-opportunity-fields'; -import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; +import { viewPersonFields } from 'src/engine/workspace-manager/standard-objects-prefill-data/view-person-fields'; +import { viewWorkflowFields } from 'src/engine/workspace-manager/standard-objects-prefill-data/view-workflow-fields'; import { OPPORTUNITY_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; +import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; export const viewPrefillData = async ( entityManager: EntityManager, @@ -64,6 +65,15 @@ export const viewPrefillData = async ( OPPORTUNITY_STANDARD_FIELD_IDS.stage ], }, + { + name: 'All Workflows', + objectMetadataId: objectMetadataMap[STANDARD_OBJECT_IDS.workflow].id, + type: 'table', + key: 'INDEX', + position: 0, + icon: 'IconSettingsAutomation', + kanbanFieldMetadataId: '', + }, ]) .returning('*') .execute(); @@ -92,6 +102,7 @@ export const viewPrefillData = async ( objectMetadataMap, ), ...viewOpportunityFields(viewIdMap['By Stage'], objectMetadataMap), + ...viewWorkflowFields(viewIdMap['All Workflows'], objectMetadataMap), ]) .execute(); }; diff --git a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/workflow-version.ts b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/workflow-version.ts new file mode 100644 index 000000000..e69de29bb diff --git a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/workflow.ts b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/workflow.ts new file mode 100644 index 000000000..7022dbd4a --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/workflow.ts @@ -0,0 +1,21 @@ +import { EntityManager } from 'typeorm'; + +export const workflowPrefillData = async ( + entityManager: EntityManager, + schemaName: string, +) => { + await entityManager + .createQueryBuilder() + .insert() + .into(`${schemaName}.workflow`, ['name', 'publishedVersionId', 'position']) + .orIgnore() + .values([ + { + name: 'Update Subscription Status', + publishedVersionId: null, + position: 1, + }, + ]) + .returning('*') + .execute(); +}; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/commands/add-standard-id.command.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/commands/add-standard-id.command.ts index f351cfabf..3f72b8dae 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/commands/add-standard-id.command.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/commands/add-standard-id.command.ts @@ -62,6 +62,7 @@ export class AddStandardIdCommand extends CommandRunner { IS_MESSAGING_ALIAS_FETCHING_ENABLED: true, IS_GOOGLE_CALENDAR_SYNC_V2_ENABLED: true, IS_FREE_ACCESS_ENABLED: false, + IS_WORKFLOW_ENABLED: false, }, ); const standardFieldMetadataCollection = this.standardFieldFactory.create( @@ -80,6 +81,7 @@ export class AddStandardIdCommand extends CommandRunner { IS_MESSAGING_ALIAS_FETCHING_ENABLED: true, IS_GOOGLE_CALENDAR_SYNC_V2_ENABLED: true, IS_FREE_ACCESS_ENABLED: false, + IS_WORKFLOW_ENABLED: false, }, ); diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids.ts index 0778c007c..af6e7dd97 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids.ts @@ -10,6 +10,7 @@ export const ACTIVITY_TARGET_STANDARD_FIELD_IDS = { person: '20202020-4afd-4ae7-99c2-de57d795a93f', company: '20202020-7cc0-44a1-8068-f11171fdd02e', opportunity: '20202020-1fc2-4af1-8c91-7901ee0fd38b', + workflow: '20202020-a63d-40d0-b24d-ddcc1347d583', custom: '20202020-7f21-442f-94be-32462281b1ca', }; @@ -42,6 +43,7 @@ export const ATTACHMENT_STANDARD_FIELD_IDS = { person: '20202020-0158-4aa2-965c-5cdafe21ffa2', company: '20202020-ceab-4a28-b546-73b06b4c08d5', opportunity: '20202020-7374-499d-bea3-9354890755b5', + workflow: '20202020-0906-4dc3-b26f-edc951c7ab82', custom: '20202020-302d-43b3-9aea-aa4f89282a9f', }; @@ -180,6 +182,7 @@ export const TIMELINE_ACTIVITY_STANDARD_FIELD_IDS = { person: '20202020-c414-45b9-a60a-ac27aa96229f', company: '20202020-04ad-4221-a744-7a8278a5ce21', opportunity: '20202020-7664-4a35-a3df-580d389fd527', + workflow: '20202020-9e59-4030-aa27-55abd676c3c8', custom: '20202020-4a71-41b0-9f83-9cdcca3f8b14', linkedRecordCachedName: '20202020-cfdb-4bef-bbce-a29f41230934', linkedRecordId: '20202020-2e0e-48c0-b445-ee6c1e61687d', @@ -192,6 +195,7 @@ export const FAVORITE_STANDARD_FIELD_IDS = { person: '20202020-c428-4f40-b6f3-86091511c41c', company: '20202020-cff5-4682-8bf9-069169e08279', opportunity: '20202020-dabc-48e1-8318-2781a2b32aa2', + workflow: '20202020-b11b-4dc8-999a-6bd0a947b463', custom: '20202020-855a-4bc8-9861-79deef37011f', }; @@ -323,6 +327,23 @@ export const WEBHOOK_STANDARD_FIELD_IDS = { operation: '20202020-15b7-458e-bf30-74770a54410c', }; +export const WORKFLOW_STANDARD_FIELD_IDS = { + name: '20202020-b3d3-478f-acc0-5d901e725b20', + publishedVersionId: '20202020-326a-4fba-8639-3456c0a169e8', + versions: '20202020-9432-416e-8f3c-27ee3153d099', + position: '20202020-39b0-4d8c-8c5f-33c2326deb5f', + favorites: '20202020-c554-4c41-be7a-cf9cd4b0d512', + activityTargets: '20202020-9d65-445a-899d-1c6f1cf3a9ab', + attachments: '20202020-ea95-4d4d-81cd-9921740316b8', + timelineActivities: '20202020-dd79-492a-9d11-58333ed0f71a', +}; + +export const WORKFLOW_VERSION_STANDARD_FIELD_IDS = { + name: '20202020-a12f-4cca-9937-a2e40cc65509', + workflow: '20202020-afa3-46c3-91b0-0631ca6aa1c8', + trigger: '20202020-4eae-43e7-86e0-212b41a30b48', +}; + export const WORKSPACE_MEMBER_STANDARD_FIELD_IDS = { name: '20202020-e914-43a6-9c26-3603c59065f4', colorScheme: '20202020-66bc-47f2-adac-f2ef7c598b63', diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids.ts index 19ad7b4e2..100f4aa3b 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids.ts @@ -34,5 +34,7 @@ export const STANDARD_OBJECT_IDS = { viewSort: '20202020-e46a-47a8-939a-e5d911f83531', view: '20202020-722e-4739-8e2c-0c372d661f49', webhook: '20202020-be4d-4e08-811d-0fffcd13ffd4', - workspaceMember: '20202020-3319-4234-a34c-82d5c0e881a6', + workflow: '20202020-62be-406c-b9ca-8caa50d51392', + workflowVersion: '20202020-d65d-4ab9-9344-d77bfb376a3d', + workspaceMember: '20202020-2632-4659-9540-567498166593', }; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/standard-objects/index.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/standard-objects/index.ts index 43d591382..f8e4d410a 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/standard-objects/index.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/standard-objects/index.ts @@ -26,6 +26,8 @@ import { ViewFilterWorkspaceEntity } from 'src/modules/view/standard-objects/vie import { ViewSortWorkspaceEntity } from 'src/modules/view/standard-objects/view-sort.workspace-entity'; import { ViewWorkspaceEntity } from 'src/modules/view/standard-objects/view.workspace-entity'; import { WebhookWorkspaceEntity } from 'src/modules/webhook/standard-objects/webhook.workspace-entity'; +import { WorkflowVersionWorkspaceEntity } from 'src/modules/workflow/standard-objects/workflow-version.workspace-entity'; +import { WorkflowWorkspaceEntity } from 'src/modules/workflow/standard-objects/workflow.workspace-entity'; import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity'; // TODO: Maybe we should automate this with the DiscoverService of Nest.JS @@ -53,6 +55,8 @@ export const standardObjectMetadataDefinitions = [ ViewSortWorkspaceEntity, ViewWorkspaceEntity, WebhookWorkspaceEntity, + WorkflowWorkspaceEntity, + WorkflowVersionWorkspaceEntity, WorkspaceMemberWorkspaceEntity, MessageThreadWorkspaceEntity, MessageWorkspaceEntity, diff --git a/packages/twenty-server/src/modules/activity/standard-objects/activity-target.workspace-entity.ts b/packages/twenty-server/src/modules/activity/standard-objects/activity-target.workspace-entity.ts index dd2ef18cb..0a6361f09 100644 --- a/packages/twenty-server/src/modules/activity/standard-objects/activity-target.workspace-entity.ts +++ b/packages/twenty-server/src/modules/activity/standard-objects/activity-target.workspace-entity.ts @@ -1,20 +1,21 @@ import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface'; +import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; +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 { 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 { ACTIVITY_TARGET_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; -import { CustomWorkspaceEntity } from 'src/engine/twenty-orm/custom.workspace-entity'; import { ActivityWorkspaceEntity } from 'src/modules/activity/standard-objects/activity.workspace-entity'; 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 { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator'; -import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; -import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; -import { WorkspaceDynamicRelation } from 'src/engine/twenty-orm/decorators/workspace-dynamic-relation.decorator'; -import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; -import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; -import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; -import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; +import { WorkflowWorkspaceEntity } from 'src/modules/workflow/standard-objects/workflow.workspace-entity'; @WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.activityTarget, @@ -86,6 +87,21 @@ export class ActivityTargetWorkspaceEntity extends BaseWorkspaceEntity { @WorkspaceJoinColumn('opportunity') opportunityId: string | null; + @WorkspaceRelation({ + standardId: ACTIVITY_TARGET_STANDARD_FIELD_IDS.workflow, + type: RelationMetadataType.MANY_TO_ONE, + label: 'Workflow', + description: 'ActivityTarget workflow', + icon: 'IconSettingsAutomation', + inverseSideTarget: () => WorkflowWorkspaceEntity, + inverseSideFieldKey: 'activityTargets', + }) + @WorkspaceIsNullable() + workflow: Relation | null; + + @WorkspaceJoinColumn('workflow') + workflowId: string | null; + @WorkspaceDynamicRelation({ type: RelationMetadataType.MANY_TO_ONE, argsFactory: (oppositeObjectMetadata) => ({ diff --git a/packages/twenty-server/src/modules/attachment/standard-objects/attachment.workspace-entity.ts b/packages/twenty-server/src/modules/attachment/standard-objects/attachment.workspace-entity.ts index 6fea68a89..ed13383e4 100644 --- a/packages/twenty-server/src/modules/attachment/standard-objects/attachment.workspace-entity.ts +++ b/packages/twenty-server/src/modules/attachment/standard-objects/attachment.workspace-entity.ts @@ -18,6 +18,7 @@ import { ActivityWorkspaceEntity } from 'src/modules/activity/standard-objects/a 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 { WorkflowWorkspaceEntity } from 'src/modules/workflow/standard-objects/workflow.workspace-entity'; import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity'; @WorkspaceEntity({ @@ -133,6 +134,21 @@ export class AttachmentWorkspaceEntity extends BaseWorkspaceEntity { @WorkspaceJoinColumn('opportunity') opportunityId: string | null; + @WorkspaceRelation({ + standardId: ATTACHMENT_STANDARD_FIELD_IDS.workflow, + type: RelationMetadataType.MANY_TO_ONE, + label: 'Workflow', + description: 'Attachment workflow', + icon: 'IconSettingsAutomation', + inverseSideTarget: () => WorkflowWorkspaceEntity, + inverseSideFieldKey: 'attachments', + }) + @WorkspaceIsNullable() + workflow: Relation | null; + + @WorkspaceJoinColumn('workflow') + workflowId: string | null; + @WorkspaceDynamicRelation({ type: RelationMetadataType.MANY_TO_ONE, argsFactory: (oppositeObjectMetadata) => ({ diff --git a/packages/twenty-server/src/modules/favorite/standard-objects/favorite.workspace-entity.ts b/packages/twenty-server/src/modules/favorite/standard-objects/favorite.workspace-entity.ts index 705c62d32..92988bbcd 100644 --- a/packages/twenty-server/src/modules/favorite/standard-objects/favorite.workspace-entity.ts +++ b/packages/twenty-server/src/modules/favorite/standard-objects/favorite.workspace-entity.ts @@ -1,23 +1,24 @@ import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface'; import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; +import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; +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 { 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 { FAVORITE_STANDARD_FIELD_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-field-ids'; import { STANDARD_OBJECT_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; -import { CustomWorkspaceEntity } from 'src/engine/twenty-orm/custom.workspace-entity'; 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 { WorkflowWorkspaceEntity } from 'src/modules/workflow/standard-objects/workflow.workspace-entity'; import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity'; -import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; -import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator'; -import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator'; -import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; -import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator'; -import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; -import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; -import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; -import { WorkspaceDynamicRelation } from 'src/engine/twenty-orm/decorators/workspace-dynamic-relation.decorator'; -import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; @WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.favorite, @@ -100,6 +101,21 @@ export class FavoriteWorkspaceEntity extends BaseWorkspaceEntity { @WorkspaceJoinColumn('opportunity') opportunityId: string; + @WorkspaceRelation({ + standardId: FAVORITE_STANDARD_FIELD_IDS.workflow, + type: RelationMetadataType.MANY_TO_ONE, + label: 'Workflow', + description: 'Favorite workflow', + icon: 'IconSettingsAutomation', + inverseSideTarget: () => WorkflowWorkspaceEntity, + inverseSideFieldKey: 'favorites', + }) + @WorkspaceIsNullable() + workflow: Relation | null; + + @WorkspaceJoinColumn('workflow') + workflowId: string; + @WorkspaceDynamicRelation({ type: RelationMetadataType.MANY_TO_ONE, argsFactory: (oppositeObjectMetadata) => ({ diff --git a/packages/twenty-server/src/modules/person/standard-objects/person.workspace-entity.ts b/packages/twenty-server/src/modules/person/standard-objects/person.workspace-entity.ts index d2119e50f..a876863e5 100644 --- a/packages/twenty-server/src/modules/person/standard-objects/person.workspace-entity.ts +++ b/packages/twenty-server/src/modules/person/standard-objects/person.workspace-entity.ts @@ -215,7 +215,7 @@ export class PersonWorkspaceEntity extends BaseWorkspaceEntity { standardId: PERSON_STANDARD_FIELD_IDS.timelineActivities, type: RelationMetadataType.ONE_TO_MANY, label: 'Events', - description: 'Events linked to the company', + description: 'Events linked to the person', icon: 'IconTimelineEvent', inverseSideTarget: () => TimelineActivityWorkspaceEntity, onDelete: RelationOnDeleteAction.CASCADE, diff --git a/packages/twenty-server/src/modules/timeline/standard-objects/timeline-activity.workspace-entity.ts b/packages/twenty-server/src/modules/timeline/standard-objects/timeline-activity.workspace-entity.ts index c104b5df8..75628b17b 100644 --- a/packages/twenty-server/src/modules/timeline/standard-objects/timeline-activity.workspace-entity.ts +++ b/packages/twenty-server/src/modules/timeline/standard-objects/timeline-activity.workspace-entity.ts @@ -1,23 +1,24 @@ import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface'; import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; +import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; +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 { 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_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; 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 { WorkflowWorkspaceEntity } from 'src/modules/workflow/standard-objects/workflow.workspace-entity'; import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity'; -import { CustomWorkspaceEntity } from 'src/engine/twenty-orm/custom.workspace-entity'; -import { BaseWorkspaceEntity } from 'src/engine/twenty-orm/base.workspace-entity'; -import { WorkspaceEntity } from 'src/engine/twenty-orm/decorators/workspace-entity.decorator'; -import { WorkspaceIsSystem } from 'src/engine/twenty-orm/decorators/workspace-is-system.decorator'; -import { WorkspaceIsNotAuditLogged } from 'src/engine/twenty-orm/decorators/workspace-is-not-audit-logged.decorator'; -import { WorkspaceField } from 'src/engine/twenty-orm/decorators/workspace-field.decorator'; -import { WorkspaceIsNullable } from 'src/engine/twenty-orm/decorators/workspace-is-nullable.decorator'; -import { WorkspaceRelation } from 'src/engine/twenty-orm/decorators/workspace-relation.decorator'; -import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; -import { WorkspaceDynamicRelation } from 'src/engine/twenty-orm/decorators/workspace-dynamic-relation.decorator'; -import { WorkspaceJoinColumn } from 'src/engine/twenty-orm/decorators/workspace-join-column.decorator'; @WorkspaceEntity({ standardId: STANDARD_OBJECT_IDS.timelineActivity, @@ -150,6 +151,21 @@ export class TimelineActivityWorkspaceEntity extends BaseWorkspaceEntity { @WorkspaceJoinColumn('opportunity') opportunityId: string | null; + @WorkspaceRelation({ + standardId: TIMELINE_ACTIVITY_STANDARD_FIELD_IDS.workflow, + type: RelationMetadataType.MANY_TO_ONE, + label: 'Workflow', + description: 'Event workflow', + icon: 'IconTargetArrow', + inverseSideTarget: () => WorkflowWorkspaceEntity, + inverseSideFieldKey: 'timelineActivities', + }) + @WorkspaceIsNullable() + workflow: Relation | null; + + @WorkspaceJoinColumn('workflow') + workflowId: string | null; + @WorkspaceDynamicRelation({ type: RelationMetadataType.MANY_TO_ONE, argsFactory: (oppositeObjectMetadata) => ({ diff --git a/packages/twenty-server/src/modules/workflow/standard-objects/workflow-version.workspace-entity.ts b/packages/twenty-server/src/modules/workflow/standard-objects/workflow-version.workspace-entity.ts new file mode 100644 index 000000000..15f150614 --- /dev/null +++ b/packages/twenty-server/src/modules/workflow/standard-objects/workflow-version.workspace-entity.ts @@ -0,0 +1,66 @@ +import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface'; + +import { FeatureFlagKeys } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; +import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; +import { RelationMetadataType } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; +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 { WorkspaceGate } from 'src/engine/twenty-orm/decorators/workspace-gate.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_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; +import { WorkflowWorkspaceEntity } from 'src/modules/workflow/standard-objects/workflow.workspace-entity'; + +@WorkspaceGate({ + featureFlag: FeatureFlagKeys.IsWorkflowEnabled, +}) +@WorkspaceEntity({ + standardId: STANDARD_OBJECT_IDS.workflowVersion, + namePlural: 'workflowVersions', + labelSingular: 'WorkflowVersion', + labelPlural: 'WorkflowVersions', + description: 'A workflow version', + icon: 'IconVersions', + 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: 'Name', + description: 'The workflow version name', + icon: 'IconVersions', + }) + name: string; + + @WorkspaceField({ + standardId: WORKFLOW_VERSION_STANDARD_FIELD_IDS.trigger, + type: FieldMetadataType.RAW_JSON, + label: 'Version trigger', + description: 'Json object to provide trigger', + icon: 'IconPlayerPlay', + }) + @WorkspaceIsNullable() + trigger: JSON | null; + + // Relations + @WorkspaceRelation({ + standardId: WORKFLOW_VERSION_STANDARD_FIELD_IDS.workflow, + type: RelationMetadataType.MANY_TO_ONE, + label: 'Workflow', + description: 'WorkflowVersion workflow', + icon: 'IconSettingsAutomation', + inverseSideTarget: () => WorkflowWorkspaceEntity, + inverseSideFieldKey: 'versions', + }) + @WorkspaceIsNullable() + workflow: Relation; + + @WorkspaceJoinColumn('workflow') + workflowId: string; +} diff --git a/packages/twenty-server/src/modules/workflow/standard-objects/workflow.workspace-entity.ts b/packages/twenty-server/src/modules/workflow/standard-objects/workflow.workspace-entity.ts new file mode 100644 index 000000000..6d986e2f0 --- /dev/null +++ b/packages/twenty-server/src/modules/workflow/standard-objects/workflow.workspace-entity.ts @@ -0,0 +1,126 @@ +import { Relation } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/relation.interface'; + +import { FeatureFlagKeys } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; +import { FieldMetadataType } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; +import { + RelationMetadataType, + RelationOnDeleteAction, +} from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity'; +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 { WorkspaceGate } from 'src/engine/twenty-orm/decorators/workspace-gate.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_IDS } from 'src/engine/workspace-manager/workspace-sync-metadata/constants/standard-object-ids'; +import { ActivityTargetWorkspaceEntity } from 'src/modules/activity/standard-objects/activity-target.workspace-entity'; +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 { WorkflowVersionWorkspaceEntity } from 'src/modules/workflow/standard-objects/workflow-version.workspace-entity'; + +@WorkspaceGate({ + featureFlag: FeatureFlagKeys.IsWorkflowEnabled, +}) +@WorkspaceEntity({ + standardId: STANDARD_OBJECT_IDS.workflow, + namePlural: 'workflows', + labelSingular: 'Workflow', + labelPlural: 'Workflows', + description: 'A workflow', + icon: 'IconSettingsAutomation', + labelIdentifierStandardId: WORKFLOW_STANDARD_FIELD_IDS.name, +}) +export class WorkflowWorkspaceEntity extends BaseWorkspaceEntity { + @WorkspaceField({ + standardId: WORKFLOW_STANDARD_FIELD_IDS.name, + type: FieldMetadataType.TEXT, + label: 'Name', + description: 'The workflow name', + icon: 'IconSettingsAutomation', + }) + name: string; + + @WorkspaceField({ + standardId: WORKFLOW_STANDARD_FIELD_IDS.publishedVersionId, + type: FieldMetadataType.TEXT, + label: 'Published Version Id', + description: 'The workflow published version id', + icon: 'IconVersions', + }) + @WorkspaceIsNullable() + publishedVersionId: string | null; + + @WorkspaceField({ + standardId: WORKFLOW_STANDARD_FIELD_IDS.position, + type: FieldMetadataType.POSITION, + label: 'Position', + description: 'Workflow record position', + icon: 'IconHierarchy2', + }) + @WorkspaceIsSystem() + @WorkspaceIsNullable() + position: number | null; + + // Relations + @WorkspaceRelation({ + standardId: WORKFLOW_STANDARD_FIELD_IDS.versions, + type: RelationMetadataType.ONE_TO_MANY, + label: 'Versions', + description: 'Workflow versions linked to the workflow.', + icon: 'IconVersions', + inverseSideTarget: () => WorkflowVersionWorkspaceEntity, + onDelete: RelationOnDeleteAction.SET_NULL, + }) + @WorkspaceIsNullable() + versions: Relation; + + @WorkspaceRelation({ + standardId: WORKFLOW_STANDARD_FIELD_IDS.activityTargets, + type: RelationMetadataType.ONE_TO_MANY, + label: 'Activities', + description: 'Activities tied to the contact', + icon: 'IconCheckbox', + inverseSideTarget: () => ActivityTargetWorkspaceEntity, + onDelete: RelationOnDeleteAction.CASCADE, + }) + activityTargets: Relation; + + @WorkspaceRelation({ + standardId: WORKFLOW_STANDARD_FIELD_IDS.favorites, + type: RelationMetadataType.ONE_TO_MANY, + label: 'Favorites', + description: 'Favorites linked to the contact', + icon: 'IconHeart', + inverseSideTarget: () => FavoriteWorkspaceEntity, + onDelete: RelationOnDeleteAction.CASCADE, + }) + @WorkspaceIsSystem() + favorites: Relation; + + @WorkspaceRelation({ + standardId: WORKFLOW_STANDARD_FIELD_IDS.attachments, + type: RelationMetadataType.ONE_TO_MANY, + label: 'Attachments', + description: 'Attachments linked to the contact.', + icon: 'IconFileImport', + inverseSideTarget: () => AttachmentWorkspaceEntity, + onDelete: RelationOnDeleteAction.CASCADE, + }) + attachments: Relation; + + @WorkspaceRelation({ + standardId: WORKFLOW_STANDARD_FIELD_IDS.timelineActivities, + type: RelationMetadataType.ONE_TO_MANY, + label: 'Events', + description: 'Events linked to the workflow', + icon: 'IconTimelineEvent', + inverseSideTarget: () => TimelineActivityWorkspaceEntity, + onDelete: RelationOnDeleteAction.CASCADE, + }) + @WorkspaceIsNullable() + @WorkspaceIsSystem() + timelineActivities: Relation; +}