@arex95/vue-core 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/composables/axios/axiosFetch.d.ts +1 -1
- package/dist/composables/axios/createFetch.d.ts +1 -1
- package/dist/composables/axios/useVueQuery.d.ts +1 -1
- package/dist/composables/breakpoints/useBreakpoint.d.ts +1 -1
- package/dist/composables/filters/useFilter.d.ts +1 -1
- package/dist/composables/paginators/usePaginator.d.ts +1 -1
- package/dist/config/axios/axiosConfig.d.ts +1 -1
- package/dist/config/axios/index.d.ts +0 -1
- package/dist/{vue-core.cjs.js → index.js} +465 -1
- package/dist/{vue-core.esm.js → index.mjs} +461 -4
- package/dist/rest/RestStd.d.ts +1 -1
- package/package.json +1 -1
|
@@ -7,4 +7,4 @@ import { AxiosInstance, AxiosRequestConfig } from 'axios';
|
|
|
7
7
|
* @param {AxiosRequestConfig} axiosRequest - Configuration for the Axios request.
|
|
8
8
|
* @returns {Promise<T>} A promise with the result of the API request.
|
|
9
9
|
*/
|
|
10
|
-
export
|
|
10
|
+
export declare function axiosFetch<T>(axios: AxiosInstance, axiosRequest: AxiosRequestConfig): Promise<T>;
|
|
@@ -7,4 +7,4 @@ import { UseQueryOptions } from '@tanstack/vue-query';
|
|
|
7
7
|
* @param axiosInstance - An optional custom Axios instance to use for the request.
|
|
8
8
|
* @returns A function that handles the request using the provided composable.
|
|
9
9
|
*/
|
|
10
|
-
export
|
|
10
|
+
export declare function createFetch(fetchComposable: Function, apiUrl: string, axiosInstance?: AxiosInstance): (axiosRequestConfig: AxiosRequestConfig, options?: UseQueryOptions) => any;
|
|
@@ -9,7 +9,7 @@ import type { ExtendedQueryOptions } from '../../types';
|
|
|
9
9
|
* @param {ExtendedQueryOptions<T>} [queryOptions] - Optional Vue Query options with server execution flag.
|
|
10
10
|
* @returns {object} Composable functions and query state for managing API requests.
|
|
11
11
|
*/
|
|
12
|
-
export
|
|
12
|
+
export declare function useVueQuery<T>(axios: AxiosInstance, axiosRequest: AxiosRequestConfig, queryOptions?: ExtendedQueryOptions): {
|
|
13
13
|
data: import("vue").Ref<T, T>;
|
|
14
14
|
error: import("vue").Ref<unknown, unknown>;
|
|
15
15
|
isError: import("vue").Ref<true, true>;
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* @returns {Object} An object containing the breakpoints and their states.
|
|
5
5
|
*/
|
|
6
|
-
export
|
|
6
|
+
export declare function useBreakpoint(): {
|
|
7
7
|
current: import("vue").ComputedRef<("sm" | "md" | "lg" | "xl" | "2xl")[]>;
|
|
8
8
|
active: import("vue").ComputedRef<"" | "sm" | "md" | "lg" | "xl" | "2xl">;
|
|
9
9
|
sm_S: import("vue").ComputedRef<boolean>;
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
*
|
|
10
10
|
* @returns {Object[]} - The filtered list of objects.
|
|
11
11
|
*/
|
|
12
|
-
export
|
|
12
|
+
export declare function useFilter<T extends Record<string, any>>(items: T[], filterConfig: {
|
|
13
13
|
field: string;
|
|
14
14
|
type: 'date' | 'string' | 'number' | 'boolean';
|
|
15
15
|
criteria: any;
|
|
@@ -7,7 +7,7 @@ import { Ref } from "vue";
|
|
|
7
7
|
* @param pageSize - Reactive ref for number of items per page.
|
|
8
8
|
* @returns An object with pagination controls.
|
|
9
9
|
*/
|
|
10
|
-
export
|
|
10
|
+
export declare function usePagination(page: Ref<number>, total: Ref<number>, pageSize: Ref<number>): {
|
|
11
11
|
totalPages: import("vue").ComputedRef<number>;
|
|
12
12
|
canFetchNextPage: () => boolean;
|
|
13
13
|
canFetchPreviousPage: () => boolean;
|
|
@@ -3,7 +3,7 @@ import { AxiosInstance } from 'axios';
|
|
|
3
3
|
* AxiosService class encapsulates the Axios configuration and logic.
|
|
4
4
|
* It manages request and response interceptors and provides methods for making HTTP requests.
|
|
5
5
|
*/
|
|
6
|
-
export
|
|
6
|
+
export declare class AxiosService {
|
|
7
7
|
private readonly instance;
|
|
8
8
|
private cancelTokenSource;
|
|
9
9
|
private activeRequests;
|
|
@@ -1,10 +1,139 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var axios = require('axios');
|
|
4
|
-
require('@tanstack/vue-query');
|
|
4
|
+
var vueQuery = require('@tanstack/vue-query');
|
|
5
5
|
var vue = require('vue');
|
|
6
6
|
var core = require('@vueuse/core');
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* A standard REST API interface for handling basic CRUD operations.
|
|
10
|
+
* This class can be instantiated with a resource endpoint and a fetch composable for API requests.
|
|
11
|
+
*/
|
|
12
|
+
class RestStd {
|
|
13
|
+
static resource;
|
|
14
|
+
static fetchComposable;
|
|
15
|
+
/**
|
|
16
|
+
* Fetch a list of items from the server.
|
|
17
|
+
*
|
|
18
|
+
* @param params Query parameters for filtering the results.
|
|
19
|
+
* @param options Additional options for the fetch composable.
|
|
20
|
+
* @returns The result of the fetch composable (typically a promise).
|
|
21
|
+
*/
|
|
22
|
+
static getMany(params, options = {}) {
|
|
23
|
+
return this.fetchComposable({
|
|
24
|
+
method: 'GET',
|
|
25
|
+
url: this.resource,
|
|
26
|
+
params,
|
|
27
|
+
}, options);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Fetch a single item by ID from the server.
|
|
31
|
+
*
|
|
32
|
+
* @param id The ID of the item to fetch.
|
|
33
|
+
* @param params Additional query parameters for the request.
|
|
34
|
+
* @param options Additional options for the fetch composable.
|
|
35
|
+
* @returns The result of the fetch composable (typically a promise).
|
|
36
|
+
*/
|
|
37
|
+
static getOne(id, params, options = {}) {
|
|
38
|
+
return this.fetchComposable({
|
|
39
|
+
method: 'GET',
|
|
40
|
+
url: `${this.resource}/${id}`,
|
|
41
|
+
params,
|
|
42
|
+
}, options);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Create a new item on the server.
|
|
46
|
+
*
|
|
47
|
+
* @param data The data for the new item to create.
|
|
48
|
+
* @param options Additional options for the fetch composable.
|
|
49
|
+
* @returns The result of the fetch composable (typically a promise).
|
|
50
|
+
*/
|
|
51
|
+
static create(data, options = {}) {
|
|
52
|
+
return this.fetchComposable({
|
|
53
|
+
method: 'POST',
|
|
54
|
+
url: this.resource,
|
|
55
|
+
data,
|
|
56
|
+
}, options);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Update an existing item on the server.
|
|
60
|
+
*
|
|
61
|
+
* @param id The ID of the item to update.
|
|
62
|
+
* @param data The updated data for the item.
|
|
63
|
+
* @param options Additional options for the fetch composable.
|
|
64
|
+
* @returns The result of the fetch composable (typically a promise).
|
|
65
|
+
*/
|
|
66
|
+
static update(id, data, options = {}) {
|
|
67
|
+
return this.fetchComposable({
|
|
68
|
+
method: 'PUT',
|
|
69
|
+
url: `${this.resource}/${id}`,
|
|
70
|
+
data,
|
|
71
|
+
}, options);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Partially update an existing item on the server.
|
|
75
|
+
*
|
|
76
|
+
* @param id The ID of the item to update.
|
|
77
|
+
* @param data The updated data for the item.
|
|
78
|
+
* @param options Additional options for the fetch composable.
|
|
79
|
+
* @returns The result of the fetch composable (typically a promise).
|
|
80
|
+
*/
|
|
81
|
+
static patch(id, data, options = {}) {
|
|
82
|
+
return this.fetchComposable({
|
|
83
|
+
method: 'PATCH',
|
|
84
|
+
url: `${this.resource}/${id}`,
|
|
85
|
+
data,
|
|
86
|
+
}, options);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Delete an item from the server.
|
|
90
|
+
*
|
|
91
|
+
* @param id The ID of the item to delete.
|
|
92
|
+
* @param options Additional options for the fetch composable.
|
|
93
|
+
* @returns The result of the fetch composable (typically a promise).
|
|
94
|
+
*/
|
|
95
|
+
static delete(id, options = {}) {
|
|
96
|
+
return this.fetchComposable({
|
|
97
|
+
method: 'DELETE',
|
|
98
|
+
url: `${this.resource}/${id}`,
|
|
99
|
+
}, options);
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Custom request method for more flexibility.
|
|
103
|
+
*
|
|
104
|
+
* @param method HTTP method (GET, POST, etc.).
|
|
105
|
+
* @param params Query parameters.
|
|
106
|
+
* @param data Request body data.
|
|
107
|
+
* @param token Authorization token (optional).
|
|
108
|
+
* @param options Additional options for the fetch composable.
|
|
109
|
+
* @returns The result of the fetch composable (typically a promise).
|
|
110
|
+
*/
|
|
111
|
+
static customRequest(method, params, data, options = {}) {
|
|
112
|
+
return this.fetchComposable({
|
|
113
|
+
method: method,
|
|
114
|
+
url: this.resource,
|
|
115
|
+
params: params,
|
|
116
|
+
data: data,
|
|
117
|
+
}, options);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Custom composable function for making API requests with Axios.
|
|
123
|
+
*
|
|
124
|
+
* @template T The expected return type of the API request.
|
|
125
|
+
* @param {AxiosInstance} axios - The Axios instance for making HTTP requests.
|
|
126
|
+
* @param {AxiosRequestConfig} axiosRequest - Configuration for the Axios request.
|
|
127
|
+
* @returns {Promise<T>} A promise with the result of the API request.
|
|
128
|
+
*/
|
|
129
|
+
async function axiosFetch(axios, axiosRequest) {
|
|
130
|
+
return axios(axiosRequest)
|
|
131
|
+
.then(response => response.data)
|
|
132
|
+
.catch(error => {
|
|
133
|
+
throw error;
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
|
|
8
137
|
/**
|
|
9
138
|
* AxiosService class encapsulates the Axios configuration and logic.
|
|
10
139
|
* It manages request and response interceptors and provides methods for making HTTP requests.
|
|
@@ -112,6 +241,334 @@ class AxiosService {
|
|
|
112
241
|
}
|
|
113
242
|
}
|
|
114
243
|
|
|
244
|
+
/**
|
|
245
|
+
* Creates a fetchComposable for Axios requests with an optional custom instance.
|
|
246
|
+
* @param fetchComposable - The composable to use for the request (can be any fetch function).
|
|
247
|
+
* @param apiUrl - The base URL for the Axios instance.
|
|
248
|
+
* @param axiosInstance - An optional custom Axios instance to use for the request.
|
|
249
|
+
* @returns A function that handles the request using the provided composable.
|
|
250
|
+
*/
|
|
251
|
+
function createFetch(fetchComposable, apiUrl, axiosInstance) {
|
|
252
|
+
const instance = axiosInstance || new AxiosService(apiUrl).getAxiosInstance();
|
|
253
|
+
return (axiosRequestConfig, options) => {
|
|
254
|
+
return fetchComposable(instance, axiosRequestConfig, options);
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Custom composable for integrating Axios requests with Vue Query.
|
|
260
|
+
*
|
|
261
|
+
* @template T - The type of data expected from the query.
|
|
262
|
+
* @param {AxiosInstance} axios - Axios instance used for making HTTP requests.
|
|
263
|
+
* @param {AxiosRequestConfig} axiosRequest - Initial Axios request configuration.
|
|
264
|
+
* @param {ExtendedQueryOptions<T>} [queryOptions] - Optional Vue Query options with server execution flag.
|
|
265
|
+
* @returns {object} Composable functions and query state for managing API requests.
|
|
266
|
+
*/
|
|
267
|
+
function useVueQuery(axios, axiosRequest, queryOptions) {
|
|
268
|
+
const key = vue.ref([
|
|
269
|
+
queryOptions?.queryKey || `${axiosRequest.url}-${JSON.stringify(axiosRequest)}`
|
|
270
|
+
]);
|
|
271
|
+
const axiosRequestRef = vue.ref(axiosRequest);
|
|
272
|
+
const queryOptionsRef = vue.ref(queryOptions);
|
|
273
|
+
const isInitialized = vue.ref(false);
|
|
274
|
+
const errorCallbacks = vue.ref([]);
|
|
275
|
+
const resultCallbacks = vue.ref([]);
|
|
276
|
+
/**
|
|
277
|
+
* Vue Query instance for managing API requests.
|
|
278
|
+
*/
|
|
279
|
+
const query = vueQuery.useQuery({
|
|
280
|
+
queryKey: key.value,
|
|
281
|
+
queryFn: async () => {
|
|
282
|
+
const response = await axios(axiosRequestRef.value);
|
|
283
|
+
return response.data;
|
|
284
|
+
},
|
|
285
|
+
...(queryOptionsRef.value?.options ?? {})
|
|
286
|
+
});
|
|
287
|
+
/**
|
|
288
|
+
* Executes the query manually with optional new key and request parameters.
|
|
289
|
+
*
|
|
290
|
+
* @param {Array<any>} [newKey] - New query key to use.
|
|
291
|
+
* @param {object} [newRequestParams] - New request parameters to use.
|
|
292
|
+
* @param {ExtendedQueryOptions<T>} [newQueryOptions] - New Vue Query options to use.
|
|
293
|
+
*/
|
|
294
|
+
function execute(newKey, newRequestParams, newQueryOptions) {
|
|
295
|
+
if (newKey) {
|
|
296
|
+
key.value = newKey;
|
|
297
|
+
}
|
|
298
|
+
if (newRequestParams) {
|
|
299
|
+
axiosRequestRef.value.data = newRequestParams;
|
|
300
|
+
}
|
|
301
|
+
if (newQueryOptions) {
|
|
302
|
+
queryOptionsRef.value = newQueryOptions;
|
|
303
|
+
}
|
|
304
|
+
query.refetch();
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Registers a callback to be executed on successful request result.
|
|
308
|
+
* If data is already available, the callback will be executed immediately.
|
|
309
|
+
*
|
|
310
|
+
* @param {(data: T) => void} cb - Callback function to handle the result.
|
|
311
|
+
*/
|
|
312
|
+
function onResult(cb) {
|
|
313
|
+
resultCallbacks.value.push(cb);
|
|
314
|
+
if (query.data.value !== undefined && query.data.value !== null) {
|
|
315
|
+
cb(query.data.value);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Registers a callback to be executed when the request results in an error.
|
|
320
|
+
* If an error is already present, the callback will be executed immediately.
|
|
321
|
+
*
|
|
322
|
+
* @param {(e: unknown) => void} callback - Callback function to handle errors.
|
|
323
|
+
*/
|
|
324
|
+
function onError(callback) {
|
|
325
|
+
errorCallbacks.value.push(callback);
|
|
326
|
+
if (query.error.value !== undefined) {
|
|
327
|
+
callback(query.error.value);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* Watches for changes in the query result and triggers result callbacks.
|
|
332
|
+
*/
|
|
333
|
+
vue.watch(query.data, (newData) => {
|
|
334
|
+
if (newData !== undefined && newData !== null && isInitialized.value) {
|
|
335
|
+
resultCallbacks.value.forEach((cb) => cb(newData));
|
|
336
|
+
}
|
|
337
|
+
});
|
|
338
|
+
/**
|
|
339
|
+
* Watches for changes in query errors and triggers error callbacks.
|
|
340
|
+
*/
|
|
341
|
+
vue.watch(query.error, (newError) => {
|
|
342
|
+
if (newError !== undefined && isInitialized.value) {
|
|
343
|
+
errorCallbacks.value.forEach((cb) => cb(newError));
|
|
344
|
+
}
|
|
345
|
+
});
|
|
346
|
+
/**
|
|
347
|
+
* Handles server-side prefetching for SSR.
|
|
348
|
+
* Ensures data is fetched before rendering on the server.
|
|
349
|
+
*/
|
|
350
|
+
vue.onServerPrefetch(async () => {
|
|
351
|
+
if (queryOptionsRef.value?.server !== false) {
|
|
352
|
+
await query.suspense();
|
|
353
|
+
if (query.data.value != null) {
|
|
354
|
+
resultCallbacks.value.forEach((cb) => cb(query.data.value));
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
});
|
|
358
|
+
/**
|
|
359
|
+
* Ensures callbacks are executed after the component is mounted on the client-side.
|
|
360
|
+
*/
|
|
361
|
+
vue.onMounted(() => {
|
|
362
|
+
isInitialized.value = true;
|
|
363
|
+
if (query.data.value != null) {
|
|
364
|
+
resultCallbacks.value.forEach((cb) => cb(query.data.value));
|
|
365
|
+
}
|
|
366
|
+
if (query.error.value !== undefined) {
|
|
367
|
+
errorCallbacks.value.forEach((cb) => cb(query.error.value));
|
|
368
|
+
}
|
|
369
|
+
});
|
|
370
|
+
return {
|
|
371
|
+
execute,
|
|
372
|
+
onResult,
|
|
373
|
+
onError,
|
|
374
|
+
...query
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
let notified = false;
|
|
379
|
+
/**
|
|
380
|
+
* Composable to manage breakpoints using Tailwind CSS and shared window resize listener.
|
|
381
|
+
*
|
|
382
|
+
* @returns {Object} An object containing the breakpoints and their states.
|
|
383
|
+
*/
|
|
384
|
+
function useBreakpoint() {
|
|
385
|
+
const breakpoints = core.useBreakpoints(core.breakpointsTailwind);
|
|
386
|
+
const current = breakpoints.current();
|
|
387
|
+
const active = breakpoints.active();
|
|
388
|
+
// Define breakpoints
|
|
389
|
+
const sm_S = breakpoints.smaller('sm');
|
|
390
|
+
const sm_SE = breakpoints.smallerOrEqual('sm');
|
|
391
|
+
const sm_GE = breakpoints.greaterOrEqual('sm');
|
|
392
|
+
const sm_md = breakpoints.between('sm', 'md');
|
|
393
|
+
const sm_xl = breakpoints.between('sm', 'xl');
|
|
394
|
+
const sm_2xl = breakpoints.between('sm', '2xl');
|
|
395
|
+
const md_S = breakpoints.smaller('md');
|
|
396
|
+
const md_SE = breakpoints.smallerOrEqual('md');
|
|
397
|
+
const md_GE = breakpoints.greaterOrEqual('md');
|
|
398
|
+
const md_lg = breakpoints.between('md', 'lg');
|
|
399
|
+
const md_xl = breakpoints.between('md', 'xl');
|
|
400
|
+
const md_2xl = breakpoints.between('md', '2xl');
|
|
401
|
+
const lg_S = breakpoints.smaller('lg');
|
|
402
|
+
const lg_SE = breakpoints.smallerOrEqual('lg');
|
|
403
|
+
const lg_GE = breakpoints.greaterOrEqual('lg');
|
|
404
|
+
const lg_xl = breakpoints.between('lg', 'xl');
|
|
405
|
+
const lg_2xl = breakpoints.between('lg', '2xl');
|
|
406
|
+
const xl_S = breakpoints.smaller('xl');
|
|
407
|
+
const xl_SE = breakpoints.smallerOrEqual('xl');
|
|
408
|
+
const xl_GE = breakpoints.greaterOrEqual('xl');
|
|
409
|
+
const xl_2xl = breakpoints.between('xl', '2xl');
|
|
410
|
+
const _2xl_S = breakpoints.smaller('2xl');
|
|
411
|
+
const _2xl_SE = breakpoints.smallerOrEqual('2xl');
|
|
412
|
+
const _2xl_GE = breakpoints.greaterOrEqual('2xl');
|
|
413
|
+
const reactiveBreakpoint = vue.ref('sm');
|
|
414
|
+
const isGreaterThanBreakpoint = breakpoints.greaterOrEqual(() => reactiveBreakpoint.value);
|
|
415
|
+
// Define device ranges
|
|
416
|
+
const mobile = breakpoints.smaller('md'); // <768px
|
|
417
|
+
const tablet = breakpoints.between('md', 'lg'); // 768px - 1024px
|
|
418
|
+
const laptop = breakpoints.between('lg', 'xl'); // 1024px - 1280px
|
|
419
|
+
const desktop = breakpoints.greaterOrEqual('xl'); // >=1280px
|
|
420
|
+
// Use VueUse for window size
|
|
421
|
+
const { width: windowWidth, height: windowHeight } = core.useWindowSize();
|
|
422
|
+
/**
|
|
423
|
+
* Logs a styled "chip" message to the console.
|
|
424
|
+
*
|
|
425
|
+
* @param {string} label - The label to display inside the chip.
|
|
426
|
+
* @param {string} backgroundColor - The background color of the chip.
|
|
427
|
+
* @param {string} textColor - The text color of the chip.
|
|
428
|
+
*/
|
|
429
|
+
const logChip = (label, backgroundColor, textColor = 'white') => {
|
|
430
|
+
console.log(`%c ${label} `, `background-color: ${backgroundColor}; color: ${textColor}; border-radius: 16px; padding: 4px 8px;`);
|
|
431
|
+
};
|
|
432
|
+
// Singleton logic: Only notify once
|
|
433
|
+
const notifyOnce = () => {
|
|
434
|
+
if (notified)
|
|
435
|
+
return;
|
|
436
|
+
vue.watch([mobile, tablet, laptop, desktop], ([isMobile, isTablet, isLaptop, isDesktop]) => {
|
|
437
|
+
if (isMobile) {
|
|
438
|
+
logChip('Mobile', '#ff6b6b');
|
|
439
|
+
}
|
|
440
|
+
else if (isTablet) {
|
|
441
|
+
logChip('Tablet', '#4ecdc4');
|
|
442
|
+
}
|
|
443
|
+
else if (isLaptop) {
|
|
444
|
+
logChip('Laptop', '#1a535c');
|
|
445
|
+
}
|
|
446
|
+
else if (isDesktop) {
|
|
447
|
+
logChip('Desktop', '#f7fff7', 'black');
|
|
448
|
+
}
|
|
449
|
+
notified = true; // Mark as notified
|
|
450
|
+
}, { immediate: true });
|
|
451
|
+
};
|
|
452
|
+
notifyOnce(); // Ensure the notification happens only once globally
|
|
453
|
+
return {
|
|
454
|
+
current,
|
|
455
|
+
active,
|
|
456
|
+
sm_S,
|
|
457
|
+
sm_SE,
|
|
458
|
+
sm_GE,
|
|
459
|
+
sm_md,
|
|
460
|
+
sm_xl,
|
|
461
|
+
sm_2xl,
|
|
462
|
+
md_S,
|
|
463
|
+
md_SE,
|
|
464
|
+
md_GE,
|
|
465
|
+
md_lg,
|
|
466
|
+
md_xl,
|
|
467
|
+
md_2xl,
|
|
468
|
+
lg_S,
|
|
469
|
+
lg_SE,
|
|
470
|
+
lg_GE,
|
|
471
|
+
lg_xl,
|
|
472
|
+
lg_2xl,
|
|
473
|
+
xl_S,
|
|
474
|
+
xl_SE,
|
|
475
|
+
xl_GE,
|
|
476
|
+
xl_2xl,
|
|
477
|
+
_2xl_S,
|
|
478
|
+
_2xl_SE,
|
|
479
|
+
_2xl_GE,
|
|
480
|
+
isGreaterThanBreakpoint,
|
|
481
|
+
reactiveBreakpoint,
|
|
482
|
+
breakpointsTailwind: core.breakpointsTailwind,
|
|
483
|
+
windowWidth,
|
|
484
|
+
windowHeight,
|
|
485
|
+
mobile,
|
|
486
|
+
tablet,
|
|
487
|
+
laptop,
|
|
488
|
+
desktop,
|
|
489
|
+
breakpoints,
|
|
490
|
+
};
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
/**
|
|
494
|
+
* A composable function that filters objects based on a specific field and criteria.
|
|
495
|
+
*
|
|
496
|
+
* @param {Object[]} items - The list of objects to filter.
|
|
497
|
+
* @param {Object} filterConfig - Configuration for the filter, specifying the field, the data type to filter, and the criteria.
|
|
498
|
+
* @param {string} filterConfig.field - The field in the objects to filter.
|
|
499
|
+
* @param {string} filterConfig.type - The data type of the field ('date', 'string', 'number', 'boolean').
|
|
500
|
+
* @param {any} filterConfig.criteria - The criteria for filtering. Can be a date range, a string to search, a number range, or a boolean value.
|
|
501
|
+
*
|
|
502
|
+
* @returns {Object[]} - The filtered list of objects.
|
|
503
|
+
*/
|
|
504
|
+
function useFilter(items, filterConfig) {
|
|
505
|
+
// Ensure the filterConfig is correctly structured
|
|
506
|
+
const { field, type, criteria } = filterConfig;
|
|
507
|
+
// Define the filter functions
|
|
508
|
+
const filterByDate = (objects, field, { startDate, endDate }) => objects.filter(item => {
|
|
509
|
+
const date = new Date(item[field]);
|
|
510
|
+
return date >= new Date(startDate) && date <= new Date(endDate);
|
|
511
|
+
});
|
|
512
|
+
const filterByString = (objects, field, searchTerm) => {
|
|
513
|
+
const normalize = (str) => str.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase();
|
|
514
|
+
const words = normalize(searchTerm).split(/\s+/).filter(Boolean);
|
|
515
|
+
return objects.filter(item => {
|
|
516
|
+
const normalizedFieldValue = normalize(item[field]);
|
|
517
|
+
return words.every(word => normalizedFieldValue.includes(word));
|
|
518
|
+
});
|
|
519
|
+
};
|
|
520
|
+
const filterByNumber = (objects, field, { min, max }) => objects.filter(item => {
|
|
521
|
+
const value = item[field];
|
|
522
|
+
return value >= min && value <= max;
|
|
523
|
+
});
|
|
524
|
+
const filterByBoolean = (objects, field, expectedValue) => objects.filter(item => item[field] === expectedValue);
|
|
525
|
+
// Apply the appropriate filter and return the filtered objects
|
|
526
|
+
const filteredObjects = vue.computed(() => {
|
|
527
|
+
if (!criteria ||
|
|
528
|
+
(type === 'date' && (!criteria.startDate || !criteria.endDate)) ||
|
|
529
|
+
(type === 'number' && (criteria.min == null || criteria.max == null)) ||
|
|
530
|
+
(type === 'boolean' && typeof criteria !== 'boolean')) {
|
|
531
|
+
return items; // Return all objects if criteria is not valid
|
|
532
|
+
}
|
|
533
|
+
// Apply the filter based on the type
|
|
534
|
+
switch (type) {
|
|
535
|
+
case 'date':
|
|
536
|
+
return filterByDate(items, field, criteria);
|
|
537
|
+
case 'string':
|
|
538
|
+
return filterByString(items, field, criteria);
|
|
539
|
+
case 'number':
|
|
540
|
+
return filterByNumber(items, field, criteria);
|
|
541
|
+
case 'boolean':
|
|
542
|
+
return filterByBoolean(items, field, criteria);
|
|
543
|
+
default:
|
|
544
|
+
return items;
|
|
545
|
+
}
|
|
546
|
+
});
|
|
547
|
+
return filteredObjects.value;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
/**
|
|
551
|
+
* Composable to handle pagination logic.
|
|
552
|
+
*
|
|
553
|
+
* @param page - Reactive ref for the current page number.
|
|
554
|
+
* @param total - Reactive ref for total number of items.
|
|
555
|
+
* @param pageSize - Reactive ref for number of items per page.
|
|
556
|
+
* @returns An object with pagination controls.
|
|
557
|
+
*/
|
|
558
|
+
function usePagination(page, total, pageSize) {
|
|
559
|
+
// Calculate the total number of pages
|
|
560
|
+
const totalPages = vue.computed(() => Math.ceil(total.value / pageSize.value));
|
|
561
|
+
// Determine if the next page can be fetched
|
|
562
|
+
const canFetchNextPage = () => page.value < totalPages.value;
|
|
563
|
+
// Determine if the previous page can be fetched
|
|
564
|
+
const canFetchPreviousPage = () => page.value > 1;
|
|
565
|
+
return {
|
|
566
|
+
totalPages,
|
|
567
|
+
canFetchNextPage,
|
|
568
|
+
canFetchPreviousPage
|
|
569
|
+
};
|
|
570
|
+
}
|
|
571
|
+
|
|
115
572
|
/**
|
|
116
573
|
* Custom composable for sorting products based on a selected criterion.
|
|
117
574
|
* @param {Array} items - The array of products to sort.
|
|
@@ -2005,6 +2462,7 @@ exports.LOCALE_KEY = LOCALE_KEY;
|
|
|
2005
2462
|
exports.LOCK_INFO_KEY = LOCK_INFO_KEY;
|
|
2006
2463
|
exports.PROJ_CFG_KEY = PROJ_CFG_KEY;
|
|
2007
2464
|
exports.ROLES_KEY = ROLES_KEY;
|
|
2465
|
+
exports.RestStd = RestStd;
|
|
2008
2466
|
exports.TOKEN_KEY = TOKEN_KEY;
|
|
2009
2467
|
exports.USER_INFO_KEY = USER_INFO_KEY;
|
|
2010
2468
|
exports.addCustomKeyboardShortcut = addCustomKeyboardShortcut;
|
|
@@ -2012,6 +2470,7 @@ exports.addDays = addDays;
|
|
|
2012
2470
|
exports.addDoubleClickListener = addDoubleClickListener;
|
|
2013
2471
|
exports.addKeyListener = addKeyListener;
|
|
2014
2472
|
exports.ageAtDate = ageAtDate;
|
|
2473
|
+
exports.axiosFetch = axiosFetch;
|
|
2015
2474
|
exports.blobToFormData = blobToFormData;
|
|
2016
2475
|
exports.bufferToBlob = bufferToBlob;
|
|
2017
2476
|
exports.calculateAge = calculateAge;
|
|
@@ -2019,6 +2478,7 @@ exports.clickOutside = clickOutside;
|
|
|
2019
2478
|
exports.compareObject = compareObject;
|
|
2020
2479
|
exports.copyToClipboard = copyToClipboard;
|
|
2021
2480
|
exports.countWords = countWords;
|
|
2481
|
+
exports.createFetch = createFetch;
|
|
2022
2482
|
exports.createKeyMap = createKeyMap;
|
|
2023
2483
|
exports.customShortcut = customShortcut;
|
|
2024
2484
|
exports.daysBetween = daysBetween;
|
|
@@ -2112,7 +2572,11 @@ exports.toggleTabNavigation = toggleTabNavigation;
|
|
|
2112
2572
|
exports.truncateString = truncateString;
|
|
2113
2573
|
exports.unregisterKeyboardShortcuts = unregisterKeyboardShortcuts;
|
|
2114
2574
|
exports.upperFirst = upperFirst;
|
|
2575
|
+
exports.useBreakpoint = useBreakpoint;
|
|
2576
|
+
exports.useFilter = useFilter;
|
|
2577
|
+
exports.usePagination = usePagination;
|
|
2115
2578
|
exports.useSorter = useSorter;
|
|
2579
|
+
exports.useVueQuery = useVueQuery;
|
|
2116
2580
|
exports.validateAlphanumeric = validateAlphanumeric;
|
|
2117
2581
|
exports.validateLetters = validateLetters;
|
|
2118
2582
|
exports.validateNumbers = validateNumbers;
|
|
@@ -1,7 +1,136 @@
|
|
|
1
1
|
import axios from 'axios';
|
|
2
|
-
import '@tanstack/vue-query';
|
|
3
|
-
import { computed } from 'vue';
|
|
4
|
-
import { useTimeoutFn } from '@vueuse/core';
|
|
2
|
+
import { useQuery } from '@tanstack/vue-query';
|
|
3
|
+
import { ref, watch, onServerPrefetch, onMounted, computed } from 'vue';
|
|
4
|
+
import { useBreakpoints, breakpointsTailwind, useWindowSize, useTimeoutFn } from '@vueuse/core';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* A standard REST API interface for handling basic CRUD operations.
|
|
8
|
+
* This class can be instantiated with a resource endpoint and a fetch composable for API requests.
|
|
9
|
+
*/
|
|
10
|
+
class RestStd {
|
|
11
|
+
static resource;
|
|
12
|
+
static fetchComposable;
|
|
13
|
+
/**
|
|
14
|
+
* Fetch a list of items from the server.
|
|
15
|
+
*
|
|
16
|
+
* @param params Query parameters for filtering the results.
|
|
17
|
+
* @param options Additional options for the fetch composable.
|
|
18
|
+
* @returns The result of the fetch composable (typically a promise).
|
|
19
|
+
*/
|
|
20
|
+
static getMany(params, options = {}) {
|
|
21
|
+
return this.fetchComposable({
|
|
22
|
+
method: 'GET',
|
|
23
|
+
url: this.resource,
|
|
24
|
+
params,
|
|
25
|
+
}, options);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Fetch a single item by ID from the server.
|
|
29
|
+
*
|
|
30
|
+
* @param id The ID of the item to fetch.
|
|
31
|
+
* @param params Additional query parameters for the request.
|
|
32
|
+
* @param options Additional options for the fetch composable.
|
|
33
|
+
* @returns The result of the fetch composable (typically a promise).
|
|
34
|
+
*/
|
|
35
|
+
static getOne(id, params, options = {}) {
|
|
36
|
+
return this.fetchComposable({
|
|
37
|
+
method: 'GET',
|
|
38
|
+
url: `${this.resource}/${id}`,
|
|
39
|
+
params,
|
|
40
|
+
}, options);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Create a new item on the server.
|
|
44
|
+
*
|
|
45
|
+
* @param data The data for the new item to create.
|
|
46
|
+
* @param options Additional options for the fetch composable.
|
|
47
|
+
* @returns The result of the fetch composable (typically a promise).
|
|
48
|
+
*/
|
|
49
|
+
static create(data, options = {}) {
|
|
50
|
+
return this.fetchComposable({
|
|
51
|
+
method: 'POST',
|
|
52
|
+
url: this.resource,
|
|
53
|
+
data,
|
|
54
|
+
}, options);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Update an existing item on the server.
|
|
58
|
+
*
|
|
59
|
+
* @param id The ID of the item to update.
|
|
60
|
+
* @param data The updated data for the item.
|
|
61
|
+
* @param options Additional options for the fetch composable.
|
|
62
|
+
* @returns The result of the fetch composable (typically a promise).
|
|
63
|
+
*/
|
|
64
|
+
static update(id, data, options = {}) {
|
|
65
|
+
return this.fetchComposable({
|
|
66
|
+
method: 'PUT',
|
|
67
|
+
url: `${this.resource}/${id}`,
|
|
68
|
+
data,
|
|
69
|
+
}, options);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Partially update an existing item on the server.
|
|
73
|
+
*
|
|
74
|
+
* @param id The ID of the item to update.
|
|
75
|
+
* @param data The updated data for the item.
|
|
76
|
+
* @param options Additional options for the fetch composable.
|
|
77
|
+
* @returns The result of the fetch composable (typically a promise).
|
|
78
|
+
*/
|
|
79
|
+
static patch(id, data, options = {}) {
|
|
80
|
+
return this.fetchComposable({
|
|
81
|
+
method: 'PATCH',
|
|
82
|
+
url: `${this.resource}/${id}`,
|
|
83
|
+
data,
|
|
84
|
+
}, options);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Delete an item from the server.
|
|
88
|
+
*
|
|
89
|
+
* @param id The ID of the item to delete.
|
|
90
|
+
* @param options Additional options for the fetch composable.
|
|
91
|
+
* @returns The result of the fetch composable (typically a promise).
|
|
92
|
+
*/
|
|
93
|
+
static delete(id, options = {}) {
|
|
94
|
+
return this.fetchComposable({
|
|
95
|
+
method: 'DELETE',
|
|
96
|
+
url: `${this.resource}/${id}`,
|
|
97
|
+
}, options);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Custom request method for more flexibility.
|
|
101
|
+
*
|
|
102
|
+
* @param method HTTP method (GET, POST, etc.).
|
|
103
|
+
* @param params Query parameters.
|
|
104
|
+
* @param data Request body data.
|
|
105
|
+
* @param token Authorization token (optional).
|
|
106
|
+
* @param options Additional options for the fetch composable.
|
|
107
|
+
* @returns The result of the fetch composable (typically a promise).
|
|
108
|
+
*/
|
|
109
|
+
static customRequest(method, params, data, options = {}) {
|
|
110
|
+
return this.fetchComposable({
|
|
111
|
+
method: method,
|
|
112
|
+
url: this.resource,
|
|
113
|
+
params: params,
|
|
114
|
+
data: data,
|
|
115
|
+
}, options);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Custom composable function for making API requests with Axios.
|
|
121
|
+
*
|
|
122
|
+
* @template T The expected return type of the API request.
|
|
123
|
+
* @param {AxiosInstance} axios - The Axios instance for making HTTP requests.
|
|
124
|
+
* @param {AxiosRequestConfig} axiosRequest - Configuration for the Axios request.
|
|
125
|
+
* @returns {Promise<T>} A promise with the result of the API request.
|
|
126
|
+
*/
|
|
127
|
+
async function axiosFetch(axios, axiosRequest) {
|
|
128
|
+
return axios(axiosRequest)
|
|
129
|
+
.then(response => response.data)
|
|
130
|
+
.catch(error => {
|
|
131
|
+
throw error;
|
|
132
|
+
});
|
|
133
|
+
}
|
|
5
134
|
|
|
6
135
|
/**
|
|
7
136
|
* AxiosService class encapsulates the Axios configuration and logic.
|
|
@@ -110,6 +239,334 @@ class AxiosService {
|
|
|
110
239
|
}
|
|
111
240
|
}
|
|
112
241
|
|
|
242
|
+
/**
|
|
243
|
+
* Creates a fetchComposable for Axios requests with an optional custom instance.
|
|
244
|
+
* @param fetchComposable - The composable to use for the request (can be any fetch function).
|
|
245
|
+
* @param apiUrl - The base URL for the Axios instance.
|
|
246
|
+
* @param axiosInstance - An optional custom Axios instance to use for the request.
|
|
247
|
+
* @returns A function that handles the request using the provided composable.
|
|
248
|
+
*/
|
|
249
|
+
function createFetch(fetchComposable, apiUrl, axiosInstance) {
|
|
250
|
+
const instance = axiosInstance || new AxiosService(apiUrl).getAxiosInstance();
|
|
251
|
+
return (axiosRequestConfig, options) => {
|
|
252
|
+
return fetchComposable(instance, axiosRequestConfig, options);
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Custom composable for integrating Axios requests with Vue Query.
|
|
258
|
+
*
|
|
259
|
+
* @template T - The type of data expected from the query.
|
|
260
|
+
* @param {AxiosInstance} axios - Axios instance used for making HTTP requests.
|
|
261
|
+
* @param {AxiosRequestConfig} axiosRequest - Initial Axios request configuration.
|
|
262
|
+
* @param {ExtendedQueryOptions<T>} [queryOptions] - Optional Vue Query options with server execution flag.
|
|
263
|
+
* @returns {object} Composable functions and query state for managing API requests.
|
|
264
|
+
*/
|
|
265
|
+
function useVueQuery(axios, axiosRequest, queryOptions) {
|
|
266
|
+
const key = ref([
|
|
267
|
+
queryOptions?.queryKey || `${axiosRequest.url}-${JSON.stringify(axiosRequest)}`
|
|
268
|
+
]);
|
|
269
|
+
const axiosRequestRef = ref(axiosRequest);
|
|
270
|
+
const queryOptionsRef = ref(queryOptions);
|
|
271
|
+
const isInitialized = ref(false);
|
|
272
|
+
const errorCallbacks = ref([]);
|
|
273
|
+
const resultCallbacks = ref([]);
|
|
274
|
+
/**
|
|
275
|
+
* Vue Query instance for managing API requests.
|
|
276
|
+
*/
|
|
277
|
+
const query = useQuery({
|
|
278
|
+
queryKey: key.value,
|
|
279
|
+
queryFn: async () => {
|
|
280
|
+
const response = await axios(axiosRequestRef.value);
|
|
281
|
+
return response.data;
|
|
282
|
+
},
|
|
283
|
+
...(queryOptionsRef.value?.options ?? {})
|
|
284
|
+
});
|
|
285
|
+
/**
|
|
286
|
+
* Executes the query manually with optional new key and request parameters.
|
|
287
|
+
*
|
|
288
|
+
* @param {Array<any>} [newKey] - New query key to use.
|
|
289
|
+
* @param {object} [newRequestParams] - New request parameters to use.
|
|
290
|
+
* @param {ExtendedQueryOptions<T>} [newQueryOptions] - New Vue Query options to use.
|
|
291
|
+
*/
|
|
292
|
+
function execute(newKey, newRequestParams, newQueryOptions) {
|
|
293
|
+
if (newKey) {
|
|
294
|
+
key.value = newKey;
|
|
295
|
+
}
|
|
296
|
+
if (newRequestParams) {
|
|
297
|
+
axiosRequestRef.value.data = newRequestParams;
|
|
298
|
+
}
|
|
299
|
+
if (newQueryOptions) {
|
|
300
|
+
queryOptionsRef.value = newQueryOptions;
|
|
301
|
+
}
|
|
302
|
+
query.refetch();
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Registers a callback to be executed on successful request result.
|
|
306
|
+
* If data is already available, the callback will be executed immediately.
|
|
307
|
+
*
|
|
308
|
+
* @param {(data: T) => void} cb - Callback function to handle the result.
|
|
309
|
+
*/
|
|
310
|
+
function onResult(cb) {
|
|
311
|
+
resultCallbacks.value.push(cb);
|
|
312
|
+
if (query.data.value !== undefined && query.data.value !== null) {
|
|
313
|
+
cb(query.data.value);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Registers a callback to be executed when the request results in an error.
|
|
318
|
+
* If an error is already present, the callback will be executed immediately.
|
|
319
|
+
*
|
|
320
|
+
* @param {(e: unknown) => void} callback - Callback function to handle errors.
|
|
321
|
+
*/
|
|
322
|
+
function onError(callback) {
|
|
323
|
+
errorCallbacks.value.push(callback);
|
|
324
|
+
if (query.error.value !== undefined) {
|
|
325
|
+
callback(query.error.value);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Watches for changes in the query result and triggers result callbacks.
|
|
330
|
+
*/
|
|
331
|
+
watch(query.data, (newData) => {
|
|
332
|
+
if (newData !== undefined && newData !== null && isInitialized.value) {
|
|
333
|
+
resultCallbacks.value.forEach((cb) => cb(newData));
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
/**
|
|
337
|
+
* Watches for changes in query errors and triggers error callbacks.
|
|
338
|
+
*/
|
|
339
|
+
watch(query.error, (newError) => {
|
|
340
|
+
if (newError !== undefined && isInitialized.value) {
|
|
341
|
+
errorCallbacks.value.forEach((cb) => cb(newError));
|
|
342
|
+
}
|
|
343
|
+
});
|
|
344
|
+
/**
|
|
345
|
+
* Handles server-side prefetching for SSR.
|
|
346
|
+
* Ensures data is fetched before rendering on the server.
|
|
347
|
+
*/
|
|
348
|
+
onServerPrefetch(async () => {
|
|
349
|
+
if (queryOptionsRef.value?.server !== false) {
|
|
350
|
+
await query.suspense();
|
|
351
|
+
if (query.data.value != null) {
|
|
352
|
+
resultCallbacks.value.forEach((cb) => cb(query.data.value));
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
});
|
|
356
|
+
/**
|
|
357
|
+
* Ensures callbacks are executed after the component is mounted on the client-side.
|
|
358
|
+
*/
|
|
359
|
+
onMounted(() => {
|
|
360
|
+
isInitialized.value = true;
|
|
361
|
+
if (query.data.value != null) {
|
|
362
|
+
resultCallbacks.value.forEach((cb) => cb(query.data.value));
|
|
363
|
+
}
|
|
364
|
+
if (query.error.value !== undefined) {
|
|
365
|
+
errorCallbacks.value.forEach((cb) => cb(query.error.value));
|
|
366
|
+
}
|
|
367
|
+
});
|
|
368
|
+
return {
|
|
369
|
+
execute,
|
|
370
|
+
onResult,
|
|
371
|
+
onError,
|
|
372
|
+
...query
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
let notified = false;
|
|
377
|
+
/**
|
|
378
|
+
* Composable to manage breakpoints using Tailwind CSS and shared window resize listener.
|
|
379
|
+
*
|
|
380
|
+
* @returns {Object} An object containing the breakpoints and their states.
|
|
381
|
+
*/
|
|
382
|
+
function useBreakpoint() {
|
|
383
|
+
const breakpoints = useBreakpoints(breakpointsTailwind);
|
|
384
|
+
const current = breakpoints.current();
|
|
385
|
+
const active = breakpoints.active();
|
|
386
|
+
// Define breakpoints
|
|
387
|
+
const sm_S = breakpoints.smaller('sm');
|
|
388
|
+
const sm_SE = breakpoints.smallerOrEqual('sm');
|
|
389
|
+
const sm_GE = breakpoints.greaterOrEqual('sm');
|
|
390
|
+
const sm_md = breakpoints.between('sm', 'md');
|
|
391
|
+
const sm_xl = breakpoints.between('sm', 'xl');
|
|
392
|
+
const sm_2xl = breakpoints.between('sm', '2xl');
|
|
393
|
+
const md_S = breakpoints.smaller('md');
|
|
394
|
+
const md_SE = breakpoints.smallerOrEqual('md');
|
|
395
|
+
const md_GE = breakpoints.greaterOrEqual('md');
|
|
396
|
+
const md_lg = breakpoints.between('md', 'lg');
|
|
397
|
+
const md_xl = breakpoints.between('md', 'xl');
|
|
398
|
+
const md_2xl = breakpoints.between('md', '2xl');
|
|
399
|
+
const lg_S = breakpoints.smaller('lg');
|
|
400
|
+
const lg_SE = breakpoints.smallerOrEqual('lg');
|
|
401
|
+
const lg_GE = breakpoints.greaterOrEqual('lg');
|
|
402
|
+
const lg_xl = breakpoints.between('lg', 'xl');
|
|
403
|
+
const lg_2xl = breakpoints.between('lg', '2xl');
|
|
404
|
+
const xl_S = breakpoints.smaller('xl');
|
|
405
|
+
const xl_SE = breakpoints.smallerOrEqual('xl');
|
|
406
|
+
const xl_GE = breakpoints.greaterOrEqual('xl');
|
|
407
|
+
const xl_2xl = breakpoints.between('xl', '2xl');
|
|
408
|
+
const _2xl_S = breakpoints.smaller('2xl');
|
|
409
|
+
const _2xl_SE = breakpoints.smallerOrEqual('2xl');
|
|
410
|
+
const _2xl_GE = breakpoints.greaterOrEqual('2xl');
|
|
411
|
+
const reactiveBreakpoint = ref('sm');
|
|
412
|
+
const isGreaterThanBreakpoint = breakpoints.greaterOrEqual(() => reactiveBreakpoint.value);
|
|
413
|
+
// Define device ranges
|
|
414
|
+
const mobile = breakpoints.smaller('md'); // <768px
|
|
415
|
+
const tablet = breakpoints.between('md', 'lg'); // 768px - 1024px
|
|
416
|
+
const laptop = breakpoints.between('lg', 'xl'); // 1024px - 1280px
|
|
417
|
+
const desktop = breakpoints.greaterOrEqual('xl'); // >=1280px
|
|
418
|
+
// Use VueUse for window size
|
|
419
|
+
const { width: windowWidth, height: windowHeight } = useWindowSize();
|
|
420
|
+
/**
|
|
421
|
+
* Logs a styled "chip" message to the console.
|
|
422
|
+
*
|
|
423
|
+
* @param {string} label - The label to display inside the chip.
|
|
424
|
+
* @param {string} backgroundColor - The background color of the chip.
|
|
425
|
+
* @param {string} textColor - The text color of the chip.
|
|
426
|
+
*/
|
|
427
|
+
const logChip = (label, backgroundColor, textColor = 'white') => {
|
|
428
|
+
console.log(`%c ${label} `, `background-color: ${backgroundColor}; color: ${textColor}; border-radius: 16px; padding: 4px 8px;`);
|
|
429
|
+
};
|
|
430
|
+
// Singleton logic: Only notify once
|
|
431
|
+
const notifyOnce = () => {
|
|
432
|
+
if (notified)
|
|
433
|
+
return;
|
|
434
|
+
watch([mobile, tablet, laptop, desktop], ([isMobile, isTablet, isLaptop, isDesktop]) => {
|
|
435
|
+
if (isMobile) {
|
|
436
|
+
logChip('Mobile', '#ff6b6b');
|
|
437
|
+
}
|
|
438
|
+
else if (isTablet) {
|
|
439
|
+
logChip('Tablet', '#4ecdc4');
|
|
440
|
+
}
|
|
441
|
+
else if (isLaptop) {
|
|
442
|
+
logChip('Laptop', '#1a535c');
|
|
443
|
+
}
|
|
444
|
+
else if (isDesktop) {
|
|
445
|
+
logChip('Desktop', '#f7fff7', 'black');
|
|
446
|
+
}
|
|
447
|
+
notified = true; // Mark as notified
|
|
448
|
+
}, { immediate: true });
|
|
449
|
+
};
|
|
450
|
+
notifyOnce(); // Ensure the notification happens only once globally
|
|
451
|
+
return {
|
|
452
|
+
current,
|
|
453
|
+
active,
|
|
454
|
+
sm_S,
|
|
455
|
+
sm_SE,
|
|
456
|
+
sm_GE,
|
|
457
|
+
sm_md,
|
|
458
|
+
sm_xl,
|
|
459
|
+
sm_2xl,
|
|
460
|
+
md_S,
|
|
461
|
+
md_SE,
|
|
462
|
+
md_GE,
|
|
463
|
+
md_lg,
|
|
464
|
+
md_xl,
|
|
465
|
+
md_2xl,
|
|
466
|
+
lg_S,
|
|
467
|
+
lg_SE,
|
|
468
|
+
lg_GE,
|
|
469
|
+
lg_xl,
|
|
470
|
+
lg_2xl,
|
|
471
|
+
xl_S,
|
|
472
|
+
xl_SE,
|
|
473
|
+
xl_GE,
|
|
474
|
+
xl_2xl,
|
|
475
|
+
_2xl_S,
|
|
476
|
+
_2xl_SE,
|
|
477
|
+
_2xl_GE,
|
|
478
|
+
isGreaterThanBreakpoint,
|
|
479
|
+
reactiveBreakpoint,
|
|
480
|
+
breakpointsTailwind,
|
|
481
|
+
windowWidth,
|
|
482
|
+
windowHeight,
|
|
483
|
+
mobile,
|
|
484
|
+
tablet,
|
|
485
|
+
laptop,
|
|
486
|
+
desktop,
|
|
487
|
+
breakpoints,
|
|
488
|
+
};
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* A composable function that filters objects based on a specific field and criteria.
|
|
493
|
+
*
|
|
494
|
+
* @param {Object[]} items - The list of objects to filter.
|
|
495
|
+
* @param {Object} filterConfig - Configuration for the filter, specifying the field, the data type to filter, and the criteria.
|
|
496
|
+
* @param {string} filterConfig.field - The field in the objects to filter.
|
|
497
|
+
* @param {string} filterConfig.type - The data type of the field ('date', 'string', 'number', 'boolean').
|
|
498
|
+
* @param {any} filterConfig.criteria - The criteria for filtering. Can be a date range, a string to search, a number range, or a boolean value.
|
|
499
|
+
*
|
|
500
|
+
* @returns {Object[]} - The filtered list of objects.
|
|
501
|
+
*/
|
|
502
|
+
function useFilter(items, filterConfig) {
|
|
503
|
+
// Ensure the filterConfig is correctly structured
|
|
504
|
+
const { field, type, criteria } = filterConfig;
|
|
505
|
+
// Define the filter functions
|
|
506
|
+
const filterByDate = (objects, field, { startDate, endDate }) => objects.filter(item => {
|
|
507
|
+
const date = new Date(item[field]);
|
|
508
|
+
return date >= new Date(startDate) && date <= new Date(endDate);
|
|
509
|
+
});
|
|
510
|
+
const filterByString = (objects, field, searchTerm) => {
|
|
511
|
+
const normalize = (str) => str.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase();
|
|
512
|
+
const words = normalize(searchTerm).split(/\s+/).filter(Boolean);
|
|
513
|
+
return objects.filter(item => {
|
|
514
|
+
const normalizedFieldValue = normalize(item[field]);
|
|
515
|
+
return words.every(word => normalizedFieldValue.includes(word));
|
|
516
|
+
});
|
|
517
|
+
};
|
|
518
|
+
const filterByNumber = (objects, field, { min, max }) => objects.filter(item => {
|
|
519
|
+
const value = item[field];
|
|
520
|
+
return value >= min && value <= max;
|
|
521
|
+
});
|
|
522
|
+
const filterByBoolean = (objects, field, expectedValue) => objects.filter(item => item[field] === expectedValue);
|
|
523
|
+
// Apply the appropriate filter and return the filtered objects
|
|
524
|
+
const filteredObjects = computed(() => {
|
|
525
|
+
if (!criteria ||
|
|
526
|
+
(type === 'date' && (!criteria.startDate || !criteria.endDate)) ||
|
|
527
|
+
(type === 'number' && (criteria.min == null || criteria.max == null)) ||
|
|
528
|
+
(type === 'boolean' && typeof criteria !== 'boolean')) {
|
|
529
|
+
return items; // Return all objects if criteria is not valid
|
|
530
|
+
}
|
|
531
|
+
// Apply the filter based on the type
|
|
532
|
+
switch (type) {
|
|
533
|
+
case 'date':
|
|
534
|
+
return filterByDate(items, field, criteria);
|
|
535
|
+
case 'string':
|
|
536
|
+
return filterByString(items, field, criteria);
|
|
537
|
+
case 'number':
|
|
538
|
+
return filterByNumber(items, field, criteria);
|
|
539
|
+
case 'boolean':
|
|
540
|
+
return filterByBoolean(items, field, criteria);
|
|
541
|
+
default:
|
|
542
|
+
return items;
|
|
543
|
+
}
|
|
544
|
+
});
|
|
545
|
+
return filteredObjects.value;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
/**
|
|
549
|
+
* Composable to handle pagination logic.
|
|
550
|
+
*
|
|
551
|
+
* @param page - Reactive ref for the current page number.
|
|
552
|
+
* @param total - Reactive ref for total number of items.
|
|
553
|
+
* @param pageSize - Reactive ref for number of items per page.
|
|
554
|
+
* @returns An object with pagination controls.
|
|
555
|
+
*/
|
|
556
|
+
function usePagination(page, total, pageSize) {
|
|
557
|
+
// Calculate the total number of pages
|
|
558
|
+
const totalPages = computed(() => Math.ceil(total.value / pageSize.value));
|
|
559
|
+
// Determine if the next page can be fetched
|
|
560
|
+
const canFetchNextPage = () => page.value < totalPages.value;
|
|
561
|
+
// Determine if the previous page can be fetched
|
|
562
|
+
const canFetchPreviousPage = () => page.value > 1;
|
|
563
|
+
return {
|
|
564
|
+
totalPages,
|
|
565
|
+
canFetchNextPage,
|
|
566
|
+
canFetchPreviousPage
|
|
567
|
+
};
|
|
568
|
+
}
|
|
569
|
+
|
|
113
570
|
/**
|
|
114
571
|
* Custom composable for sorting products based on a selected criterion.
|
|
115
572
|
* @param {Array} items - The array of products to sort.
|
|
@@ -1990,4 +2447,4 @@ function isValidHexNumber(hex) {
|
|
|
1990
2447
|
// console.log(isValidHexNumber('1A3F')); // true
|
|
1991
2448
|
// console.log(isValidHexNumber('GHIJ')); // false
|
|
1992
2449
|
|
|
1993
|
-
export { APP_LOCAL_CACHE_KEY, APP_SESSION_CACHE_KEY, AxiosService, CacheTypeEnum, ContentTypeEnum, ExceptionEnum, FileMetaTypes, ImageTypes, KeyCodeEnum, LOCALE_KEY, LOCK_INFO_KEY, PROJ_CFG_KEY, ROLES_KEY, TOKEN_KEY, USER_INFO_KEY, addCustomKeyboardShortcut, addDays, addDoubleClickListener, addKeyListener, ageAtDate, blobToFormData, bufferToBlob, calculateAge, clickOutside, compareObject, copyToClipboard, countWords, createKeyMap, customShortcut, daysBetween, daysToNextBirthday, debounce, debounceAsync, debounceAsyncValidator, debounceAsyncWithImmediate, debounceLeading, debounceLeadingTrailing, debounceTrailing, deepClone, deepEqual, deepMerge, detectKeyHold, disableCopy, disableF12Key, disableMouseButtons, disableRightClick, disableSpecificKeys, downloadBlob, enableMouseButtons, enableRightClick, enableSpecificKeys, exportToCSV, exportToExcel, exportToJSON, exportToText, exportToXML, filterObjectByKeys, flattenObject, formDataToObject, formatDate, generateRandomString, getEndOfMonth, getObjectDifferences, getObjectKeys, getQueryParam, getStartOfMonth, hasNestedProperties, isEmptyObject, isLeapYear, isStrongPassword, isValidAge, isValidCreditCard, isValidDate, isValidEmail, isValidExpiryDate, isValidHexColor, isValidHexColorAlpha, isValidHexNumber, isValidIP, isValidPhoneNumber, isValidSSN, isValidTime, isValidURL, isValidUsername, isValidZIP, lowerFirst, objectToFormData, objectToFormDataEnhanced, objectToQueryString, openWindow, parseDate, proxyToPlainObject, readFileAsDataURL, readFileAsText, registerKeyboardShortcuts, removeAccent, removeClickOutside, removeCustomKeyboardShortcut, removeCustomShortcuts, removeDoubleClickListener, removeEmptyProperties, removeKeyListeners, replaceAll, reverseString, safeGet, screenEnum, screenMap, scrollToTop, simulateKeyPress, sizeEnum, stopDetectingKeyHold, stringToBlob, subtractDays, throttle, toCamelCase, toKebabCase, toggleTabNavigation, truncateString, unregisterKeyboardShortcuts, upperFirst, useSorter, validateAlphanumeric, validateLetters, validateNumbers };
|
|
2450
|
+
export { APP_LOCAL_CACHE_KEY, APP_SESSION_CACHE_KEY, AxiosService, CacheTypeEnum, ContentTypeEnum, ExceptionEnum, FileMetaTypes, ImageTypes, KeyCodeEnum, LOCALE_KEY, LOCK_INFO_KEY, PROJ_CFG_KEY, ROLES_KEY, RestStd, TOKEN_KEY, USER_INFO_KEY, addCustomKeyboardShortcut, addDays, addDoubleClickListener, addKeyListener, ageAtDate, axiosFetch, blobToFormData, bufferToBlob, calculateAge, clickOutside, compareObject, copyToClipboard, countWords, createFetch, createKeyMap, customShortcut, daysBetween, daysToNextBirthday, debounce, debounceAsync, debounceAsyncValidator, debounceAsyncWithImmediate, debounceLeading, debounceLeadingTrailing, debounceTrailing, deepClone, deepEqual, deepMerge, detectKeyHold, disableCopy, disableF12Key, disableMouseButtons, disableRightClick, disableSpecificKeys, downloadBlob, enableMouseButtons, enableRightClick, enableSpecificKeys, exportToCSV, exportToExcel, exportToJSON, exportToText, exportToXML, filterObjectByKeys, flattenObject, formDataToObject, formatDate, generateRandomString, getEndOfMonth, getObjectDifferences, getObjectKeys, getQueryParam, getStartOfMonth, hasNestedProperties, isEmptyObject, isLeapYear, isStrongPassword, isValidAge, isValidCreditCard, isValidDate, isValidEmail, isValidExpiryDate, isValidHexColor, isValidHexColorAlpha, isValidHexNumber, isValidIP, isValidPhoneNumber, isValidSSN, isValidTime, isValidURL, isValidUsername, isValidZIP, lowerFirst, objectToFormData, objectToFormDataEnhanced, objectToQueryString, openWindow, parseDate, proxyToPlainObject, readFileAsDataURL, readFileAsText, registerKeyboardShortcuts, removeAccent, removeClickOutside, removeCustomKeyboardShortcut, removeCustomShortcuts, removeDoubleClickListener, removeEmptyProperties, removeKeyListeners, replaceAll, reverseString, safeGet, screenEnum, screenMap, scrollToTop, simulateKeyPress, sizeEnum, stopDetectingKeyHold, stringToBlob, subtractDays, throttle, toCamelCase, toKebabCase, toggleTabNavigation, truncateString, unregisterKeyboardShortcuts, upperFirst, useBreakpoint, useFilter, usePagination, useSorter, useVueQuery, validateAlphanumeric, validateLetters, validateNumbers };
|
package/dist/rest/RestStd.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* A standard REST API interface for handling basic CRUD operations.
|
|
3
3
|
* This class can be instantiated with a resource endpoint and a fetch composable for API requests.
|
|
4
4
|
*/
|
|
5
|
-
export
|
|
5
|
+
export declare class RestStd {
|
|
6
6
|
static resource: string;
|
|
7
7
|
static fetchComposable: Function;
|
|
8
8
|
/**
|