Skip to content

Commit d6fc1da

Browse files
committed
refactor(frontend): extract generic entity detail loading from IP view
Splits IP view into a generic template usable for any entity detail (data loading, history selection, URL synchronization,...) and IP-specific charts. The template will be reused for IP subnet view.
1 parent b4e56fa commit d6fc1da

File tree

2 files changed

+316
-279
lines changed

2 files changed

+316
-279
lines changed
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
<script setup>
2+
import { computed, inject, onMounted, ref } from 'vue'
3+
4+
import dayjs from 'dayjs'
5+
import utc from 'dayjs/plugin/utc'
6+
dayjs.extend(utc)
7+
8+
import SnapshotsTimePickerUrlSync from '@/components/SnapshotsTimePickerUrlSync.vue'
9+
10+
const getData = inject('getData')
11+
12+
const props = defineProps({
13+
etype: {
14+
type: String,
15+
required: true,
16+
},
17+
eid: {
18+
type: String,
19+
required: true,
20+
},
21+
})
22+
23+
const empty = ref(false)
24+
const loaded = ref(false)
25+
const timePickerState = ref({
26+
from: null,
27+
to: null,
28+
picked: null,
29+
latest: null,
30+
range: null,
31+
resampleUnitCount: null,
32+
resampleUnit: null,
33+
})
34+
35+
const masterRecord = ref({})
36+
const snapshots = ref([])
37+
38+
// Picked snapshot is either:
39+
// - latest one if `timePickerState.latest == true`
40+
// - the last one before midpoint of the selected interval otherwise
41+
// (midpoint is `timePickerState.picked`)
42+
const pickedSnapshot = computed(() => {
43+
if (snapshots.value.length > 0) {
44+
if (timePickerState.value.latest) {
45+
// Select last (latest) one
46+
return snapshots.value[snapshots.value.length - 1]
47+
} else {
48+
// Find "midpoint"
49+
let midpointSnapshot = null
50+
let minTsDiff = Infinity
51+
for (let i = 0; i < snapshots.value.length; i++) {
52+
let snapshotTs = dayjs(snapshots.value[i]._time_created).millisecond(0).second(0)
53+
let tsDiff = dayjs(timePickerState.value.picked).diff(snapshotTs)
54+
if (tsDiff >= 0 && tsDiff < minTsDiff) {
55+
minTsDiff = tsDiff
56+
midpointSnapshot = snapshots.value[i]
57+
}
58+
}
59+
return midpointSnapshot
60+
}
61+
} else {
62+
return null
63+
}
64+
})
65+
66+
// Shortcut for picked snapshot timestamp
67+
const pickedSnapshotTs = computed(() => {
68+
return dayjs.utc(pickedSnapshot.value?._time_created).local()
69+
})
70+
71+
/**
72+
* Loads data
73+
*/
74+
async function load() {
75+
const data = await getData(`/entity/${props.etype}/${props.eid}`, {
76+
params: {
77+
date_from: timePickerState.value.from,
78+
date_to: timePickerState.value.to,
79+
},
80+
})
81+
82+
masterRecord.value = data.master_record
83+
snapshots.value = data.snapshots
84+
empty.value = data.empty
85+
}
86+
87+
/**
88+
* Hook to update `timePickerState` value and reload data
89+
*/
90+
async function updateTimePickerState(newTimePickerState) {
91+
timePickerState.value = newTimePickerState
92+
await load()
93+
}
94+
95+
onMounted(async () => {
96+
await load()
97+
loaded.value = true
98+
})
99+
</script>
100+
101+
<template>
102+
<main class="py-4">
103+
<div class="container">
104+
<div class="row mb-5">
105+
<div class="col col-lg-7 title">
106+
<slot
107+
name="header"
108+
:master-record="masterRecord"
109+
:snapshots="snapshots"
110+
:picked-snapshot="pickedSnapshot"
111+
:picked-snapshot-ts="pickedSnapshotTs"
112+
:time-picker-state="timePickerState"
113+
></slot>
114+
</div>
115+
<div class="col col-lg-5">
116+
<SnapshotsTimePickerUrlSync @update:timePickerState="updateTimePickerState" />
117+
</div>
118+
</div>
119+
120+
<div v-if="empty" class="alert alert-info">No data for selected datetime in DP³</div>
121+
<div v-else-if="loaded">
122+
<slot
123+
:master-record="masterRecord"
124+
:snapshots="snapshots"
125+
:picked-snapshot="pickedSnapshot"
126+
:picked-snapshot-ts="pickedSnapshotTs"
127+
:time-picker-state="timePickerState"
128+
></slot>
129+
</div>
130+
<div v-else class="spinner-border"></div>
131+
</div>
132+
</main>
133+
</template>

0 commit comments

Comments
 (0)