feat: migrate workflow-in-workflow capabilities and enhanced node preview (PR #3735)

Migrate hotfix for workflow blockers including:

- Feature: Ability to call workflow within a workflow
- Feature: Preview query node with other previewed node results
- Fix: startTrigger input accepts string values instead of code/JSON

Frontend changes:
- Add workflow-in-workflow support in FlowBuilder and QueryNodeConfiguration
- Enhance query node preview with upstream node state management
- Implement preview state cleanup with deleteNodePreviewState calls
- Replace TestParameter input with CodeHinter for better JSON editing
- Add workflow node type support and error styling
- Update WorkflowEditor components for nested workflow handling

Backend changes:
- Update workflow execution controller to handle state parameter
- Enhance PreviewWorkflowNodeDto with optional state field
- Modify workflow services for state-aware query execution
- Update triggers listener and webhooks service

Migration follows composition pattern for frontend EE modules and
inheritance pattern for backend services.

Co-authored-by: Akshay Sasidharan <akshaysasidrn@tooljet.com>
Co-authored-by: Shah <shah21@tooljet.com>
Co-authored-by: Devanshu <devanshu052000@tooljet.com>
This commit is contained in:
Akshay Sasidharan 2025-07-03 14:06:15 +05:30
parent d6bda6610a
commit f11ea30325
7 changed files with 30 additions and 8 deletions

@ -1 +1 @@
Subproject commit 5ab476909c9859a4a029185c2c8b922ca6ea0d23
Subproject commit 9cfaf2261b1801eea1c78beb2c2a9508a39638ff

View file

@ -14,9 +14,9 @@ export const workflowExecutionsService = {
streamSSE,
};
function previewQueryNode(queryId, appVersionId, nodeId) {
function previewQueryNode(queryId, appVersionId, nodeId, state = {}) {
const currentSession = authenticationService.currentSessionValue;
const body = { appVersionId, userId: currentSession.current_user?.id, queryId, nodeId };
const body = { appVersionId, userId: currentSession.current_user?.id, queryId, nodeId, state };
const requestOptions = { method: 'POST', headers: authHeader(), body: JSON.stringify(body), credentials: 'include' };
return fetch(`${config.apiUrl}/workflow_executions/previewQueryNode`, requestOptions).then(handleResponse);
}

@ -1 +1 @@
Subproject commit 15013b41acee6f951195a7ba37031c38f4c297af
Subproject commit 5ce75fab06b309f2e02c9c30f4ceee222113affb

View file

@ -1,4 +1,4 @@
import { IsString, IsNotEmpty, IsOptional } from 'class-validator';
import { IsString, IsNotEmpty, IsOptional, IsObject } from 'class-validator';
export class PreviewWorkflowNodeDto {
@IsString()
@ -20,4 +20,8 @@ export class PreviewWorkflowNodeDto {
@IsString()
@IsOptional()
appEnvId?: string;
@IsObject()
@IsOptional()
state?: Record<string, any>;
}

View file

@ -95,7 +95,7 @@ export class DataQueryRepository extends Repository<DataQuery> {
findOptions: FindOptionsWhere<DataQuery>,
relations?: string[],
manager?: EntityManager
): Promise<DataQuery> {
): Promise<DataQuery[]> {
return dbTransactionWrap(async (manager: EntityManager) => {
return manager.find(DataQuery, {
where: { ...(findOptions ? findOptions : {}) },

View file

@ -6,7 +6,16 @@ export interface IWorkflowExecutionsService {
execute(workflowExecution: WorkflowExecution, params: any, envId: string, response: Response): Promise<any>;
getStatus(id: string): Promise<{ logs: string[]; status: boolean; nodes: any[] }>;
getStatus(id: string): Promise<{
logs: unknown;
status: boolean;
nodes: Array<{
id: string;
idOnDefinition: string;
executed: boolean;
result: unknown;
}>;
}>;
getWorkflowExecution(id: string): Promise<WorkflowExecution>;

View file

@ -18,7 +18,16 @@ export class WorkflowExecutionsService implements IWorkflowExecutionsService {
throw new Error('Method not implemented.');
}
async getStatus(workflowExecutionId: string): Promise<{ logs: string[]; status: boolean; nodes: any[] }> {
async getStatus(workflowExecutionId: string): Promise<{
logs: unknown;
status: boolean;
nodes: Array<{
id: string;
idOnDefinition: string;
executed: boolean;
result: unknown;
}>;
}> {
throw new Error('Method not implemented.');
}