0
0
Fork 0

feat: add useStateQuery to FetchData and ArrayData

This commit is contained in:
Alex Moreno 2024-09-12 12:45:36 +02:00
parent 856d551503
commit 59f812e6d7
5 changed files with 59 additions and 8 deletions

View File

@ -1,6 +1,7 @@
<script setup>
import { onMounted } from 'vue';
import axios from 'axios';
import { useStateQuery } from 'src/composables/useStateQuery';
const $props = defineProps({
autoLoad: {
@ -32,7 +33,7 @@ const $props = defineProps({
default: null,
},
});
const stateQuery = useStateQuery();
const emit = defineEmits(['onFetch']);
defineExpose({ fetch });
@ -43,6 +44,7 @@ onMounted(async () => {
});
async function fetch(fetchFilter = {}) {
const hash = stateQuery.add();
try {
const filter = { ...fetchFilter, ...$props.filter }; // eslint-disable-line vue/no-dupe-keys
if ($props.where && !fetchFilter.where) filter.where = $props.where;
@ -55,8 +57,8 @@ async function fetch(fetchFilter = {}) {
emit('onFetch', data);
return data;
} catch (e) {
//
} finally {
stateQuery.remove(hash);
}
}
</script>

View File

@ -3,6 +3,7 @@ import { onMounted, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import { useState } from 'src/composables/useState';
import { useStateStore } from 'stores/useStateStore';
import { useStateQuery } from 'src/composables/useStateQuery';
import { useQuasar } from 'quasar';
import PinnedModules from './PinnedModules.vue';
import UserPanel from 'components/UserPanel.vue';
@ -12,6 +13,7 @@ import VnAvatar from './ui/VnAvatar.vue';
const { t } = useI18n();
const stateStore = useStateStore();
const quasar = useQuasar();
const stateQuery = useStateQuery();
const state = useState();
const user = state.getUser();
const appName = 'Lilium';
@ -50,6 +52,14 @@ const pinnedModulesRef = ref();
</QBtn>
</RouterLink>
<VnBreadcrumbs v-if="$q.screen.gt.sm" />
<QSpinner
color="primary"
class="q-ml-md"
:class="{
'no-visible': !stateQuery.isLoading().value,
}"
size="xs"
/>
<QSpace />
<div id="searchbar" class="searchbar"></div>
<QSpace />
@ -104,6 +114,9 @@ const pinnedModulesRef = ref();
.q-header {
background-color: var(--vn-section-color);
}
.no-visible {
visibility: hidden;
}
</style>
<i18n>
en:

View File

@ -3,8 +3,10 @@ import { useRouter, useRoute } from 'vue-router';
import axios from 'axios';
import { useArrayDataStore } from 'stores/useArrayDataStore';
import { buildFilter } from 'filters/filterPanel';
import { useStateQuery } from 'src/composables/useStateQuery';
const arrayDataStore = useArrayDataStore();
const stateQuery = useStateQuery();
export function useArrayData(key = useRoute().meta.moduleName, userOptions) {
if (!key) throw new Error('ArrayData: A key is required to use this composable');
@ -99,11 +101,18 @@ export function useArrayData(key = useRoute().meta.moduleName, userOptions) {
params.filter = JSON.stringify(params.filter);
store.currentFilter = params;
store.isLoading = true;
const response = await axios.get(store.url, {
const hash = stateQuery.add();
let response;
try {
response = await axios.get(store.url, {
signal: canceller.signal,
params,
});
} finally {
stateQuery.remove(hash);
}
const { limit } = filter;
store.hasMoreData = limit && response.data.length >= limit;

View File

@ -0,0 +1,27 @@
import { ref, computed } from 'vue';
const queries = ref(new Set());
export function useStateQuery() {
function add() {
const min = 100000;
const max = 999999;
const hash = String(Math.floor(Math.random() * (max - min + 1)) + min);
queries.value.add(hash);
return hash;
}
function isLoading() {
return computed(() => queries.value.size);
}
function remove(hash) {
queries.value.delete(hash);
}
return {
add,
isLoading,
remove,
};
}

View File

@ -12,7 +12,7 @@ import ItemListFilter from '../ItemListFilter.vue';
search-data-key="ItemList"
:searchbar-props="{
url: 'Items/filter',
label: 'searchbar.labelr',
label: 'searchbar.label',
info: 'searchbar.info',
}"
/>