@xh/hoist 76.0.0-SNAPSHOT.1755706862648 → 76.0.0-SNAPSHOT.1755780982882
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 +7 -0
- package/build/types/core/HoistAppModel.d.ts +5 -2
- package/build/types/core/XH.d.ts +4 -2
- package/build/types/desktop/cmp/grid/impl/filter/headerfilter/HeaderFilterModel.d.ts +10 -7
- package/build/types/svc/PrefService.d.ts +0 -5
- package/core/HoistAppModel.ts +9 -3
- package/core/XH.ts +14 -4
- 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/svc/PrefService.ts +0 -12
- package/tsconfig.tsbuildinfo +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,17 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
## 76.0.0-SNAPSHOT - unreleased
|
|
4
4
|
|
|
5
|
+
### 💥 Breaking Changes (upgrade difficulty: 🟢 LOW - requires hoist-core v31.2)
|
|
6
|
+
|
|
5
7
|
### 🎁 New Features
|
|
6
8
|
|
|
7
9
|
* Added new `extraConfirmText`, `extraConfirmLabel` properties to `MessageOptions`. Use this option
|
|
8
10
|
to require the specified text to be re-typed by a user when confirming a potentially destructive
|
|
9
11
|
or disruptive action.
|
|
12
|
+
* Updated grid column filters to apply on `Enter` / dismiss on `Esc` and tweaked the filter popup
|
|
13
|
+
toolbar for clarity.
|
|
10
14
|
|
|
11
15
|
### 🐞 Bug Fixes
|
|
12
16
|
|
|
13
17
|
* Handled an edge-case `ViewManager` bug where `enableDefault` changed to `false` after some user
|
|
14
18
|
state had already been persisted w/users pointed at in-code default view. The manager now calls
|
|
15
19
|
its configured `initialViewSpec` function as expected in this case.
|
|
20
|
+
|
|
21
|
+
* `XH.restoreDefaultsAsync` will now clear basic view state. Views themselves will be preserved.
|
|
22
|
+
Requires hoist-core v31.2
|
|
16
23
|
|
|
17
24
|
### ⚙️ Technical
|
|
18
25
|
|
|
@@ -51,12 +51,15 @@ export declare class HoistAppModel extends HoistModel {
|
|
|
51
51
|
/**
|
|
52
52
|
* Resets user preferences and any persistent local application state.
|
|
53
53
|
*
|
|
54
|
-
* The default implementation for this method will clear
|
|
54
|
+
* The default implementation for this method will clear all preferences, local storage, and
|
|
55
|
+
* transient view state such as current, and pinned views. Views themselves are preserved.
|
|
55
56
|
*
|
|
56
|
-
* Applications may wish to override this method to
|
|
57
|
+
* Applications may wish to override this method to perform a more targeted clearing of state.
|
|
57
58
|
* This is important for complex applications with smaller sub-applications, and/or device
|
|
58
59
|
* specific applications. These applications will typically want to perform a custom clearing
|
|
59
60
|
* that is more targeted, and includes any additional app-specific state.
|
|
61
|
+
*
|
|
62
|
+
* Not typically called directly by applications. Call XH.restoreDefaultsAsync() instead.
|
|
60
63
|
*/
|
|
61
64
|
restoreDefaultsAsync(): Promise<void>;
|
|
62
65
|
}
|
package/build/types/core/XH.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ import { ToastModel } from '../appcontainer/ToastModel';
|
|
|
11
11
|
import '../styles/XH.scss';
|
|
12
12
|
import { AppSpec, AppState, AppSuspendData, BannerSpec, ExceptionHandler, ExceptionHandlerOptions, HoistAppModel, HoistException, HoistService, HoistServiceClass, HoistUser, MessageSpec, PageState, PlainObject, ReloadAppOptions, SizingMode, TaskObserver, Theme, ToastSpec, TrackOptions } from './';
|
|
13
13
|
import { HoistModel, ModelSelector, RefreshContextModel } from './model';
|
|
14
|
-
export declare const MIN_HOIST_CORE_VERSION = "
|
|
14
|
+
export declare const MIN_HOIST_CORE_VERSION = "31.2";
|
|
15
15
|
/**
|
|
16
16
|
* Top-level Singleton model for Hoist. This is the main entry point for the API.
|
|
17
17
|
*
|
|
@@ -396,7 +396,9 @@ export declare class XHApi {
|
|
|
396
396
|
/** All Stores registered with this application. */
|
|
397
397
|
getStores(): Store[];
|
|
398
398
|
/**
|
|
399
|
-
* Reset user
|
|
399
|
+
* Reset user state and then reload the app.
|
|
400
|
+
*
|
|
401
|
+
* @see HoistAppModel.restoreDefaultsAsync()
|
|
400
402
|
*/
|
|
401
403
|
restoreDefaultsAsync(): Promise<void>;
|
|
402
404
|
/**
|
|
@@ -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;
|
|
@@ -56,11 +56,6 @@ export declare class PrefService extends HoistService {
|
|
|
56
56
|
* before making another call that relies on its updated value being read on the server.
|
|
57
57
|
*/
|
|
58
58
|
pushAsync(key: string, value: any): Promise<void>;
|
|
59
|
-
/**
|
|
60
|
-
* Reset *all* preferences, reverting their effective values back to defaults.
|
|
61
|
-
* @returns a Promise that resolves when preferences have been cleared and defaults reloaded.
|
|
62
|
-
*/
|
|
63
|
-
clearAllAsync(): Promise<void>;
|
|
64
59
|
/**
|
|
65
60
|
* Push any pending buffered updates to persist newly set values to server.
|
|
66
61
|
* Called automatically by this app on page unload to avoid dropping changes when e.g. a user
|
package/core/HoistAppModel.ts
CHANGED
|
@@ -88,16 +88,22 @@ export class HoistAppModel extends HoistModel {
|
|
|
88
88
|
/**
|
|
89
89
|
* Resets user preferences and any persistent local application state.
|
|
90
90
|
*
|
|
91
|
-
* The default implementation for this method will clear
|
|
91
|
+
* The default implementation for this method will clear all preferences, local storage, and
|
|
92
|
+
* transient view state such as current, and pinned views. Views themselves are preserved.
|
|
92
93
|
*
|
|
93
|
-
* Applications may wish to override this method to
|
|
94
|
+
* Applications may wish to override this method to perform a more targeted clearing of state.
|
|
94
95
|
* This is important for complex applications with smaller sub-applications, and/or device
|
|
95
96
|
* specific applications. These applications will typically want to perform a custom clearing
|
|
96
97
|
* that is more targeted, and includes any additional app-specific state.
|
|
98
|
+
*
|
|
99
|
+
* Not typically called directly by applications. Call XH.restoreDefaultsAsync() instead.
|
|
97
100
|
*/
|
|
98
101
|
async restoreDefaultsAsync() {
|
|
99
102
|
const XH = window['XH'];
|
|
100
|
-
await XH.
|
|
103
|
+
await XH.fetchJson({
|
|
104
|
+
url: 'xh/clearUserState',
|
|
105
|
+
params: {clientUsername: XH.getUsername()}
|
|
106
|
+
});
|
|
101
107
|
XH.localStorageService.clear();
|
|
102
108
|
XH.sessionStorageService.clear();
|
|
103
109
|
}
|
package/core/XH.ts
CHANGED
|
@@ -67,7 +67,7 @@ import {instanceManager} from './impl/InstanceManager';
|
|
|
67
67
|
import {HoistModel, ModelSelector, RefreshContextModel} from './model';
|
|
68
68
|
import ShortUniqueId from 'short-unique-id';
|
|
69
69
|
|
|
70
|
-
export const MIN_HOIST_CORE_VERSION = '
|
|
70
|
+
export const MIN_HOIST_CORE_VERSION = '31.2';
|
|
71
71
|
|
|
72
72
|
declare const xhAppCode: string;
|
|
73
73
|
declare const xhAppName: string;
|
|
@@ -772,11 +772,21 @@ export class XHApi {
|
|
|
772
772
|
}
|
|
773
773
|
|
|
774
774
|
/**
|
|
775
|
-
* Reset user
|
|
775
|
+
* Reset user state and then reload the app.
|
|
776
|
+
*
|
|
777
|
+
* @see HoistAppModel.restoreDefaultsAsync()
|
|
776
778
|
*/
|
|
777
779
|
async restoreDefaultsAsync() {
|
|
778
|
-
|
|
779
|
-
|
|
780
|
+
try {
|
|
781
|
+
await this.appModel.restoreDefaultsAsync();
|
|
782
|
+
XH.trackService.track({category: 'App', message: 'Restored app defaults'});
|
|
783
|
+
this.reloadApp();
|
|
784
|
+
} catch (e) {
|
|
785
|
+
XH.handleException(e, {
|
|
786
|
+
message: 'Failed to restore app defaults',
|
|
787
|
+
requireReload: true
|
|
788
|
+
});
|
|
789
|
+
}
|
|
780
790
|
}
|
|
781
791
|
|
|
782
792
|
/**
|
|
@@ -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.1755780982882",
|
|
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",
|
package/svc/PrefService.ts
CHANGED
|
@@ -110,18 +110,6 @@ export class PrefService extends HoistService {
|
|
|
110
110
|
return this.pushPendingAsync();
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
-
/**
|
|
114
|
-
* Reset *all* preferences, reverting their effective values back to defaults.
|
|
115
|
-
* @returns a Promise that resolves when preferences have been cleared and defaults reloaded.
|
|
116
|
-
*/
|
|
117
|
-
async clearAllAsync() {
|
|
118
|
-
await XH.fetchJson({
|
|
119
|
-
url: 'xh/clearPrefs',
|
|
120
|
-
params: {clientUsername: XH.getUsername()}
|
|
121
|
-
});
|
|
122
|
-
return this.loadPrefsAsync();
|
|
123
|
-
}
|
|
124
|
-
|
|
125
113
|
/**
|
|
126
114
|
* Push any pending buffered updates to persist newly set values to server.
|
|
127
115
|
* Called automatically by this app on page unload to avoid dropping changes when e.g. a user
|