mirror of
https://gitlab.com/wgp/dougal/software.git
synced 2025-12-06 13:07:08 +00:00
Compare commits
53 Commits
334-add-4d
...
a8ff7f3b52
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a8ff7f3b52 | ||
|
|
15b62ff581 | ||
|
|
ade86be556 | ||
|
|
53594416a7 | ||
|
|
ff4b4a9c90 | ||
|
|
5842940d3b | ||
|
|
df6f1b2d32 | ||
|
|
c39afc1f3c | ||
|
|
a68000eac6 | ||
|
|
87aa78af00 | ||
|
|
3b9061aeae | ||
|
|
57dae4c755 | ||
|
|
b1344bebd8 | ||
|
|
3e91ccba8d | ||
|
|
fa0be9c0b7 | ||
|
|
dcbf5496f6 | ||
|
|
8007f46e37 | ||
|
|
4a7683cfd0 | ||
|
|
565a9d7e01 | ||
|
|
b07244c823 | ||
|
|
c909edc41f | ||
|
|
41ef511123 | ||
|
|
4196e9760b | ||
|
|
6b6f5ab511 | ||
|
|
7d8c78648d | ||
|
|
faf7e9c98f | ||
|
|
abf2709705 | ||
|
|
f5dfafd85a | ||
|
|
cf8b0937d9 | ||
|
|
d737f5d676 | ||
|
|
5fe19da586 | ||
|
|
0af0cf4b42 | ||
|
|
ccb8205d26 | ||
|
|
9b3fffdcfc | ||
|
|
dea1e9ee0d | ||
|
|
d45ec767ec | ||
|
|
67520ffc48 | ||
|
|
22a296ba26 | ||
|
|
f89435d80f | ||
|
|
a3f1dd490c | ||
|
|
2fcfcb4f84 | ||
|
|
b60db7e7ef | ||
|
|
4bb087fff7 | ||
|
|
15af5effc3 | ||
|
|
b5c6d04e62 | ||
|
|
571c5a8bca | ||
|
|
c45982829c | ||
|
|
f3958b37b7 | ||
|
|
58374adc68 | ||
|
|
32aea8a5ed | ||
|
|
023b65285f | ||
|
|
a320962669 | ||
|
|
0c0067b8d9 |
@@ -1,7 +1,5 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# Maximum runtime in seconds before killing an overdue instance (e.g., 10 minutes)
|
|
||||||
MAX_RUNTIME_SECONDS=$((15 * 60))
|
|
||||||
|
|
||||||
DOUGAL_ROOT=${DOUGAL_ROOT:-$(dirname "$0")/..}
|
DOUGAL_ROOT=${DOUGAL_ROOT:-$(dirname "$0")/..}
|
||||||
|
|
||||||
@@ -82,9 +80,8 @@ function run () {
|
|||||||
# DESCRIPTION=""
|
# DESCRIPTION=""
|
||||||
SERVICE="deferred_imports"
|
SERVICE="deferred_imports"
|
||||||
|
|
||||||
# Disable GitLab alerts. They're just not very practical
|
$BINDIR/send_alert.py -t "$TITLE" -s "$SERVICE" -l "critical" \
|
||||||
# $BINDIR/send_alert.py -t "$TITLE" -s "$SERVICE" -l "critical" \
|
-O "$(cat $STDOUTLOG)" -E "$(cat $STDERRLOG)"
|
||||||
# -O "$(cat $STDOUTLOG)" -E "$(cat $STDERRLOG)"
|
|
||||||
|
|
||||||
exit 2
|
exit 2
|
||||||
}
|
}
|
||||||
@@ -100,37 +97,14 @@ function cleanup () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if [[ -f $LOCKFILE ]]; then
|
if [[ -f $LOCKFILE ]]; then
|
||||||
PID=$(cat "$LOCKFILE")
|
PID=$(cat "$LOCKFILE")
|
||||||
if kill -0 "$PID" 2>/dev/null; then # Check if process is running
|
if pgrep -F "$LOCKFILE"; then
|
||||||
# Get elapsed time in D-HH:MM:SS format and convert to seconds
|
print_warning $(printf "The previous process is still running (%d)" $PID)
|
||||||
ELAPSED_STR=$(ps -p "$PID" -o etime= | tr -d '[:space:]')
|
exit 1
|
||||||
if [ -n "$ELAPSED_STR" ]; then
|
else
|
||||||
# Convert D-HH:MM:SS to seconds
|
rm "$LOCKFILE"
|
||||||
ELAPSED_SECONDS=$(echo "$ELAPSED_STR" | awk -F'[-:]' '{
|
print_warning $(printf "Previous process (%d) not found. Must have died unexpectedly" $PID)
|
||||||
seconds = 0
|
fi
|
||||||
if (NF == 4) { seconds += $1 * 86400 } # Days
|
|
||||||
if (NF >= 3) { seconds += $NF-2 * 3600 } # Hours
|
|
||||||
if (NF >= 2) { seconds += $NF-1 * 60 } # Minutes
|
|
||||||
seconds += $NF # Seconds
|
|
||||||
print seconds
|
|
||||||
}')
|
|
||||||
if [ "$ELAPSED_SECONDS" -gt "$MAX_RUNTIME_SECONDS" ]; then
|
|
||||||
# Kill the overdue process (SIGTERM; use -9 for SIGKILL if needed)
|
|
||||||
kill "$PID" 2>/dev/null
|
|
||||||
print_warning $(printf "Killed overdue process (%d) that ran for %s (%d seconds)" "$PID" "$ELAPSED_STR" "$ELAPSED_SECONDS")
|
|
||||||
rm "$LOCKFILE"
|
|
||||||
else
|
|
||||||
print_warning $(printf "Previous process is still running (%d) for %s (%d seconds)" "$PID" "$ELAPSED_STR" "$ELAPSED_SECONDS")
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
print_warning $(printf "Could not retrieve elapsed time for process (%d)" "$PID")
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
rm "$LOCKFILE"
|
|
||||||
print_warning $(printf "Previous process (%d) not found. Must have died unexpectedly" "$PID")
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "$$" > "$LOCKFILE" || {
|
echo "$$" > "$LOCKFILE" || {
|
||||||
|
|||||||
@@ -2,32 +2,8 @@
|
|||||||
|
|
||||||
const cmp = require('../lib/www/server/lib/comparisons');
|
const cmp = require('../lib/www/server/lib/comparisons');
|
||||||
|
|
||||||
async function purgeComparisons () {
|
|
||||||
const groups = await cmp.groups();
|
|
||||||
const comparisons = await cmp.getGroup();
|
|
||||||
|
|
||||||
const pids = new Set(Object.values(groups).flat().map( p => p.pid ));
|
|
||||||
const comparison_pids = new Set(comparisons.map( c => [ c.baseline_pid, c.monitor_pid ] ).flat());
|
|
||||||
|
|
||||||
for (const pid of comparison_pids) {
|
|
||||||
if (!pids.has(pid)) {
|
|
||||||
console.log(`${pid} no longer par of a group. Deleting comparisons`);
|
|
||||||
|
|
||||||
staleComps = comparisons.filter( c => c.baseline_pid == pid || c.monitor_pid == pid );
|
|
||||||
for (c of staleComps) {
|
|
||||||
console.log(`Deleting comparison ${c.baseline_pid} → ${c.monitor_pid}`);
|
|
||||||
await cmp.remove(c.baseline_pid, c.monitor_pid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
async function main () {
|
async function main () {
|
||||||
|
|
||||||
console.log("Looking for unreferenced comparisons to purge");
|
|
||||||
await purgeComparisons();
|
|
||||||
|
|
||||||
console.log("Retrieving project groups");
|
console.log("Retrieving project groups");
|
||||||
const groups = await cmp.groups();
|
const groups = await cmp.groups();
|
||||||
|
|
||||||
@@ -36,7 +12,7 @@ async function main () {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`Found ${Object.keys(groups)?.length} groups: ${Object.keys(groups).join(", ")}`);
|
console.log(`Found ${groups.length} groups: ${Object.keys(groups).join(", ")}`);
|
||||||
|
|
||||||
for (const groupName of Object.keys(groups)) {
|
for (const groupName of Object.keys(groups)) {
|
||||||
const projects = groups[groupName];
|
const projects = groups[groupName];
|
||||||
@@ -45,11 +21,6 @@ async function main () {
|
|||||||
|
|
||||||
const comparisons = await cmp.getGroup(groupName);
|
const comparisons = await cmp.getGroup(groupName);
|
||||||
|
|
||||||
if (!comparisons || !comparisons.length) {
|
|
||||||
console.log(`No comparisons found for ${groupName}`);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if there are any projects that have been modified since last comparison
|
// Check if there are any projects that have been modified since last comparison
|
||||||
// or if there are any pairs that are no longer part of the group
|
// or if there are any pairs that are no longer part of the group
|
||||||
|
|
||||||
|
|||||||
@@ -39,8 +39,7 @@ export default {
|
|||||||
default:
|
default:
|
||||||
return {
|
return {
|
||||||
editable: false,
|
editable: false,
|
||||||
displaylogo: false,
|
displaylogo: false
|
||||||
responsive: true
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -49,8 +48,7 @@ export default {
|
|||||||
const base = {
|
const base = {
|
||||||
font: {
|
font: {
|
||||||
color: this.$vuetify.theme.isDark ? "#fff" : undefined
|
color: this.$vuetify.theme.isDark ? "#fff" : undefined
|
||||||
},
|
}
|
||||||
autosize: true
|
|
||||||
};
|
};
|
||||||
|
|
||||||
switch (this.facet) {
|
switch (this.facet) {
|
||||||
@@ -276,25 +274,18 @@ export default {
|
|||||||
replot () {
|
replot () {
|
||||||
if (this.plotted) {
|
if (this.plotted) {
|
||||||
const ref = this.$refs.graph;
|
const ref = this.$refs.graph;
|
||||||
if (ref && ref.clientWidth > 0 && ref.clientHeight > 0) {
|
Plotly.relayout(ref, {
|
||||||
Plotly.relayout(ref, {
|
width: ref.clientWidth,
|
||||||
width: ref.clientWidth,
|
height: ref.clientHeight
|
||||||
height: ref.clientHeight
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted () {
|
mounted () {
|
||||||
this.$nextTick( () => {
|
this.resizeObserver = new ResizeObserver(this.replot)
|
||||||
if (this.items?.length) {
|
this.resizeObserver.observe(this.$refs.graph);
|
||||||
this.plot();
|
|
||||||
}
|
|
||||||
this.resizeObserver = new ResizeObserver(this.replot)
|
|
||||||
this.resizeObserver.observe(this.$refs.graph);
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
beforeDestroy () {
|
beforeDestroy () {
|
||||||
|
|||||||
@@ -36,8 +36,7 @@ export default {
|
|||||||
config () {
|
config () {
|
||||||
return {
|
return {
|
||||||
editable: false,
|
editable: false,
|
||||||
displaylogo: false,
|
displaylogo: false
|
||||||
responsive: true
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -54,8 +53,7 @@ export default {
|
|||||||
title: "Time (s)"
|
title: "Time (s)"
|
||||||
},
|
},
|
||||||
plot_bgcolor:"rgba(0,0,0,0)",
|
plot_bgcolor:"rgba(0,0,0,0)",
|
||||||
paper_bgcolor:"rgba(0,0,0,0)",
|
paper_bgcolor:"rgba(0,0,0,0)"
|
||||||
autosize: true
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -156,12 +154,10 @@ export default {
|
|||||||
replot () {
|
replot () {
|
||||||
if (this.plotted) {
|
if (this.plotted) {
|
||||||
const ref = this.$refs.graph;
|
const ref = this.$refs.graph;
|
||||||
if (ref && ref.clientWidth > 0 && ref.clientHeight > 0) {
|
Plotly.relayout(ref, {
|
||||||
Plotly.relayout(ref, {
|
width: ref.clientWidth,
|
||||||
width: ref.clientWidth,
|
height: ref.clientHeight
|
||||||
height: ref.clientHeight
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -194,13 +190,8 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
mounted () {
|
mounted () {
|
||||||
this.$nextTick( () => {
|
this.resizeObserver = new ResizeObserver(this.replot)
|
||||||
if (this.items?.length) {
|
this.resizeObserver.observe(this.$refs.graph);
|
||||||
this.plot();
|
|
||||||
}
|
|
||||||
this.resizeObserver = new ResizeObserver(this.replot)
|
|
||||||
this.resizeObserver.observe(this.$refs.graph);
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
beforeDestroy () {
|
beforeDestroy () {
|
||||||
|
|||||||
@@ -158,7 +158,6 @@ Vue.use(VueRouter)
|
|||||||
component: SequenceList
|
component: SequenceList
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "shotlog",
|
|
||||||
path: "sequences/:sequence",
|
path: "sequences/:sequence",
|
||||||
component: SequenceSummary
|
component: SequenceSummary
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ async function refreshEvents ({commit, dispatch, state, rootState}, [modifiedAft
|
|||||||
|
|
||||||
/** Return a subset of events from state.events
|
/** Return a subset of events from state.events
|
||||||
*/
|
*/
|
||||||
async function getEvents ({commit, dispatch, state}, [projectId, {sequence, date0, date1, sortBy, sortDesc, itemsPerPage, page, text, label, excludeLabels}]) {
|
async function getEvents ({commit, dispatch, state}, [projectId, {sequence, date0, date1, sortBy, sortDesc, itemsPerPage, page, text, label}]) {
|
||||||
let filteredEvents = [...state.events];
|
let filteredEvents = [...state.events];
|
||||||
|
|
||||||
if (sortBy) {
|
if (sortBy) {
|
||||||
@@ -114,10 +114,6 @@ async function getEvents ({commit, dispatch, state}, [projectId, {sequence, date
|
|||||||
filteredEvents = filteredEvents.filter( event => event.labels?.includes(label) );
|
filteredEvents = filteredEvents.filter( event => event.labels?.includes(label) );
|
||||||
}
|
}
|
||||||
|
|
||||||
if (excludeLabels) {
|
|
||||||
filteredEvents = filteredEvents.filter( event => !excludeLabels?.some( label => event.labels?.includes(label) ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
const count = filteredEvents.length;
|
const count = filteredEvents.length;
|
||||||
|
|
||||||
if (itemsPerPage && itemsPerPage > 0) {
|
if (itemsPerPage && itemsPerPage > 0) {
|
||||||
|
|||||||
@@ -5,22 +5,6 @@
|
|||||||
<v-card-title>
|
<v-card-title>
|
||||||
<v-toolbar flat>
|
<v-toolbar flat>
|
||||||
<v-toolbar-title>
|
<v-toolbar-title>
|
||||||
<template v-if="$route.params.sequence">
|
|
||||||
<v-btn icon small
|
|
||||||
:disabled="sequenceIndex >= (sequences.length - 1)"
|
|
||||||
:to="{name: 'logBySequence', params: { sequence: (sequences[sequences.length-1]||{}).sequence }}"
|
|
||||||
title="Go to the first sequence"
|
|
||||||
>
|
|
||||||
<v-icon dense>mdi-chevron-double-left</v-icon>
|
|
||||||
</v-btn>
|
|
||||||
<v-btn icon small
|
|
||||||
:disabled="sequenceIndex >= (sequences.length - 1)"
|
|
||||||
:to="{name: 'logBySequence', params: { sequence: (sequences[sequenceIndex+1]||{}).sequence }}"
|
|
||||||
title="Go to the previous sequence"
|
|
||||||
>
|
|
||||||
<v-icon dense>mdi-chevron-left</v-icon>
|
|
||||||
</v-btn>
|
|
||||||
</template>
|
|
||||||
<span class="d-none d-lg-inline">
|
<span class="d-none d-lg-inline">
|
||||||
{{
|
{{
|
||||||
$route.params.sequence
|
$route.params.sequence
|
||||||
@@ -47,38 +31,18 @@
|
|||||||
: ""
|
: ""
|
||||||
}}
|
}}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<template v-if="$route.params.sequence">
|
|
||||||
<v-btn icon small
|
|
||||||
:disabled="sequenceIndex==0"
|
|
||||||
:to="{name: 'logBySequence', params: { sequence: (sequences[sequenceIndex-1]||{}).sequence }}"
|
|
||||||
title="Go to the next sequence"
|
|
||||||
>
|
|
||||||
<v-icon dense>mdi-chevron-right</v-icon>
|
|
||||||
</v-btn>
|
|
||||||
<v-btn icon small class="mr-1"
|
|
||||||
:disabled="sequenceIndex==0"
|
|
||||||
:to="{name: 'logBySequence', params: { sequence: (sequences[0]||{}).sequence }}"
|
|
||||||
title="Go to the last sequence"
|
|
||||||
>
|
|
||||||
<v-icon dense>mdi-chevron-double-right</v-icon>
|
|
||||||
</v-btn>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<a v-if="$route.params.sequence"
|
|
||||||
class="mr-3"
|
|
||||||
:href="`/projects/${$route.params.project}/sequences/${$route.params.sequence}`"
|
|
||||||
title="View the shotlog for this sequence"
|
|
||||||
>
|
|
||||||
<v-icon
|
|
||||||
right
|
|
||||||
color="teal"
|
|
||||||
>mdi-format-list-numbered</v-icon>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
</v-toolbar-title>
|
</v-toolbar-title>
|
||||||
|
|
||||||
|
<a v-if="$route.params.sequence"
|
||||||
|
class="mr-3"
|
||||||
|
:href="`/projects/${$route.params.project}/sequences/${$route.params.sequence}`"
|
||||||
|
title="View the shotlog for this sequence"
|
||||||
|
>
|
||||||
|
<v-icon
|
||||||
|
right
|
||||||
|
color="teal"
|
||||||
|
>mdi-format-list-numbered</v-icon>
|
||||||
|
</a>
|
||||||
|
|
||||||
<dougal-event-edit v-if="$parent.writeaccess()"
|
<dougal-event-edit v-if="$parent.writeaccess()"
|
||||||
v-model="eventDialog"
|
v-model="eventDialog"
|
||||||
@@ -530,6 +494,17 @@ export default {
|
|||||||
rows () {
|
rows () {
|
||||||
const rows = {};
|
const rows = {};
|
||||||
this.items
|
this.items
|
||||||
|
.filter(i => {
|
||||||
|
return !this.$route.params.sequence || (this.$route.params.sequence == i.sequence)
|
||||||
|
})
|
||||||
|
.filter(i => {
|
||||||
|
for (const label of this.filterableLabels) {
|
||||||
|
if (!this.shownLabels.includes(label) && i.labels.includes(label)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
})
|
||||||
.forEach(i => {
|
.forEach(i => {
|
||||||
const key = (i.sequence && i.point) ? (i.sequence+"@"+i.point) : i.tstamp;
|
const key = (i.sequence && i.point) ? (i.sequence+"@"+i.point) : i.tstamp;
|
||||||
if (!rows[key]) {
|
if (!rows[key]) {
|
||||||
@@ -560,10 +535,6 @@ export default {
|
|||||||
.sort( (a, b) => b[1]-a[1] );
|
.sort( (a, b) => b[1]-a[1] );
|
||||||
},
|
},
|
||||||
|
|
||||||
filteredLabels () {
|
|
||||||
return this.filterableLabels.filter( label => !this.shownLabels.includes(label) );
|
|
||||||
},
|
|
||||||
|
|
||||||
presetRemarks () {
|
presetRemarks () {
|
||||||
return this.projectConfiguration?.events?.presetRemarks ?? [];
|
return this.projectConfiguration?.events?.presetRemarks ?? [];
|
||||||
},
|
},
|
||||||
@@ -576,17 +547,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
sequenceIndex () {
|
...mapGetters(['user', 'eventsLoading', 'online', 'sequence', 'line', 'point', 'position', 'timestamp', 'lineName', 'events', 'labels', 'userLabels', 'projectConfiguration']),
|
||||||
if ("sequence" in this.$route.params) {
|
|
||||||
const index = this.sequences.findIndex( i => i.sequence == this.$route.params.sequence );
|
|
||||||
if (index != -1) {
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// return undefined
|
|
||||||
},
|
|
||||||
|
|
||||||
...mapGetters(['user', 'eventsLoading', 'online', 'sequence', 'sequences', 'line', 'point', 'position', 'timestamp', 'lineName', 'events', 'labels', 'userLabels', 'projectConfiguration']),
|
|
||||||
...mapState({projectSchema: state => state.project.projectSchema})
|
...mapState({projectSchema: state => state.project.projectSchema})
|
||||||
|
|
||||||
},
|
},
|
||||||
@@ -594,7 +555,6 @@ export default {
|
|||||||
watch: {
|
watch: {
|
||||||
options: {
|
options: {
|
||||||
async handler () {
|
async handler () {
|
||||||
this.savePrefs(),
|
|
||||||
await this.fetchEvents();
|
await this.fetchEvents();
|
||||||
},
|
},
|
||||||
deep: true
|
deep: true
|
||||||
@@ -613,19 +573,12 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
filter (newVal, oldVal) {
|
filter (newVal, oldVal) {
|
||||||
this.savePrefs();
|
|
||||||
if (newVal?.toLowerCase() != oldVal?.toLowerCase()) {
|
if (newVal?.toLowerCase() != oldVal?.toLowerCase()) {
|
||||||
this.fetchEvents();
|
this.fetchEvents();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
labelSearch () {
|
labelSearch () {
|
||||||
this.savePrefs();
|
|
||||||
this.fetchEvents();
|
|
||||||
},
|
|
||||||
|
|
||||||
filteredLabels () {
|
|
||||||
this.savePrefs()
|
|
||||||
this.fetchEvents();
|
this.fetchEvents();
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -634,7 +587,7 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
user (newVal, oldVal) {
|
user (newVal, oldVal) {
|
||||||
this.loadPrefs();
|
this.itemsPerPage = Number(localStorage.getItem(`dougal/prefs/${this.user?.name}/${this.$route.params.project}/${this.$options.name}/items-per-page`)) || 25;
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
@@ -685,10 +638,8 @@ export default {
|
|||||||
|
|
||||||
async fetchEvents (opts = {}) {
|
async fetchEvents (opts = {}) {
|
||||||
const options = {
|
const options = {
|
||||||
sequence: this.$route.params.sequence,
|
|
||||||
text: this.filter,
|
text: this.filter,
|
||||||
label: this.labelSearch,
|
label: this.labelSearch,
|
||||||
excludeLabels: this.filteredLabels,
|
|
||||||
...this.options
|
...this.options
|
||||||
};
|
};
|
||||||
const res = await this.getEvents([this.$route.params.project, options]);
|
const res = await this.getEvents([this.$route.params.project, options]);
|
||||||
@@ -926,36 +877,10 @@ export default {
|
|||||||
*/
|
*/
|
||||||
},
|
},
|
||||||
|
|
||||||
getPrefsKey () {
|
|
||||||
return `dougal/prefs/${this.user?.name}/${this.$route.params.project}/Log/v1`;
|
|
||||||
},
|
|
||||||
|
|
||||||
savePrefs () {
|
|
||||||
const prefs = {
|
|
||||||
shownLabels: this.shownLabels,
|
|
||||||
labelSearch: this.labelSearch,
|
|
||||||
filter: this.filter,
|
|
||||||
options: this.options
|
|
||||||
};
|
|
||||||
localStorage.setItem(this.getPrefsKey(), JSON.stringify(prefs));
|
|
||||||
},
|
|
||||||
|
|
||||||
loadPrefs () {
|
|
||||||
const stored = localStorage.getItem(this.getPrefsKey());
|
|
||||||
if (stored) {
|
|
||||||
const prefs = JSON.parse(stored);
|
|
||||||
if (prefs.shownLabels !== undefined) this.shownLabels = prefs.shownLabels;
|
|
||||||
if (prefs.labelSearch !== undefined) this.labelSearch = prefs.labelSearch;
|
|
||||||
if (prefs.filter !== undefined) this.filter = prefs.filter;
|
|
||||||
if (prefs.options !== undefined) this.options = prefs.options;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
...mapActions(["api", "showSnack", "refreshEvents", "getEvents"])
|
...mapActions(["api", "showSnack", "refreshEvents", "getEvents"])
|
||||||
},
|
},
|
||||||
|
|
||||||
async mounted () {
|
async mounted () {
|
||||||
this.loadPrefs();
|
|
||||||
this.fetchEvents();
|
this.fetchEvents();
|
||||||
|
|
||||||
window.addEventListener('keyup', this.handleKeyboardEvent);
|
window.addEventListener('keyup', this.handleKeyboardEvent);
|
||||||
|
|||||||
@@ -6,42 +6,8 @@
|
|||||||
<v-progress-linear indeterminate v-if="loading"></v-progress-linear>
|
<v-progress-linear indeterminate v-if="loading"></v-progress-linear>
|
||||||
<v-toolbar flat>
|
<v-toolbar flat>
|
||||||
<v-toolbar-title>
|
<v-toolbar-title>
|
||||||
<template v-if="$route.params.sequence">
|
|
||||||
<v-btn icon small
|
|
||||||
:disabled="sequenceIndex >= (sequences.length - 1)"
|
|
||||||
:to="{name: 'shotlog', params: { sequence: (sequences[sequences.length-1]||{}).sequence }}"
|
|
||||||
title="Go to the first sequence"
|
|
||||||
>
|
|
||||||
<v-icon dense>mdi-chevron-double-left</v-icon>
|
|
||||||
</v-btn>
|
|
||||||
<v-btn icon small
|
|
||||||
:disabled="sequenceIndex >= (sequences.length - 1)"
|
|
||||||
:to="{name: 'shotlog', params: { sequence: (sequences[sequenceIndex+1]||{}).sequence }}"
|
|
||||||
title="Go to the previous sequence"
|
|
||||||
>
|
|
||||||
<v-icon dense>mdi-chevron-left</v-icon>
|
|
||||||
</v-btn>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
Sequence {{sequenceNumber}}
|
Sequence {{sequenceNumber}}
|
||||||
<small :class="statusColour" v-if="sequence">({{sequence.status}})</small>
|
<small :class="statusColour" v-if="sequence">({{sequence.status}})</small>
|
||||||
|
|
||||||
<template v-if="$route.params.sequence">
|
|
||||||
<v-btn icon small
|
|
||||||
:disabled="sequenceIndex==0"
|
|
||||||
:to="{name: 'shotlog', params: { sequence: (sequences[sequenceIndex-1]||{}).sequence }}"
|
|
||||||
title="Go to the next sequence"
|
|
||||||
>
|
|
||||||
<v-icon dense>mdi-chevron-right</v-icon>
|
|
||||||
</v-btn>
|
|
||||||
<v-btn icon small class="mr-1"
|
|
||||||
:disabled="sequenceIndex==0"
|
|
||||||
:to="{name: 'shotlog', params: { sequence: (sequences[0]||{}).sequence }}"
|
|
||||||
title="Go to the last sequence"
|
|
||||||
>
|
|
||||||
<v-icon dense>mdi-chevron-double-right</v-icon>
|
|
||||||
</v-btn>
|
|
||||||
</template>
|
|
||||||
</v-toolbar-title>
|
</v-toolbar-title>
|
||||||
|
|
||||||
<a v-if="$route.params.sequence"
|
<a v-if="$route.params.sequence"
|
||||||
@@ -386,16 +352,6 @@ export default {
|
|||||||
return this.sequences.find(i => i.sequence == this.sequenceNumber);
|
return this.sequences.find(i => i.sequence == this.sequenceNumber);
|
||||||
},
|
},
|
||||||
|
|
||||||
sequenceIndex () {
|
|
||||||
if ("sequence" in this.$route.params) {
|
|
||||||
const index = this.sequences.findIndex( i => i.sequence == this.$route.params.sequence );
|
|
||||||
if (index != -1) {
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// return undefined
|
|
||||||
},
|
|
||||||
|
|
||||||
remarks () {
|
remarks () {
|
||||||
return this.sequence?.remarks || "Nil.";
|
return this.sequence?.remarks || "Nil.";
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -330,80 +330,44 @@ async function saveGroup (group, opts = {}) {
|
|||||||
|
|
||||||
async function getGroup (groupName, opts = {}) {
|
async function getGroup (groupName, opts = {}) {
|
||||||
|
|
||||||
|
const group = (await groups())?.[groupName]?.map( i => i.pid)?.sort();
|
||||||
|
|
||||||
|
if (!group?.length) return;
|
||||||
|
|
||||||
const client = await pool.connect();
|
const client = await pool.connect();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
if (groupName) {
|
const pairs = combinations(group, 2);
|
||||||
|
const flatValues = pairs.flat();
|
||||||
|
const placeholders = [];
|
||||||
|
for (let i = 0; i < pairs.length; i++) {
|
||||||
|
placeholders.push(`($${i * 2 + 1}, $${i * 2 + 2})`);
|
||||||
|
}
|
||||||
|
const inClause = placeholders.join(',');
|
||||||
|
const selectFields = opts.returnData ? 'data, meta' : 'meta';
|
||||||
|
|
||||||
const group = (await groups())?.[groupName]?.map( i => i.pid)?.sort();
|
const text = `
|
||||||
|
SELECT baseline_pid, monitor_pid, ${selectFields}
|
||||||
|
FROM comparisons.comparisons
|
||||||
|
WHERE type = 'geometric_difference'
|
||||||
|
AND (baseline_pid, monitor_pid) IN (VALUES ${inClause})
|
||||||
|
ORDER BY baseline_pid, monitor_pid
|
||||||
|
`;
|
||||||
|
|
||||||
if (!group?.length || group?.length < 2) return;
|
const res = await client.query(text, flatValues);
|
||||||
|
if (!res.rows.length) {
|
||||||
|
console.log("Comparison not found in database");
|
||||||
const pairs = combinations(group, 2);
|
return;
|
||||||
const flatValues = pairs.flat();
|
}
|
||||||
const placeholders = [];
|
|
||||||
for (let i = 0; i < pairs.length; i++) {
|
|
||||||
placeholders.push(`($${i * 2 + 1}, $${i * 2 + 2})`);
|
|
||||||
}
|
|
||||||
const inClause = placeholders.join(',');
|
|
||||||
const selectFields = opts.returnData ? 'data, meta' : 'meta';
|
|
||||||
|
|
||||||
const text = `
|
|
||||||
SELECT baseline_pid, monitor_pid, ${selectFields}
|
|
||||||
FROM comparisons.comparisons
|
|
||||||
WHERE type = 'geometric_difference'
|
|
||||||
AND (baseline_pid, monitor_pid) IN (VALUES ${inClause})
|
|
||||||
ORDER BY baseline_pid, monitor_pid
|
|
||||||
`;
|
|
||||||
|
|
||||||
if (!placeholders) {
|
|
||||||
console.log("No pairs found in group");
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
const res = await client.query(text, flatValues);
|
|
||||||
if (!res.rows.length) {
|
|
||||||
console.log("Comparison not found in database");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opts.returnData) {
|
|
||||||
return res.rows.map( row => ({
|
|
||||||
...row,
|
|
||||||
data: DougalBinaryBundle.clone(row.data),
|
|
||||||
}));
|
|
||||||
} else {
|
|
||||||
return res.rows;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (opts.returnData) {
|
||||||
|
return res.rows.map( row => ({
|
||||||
|
...row,
|
||||||
|
data: DougalBinaryBundle.clone(row.data),
|
||||||
|
}));
|
||||||
} else {
|
} else {
|
||||||
|
return res.rows;
|
||||||
const selectFields = opts.returnData ? 'data, meta' : 'meta';
|
|
||||||
|
|
||||||
const text = `
|
|
||||||
SELECT baseline_pid, monitor_pid, ${selectFields}
|
|
||||||
FROM comparisons.comparisons
|
|
||||||
WHERE type = 'geometric_difference'
|
|
||||||
ORDER BY baseline_pid, monitor_pid
|
|
||||||
`;
|
|
||||||
|
|
||||||
const res = await client.query(text);
|
|
||||||
if (!res.rows.length) {
|
|
||||||
console.log("Comparison not found in database");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opts.returnData) {
|
|
||||||
return res.rows.map( row => ({
|
|
||||||
...row,
|
|
||||||
data: DougalBinaryBundle.clone(row.data),
|
|
||||||
}));
|
|
||||||
} else {
|
|
||||||
return res.rows;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
|
|||||||
Reference in New Issue
Block a user