@webitel/ui-datalist 1.0.0 → 1.0.1

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.
Files changed (155) hide show
  1. package/Readme.md +19 -0
  2. package/package.json +3 -1
  3. package/src/filter-presets/api/PresetQuery.api.ts +123 -0
  4. package/src/filter-presets/components/_shared/input-fields/preset-description-field.vue +33 -0
  5. package/src/filter-presets/components/_shared/input-fields/preset-name-field.vue +29 -0
  6. package/src/filter-presets/components/_shared/preset-filters-preview.vue +45 -0
  7. package/src/filter-presets/components/apply-preset/apply-preset-action.vue +234 -0
  8. package/src/filter-presets/components/apply-preset/preset-preview.vue +210 -0
  9. package/src/filter-presets/components/save-preset/overwrite-preset-popup.vue +64 -0
  10. package/src/filter-presets/components/save-preset/save-preset-action.vue +139 -0
  11. package/src/filter-presets/components/save-preset/save-preset-popup.vue +136 -0
  12. package/src/filter-presets/index.ts +5 -0
  13. package/src/filter-presets/stores/createFilterPresetsStore.ts +17 -0
  14. package/src/filter-presets/stores/headers/headers.ts +24 -0
  15. package/src/filters/classes/Filter.ts +30 -0
  16. package/src/filters/classes/FilterStorage.ts +34 -0
  17. package/src/filters/classes/FilterStorageOptions.d.ts +6 -0
  18. package/src/filters/classes/FiltersManager.ts +189 -0
  19. package/src/filters/components/config/dynamic-filter-config-form-label.vue +50 -0
  20. package/src/filters/components/config/dynamic-filter-config-form.vue +140 -0
  21. package/src/filters/components/config/dynamic-filter-config-view.vue +40 -0
  22. package/src/filters/components/dynamic-filter-add-action.vue +54 -0
  23. package/src/filters/components/dynamic-filter-panel-wrapper.vue +57 -0
  24. package/src/filters/components/dynamic-filter-search.vue +61 -0
  25. package/src/filters/components/filter-options/_shared/composables/booleanFilterToolkit.ts +39 -0
  26. package/src/filters/components/filter-options/_shared/composables/useFromToSecToPreviewTime.ts +41 -0
  27. package/src/filters/components/filter-options/_shared/date-time-filter/date-time-filter-value-field.vue +56 -0
  28. package/src/filters/components/filter-options/_shared/durations/duration-filter-value-field.vue +84 -0
  29. package/src/filters/components/filter-options/_shared/has-options/has-option-filter-value-field.vue +38 -0
  30. package/src/filters/components/filter-options/_shared/types/BooleanFilter.ts +1 -0
  31. package/src/filters/components/filter-options/actual-reaction-time/actual-reaction-time-filter-value-field.vue +18 -0
  32. package/src/filters/components/filter-options/actual-reaction-time/actual-reaction-time-filter-value-preview.vue +44 -0
  33. package/src/filters/components/filter-options/actual-resolution-time/actual-resolution-time-filter-value-field.vue +18 -0
  34. package/src/filters/components/filter-options/actual-resolution-time/actual-resolution-time-filter-value-preview.vue +44 -0
  35. package/src/filters/components/filter-options/agent/agent-filter-value-field.vue +58 -0
  36. package/src/filters/components/filter-options/agent/agent-filter-value-preview.vue +31 -0
  37. package/src/filters/components/filter-options/agent/config.js +4 -0
  38. package/src/filters/components/filter-options/amd-result/amd-result-filter-value-field.vue +52 -0
  39. package/src/filters/components/filter-options/amd-result/amd-result-filter-value-preview.vue +18 -0
  40. package/src/filters/components/filter-options/assignee/assignee-filter-value-field.vue +74 -0
  41. package/src/filters/components/filter-options/assignee/assignee-filter-value-preview.vue +36 -0
  42. package/src/filters/components/filter-options/assignee/config.js +4 -0
  43. package/src/filters/components/filter-options/author/author-filter-value-field.vue +56 -0
  44. package/src/filters/components/filter-options/author/author-filter-value-preview.vue +31 -0
  45. package/src/filters/components/filter-options/author/config.js +4 -0
  46. package/src/filters/components/filter-options/cause/cause-filter-value-field.vue +52 -0
  47. package/src/filters/components/filter-options/cause/cause-filter-value-preview.vue +18 -0
  48. package/src/filters/components/filter-options/close-reason-groups-case/close-reason-groups-case-filter-value-field.vue +102 -0
  49. package/src/filters/components/filter-options/close-reason-groups-case/close-reason-groups-case-filter-value-preview.vue +34 -0
  50. package/src/filters/components/filter-options/close-reason-groups-case/config.js +7 -0
  51. package/src/filters/components/filter-options/contact/config.js +4 -0
  52. package/src/filters/components/filter-options/contact/contact-filter-value-field.vue +56 -0
  53. package/src/filters/components/filter-options/contact/contact-filter-value-preview.vue +31 -0
  54. package/src/filters/components/filter-options/contact-group/config.js +4 -0
  55. package/src/filters/components/filter-options/contact-group/contact-group-filter-value-field.vue +74 -0
  56. package/src/filters/components/filter-options/contact-group/contact-group-filter-value-preview.vue +38 -0
  57. package/src/filters/components/filter-options/created-at-from/created-at-from-filter-value-field.vue +24 -0
  58. package/src/filters/components/filter-options/created-at-from/created-at-from-filter-value-preview.vue +15 -0
  59. package/src/filters/components/filter-options/created-at-to/created-at-to-filter-value-field.vue +24 -0
  60. package/src/filters/components/filter-options/created-at-to/created-at-to-filter-value-preview.vue +15 -0
  61. package/src/filters/components/filter-options/direction/direction-filter-value-field.vue +51 -0
  62. package/src/filters/components/filter-options/direction/direction-filter-value-preview.vue +17 -0
  63. package/src/filters/components/filter-options/gateway/config.js +4 -0
  64. package/src/filters/components/filter-options/gateway/gateway-filter-value-field.vue +56 -0
  65. package/src/filters/components/filter-options/gateway/gateway-filter-value-preview.vue +31 -0
  66. package/src/filters/components/filter-options/grantee/config.js +4 -0
  67. package/src/filters/components/filter-options/grantee/grantee-filter-value-field.vue +56 -0
  68. package/src/filters/components/filter-options/grantee/grantee-filter-value-preview.vue +31 -0
  69. package/src/filters/components/filter-options/has-attachment/has-attachment-filter-value-field.vue +43 -0
  70. package/src/filters/components/filter-options/has-attachment/has-attachment-filter-value-preview.vue +24 -0
  71. package/src/filters/components/filter-options/has-file/has-file-filter-value-field.vue +33 -0
  72. package/src/filters/components/filter-options/has-file/has-file-filter-value-preview.vue +15 -0
  73. package/src/filters/components/filter-options/has-rating/has-rating-filter-value-field.vue +33 -0
  74. package/src/filters/components/filter-options/has-rating/has-rating-filter-value-preview.vue +15 -0
  75. package/src/filters/components/filter-options/has-transcription/has-transcription-filter-value-field.vue +33 -0
  76. package/src/filters/components/filter-options/has-transcription/has-transcription-filter-value-preview.vue +15 -0
  77. package/src/filters/components/filter-options/impacted/config.js +4 -0
  78. package/src/filters/components/filter-options/impacted/impacted-filter-value-field.vue +56 -0
  79. package/src/filters/components/filter-options/impacted/impacted-filter-value-preview.vue +31 -0
  80. package/src/filters/components/filter-options/index.ts +250 -0
  81. package/src/filters/components/filter-options/priority-case/config.js +4 -0
  82. package/src/filters/components/filter-options/priority-case/priority-case-filter-value-field.vue +57 -0
  83. package/src/filters/components/filter-options/priority-case/priority-case-filter-value-preview.vue +31 -0
  84. package/src/filters/components/filter-options/queue/config.js +4 -0
  85. package/src/filters/components/filter-options/queue/queue-filter-value-field.vue +56 -0
  86. package/src/filters/components/filter-options/queue/queue-filter-value-preview.vue +31 -0
  87. package/src/filters/components/filter-options/rated-by/config.js +4 -0
  88. package/src/filters/components/filter-options/rated-by/rated-by-filter-value-field.vue +56 -0
  89. package/src/filters/components/filter-options/rated-by/rated-by-filter-value-preview.vue +31 -0
  90. package/src/filters/components/filter-options/rating/rating-from-to-filter-value-field.vue +101 -0
  91. package/src/filters/components/filter-options/rating/rating-from-to-filter-value-preview.vue +39 -0
  92. package/src/filters/components/filter-options/reaction-time/reaction-time-filter-value-field.vue +18 -0
  93. package/src/filters/components/filter-options/reaction-time/reaction-time-filter-value-preview.vue +44 -0
  94. package/src/filters/components/filter-options/reporter/config.js +4 -0
  95. package/src/filters/components/filter-options/reporter/reporter-filter-value-field.vue +56 -0
  96. package/src/filters/components/filter-options/reporter/reporter-filter-value-preview.vue +31 -0
  97. package/src/filters/components/filter-options/resolution-time/resolution-time-filter-value-field.vue +18 -0
  98. package/src/filters/components/filter-options/resolution-time/resolution-time-filter-value-preview.vue +44 -0
  99. package/src/filters/components/filter-options/score/score-from-to-filter-value-field.vue +100 -0
  100. package/src/filters/components/filter-options/score/score-from-to-filter-value-preview.vue +39 -0
  101. package/src/filters/components/filter-options/service-case/config.js +6 -0
  102. package/src/filters/components/filter-options/service-case/service-case-filter-value-field.vue +82 -0
  103. package/src/filters/components/filter-options/service-case/service-case-filter-value-preview.vue +34 -0
  104. package/src/filters/components/filter-options/sla/config.js +4 -0
  105. package/src/filters/components/filter-options/sla/sla-filter-value-field.vue +57 -0
  106. package/src/filters/components/filter-options/sla/sla-filter-value-preview.vue +31 -0
  107. package/src/filters/components/filter-options/sla-condition/config.js +6 -0
  108. package/src/filters/components/filter-options/sla-condition/sla-condition-filter-value-field.vue +98 -0
  109. package/src/filters/components/filter-options/sla-condition/sla-condition-filter-value-preview.vue +37 -0
  110. package/src/filters/components/filter-options/source-case/config.js +4 -0
  111. package/src/filters/components/filter-options/source-case/source-case-filter-value-field.vue +57 -0
  112. package/src/filters/components/filter-options/source-case/source-case-filter-value-preview.vue +31 -0
  113. package/src/filters/components/filter-options/status-case/config.js +7 -0
  114. package/src/filters/components/filter-options/status-case/status-case-filter-value-field.vue +102 -0
  115. package/src/filters/components/filter-options/status-case/status-case-filter-value-preview.vue +37 -0
  116. package/src/filters/components/filter-options/tag/tag-filter-value-field.vue +52 -0
  117. package/src/filters/components/filter-options/tag/tag-filter-value-preview.vue +38 -0
  118. package/src/filters/components/filter-options/talk-duration/TalkDurationFilter.d.ts +4 -0
  119. package/src/filters/components/filter-options/talk-duration/talk-duration-filter-value-field.vue +19 -0
  120. package/src/filters/components/filter-options/talk-duration/talk-duration-filter-value-preview.vue +44 -0
  121. package/src/filters/components/filter-options/team/config.js +4 -0
  122. package/src/filters/components/filter-options/team/team-filter-value-field.vue +56 -0
  123. package/src/filters/components/filter-options/team/team-filter-value-preview.vue +31 -0
  124. package/src/filters/components/filter-options/total-duration/TotalDurationFilter.d.ts +4 -0
  125. package/src/filters/components/filter-options/total-duration/total-duration-filter-value-field.vue +19 -0
  126. package/src/filters/components/filter-options/total-duration/total-duration-filter-value-preview.vue +44 -0
  127. package/src/filters/components/filter-options/user/config.js +4 -0
  128. package/src/filters/components/filter-options/user/user-filter-value-field.vue +56 -0
  129. package/src/filters/components/filter-options/user/user-filter-value-preview.vue +31 -0
  130. package/src/filters/components/filter-options/variable/variable-filter-value-field.vue +50 -0
  131. package/src/filters/components/filter-options/variable/variable-filter-value-preview.vue +39 -0
  132. package/src/filters/components/preview/dynamic-filter-preview-info.vue +35 -0
  133. package/src/filters/components/preview/dynamic-filter-preview.vue +76 -0
  134. package/src/filters/components/table-filters-panel.vue +87 -0
  135. package/src/filters/createTableFiltersStore.ts +81 -0
  136. package/src/filters/enums/FilterOption.ts +43 -0
  137. package/src/filters/enums/amd-result-options.ts +38 -0
  138. package/src/filters/enums/boolean-options.ts +16 -0
  139. package/src/filters/enums/direction-options.ts +20 -0
  140. package/src/filters/enums/hangup-cause-options.ts +265 -0
  141. package/src/filters/enums/tag-options.ts +8 -0
  142. package/src/filters/index.ts +27 -0
  143. package/src/filters/scripts/utils.ts +31 -0
  144. package/src/filters/types/Filter.d.ts +46 -0
  145. package/src/filters/types/FiltersManager.d.ts +76 -0
  146. package/src/headers/createTableHeadersStore.ts +140 -0
  147. package/src/index.d.ts +0 -0
  148. package/src/index.ts +3 -0
  149. package/src/pagination/createTablePaginationStore.ts +64 -0
  150. package/src/persist/PersistedStorage.types.ts +51 -0
  151. package/src/persist/useLocalStoragePersistedStorage.ts +37 -0
  152. package/src/persist/usePersistedStorage.ts +151 -0
  153. package/src/persist/useRoutePersistedStorage.ts +41 -0
  154. package/src/table/createTableStore.store.ts +206 -0
  155. package/src/types/tableStore.types.ts +61 -0
