@servicetitan/titan-chatbot-api 4.3.2 → 4.4.0
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/CHANGELOG.md +24 -0
- package/dist/api-client/models/__mocks__/models.mock.d.ts.map +1 -1
- package/dist/api-client/models/__mocks__/models.mock.js +9 -7
- package/dist/api-client/models/__mocks__/models.mock.js.map +1 -1
- package/dist/api-client/utils/model-utils.d.ts +1 -1
- package/dist/api-client/utils/model-utils.d.ts.map +1 -1
- package/dist/api-client/utils/model-utils.js +2 -2
- package/dist/api-client/utils/model-utils.js.map +1 -1
- package/dist/stores/__tests__/chatbot-ui.store.test.js +1 -1
- package/dist/stores/__tests__/filter.store.test.js +49 -40
- package/dist/stores/__tests__/filter.store.test.js.map +1 -1
- package/dist/stores/chatbot-ui-backend.store.d.ts +9 -9
- package/dist/stores/chatbot-ui-backend.store.d.ts.map +1 -1
- package/dist/stores/chatbot-ui-backend.store.js.map +1 -1
- package/dist/stores/chatbot-ui.store.d.ts +3 -3
- package/dist/stores/chatbot-ui.store.d.ts.map +1 -1
- package/dist/stores/chatbot-ui.store.js.map +1 -1
- package/dist/stores/filter.store.d.ts +50 -17
- package/dist/stores/filter.store.d.ts.map +1 -1
- package/dist/stores/filter.store.js +255 -179
- package/dist/stores/filter.store.js.map +1 -1
- package/dist/stores/index.d.ts +1 -0
- package/dist/stores/index.d.ts.map +1 -1
- package/dist/stores/index.js.map +1 -1
- package/package.json +3 -3
- package/src/api-client/models/__mocks__/models.mock.ts +10 -6
- package/src/api-client/utils/model-utils.ts +3 -3
- package/src/stores/__tests__/chatbot-ui.store.test.ts +1 -1
- package/src/stores/__tests__/filter.store.test.ts +63 -45
- package/src/stores/chatbot-ui-backend.store.ts +11 -8
- package/src/stores/chatbot-ui.store.ts +3 -3
- package/src/stores/filter.store.ts +250 -187
- package/src/stores/index.ts +1 -0
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1,30 +1,63 @@
|
|
|
1
1
|
import { Models } from '../api-client';
|
|
2
|
-
interface
|
|
3
|
-
uid
|
|
4
|
-
|
|
2
|
+
export interface IUiFilterOption {
|
|
3
|
+
uid: string;
|
|
4
|
+
parentUids: string[];
|
|
5
|
+
key: string;
|
|
6
|
+
displayName?: string | undefined;
|
|
7
|
+
type: Models.OptionType;
|
|
8
|
+
subOptions?: IUiFilterOption[] | undefined;
|
|
5
9
|
}
|
|
6
|
-
export
|
|
7
|
-
|
|
8
|
-
filters:
|
|
9
|
-
|
|
10
|
+
export interface IFilterStore {
|
|
11
|
+
selected: Map<string, string[]>;
|
|
12
|
+
filters: IUiFilterOption[];
|
|
13
|
+
initFilters(model: Models.IFrontendModel): void;
|
|
14
|
+
isOptionChecked(filterKey: string, optionKey: string): boolean;
|
|
15
|
+
isOptionDisabled(filterKey: string, optionKey: string): boolean;
|
|
16
|
+
getFilterOptions(filterKey: string): IUiFilterOption[];
|
|
17
|
+
selectOption(filterKey: string, optionKey: string): void;
|
|
18
|
+
selectAll(filterKey: string): void;
|
|
19
|
+
deselectOption(filterKey: string, optionKey: string): void;
|
|
20
|
+
deselectAll(filterKey: string): void;
|
|
21
|
+
getFilterLabel(key: string): string;
|
|
22
|
+
export(): Models.Selections | undefined;
|
|
23
|
+
}
|
|
24
|
+
export declare class FilterStore implements IFilterStore {
|
|
25
|
+
/**
|
|
26
|
+
* Selected items map: filter key -> selectable keys
|
|
27
|
+
*/
|
|
28
|
+
selected: Map<string, string[]>;
|
|
29
|
+
/**
|
|
30
|
+
* Available filters with their selectable options (flattened and merged)
|
|
31
|
+
*/
|
|
32
|
+
filters: IUiFilterOption[];
|
|
33
|
+
private localFilters;
|
|
10
34
|
private originalFilters;
|
|
35
|
+
private mapUidToOption;
|
|
36
|
+
private mapUidToParentUid;
|
|
11
37
|
constructor();
|
|
12
38
|
initFilters(model: Models.IFrontendModel): void;
|
|
39
|
+
isOptionChecked: (filterKey: string, optionKey: string) => boolean;
|
|
40
|
+
isOptionDisabled: (filterKey: string, optionKey: string) => boolean;
|
|
41
|
+
getFilterOptions: (filterKey: string) => IUiFilterOption[];
|
|
13
42
|
selectOption: (filterKey: string, optionKey: string) => void;
|
|
14
43
|
selectAll: (filterKey: string) => void;
|
|
15
44
|
deselectOption: (filterKey: string, optionKey: string) => void;
|
|
16
45
|
deselectAll: (filterKey: string) => void;
|
|
17
46
|
getFilterLabel: (key: string) => string;
|
|
18
47
|
export(): Models.Selections | undefined;
|
|
19
|
-
private
|
|
20
|
-
private
|
|
21
|
-
private
|
|
22
|
-
private
|
|
23
|
-
private
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
48
|
+
private assertFilterKeyExists;
|
|
49
|
+
private assertOptionKeyExists;
|
|
50
|
+
private getFilterByKey;
|
|
51
|
+
private getOptionFilter;
|
|
52
|
+
private uncheckDisabledOptions;
|
|
53
|
+
/**
|
|
54
|
+
* Sets unique IDs (uids) for each option and builds a parent options map that tracks parent-child relationships.
|
|
55
|
+
* @param options The list of options to process (recursive).
|
|
56
|
+
*/
|
|
57
|
+
private initLocalFilters;
|
|
58
|
+
/**
|
|
59
|
+
* Go through local filters and set up UI objects that will be rendered: filters and filter selectables
|
|
60
|
+
*/
|
|
61
|
+
private initLocalUiFilters;
|
|
28
62
|
}
|
|
29
|
-
export {};
|
|
30
63
|
//# sourceMappingURL=filter.store.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filter.store.d.ts","sourceRoot":"","sources":["../../src/stores/filter.store.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAe,MAAM,eAAe,CAAC;AAEpD,
|
|
1
|
+
{"version":3,"file":"filter.store.d.ts","sourceRoot":"","sources":["../../src/stores/filter.store.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAe,MAAM,eAAe,CAAC;AAEpD,MAAM,WAAW,eAAe;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,IAAI,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,UAAU,CAAC,EAAE,eAAe,EAAE,GAAG,SAAS,CAAC;CAC9C;AAED,MAAM,WAAW,YAAY;IACzB,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAChC,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,WAAW,CAAC,KAAK,EAAE,MAAM,CAAC,cAAc,GAAG,IAAI,CAAC;IAChD,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;IAC/D,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;IAChE,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,eAAe,EAAE,CAAC;IACvD,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzD,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3D,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;IACpC,MAAM,IAAI,MAAM,CAAC,UAAU,GAAG,SAAS,CAAC;CAC3C;AAED,qBAAa,WAAY,YAAW,YAAY;IAC5C;;OAEG;IACS,QAAQ,wBAA+B;IACnD;;OAEG;IACS,OAAO,EAAE,eAAe,EAAE,CAAM;IAC5C,OAAO,CAAC,YAAY,CAAyB;IAC7C,OAAO,CAAC,eAAe,CAAwB;IAC/C,OAAO,CAAC,cAAc,CAAsC;IAC5D,OAAO,CAAC,iBAAiB,CAAyC;;IAOlE,WAAW,CAAC,KAAK,EAAE,MAAM,CAAC,cAAc;IAOxC,eAAe,GAAI,WAAW,MAAM,EAAE,WAAW,MAAM,KAAG,OAAO,CAM/D;IAEF,gBAAgB,GAAI,WAAW,MAAM,EAAE,WAAW,MAAM,KAAG,OAAO,CA+BhE;IAEF,gBAAgB,GAAI,WAAW,MAAM,KAAG,eAAe,EAAE,CAMvD;IAGF,YAAY,GAAI,WAAW,MAAM,EAAE,WAAW,MAAM,UAWlD;IAGF,SAAS,GAAI,WAAW,MAAM,UAa5B;IAGF,cAAc,GAAI,WAAW,MAAM,EAAE,WAAW,MAAM,UASpD;IAGF,WAAW,GAAI,WAAW,MAAM,UAI9B;IAEF,cAAc,GAAI,KAAK,MAAM,YAO3B;IAEF,MAAM,IAAI,MAAM,CAAC,UAAU,GAAG,SAAS;IAIvC,OAAO,CAAC,qBAAqB,CAK3B;IAEF,OAAO,CAAC,qBAAqB,CAS3B;IAEF,OAAO,CAAC,cAAc,CAEpB;IAEF,OAAO,CAAC,eAAe,CAMrB;IAGF,OAAO,CAAC,sBAAsB,CAe5B;IAEF;;;OAGG;IACH,OAAO,CAAC,gBAAgB,CAetB;IAEF;;OAEG;IAEH,OAAO,CAAC,kBAAkB,CAoFxB;CACL"}
|
|
@@ -13,23 +13,29 @@ import { nanoid } from 'nanoid';
|
|
|
13
13
|
import { Models, ModelsUtils } from '../api-client';
|
|
14
14
|
export class FilterStore {
|
|
15
15
|
constructor() {
|
|
16
|
-
|
|
16
|
+
/**
|
|
17
|
+
* Selected items map: filter key -> selectable keys
|
|
18
|
+
*/
|
|
19
|
+
Object.defineProperty(this, "selected", {
|
|
17
20
|
enumerable: true,
|
|
18
21
|
configurable: true,
|
|
19
22
|
writable: true,
|
|
20
|
-
value:
|
|
23
|
+
value: new Map()
|
|
21
24
|
});
|
|
25
|
+
/**
|
|
26
|
+
* Available filters with their selectable options (flattened and merged)
|
|
27
|
+
*/
|
|
22
28
|
Object.defineProperty(this, "filters", {
|
|
23
29
|
enumerable: true,
|
|
24
30
|
configurable: true,
|
|
25
31
|
writable: true,
|
|
26
32
|
value: []
|
|
27
33
|
});
|
|
28
|
-
Object.defineProperty(this, "
|
|
34
|
+
Object.defineProperty(this, "localFilters", {
|
|
29
35
|
enumerable: true,
|
|
30
36
|
configurable: true,
|
|
31
37
|
writable: true,
|
|
32
|
-
value:
|
|
38
|
+
value: []
|
|
33
39
|
});
|
|
34
40
|
Object.defineProperty(this, "originalFilters", {
|
|
35
41
|
enumerable: true,
|
|
@@ -37,21 +43,95 @@ export class FilterStore {
|
|
|
37
43
|
writable: true,
|
|
38
44
|
value: []
|
|
39
45
|
});
|
|
40
|
-
Object.defineProperty(this, "
|
|
46
|
+
Object.defineProperty(this, "mapUidToOption", {
|
|
47
|
+
enumerable: true,
|
|
48
|
+
configurable: true,
|
|
49
|
+
writable: true,
|
|
50
|
+
value: new Map()
|
|
51
|
+
});
|
|
52
|
+
Object.defineProperty(this, "mapUidToParentUid", {
|
|
53
|
+
enumerable: true,
|
|
54
|
+
configurable: true,
|
|
55
|
+
writable: true,
|
|
56
|
+
value: new Map()
|
|
57
|
+
});
|
|
58
|
+
Object.defineProperty(this, "isOptionChecked", {
|
|
41
59
|
enumerable: true,
|
|
42
60
|
configurable: true,
|
|
43
61
|
writable: true,
|
|
44
62
|
value: (filterKey, optionKey) => {
|
|
45
|
-
const
|
|
46
|
-
|
|
63
|
+
const selectedOptions = this.selected.get(filterKey);
|
|
64
|
+
if (!selectedOptions) {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
return selectedOptions.includes(optionKey);
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
Object.defineProperty(this, "isOptionDisabled", {
|
|
71
|
+
enumerable: true,
|
|
72
|
+
configurable: true,
|
|
73
|
+
writable: true,
|
|
74
|
+
value: (filterKey, optionKey) => {
|
|
75
|
+
var _a, _b;
|
|
76
|
+
const filter = this.getFilterByKey(filterKey);
|
|
77
|
+
const option = (_a = filter === null || filter === void 0 ? void 0 : filter.subOptions) === null || _a === void 0 ? void 0 : _a.find(o => o.key === optionKey);
|
|
47
78
|
if (!option) {
|
|
48
|
-
|
|
79
|
+
return false;
|
|
49
80
|
}
|
|
50
|
-
|
|
51
|
-
|
|
81
|
+
// check any parent selectable is selected
|
|
82
|
+
for (const optionFilter of option.parentUids
|
|
83
|
+
.map(uid => this.mapUidToOption.get(uid))
|
|
84
|
+
.filter(Boolean)) {
|
|
85
|
+
if (!((_b = optionFilter === null || optionFilter === void 0 ? void 0 : optionFilter.parentUids) === null || _b === void 0 ? void 0 : _b.length)) {
|
|
86
|
+
// no parent -> root filter -> so not disabled
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
// Check all parent filters
|
|
90
|
+
for (const parentUid of optionFilter.parentUids) {
|
|
91
|
+
const parentOption = this.mapUidToOption.get(parentUid);
|
|
92
|
+
if (!parentOption) {
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
const parentFilter = this.getOptionFilter(parentOption);
|
|
96
|
+
if (!parentFilter) {
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
const isParentSelected = this.isOptionChecked(parentFilter.key, parentOption.key);
|
|
100
|
+
if (isParentSelected) {
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
52
104
|
}
|
|
53
|
-
|
|
54
|
-
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
Object.defineProperty(this, "getFilterOptions", {
|
|
109
|
+
enumerable: true,
|
|
110
|
+
configurable: true,
|
|
111
|
+
writable: true,
|
|
112
|
+
value: (filterKey) => {
|
|
113
|
+
const filter = this.getFilterByKey(filterKey);
|
|
114
|
+
if (!(filter === null || filter === void 0 ? void 0 : filter.subOptions)) {
|
|
115
|
+
return [];
|
|
116
|
+
}
|
|
117
|
+
return filter.subOptions.filter(x => x.type === Models.OptionType.Selectable);
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
Object.defineProperty(this, "selectOption", {
|
|
121
|
+
enumerable: true,
|
|
122
|
+
configurable: true,
|
|
123
|
+
writable: true,
|
|
124
|
+
value: (filterKey, optionKey) => {
|
|
125
|
+
this.assertFilterKeyExists(filterKey);
|
|
126
|
+
this.assertOptionKeyExists(filterKey, optionKey);
|
|
127
|
+
if (!this.selected.has(filterKey)) {
|
|
128
|
+
this.selected.set(filterKey, []);
|
|
129
|
+
}
|
|
130
|
+
const selectedOptions = this.selected.get(filterKey);
|
|
131
|
+
if (selectedOptions.includes(optionKey)) {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
this.selected.set(filterKey, [...selectedOptions, optionKey]);
|
|
55
135
|
}
|
|
56
136
|
});
|
|
57
137
|
Object.defineProperty(this, "selectAll", {
|
|
@@ -59,8 +139,13 @@ export class FilterStore {
|
|
|
59
139
|
configurable: true,
|
|
60
140
|
writable: true,
|
|
61
141
|
value: (filterKey) => {
|
|
62
|
-
this.
|
|
63
|
-
this.
|
|
142
|
+
this.assertFilterKeyExists(filterKey);
|
|
143
|
+
const filter = this.getFilterByKey(filterKey);
|
|
144
|
+
if (!(filter === null || filter === void 0 ? void 0 : filter.subOptions)) {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
const selectableOptions = filter.subOptions.filter(x => x.type === Models.OptionType.Selectable);
|
|
148
|
+
this.selected.set(filterKey, selectableOptions.map(o => o.key));
|
|
64
149
|
}
|
|
65
150
|
});
|
|
66
151
|
Object.defineProperty(this, "deselectOption", {
|
|
@@ -68,10 +153,12 @@ export class FilterStore {
|
|
|
68
153
|
configurable: true,
|
|
69
154
|
writable: true,
|
|
70
155
|
value: (filterKey, optionKey) => {
|
|
71
|
-
|
|
72
|
-
this.
|
|
73
|
-
this.
|
|
74
|
-
this.
|
|
156
|
+
var _a;
|
|
157
|
+
this.assertFilterKeyExists(filterKey);
|
|
158
|
+
this.assertOptionKeyExists(filterKey, optionKey);
|
|
159
|
+
const selectedOptions = (_a = this.selected.get(filterKey)) !== null && _a !== void 0 ? _a : [];
|
|
160
|
+
this.selected.set(filterKey, selectedOptions.filter(o => o !== optionKey));
|
|
161
|
+
this.uncheckDisabledOptions();
|
|
75
162
|
}
|
|
76
163
|
});
|
|
77
164
|
Object.defineProperty(this, "deselectAll", {
|
|
@@ -79,9 +166,9 @@ export class FilterStore {
|
|
|
79
166
|
configurable: true,
|
|
80
167
|
writable: true,
|
|
81
168
|
value: (filterKey) => {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
169
|
+
this.assertFilterKeyExists(filterKey);
|
|
170
|
+
this.selected.set(filterKey, []);
|
|
171
|
+
this.uncheckDisabledOptions();
|
|
85
172
|
}
|
|
86
173
|
});
|
|
87
174
|
Object.defineProperty(this, "getFilterLabel", {
|
|
@@ -97,214 +184,203 @@ export class FilterStore {
|
|
|
97
184
|
});
|
|
98
185
|
}
|
|
99
186
|
});
|
|
100
|
-
Object.defineProperty(this, "
|
|
187
|
+
Object.defineProperty(this, "assertFilterKeyExists", {
|
|
101
188
|
enumerable: true,
|
|
102
189
|
configurable: true,
|
|
103
190
|
writable: true,
|
|
104
191
|
value: (filterKey) => {
|
|
105
|
-
const filter = this.
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
}
|
|
109
|
-
});
|
|
110
|
-
Object.defineProperty(this, "addSubSequentFilters", {
|
|
111
|
-
enumerable: true,
|
|
112
|
-
configurable: true,
|
|
113
|
-
writable: true,
|
|
114
|
-
value: (filterKey) => {
|
|
115
|
-
var _a, _b;
|
|
116
|
-
const filter = this.getExistingFilterByKey(filterKey);
|
|
117
|
-
if (!filter.subOptions) {
|
|
118
|
-
return;
|
|
119
|
-
}
|
|
120
|
-
// Get selected items for the filter
|
|
121
|
-
const filterSelectedKeys = (_a = this.selectedOptions[filterKey]) !== null && _a !== void 0 ? _a : [];
|
|
122
|
-
const filterSelectedOptions = filter.subOptions.filter(x => x.type === Models.OptionType.Selectable && filterSelectedKeys.includes(x.key));
|
|
123
|
-
// Find all sub-filters for the selected options
|
|
124
|
-
const allSubFilters = (_b = filterSelectedOptions.flatMap(selectedOption => {
|
|
125
|
-
var _a;
|
|
126
|
-
// For each selected option, collect its sub-filters
|
|
127
|
-
const subFilters = [];
|
|
128
|
-
for (const subFilter of (_a = selectedOption.subOptions) !== null && _a !== void 0 ? _a : []) {
|
|
129
|
-
const originalFilter = cloneDeep(this.getOriginalFilter(subFilter.uid));
|
|
130
|
-
originalFilter.parentKeys = [selectedOption.uid];
|
|
131
|
-
subFilters.push(originalFilter);
|
|
132
|
-
}
|
|
133
|
-
return subFilters;
|
|
134
|
-
})) !== null && _b !== void 0 ? _b : [];
|
|
135
|
-
// Merge sub-filters with the same key and their options (with parent keys merging)
|
|
136
|
-
const mergedSubFilters = allSubFilters.reduce((acc, subFilter) => {
|
|
137
|
-
var _a, _b;
|
|
138
|
-
if (!subFilter.subOptions) {
|
|
139
|
-
return acc;
|
|
140
|
-
}
|
|
141
|
-
const subfilterOptions = ((_a = subFilter.subOptions) !== null && _a !== void 0 ? _a : []);
|
|
142
|
-
const subfilterParentKeys = subFilter.parentKeys;
|
|
143
|
-
// Merge filters with the same key and their options if they already exist
|
|
144
|
-
subfilterOptions.forEach(subfilterOption => {
|
|
145
|
-
subfilterOption.parentKeys = this.mergeParentKeys(subfilterOption.parentKeys, subfilterParentKeys);
|
|
146
|
-
});
|
|
147
|
-
// Check if the filter already exists in the accumulator
|
|
148
|
-
const existingFilter = acc.find(x => x.key === subFilter.key);
|
|
149
|
-
if (!existingFilter) {
|
|
150
|
-
return [...acc, subFilter];
|
|
151
|
-
}
|
|
152
|
-
// Merge parent keys for the filter
|
|
153
|
-
existingFilter.parentKeys = this.mergeParentKeys(existingFilter.parentKeys, subfilterParentKeys);
|
|
154
|
-
// Merge options for subfilters by key
|
|
155
|
-
existingFilter.subOptions = subfilterOptions.reduce((acc2, subfilterOption) => {
|
|
156
|
-
const existing = acc2.find(o => o.key === subfilterOption.key);
|
|
157
|
-
if (!existing) {
|
|
158
|
-
return [...acc2, subfilterOption];
|
|
159
|
-
}
|
|
160
|
-
existing.parentKeys = this.mergeParentKeys(existing.parentKeys, subfilterOption.parentKeys);
|
|
161
|
-
return acc2;
|
|
162
|
-
}, [...((_b = existingFilter.subOptions) !== null && _b !== void 0 ? _b : [])]);
|
|
163
|
-
return acc;
|
|
164
|
-
}, []);
|
|
165
|
-
// Update the filters with the merged sub-filters
|
|
166
|
-
for (const newFilter of mergedSubFilters) {
|
|
167
|
-
const existingFilterIdx = this.filters.findIndex(f => f.key === newFilter.key);
|
|
168
|
-
if (existingFilterIdx < 0) {
|
|
169
|
-
this.filters.push(newFilter);
|
|
170
|
-
}
|
|
171
|
-
else {
|
|
172
|
-
this.filters[existingFilterIdx] = newFilter;
|
|
173
|
-
}
|
|
174
|
-
this.addSubSequentFilters(newFilter.key);
|
|
192
|
+
const filter = this.getFilterByKey(filterKey);
|
|
193
|
+
if (!filter) {
|
|
194
|
+
throw new Error(`Filter with key "${filterKey}" does not exist.`);
|
|
175
195
|
}
|
|
176
196
|
}
|
|
177
197
|
});
|
|
178
|
-
Object.defineProperty(this, "
|
|
198
|
+
Object.defineProperty(this, "assertOptionKeyExists", {
|
|
179
199
|
enumerable: true,
|
|
180
200
|
configurable: true,
|
|
181
201
|
writable: true,
|
|
182
|
-
value: (
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
if (!keys2) {
|
|
190
|
-
return keys1;
|
|
202
|
+
value: (filterKey, optionKey) => {
|
|
203
|
+
var _a;
|
|
204
|
+
this.assertFilterKeyExists(filterKey);
|
|
205
|
+
const filter = this.getFilterByKey(filterKey);
|
|
206
|
+
const option = (_a = filter.subOptions) === null || _a === void 0 ? void 0 : _a.find(o => o.key === optionKey);
|
|
207
|
+
if (!option) {
|
|
208
|
+
throw new Error(`Option with key "${optionKey}" does not exist in filter "${filterKey}".`);
|
|
191
209
|
}
|
|
192
|
-
const mergedKeys = new Set([...keys1, ...keys2]);
|
|
193
|
-
return Array.from(mergedKeys);
|
|
194
210
|
}
|
|
195
211
|
});
|
|
196
|
-
Object.defineProperty(this, "
|
|
212
|
+
Object.defineProperty(this, "getFilterByKey", {
|
|
197
213
|
enumerable: true,
|
|
198
214
|
configurable: true,
|
|
199
215
|
writable: true,
|
|
200
|
-
value: (filterKey
|
|
201
|
-
|
|
202
|
-
const filter = this.getExistingFilterByKey(filterKey);
|
|
203
|
-
const filterSubOptionToRemove = (_a = filter.subOptions) === null || _a === void 0 ? void 0 : _a.find(x => x.key === parentKeyToRemove);
|
|
204
|
-
const filterSubOptionToRemoveUid = filterSubOptionToRemove === null || filterSubOptionToRemove === void 0 ? void 0 : filterSubOptionToRemove.uid;
|
|
205
|
-
const filterIdx = this.filters.findIndex(f => f.key === filterKey);
|
|
206
|
-
for (let i = filterIdx + 1; i < this.filters.length; i++) {
|
|
207
|
-
const subFilter = this.filters[i];
|
|
208
|
-
if (!((_b = subFilter.parentKeys) === null || _b === void 0 ? void 0 : _b.some(k => k === filterSubOptionToRemoveUid))) {
|
|
209
|
-
// If the sub-filter does not depend on the removed option, skip it
|
|
210
|
-
continue;
|
|
211
|
-
}
|
|
212
|
-
(_c = subFilter.subOptions) === null || _c === void 0 ? void 0 : _c.forEach((o) => {
|
|
213
|
-
var _a, _b, _c;
|
|
214
|
-
o.parentKeys = ((_a = o.parentKeys) !== null && _a !== void 0 ? _a : []).filter(p => p !== filterSubOptionToRemoveUid);
|
|
215
|
-
// Uncheck sub-filter options if they no longer have parent keys
|
|
216
|
-
if (!((_b = o.parentKeys) === null || _b === void 0 ? void 0 : _b.length)) {
|
|
217
|
-
this.selectedOptions[subFilter.key] = (_c = this.selectedOptions[subFilter.key]) === null || _c === void 0 ? void 0 : _c.filter(x => x !== o.key);
|
|
218
|
-
}
|
|
219
|
-
});
|
|
220
|
-
subFilter.subOptions = (_d = subFilter.subOptions) === null || _d === void 0 ? void 0 : _d.filter((o) => { var _a; return Boolean((_a = o.parentKeys) === null || _a === void 0 ? void 0 : _a.length); });
|
|
221
|
-
}
|
|
216
|
+
value: (filterKey) => {
|
|
217
|
+
return this.filters.find(f => f.key === filterKey);
|
|
222
218
|
}
|
|
223
219
|
});
|
|
224
|
-
Object.defineProperty(this, "
|
|
220
|
+
Object.defineProperty(this, "getOptionFilter", {
|
|
225
221
|
enumerable: true,
|
|
226
222
|
configurable: true,
|
|
227
223
|
writable: true,
|
|
228
|
-
value: (
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
result.push(subFilter, ...this.getSubFilters(subFilter));
|
|
235
|
-
});
|
|
236
|
-
});
|
|
237
|
-
return result;
|
|
224
|
+
value: (option) => {
|
|
225
|
+
const parentUid = this.mapUidToParentUid.get(option.uid);
|
|
226
|
+
if (!parentUid) {
|
|
227
|
+
return undefined;
|
|
228
|
+
}
|
|
229
|
+
return this.mapUidToOption.get(parentUid);
|
|
238
230
|
}
|
|
239
231
|
});
|
|
240
|
-
Object.defineProperty(this, "
|
|
232
|
+
Object.defineProperty(this, "uncheckDisabledOptions", {
|
|
241
233
|
enumerable: true,
|
|
242
234
|
configurable: true,
|
|
243
235
|
writable: true,
|
|
244
236
|
value: () => {
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
237
|
+
for (const [filterKey, selectedOptions] of this.selected.entries()) {
|
|
238
|
+
const filter = this.getFilterByKey(filterKey);
|
|
239
|
+
if (!filter) {
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
const validSelectedOptions = selectedOptions.filter(optionKey => {
|
|
243
|
+
var _a;
|
|
244
|
+
const option = (_a = filter.subOptions) === null || _a === void 0 ? void 0 : _a.find(o => o.key === optionKey);
|
|
245
|
+
if (!option) {
|
|
246
|
+
return false;
|
|
247
|
+
}
|
|
248
|
+
return !this.isOptionDisabled(filterKey, optionKey);
|
|
249
|
+
});
|
|
250
|
+
this.selected.set(filterKey, validSelectedOptions);
|
|
259
251
|
}
|
|
260
|
-
return filter;
|
|
261
252
|
}
|
|
262
253
|
});
|
|
263
|
-
|
|
254
|
+
/**
|
|
255
|
+
* Sets unique IDs (uids) for each option and builds a parent options map that tracks parent-child relationships.
|
|
256
|
+
* @param options The list of options to process (recursive).
|
|
257
|
+
*/
|
|
258
|
+
Object.defineProperty(this, "initLocalFilters", {
|
|
264
259
|
enumerable: true,
|
|
265
260
|
configurable: true,
|
|
266
261
|
writable: true,
|
|
267
|
-
value: (
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
262
|
+
value: (options) => {
|
|
263
|
+
// Set up local filters uids
|
|
264
|
+
this.localFilters = cloneDeep(options);
|
|
265
|
+
const setUids = (o, parentUid) => {
|
|
266
|
+
if (!o) {
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
o.forEach(x => {
|
|
270
|
+
x.uid = nanoid();
|
|
271
|
+
x.parentUids = parentUid ? [parentUid] : [];
|
|
272
|
+
setUids(x.subOptions, x.uid);
|
|
273
|
+
});
|
|
274
|
+
};
|
|
275
|
+
setUids(this.localFilters);
|
|
276
|
+
this.initLocalUiFilters(this.localFilters);
|
|
271
277
|
}
|
|
272
278
|
});
|
|
273
|
-
|
|
279
|
+
/**
|
|
280
|
+
* Go through local filters and set up UI objects that will be rendered: filters and filter selectables
|
|
281
|
+
*/
|
|
282
|
+
Object.defineProperty(this, "initLocalUiFilters", {
|
|
274
283
|
enumerable: true,
|
|
275
284
|
configurable: true,
|
|
276
285
|
writable: true,
|
|
277
|
-
value: (
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
286
|
+
value: (options) => {
|
|
287
|
+
this.mapUidToOption = new Map();
|
|
288
|
+
this.mapUidToParentUid = new Map();
|
|
289
|
+
const filtersKeyToFilter = new Map();
|
|
290
|
+
// Function to merge duplicate selectable options by key
|
|
291
|
+
const mergeDuplicates = (options) => {
|
|
292
|
+
// Merge selectables with the same keys. Original uids will be stored in "parentUids"
|
|
293
|
+
const keyToOption = new Map();
|
|
294
|
+
for (const option of options) {
|
|
295
|
+
if (option.type !== Models.OptionType.Selectable) {
|
|
296
|
+
continue;
|
|
297
|
+
}
|
|
298
|
+
if (!keyToOption.has(option.key)) {
|
|
299
|
+
keyToOption.set(option.key, {
|
|
300
|
+
uid: option.uid,
|
|
301
|
+
parentUids: [],
|
|
302
|
+
key: option.key,
|
|
303
|
+
displayName: option.displayName,
|
|
304
|
+
type: option.type,
|
|
305
|
+
subOptions: [],
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
const existingOption = keyToOption.get(option.key);
|
|
309
|
+
existingOption.parentUids = [...existingOption.parentUids, ...option.parentUids];
|
|
310
|
+
}
|
|
311
|
+
return Array.from(keyToOption.values());
|
|
312
|
+
};
|
|
313
|
+
// Recursive flattening function
|
|
314
|
+
const flatten = (curr, parent) => {
|
|
315
|
+
var _a, _b, _c, _d;
|
|
316
|
+
// Skip empty objects and none types
|
|
317
|
+
if (!curr || curr.type === Models.OptionType.None) {
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
// Map uid to parent uid
|
|
321
|
+
if (parent) {
|
|
322
|
+
this.mapUidToParentUid.set(curr.uid, parent.uid);
|
|
323
|
+
}
|
|
324
|
+
// Process selectable
|
|
325
|
+
if (curr.type === Models.OptionType.Selectable) {
|
|
326
|
+
const newOption = {
|
|
327
|
+
uid: curr.uid,
|
|
328
|
+
parentUids: parent ? [parent.uid] : [],
|
|
329
|
+
key: curr.key,
|
|
330
|
+
displayName: curr.displayName,
|
|
331
|
+
type: curr.type,
|
|
332
|
+
};
|
|
333
|
+
this.mapUidToOption.set(newOption.uid, newOption);
|
|
334
|
+
const optionFilter = filtersKeyToFilter.get(parent.key);
|
|
335
|
+
optionFilter.subOptions = [...((_a = optionFilter.subOptions) !== null && _a !== void 0 ? _a : []), newOption];
|
|
336
|
+
// Go into subfilters
|
|
337
|
+
for (const subOption of (_b = curr.subOptions) !== null && _b !== void 0 ? _b : []) {
|
|
338
|
+
flatten(subOption, newOption);
|
|
339
|
+
}
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
// Process filter
|
|
343
|
+
if (!filtersKeyToFilter.has(curr.key)) {
|
|
344
|
+
const newFilter = {
|
|
345
|
+
uid: curr.uid,
|
|
346
|
+
parentUids: parent ? [parent.uid] : [],
|
|
347
|
+
key: curr.key,
|
|
348
|
+
type: curr.type,
|
|
349
|
+
displayName: curr.displayName,
|
|
350
|
+
subOptions: [],
|
|
351
|
+
};
|
|
352
|
+
filtersKeyToFilter.set(curr.key, newFilter);
|
|
353
|
+
}
|
|
354
|
+
const filter = filtersKeyToFilter.get(curr.key);
|
|
355
|
+
this.mapUidToOption.set(curr.uid, curr);
|
|
356
|
+
for (const subOption of (_c = curr.subOptions) !== null && _c !== void 0 ? _c : []) {
|
|
357
|
+
flatten(subOption, curr);
|
|
358
|
+
}
|
|
359
|
+
if ((_d = filter.subOptions) === null || _d === void 0 ? void 0 : _d.length) {
|
|
360
|
+
filter.subOptions = mergeDuplicates(filter.subOptions);
|
|
361
|
+
}
|
|
362
|
+
};
|
|
363
|
+
for (const option of options) {
|
|
364
|
+
flatten(option);
|
|
281
365
|
}
|
|
282
|
-
|
|
366
|
+
this.filters = Array.from(filtersKeyToFilter.values());
|
|
283
367
|
}
|
|
284
368
|
});
|
|
285
369
|
makeObservable(this);
|
|
286
370
|
}
|
|
287
371
|
initFilters(model) {
|
|
288
372
|
var _a, _b;
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
x.uid = nanoid();
|
|
292
|
-
setUids(x.subOptions);
|
|
293
|
-
});
|
|
294
|
-
};
|
|
295
|
-
this.model = model;
|
|
296
|
-
this.originalFilters = cloneDeep((_b = (_a = model.options.subOptions) === null || _a === void 0 ? void 0 : _a.filter(x => x.type === Models.OptionType.Group)) !== null && _b !== void 0 ? _b : []);
|
|
297
|
-
setUids(this.originalFilters);
|
|
298
|
-
this.filters = this.originalFilters;
|
|
373
|
+
this.originalFilters = cloneDeep((_b = (_a = model === null || model === void 0 ? void 0 : model.options.subOptions) === null || _a === void 0 ? void 0 : _a.filter(x => x.type === Models.OptionType.Group)) !== null && _b !== void 0 ? _b : []);
|
|
374
|
+
this.initLocalFilters(this.originalFilters);
|
|
299
375
|
}
|
|
300
376
|
export() {
|
|
301
|
-
return ModelsUtils.createSelectionsModel(this.originalFilters, this.
|
|
377
|
+
return ModelsUtils.createSelectionsModel(this.originalFilters, this.selected);
|
|
302
378
|
}
|
|
303
379
|
}
|
|
304
380
|
__decorate([
|
|
305
381
|
observable,
|
|
306
382
|
__metadata("design:type", Object)
|
|
307
|
-
], FilterStore.prototype, "
|
|
383
|
+
], FilterStore.prototype, "selected", void 0);
|
|
308
384
|
__decorate([
|
|
309
385
|
observable,
|
|
310
386
|
__metadata("design:type", Array)
|
|
@@ -334,9 +410,9 @@ __decorate([
|
|
|
334
410
|
__decorate([
|
|
335
411
|
action,
|
|
336
412
|
__metadata("design:type", Object)
|
|
337
|
-
], FilterStore.prototype, "
|
|
413
|
+
], FilterStore.prototype, "uncheckDisabledOptions", void 0);
|
|
338
414
|
__decorate([
|
|
339
415
|
action,
|
|
340
416
|
__metadata("design:type", Object)
|
|
341
|
-
], FilterStore.prototype, "
|
|
417
|
+
], FilterStore.prototype, "initLocalUiFilters", void 0);
|
|
342
418
|
//# sourceMappingURL=filter.store.js.map
|