@xh/hoist 76.0.0-SNAPSHOT.1755703653662 → 76.0.0-SNAPSHOT.1755706915375
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 +2 -0
- package/admin/jsonsearch/JsonSearch.ts +9 -0
- package/build/types/desktop/cmp/grid/impl/filter/headerfilter/HeaderFilterModel.d.ts +10 -7
- package/desktop/cmp/grid/impl/filter/headerfilter/HeaderFilter.ts +29 -10
- package/desktop/cmp/grid/impl/filter/headerfilter/HeaderFilterModel.ts +32 -12
- package/desktop/cmp/grid/impl/filter/headerfilter/values/ValuesTabModel.ts +2 -0
- package/package.json +1 -1
- package/tsconfig.tsbuildinfo +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
* Added new `extraConfirmText`, `extraConfirmLabel` properties to `MessageOptions`. Use this option
|
|
8
8
|
to require the specified text to be re-typed by a user when confirming a potentially destructive
|
|
9
9
|
or disruptive action.
|
|
10
|
+
* Updated grid column filters to apply on `Enter` / dismiss on `Esc` and tweaked the filter popup
|
|
11
|
+
toolbar for clarity.
|
|
10
12
|
|
|
11
13
|
### 🐞 Bug Fixes
|
|
12
14
|
|
|
@@ -296,5 +296,14 @@ const queryExamples = [
|
|
|
296
296
|
{
|
|
297
297
|
query: '$..grid[?(@.version == 1)]',
|
|
298
298
|
explanation: 'Find all nodes with a key of "grid" and a property "version" equal to 1'
|
|
299
|
+
},
|
|
300
|
+
{
|
|
301
|
+
query: '$.currentView[?(@.desktop == null && @.desktop)]',
|
|
302
|
+
explanation:
|
|
303
|
+
'Find all JSON documents with path "currentView.desktop" that is explicitly set to null'
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
query: '$.[?(@ == "someString")]',
|
|
307
|
+
explanation: 'Find all JSON documents with an array that contains the value "someString"'
|
|
299
308
|
}
|
|
300
309
|
];
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { TabContainerModel } from '@xh/hoist/cmp/tab';
|
|
2
2
|
import { HoistModel } from '@xh/hoist/core';
|
|
3
|
-
import {
|
|
3
|
+
import { CompoundFilter, FieldFilter, FieldType, Filter, FilterLike, Store } from '@xh/hoist/data';
|
|
4
|
+
import { GridFilterFieldSpec, GridFilterModel } from '@xh/hoist/cmp/grid';
|
|
4
5
|
import { CustomTabModel } from './custom/CustomTabModel';
|
|
5
6
|
import { ValuesTabModel } from './values/ValuesTabModel';
|
|
6
7
|
import { ColumnHeaderFilterModel } from '../ColumnHeaderFilterModel';
|
|
@@ -11,15 +12,17 @@ export declare class HeaderFilterModel extends HoistModel {
|
|
|
11
12
|
tabContainerModel: TabContainerModel;
|
|
12
13
|
valuesTabModel: ValuesTabModel;
|
|
13
14
|
customTabModel: CustomTabModel;
|
|
14
|
-
get filterModel():
|
|
15
|
+
get filterModel(): GridFilterModel;
|
|
15
16
|
get field(): string;
|
|
16
|
-
get store():
|
|
17
|
-
get fieldType():
|
|
18
|
-
get currentGridFilter():
|
|
19
|
-
get columnFilters():
|
|
20
|
-
get columnCompoundFilter():
|
|
17
|
+
get store(): Store;
|
|
18
|
+
get fieldType(): FieldType;
|
|
19
|
+
get currentGridFilter(): Filter;
|
|
20
|
+
get columnFilters(): FieldFilter[];
|
|
21
|
+
get columnCompoundFilter(): CompoundFilter;
|
|
21
22
|
get hasFilter(): boolean;
|
|
23
|
+
get pendingFilter(): FilterLike;
|
|
22
24
|
get hasPendingFilter(): boolean;
|
|
25
|
+
get isDirty(): boolean;
|
|
23
26
|
get isCustomFilter(): boolean;
|
|
24
27
|
get commitOnChange(): boolean;
|
|
25
28
|
onLinked(): void;
|
|
@@ -12,6 +12,7 @@ import {button, buttonGroup} from '@xh/hoist/desktop/cmp/button';
|
|
|
12
12
|
import {panel} from '@xh/hoist/desktop/cmp/panel';
|
|
13
13
|
import {toolbar} from '@xh/hoist/desktop/cmp/toolbar';
|
|
14
14
|
import {Icon} from '@xh/hoist/icon';
|
|
15
|
+
import {wait} from '@xh/hoist/promise';
|
|
15
16
|
import {stopPropagation} from '@xh/hoist/utils/js';
|
|
16
17
|
import {HeaderFilterModel} from './HeaderFilterModel';
|
|
17
18
|
|
|
@@ -22,7 +23,7 @@ import {HeaderFilterModel} from './HeaderFilterModel';
|
|
|
22
23
|
*/
|
|
23
24
|
export const headerFilter = hoistCmp.factory({
|
|
24
25
|
model: creates(HeaderFilterModel),
|
|
25
|
-
render() {
|
|
26
|
+
render({model}) {
|
|
26
27
|
return panel({
|
|
27
28
|
title: `Filter`,
|
|
28
29
|
className: 'xh-column-header-filter',
|
|
@@ -31,31 +32,49 @@ export const headerFilter = hoistCmp.factory({
|
|
|
31
32
|
onDoubleClick: stopPropagation,
|
|
32
33
|
headerItems: [switcher()],
|
|
33
34
|
item: tabContainer(),
|
|
34
|
-
bbar: bbar()
|
|
35
|
+
bbar: bbar(),
|
|
36
|
+
hotkeys: [
|
|
37
|
+
{
|
|
38
|
+
allowInInput: true,
|
|
39
|
+
combo: 'enter',
|
|
40
|
+
label: 'Apply',
|
|
41
|
+
group: 'Column Filter',
|
|
42
|
+
onKeyDown: () =>
|
|
43
|
+
// Wait for debounced reaction in `ValuesTabModel` to run before committing
|
|
44
|
+
wait(400).then(() => {
|
|
45
|
+
if (model.isDirty) model.commit();
|
|
46
|
+
})
|
|
47
|
+
}
|
|
48
|
+
]
|
|
35
49
|
});
|
|
36
50
|
}
|
|
37
51
|
});
|
|
38
52
|
|
|
39
53
|
const bbar = hoistCmp.factory<HeaderFilterModel>({
|
|
40
54
|
render({model}) {
|
|
41
|
-
const {commitOnChange} = model;
|
|
55
|
+
const {commitOnChange, hasFilter, isDirty} = model;
|
|
42
56
|
return toolbar({
|
|
43
57
|
compact: true,
|
|
44
58
|
items: [
|
|
45
|
-
filler(),
|
|
46
59
|
button({
|
|
47
60
|
icon: Icon.delete(),
|
|
48
|
-
text: 'Clear
|
|
61
|
+
text: 'Clear',
|
|
49
62
|
intent: 'danger',
|
|
50
|
-
disabled: !
|
|
63
|
+
disabled: !hasFilter,
|
|
51
64
|
onClick: () => model.clear()
|
|
52
65
|
}),
|
|
66
|
+
filler(),
|
|
67
|
+
button({
|
|
68
|
+
omit: commitOnChange,
|
|
69
|
+
text: 'Cancel',
|
|
70
|
+
onClick: () => model.parent.close()
|
|
71
|
+
}),
|
|
53
72
|
button({
|
|
54
73
|
omit: commitOnChange,
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
intent: '
|
|
58
|
-
|
|
74
|
+
text: 'Apply',
|
|
75
|
+
disabled: !isDirty,
|
|
76
|
+
intent: 'primary',
|
|
77
|
+
minimal: false,
|
|
59
78
|
onClick: () => model.commit()
|
|
60
79
|
})
|
|
61
80
|
]
|
|
@@ -7,10 +7,19 @@
|
|
|
7
7
|
|
|
8
8
|
import {TabContainerModel} from '@xh/hoist/cmp/tab';
|
|
9
9
|
import {HoistModel, managed, lookup} from '@xh/hoist/core';
|
|
10
|
+
import {
|
|
11
|
+
CompoundFilter,
|
|
12
|
+
FieldFilter,
|
|
13
|
+
FieldType,
|
|
14
|
+
Filter,
|
|
15
|
+
FilterLike,
|
|
16
|
+
parseFilter,
|
|
17
|
+
Store
|
|
18
|
+
} from '@xh/hoist/data';
|
|
10
19
|
import {action, computed} from '@xh/hoist/mobx';
|
|
11
20
|
import {wait} from '@xh/hoist/promise';
|
|
12
21
|
import {isEmpty} from 'lodash';
|
|
13
|
-
import {GridFilterFieldSpec} from '@xh/hoist/cmp/grid';
|
|
22
|
+
import {GridFilterFieldSpec, GridFilterModel} from '@xh/hoist/cmp/grid';
|
|
14
23
|
import {customTab} from './custom/CustomTab';
|
|
15
24
|
import {CustomTabModel} from './custom/CustomTabModel';
|
|
16
25
|
import {valuesTab} from './values/ValuesTab';
|
|
@@ -29,43 +38,54 @@ export class HeaderFilterModel extends HoistModel {
|
|
|
29
38
|
@managed valuesTabModel: ValuesTabModel;
|
|
30
39
|
@managed customTabModel: CustomTabModel;
|
|
31
40
|
|
|
32
|
-
get filterModel() {
|
|
41
|
+
get filterModel(): GridFilterModel {
|
|
33
42
|
return this.parent.filterModel;
|
|
34
43
|
}
|
|
35
44
|
|
|
36
|
-
get field() {
|
|
45
|
+
get field(): string {
|
|
37
46
|
return this.fieldSpec.field;
|
|
38
47
|
}
|
|
39
48
|
|
|
40
|
-
get store() {
|
|
49
|
+
get store(): Store {
|
|
41
50
|
return this.filterModel.gridModel.store;
|
|
42
51
|
}
|
|
43
52
|
|
|
44
|
-
get fieldType() {
|
|
53
|
+
get fieldType(): FieldType {
|
|
45
54
|
return this.store.getField(this.field).type;
|
|
46
55
|
}
|
|
47
56
|
|
|
48
|
-
get currentGridFilter() {
|
|
57
|
+
get currentGridFilter(): Filter {
|
|
49
58
|
return this.filterModel.filter;
|
|
50
59
|
}
|
|
51
60
|
|
|
52
|
-
get columnFilters() {
|
|
61
|
+
get columnFilters(): FieldFilter[] {
|
|
53
62
|
return this.filterModel.getColumnFilters(this.field);
|
|
54
63
|
}
|
|
55
64
|
|
|
56
|
-
get columnCompoundFilter() {
|
|
65
|
+
get columnCompoundFilter(): CompoundFilter {
|
|
57
66
|
return this.filterModel.getColumnCompoundFilter(this.field);
|
|
58
67
|
}
|
|
59
68
|
|
|
60
|
-
get hasFilter() {
|
|
69
|
+
get hasFilter(): boolean {
|
|
61
70
|
return !isEmpty(this.columnFilters);
|
|
62
71
|
}
|
|
63
72
|
|
|
64
|
-
get
|
|
73
|
+
get pendingFilter(): FilterLike {
|
|
65
74
|
const {activeTabId} = this.tabContainerModel;
|
|
66
75
|
return activeTabId === 'valuesFilter'
|
|
67
|
-
?
|
|
68
|
-
:
|
|
76
|
+
? this.valuesTabModel.filter
|
|
77
|
+
: this.customTabModel.filter;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
get hasPendingFilter(): boolean {
|
|
81
|
+
return !!this.pendingFilter;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
@computed
|
|
85
|
+
get isDirty(): boolean {
|
|
86
|
+
const current = parseFilter(this.columnFilters),
|
|
87
|
+
pending = parseFilter(this.pendingFilter);
|
|
88
|
+
return current ? !current.equals(pending) : !!pending;
|
|
69
89
|
}
|
|
70
90
|
|
|
71
91
|
@computed
|
|
@@ -96,6 +96,8 @@ export class ValuesTabModel extends HoistModel {
|
|
|
96
96
|
{
|
|
97
97
|
track: () => this.filterText,
|
|
98
98
|
run: () => this.onFilterTextChange(),
|
|
99
|
+
// Must be longer than the `filterBuffer` on `storeFilterField` since this Grid's
|
|
100
|
+
// filtered RecordSet must be current before `onFilterTextChange` can run.
|
|
99
101
|
debounce: 300
|
|
100
102
|
},
|
|
101
103
|
{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xh/hoist",
|
|
3
|
-
"version": "76.0.0-SNAPSHOT.
|
|
3
|
+
"version": "76.0.0-SNAPSHOT.1755706915375",
|
|
4
4
|
"description": "Hoist add-on for building and deploying React Applications.",
|
|
5
5
|
"repository": "github:xh/hoist-react",
|
|
6
6
|
"homepage": "https://xh.io",
|