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:
parent
1331d29b10
commit
d84efb8c9a
@ -149,7 +149,7 @@ export default {
|
|||||||
--footer-height: 25px;
|
--footer-height: 25px;
|
||||||
--grid-gap: 4px;
|
--grid-gap: 4px;
|
||||||
|
|
||||||
--action-bar-height: 3em;
|
--action-bar-height: 2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
html,
|
html,
|
||||||
@ -232,12 +232,11 @@ footer {
|
|||||||
|
|
||||||
section.action-bar {
|
section.action-bar {
|
||||||
height: var(--action-bar-height);
|
height: var(--action-bar-height);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
}
|
}
|
||||||
|
|
||||||
section.action-bar button.action {
|
section.action-bar button.action {
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
padding: 0.1rem 0.75rem;
|
padding: 0.1rem 0.75rem;
|
||||||
border-radius: 0.3rem;
|
border-radius: 0.3rem;
|
||||||
border: thin solid white;
|
border: thin solid white;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<section class="action-bar jobs">
|
<section class="action-bar jobs">
|
||||||
<button class="action delete dangerous" :disabled="!jobs.canDelete" v-on:click="onButtonDelete">Delete</button>
|
<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>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -10,7 +11,6 @@ import { useNotifs } from '@/stores/notifications';
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "JobActionsBar",
|
name: "JobActionsBar",
|
||||||
events: ["actionDone", "apiError"],
|
|
||||||
data: () => ({
|
data: () => ({
|
||||||
jobs: useJobs(),
|
jobs: useJobs(),
|
||||||
notifs: useNotifs(),
|
notifs: useNotifs(),
|
||||||
@ -29,6 +29,23 @@ export default {
|
|||||||
this.notifs.add(`Error: ${errorMsg}`);
|
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}`);
|
||||||
|
})
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,9 @@ import { defineStore } from 'pinia'
|
|||||||
import * as urls from '@/urls'
|
import * as urls from '@/urls'
|
||||||
import * as API from '@/manager-api';
|
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.
|
// 'use' prefix is idiomatic for Pinia stores.
|
||||||
// See https://pinia.vuejs.org/core-concepts/
|
// See https://pinia.vuejs.org/core-concepts/
|
||||||
export const useJobs = defineStore('jobs', {
|
export const useJobs = defineStore('jobs', {
|
||||||
@ -17,7 +20,10 @@ export const useJobs = defineStore('jobs', {
|
|||||||
return this.selectedJobs.length;
|
return this.selectedJobs.length;
|
||||||
},
|
},
|
||||||
canDelete() {
|
canDelete() {
|
||||||
return this._anyJobWithStatus(["queued", "paused", "failed", "completed"])
|
return this._anyJobWithStatus(["queued", "paused", "failed", "completed", "canceled"])
|
||||||
|
},
|
||||||
|
canCancel() {
|
||||||
|
return this._anyJobWithStatus(["queued", "active"])
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
@ -35,13 +41,25 @@ export const useJobs = defineStore('jobs', {
|
|||||||
this.activeJob = null;
|
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() {
|
deleteJobs() {
|
||||||
const deletionPromise = new Promise( (resolutionFunc, rejectionFunc) => {
|
const deletionPromise = new Promise( (resolutionFunc, rejectionFunc) => {
|
||||||
rejectionFunc({code: 327, message: "deleting jobs is not implemented in JS yet"});
|
rejectionFunc({code: 327, message: "deleting jobs is not implemented in JS yet"});
|
||||||
});
|
});
|
||||||
return deletionPromise;
|
return deletionPromise;
|
||||||
},
|
},
|
||||||
|
cancelJobs() {
|
||||||
|
const statuschange = new API.JobStatusChange("cancel-requested", "requested from web interface");
|
||||||
|
return jobsAPI.setJobStatus(this.activeJob.id, statuschange);
|
||||||
|
},
|
||||||
|
|
||||||
// Internal methods.
|
// Internal methods.
|
||||||
_anyJobWithStatus(statuses) {
|
_anyJobWithStatus(statuses) {
|
||||||
return this.selectedJobs.reduce((foundJob, job) => (foundJob || statuses.includes(job.status)), false);
|
return this.selectedJobs.reduce((foundJob, job) => (foundJob || statuses.includes(job.status)), false);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user