quasar-ui-danx 0.4.4 → 0.4.5

Sign up to get free protection for your applications and to get access to all the features.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "quasar-ui-danx",
3
- "version": "0.4.4",
3
+ "version": "0.4.5",
4
4
  "author": "Dan <dan@flytedesk.com>",
5
5
  "description": "DanX Vue / Quasar component library",
6
6
  "license": "MIT",
@@ -9,7 +9,7 @@
9
9
  :selected="selectedRows"
10
10
  :pagination="pagination"
11
11
  :columns="tableColumns"
12
- :loading="loadingList"
12
+ :loading="loadingList || loadingSummary"
13
13
  :rows="pagedItems?.data || []"
14
14
  :binary-state-sort="false"
15
15
  selection="multiple"
@@ -8,6 +8,7 @@
8
8
  :actions="actions?.filter(a => a.batch)"
9
9
  :action-target="controller.selectedRows.value"
10
10
  :exporter="controller.exportList"
11
+ :loading="controller.isLoadingList.value || controller.isLoadingSummary.value"
11
12
  @refresh="controller.refreshAll"
12
13
  >
13
14
  <template #default>
@@ -1,5 +1,5 @@
1
1
  import { computed, Ref, ref, shallowRef, watch } from "vue";
2
- import { RouteLocationNormalizedLoaded, RouteParams, Router, useRoute, useRouter } from "vue-router";
2
+ import { RouteLocationNormalizedLoaded, RouteParams, Router } from "vue-router";
3
3
  import { getItem, setItem, storeObject, waitForRef } from "../../helpers";
