From ba4983ca53aee68b740d881f98634936844e4ad4 Mon Sep 17 00:00:00 2001 From: pk-zipstack Date: Mon, 9 Feb 2026 12:32:49 +0530 Subject: [PATCH 1/3] Improved workflow deltion error message --- .../workflow_v2/workflow_helper.py | 22 +++++++++--- .../workflows/workflow/Workflows.jsx | 36 ++++++++++++++----- 2 files changed, 46 insertions(+), 12 deletions(-) diff --git a/backend/workflow_manager/workflow_v2/workflow_helper.py b/backend/workflow_manager/workflow_v2/workflow_helper.py index 73aef3e9db..759547a87c 100644 --- a/backend/workflow_manager/workflow_v2/workflow_helper.py +++ b/backend/workflow_manager/workflow_v2/workflow_helper.py @@ -1000,10 +1000,24 @@ def can_update_workflow(workflow_id: str) -> dict[str, Any]: workflow: Workflow = Workflow.objects.get(pk=workflow_id) if not workflow or workflow is None: raise WorkflowDoesNotExistError() - used_count = Pipeline.objects.filter(workflow=workflow).count() - if used_count == 0: - used_count = APIDeployment.objects.filter(workflow=workflow).count() - return {"can_update": used_count == 0} + + pipeline_names = list( + Pipeline.objects.filter(workflow=workflow).values_list( + "pipeline_name", flat=True + ) + ) + api_names = list( + APIDeployment.objects.filter(workflow=workflow).values_list( + "display_name", flat=True + ) + ) + total_usage = len(pipeline_names) + len(api_names) + + return { + "can_update": total_usage == 0, + "pipeline_names": pipeline_names, + "api_names": api_names, + } except Workflow.DoesNotExist: logger.error(f"Error getting workflow: {id}") raise WorkflowDoesNotExistError() diff --git a/frontend/src/components/workflows/workflow/Workflows.jsx b/frontend/src/components/workflows/workflow/Workflows.jsx index 9b6ee23989..b7e33bcc2a 100644 --- a/frontend/src/components/workflows/workflow/Workflows.jsx +++ b/frontend/src/components/workflows/workflow/Workflows.jsx @@ -146,17 +146,34 @@ function Workflows() { }); } - const canDeleteProject = async (id) => { - let status = false; + const checkWorkflowUsage = async (id) => { + let result = { can_update: false, pipeline_names: [], api_names: [] }; await projectApiService.canUpdate(id).then((res) => { - status = res?.data?.can_update || false; + result = { + can_update: res?.data?.can_update || false, + pipeline_names: res?.data?.pipeline_names || [], + api_names: res?.data?.api_names || [], + }; }); - return status; + return result; + }; + + const getUsageMessage = (workflowName, pipelineNames, apiNames) => { + const allNames = [...apiNames, ...pipelineNames]; + const total = allNames.length; + if (total === 0) return ""; + const firstName = `"${allNames[0]}"`; + if (total === 1) { + return `Cannot delete "${workflowName}" as it is used in ${firstName}.`; + } + const remaining = total - 1; + const pipelineLabel = remaining === 1 ? "pipeline" : "pipelines"; + return `Cannot delete "${workflowName}" as it is used in ${firstName} and ${remaining} other ${pipelineLabel}.`; }; const deleteProject = async (_evt, project) => { - const canDelete = await canDeleteProject(project.id); - if (canDelete) { + const usage = await checkWorkflowUsage(project.id); + if (usage.can_update) { projectApiService .deleteProject(project.id) .then(() => { @@ -174,8 +191,11 @@ function Workflows() { } else { setAlertDetails({ type: "error", - content: - "Cannot delete this Workflow, since it is used in one or many of the API/ETL/Task pipelines", + content: getUsageMessage( + project.workflow_name, + usage.pipeline_names, + usage.api_names + ), }); } }; From 5bd98e13b48e961767bc1c2fa12b71758cf711cf Mon Sep 17 00:00:00 2001 From: pk-zipstack Date: Mon, 9 Feb 2026 12:51:52 +0530 Subject: [PATCH 2/3] improved error message --- frontend/src/components/workflows/workflow/Workflows.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/components/workflows/workflow/Workflows.jsx b/frontend/src/components/workflows/workflow/Workflows.jsx index b7e33bcc2a..55b44593e2 100644 --- a/frontend/src/components/workflows/workflow/Workflows.jsx +++ b/frontend/src/components/workflows/workflow/Workflows.jsx @@ -168,7 +168,7 @@ function Workflows() { } const remaining = total - 1; const pipelineLabel = remaining === 1 ? "pipeline" : "pipelines"; - return `Cannot delete "${workflowName}" as it is used in ${firstName} and ${remaining} other ${pipelineLabel}.`; + return `Cannot delete "${workflowName}" as it is used in ${firstName} and ${remaining} other API/ETL/Task ${pipelineLabel}.`; }; const deleteProject = async (_evt, project) => { From c0b40f2dc7810deed6e1c6453ff18faa4bcbcb8e Mon Sep 17 00:00:00 2001 From: pk-zipstack Date: Mon, 9 Feb 2026 15:56:19 +0530 Subject: [PATCH 3/3] addressed code rabbit comments --- .../workflows/workflow/Workflows.jsx | 67 ++++++++++--------- 1 file changed, 35 insertions(+), 32 deletions(-) diff --git a/frontend/src/components/workflows/workflow/Workflows.jsx b/frontend/src/components/workflows/workflow/Workflows.jsx index 55b44593e2..e7c493cf09 100644 --- a/frontend/src/components/workflows/workflow/Workflows.jsx +++ b/frontend/src/components/workflows/workflow/Workflows.jsx @@ -147,15 +147,12 @@ function Workflows() { } const checkWorkflowUsage = async (id) => { - let result = { can_update: false, pipeline_names: [], api_names: [] }; - await projectApiService.canUpdate(id).then((res) => { - result = { - can_update: res?.data?.can_update || false, - pipeline_names: res?.data?.pipeline_names || [], - api_names: res?.data?.api_names || [], - }; - }); - return result; + const res = await projectApiService.canUpdate(id); + return { + can_update: res?.data?.can_update || false, + pipeline_names: res?.data?.pipeline_names || [], + api_names: res?.data?.api_names || [], + }; }; const getUsageMessage = (workflowName, pipelineNames, apiNames) => { @@ -172,31 +169,37 @@ function Workflows() { }; const deleteProject = async (_evt, project) => { - const usage = await checkWorkflowUsage(project.id); - if (usage.can_update) { - projectApiService - .deleteProject(project.id) - .then(() => { - getProjectList(); - setAlertDetails({ - type: "success", - content: "Workflow deleted successfully", + try { + const usage = await checkWorkflowUsage(project.id); + if (usage.can_update) { + projectApiService + .deleteProject(project.id) + .then(() => { + getProjectList(); + setAlertDetails({ + type: "success", + content: "Workflow deleted successfully", + }); + }) + .catch((err) => { + setAlertDetails( + handleException(err, `Unable to delete workflow ${project.id}`) + ); }); - }) - .catch((err) => { - setAlertDetails( - handleException(err, `Unable to delete workflow ${project.id}`) - ); + } else { + setAlertDetails({ + type: "error", + content: getUsageMessage( + project.workflow_name, + usage.pipeline_names, + usage.api_names + ), }); - } else { - setAlertDetails({ - type: "error", - content: getUsageMessage( - project.workflow_name, - usage.pipeline_names, - usage.api_names - ), - }); + } + } catch (err) { + setAlertDetails( + handleException(err, `Unable to delete workflow ${project.id}`) + ); } };