|
1 | | -import { reduceArray, restoreArray } from "@mendix/filter-commons/condition-utils"; |
2 | 1 | import { QueryController } from "@mendix/widget-plugin-grid/query/query-controller"; |
3 | | -import { fnv1aHash } from "@mendix/widget-plugin-grid/utils/fnv-1a-hash"; |
4 | 2 | import { disposeBatch } from "@mendix/widget-plugin-mobx-kit/disposeBatch"; |
5 | 3 | import { ReactiveController, ReactiveControllerHost } from "@mendix/widget-plugin-mobx-kit/reactive-controller"; |
6 | 4 | import { FilterCondition } from "mendix/filters"; |
7 | | -import { makeAutoObservable, reaction } from "mobx"; |
| 5 | +import { reaction } from "mobx"; |
8 | 6 | import { SortInstruction } from "../typings/sorting"; |
9 | 7 |
|
10 | | -interface Columns { |
11 | | - conditions: Array<FilterCondition | undefined>; |
12 | | - sortInstructions: SortInstruction[] | undefined; |
| 8 | +interface ObservableFilterStore { |
| 9 | + filter: FilterCondition | undefined; |
13 | 10 | } |
14 | 11 |
|
15 | | -interface FiltersInput { |
16 | | - conditions: Array<FilterCondition | undefined>; |
| 12 | +interface ObservableSortStore { |
| 13 | + sortInstructions: SortInstruction[] | undefined; |
17 | 14 | } |
18 | 15 |
|
19 | 16 | type DatasourceParamsControllerSpec = { |
20 | 17 | query: QueryController; |
21 | | - columns: Columns; |
22 | | - customFilters: FiltersInput; |
23 | | - widgetName: string; |
24 | | -}; |
25 | | - |
26 | | -type FiltersMeta = { |
27 | | - columnFilters: string; |
28 | | - customFilters: string; |
29 | | - combined: string; |
| 18 | + filterHost: ObservableFilterStore; |
| 19 | + sortHost: ObservableSortStore; |
30 | 20 | }; |
31 | 21 |
|
32 | | -type CondArray = Array<FilterCondition | undefined>; |
33 | | - |
34 | 22 | export class DatasourceParamsController implements ReactiveController { |
35 | | - private columns: Columns; |
36 | 23 | private query: QueryController; |
37 | | - private customFilters: FiltersInput; |
38 | | - readonly widgetName: string; |
| 24 | + private filterHost: ObservableFilterStore; |
| 25 | + private sortHost: ObservableSortStore; |
39 | 26 |
|
40 | 27 | constructor(host: ReactiveControllerHost, spec: DatasourceParamsControllerSpec) { |
41 | 28 | host.addController(this); |
42 | | - this.columns = spec.columns; |
| 29 | + this.filterHost = spec.filterHost; |
| 30 | + this.sortHost = spec.sortHost; |
43 | 31 | this.query = spec.query; |
44 | | - this.customFilters = spec.customFilters; |
45 | | - this.widgetName = spec.widgetName; |
46 | | - |
47 | | - makeAutoObservable(this, { setup: false }); |
48 | | - } |
49 | | - |
50 | | - private get derivedFilter(): { |
51 | | - filter: FilterCondition | undefined; |
52 | | - meta: FiltersMeta; |
53 | | - hash: string | null; |
54 | | - } { |
55 | | - return this.reduceFilters(this.columns.conditions, this.customFilters.conditions); |
56 | | - } |
57 | | - |
58 | | - private get derivedSortOrder(): SortInstruction[] | undefined { |
59 | | - return this.columns.sortInstructions; |
60 | | - } |
61 | | - |
62 | | - reduceFilters( |
63 | | - columnFilters: CondArray, |
64 | | - customFilters: CondArray |
65 | | - ): { |
66 | | - filter: FilterCondition | undefined; |
67 | | - meta: FiltersMeta; |
68 | | - hash: string | null; |
69 | | - } { |
70 | | - const [columnsCond, columnsMeta] = reduceArray(columnFilters); |
71 | | - const [customCond, customMeta] = reduceArray(customFilters); |
72 | | - const [filter, combinedMeta] = reduceArray([columnsCond, customCond]); |
73 | | - |
74 | | - const meta: FiltersMeta = { columnFilters: columnsMeta, customFilters: customMeta, combined: combinedMeta }; |
75 | | - const hash = filter ? DatasourceParamsController.filterHash(filter) : null; |
76 | | - |
77 | | - return { filter, meta, hash }; |
78 | 32 | } |
79 | 33 |
|
80 | 34 | setup(): () => void { |
81 | 35 | const [add, disposeAll] = disposeBatch(); |
82 | 36 | add( |
83 | 37 | reaction( |
84 | | - () => this.derivedSortOrder, |
| 38 | + () => this.sortHost.sortInstructions, |
85 | 39 | sortOrder => this.query.setSortOrder(sortOrder), |
86 | 40 | { fireImmediately: true } |
87 | 41 | ) |
88 | 42 | ); |
89 | 43 | add( |
90 | 44 | reaction( |
91 | | - () => this.derivedFilter, |
92 | | - (next, prev) => { |
93 | | - if (prev && prev.hash) { |
94 | | - this.clearFilterMeta(prev.hash); |
95 | | - } |
96 | | - if (next.hash) { |
97 | | - this.saveFilterMeta(next.hash, next.meta); |
98 | | - } |
99 | | - this.query.setFilter(next.filter); |
100 | | - }, |
| 45 | + () => this.filterHost.filter, |
| 46 | + filter => this.query.setFilter(filter), |
101 | 47 | { fireImmediately: true } |
102 | 48 | ) |
103 | 49 | ); |
104 | 50 |
|
105 | 51 | return disposeAll; |
106 | 52 | } |
107 | | - |
108 | | - dataKey(hash: string): string { |
109 | | - return DatasourceParamsController.storageKey(this.widgetName, hash); |
110 | | - } |
111 | | - |
112 | | - clearFilterMeta(hash: string): void { |
113 | | - sessionStorage.removeItem(this.dataKey(hash)); |
114 | | - } |
115 | | - |
116 | | - saveFilterMeta(hash: string | null, meta: FiltersMeta): void { |
117 | | - if (!hash) { |
118 | | - return; |
119 | | - } |
120 | | - |
121 | | - sessionStorage.setItem(this.dataKey(hash), JSON.stringify(meta)); |
122 | | - } |
123 | | - |
124 | | - readFilterMeta(hash: string): FiltersMeta | null { |
125 | | - const item = sessionStorage.getItem(this.dataKey(hash)); |
126 | | - if (!item) { |
127 | | - return null; |
128 | | - } |
129 | | - try { |
130 | | - return JSON.parse(item) as FiltersMeta; |
131 | | - } catch (e) { |
132 | | - console.error(`DatasourceParamsController.readFilterMeta: Error parsing meta for hash ${hash}`, e); |
133 | | - return null; |
134 | | - } |
135 | | - } |
136 | | - |
137 | | - static filterHash(filter: FilterCondition): string { |
138 | | - return fnv1aHash(JSON.stringify(filter)).toString(); |
139 | | - } |
140 | | - |
141 | | - static storageKey(widgetName: string, hash: string): string { |
142 | | - return `[${widgetName}:${hash}]`; |
143 | | - } |
144 | | - |
145 | | - static restoreMeta(filter: FilterCondition, widgetName: string): FiltersMeta | null { |
146 | | - const hash = this.filterHash(filter); |
147 | | - const key = this.storageKey(widgetName, hash); |
148 | | - const metaJson = sessionStorage.getItem(key); |
149 | | - if (!metaJson) { |
150 | | - return null; |
151 | | - } |
152 | | - return JSON.parse(metaJson) as FiltersMeta; |
153 | | - } |
154 | | - |
155 | | - static unzipFilter( |
156 | | - filter: FilterCondition | undefined, |
157 | | - widgetName: string |
158 | | - ): [columnFilters: Array<FilterCondition | undefined>, customFilters: Array<FilterCondition | undefined>] { |
159 | | - if (!filter) { |
160 | | - return [[], []]; |
161 | | - } |
162 | | - const meta = this.restoreMeta(filter, widgetName); |
163 | | - if (!meta) { |
164 | | - return [[], []]; |
165 | | - } |
166 | | - |
167 | | - const [column, custom] = restoreArray(filter, meta.combined); |
168 | | - const columnFilters = restoreArray(column, meta.columnFilters); |
169 | | - const customFilters = restoreArray(custom, meta.customFilters); |
170 | | - return [columnFilters, customFilters]; |
171 | | - } |
172 | 53 | } |
0 commit comments