diff --git a/ui/src/components/workflow/WorkflowRuns.tsx b/ui/src/components/workflow/WorkflowRuns.tsx index e670e102..02bfb453 100644 --- a/ui/src/components/workflow/WorkflowRuns.tsx +++ b/ui/src/components/workflow/WorkflowRuns.tsx @@ -1,4 +1,4 @@ -import { useState } from "react"; +import { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { CheckCircleOutlined as CheckCircleOutlinedIcon, @@ -18,7 +18,12 @@ import { ClientResponseError } from "pocketbase"; import { cancelRun as cancelWorkflowRun } from "@/api/workflows"; import { WORKFLOW_TRIGGERS } from "@/domain/workflow"; import { WORKFLOW_RUN_STATUSES, type WorkflowRunModel } from "@/domain/workflowRun"; -import { list as listWorkflowRuns, remove as removeWorkflowRun } from "@/repository/workflowRun"; +import { + list as listWorkflowRuns, + remove as removeWorkflowRun, + subscribe as subscribeWorkflowRun, + unsubscribe as unsubscribeWorkflowRun, +} from "@/repository/workflowRun"; import { getErrMsg } from "@/utils/error"; import WorkflowRunDetailDrawer from "./WorkflowRunDetailDrawer"; @@ -211,6 +216,27 @@ const WorkflowRuns = ({ className, style, workflowId }: WorkflowRunsProps) => { } ); + useEffect(() => { + const items = tableData.filter((e) => e.status === WORKFLOW_RUN_STATUSES.PENDING || e.status === WORKFLOW_RUN_STATUSES.RUNNING); + for (const item of items) { + subscribeWorkflowRun(item.id, (cb) => { + setTableData((prev) => { + const index = prev.findIndex((e) => e.id === item.id); + if (index !== -1) { + prev[index] = cb.record; + } + return [...prev]; + }); + }); + } + + return () => { + for (const item of items) { + unsubscribeWorkflowRun(item.id); + } + }; + }, [tableData]); + const handleCancelClick = (workflowRun: WorkflowRunModel) => { modalApi.confirm({ title: t("workflow_run.action.cancel"), diff --git a/ui/src/pages/workflows/WorkflowDetail.tsx b/ui/src/pages/workflows/WorkflowDetail.tsx index 7db866e3..df931504 100644 --- a/ui/src/pages/workflows/WorkflowDetail.tsx +++ b/ui/src/pages/workflows/WorkflowDetail.tsx @@ -64,8 +64,8 @@ const WorkflowDetail = () => { useEffect(() => { if (!!workflowId && isPendingOrRunning) { - subscribeWorkflow(workflowId, (e) => { - if (e.record.lastRunStatus !== WORKFLOW_RUN_STATUSES.PENDING && e.record.lastRunStatus !== WORKFLOW_RUN_STATUSES.RUNNING) { + subscribeWorkflow(workflowId, (cb) => { + if (cb.record.lastRunStatus !== WORKFLOW_RUN_STATUSES.PENDING && cb.record.lastRunStatus !== WORKFLOW_RUN_STATUSES.RUNNING) { setIsPendingOrRunning(false); unsubscribeWorkflow(workflowId); } diff --git a/ui/src/repository/workflow.ts b/ui/src/repository/workflow.ts index 54ddddd4..0241eecf 100644 --- a/ui/src/repository/workflow.ts +++ b/ui/src/repository/workflow.ts @@ -50,13 +50,9 @@ export const remove = async (record: MaybeModelRecordWithId) => { }; export const subscribe = async (id: string, cb: (e: RecordSubscription) => void) => { - const pb = getPocketBase(); - - return pb.collection("workflow").subscribe(id, cb); + return getPocketBase().collection(COLLECTION_NAME).subscribe(id, cb); }; export const unsubscribe = async (id: string) => { - const pb = getPocketBase(); - - return pb.collection("workflow").unsubscribe(id); + return getPocketBase().collection(COLLECTION_NAME).unsubscribe(id); }; diff --git a/ui/src/repository/workflowRun.ts b/ui/src/repository/workflowRun.ts index 0aa88080..cf681b70 100644 --- a/ui/src/repository/workflowRun.ts +++ b/ui/src/repository/workflowRun.ts @@ -1,4 +1,6 @@ -import { type WorkflowRunModel } from "@/domain/workflowRun"; +import { type RecordSubscription } from "pocketbase"; + +import { type WorkflowRunModel } from "@/domain/workflowRun"; import { getPocketBase } from "./_pocketbase"; @@ -35,3 +37,11 @@ export const list = async (request: ListWorkflowRunsRequest) => { export const remove = async (record: MaybeModelRecordWithId) => { return await getPocketBase().collection(COLLECTION_NAME).delete(record.id); }; + +export const subscribe = async (id: string, cb: (e: RecordSubscription) => void) => { + return getPocketBase().collection(COLLECTION_NAME).subscribe(id, cb); +}; + +export const unsubscribe = async (id: string) => { + return getPocketBase().collection(COLLECTION_NAME).unsubscribe(id); +};