mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
Merge pull request #17566 from jmchilton/invocation_links
Links to individual invocations.
This commit is contained in:
@@ -19,6 +19,15 @@ export interface WorkflowInvocationStep {
|
||||
id: string;
|
||||
}
|
||||
|
||||
export async function invocationForJob(params: { jobId: string }): Promise<WorkflowInvocation | null> {
|
||||
const { data } = await axios.get(`${getAppRoot()}api/invocations?job_id=${params.jobId}`);
|
||||
if (data.length > 0) {
|
||||
return data[0] as WorkflowInvocation;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Replace these provisional functions with fetchers after https://github.com/galaxyproject/galaxy/pull/16707 is merged
|
||||
export async function fetchInvocationDetails(params: { id: string }): Promise<ApiResponse<WorkflowInvocation>> {
|
||||
const { data } = await axios.get(`${getAppRoot()}api/invocations/${params.id}`);
|
||||
|
||||
@@ -22,6 +22,7 @@ describe("JobInformation/JobInformation.vue", () => {
|
||||
axiosMock = new MockAdapter(axios);
|
||||
axiosMock.onGet(new RegExp(`api/configuration/decode/*`)).reply(200, { decoded_id: 123 });
|
||||
axiosMock.onGet("/api/jobs/test_id?full=True").reply(200, jobResponse);
|
||||
axiosMock.onGet("/api/invocations?job_id=test_id").reply(200, []);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
||||
@@ -89,6 +89,12 @@
|
||||
{{ job.copied_from_job_id }} <DecodedId :id="job.copied_from_job_id" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="invocationId">
|
||||
<td>Workflow Invocation</td>
|
||||
<td>
|
||||
<router-link :to="routeToInvocation">{{ invocationId }}</router-link>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@@ -103,6 +109,8 @@ import { formatDuration, intervalToDuration } from "date-fns";
|
||||
import { getAppRoot } from "onload/loadConfig";
|
||||
import JOB_STATES_MODEL from "utils/job-states-model";
|
||||
|
||||
import { invocationForJob } from "@/api/invocations";
|
||||
|
||||
import DecodedId from "../DecodedId.vue";
|
||||
import CodeRow from "./CodeRow.vue";
|
||||
|
||||
@@ -128,6 +136,7 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
job: null,
|
||||
invocationId: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@@ -139,6 +148,9 @@ export default {
|
||||
jobIsTerminal() {
|
||||
return this.job && !JOB_STATES_MODEL.NON_TERMINAL_STATES.includes(this.job.state);
|
||||
},
|
||||
routeToInvocation() {
|
||||
return `/workflows/invocations/${this.invocationId}`;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
getAppRoot() {
|
||||
@@ -146,6 +158,17 @@ export default {
|
||||
},
|
||||
updateJob(job) {
|
||||
this.job = job;
|
||||
if (job) {
|
||||
this.fetchInvocation(job.id);
|
||||
}
|
||||
},
|
||||
async fetchInvocation(jobId) {
|
||||
if (jobId) {
|
||||
const invocation = await invocationForJob({ jobId: jobId });
|
||||
if (invocation) {
|
||||
this.invocationId = invocation.id;
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -24,7 +24,8 @@
|
||||
<small class="float-right" :data-invocation-id="row.item.id">
|
||||
<b>Last updated: <UtcDate :date="row.item.update_time" mode="elapsed" />;</b>
|
||||
<b
|
||||
>Invocation ID: <code>{{ row.item.id }}</code></b
|
||||
>Invocation ID:
|
||||
<router-link :to="invocationLink(row.item)">{{ row.item.id }}</router-link></b
|
||||
>
|
||||
</small>
|
||||
<WorkflowInvocationState :invocation-id="row.item.id" @invocation-cancelled="refresh" />
|
||||
@@ -222,6 +223,9 @@ export default {
|
||||
swapRowDetails(row) {
|
||||
row.toggleDetails();
|
||||
},
|
||||
invocationLink(item) {
|
||||
return `/workflows/invocations/${item.id}`;
|
||||
},
|
||||
switchHistory(historyId) {
|
||||
const Galaxy = getGalaxyInstance();
|
||||
Galaxy.currHistoryPanel.switchToHistory(historyId);
|
||||
|
||||
@@ -71,6 +71,7 @@ import Sharing from "@/components/Sharing/SharingPage.vue";
|
||||
import HistoryStorageOverview from "@/components/User/DiskUsage/Visualizations/HistoryStorageOverview.vue";
|
||||
import UserDatasetPermissions from "@/components/User/UserDatasetPermissions.vue";
|
||||
import WorkflowPublished from "@/components/Workflow/Published/WorkflowPublished.vue";
|
||||
import WorkflowInvocationState from "@/components/WorkflowInvocationState/WorkflowInvocationState.vue";
|
||||
|
||||
Vue.use(VueRouter);
|
||||
|
||||
@@ -527,6 +528,11 @@ export function getRouter(Galaxy) {
|
||||
invocationId: route.query.id,
|
||||
}),
|
||||
},
|
||||
{
|
||||
path: "workflows/invocations/:invocationId",
|
||||
component: WorkflowInvocationState,
|
||||
props: true,
|
||||
},
|
||||
{
|
||||
path: "workflows/list",
|
||||
component: WorkflowList,
|
||||
|
||||
@@ -272,6 +272,7 @@ def app_pair(global_conf, load_app_kwds=None, wsgi_preflight=True, **kwargs):
|
||||
webapp.add_client_route("/workflows/trs_import")
|
||||
webapp.add_client_route("/workflows/trs_search")
|
||||
webapp.add_client_route("/workflows/invocations")
|
||||
webapp.add_client_route("/workflows/invocations/{invocation_id}")
|
||||
webapp.add_client_route("/workflows/sharing")
|
||||
webapp.add_client_route("/workflows/{stored_workflow_id}/invocations")
|
||||
webapp.add_client_route("/workflows/invocations/report")
|
||||
|
||||
Reference in New Issue
Block a user