diff --git a/frontend/vue/components/Dashboard.vue b/frontend/vue/components/Dashboard.vue index 1b9425feb..16c8896c2 100644 --- a/frontend/vue/components/Dashboard.vue +++ b/frontend/vue/components/Dashboard.vue @@ -109,7 +109,7 @@ variant="outline-light" size="sm" class="py-2" - @click="toggleCharts" + @click="chartsVisible = !chartsVisible" > {{ langShowHideCharts @@ -321,107 +321,77 @@ - diff --git a/frontend/vue/functions/syncOnce.js b/frontend/vue/functions/syncOnce.js new file mode 100644 index 000000000..762e2250b --- /dev/null +++ b/frontend/vue/functions/syncOnce.js @@ -0,0 +1,18 @@ +import {resolveRef, watchOnce} from "@vueuse/core"; +import {ref} from "vue"; + +/** + * Creates a ref that syncs with its "source" value only once. + * Useful for, for example, showing a loading value on initial load, but not on + * subsequent refreshes. + */ +export default function syncOnce(sourceMaybeRef) { + const sourceRef = resolveRef(sourceMaybeRef); + + const newRef = ref(sourceRef.value); + watchOnce(sourceRef, (newVal) => { + newRef.value = newVal; + }); + + return newRef; +} diff --git a/frontend/vue/functions/useRefreshableAsyncState.js b/frontend/vue/functions/useRefreshableAsyncState.js new file mode 100644 index 000000000..1ca58e103 --- /dev/null +++ b/frontend/vue/functions/useRefreshableAsyncState.js @@ -0,0 +1,32 @@ +import {useAsyncState} from "@vueuse/core"; +import syncOnce from "~/functions/syncOnce"; + +/** + * Just like useAsyncState, except with settings changed: + * - Does not reset to initial state after every reload + * - Only sets the "loading" ref to true on the initial load, not refreshes + * + * @see useAsyncState + */ +export default function useRefreshableAsyncState( + promise, + initialState, + options = {} +) { + const {state, isLoading: allIsLoading, execute} = useAsyncState( + promise, + initialState, + { + resetOnExecute: false, + ...options + } + ); + + const isLoading = syncOnce(allIsLoading); + + return { + state, + isLoading, + execute + }; +}