Web: implement 'Cancel Job' button

The button calls the 'setJobStatus' API endpoint to set the job status to
`cancel-requested`.
This commit is contained in:
Sybren A. Stüvel 2022-04-21 16:53:20 +02:00
parent 1331d29b10
commit d84efb8c9a
3 changed files with 41 additions and 7 deletions

View File

@ -149,7 +149,7 @@ export default {
--footer-height: 25px;
--grid-gap: 4px;
--action-bar-height: 3em;
--action-bar-height: 2em;
}
html,
@ -232,12 +232,11 @@ footer {
section.action-bar {
height: var(--action-bar-height);
display: flex;
flex-direction: row;
}
section.action-bar button.action {
display: flex;
flex-direction: column;
align-items: center;
padding: 0.1rem 0.75rem;
border-radius: 0.3rem;
border: thin solid white;

View File

@ -1,6 +1,7 @@
<template>
<section class="action-bar jobs">
<button class="action delete dangerous" :disabled="!jobs.canDelete" v-on:click="onButtonDelete">Delete</button>
<button class="action cancel" :disabled="!jobs.canCancel" v-on:click="onButtonCancel">Cancel</button>
</section>
</template>
@ -10,7 +11,6 @@ import { useNotifs } from '@/stores/notifications';
export default {
name: "JobActionsBar",
events: ["actionDone", "apiError"],
data: () => ({
jobs: useJobs(),
notifs: useNotifs(),
@ -29,6 +29,23 @@ export default {
this.notifs.add(`Error: ${errorMsg}`);
})
},
onButtonCancel() {
const numJobs = this.jobs.numSelected;
this.jobs.cancelJobs()
.then(() => {
let message;
if (numJobs == 1) {
message = `Job marked for cancellation`;
} else {
message = `${numJobs} jobs marked for cancellation`;
}
this.notifs.add(message);
})
.catch((error) => {
const errorMsg = JSON.stringify(error); // TODO: handle API errors better.
this.notifs.add(`Error: ${errorMsg}`);
})
},
}
}

View File

@ -3,6 +3,9 @@ import { defineStore } from 'pinia'
import * as urls from '@/urls'
import * as API from '@/manager-api';
const apiClient = new API.ApiClient(urls.api());
const jobsAPI = new API.JobsApi(apiClient);
// 'use' prefix is idiomatic for Pinia stores.
// See https://pinia.vuejs.org/core-concepts/
export const useJobs = defineStore('jobs', {
@ -17,7 +20,10 @@ export const useJobs = defineStore('jobs', {
return this.selectedJobs.length;
},
canDelete() {
return this._anyJobWithStatus(["queued", "paused", "failed", "completed"])
return this._anyJobWithStatus(["queued", "paused", "failed", "completed", "canceled"])
},
canCancel() {
return this._anyJobWithStatus(["queued", "active"])
},
},
actions: {
@ -35,13 +41,25 @@ export const useJobs = defineStore('jobs', {
this.activeJob = null;
},
// Actions on the selected jobs.
/**
* Actions on the selected jobs.
*
* All the action functions return a promise that resolves when the action has been performed.
*
* TODO: actually have these work on all selected jobs. For simplicity, the
* code now assumes that only the active job needs to be operated on.
*/
deleteJobs() {
const deletionPromise = new Promise( (resolutionFunc, rejectionFunc) => {
rejectionFunc({code: 327, message: "deleting jobs is not implemented in JS yet"});
});
return deletionPromise;
},
cancelJobs() {
const statuschange = new API.JobStatusChange("cancel-requested", "requested from web interface");
return jobsAPI.setJobStatus(this.activeJob.id, statuschange);
},
// Internal methods.
_anyJobWithStatus(statuses) {
return this.selectedJobs.reduce((foundJob, job) => (foundJob || statuses.includes(job.status)), false);