Implement branch front end (#13489)

First PR to support workflow branches on frontend
This commit is contained in:
martmull
2025-08-04 16:11:46 +02:00
committed by GitHub
parent 2c87c6fc1b
commit 9a05673093
124 changed files with 3735 additions and 938 deletions
@@ -8,6 +8,7 @@ export enum FeatureFlagKey {
IS_IMAP_SMTP_CALDAV_ENABLED = 'IS_IMAP_SMTP_CALDAV_ENABLED',
IS_MORPH_RELATION_ENABLED = 'IS_MORPH_RELATION_ENABLED',
IS_WORKFLOW_FILTERING_ENABLED = 'IS_WORKFLOW_FILTERING_ENABLED',
IS_WORKFLOW_BRANCH_ENABLED = 'IS_WORKFLOW_BRANCH_ENABLED',
IS_RELATION_CONNECT_ENABLED = 'IS_RELATION_CONNECT_ENABLED',
IS_WORKSPACE_API_KEY_WEBHOOK_GRAPHQL_ENABLED = 'IS_WORKSPACE_API_KEY_WEBHOOK_GRAPHQL_ENABLED',
IS_FIELDS_PERMISSIONS_ENABLED = 'IS_FIELDS_PERMISSIONS_ENABLED',
@@ -0,0 +1,22 @@
import { Field, InputType } from '@nestjs/graphql';
@InputType()
export class CreateWorkflowVersionEdgeInput {
@Field(() => String, {
description: 'Workflow version ID',
nullable: false,
})
workflowVersionId: string;
@Field(() => String, {
description: 'Workflow version source step ID',
nullable: false,
})
source: string;
@Field(() => String, {
description: 'Workflow version target step ID',
nullable: false,
})
target: string;
}
@@ -2,6 +2,7 @@ import { Field, InputType } from '@nestjs/graphql';
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
import { WorkflowActionType } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
import { WorkflowStepPositionInput } from 'src/engine/core-modules/workflow/dtos/update-workflow-step-position-input.dto';
@InputType()
export class CreateWorkflowVersionStepInput {
@@ -17,7 +18,8 @@ export class CreateWorkflowVersionStepInput {
})
stepType: WorkflowActionType;
@Field(() => UUIDScalarType, {
// Typed String as it can be 'trigger'
@Field(() => String, {
description: 'Parent step ID',
nullable: true,
})
@@ -28,4 +30,10 @@ export class CreateWorkflowVersionStepInput {
nullable: true,
})
nextStepId?: string;
@Field(() => WorkflowStepPositionInput, {
description: 'Step position',
nullable: true,
})
position?: WorkflowStepPositionInput;
}
@@ -0,0 +1,10 @@
import { Field, InputType } from '@nestjs/graphql';
@InputType()
export class WorkflowStepPositionInput {
@Field(() => Number)
x: number;
@Field(() => Number)
y: number;
}
@@ -0,0 +1,18 @@
import { Field, InputType } from '@nestjs/graphql';
import { WorkflowStepPositionInput } from 'src/engine/core-modules/workflow/dtos/update-workflow-step-position-input.dto';
@InputType()
export class WorkflowStepPositionUpdateInput {
@Field(() => String, {
description: 'Step or trigger ID',
nullable: false,
})
id: string;
@Field(() => WorkflowStepPositionInput, {
description: 'Position of the step or trigger',
nullable: false,
})
position: WorkflowStepPositionInput;
}
@@ -0,0 +1,19 @@
import { Field, InputType } from '@nestjs/graphql';
import { WorkflowStepPositionUpdateInput } from 'src/engine/core-modules/workflow/dtos/update-workflow-step-position-update-input.dto';
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
@InputType()
export class UpdateWorkflowVersionPositionsInput {
@Field(() => UUIDScalarType, {
description: 'Workflow version ID',
nullable: false,
})
workflowVersionId: string;
@Field(() => [WorkflowStepPositionUpdateInput], {
description: 'Workflow version updated positions',
nullable: false,
})
positions: WorkflowStepPositionUpdateInput[];
}
@@ -0,0 +1,10 @@
import { Field, ObjectType } from '@nestjs/graphql';
@ObjectType('WorkflowStepPosition')
export class WorkflowStepPosition {
@Field(() => Number)
x: number;
@Field(() => Number)
y: number;
}
@@ -4,6 +4,7 @@ import graphqlTypeJson from 'graphql-type-json';
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
import { WorkflowActionType } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
import { WorkflowStepPosition } from 'src/engine/core-modules/workflow/dtos/workflow-step-position.dto';
@ObjectType('WorkflowAction')
export class WorkflowActionDTO {
@@ -24,4 +25,7 @@ export class WorkflowActionDTO {
@Field(() => [UUIDScalarType], { nullable: true })
nextStepIds?: string[];
@Field(() => WorkflowStepPosition, { nullable: true })
position?: WorkflowStepPosition;
}
@@ -0,0 +1,20 @@
import { Field, ObjectType } from '@nestjs/graphql';
import graphqlTypeJson from 'graphql-type-json';
import { WorkflowActionDTO } from 'src/engine/core-modules/workflow/dtos/workflow-step.dto';
@ObjectType('WorkflowVersionStepChanges')
export class WorkflowVersionStepChangesDTO {
@Field(() => [String], { nullable: true })
triggerNextStepIds?: string[];
@Field(() => graphqlTypeJson, { nullable: true })
stepsNextStepIds?: Record<string, string[] | undefined>;
@Field(() => WorkflowActionDTO, { nullable: true })
createdStep?: WorkflowActionDTO;
@Field(() => String, { nullable: true })
deletedStepId?: string;
}
@@ -21,6 +21,8 @@ import { PermissionsGraphqlApiExceptionFilter } from 'src/engine/metadata-module
import { WorkflowVersionStepWorkspaceService } from 'src/modules/workflow/workflow-builder/workflow-step/workflow-version-step.workspace-service';
import { WorkflowActionType } from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
import { WorkflowRunWorkspaceService } from 'src/modules/workflow/workflow-runner/workflow-run/workflow-run.workspace-service';
import { CreateWorkflowVersionEdgeInput } from 'src/engine/core-modules/workflow/dtos/create-workflow-version-edge-input.dto';
import { WorkflowVersionStepChangesDTO } from 'src/engine/core-modules/workflow/dtos/workflow-version-step-changes.dto';
@Resolver()
@UsePipes(ResolverValidationPipe)
@@ -40,12 +42,12 @@ export class WorkflowStepResolver {
private readonly featureFlagService: FeatureFlagService,
) {}
@Mutation(() => WorkflowActionDTO)
@Mutation(() => WorkflowVersionStepChangesDTO)
async createWorkflowVersionStep(
@AuthWorkspace() { id: workspaceId }: Workspace,
@Args('input')
input: CreateWorkflowVersionStepInput,
): Promise<WorkflowActionDTO> {
): Promise<WorkflowVersionStepChangesDTO> {
if (input.stepType === WorkflowActionType.AI_AGENT) {
const isAiEnabled = await this.featureFlagService.isFeatureEnabled(
FeatureFlagKey.IS_AI_ENABLED,
@@ -78,12 +80,12 @@ export class WorkflowStepResolver {
});
}
@Mutation(() => WorkflowActionDTO)
@Mutation(() => WorkflowVersionStepChangesDTO)
async deleteWorkflowVersionStep(
@AuthWorkspace() { id: workspaceId }: Workspace,
@Args('input')
{ stepId, workflowVersionId }: DeleteWorkflowVersionStepInput,
): Promise<WorkflowActionDTO> {
): Promise<WorkflowVersionStepChangesDTO> {
return this.workflowVersionStepWorkspaceService.deleteWorkflowVersionStep({
workspaceId,
workflowVersionId,
@@ -121,4 +123,32 @@ export class WorkflowStepResolver {
return step;
}
@Mutation(() => WorkflowVersionStepChangesDTO)
async createWorkflowVersionEdge(
@AuthWorkspace() { id: workspaceId }: Workspace,
@Args('input')
{ source, target, workflowVersionId }: CreateWorkflowVersionEdgeInput,
): Promise<WorkflowVersionStepChangesDTO> {
return this.workflowVersionStepWorkspaceService.createWorkflowVersionEdge({
source,
target,
workflowVersionId,
workspaceId,
});
}
@Mutation(() => WorkflowVersionStepChangesDTO)
async deleteWorkflowVersionEdge(
@AuthWorkspace() { id: workspaceId }: Workspace,
@Args('input')
{ source, target, workflowVersionId }: CreateWorkflowVersionEdgeInput,
): Promise<WorkflowVersionStepChangesDTO> {
return this.workflowVersionStepWorkspaceService.deleteWorkflowVersionEdge({
source,
target,
workflowVersionId,
workspaceId,
});
}
}
@@ -3,7 +3,7 @@ import { Args, Mutation, Resolver } from '@nestjs/graphql';
import { PreventNestToAutoLogGraphqlErrorsFilter } from 'src/engine/core-modules/graphql/filters/prevent-nest-to-auto-log-graphql-errors.filter';
import { ResolverValidationPipe } from 'src/engine/core-modules/graphql/pipes/resolver-validation.pipe';
import { CreateDraftFromWorkflowVersionInput } from 'src/engine/core-modules/workflow/dtos/create-draft-from-workflow-version-input';
import { CreateDraftFromWorkflowVersionInput } from 'src/engine/core-modules/workflow/dtos/create-draft-from-workflow-version-input.dto';
import { WorkflowVersionDTO } from 'src/engine/core-modules/workflow/dtos/workflow-version.dto';
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
@@ -13,6 +13,7 @@ import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
import { PermissionFlagType } from 'src/engine/metadata-modules/permissions/constants/permission-flag-type.constants';
import { PermissionsGraphqlApiExceptionFilter } from 'src/engine/metadata-modules/permissions/utils/permissions-graphql-api-exception.filter';
import { WorkflowVersionWorkspaceService } from 'src/modules/workflow/workflow-builder/workflow-version/workflow-version.workspace-service';
import { UpdateWorkflowVersionPositionsInput } from 'src/engine/core-modules/workflow/dtos/update-workflow-version-positions-input.dto';
@Resolver()
@UsePipes(ResolverValidationPipe)
@@ -49,4 +50,19 @@ export class WorkflowVersionResolver {
),
};
}
@Mutation(() => Boolean)
async updateWorkflowVersionPositions(
@AuthWorkspace() { id: workspaceId }: Workspace,
@Args('input')
{ workflowVersionId, positions }: UpdateWorkflowVersionPositionsInput,
) {
await this.workflowVersionWorkspaceService.updateWorkflowVersionPositions({
workspaceId,
workflowVersionId,
positions,
});
return true;
}
}