From 7c52ada9227f73cbe050f8305998f1a1d0bca5fd Mon Sep 17 00:00:00 2001 From: "D. Berge" Date: Mon, 18 Aug 2025 13:50:49 +0200 Subject: [PATCH] Add project group info to Vuex --- .../src/store/modules/projects/actions.js | 102 +++++++++++++++++- .../src/store/modules/projects/getters.js | 8 +- .../src/store/modules/projects/mutations.js | 7 +- .../src/store/modules/projects/state.js | 1 + 4 files changed, 113 insertions(+), 5 deletions(-) diff --git a/lib/www/client/source/src/store/modules/projects/actions.js b/lib/www/client/source/src/store/modules/projects/actions.js index a604d44..38bca66 100644 --- a/lib/www/client/source/src/store/modules/projects/actions.js +++ b/lib/www/client/source/src/store/modules/projects/actions.js @@ -1,3 +1,5 @@ +import * as d3a from 'd3-array'; +import { duration_to_ms, ms_to_duration, normalise_duration, add_durations } from '@/lib/durations'; /** Fetch projects from server */ @@ -8,6 +10,7 @@ async function refreshProjects ({commit, dispatch, state, rootState}) { } commit('setProjectsLoading'); + const tstamp = new Date(); const pid = rootState.project.projectId; const url = `/project`; const init = { @@ -17,10 +20,26 @@ async function refreshProjects ({commit, dispatch, state, rootState}) { const res = await dispatch('api', [url, init, null, {silent:true}]); if (res) { + for (let index in res) { + const project = res[index]; + + if (!project.pid) { + console.warn("Project has no Project ID!"); + continue; + } + + const url = `/project/${project.pid}/summary`; + const init = {}; + const summary = await dispatch('api', [url, init, null, {silent:true}]); + if (summary) { + res[index] = {...project, ...summary}; + } + } commit('setProjects', res); - commit('setProjectsTimestamp'); + commit('setProjectsTimestamp', tstamp); } commit('clearProjectsLoading'); + dispatch('prepareGroups'); } /** Return a subset of projects from state.projects @@ -118,4 +137,83 @@ async function getProjects ({commit, dispatch, state}, [{pid, name, schema, grou return {projects: filteredProjects, count}; } -export default { refreshProjects, getProjects }; + + +async function prepareGroups ({commit, dispatch, state, rootState}) { + const groups = {}; + + for (const project of state.projects) { + + if (!project.prod_distance) { + // This project has no production data (either not started yet + // or production data has not been imported) so we skip it. + continue; + } + + if (!project.prod_duration.days) { + project.prod_duration = normalise_duration(project.prod_duration); + } + + for (const name of project.groups) { + if (!(name in groups)) { + groups[name] = { + group: name, + num_projects: 0, + lines: 0, + points: 0, + sequences: 0, + // Shots: + prime: 0, + other: 0, + ntba: 0, + prod_duration: { + days: 0, + hours: 0, + minutes: 0, + seconds: 0, + milliseconds: 0 + }, + prod_distance: 0, + shooting_rate: [], + projects: [] + }; + } + const group = groups[name]; + + group.num_projects++; + group.lines = Math.max(group.lines, project.lines); // In case preplots changed + group.points = Math.max(group.points, project.total); // Idem + group.sequences += project.seq_final; + group.prime += project.prime; + group.other += project.other; + //group.ntba += project.ntba; + group.prod_duration = add_durations(group.prod_duration, project.prod_duration); + group.prod_distance += project.prod_distance; + group.shooting_rate.push(project.shooting_rate); + group.projects.push(project); + } + } + + const grouplist = []; + for (const group of Object.values(groups)) { + group.shooting_rate_mean = d3a.mean(group.shooting_rate); + group.shooting_rate_sd = d3a.deviation(group.shooting_rate); + delete group.shooting_rate; + + grouplist.push(group); + } + + commit('setGroups', grouplist); + +} + +async function getGroups({commit, dispatch, state, rootState}) { + if (!state.groups.length) { + await dispatch('refreshProjects'); + } + + return state.groups; +} + + +export default { refreshProjects, getProjects, prepareGroups, getGroups }; diff --git a/lib/www/client/source/src/store/modules/projects/getters.js b/lib/www/client/source/src/store/modules/projects/getters.js index df0758b..8b0b6bb 100644 --- a/lib/www/client/source/src/store/modules/projects/getters.js +++ b/lib/www/client/source/src/store/modules/projects/getters.js @@ -3,7 +3,7 @@ function projects (state) { return state.projects; } -function projectGroups (state) { +function projectGroupNames (state) { return [...new Set(state.projects.map(i => i.groups).flat())].sort(); } @@ -15,4 +15,8 @@ function projectsLoading (state) { return !!state.loading; } -export default { projects, projectGroups, projectCount, projectsLoading }; +function groups (state) { + return state.groups; +} + +export default { projects, projectGroupNames, projectCount, projectsLoading, groups }; diff --git a/lib/www/client/source/src/store/modules/projects/mutations.js b/lib/www/client/source/src/store/modules/projects/mutations.js index 0f639b1..b9ce4fd 100644 --- a/lib/www/client/source/src/store/modules/projects/mutations.js +++ b/lib/www/client/source/src/store/modules/projects/mutations.js @@ -39,10 +39,15 @@ function abortProjectsLoading (state) { state.loading = null; } +function setGroups (state, groups) { + state.groups = Object.freeze(groups); +} + export default { setProjects, setProjectsLoading, clearProjectsLoading, setProjectsTimestamp, - setProjectsETag + setProjectsETag, + setGroups }; diff --git a/lib/www/client/source/src/store/modules/projects/state.js b/lib/www/client/source/src/store/modules/projects/state.js index 3758fc2..ab01728 100644 --- a/lib/www/client/source/src/store/modules/projects/state.js +++ b/lib/www/client/source/src/store/modules/projects/state.js @@ -1,5 +1,6 @@ const state = () => ({ projects: Object.freeze([]), + groups: Object.freeze([]), loading: null, timestamp: null, etag: null,