salix-front/src/composables/useArrayData.js

236 lines
6.8 KiB
JavaScript
Raw Normal View History

2023-03-01 15:20:28 +00:00
import { onMounted, ref, computed } from 'vue';
2023-01-14 12:48:57 +00:00
import { useRouter, useRoute } from 'vue-router';
2023-01-05 13:57:47 +00:00
import axios from 'axios';
import { useArrayDataStore } from 'stores/useArrayDataStore';
import { buildFilter } from 'filters/filterPanel';
2023-01-05 13:57:47 +00:00
const arrayDataStore = useArrayDataStore();
export function useArrayData(key, userOptions) {
if (!key) throw new Error('ArrayData: A key is required to use this composable');
2023-01-10 13:58:24 +00:00
if (!arrayDataStore.get(key)) {
arrayDataStore.set(key);
}
2023-01-05 13:57:47 +00:00
2023-01-10 13:58:24 +00:00
const store = arrayDataStore.get(key);
2023-02-14 13:59:39 +00:00
const hasMoreData = ref(false);
2023-01-14 12:48:57 +00:00
const router = useRouter();
const route = useRoute();
2023-02-23 14:01:40 +00:00
let canceller = null;
2023-01-14 12:48:57 +00:00
2023-01-10 13:58:24 +00:00
const page = ref(1);
2023-01-05 13:57:47 +00:00
onMounted(() => {
setOptions();
2023-03-13 09:07:52 +00:00
const query = route.query;
if (query.params) {
store.userParams = JSON.parse(query.params);
}
});
2023-11-23 14:50:42 +00:00
if (key && userOptions) {
setOptions();
}
2023-03-13 09:07:52 +00:00
function setOptions() {
2023-03-21 08:49:47 +00:00
const allowedOptions = [
'url',
'filter',
'where',
'order',
'limit',
'skip',
'userParams',
2023-09-27 11:41:50 +00:00
'userFilter',
'exprBuilder',
2023-03-21 08:49:47 +00:00
];
if (typeof userOptions === 'object') {
2023-03-13 09:07:52 +00:00
for (const option in userOptions) {
2023-11-17 13:06:43 +00:00
const isEmpty = userOptions[option] == null || userOptions[option] === '';
2023-03-21 08:49:47 +00:00
if (isEmpty || !allowedOptions.includes(option)) continue;
2023-03-13 09:07:52 +00:00
if (Object.prototype.hasOwnProperty.call(store, option)) {
store[option] = userOptions[option];
}
}
}
}
async function fetch({ append = false, updateRouter = true }) {
2023-01-14 12:48:57 +00:00
if (!store.url) return;
2023-01-10 13:58:24 +00:00
2023-02-23 14:01:40 +00:00
cancelRequest();
canceller = new AbortController();
2023-01-14 12:48:57 +00:00
const filter = {
order: store.order,
limit: store.limit,
skip: store.skip,
2023-01-05 13:57:47 +00:00
};
let exprFilter;
let userParams = { ...store.userParams };
if (store?.exprBuilder) {
const where = buildFilter(userParams, (param, value) => {
const res = store.exprBuilder(param, value);
if (res) delete userParams[param];
return res;
});
exprFilter = where ? { where } : null;
}
2023-01-10 13:58:24 +00:00
Object.assign(filter, store.userFilter, exprFilter);
Object.assign(store.filter, filter);
2023-01-17 13:57:12 +00:00
const params = {
filter: JSON.stringify(store.filter),
2023-01-17 13:57:12 +00:00
};
Object.assign(params, userParams);
2023-01-17 13:57:12 +00:00
2023-09-27 11:41:50 +00:00
store.isLoading = true;
store.currentFilter = params;
2023-02-23 14:01:40 +00:00
const response = await axios.get(store.url, {
signal: canceller.signal,
params,
});
2023-01-14 12:48:57 +00:00
const { limit } = filter;
2023-01-05 13:57:47 +00:00
2024-01-16 10:24:28 +00:00
/*if (Object.keys(store.userParams).length > 0) {
hasMoreData.value = true;
} else if(store.userParamsChanged){
hasMoreData.value = false;
2024-01-16 07:40:03 +00:00
}
2024-01-16 10:24:28 +00:00
else */hasMoreData.value = response.data.length === limit;
// if (store.pagination) {
// console.error('Before-ArrayData', store.pagination, hasMoreData.value)
// hasMoreData.value = true;
// console.error('After-ArrayData', store.pagination, hasMoreData.value)
// }
if (append) {
2023-03-01 15:20:28 +00:00
if (!store.data) store.data = [];
2023-01-10 13:58:24 +00:00
for (const row of response.data) store.data.push(row);
} else {
2023-01-10 13:58:24 +00:00
store.data = response.data;
updateRouter && updateStateParams();
2023-01-27 08:43:10 +00:00
}
2023-02-23 14:01:40 +00:00
2023-09-27 11:41:50 +00:00
store.isLoading = false;
2023-03-21 08:49:47 +00:00
2023-02-23 14:01:40 +00:00
canceller = null;
2023-11-23 14:50:42 +00:00
return response;
2023-01-14 12:48:57 +00:00
}
2023-03-01 15:20:28 +00:00
function destroy() {
2023-02-24 10:04:02 +00:00
if (arrayDataStore.get(key)) {
arrayDataStore.clear(key);
}
}
2023-02-23 14:01:40 +00:00
function cancelRequest() {
if (canceller) {
canceller.abort();
canceller = null;
}
}
2023-01-14 12:48:57 +00:00
2023-02-15 14:51:31 +00:00
async function applyFilter({ filter, params }) {
2023-01-14 12:48:57 +00:00
if (filter) store.userFilter = filter;
2023-12-15 13:23:57 +00:00
store.filter = {};
2023-02-09 06:26:08 +00:00
if (params) store.userParams = Object.assign({}, params);
2023-01-10 13:58:24 +00:00
await fetch({ append: false });
}
2023-01-05 13:57:47 +00:00
2023-02-15 14:51:31 +00:00
async function addFilter({ filter, params }) {
if (filter) store.userFilter = Object.assign(store.userFilter, filter);
let userParams = Object.assign({}, store.userParams, params);
userParams = sanitizerParams(userParams, store?.exprBuilder);
store.userParams = userParams;
2024-01-16 06:24:41 +00:00
store.skip = 0;
2024-01-16 07:40:03 +00:00
store.filter.skip = 0;
await fetch({ append: false, loadMore: true });
return { filter, params };
}
2024-01-16 06:24:41 +00:00
async function removeFilter({ filter, params }) {
if (filter) store.userFilter = Object.assign(store.userFilter, filter);
let userParams = Object.assign({}, store.userParams, params);
userParams = sanitizerParams(userParams, store?.exprBuilder);
store.userParams = userParams;
store.skip = 0;
await loadMore({ append: false });
return { filter, params };
}
2023-12-13 13:19:42 +00:00
function sanitizerParams(params, exprBuilder) {
for (const param in params) {
if (params[param] === '' || params[param] === null) {
delete store.userParams[param];
delete params[param];
if (store.filter?.where) {
delete store.filter.where[
Object.keys(exprBuilder ? exprBuilder(param) : param)[0]
];
if (Object.keys(store.filter.where).length === 0) {
delete store.filter.where;
}
}
}
}
return params;
2023-02-15 14:51:31 +00:00
}
2023-01-10 13:58:24 +00:00
async function loadMore() {
if (!hasMoreData.value) return;
2024-01-16 10:24:28 +00:00
console.error('loadMore', hasMoreData.value);
2023-01-05 13:57:47 +00:00
2023-03-01 15:20:28 +00:00
store.skip = store.limit * page.value;
2023-01-10 13:58:24 +00:00
page.value += 1;
2023-01-05 13:57:47 +00:00
2023-01-10 13:58:24 +00:00
await fetch({ append: true });
2023-01-05 13:57:47 +00:00
}
2023-10-11 08:40:13 +00:00
async function refresh() {
if (Object.values(store.userParams).length) await fetch({ append: false });
2023-01-14 12:48:57 +00:00
}
function updateStateParams() {
2023-02-16 14:01:02 +00:00
const query = {};
if (store.order) query.order = store.order;
if (store.limit) query.limit = store.limit;
if (store.skip) query.skip = store.skip;
if (store.userParams && Object.keys(store.userParams).length !== 0)
query.params = JSON.stringify(store.userParams);
2024-01-16 10:24:28 +00:00
// hasMoreData.value = true;
2023-11-23 14:50:42 +00:00
if (router)
router.replace({
path: route.path,
query: query,
});
2023-01-05 13:57:47 +00:00
}
2023-09-27 11:41:50 +00:00
const totalRows = computed(() => (store.data && store.data.length) || 0);
const isLoading = computed(() => store.isLoading || false);
2023-03-01 15:20:28 +00:00
2023-01-05 13:57:47 +00:00
return {
fetch,
2023-02-15 14:51:31 +00:00
applyFilter,
addFilter,
2024-01-16 06:24:41 +00:00
removeFilter,
2023-01-05 13:57:47 +00:00
refresh,
2023-03-01 15:20:28 +00:00
destroy,
2023-01-10 13:58:24 +00:00
loadMore,
store,
hasMoreData,
2023-03-01 15:20:28 +00:00
totalRows,
2023-01-14 12:48:57 +00:00
updateStateParams,
2023-09-27 11:41:50 +00:00
isLoading,
2023-01-05 13:57:47 +00:00
};
}