Add Vuex sequence module

This commit is contained in:
D. Berge
2023-10-25 09:57:05 +02:00
parent a26974670a
commit 680e376ed1
6 changed files with 201 additions and 0 deletions

View File

@@ -7,6 +7,7 @@ import snack from './modules/snack'
import project from './modules/project'
import event from './modules/event'
import label from './modules/label'
import sequence from './modules/sequence'
import plan from './modules/plan'
import line from './modules/line'
import notify from './modules/notify'
@@ -21,6 +22,7 @@ export default new Vuex.Store({
project,
event,
label,
sequence,
plan,
line,
notify

View File

@@ -0,0 +1,122 @@
/** Fetch sequences from server
*/
async function refreshSequences ({commit, dispatch, state, rootState}) {
if (state.loading) {
commit('abortSequencesLoading');
}
commit('setSequencesLoading');
const pid = rootState.project.projectId;
const url = `/project/${pid}/sequence?files=true`;
const init = {
signal: state.loading.signal
};
const res = await dispatch('api', [url, init]);
if (res) {
commit('setSequences', res);
commit('setSequencesTimestamp');
}
commit('clearSequencesLoading');
}
/** Return a subset of sequences from state.sequences
*/
async function getSequences ({commit, dispatch, state}, [projectId, {sequence, date0, date1, sortBy, sortDesc, itemsPerPage, page, text}]) {
let filteredSequences = [...state.sequences];
if (sortBy) {
sortBy.forEach( (key, idx) => {
filteredSequences.sort( (el0, el1) => {
const a = el0?.[key];
const b = el1?.[key];
if (a < b) {
return -1;
} else if (a > b) {
return 1;
} else if (a == b) {
return 0;
} else if (a && !b) {
return 1;
} else if (!a && b) {
return -1;
} else {
return 0;
}
});
if (sortDesc && sortDesc[idx] === true) {
filteredSequences.reverse();
}
});
}
if (sequence) {
filteredSequences = filteredSequences.filter( sequence => sequence.sequence == sequence );
}
if (date0 && date1) {
filteredSequences = filteredSequences.filter( sequence =>
(sequence.ts0_final ?? sequence.ts0)?.substr(0, 10) >= date0 &&
(sequence.ts1_final ?? sequence.ts1)?.substr(0, 10) <= date1
);
} else if (date0) {
filteredSequences = filteredSequences.filter( sequence => (sequence.ts0_final ?? sequence.ts0)?.substr(0, 10) == date0 || (sequence.ts1_final ?? sequence.ts1)?.substr(0, 10) );
}
if (text) {
const tstampFilter = (value, search, item) => {
return search?.length >= 5 && textFilter(value, search, item);
};
const numberFilter = (value, search, item) => {
return value == search;
};
const textFilter = (value, search, item) => {
return String(value).toLowerCase().includes(search.toLowerCase());
};
const searchFunctions = {
ts0: tstampFilter,
ts1: tstampFilter,
ts0_final: tstampFilter,
ts1_final: tstampFilter,
sequence: numberFilter,
line: numberFilter,
fsp: numberFilter,
lsp: numberFilter,
fsp_final: numberFilter,
fsp_final: numberFilter,
remarks: textFilter,
remarks_final: textFilter
};
filteredSequences = filteredSequences.filter ( sequence => {
for (let key in searchFunctions) {
const fn = searchFunctions[key];
if (fn(sequence[key], text, sequence)) {
return true;
}
}
return false;
});
}
const count = filteredSequences.length;
if (itemsPerPage && itemsPerPage > 0) {
const offset = (page > 0)
? (page-1) * itemsPerPage
: 0;
filteredSequences = filteredSequences.slice(offset, offset+itemsPerPage);
}
return {sequences: filteredSequences, count};
}
export default { refreshSequences, getSequences };

View File

@@ -0,0 +1,14 @@
function sequences (state) {
return state.sequences;
}
function sequenceCount (state) {
return state.sequences?.length ?? 0;
}
function sequencesLoading (state) {
return !!state.loading;
}
export default { sequences, sequenceCount, sequencesLoading };

View File

@@ -0,0 +1,6 @@
import state from './state'
import getters from './getters'
import actions from './actions'
import mutations from './mutations'
export default { state, getters, actions, mutations };

View File

@@ -0,0 +1,49 @@
function setSequences (state, sequences) {
// We don't need or want the events array to be reactive, since
// it can be tens of thousands of items long.
state.sequences = Object.freeze(sequences);
}
function setSequencesLoading (state, abortController = new AbortController()) {
state.loading = abortController;
}
// This assumes that we know any transactions have finished or we
// don't care about aborting.
function clearSequencesLoading (state) {
state.loading = null;
}
function setSequencesTimestamp (state, timestamp = new Date()) {
// NOTE: There is no `modified_on` property in the sequences
// result or in the database schema, but we should probably add
// one.
if (timestamp === true) {
const tstamp = state.sequences
.map( event => event.modified_on )
.reduce( (acc, cur) => acc > cur ? acc : cur );
state.timestamp = tstamp ? new Date(tstamp) : new Date();
} else {
state.timestamp = timestamp;
}
}
function setSequencesETag (state, etag) {
state.etag = etag;
}
function abortSequencesLoading (state) {
if (state.loading) {
state.loading.abort();
}
state.loading = null;
}
export default {
setSequences,
setSequencesLoading,
clearSequencesLoading,
setSequencesTimestamp,
setSequencesETag
};

View File

@@ -0,0 +1,8 @@
const state = () => ({
sequences: Object.freeze([]),
loading: null,
timestamp: null,
etag: null,
});
export default state;