Skip to content

Commit 0818cfc

Browse files
committed
feat: finish "clean" xpath feature
1 parent c2e50fc commit 0818cfc

File tree

15 files changed

+110
-231
lines changed

15 files changed

+110
-231
lines changed

packages/pluggableWidgets/datagrid-dropdown-filter-web/src/hocs/withLinkedRefStore.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ class RefStoreProvider extends BaseStoreProvider<RefFilterStore> {
106106
this.dataKey = gate.props.name;
107107
this._store = new RefFilterStore({
108108
gate,
109-
initCond: this.findInitFilter(filterAPI.sharedInitFilter, this.dataKey)
109+
initCond: null
110110
});
111111
}
112112

packages/pluggableWidgets/datagrid-web/src/components/WidgetHeaderContext.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ const FilterContext = getGlobalFilterContextObject();
1919
function HeaderContainer(props: WidgetHeaderContextProps): ReactElement {
2020
const selectionContext = useCreateSelectionContextValue(props.selectionHelper);
2121
return (
22-
<FilterContext.Provider value={props.rootStore.autonomousFilterAPI}>
22+
<FilterContext.Provider value={props.rootStore.filterAPI}>
2323
<SelectionContext.Provider value={selectionContext}>{props.children}</SelectionContext.Provider>
2424
</FilterContext.Provider>
2525
);
Lines changed: 14 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -1,172 +1,53 @@
1-
import { reduceArray, restoreArray } from "@mendix/filter-commons/condition-utils";
21
import { QueryController } from "@mendix/widget-plugin-grid/query/query-controller";
3-
import { fnv1aHash } from "@mendix/widget-plugin-grid/utils/fnv-1a-hash";
42
import { disposeBatch } from "@mendix/widget-plugin-mobx-kit/disposeBatch";
53
import { ReactiveController, ReactiveControllerHost } from "@mendix/widget-plugin-mobx-kit/reactive-controller";
64
import { FilterCondition } from "mendix/filters";
7-
import { makeAutoObservable, reaction } from "mobx";
5+
import { reaction } from "mobx";
86
import { SortInstruction } from "../typings/sorting";
97

10-
interface Columns {
11-
conditions: Array<FilterCondition | undefined>;
12-
sortInstructions: SortInstruction[] | undefined;
8+
interface ObservableFilterStore {
9+
filter: FilterCondition | undefined;
1310
}
1411

15-
interface FiltersInput {
16-
conditions: Array<FilterCondition | undefined>;
12+
interface ObservableSortStore {
13+
sortInstructions: SortInstruction[] | undefined;
1714
}
1815

1916
type DatasourceParamsControllerSpec = {
2017
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;
3020
};
3121

32-
type CondArray = Array<FilterCondition | undefined>;
33-
3422
export class DatasourceParamsController implements ReactiveController {
35-
private columns: Columns;
3623
private query: QueryController;
37-
private customFilters: FiltersInput;
38-
readonly widgetName: string;
24+
private filterHost: ObservableFilterStore;
25+
private sortHost: ObservableSortStore;
3926

4027
constructor(host: ReactiveControllerHost, spec: DatasourceParamsControllerSpec) {
4128
host.addController(this);
42-
this.columns = spec.columns;
29+
this.filterHost = spec.filterHost;
30+
this.sortHost = spec.sortHost;
4331
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 };
7832
}
7933

8034
setup(): () => void {
8135
const [add, disposeAll] = disposeBatch();
8236
add(
8337
reaction(
84-
() => this.derivedSortOrder,
38+
() => this.sortHost.sortInstructions,
8539
sortOrder => this.query.setSortOrder(sortOrder),
8640
{ fireImmediately: true }
8741
)
8842
);
8943
add(
9044
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),
10147
{ fireImmediately: true }
10248
)
10349
);
10450

10551
return disposeAll;
10652
}
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-
}
17253
}