4
4
  import {
5
5
  ActionController,
@@ -7,6 +7,7 @@ import {
7
7
  AnyObject,
8
8
  FilterGroup,
9
9
  ListControlsFilter,
10
+ ListControlsInitializeOptions,
10
11
  ListControlsOptions,
11
12
  ListControlsPagination,
12
13
  PagedItems
@@ -380,19 +381,17 @@ export function useListControls(name: string, options: ListControlsOptions): Act
380
381
  }
381
382
 
382
383
  async function exportList(filter?: ListControlsFilter) {
383
- return options.routes.export(filter);
384
+ options.routes.export && await options.routes.export(filter);
384
385
  }
385
386
 
386
387
  // Initialize the list actions and load settings, lists, summaries, filter fields, etc.
387
- function initialize() {
388
+ function initialize(initOptions: ListControlsInitializeOptions) {
389
+ vueRouter = initOptions.vueRouter;
390
+ vueRoute = initOptions.vueRoute;
388
391
  isInitialized = true;
389
392
  loadSettings();
390
393
 
391
- // Setup Vue Router handling
392
- vueRoute = useRoute();
393
- vueRouter = useRouter();
394
-
395
- console.log("init listControl", name, options, "vueRoute", vueRoute);
394
+ console.log("initialize() called", name, options, "initOptions", initOptions);
396
395
  /**
397
396
  * Watch the id params in the route and set the active item to the item with the given id.
398
397
  */
@@ -1,22 +1,53 @@
1
1
  import { Ref } from "vue";
2
2
  import { danxOptions } from "../config";
3
- import { AnyObject } from "../types";
3
+ import { RequestApi } from "../types";
4
4
 
5
5
  /**
6
6
  * A simple request helper that wraps the fetch API
7
7
  * to make GET and POST requests easier w/ JSON payloads
8
8
  */
9
- export const request = {
10
- url(url: string) {
9
+ export const request: RequestApi = {
10
+ abortControllers: {},
11
+
12
+ url(url) {
11
13
  if (url.startsWith("http")) {
12
14
  return url;
13
15
  }
14
16
  return (danxOptions.value.request?.baseUrl || "").replace(/\/$/, "") + "/" + url;
15
17
  },
16
18
 
17
- async call(url: string, options: RequestInit): Promise<object> {
19
+ async call(url, options) {
18
20
  try {
21
+ const abort = new AbortController();
22
+ const timestamp = new Date().getTime();
23
+
24
+ console.log("call", url, options);
25
+ if (options?.abortOn) {
26
+ console.log("setting up abort", options.abortOn);
27
+ const previousAbort = options.abortOn && request.abortControllers[options.abortOn];
28
+ // If there is already an abort controller set for this key, abort it
29
+ if (previousAbort) {
30
+ previousAbort.abort.abort();
31
+ }
32
+
33
+ // Set the new abort controller for this key
34
+ request.abortControllers[options.abortOn] = { abort, timestamp };
35
+ options.signal = abort.signal;
36
+ }
37
+
38
+ console.log("current timestamp:", timestamp);
19
39
  const response = await fetch(request.url(url), options);
40
+
41
+ // handle the case where the request was aborted too late, and we need to abort the response via timestamp check
42
+ if (options?.abortOn) {
43
+ if (request.abortControllers[options.abortOn].timestamp !== timestamp) {
44
+ console.log("aborting request", options.abortOn, timestamp, "!==", request.abortControllers[options.abortOn].timestamp);
45
+ return { abort: true };
46
+ }
47
+
48
+ delete request.abortControllers[options.abortOn];
49
+ }
50
+
20
51
  const result = await response.json();
21
52
 
22
53
  if (response.status === 401) {
@@ -40,7 +71,7 @@ export const request = {
40
71
  };
41
72
  }
42
73
  },
43
- async get(url: string, options: RequestInit = {}): Promise<object> {
74
+ async get(url, options) {
44
75
  return await request.call(url, {
45
76
  method: "get",
46
77
  headers: {
@@ -52,10 +83,10 @@ export const request = {
52
83
  });
53
84
  },
54
85
 
55
- async post(url: string, data: AnyObject = {}, options: RequestInit = {}) {
56
- return request.call(url, {
86
+ async post(url, data, options) {
87
+ return await request.call(url, {
57
88
  method: "post",
58
- body: JSON.stringify(data),
89
+ body: data && JSON.stringify(data),
59
90
  headers: {
60
91
  Accept: "application/json",
61
92
  "Content-Type": "application/json",
@@ -1,28 +1,29 @@
1
- import { ActionTargetItem, AnyObject, ListControlsPagination } from "../types";
1
+ import { ListControlsRoutes } from "../types";
2
2
  import { downloadFile } from "./downloadPdf";
3
3
  import { request } from "./request";
4
4
 
5
- export function useActionRoutes(baseUrl: string) {
5
+ export function useActionRoutes(baseUrl: string): ListControlsRoutes {
6
6
  return {
7
- list(pager: ListControlsPagination) {
8
- return request.post(`${baseUrl}/list`, pager);
7
+ list(pager?) {
8
+ console.log("here");
9
+ return request.post(`${baseUrl}/list`, pager, { abortOn: "list" });
9
10
  },
10
- summary(filter: AnyObject) {
11
+ summary(filter) {
11
12
  return request.post(`${baseUrl}/summary`, { filter });
12
13
  },
13
- details(target: ActionTargetItem) {
14
+ details(target) {
14
15
  return request.get(`${baseUrl}/${target.id}/details`);
15
16
  },
16
17
  fieldOptions() {
17
18
  return request.get(`${baseUrl}/field-options`);
18
19
  },
19
- applyAction(action: string, target: ActionTargetItem | null, data: object) {
20
+ applyAction(action, target, data) {
20
21
  return request.post(`${baseUrl}/${target ? target.id : "new"}/apply-action`, { action, data });
21
22
  },
22
- batchAction(action: string, targets: ActionTargetItem[], data: object) {
23
+ batchAction(action, targets, data) {
23
24
  return request.post(`${baseUrl}/batch-action`, { action, filter: { id: targets.map(r => r.id) }, data });
24
25
  },
25
- export(filter: AnyObject, name?: string) {
26
+ export(filter, name) {
26
27
  return downloadFile(`${baseUrl}/export`, name || "export.csv", { filter });
27
28
  }
28
29
  };
@@ -1,6 +1,7 @@
1
1
  import { ComputedRef, Ref, ShallowRef } from "vue";
2
+ import { RouteLocationNormalizedLoaded, Router } from "vue-router";
2
3
  import { ActionTargetItem } from "./actions";
3
- import { LabelValueItem } from "./shared";
4
+ import { AnyObject, LabelValueItem } from "./shared";
4
5
 
5
6
  export interface ListControlsFilter {
6
7
  [key: string]: object | object[] | null | undefined | string | number | boolean;
@@ -20,13 +21,23 @@ export interface FilterGroup {
20
21
  fields: FilterableField[];
21
22
  }
22
23
 
24
+
23
25
  export interface ListControlsRoutes {
24
- list: (pager: object) => Promise<ActionTargetItem[]>;
25
- details?: (item: object) => Promise<ActionTargetItem> | null;
26
- summary?: (filter: object | null) => Promise<object> | null;
27
- fieldOptions?: (filter: object | null) => Promise<object> | null;
28
- more?: (pager: object) => Promise<ActionTargetItem[]> | null;
29
- export: (filter?: ListControlsFilter) => Promise<void>;
26
+ list(pager?: ListControlsPagination): Promise<ActionTargetItem[]>;
27
+
28
+ summary?(filter?: ListControlsFilter): Promise<object>;
29
+
30
+ details?(target: ActionTargetItem): Promise<ActionTargetItem>;
31
+
32
+ more?(pager: ListControlsPagination): Promise<ActionTargetItem[]>;
33
+
34
+ fieldOptions?(filter?: AnyObject): Promise<object>;
35
+
36
+ applyAction?(action: string, target: ActionTargetItem | null, data: object): Promise<object>;
37
+
38
+ batchAction?(action: string, targets: ActionTargetItem[], data: object): Promise<object>;
39
+
40
+ export?(filter?: ListControlsFilter, name?: string): Promise<void>;
30
41
  }
31
42
 
32
43
  export interface ListControlsOptions {
@@ -44,6 +55,8 @@ export interface ListControlsPagination {
44
55
  page?: number;
45
56
  rowsNumber?: number;
46
57
  rowsPerPage?: number;
58
+ perPage?: number;
59
+ filter?: ListControlsFilter;
47
60
  }
48
61
 
49
62
  export interface PagedItems {
@@ -54,6 +67,11 @@ export interface PagedItems {
54
67
  } | undefined;
55
68
  }
56
69
 
70
+ export interface ListControlsInitializeOptions {
71
+ vueRoute: RouteLocationNormalizedLoaded;
72
+ vueRouter: Router;
73
+ }
74
+
57
75
  export interface ActionController {
58
76
  name: string;
59
77
  label: string;
@@ -78,7 +96,7 @@ export interface ActionController {
78
96
  activePanel: ShallowRef<string | null>;
79
97
 
80
98
  // Actions
81
- initialize: () => void;
99
+ initialize: (options: ListControlsInitializeOptions) => void;
82
100
  resetPaging: () => void;
83
101
  setPagination: (updated: ListControlsPagination) => void;
84
102
  setSelectedRows: (selection: ActionTargetItem[]) => void;
@@ -1,3 +1,15 @@
1
+ export interface RequestApi {
2
+ abortControllers: { [key: string]: { abort: AbortController, timestamp: number } };
3
+
4
+ url(url: string): string;
5
+
6
+ call(url: string, options?: RequestCallOptions): Promise<any>;
7
+
8
+ get(url: string, options?: RequestCallOptions): Promise<any>;
9
+
10
+ post(url: string, data?: object, options?: RequestCallOptions): Promise<any>;
11
+ }
12
+
1
13
  export interface HttpResponse {
2
14
  headers: any;
3
15
  data?: any;
@@ -11,3 +23,8 @@ export interface RequestOptions {
11
23
  headers?: object;
12
24
  onUnauthorized?: (response) => object;
13
25
  }
26
+
27
+ export interface RequestCallOptions extends RequestInit {
28
+ abortOn?: string;
29
+ }
30
+