Web: proper updating & sorting of jobs in Tabulator

This commit is contained in:
Sybren A. Stüvel 2022-04-08 13:08:53 +02:00
parent def1778aa6
commit 96e5e84881

View File

@ -1,12 +1,21 @@
<template> <template>
<div class="flamenco-jobs-table"> <div class="flamenco-jobs-table">
<JobsTabulator v-model="jobs" :options="options" /> <JobsTabulator
ref="tabulator"
:options="options"
/>
</div> </div>
</template> </template>
<script> <script>
import { TabulatorComponent } from "vue-tabulator"; /**
* NOTE: the <JobsTabulator> component does NOT have a v-model attribute.
* Instead of using Vue, data updates are handled on the Tabulator instance
* directly. This gives more control over replacing data & updating existing
* entries.
*/
import moment from "moment"; import moment from "moment";
import { TabulatorComponent } from "vue-tabulator";
const flamencoManager = require('flamenco-manager'); const flamencoManager = require('flamenco-manager');
@ -19,67 +28,78 @@ export default {
const options = { const options = {
// See pkg/api/flamenco-manager.yaml, schemas Job and JobUpdate. // See pkg/api/flamenco-manager.yaml, schemas Job and JobUpdate.
columns: [ columns: [
{ title: 'Name', field: 'name', sorter: 'string', width: 200 }, { title: 'ID', field: 'id', sorter: 'string'},
{ title: 'Name', field: 'name', sorter: 'string' },
{ title: 'Status', field: 'status', sorter: 'string', width: 100 }, { title: 'Status', field: 'status', sorter: 'string', width: 100 },
{ title: 'Type', field: 'type', sorter: 'string', width: 150 }, { title: 'Type', field: 'type', sorter: 'string', width: 150 },
{ title: 'Prio', field: 'priority', sorter: 'number'}, { title: 'Prio', field: 'priority', sorter: 'number'},
{ title: 'Updated', field: 'updated', sorter: 'string', { title: 'Updated', field: 'updated', sorter: 'datetime',
sorterParams: {
format: "YYYY-MM-DD hh:mm:ss", // Format suitable for sorting chronologically.
alignEmptyValues: "top",
},
formatter: function (cell, formatterParams) { // eslint-disable-line no-unused-vars formatter: function (cell, formatterParams) { // eslint-disable-line no-unused-vars
return moment(cell.getData().value).format('YYYY-MM-DD HH:mm') const updated = moment(cell.getData().updated);
const now = moment();
const ageInDays = now.diff(updated, 'days');
if (ageInDays > 14)
return updated.format('YYYY-MM-DD HH:mm:ss')
return updated.fromNow();
} }
}, },
], ],
initialSort:[ initialSort:[
{column:"updated", dir:"desc"}, {column:"updated", dir:"desc"},
], ],
pagination: "local",
paginationSize: 10,
}; };
return { return {
jobs: [
// Will be loaded via a Flamenco API call.
],
options: options, options: options,
}; };
}, },
mounted: function() { mounted: function() {
// Allow testing from the JS console:
// jobsTableVue.processJobUpdate({id: "1e42bbf8-6a17-49b9-8a2a-2c80c6532465", status: "heyy", updated: moment().format(), previous_status: "uuuuh", name: "Updated manually"});
// jobsTableVue.processJobUpdate({id: "7c26cac3-1811-42a8-8577-cd20faeb01a4", status: "heyy", updated: moment().format()});
window.jobsTableVue = this;
this.fetchAllJobs(); this.fetchAllJobs();
}, },
methods: { methods: {
tabulator: function() {
const tab = this.$refs.tabulator.getInstance();
return tab;
},
sortData: function() {
const tab = this.tabulator();
tab.setSort(tab.getSorters()); // This triggers re-sorting.
},
fetchAllJobs: function() { fetchAllJobs: function() {
// TODO: maybe move fetching of the data out of this component?
const JobsApi = new flamencoManager.JobsApi(this.apiClient); const JobsApi = new flamencoManager.JobsApi(this.apiClient);
const jobsQuery = {}; const jobsQuery = {};
JobsApi.queryJobs(jobsQuery).then(this.onJobsFetched, function(error) { JobsApi.queryJobs(jobsQuery).then(this.onJobsFetched, function(error) {
// TODO: error handling. // TODO: error handling.
console.error(error); console.error(error);
}); });
}, },
onJobsFetched: function(data) { onJobsFetched: function(data) {
this.jobs = data.jobs; this.tabulator().setData(data.jobs);
}, },
processJobUpdate: function(jobUpdate) { processJobUpdate: function(jobUpdate) {
console.log("processJobUpdate:", jobUpdate); // updateData() will only overwrite properties that are actually set on
for (let job of this.jobs) { // jobUpdate, and leave the rest as-is.
if (job.id != jobUpdate.id) { this.tabulator().updateData([jobUpdate])
console.log("not same ID:", job.id, jobUpdate.id); .then(this.sortData);
continue;
}
console.log("Found job:", JSON.parse(JSON.stringify(job)));
job.name = jobUpdate.name; // Shouldn't be changing, but you never know.
job.status = jobUpdate.status;
job.updated = jobUpdate.updated;
}
}, },
processNewJob: function(jobUpdate) { processNewJob: function(jobUpdate) {
console.log("processNewJob:", jobUpdate); console.log("processNewJob:", jobUpdate);
// The update doesn't have all the info we need, so just fetch the job via an API call. // The update doesn't have all the info we need, so just fetch the job via an API call.
// Updates should match what's needed here, but the API call needs testing too, so whatevah ;-)
const JobsApi = new flamencoManager.JobsApi(this.apiClient); const JobsApi = new flamencoManager.JobsApi(this.apiClient);
JobsApi.fetchJob(jobUpdate.id).then((job) => { JobsApi.fetchJob(jobUpdate.id).then((job) => {
console.log('API called successfully. Returned data: ' + job); console.log('API called successfully. Returned data: ' + job);
console.log("Fetched job:", JSON.parse(JSON.stringify(job))); console.log("Fetched job:", JSON.parse(JSON.stringify(job)));
this.jobs.push(job); this.tabulator().addData([job])
.then(this.sortData);
}, (error) => { }, (error) => {
console.error(error); console.error(error);
}); });