packages/pluggableWidgets/datagrid-web/src/helpers/state/ColumnGroupStore.ts

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1+
import { reduceArray, restoreArray } from "@mendix/filter-commons/condition-utils";
12
import { FiltersSettingsMap } from "@mendix/filter-commons/typings/settings";
3+
import { ConditionWithMeta } from "@mendix/widget-plugin-filtering/typings/ConditionWithMeta";
4+
import { ObservableFilterHost } from "@mendix/widget-plugin-filtering/typings/ObservableFilterHost";
25
import { disposeBatch } from "@mendix/widget-plugin-mobx-kit/disposeBatch";
3-
import { FilterCondition } from "mendix/filters";
6+
47
import { action, computed, makeObservable, observable } from "mobx";
58
import { DatagridContainerProps } from "../../../typings/DatagridProps";
69
import { ColumnId, GridColumn } from "../../typings/GridColumn";
@@ -13,7 +16,7 @@ import {
1316
sortInstructionsToSortRules,
1417
sortRulesToSortInstructions
1518
} from "./ColumnsSortingStore";
16-
import { ColumnFilterStore, ObserverBag } from "./column/ColumnFilterStore";
19+
import { ColumnFilterStore } from "./column/ColumnFilterStore";
1720
import { ColumnStore } from "./column/ColumnStore";
1821

