quasar-ui-danx 0.4.68 → 0.4.69
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/danx.es.js +2835 -2836
- package/dist/danx.es.js.map +1 -1
- package/dist/danx.umd.js +15 -15
- package/dist/danx.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/helpers/actions.ts +15 -27
- package/src/helpers/request.ts +31 -14
- package/src/helpers/routes.ts +2 -2
- package/src/types/requests.d.ts +5 -2
package/package.json
CHANGED
package/src/helpers/actions.ts
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
import { useDebounceFn } from "@vueuse/core";
|
2
2
|
import { FaSolidCopy as CopyIcon, FaSolidPencil as EditIcon, FaSolidTrash as DeleteIcon } from "danx-icon";
|
3
3
|
import { uid } from "quasar";
|
4
|
-
import { h,
|
4
|
+
import { h, Ref, shallowRef } from "vue";
|
5
5
|
import { ConfirmActionDialog, CreateNewWithNameDialog } from "../components";
|
6
6
|
import type {
|
7
7
|
ActionGlobalOptions,
|
@@ -55,39 +55,27 @@ export function useActions(actions: ActionOptions[], globalOptions: ActionGlobal
|
|
55
55
|
*/
|
56
56
|
function getAction(actionName: string, actionOptions?: Partial<ActionOptions>): ResourceAction {
|
57
57
|
/// Resolve the action options or resource action based on the provided input
|
58
|
-
|
59
|
-
|
60
|
-
if (actionOptions) {
|
61
|
-
Object.assign(resourceAction, actionOptions);
|
62
|
-
}
|
58
|
+
const baseOptions: Partial<ResourceAction> = actions.find(a => a.name === actionName) || { name: actionName };
|
63
59
|
|
64
60
|
// If the action is already reactive, return it
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
});
|
75
|
-
|
76
|
-
// Splice the resourceAction in place of the action in the actions list
|
77
|
-
actions.splice(actions.findIndex(a => a.name === actionName), 1, resourceAction as ResourceAction);
|
78
|
-
}
|
79
|
-
|
80
|
-
// Return a clone of the action so it can be modified without affecting the original
|
81
|
-
const clonedAction = shallowReactive({ ...resourceAction }) as ResourceAction;
|
61
|
+
const resourceAction = storeObject({
|
62
|
+
onAction: globalOptions?.routes?.applyAction,
|
63
|
+
onBatchAction: globalOptions?.routes?.batchAction,
|
64
|
+
onBatchSuccess: globalOptions?.controls?.clearSelectedRows,
|
65
|
+
...baseOptions,
|
66
|
+
...actionOptions,
|
67
|
+
isApplying: false,
|
68
|
+
__type: "__Action:" + namespace
|
69
|
+
}) as ResourceAction;
|
82
70
|
|
83
71
|
// Assign Trigger function if it doesn't exist
|
84
|
-
if (
|
85
|
-
|
72
|
+
if (resourceAction.debounce) {
|
73
|
+
resourceAction.trigger = useDebounceFn((target, input) => performAction(resourceAction, target, input), resourceAction.debounce);
|
86
74
|
} else {
|
87
|
-
|
75
|
+
resourceAction.trigger = (target, input) => performAction(resourceAction, target, input);
|
88
76
|
}
|
89
77
|
|
90
|
-
return
|
78
|
+
return resourceAction;
|
91
79
|
}
|
92
80
|
|
93
81
|
/**
|
package/src/helpers/request.ts
CHANGED
@@ -8,7 +8,7 @@ import { sleep } from "./utils";
|
|
8
8
|
* to make GET and POST requests easier w/ JSON payloads
|
9
9
|
*/
|
10
10
|
export const request: RequestApi = {
|
11
|
-
|
11
|
+
activeRequests: {},
|
12
12
|
|
13
13
|
url(url) {
|
14
14
|
if (url.startsWith("http")) {
|
@@ -19,20 +19,27 @@ export const request: RequestApi = {
|
|
19
19
|
|
20
20
|
async call(url, options) {
|
21
21
|
options = options || {};
|
22
|
-
const
|
22
|
+
const requestKey = options?.requestKey || url + JSON.stringify(options.params || "");
|
23
|
+
const waitOnPrevious = !!options?.waitOnPrevious;
|
24
|
+
const shouldAbort = !waitOnPrevious;
|
23
25
|
const timestamp = Date.now();
|
24
26
|
|
25
|
-
|
26
|
-
|
27
|
-
|
27
|
+
// If there was a request with the same key made that is still active, track that here
|
28
|
+
const previousRequest = request.activeRequests[requestKey];
|
29
|
+
|
30
|
+
// Set the current active request to this one
|
31
|
+
request.activeRequests[requestKey] = { timestamp };
|
32
|
+
|
33
|
+
if (shouldAbort) {
|
28
34
|
// If there is already an abort controller set for this key, abort it
|
29
|
-
if (
|
30
|
-
|
35
|
+
if (previousRequest) {
|
36
|
+
previousRequest.abortController?.abort("Request was aborted due to a newer request being made");
|
31
37
|
}
|
32
38
|
|
39
|
+
const abortController = new AbortController();
|
33
40
|
// Set the new abort controller for this key
|
34
|
-
request.
|
35
|
-
options.signal =
|
41
|
+
request.activeRequests[requestKey].abortController = abortController;
|
42
|
+
options.signal = abortController.signal;
|
36
43
|
}
|
37
44
|
|
38
45
|
if (options.params) {
|
@@ -49,7 +56,14 @@ export const request: RequestApi = {
|
|
49
56
|
|
50
57
|
let response = null;
|
51
58
|
try {
|
52
|
-
|
59
|
+
// If there is a previous request still active, wait for it to finish before proceeding (if the waitForPrevious flag is set)
|
60
|
+
if (waitOnPrevious && previousRequest?.requestPromise) {
|
61
|
+
await previousRequest.requestPromise;
|
62
|
+
}
|
63
|
+
|
64
|
+
const requestPromise = fetch(request.url(url), options);
|
65
|
+
request.activeRequests[requestKey].requestPromise = requestPromise;
|
66
|
+
response = await requestPromise;
|
53
67
|
} catch (e) {
|
54
68
|
if (options.ignoreAbort && (e + "").match(/Request was aborted/)) {
|
55
69
|
return { abort: true };
|
@@ -61,15 +75,18 @@ export const request: RequestApi = {
|
|
61
75
|
checkAppVersion(response);
|
62
76
|
|
63
77
|
// handle the case where the request was aborted too late, and we need to abort the response via timestamp check
|
64
|
-
if (
|
78
|
+
if (shouldAbort) {
|
65
79
|
// If the request was aborted too late, but there was still another request that was made after the current,
|
66
80
|
// then abort the current request with an abort flag
|
67
|
-
if (timestamp < request.
|
81
|
+
if (timestamp < request.activeRequests[requestKey].timestamp) {
|
68
82
|
return { abort: true };
|
69
83
|
}
|
84
|
+
}
|
70
85
|
|
71
|
-
|
72
|
-
|
86
|
+
// If this request is the active request for the requestKey, we can clear this key from active requests
|
87
|
+
if (request.activeRequests[requestKey].timestamp === timestamp) {
|
88
|
+
// Remove the request from the active requests list
|
89
|
+
delete request.activeRequests[requestKey];
|
73
90
|
}
|
74
91
|
|
75
92
|
const result = await response.json();
|
package/src/helpers/routes.ts
CHANGED
@@ -56,7 +56,7 @@ export function useActionRoutes(baseUrl: string, extend?: object): ListControlsR
|
|
56
56
|
async applyAction(action, target, data, options?) {
|
57
57
|
options = {
|
58
58
|
...options,
|
59
|
-
|
59
|
+
waitOnPrevious: true,
|
60
60
|
headers: {
|
61
61
|
...options?.headers,
|
62
62
|
"X-Timestamp": Date.now().toString()
|
@@ -86,7 +86,7 @@ export function useActionRoutes(baseUrl: string, extend?: object): ListControlsR
|
|
86
86
|
batchAction(action, targets, data, options?) {
|
87
87
|
options = {
|
88
88
|
...options,
|
89
|
-
|
89
|
+
waitOnPrevious: true
|
90
90
|
};
|
91
91
|
return request.post(`${baseUrl}/batch-action`, { action, filter: { id: targets.map(r => r.id) }, data }, options);
|
92
92
|
},
|
package/src/types/requests.d.ts
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
import { AnyObject } from "./shared";
|
2
2
|
|
3
3
|
export interface RequestApi {
|
4
|
-
|
4
|
+
activeRequests: {
|
5
|
+
[key: string]: { requestPromise?: Promise<any>, abortController?: AbortController, timestamp: number }
|
6
|
+
};
|
5
7
|
|
6
8
|
url(url: string): string;
|
7
9
|
|
@@ -30,7 +32,8 @@ export interface RequestOptions {
|
|
30
32
|
}
|
31
33
|
|
32
34
|
export interface RequestCallOptions extends RequestInit {
|
33
|
-
|
35
|
+
requestKey?: string;
|
36
|
+
waitOnPrevious?: boolean;
|
34
37
|
ignoreAbort?: boolean;
|
35
38
|
params?: AnyObject;
|
36
39
|
}
|