96 lines
3.0 KiB
JavaScript
96 lines
3.0 KiB
JavaScript
import { defineStore } from 'pinia'
|
|
|
|
import * as API from '@/manager-api';
|
|
import { apiClient } from '@/stores/api-query-count';
|
|
|
|
|
|
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', {
|
|
state: () => ({
|
|
/** @type {API.Job} */
|
|
activeJob: null,
|
|
/**
|
|
* ID of the active job. Easier to query than `activeJob ? activeJob.id : ""`.
|
|
* @type {string}
|
|
*/
|
|
activeJobID: "",
|
|
}),
|
|
getters: {
|
|
canDelete() {
|
|
return this._anyJobWithStatus(["queued", "paused", "failed", "completed", "canceled"])
|
|
},
|
|
canCancel() {
|
|
return this._anyJobWithStatus(["queued", "active", "failed"])
|
|
},
|
|
canRequeue() {
|
|
return this._anyJobWithStatus(["canceled", "completed", "failed", "paused"])
|
|
},
|
|
},
|
|
actions: {
|
|
setActiveJobID(jobID) {
|
|
this.$patch({
|
|
activeJob: {id: jobID, settings: {}, metadata: {}},
|
|
activeJobID: jobID,
|
|
});
|
|
},
|
|
setActiveJob(job) {
|
|
// The "function" form of $patch is necessary here, as otherwise it'll
|
|
// merge `job` into `state.activeJob`. As a result, it won't touch missing
|
|
// keys, which means that metadata fields that existed on the previous job
|
|
// but not on the new one will still linger around. By passing a function
|
|
// to `$patch` this is resolved.
|
|
this.$patch((state) => {
|
|
state.activeJob = job;
|
|
state.activeJobID = job.id;
|
|
state.hasChanged = true;
|
|
});
|
|
},
|
|
deselectAllJobs() {
|
|
this.$patch({
|
|
activeJob: null,
|
|
activeJobID: "",
|
|
});
|
|
},
|
|
|
|
/**
|
|
* 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.
|
|
*/
|
|
cancelJobs() { return this._setJobStatus("cancel-requested"); },
|
|
requeueJobs() { return this._setJobStatus("requeueing"); },
|
|
|
|
// Internal methods.
|
|
|
|
/**
|
|
*
|
|
* @param {string[]} statuses
|
|
* @returns bool indicating whether there is a selected job with any of the given statuses.
|
|
*/
|
|
_anyJobWithStatus(statuses) {
|
|
return !!this.activeJob && !!this.activeJob.status && statuses.includes(this.activeJob.status);
|
|
// return this.selectedJobs.reduce((foundJob, job) => (foundJob || statuses.includes(job.status)), false);
|
|
},
|
|
|
|
/**
|
|
* Transition the selected job(s) to the new status.
|
|
* @param {string} newStatus
|
|
* @returns a Promise for the API request.
|
|
*/
|
|
_setJobStatus(newStatus) {
|
|
if (!this.activeJobID) {
|
|
console.warn(`_setJobStatus(${newStatus}) impossible, no active job ID`);
|
|
return;
|
|
}
|
|
const statuschange = new API.JobStatusChange(newStatus, "requested from web interface");
|
|
return jobsAPI.setJobStatus(this.activeJobID, statuschange);
|
|
},
|
|
},
|
|
})
|