@@ -0,0 +1,64 @@
1
+ import { defineStore } from 'pinia';
2
+ import { ref } from 'vue';
3
+
4
+ import { usePersistedStorage } from '../persist/usePersistedStorage.ts';
5
+
6
+ export const createTablePaginationStore = (namespace: string) => {
7
+ const id = `${namespace}/pagination`;
8
+
9
+ return defineStore(id, () => {
10
+ const page = ref(1);
11
+ const size = ref(10);
12
+ const next = ref(false);
13
+
14
+ const updatePage = (newPage: number) => {
15
+ page.value = newPage;
16
+ };
17
+
18
+ const updateSize = (newSize: number) => {
19
+ size.value = newSize;
20
+ };
21
+
22
+ const $reset = () => {
23
+ page.value = 1;
24
+ size.value = 10;
25
+ next.value = false;
26
+ };
27
+
28
+ const setupPersistence = () => {
29
+ const { restore: restorePage } = usePersistedStorage({
30
+ name: 'page',
31
+ value: page,
32
+ onRestore: async (restore, name) => {
33
+ const value = await restore(name);
34
+ const numValue = +value;
35
+ if (numValue) page.value = numValue;
36
+ },
37
+ });
38
+
39
+ const { restore: restoreSize } = usePersistedStorage({
40
+ name: 'size',
41
+ value: size,
42
+ onRestore: async (restore, name) => {
43
+ const value = await restore(name);
44
+ const numValue = +value;
45
+ if (numValue) size.value = numValue;
46
+ },
47
+ });
48
+
49
+ return Promise.allSettled([restorePage(), restoreSize()]);
50
+ };
51
+
52
+ return {
53
+ page,
54
+ size,
55
+ next,
56
+
57
+ updatePage,
58
+ updateSize,
59
+
60
+ setupPersistence,
61
+ $reset,
62
+ };
63
+ });
64
+ };
@@ -0,0 +1,51 @@
1
+ import { Ref, WatchOptions } from 'vue';
2
+
3
+ export enum PersistedStorageType {
4
+ LocalStorage = 'localStorage',
5
+ Route = 'route',
6
+ }
7
+
8
+ // in route query, or in localStorage
9
+ export type PersistStorableValue = string;
10
+
11
+ export type PersistableValue =
12
+ | PersistStorableValue
13
+ | { toString: () => PersistStorableValue };
14
+
15
+ export interface StorageLike {
16
+ getItem(key: string): Promise<PersistableValue | null>;
17
+
18
+ setItem(key: string, value: PersistableValue): Promise<void>;
19
+
20
+ removeItem(key: string): Promise<void>;
21
+ }
22
+
23
+ export interface PersistedPropertyConfig {
24
+ name: string;
25
+ value: Ref<PersistableValue>;
26
+ storages?: PersistedStorageType | PersistedStorageType[];
27
+ storagePath?: string;
28
+ startWatchManually?: boolean;
29
+ watchConfig?: WatchOptions;
30
+ onStore?: (
31
+ save: ({
32
+ name,
33
+ value,
34
+ }: {
35
+ name: string;
36
+ value: PersistableValue;
37
+ }) => Promise<void>,
38
+ { value, name },
39
+ ) => Promise<void>;
40
+ onRestore?: (
41
+ restore: (name: string) => Promise<PersistableValue>,
42
+ name: string,
43
+ ) => Promise<void>;
44
+ }
45
+
46
+ export interface PersistedStorageController {
47
+ watch: () => void;
48
+ unwatch: () => void;
49
+ restore: () => Promise<void>;
50
+ reset: () => Promise<void>;
51
+ }
@@ -0,0 +1,37 @@
1
+ import { StorageLike } from './PersistedStorage.types.ts';
2
+
3
+ const separator = ';';
4
+
5
+ const makePath = (storagePath: string, key: string) => `${storagePath}/${key}`;
6
+
7
+ export const useLocalStoragePersistedStorage = ({
8
+ storagePath = '',
9
+ }: {
10
+ storagePath: string;
11
+ }): StorageLike => {
12
+ const getItem = async (key: string) => {
13
+ const value = localStorage.getItem(makePath(storagePath, key));
14
+ try {
15
+ return value.split(separator).join();
16
+ } catch {
17
+ return value;
18
+ }
19
+ };
20
+
21
+ const setItem = async (key: string, inputValue: string | string[]) => {
22
+ const value = Array.isArray(inputValue)
23
+ ? inputValue.join(separator)
24
+ : inputValue;
25
+ localStorage.setItem(makePath(storagePath, key), value);
26
+ };
27
+
28
+ const removeItem = async (key: string) => {
29
+ localStorage.removeItem(makePath(storagePath, key));
30
+ };
31
+
32
+ return {
33
+ getItem,
34
+ setItem,
35
+ removeItem,
36
+ };
37
+ };
@@ -0,0 +1,151 @@
1
+ import { watch } from 'vue';
2
+
3
+ import {
4
+ PersistableValue,
5
+ PersistedPropertyConfig,
6
+ PersistedStorageController,
7
+ PersistedStorageType,
8
+ } from './PersistedStorage.types.ts';
9
+ import { useLocalStoragePersistedStorage } from './useLocalStoragePersistedStorage.ts';
10
+ import { useRoutePersistedStorage } from './useRoutePersistedStorage.ts';
11
+
12
+ export const usePersistedStorage = ({
13
+ name,
14
+ value,
15
+ storages: configStorages = [PersistedStorageType.Route],
16
+ storagePath,
17
+ startWatchManually = false,
18
+ onStore,
19
+ onRestore,
20
+ }: PersistedPropertyConfig): PersistedStorageController => {
21
+ let unwatch = null;
22
+
23
+ const setItemFns = [];
24
+ const getItemFns: Array<(name: string) => Promise<PersistableValue>> = [];
25
+ const removeItemFns = [];
26
+
27
+ const composedValueGetter = async (
28
+ name: string,
29
+ ): Promise<PersistableValue[]> => {
30
+ const settledResults = await Promise.allSettled(
31
+ getItemFns.map((getter) => getter(name)),
32
+ );
33
+
34
+ return settledResults.reduce((acc, result) => {
35
+ if (result.status === 'fulfilled') {
36
+ return [...acc, result.value];
37
+ }
38
+ return acc;
39
+ }, []);
40
+ };
41
+
42
+ const storages = Array.isArray(configStorages)
43
+ ? configStorages
44
+ : [configStorages];
45
+
46
+ /*
47
+ order matters, as the first storage in the list has the highest priority
48
+ */
49
+ if (storages.includes(PersistedStorageType.Route)) {
50
+ const { setItem, getItem, removeItem } = useRoutePersistedStorage();
51
+ setItemFns.push(setItem);
52
+ getItemFns.push(getItem);
53
+ removeItemFns.push(removeItem);
54
+ }
55
+
56
+ if (storages.includes(PersistedStorageType.LocalStorage)) {
57
+ const { setItem, getItem, removeItem } = useLocalStoragePersistedStorage({
58
+ storagePath,
59
+ });
60
+ setItemFns.push(setItem);
61
+ getItemFns.push(getItem);
62
+ removeItemFns.push(removeItem);
63
+ }
64
+
65
+ const startWatch = () => {
66
+ unwatch = watch(
67
+ value,
68
+ async () => {
69
+ /*
70
+ if onStore callback is provided,
71
+ call custom logic for storing value
72
+ */
73
+ if (onStore) {
74
+ /*
75
+ wrap all setItemFns in one callback
76
+ so that onStore is called only once on each value change
77
+ */
78
+ const save = async ({ name, value: storedValue }) => {
79
+ setItemFns.forEach((setter) => {
80
+ setter(name, storedValue);
81
+ });
82
+ };
83
+ await onStore(save, { name, value });
84
+ } else {
85
+ /*
86
+ else, perform default storing logic
87
+ */
88
+ const storedValue = value.value;
89
+ setItemFns.forEach((setter) => {
90
+ setter(name, storedValue);
91
+ });
92
+ }
93
+ },
94
+ { deep: true },
95
+ );
96
+ };
97
+
98
+ const restore = async () => {
99
+ /*
100
+ if onRestore callback is provided,
101
+ call custom logic for restoring value
102
+ */
103
+ if (onRestore) {
104
+ /*
105
+ wrap all getItemFns in one callback
106
+ so that onRestore is called only once on each value change
107
+ */
108
+ const restore = async (name: string) => {
109
+ const restoredValues = await composedValueGetter(name);
110
+ /*
111
+ not sure if value to restore should be picked automatically
112
+ before running onRestore
113
+ */
114
+ return restoredValues.find((value) => {
115
+ return value != null;
116
+ });
117
+ };
118
+ await onRestore(restore, name);
119
+ } else {
120
+ /*
121
+ else, perform default restoring logic
122
+ */
123
+ const restoredValues = await composedValueGetter(name);
124
+ const restoredValue = restoredValues.find((value) => value !== null);
125
+
126
+ if (restoredValue !== undefined) {
127
+ value.value = restoredValue;
128
+ }
129
+ }
130
+ /*
131
+ start watching after restoring value to prevent restored value
132
+ from storing again
133
+ */
134
+ if (!startWatchManually) {
135
+ startWatch();
136
+ }
137
+ };
138
+
139
+ const reset = async () => {
140
+ await Promise.all(removeItemFns.map((removeItem) => removeItem(name)));
141
+ };
142
+
143
+ const endWatch = () => unwatch && unwatch();
144
+
145
+ return {
146
+ watch: startWatch,
147
+ unwatch: endWatch,
148
+ restore,
149
+ reset,
150
+ };
151
+ };
@@ -0,0 +1,41 @@
1
+ import { useRoute, useRouter } from 'vue-router';
2
+
3
+ import { StorageLike } from './PersistedStorage.types.ts';
4
+
5
+ export const useRoutePersistedStorage = (): StorageLike => {
6
+ const router = useRouter();
7
+ const route = useRoute();
8
+
9
+ const getItem = async (key: string) => {
10
+ return route.query[key];
11
+ };
12
+
13
+ const setItem = async (key: string, value: string | string[]) => {
14
+ await router.replace({
15
+ name: route.name,
16
+ params: route.params,
17
+ hash: route.hash,
18
+ query: {
19
+ ...route.query,
20
+ [key]: value,
21
+ },
22
+ });
23
+ };
24
+
25
+ const removeItem = async (key: string) => {
26
+ const query = { ...route.query };
27
+ delete query[key];
28
+ await router.replace({
29
+ name: route.name,
30
+ params: route.params,
31
+ hash: route.hash,
32
+ query,
33
+ });
34
+ };
35
+
36
+ return {
37
+ getItem,
38
+ setItem,
39
+ removeItem,
40
+ };
41
+ };
@@ -0,0 +1,206 @@
1
+ import set from 'lodash/fp/set';
2
+ import { defineStore, storeToRefs } from 'pinia';
3
+ import { type Ref, ref, watch } from 'vue';
4
+
5
+ import { createTableFiltersStore } from '../filters/createTableFiltersStore.ts';
6
+ import { createTableHeadersStore } from '../headers/createTableHeadersStore.ts';
7
+ import { createTablePaginationStore } from '../pagination/createTablePaginationStore.ts';
8
+ import {
9
+ PatchItemPropertyParams,
10
+ TableStore,
11
+ useTableStoreParams,
12
+ } from '../types/tableStore.types.ts';
13
+
14
+ export const createTableStore = <Entity extends { id: string; etag?: string }>(
15
+ namespace: string,
16
+ { apiModule, headers, disablePersistence }: useTableStoreParams<Entity>,
17
+ ) => {
18
+ const usePaginationStore = createTablePaginationStore(namespace);
19
+ const useHeadersStore = createTableHeadersStore(namespace, { headers });
20
+ const useFiltersStore = createTableFiltersStore(namespace);
21
+
22
+ return defineStore(namespace, (): TableStore<Entity> => {
23
+ const parentId = ref();
24
+
25
+ const paginationStore = usePaginationStore();
26
+ const { page, size, next } = storeToRefs(paginationStore);
27
+ const {
28
+ updatePage,
29
+ updateSize,
30
+ // $reset: $resetPaginationStore,
31
+ $patch: $patchPaginationStore,
32
+ setupPersistence: setupPaginationPersistence,
33
+ } = paginationStore;
34
+
35
+ const headersStore = useHeadersStore();
36
+ const { headers, shownHeaders, fields, sort } = storeToRefs(headersStore);
37
+ const {
38
+ updateSort,
39
+ updateShownHeaders,
40
+ setupPersistence: setupHeadersPersistence,
41
+ } = headersStore;
42
+
43
+ const filtersStore = useFiltersStore();
44
+ const { filtersManager, isRestoring: isFiltersRestoring } =
45
+ storeToRefs(filtersStore);
46
+ const {
47
+ hasFilter,
48
+ addFilter,
49
+ updateFilter,
50
+ deleteFilter,
51
+ setupPersistence: setupFiltersPersistence,
52
+ } = filtersStore;
53
+
54
+ const dataList: Ref<Entity[]> = ref([]);
55
+ const selected: Ref<Entity[]> = ref([]);
56
+ const error = ref(null);
57
+ const isLoading = ref(false);
58
+
59
+ const updateSelected = (value: Entity[]) => {
60
+ selected.value = value;
61
+ };
62
+
63
+ const loadDataList = async () => {
64
+ isLoading.value = true;
65
+ $patchPaginationStore({ next: false });
66
+
67
+ const params = {
68
+ ...filtersManager.value.getAllValues(),
69
+ page: page.value,
70
+ size: size.value,
71
+ sort: sort.value,
72
+ fields: fields.value,
73
+ parentId: parentId.value,
74
+ };
75
+
76
+ try {
77
+ const { items, next } = await apiModule.getList(params);
78
+
79
+ dataList.value = items;
80
+ updateSelected([]);
81
+ $patchPaginationStore({ next });
82
+ } catch (err) {
83
+ error.value = err;
84
+ throw err;
85
+ } finally {
86
+ isLoading.value = false;
87
+ }
88
+ };
89
+
90
+ const patchItemProperty = async ({
91
+ index,
92
+ path,
93
+ value,
94
+ }: PatchItemPropertyParams) => {
95
+ const item = dataList.value[index];
96
+ const changes = {};
97
+ set(path, value, changes);
98
+
99
+ try {
100
+ await apiModule.patch({
101
+ changes,
102
+ parentId: parentId.value,
103
+ id: item.id,
104
+ etag: item.etag,
105
+ });
106
+ set(path, value, item);
107
+ } catch (err) {
108
+ await loadDataList();
109
+ throw err;
110
+ }
111
+ };
112
+
113
+ const deleteEls = async (_els: Entity[]) => {
114
+ const els = Array.isArray(_els) ? _els : [_els];
115
+ const deleteEl = (el: Entity) => {
116
+ return apiModule.delete({
117
+ id: el.id,
118
+ etag: el.etag,
119
+ parentId: parentId.value,
120
+ });
121
+ };
122
+
123
+ try {
124
+ await Promise.all(els.map(deleteEl));
125
+ } finally {
126
+ await loadDataList();
127
+ }
128
+ };
129
+
130
+ const initialize = async ({
131
+ parentId: storeParentId,
132
+ }: { parentId?: string | number } = {}) => {
133
+ if (storeParentId) {
134
+ parentId.value = storeParentId;
135
+ }
136
+
137
+ if (!disablePersistence) {
138
+ await Promise.allSettled([
139
+ setupPaginationPersistence(),
140
+ setupFiltersPersistence(),
141
+ setupHeadersPersistence(),
142
+ ]);
143
+ }
144
+
145
+ let loadingAfterFiltersChange = false;
146
+
147
+ watch(
148
+ [() => filtersManager.value.getAllValues(), sort, fields, size],
149
+ async () => {
150
+ loadingAfterFiltersChange = true;
151
+ updatePage(1);
152
+ await loadDataList();
153
+ loadingAfterFiltersChange = false;
154
+ },
155
+ /* filtersManager requires deep watching for its values */
156
+ { deep: true },
157
+ );
158
+
159
+ watch([page], () => {
160
+ if (!loadingAfterFiltersChange) {
161
+ return loadDataList();
162
+ }
163
+ });
164
+
165
+ return loadDataList();
166
+ };
167
+
168
+ return {
169
+ dataList,
170
+ selected,
171
+ error,
172
+ isLoading,
173
+
174
+ page,
175
+ size,
176
+ next,
177
+
178
+ headers,
179
+ shownHeaders,
180
+ fields,
181
+ sort,
182
+
183
+ filtersManager,
184
+ isFiltersRestoring,
185
+
186
+ initialize,
187
+
188
+ loadDataList,
189
+
190
+ updateSelected,
191
+ patchItemProperty,
192
+ deleteEls,
193
+
194
+ updatePage,
195
+ updateSize,
196
+
197
+ updateSort,
198
+ updateShownHeaders,
199
+
200
+ hasFilter,
201
+ addFilter,
202
+ updateFilter,
203
+ deleteFilter,
204
+ };
205
+ });
206
+ };
@@ -0,0 +1,61 @@
1
+ import type { Ref } from 'vue';
2
+
3
+ import { ApiModule } from '../../../../api/types/ApiModule.type.ts';
4
+ import { IFiltersManager } from '../filters';
5
+
6
+ export interface useTableStoreParams<Entity> {
7
+ apiModule: ApiModule<Entity>;
8
+ headers: [];
9
+ disablePersistence?: boolean | [];
10
+ // etagMode: boolean;
11
+ }
12
+
13
+ export interface PatchItemPropertyParams {
14
+ index: number;
15
+ path: string;
16
+ value: unknown;
17
+ }
18
+
19
+ export interface TableStore<Entity> {
20
+ // tableStore
21
+ dataList: Ref<Entity[]>;
22
+ selected: Ref<Entity[]>;
23
+ error: Ref<Error | null>;
24
+ isLoading: Ref<boolean>;
25
+
26
+ // paginationStore
27
+ page: Ref<number>;
28
+ size: Ref<number>;
29
+ next: Ref<boolean>;
30
+
31
+ // headersStore
32
+ headers: Ref<[]>;
33
+ shownHeaders: Ref<[]>;
34
+ fields: Ref<[]>;
35
+ sort: Ref<string>;
36
+
37
+ // filtersStore
38
+ filtersManager: Ref<IFiltersManager>;
39
+ isFiltersRestoring: Ref<boolean>;
40
+
41
+ // tableStore
42
+ initialize: () => Promise<void>;
43
+ loadDataList: (query?: object) => Promise<void>;
44
+ updateSelected: (selected: Entity[]) => void;
45
+ patchItemProperty: (payload: PatchItemPropertyParams) => Promise<void>;
46
+ deleteEls: (deleted: Entity[]) => Promise<void>;
47
+
48
+ // paginationStore
49
+ updatePage: (page: number) => void;
50
+ updateSize: (size: number) => void;
51
+
52
+ // headersStore
53
+ updateSort: (column: object) => void;
54
+ updateShownHeaders: () => void;
55
+
56
+ // filtersStore
57
+ hasFilter: IFiltersManager['hasFilter'];
58
+ addFilter: IFiltersManager['addFilter'];
59
+ updateFilter: IFiltersManager['updateFilter'];
60
+ deleteFilter: IFiltersManager['deleteFilter'];
61
+ }