mirror of
https://gitlab.com/wgp/dougal/software.git
synced 2025-12-06 06:27:07 +00:00
340 lines
8.2 KiB
Vue
340 lines
8.2 KiB
Vue
<template>
|
||
<dougal-group-map v-if="mapView"
|
||
:baseline="baseline"
|
||
:monitor="monitor"
|
||
:monitors="monitors"
|
||
@input="mapView=$event"
|
||
></dougal-group-map>
|
||
<v-container fluid fill-height class="ma-0 pa-0" v-else>
|
||
|
||
<v-overlay :value="loading && !comparisons.length" absolute>
|
||
<v-progress-circular
|
||
indeterminate
|
||
size="64"
|
||
></v-progress-circular>
|
||
</v-overlay>
|
||
|
||
<v-overlay :value="!loading && !groupFound" absolute opacity="0.8">
|
||
<v-row justify="center">
|
||
<v-alert
|
||
type="error"
|
||
>
|
||
Group not found
|
||
</v-alert>
|
||
</v-row>
|
||
<v-row justify="center">
|
||
<v-btn color="primary" @click="refreshProjects">Retry</v-btn>
|
||
</v-row>
|
||
</v-overlay>
|
||
|
||
<v-row no-gutters align="stretch" class="fill-height">
|
||
<v-col cols="12" v-if="groupFound">
|
||
|
||
<v-data-table class="ma-1"
|
||
:headers="projectHeaders"
|
||
:items="projects"
|
||
dense
|
||
>
|
||
|
||
<template v-slot:item.baseline="{item, value, index}">
|
||
<v-simple-checkbox v-if="index+1 < projects.length"
|
||
color="primary"
|
||
:value="baseline === item"
|
||
@input="setBaseline(item)"
|
||
></v-simple-checkbox>
|
||
</template>
|
||
|
||
<template v-slot:item.monitor="{item, value, index}">
|
||
<v-simple-checkbox v-if="index > 0 && !(index <= baselineIndex)"
|
||
color="primary"
|
||
:value="monitor === item"
|
||
@input="setMonitor(item)"
|
||
></v-simple-checkbox>
|
||
</template>
|
||
|
||
<template v-slot:item.pid="{item, value}">
|
||
<v-chip
|
||
label
|
||
small
|
||
outlined
|
||
:href="`/projects/${item.pid}`"
|
||
:color="!item.archived ? 'primary' : ''"
|
||
>{{ value }}</v-chip>
|
||
</template>
|
||
|
||
<template v-slot:item.fsp="{item, value}">
|
||
<span title="First production shot">{{value.tstamp.substr(0, 10)}}</span>
|
||
</template>
|
||
|
||
<template v-slot:item.lsp="{item, value}">
|
||
<span title="Last production shot">{{value.tstamp.substr(0, 10)}}</span>
|
||
</template>
|
||
|
||
<template v-slot:item.prod_duration="{item, value}">
|
||
<span v-if="value.days > 2" :title="`${value.days} d ${value.hours} h ${value.minutes} m ${(value.seconds + value.milliseconds/1000).toFixed(3)} s`">
|
||
{{ value.days }} d
|
||
</span>
|
||
<span v-else>
|
||
{{ value.days }} d {{ value.hours }} h {{ value.minutes }} m {{ (value.seconds + value.milliseconds/1000).toFixed(1) }} s
|
||
</span>
|
||
</template>
|
||
|
||
<template v-slot:item.prod_distance="{item, value}">
|
||
{{ (value/1000).toFixed(1) }} km
|
||
</template>
|
||
|
||
<template v-slot:footer.prepend>
|
||
|
||
<v-btn v-if="baseline && !mapView"
|
||
text
|
||
color="primary"
|
||
title="Switch to map view"
|
||
@click="mapView = true"
|
||
>View map</v-btn>
|
||
|
||
<v-btn v-if="comparison"
|
||
text
|
||
color="primary"
|
||
title="Back to summary"
|
||
@click="clearComparison"
|
||
>Back</v-btn>
|
||
</template>
|
||
|
||
</v-data-table>
|
||
|
||
<!-- BEGIN TEST -->
|
||
|
||
<dougal-group-comparison-summary v-if="comparison"
|
||
:baseline="baseline"
|
||
:monitor="monitor"
|
||
:comparison="comparison"
|
||
></dougal-group-comparison-summary>
|
||
|
||
<dougal-group-repeatability-summary v-else-if="comparisons.length"
|
||
:comparisons="comparisons"
|
||
:projects="projects"
|
||
@input="setComparison"
|
||
></dougal-group-repeatability-summary>
|
||
|
||
<!-- END TEST -->
|
||
|
||
|
||
</v-col>
|
||
<v-col cols="12" v-else>
|
||
<v-card>
|
||
<v-card-text>
|
||
Group does not exist.
|
||
</v-card-text>
|
||
</v-card>
|
||
</v-col>
|
||
</v-row>
|
||
</v-container>
|
||
</template>
|
||
|
||
<script>
|
||
import { mapActions, mapGetters } from 'vuex'
|
||
import AccessMixin from '@/mixins/access';
|
||
import DougalGroupRepeatabilitySummary from '@/components/groups/group-repeatability-summary.vue';
|
||
import DougalGroupComparisonSummary from '@/components/groups/group-comparison-summary';
|
||
import DougalGroupMap from '@/components/groups/group-map';
|
||
|
||
export default {
|
||
name: 'Group',
|
||
|
||
mixins: [
|
||
AccessMixin
|
||
],
|
||
|
||
components: {
|
||
DougalGroupRepeatabilitySummary,
|
||
DougalGroupComparisonSummary,
|
||
DougalGroupMap
|
||
},
|
||
|
||
data () {
|
||
return {
|
||
projectHeaders: [
|
||
{
|
||
value: "baseline",
|
||
text: "Baseline"
|
||
},
|
||
{
|
||
value: "monitor",
|
||
text: "Monitor"
|
||
},
|
||
{
|
||
value: "pid",
|
||
text: "ID"
|
||
},
|
||
{
|
||
value: "name",
|
||
text: "Name"
|
||
},
|
||
{
|
||
value: "fsp",
|
||
text: "Start"
|
||
},
|
||
{
|
||
value: "lsp",
|
||
text: "Finish"
|
||
},
|
||
{
|
||
value: "lines",
|
||
text: "Preplot lines"
|
||
},
|
||
{
|
||
value: "seq_final",
|
||
text: "Num. of sequences"
|
||
},
|
||
{
|
||
value: "prod_duration",
|
||
text: "Duration"
|
||
},
|
||
{
|
||
value: "prod_distance",
|
||
text: "Distance"
|
||
},
|
||
],
|
||
|
||
mapView: false,
|
||
|
||
baseline: null,
|
||
monitor: null,
|
||
comparisons: []
|
||
}
|
||
},
|
||
|
||
computed: {
|
||
|
||
groupName () {
|
||
return this.$route.params.group;
|
||
},
|
||
|
||
group () {
|
||
return this.groups.find( i => i.group === this.groupName );
|
||
},
|
||
|
||
groupFound () {
|
||
return !!(this.loading || this.group);
|
||
},
|
||
|
||
projects () {
|
||
return this.group?.projects.toSorted((a, b) => a.pid.localeCompare(b.pid));
|
||
},
|
||
|
||
baselineIndex () {
|
||
return this.projects.indexOf(this.baseline);
|
||
},
|
||
|
||
monitors () {
|
||
if (this.baseline && this.comparisons) {
|
||
return this.comparisons
|
||
.filter( i => i.baseline_pid == this.baseline.pid )
|
||
.map( i => this.projects.find( p => p.pid == i.monitor_pid ));
|
||
} else {
|
||
return null;
|
||
}
|
||
},
|
||
|
||
comparison () {
|
||
return this.comparisons.find( row =>
|
||
row.baseline_pid == this.baseline?.pid && row.monitor_pid == this.monitor?.pid
|
||
)?.meta;
|
||
},
|
||
|
||
...mapGetters(["loading", "groups"])
|
||
},
|
||
|
||
methods: {
|
||
|
||
setBaseline (project) {
|
||
if (project === this.baseline) {
|
||
this.baseline = null;
|
||
} else {
|
||
this.baseline = project;
|
||
if (this.monitor) {
|
||
if (this.projects.indexOf(this.monitor) <= this.projects.indexOf(this.baseline)) {
|
||
this.monitor = null;
|
||
}
|
||
}
|
||
}
|
||
},
|
||
|
||
setMonitor (project) {
|
||
if (project === this.monitor) {
|
||
this.monitor = null;
|
||
} else {
|
||
this.monitor = project;
|
||
}
|
||
},
|
||
|
||
clearComparison () {
|
||
this.baseline = null;
|
||
this.monitor = null;
|
||
},
|
||
|
||
setComparison (baseline, monitor) {
|
||
this.clearComparison();
|
||
this.setBaseline(baseline);
|
||
this.setMonitor(monitor);
|
||
},
|
||
|
||
async getComparisons () {
|
||
const url = `/comparison/group/${this.$route.params.group}`;
|
||
this.comparisons = await this.api([url]);
|
||
},
|
||
|
||
// TODO Should this go in a Vuex action rather?
|
||
async refreshComparisons () {
|
||
await this.getGroups();
|
||
if (this.groupFound) {
|
||
await this.getComparisons();
|
||
}
|
||
},
|
||
|
||
/*
|
||
async getComparison () {
|
||
if (this.baseline && this.monitor) {
|
||
const url = `/comparison/group/${this.$route.params.group}/baseline/${this.baseline.pid}/monitor/${this.monitor.pid}`;
|
||
const comparison = await this.api([url]);
|
||
if (comparison) {
|
||
this.comparison = comparison;
|
||
}
|
||
}
|
||
},
|
||
*/
|
||
|
||
handleComparisons (context, {payload}) {
|
||
this.refreshComparisons();
|
||
},
|
||
|
||
registerNotificationHandlers (action = "registerHandler") {
|
||
|
||
this.$store.dispatch(action, {
|
||
table: 'comparisons',
|
||
handler: this.handleComparisons
|
||
});
|
||
|
||
},
|
||
|
||
unregisterNotificationHandlers () {
|
||
return this.registerNotificationHandlers("unregisterHandler");
|
||
},
|
||
|
||
|
||
...mapActions(["api", "getGroups", "refreshProjects"])
|
||
},
|
||
|
||
async mounted () {
|
||
this.registerNotificationHandlers();
|
||
this.refreshComparisons()
|
||
},
|
||
|
||
beforeDestroy () {
|
||
this.unregisterNotificationHandlers();
|
||
}
|
||
|
||
|
||
}
|
||
</script>
|