diff --git a/client/src/api/invocations.ts b/client/src/api/invocations.ts index 88c34695fb8c..fe5f98d51772 100644 --- a/client/src/api/invocations.ts +++ b/client/src/api/invocations.ts @@ -6,16 +6,18 @@ import { ApiResponse, components, fetcher } from "./schema"; export type WorkflowInvocationElementView = components["schemas"]["WorkflowInvocationElementView"]; export type WorkflowInvocationCollectionView = components["schemas"]["WorkflowInvocationCollectionView"]; +export type WorkflowInvocationStepStatesView = components["schemas"]["WorkflowInvocationStepStatesView"]; export type InvocationJobsSummary = components["schemas"]["InvocationJobsResponse"]; export type InvocationStep = components["schemas"]["InvocationStep"]; export const invocationsFetcher = fetcher.path("/api/invocations").method("get").create(); +export const invocationFetcher = fetcher.path("/api/invocations/{invocation_id}").method("get").create(); +export const jobsSummaryFetcher = fetcher.path("/api/invocations/{invocation_id}/jobs_summary").method("get").create(); -export type WorkflowInvocation = WorkflowInvocationElementView | WorkflowInvocationCollectionView; - -export interface WorkflowInvocationJobsSummary { - id: string; -} +export type WorkflowInvocation = + | WorkflowInvocationElementView + | WorkflowInvocationCollectionView + | WorkflowInvocationStepStatesView; export interface WorkflowInvocationStep { id: string; @@ -32,19 +34,26 @@ export async function invocationForJob(params: { jobId: string }): Promise> { - const { data } = await axios.get(`${getAppRoot()}api/invocations/${params.id}`); + const { data } = await invocationFetcher({ invocation_id: params.id }); return { data, } as ApiResponse; } -export async function fetchInvocationJobsSummary(params: { +export async function fetchInvocationStepStateDetails(params: { id: string; -}): Promise> { - const { data } = await axios.get(`${getAppRoot()}api/invocations/${params.id}/jobs_summary`); +}): Promise> { + const { data } = await invocationFetcher({ invocation_id: params.id, view: "step_states" }); + return { + data, + } as ApiResponse; +} + +export async function fetchInvocationJobsSummary(params: { id: string }): Promise> { + const { data } = await jobsSummaryFetcher({ invocation_id: params.id }); return { data, - } as ApiResponse; + } as ApiResponse; } export async function fetchInvocationStep(params: { id: string }): Promise> { diff --git a/client/src/api/schema/schema.ts b/client/src/api/schema/schema.ts index 190abb1ad1ea..7499fa5218b6 100644 --- a/client/src/api/schema/schema.ts +++ b/client/src/api/schema/schema.ts @@ -7979,7 +7979,7 @@ export interface components { * InvocationSerializationView * @enum {string} */ - InvocationSerializationView: "element" | "collection"; + InvocationSerializationView: "element" | "collection" | "step_states"; /** * InvocationSortByEnum * @enum {string} @@ -7990,10 +7990,7 @@ export interface components { * @enum {string} */ InvocationState: "new" | "ready" | "scheduled" | "cancelled" | "cancelling" | "failed"; - /** - * InvocationStep - * @description Information about workflow invocation step - */ + /** InvocationStep */ InvocationStep: { /** * Action @@ -8005,8 +8002,6 @@ export interface components { * @example 0123456789ABCDEF */ id: string; - /** Job Id */ - job_id: string | null; /** * Jobs * @description Jobs associated with the workflow invocation step. @@ -8045,7 +8040,7 @@ export interface components { * State of the invocation step * @description Describes where in the scheduling process the workflow invocation step is. */ - state?: components["schemas"]["InvocationStepState"] | components["schemas"]["JobState"] | null; + state: components["schemas"]["InvocationStepState"]; /** Subworkflow Invocation Id */ subworkflow_invocation_id: string | null; /** @@ -8916,6 +8911,82 @@ export interface components { */ value: string; }; + /** LegacyInvocationStep */ + LegacyInvocationStep: { + /** + * Action + * @description Whether to take action on the invocation step. + */ + action: boolean | null; + /** + * Invocation Step ID + * @example 0123456789ABCDEF + */ + id: string; + /** Job Id */ + job_id: string | null; + /** + * Jobs + * @description Jobs associated with the workflow invocation step. + * @default [] + */ + jobs?: components["schemas"]["JobBaseModel"][]; + /** + * Model class + * @description The name of the database model class. + * @constant + */ + model_class: "WorkflowInvocationStep"; + /** + * Order index + * @description The index of the workflow step in the workflow. + */ + order_index: number; + /** + * Output collections + * @description The dataset collection outputs of the workflow invocation step. + * @default {} + */ + output_collections?: { + [key: string]: components["schemas"]["InvocationStepCollectionOutput"] | undefined; + }; + /** + * Outputs + * @description The outputs of the workflow invocation step. + * @default {} + */ + outputs?: { + [key: string]: components["schemas"]["InvocationStepOutput"] | undefined; + }; + /** + * State of the invocation step + * @description Describes the job state corresponding to this invocation step. + */ + state: components["schemas"]["JobState"] | null; + /** Subworkflow Invocation Id */ + subworkflow_invocation_id: string | null; + /** + * Update Time + * @description The last time and date this item was updated. + */ + update_time: string | null; + /** + * Workflow step ID + * @description The encoded ID of the workflow step associated with this workflow invocation step. + * @example 0123456789ABCDEF + */ + workflow_step_id: string; + /** + * Step label + * @description The label of the workflow step + */ + workflow_step_label?: string | null; + /** + * UUID + * @description Universal unique identifier of the workflow step. + */ + workflow_step_uuid?: string | null; + }; /** LegacyLibraryPermissionsPayload */ LegacyLibraryPermissionsPayload: { /** @@ -8943,6 +9014,110 @@ export interface components { */ LIBRARY_MODIFY_in?: string[] | string | null; }; + /** LegacyWorkflowInvocationElementView */ + LegacyWorkflowInvocationElementView: { + /** + * Create Time + * Format: date-time + * @description The time and date this item was created. + */ + create_time: string; + /** + * History ID + * @description The encoded ID of the history associated with the invocation. + * @example 0123456789ABCDEF + */ + history_id: string; + /** + * ID + * @description The encoded ID of the workflow invocation. + * @example 0123456789ABCDEF + */ + id: string; + /** + * Input step parameters + * @description Input step parameters of the workflow invocation. + */ + input_step_parameters: { + [key: string]: components["schemas"]["InvocationInputParameter"] | undefined; + }; + /** + * Inputs + * @description Input datasets/dataset collections of the workflow invocation. + */ + inputs: { + [key: string]: components["schemas"]["InvocationInput"] | undefined; + }; + /** + * Messages + * @description A list of messages about why the invocation did not succeed. + */ + messages: ( + | components["schemas"]["InvocationCancellationReviewFailedResponse"] + | components["schemas"]["InvocationCancellationHistoryDeletedResponse"] + | components["schemas"]["InvocationCancellationUserRequestResponse"] + | components["schemas"]["InvocationFailureDatasetFailedResponse"] + | components["schemas"]["InvocationFailureCollectionFailedResponse"] + | components["schemas"]["InvocationFailureJobFailedResponse"] + | components["schemas"]["InvocationFailureOutputNotFoundResponse"] + | components["schemas"]["InvocationFailureExpressionEvaluationFailedResponse"] + | components["schemas"]["InvocationFailureWhenNotBooleanResponse"] + | components["schemas"]["InvocationUnexpectedFailureResponse"] + | components["schemas"]["InvocationEvaluationWarningWorkflowOutputNotFoundResponse"] + )[]; + /** + * Model class + * @description The name of the database model class. + * @constant + */ + model_class: "WorkflowInvocation"; + /** + * Output collections + * @description Output dataset collections of the workflow invocation. + */ + output_collections: { + [key: string]: components["schemas"]["InvocationOutputCollection"] | undefined; + }; + /** + * Output values + * @description Output values of the workflow invocation. + */ + output_values: Record; + /** + * Outputs + * @description Output datasets of the workflow invocation. + */ + outputs: { + [key: string]: components["schemas"]["InvocationOutput"] | undefined; + }; + /** + * Invocation state + * @description State of workflow invocation. + */ + state: components["schemas"]["InvocationState"]; + /** + * Steps + * @description Steps of the workflow invocation (legacy view using job state). + */ + steps: components["schemas"]["LegacyInvocationStep"][]; + /** + * Update Time + * Format: date-time + * @description The last time and date this item was updated. + */ + update_time: string; + /** + * UUID + * @description Universal unique identifier of the workflow invocation. + */ + uuid?: string | string | null; + /** + * Workflow ID + * @description The encoded Workflow ID associated with the invocation. + * @example 0123456789ABCDEF + */ + workflow_id: string; + }; /** LibraryAvailablePermissions */ LibraryAvailablePermissions: { /** @@ -12911,7 +13086,9 @@ export interface components { /** WorkflowInvocationResponse */ WorkflowInvocationResponse: | components["schemas"]["WorkflowInvocationElementView"] - | components["schemas"]["WorkflowInvocationCollectionView"]; + | components["schemas"]["LegacyWorkflowInvocationElementView"] + | components["schemas"]["WorkflowInvocationCollectionView"] + | components["schemas"]["WorkflowInvocationStepStatesView"]; /** WorkflowInvocationStateSummary */ WorkflowInvocationStateSummary: { /** @@ -12940,6 +13117,60 @@ export interface components { [key: string]: number | undefined; }; }; + /** WorkflowInvocationStepStatesView */ + WorkflowInvocationStepStatesView: { + /** + * Create Time + * Format: date-time + * @description The time and date this item was created. + */ + create_time: string; + /** + * History ID + * @description The encoded ID of the history associated with the invocation. + * @example 0123456789ABCDEF + */ + history_id: string; + /** + * ID + * @description The encoded ID of the workflow invocation. + * @example 0123456789ABCDEF + */ + id: string; + /** + * Model class + * @description The name of the database model class. + * @constant + */ + model_class: "WorkflowInvocation"; + /** + * Invocation state + * @description State of workflow invocation. + */ + state: components["schemas"]["InvocationState"]; + /** + * Steps + * @description Steps of the workflow invocation. + */ + steps: components["schemas"]["InvocationStep"][]; + /** + * Update Time + * Format: date-time + * @description The last time and date this item was updated. + */ + update_time: string; + /** + * UUID + * @description Universal unique identifier of the workflow invocation. + */ + uuid?: string | string | null; + /** + * Workflow ID + * @description The encoded Workflow ID associated with the invocation. + * @example 0123456789ABCDEF + */ + workflow_id: string; + }; /** WriteInvocationStoreToPayload */ WriteInvocationStoreToPayload: { /** @@ -18711,6 +18942,7 @@ export interface operations { show_invocation_api_invocations__invocation_id__get: { /** Get detailed description of a workflow invocation. */ parameters: { + /** @description View to be passed to the serializer */ /** @description Include details for individual invocation steps and populate a steps attribute in the resulting dictionary. */ /** * @description Populate the invocation step state with the job state instead of the invocation step state. @@ -18719,6 +18951,7 @@ export interface operations { * are not the mapped over step outputs but the individual job outputs. */ query?: { + view?: string | null; step_details?: boolean; legacy_job_state?: boolean; }; diff --git a/client/src/components/Workflow/InvocationsList.test.js b/client/src/components/Workflow/InvocationsList.test.js index 6321039a1c55..cce9721b3eda 100644 --- a/client/src/components/Workflow/InvocationsList.test.js +++ b/client/src/components/Workflow/InvocationsList.test.js @@ -7,10 +7,13 @@ import MockAdapter from "axios-mock-adapter"; import { formatDistanceToNow, parseISO } from "date-fns"; import { getLocalVue } from "tests/jest/helpers"; +import { mockFetcher } from "@/api/schema/__mocks__"; + import InvocationsList from "./InvocationsList"; import mockInvocationData from "./test/json/invocation.json"; const localVue = getLocalVue(); +jest.mock("@/api/schema"); const pinia = createTestingPinia(); describe("InvocationsList.vue", () => { @@ -19,12 +22,16 @@ describe("InvocationsList.vue", () => { beforeEach(async () => { axiosMock = new MockAdapter(axios); - axiosMock.onGet(`api/invocations/${mockInvocationData.id}`).reply(200, mockInvocationData); - axiosMock.onGet(`api/invocations/${mockInvocationData.id}/jobs_summary`).reply(200, {}); + mockFetcher.path("/api/invocations/{invocation_id}").method("get").mock({ data: mockInvocationData }); + mockFetcher + .path("/api/invocations/{invocation_id}/jobs_summary") + .method("get") + .mock({ data: { states: {} } }); }); afterEach(() => { axiosMock.restore(); + mockFetcher.clearMocks(); }); describe(" with empty invocation list", () => { @@ -36,6 +43,7 @@ describe("InvocationsList.vue", () => { wrapper = mount(InvocationsList, { propsData, localVue, + pinia, }); }); @@ -124,6 +132,7 @@ describe("InvocationsList.vue", () => { wrapper = mount(InvocationsList, { propsData, localVue, + pinia, }); }); @@ -186,7 +195,6 @@ describe("InvocationsList.vue", () => { expect(columns.at(3).text()).toBe( formatDistanceToNow(parseISO(`${mockInvocationData.create_time}Z`), { addSuffix: true }) ); - expect(columns.at(4).text()).toBe("scheduled"); expect(columns.at(5).text()).toBe(""); }); @@ -242,6 +250,7 @@ describe("InvocationsList.vue", () => { }, }, localVue, + pinia, }); }); diff --git a/client/src/components/Workflow/InvocationsList.vue b/client/src/components/Workflow/InvocationsList.vue index ce962d036388..28f2470711eb 100644 --- a/client/src/components/Workflow/InvocationsList.vue +++ b/client/src/components/Workflow/InvocationsList.vue @@ -65,7 +65,10 @@