Skip to content

Commit a3fe397

Browse files
committed
Removed auto-refresh from store
Added throttle so not too many calls to refresh happen in succession. Updated the UI to simplify auto refresh
1 parent 37c96b1 commit a3fe397

File tree

5 files changed

+96
-65
lines changed

5 files changed

+96
-65
lines changed

src/Frontend/package-lock.json

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Frontend/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
"codemirror": "^6.0.1",
3131
"hex-to-css-filter": "^6.0.0",
3232
"lodash.debounce": "^4.0.8",
33+
"lodash.throttle": "^4.0.8",
3334
"lossless-json": "^4.0.2",
3435
"memoize-one": "^6.0.0",
3536
"moment": "^2.30.1",
Lines changed: 58 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,86 +1,89 @@
11
<script setup lang="ts">
2-
import { ref } from "vue";
3-
import OnOffSwitch from "./OnOffSwitch.vue";
2+
import { ref, watch } from "vue";
3+
import ListFilterSelector from "@/components/audit/ListFilterSelector.vue";
44
5-
const props = defineProps<{
6-
id: string;
7-
initialTimeout?: number;
8-
onManualRefresh: () => void;
9-
}>();
5+
const props = defineProps<{ isLoading: boolean }>();
6+
const model = defineModel<number | null>({ required: true });
7+
const emit = defineEmits<{ (e: "manualRefresh"): Promise<void> }>();
8+
const autoRefreshOptionsText = ["Off", "Every 5 seconds", "Every 15 seconds", "Every 30 seconds"];
9+
let selectValue = "Off";
1010
11-
const emit = defineEmits<{ change: [newValue: number | null]; manualRefresh: [] }>();
12-
13-
const autoRefresh = ref(props.initialTimeout != null);
14-
const refreshTimeout = ref(props.initialTimeout ?? 5);
15-
16-
function toggleRefresh() {
17-
autoRefresh.value = !autoRefresh.value;
18-
updateTimeout();
11+
if (model.value === 5000) {
12+
selectValue = "Every 5 seconds";
1913
}
20-
21-
function updateTimeout() {
22-
validateTimeout();
23-
emit("change", autoRefresh.value ? refreshTimeout.value * 1000 : null);
14+
if (model.value === 15000) {
15+
selectValue = "Every 15 seconds";
2416
}
17+
if (model.value === 30000) {
18+
selectValue = "Every 30 seconds";
19+
}
20+
21+
const selectedRefresh = ref<string>(selectValue);
22+
23+
watch(selectedRefresh, (newValue) => {
24+
if (newValue === autoRefreshOptionsText[0]) {
25+
model.value = null;
26+
}
27+
if (newValue === autoRefreshOptionsText[1]) {
28+
model.value = 5000;
29+
}
30+
if (newValue === autoRefreshOptionsText[2]) {
31+
model.value = 15000;
32+
}
33+
if (newValue === autoRefreshOptionsText[3]) {
34+
model.value = 30000;
35+
}
36+
});
2537
26-
function validateTimeout() {
27-
refreshTimeout.value = Math.max(1, Math.min(600, refreshTimeout.value));
38+
async function refresh() {
39+
await emit("manualRefresh");
2840
}
2941
</script>
3042

3143
<template>
3244
<div class="refresh-config">
33-
<button class="fa" title="refresh" @click="() => emit('manualRefresh')">
34-
<i class="fa fa-lg fa-refresh" />
35-
</button>
36-
<span>|</span>
37-
<label>Auto-Refresh:</label>
38-
<div>
39-
<OnOffSwitch :id="id" @toggle="toggleRefresh" :value="autoRefresh" />
45+
<button class="btn btn-sm" title="refresh" @click="refresh"><i class="fa fa-refresh" :class="{ spinning: props.isLoading }" /> Refresh List</button>
46+
<div class="filter">
47+
<div class="filter-label">Auto-Refresh:</div>
48+
<div class="filter-component">
49+
<ListFilterSelector :items="autoRefreshOptionsText" v-model="selectedRefresh" item-name="result" :can-clear="false" :show-clear="false" :show-filter="false" />
50+
</div>
4051
</div>
41-
<input type="number" v-model="refreshTimeout" min="1" max="600" v-on:change="updateTimeout" />
42-
<span class="unit">s</span>
4352
</div>
4453
</template>
4554

4655
<style scoped>
4756
.refresh-config {
4857
display: flex;
4958
align-items: center;
50-
gap: 0.5em;
59+
gap: 1em;
60+
margin-bottom: 0.5em;
5161
}
5262
53-
.refresh-config .unit {
54-
margin-left: -0.45em;
55-
}
56-
57-
.refresh-config label {
58-
margin: 0;
59-
}
60-
61-
.refresh-config input {
62-
width: 3.5em;
63+
.filter {
64+
display: flex;
65+
align-items: center;
6366
}
6467
65-
.refresh-config button {
66-
background: none;
67-
border: none;
68-
width: 2em;
68+
.filter-label {
69+
font-weight: bold;
6970
}
7071
71-
.refresh-config button .fa {
72-
transition: all 0.15s ease-in-out;
73-
transition: rotate 0.05s ease-in-out;
74-
transform-origin: center;
72+
@keyframes spin {
73+
from {
74+
transform: rotate(0deg);
75+
}
76+
to {
77+
transform: rotate(360deg);
78+
}
7579
}
7680
77-
.refresh-config button:hover .fa {
78-
color: #00a3c4;
79-
transform: scale(1.1);
81+
.fa-refresh {
82+
display: inline-block;
8083
}
8184
82-
.refresh-config button:active .fa {
83-
transform: rotate(25deg);
84-
text-shadow: #929e9e 0.25px 0.25px;
85+
/* You can add this class dynamically when needed */
86+
.fa-refresh.spinning {
87+
animation: spin 1s linear infinite;
8588
}
8689
</style>

src/Frontend/src/components/audit/AuditList.vue

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,33 @@ import ResultsCount from "@/components/ResultsCount.vue";
88
import { dotNetTimespanToMilliseconds, formatDotNetTimespan } from "@/composables/formatUtils.ts";
99
import "@vuepic/vue-datepicker/dist/main.css";
1010
import FiltersPanel from "@/components/audit/FiltersPanel.vue";
11-
import { onBeforeMount, watch } from "vue";
11+
import { onBeforeMount, onUnmounted, ref, watch } from "vue";
1212
import RefreshConfig from "../RefreshConfig.vue";
13+
import useAutoRefresh from "@/composables/autoRefresh.ts";
14+
import throttle from "lodash/throttle";
1315
1416
const store = useAuditStore();
1517
const { messages, totalCount, sortBy, messageFilterString, selectedEndpointName, itemsPerPage, dateRange } = storeToRefs(store);
1618
const route = useRoute();
1719
const router = useRouter();
20+
const autoRefreshValue = ref<number | null>(null);
21+
const isLoading = ref(false);
22+
23+
const dataRetriever = useAutoRefresh(
24+
throttle(async () => {
25+
isLoading.value = true;
26+
try {
27+
await store.refresh();
28+
} finally {
29+
isLoading.value = false;
30+
}
31+
}, 2000),
32+
null
33+
);
34+
35+
onUnmounted(() => {
36+
dataRetriever.updateTimeout(null);
37+
});
1838
1939
function statusToName(messageStatus: MessageStatus) {
2040
switch (messageStatus) {
@@ -78,7 +98,7 @@ onBeforeMount(() => {
7898
7999
//without setTimeout, this happens before the store is properly initialised, and therefore the query route values aren't applied to the refresh
80100
//TODO: is there a better way to achieve this?
81-
setTimeout(async () => await Promise.all([store.refresh(), store.loadEndpoints()]), 0);
101+
setTimeout(async () => await Promise.all([dataRetriever.executeAndResetTimer(), store.loadEndpoints()]), 0);
82102
83103
firstLoad = false;
84104
});
@@ -87,7 +107,7 @@ watch(
87107
() => router.currentRoute.value.query,
88108
async () => {
89109
setQuery();
90-
await store.refresh();
110+
await dataRetriever.executeAndResetTimer();
91111
},
92112
{ deep: true }
93113
);
@@ -113,7 +133,7 @@ const watchHandle = watch([() => route.query, itemsPerPage, sortBy, messageFilte
113133
},
114134
});
115135
116-
await store.refresh();
136+
await dataRetriever.executeAndResetTimer();
117137
});
118138
119139
function setQuery() {
@@ -132,12 +152,14 @@ function setQuery() {
132152
133153
watchHandle.resume();
134154
}
155+
156+
watch(autoRefreshValue, (newValue) => dataRetriever.updateTimeout(newValue));
135157
</script>
136158

137159
<template>
138160
<div>
139161
<div class="header">
140-
<RefreshConfig id="auditListRefresh" @change="store.updateRefreshTimer" @manual-refresh="store.refresh" />
162+
<RefreshConfig v-model="autoRefreshValue" :isLoading="isLoading" @manual-refresh="dataRetriever.executeAndResetTimer()" />
141163
<div class="row">
142164
<FiltersPanel />
143165
</div>

src/Frontend/src/stores/AuditStore.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import { ref } from "vue";
44
import type { SortInfo } from "@/components/SortInfo";
55
import Message from "@/resources/Message";
66
import { EndpointsView } from "@/resources/EndpointView.ts";
7-
import useAutoRefresh from "@/composables/autoRefresh";
87

98
export type DateRange = [fromDate: Date, toDate: Date] | [];
109

@@ -39,7 +38,7 @@ export const useAuditStore = defineStore("AuditStore", () => {
3938
}
4039
}
4140

42-
const dataRetriever = useAutoRefresh(async () => {
41+
async function refresh() {
4342
try {
4443
const [fromDate, toDate] = dateRange.value;
4544
const from = fromDate?.toISOString() ?? "";
@@ -53,11 +52,10 @@ export const useAuditStore = defineStore("AuditStore", () => {
5352
messages.value = [];
5453
throw e;
5554
}
56-
}, null);
55+
}
5756

5857
return {
59-
refresh: dataRetriever.executeAndResetTimer,
60-
updateRefreshTimer: dataRetriever.updateTimeout,
58+
refresh,
6159
loadEndpoints,
6260
sortBy: sortByInstances,
6361
messages,

0 commit comments

Comments
 (0)