1922
export interface IColumnGroupStore {
@@ -40,24 +43,24 @@ export class ColumnGroupStore implements IColumnGroupStore, IColumnParentStore {
4043

4144
readonly columnFilters: ColumnFilterStore[];
4245

46+
readonly metaKey = "ColumnGroupStore";
47+
4348
sorting: ColumnsSortingStore;
4449
isResizing = false;
4550

4651
constructor(
4752
props: Pick<DatagridContainerProps, "columns" | "datasource">,
4853
info: StaticInfo,
49-
initFilter: Array<FilterCondition | undefined>,
50-
observerBag: ObserverBag
54+
filterHost: ObservableFilterHost
5155
) {
5256
this._allColumns = [];
5357
this.columnFilters = [];
5458

5559
props.columns.forEach((columnProps, i) => {
56-
const initCond = initFilter.at(i) ?? null;
5760
const column = new ColumnStore(i, columnProps, this);
5861
this._allColumnsById.set(column.columnId, column);
5962
this._allColumns[i] = column;
60-
this.columnFilters[i] = new ColumnFilterStore(columnProps, info, initCond, observerBag);
63+
this.columnFilters[i] = new ColumnFilterStore(columnProps, info, filterHost);
6164
});
6265

6366
this.sorting = new ColumnsSortingStore(
@@ -72,13 +75,14 @@ export class ColumnGroupStore implements IColumnGroupStore, IColumnParentStore {
7275
_allColumnsOrdered: computed,
7376
availableColumns: computed,
7477
visibleColumns: computed,
75-
conditions: computed.struct,
78+
condWithMeta: computed,
7679
columnSettings: computed.struct,
7780
filterSettings: computed({ keepAlive: true }),
7881
updateProps: action,
7982
setIsResizing: action,
8083
swapColumns: action,
81-
setColumnSettings: action
84+
setColumnSettings: action,
85+
hydrate: action
8286
});
8387
}
8488

@@ -142,12 +146,6 @@ export class ColumnGroupStore implements IColumnGroupStore, IColumnParentStore {
142146
return [...this.availableColumns].filter(column => !column.isHidden);
143147
}
144148

145-
get conditions(): Array<FilterCondition | undefined> {
146-
return this.columnFilters.map((store, index) => {
147-
return this._allColumns[index].isHidden ? undefined : store.condition;
148-
});
149-
}
150-
151149
get sortInstructions(): SortInstruction[] | undefined {
152150
return sortRulesToSortInstructions(this.sorting.rules, this._allColumns);
153151
}
@@ -194,4 +192,21 @@ export class ColumnGroupStore implements IColumnGroupStore, IColumnParentStore {
194192
isLastVisible(column: ColumnStore): boolean {
195193
return this.visibleColumns.at(-1) === column;
196194
}
195+
196+
get condWithMeta(): ConditionWithMeta {
197+
const conditions = this.columnFilters.map((store, index) => {
198+
return this._allColumns[index].isHidden ? undefined : store.condition;
199+
});
200+
const [cond, meta] = reduceArray(conditions);
201+
return { cond, meta };
202+
}
203+
204+
hydrate({ cond, meta }: ConditionWithMeta): void {
205+
restoreArray(cond, meta).forEach((condition, index) => {
206+
const filter = this.columnFilters[index];
207+
if (filter && condition) {
208+
filter.fromViewState(condition);
209+
}
210+
});
211+
}
197212
}

packages/pluggableWidgets/datagrid-web/src/helpers/state/RootGridStore.ts

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { createContextWithStub, FilterAPI } from "@mendix/widget-plugin-filtering/context";
2+
import { CombinedFilter } from "@mendix/widget-plugin-filtering/stores/generic/CombinedFilter";
23
import { CustomFilterHost } from "@mendix/widget-plugin-filtering/stores/generic/CustomFilterHost";
34
import { DatasourceController } from "@mendix/widget-plugin-grid/query/DatasourceController";
45
import { RefreshController } from "@mendix/widget-plugin-grid/query/RefreshController";
@@ -30,44 +31,47 @@ export class RootGridStore extends BaseControllerHost {
3031
exportProgressCtrl: ProgressStore;
3132
loaderCtrl: DerivedLoaderController;
3233
paginationCtrl: PaginationController;
33-
readonly autonomousFilterAPI: FilterAPI;
34+
readonly filterAPI: FilterAPI;
3435

3536
private gate: Gate;
3637

3738
constructor({ gate, exportCtrl }: Spec) {
3839
super();
39-
4040
const { props } = gate;
41-
const [columnsInitFilter, sharedInitFilter] = DatasourceParamsController.unzipFilter(
42-
props.datasource.filter,
43-
props.name
44-
);
4541

4642
this.gate = gate;
43+
4744
this.staticInfo = {
4845
name: props.name,
4946
filtersChannelName: `datagrid/${generateUUID()}`
5047
};
51-
const customFilterHost = new CustomFilterHost();
48+
49+
const filterHost = new CustomFilterHost();
50+
5251
const query = new DatasourceController(this, { gate });
53-
this.autonomousFilterAPI = createContextWithStub({
54-
filterObserver: customFilterHost,
55-
sharedInitFilter,
52+
53+
this.filterAPI = createContextWithStub({
54+
filterObserver: filterHost,
5655
parentChannelName: this.staticInfo.filtersChannelName
5756
});
58-
const columns = (this.columnsStore = new ColumnGroupStore(props, this.staticInfo, columnsInitFilter, {
59-
customFilterHost,
60-
sharedInitFilter
61-
}));
62-
this.settingsStore = new GridPersonalizationStore(props, this.columnsStore, customFilterHost);
57+
58+
this.columnsStore = new ColumnGroupStore(props, this.staticInfo, filterHost);
59+
60+
const combinedFilter = new CombinedFilter(this, {
61+
stableKey: props.name,
62+
inputs: [filterHost, this.columnsStore]
63+
});
64+
65+
this.settingsStore = new GridPersonalizationStore(props, this.columnsStore, filterHost);
66+
6367
this.paginationCtrl = new PaginationController(this, { gate, query });
68+
6469
this.exportProgressCtrl = exportCtrl;
6570

6671
new DatasourceParamsController(this, {
6772
query,
68-
columns,
69-
customFilters: customFilterHost,
70-
widgetName: props.name
73+
filterHost: combinedFilter,
74+
sortHost: this.columnsStore
7175
});
7276

7377
new RefreshController(this, {
@@ -77,9 +81,11 @@ export class RootGridStore extends BaseControllerHost {
7781

7882
this.loaderCtrl = new DerivedLoaderController({
7983
exp: exportCtrl,
80-
cols: columns,
84+
cols: this.columnsStore,
8185
query
8286
});
87+
88+
combinedFilter.hydrate(props.datasource.filter);
8389
}
8490

8591
setup(): () => void {

0 commit comments

Comments
 (0)