mirror of
https://gitlab.com/wgp/dougal/software.git
synced 2025-12-06 10:57:07 +00:00
Add Vuex plan module
This commit is contained in:
@@ -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 plan from './modules/plan'
|
||||
import line from './modules/line'
|
||||
import notify from './modules/notify'
|
||||
|
||||
@@ -20,6 +21,7 @@ export default new Vuex.Store({
|
||||
project,
|
||||
event,
|
||||
label,
|
||||
plan,
|
||||
line,
|
||||
notify
|
||||
}
|
||||
|
||||
114
lib/www/client/source/src/store/modules/plan/actions.js
Normal file
114
lib/www/client/source/src/store/modules/plan/actions.js
Normal file
@@ -0,0 +1,114 @@
|
||||
|
||||
/** Fetch sequences from server
|
||||
*/
|
||||
async function refreshPlan ({commit, dispatch, state, rootState}) {
|
||||
|
||||
if (state.loading) {
|
||||
commit('abortPlanLoading');
|
||||
}
|
||||
|
||||
commit('setPlanLoading');
|
||||
const pid = rootState.project.projectId;
|
||||
const url = `/project/${pid}/plan`;
|
||||
const init = {
|
||||
signal: state.loading.signal
|
||||
};
|
||||
const res = await dispatch('api', [url, init]);
|
||||
|
||||
if (res) {
|
||||
commit('setPlan', res);
|
||||
commit('setPlanTimestamp');
|
||||
}
|
||||
commit('clearPlanLoading');
|
||||
}
|
||||
|
||||
/** Return a subset of sequences from state.sequences
|
||||
*/
|
||||
async function getPlannedSequences ({commit, dispatch, state}, [projectId, {sequence, date0, date1, sortBy, sortDesc, itemsPerPage, page, text}]) {
|
||||
let filteredPlannedSequences = [...state.sequences];
|
||||
|
||||
if (sortBy) {
|
||||
|
||||
sortBy.forEach( (key, idx) => {
|
||||
filteredPlannedSequences.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) {
|
||||
filteredPlannedSequences.reverse();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
if (sequence) {
|
||||
filteredPlannedSequences = filteredPlannedSequences.filter( sequence => sequence.sequence == sequence );
|
||||
}
|
||||
|
||||
if (date0 && date1) {
|
||||
filteredPlannedSequences = filteredPlannedSequences.filter( sequence =>
|
||||
sequence.ts0.substr(0, 10) >= date0 && sequence.ts1.substr(0, 10) <= date1
|
||||
);
|
||||
} else if (date0) {
|
||||
filteredPlannedSequences = filteredPlannedSequences.filter( sequence => sequence.ts0.substr(0, 10) == date0 || sequence.ts1.substr(0, 10) );
|
||||
}
|
||||
|
||||
if (text) {
|
||||
const tstampFilter = (value, search, item) => {
|
||||
return textFilter(value.toISOString(), search, item);
|
||||
};
|
||||
|
||||
const numberFilter = (value, search, item) => {
|
||||
return value == search;
|
||||
};
|
||||
|
||||
const textFilter = (value, search, item) => {
|
||||
return String(value).toLowerCase().includes(search.toLowerCase());
|
||||
};
|
||||
|
||||
const searchFunctions = {
|
||||
sequence: numberFilter,
|
||||
line: numberFilter,
|
||||
remarks: textFilter,
|
||||
ts0: tstampFilter,
|
||||
ts1: tstampFilter
|
||||
};
|
||||
|
||||
filteredPlannedSequences = filteredPlannedSequences.filter ( sequence => {
|
||||
for (let key in searchFunctions) {
|
||||
const fn = searchFunctions[key];
|
||||
if (fn(sequence[key], text, sequence)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
const count = filteredPlannedSequences.length;
|
||||
|
||||
if (itemsPerPage && itemsPerPage > 0) {
|
||||
const offset = (page > 0)
|
||||
? (page-1) * itemsPerPage
|
||||
: 0;
|
||||
|
||||
filteredPlannedSequences = filteredPlannedSequences.slice(offset, offset+itemsPerPage);
|
||||
}
|
||||
|
||||
return {sequences: filteredPlannedSequences, count};
|
||||
}
|
||||
|
||||
export default { refreshPlan, getPlannedSequences };
|
||||
18
lib/www/client/source/src/store/modules/plan/getters.js
Normal file
18
lib/www/client/source/src/store/modules/plan/getters.js
Normal file
@@ -0,0 +1,18 @@
|
||||
|
||||
function planRemarks (state) {
|
||||
return state.remarks;
|
||||
}
|
||||
|
||||
function plannedSequences (state) {
|
||||
return state.sequences;
|
||||
}
|
||||
|
||||
function plannedSequenceCount (state) {
|
||||
return state.sequences?.length ?? 0;
|
||||
}
|
||||
|
||||
function plannedSequencesLoading (state) {
|
||||
return !!state.loading;
|
||||
}
|
||||
|
||||
export default { planRemarks, plannedSequences, plannedSequenceCount, plannedSequencesLoading };
|
||||
6
lib/www/client/source/src/store/modules/plan/index.js
Normal file
6
lib/www/client/source/src/store/modules/plan/index.js
Normal 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 };
|
||||
59
lib/www/client/source/src/store/modules/plan/mutations.js
Normal file
59
lib/www/client/source/src/store/modules/plan/mutations.js
Normal file
@@ -0,0 +1,59 @@
|
||||
|
||||
|
||||
function transform (item) {
|
||||
item.ts0 = new Date(item.ts0);
|
||||
item.ts1 = new Date(item.ts1);
|
||||
return item;
|
||||
}
|
||||
|
||||
// ATTENTION: This relies on the new planner endpoint
|
||||
// as per issue #281.
|
||||
|
||||
function setPlan (state, plan) {
|
||||
// We don't need or want the planned sequences array to be reactive
|
||||
state.sequences = Object.freeze(plan.sequences.map(transform));
|
||||
state.remarks = plan.remarks;
|
||||
}
|
||||
|
||||
function setPlanLoading (state, abortController = new AbortController()) {
|
||||
state.loading = abortController;
|
||||
}
|
||||
|
||||
// This assumes that we know any transactions have finished or we
|
||||
// don't care about aborting.
|
||||
function clearPlanLoading (state) {
|
||||
state.loading = null;
|
||||
}
|
||||
|
||||
function setPlanTimestamp (state, timestamp = new Date()) {
|
||||
// NOTE: There is no `modified_on` property in the plan
|
||||
// result or in the database schema, but we should probably add
|
||||
// one.
|
||||
if (timestamp === true) {
|
||||
const tstamp = state.plan
|
||||
.map( item => item.modified_on )
|
||||
.reduce( (acc, cur) => acc > cur ? acc : cur );
|
||||
state.timestamp = tstamp ? new Date(tstamp) : new Date();
|
||||
} else {
|
||||
state.timestamp = timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
function setPlanETag (state, etag) {
|
||||
state.etag = etag;
|
||||
}
|
||||
|
||||
function abortPlanLoading (state) {
|
||||
if (state.loading) {
|
||||
state.loading.abort();
|
||||
}
|
||||
state.loading = null;
|
||||
}
|
||||
|
||||
export default {
|
||||
setPlan,
|
||||
setPlanLoading,
|
||||
clearPlanLoading,
|
||||
setPlanTimestamp,
|
||||
setPlanETag
|
||||
};
|
||||
9
lib/www/client/source/src/store/modules/plan/state.js
Normal file
9
lib/www/client/source/src/store/modules/plan/state.js
Normal file
@@ -0,0 +1,9 @@
|
||||
const state = () => ({
|
||||
sequences: Object.freeze([]),
|
||||
remarks: null,
|
||||
loading: null,
|
||||
timestamp: null,
|
||||
etag: null,
|
||||
});
|
||||
|
||||
export default state;
|
||||
Reference in New Issue
Block a user