@xh/hoist 72.0.0 → 72.2.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 +41 -2
- package/admin/jsonsearch/JsonSearch.ts +294 -0
- package/admin/jsonsearch/impl/JsonSearchImplModel.ts +175 -0
- package/admin/tabs/activity/clienterrors/ClientErrorsModel.ts +23 -4
- package/admin/tabs/general/config/ConfigPanel.ts +26 -4
- package/admin/tabs/userData/jsonblob/JsonBlobPanel.ts +47 -10
- package/admin/tabs/userData/prefs/UserPreferencePanel.ts +45 -15
- package/admin/tabs/userData/roles/RoleModel.ts +3 -3
- package/admin/tabs/userData/roles/details/RoleDetailsModel.ts +2 -1
- package/admin/tabs/userData/roles/editor/form/RoleFormModel.ts +3 -3
- package/admin/tabs/userData/roles/recategorize/RecategorizeDialogModel.ts +1 -1
- package/build/types/admin/jsonsearch/JsonSearch.d.ts +17 -0
- package/build/types/admin/jsonsearch/impl/JsonSearchImplModel.d.ts +32 -0
- package/build/types/cmp/tab/TabContainerModel.d.ts +5 -5
- package/build/types/core/HoistProps.d.ts +1 -0
- package/build/types/core/XH.d.ts +5 -5
- package/build/types/core/persist/PersistenceProvider.d.ts +4 -0
- package/build/types/core/types/Interfaces.d.ts +9 -0
- package/build/types/data/Store.d.ts +4 -0
- package/build/types/data/StoreRecord.d.ts +2 -0
- package/build/types/desktop/cmp/appOption/AutoRefreshAppOption.d.ts +1 -0
- package/build/types/desktop/cmp/appOption/ThemeAppOption.d.ts +1 -0
- package/build/types/kit/blueprint/Wrappers.d.ts +1 -1
- package/build/types/kit/swiper/index.d.ts +4 -4
- package/build/types/security/BaseOAuthClient.d.ts +19 -21
- package/build/types/security/Token.d.ts +0 -1
- package/build/types/security/Types.d.ts +12 -0
- package/build/types/security/authzero/AuthZeroClient.d.ts +3 -4
- package/build/types/security/msal/MsalClient.d.ts +3 -4
- package/cmp/filter/FilterChooserModel.ts +6 -2
- package/cmp/grid/impl/InitPersist.ts +9 -3
- package/cmp/grouping/GroupingChooserModel.ts +6 -2
- package/cmp/tab/TabContainerModel.ts +5 -5
- package/cmp/zoneGrid/impl/InitPersist.ts +9 -3
- package/core/HoistBase.ts +1 -2
- package/core/HoistBaseDecorators.ts +4 -1
- package/core/HoistProps.ts +1 -0
- package/core/XH.ts +13 -5
- package/core/exception/Exception.ts +19 -12
- package/core/persist/PersistenceProvider.ts +31 -0
- package/core/types/Interfaces.ts +11 -0
- package/data/Store.ts +13 -3
- package/data/StoreRecord.ts +6 -1
- package/data/cube/row/BaseRow.ts +3 -2
- package/desktop/appcontainer/ExceptionDialog.ts +1 -1
- package/desktop/cmp/dash/canvas/DashCanvas.ts +2 -1
- package/mobile/cmp/navigator/NavigatorModel.ts +7 -0
- package/package.json +1 -1
- package/security/BaseOAuthClient.ts +41 -36
- package/security/Token.ts +0 -2
- package/security/Types.ts +22 -0
- package/security/authzero/AuthZeroClient.ts +6 -8
- package/security/msal/MsalClient.ts +6 -8
- package/tsconfig.tsbuildinfo +1 -1
- package/utils/react/LayoutPropUtils.ts +2 -1
|
@@ -5,10 +5,15 @@
|
|
|
5
5
|
* Copyright © 2025 Extremely Heavy Industries Inc.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import
|
|
8
|
+
import * as Col from '@xh/hoist/admin/columns/Rest';
|
|
9
|
+
import * as AdminCol from '@xh/hoist/admin/columns';
|
|
10
|
+
import {hframe} from '@xh/hoist/cmp/layout';
|
|
9
11
|
import {creates, hoistCmp} from '@xh/hoist/core';
|
|
10
12
|
import {button} from '@xh/hoist/desktop/cmp/button';
|
|
13
|
+
import {jsonSearchButton} from '@xh/hoist/admin/jsonsearch/JsonSearch';
|
|
14
|
+
import {panel} from '@xh/hoist/desktop/cmp/panel';
|
|
11
15
|
import {restGrid} from '@xh/hoist/desktop/cmp/rest';
|
|
16
|
+
import {toolbarSep} from '@xh/hoist/desktop/cmp/toolbar';
|
|
12
17
|
import {Icon} from '@xh/hoist/icon';
|
|
13
18
|
import {differ} from '../../../differ/Differ';
|
|
14
19
|
import {JsonBlobModel} from './JsonBlobModel';
|
|
@@ -17,15 +22,47 @@ export const jsonBlobPanel = hoistCmp.factory({
|
|
|
17
22
|
model: creates(JsonBlobModel),
|
|
18
23
|
|
|
19
24
|
render({model}) {
|
|
20
|
-
return
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
return hframe(
|
|
26
|
+
panel({
|
|
27
|
+
item: restGrid({
|
|
28
|
+
extraToolbarItems: () => [
|
|
29
|
+
button({
|
|
30
|
+
icon: Icon.diff(),
|
|
31
|
+
text: 'Compare w/ Remote',
|
|
32
|
+
onClick: () => model.openDiffer()
|
|
33
|
+
}),
|
|
34
|
+
toolbarSep(),
|
|
35
|
+
jsonSearchButton({
|
|
36
|
+
subjectName: 'JSON Blob',
|
|
37
|
+
docSearchUrl: 'jsonSearch/searchBlobs',
|
|
38
|
+
gridModelConfig: {
|
|
39
|
+
sortBy: ['type', 'name', 'owner'],
|
|
40
|
+
columns: [
|
|
41
|
+
{
|
|
42
|
+
field: {name: 'token', type: 'string'},
|
|
43
|
+
hidden: true,
|
|
44
|
+
width: 100
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
field: {name: 'type', type: 'string'},
|
|
48
|
+
width: 200
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
field: {name: 'owner', type: 'string'},
|
|
52
|
+
width: 200
|
|
53
|
+
},
|
|
54
|
+
{...AdminCol.name},
|
|
55
|
+
{
|
|
56
|
+
field: {name: 'json', type: 'string'},
|
|
57
|
+
hidden: true
|
|
58
|
+
},
|
|
59
|
+
{...Col.lastUpdated}
|
|
60
|
+
]
|
|
61
|
+
},
|
|
62
|
+
groupByOptions: ['owner', 'type', 'name']
|
|
63
|
+
})
|
|
64
|
+
]
|
|
65
|
+
})
|
|
29
66
|
}),
|
|
30
67
|
differ({omit: !model.differModel})
|
|
31
68
|
);
|
|
@@ -4,32 +4,62 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Copyright © 2025 Extremely Heavy Industries Inc.
|
|
6
6
|
*/
|
|
7
|
+
|
|
8
|
+
import * as Col from '@xh/hoist/admin/columns/Rest';
|
|
9
|
+
import * as AdminCol from '@xh/hoist/admin/columns';
|
|
7
10
|
import {prefEditorDialog} from '@xh/hoist/admin/tabs/userData/prefs/editor/PrefEditorDialog';
|
|
8
11
|
import {UserPreferenceModel} from '@xh/hoist/admin/tabs/userData/prefs/UserPreferenceModel';
|
|
12
|
+
import {hframe} from '@xh/hoist/cmp/layout';
|
|
9
13
|
import {creates, hoistCmp} from '@xh/hoist/core';
|
|
10
14
|
import {button} from '@xh/hoist/desktop/cmp/button';
|
|
15
|
+
import {jsonSearchButton} from '@xh/hoist/admin/jsonsearch/JsonSearch';
|
|
11
16
|
import {panel} from '@xh/hoist/desktop/cmp/panel';
|
|
12
17
|
import {restGrid} from '@xh/hoist/desktop/cmp/rest';
|
|
18
|
+
import {toolbarSep} from '@xh/hoist/desktop/cmp/toolbar';
|
|
13
19
|
import {Icon} from '@xh/hoist/icon';
|
|
14
20
|
|
|
15
21
|
export const userPreferencePanel = hoistCmp.factory({
|
|
16
22
|
model: creates(UserPreferenceModel),
|
|
17
23
|
|
|
18
24
|
render({model}) {
|
|
19
|
-
return
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
25
|
+
return hframe(
|
|
26
|
+
panel({
|
|
27
|
+
items: [
|
|
28
|
+
restGrid({
|
|
29
|
+
extraToolbarItems: () => [
|
|
30
|
+
button({
|
|
31
|
+
icon: Icon.gear(),
|
|
32
|
+
text: 'Configure',
|
|
33
|
+
onClick: () => (model.showEditorDialog = true)
|
|
34
|
+
}),
|
|
35
|
+
toolbarSep(),
|
|
36
|
+
jsonSearchButton({
|
|
37
|
+
subjectName: 'User Preference',
|
|
38
|
+
docSearchUrl: 'jsonSearch/searchUserPreferences',
|
|
39
|
+
gridModelConfig: {
|
|
40
|
+
sortBy: ['groupName', 'name', 'owner'],
|
|
41
|
+
columns: [
|
|
42
|
+
{
|
|
43
|
+
field: {name: 'owner', type: 'string'},
|
|
44
|
+
width: 200
|
|
45
|
+
},
|
|
46
|
+
{...AdminCol.groupName},
|
|
47
|
+
{...AdminCol.name},
|
|
48
|
+
{
|
|
49
|
+
field: {name: 'json', type: 'string'},
|
|
50
|
+
hidden: true
|
|
51
|
+
},
|
|
52
|
+
{...Col.lastUpdated}
|
|
53
|
+
]
|
|
54
|
+
},
|
|
55
|
+
groupByOptions: ['owner', 'groupName', 'name']
|
|
56
|
+
})
|
|
57
|
+
]
|
|
58
|
+
}),
|
|
59
|
+
prefEditorDialog()
|
|
60
|
+
],
|
|
61
|
+
mask: 'onLoad'
|
|
62
|
+
})
|
|
63
|
+
);
|
|
34
64
|
}
|
|
35
65
|
});
|
|
@@ -80,7 +80,7 @@ export class RoleModel extends HoistModel {
|
|
|
80
80
|
runInAction(() => {
|
|
81
81
|
this.allRoles = this.processRolesFromServer(data);
|
|
82
82
|
});
|
|
83
|
-
this.displayRoles();
|
|
83
|
+
this.displayRoles(loadSpec.isRefresh);
|
|
84
84
|
await this.gridModel.preSelectFirstAsync();
|
|
85
85
|
} catch (e) {
|
|
86
86
|
if (loadSpec.isStale) return;
|
|
@@ -212,13 +212,13 @@ export class RoleModel extends HoistModel {
|
|
|
212
212
|
//------------------
|
|
213
213
|
// Implementation
|
|
214
214
|
//------------------
|
|
215
|
-
private displayRoles() {
|
|
215
|
+
private displayRoles(isRefresh?: boolean) {
|
|
216
216
|
const {gridModel} = this,
|
|
217
217
|
gridData = this.showInGroups
|
|
218
218
|
? this.processRolesForTreeGrid(this.allRoles)
|
|
219
219
|
: this.allRoles;
|
|
220
220
|
gridModel.loadData(gridData);
|
|
221
|
-
gridModel.expandAll();
|
|
221
|
+
if (!isRefresh) gridModel.expandAll();
|
|
222
222
|
gridModel.autosizeAsync({includeCollapsedChildren: true});
|
|
223
223
|
}
|
|
224
224
|
|
|
@@ -44,7 +44,7 @@ export class RoleDetailsModel extends HoistModel {
|
|
|
44
44
|
);
|
|
45
45
|
|
|
46
46
|
this.setTabTitle('users', 'Users', role?.effectiveUsers);
|
|
47
|
-
this.setTabTitle('directories', '
|
|
47
|
+
this.setTabTitle('directories', 'Dir. Groups', role?.effectiveDirectoryGroups);
|
|
48
48
|
this.setTabTitle('effectiveRoles', 'Granted To', role?.effectiveRoles);
|
|
49
49
|
this.setTabTitle('inheritedRoles', 'Inheriting From', role?.inheritedRoles);
|
|
50
50
|
},
|
|
@@ -77,6 +77,7 @@ export class RoleDetailsModel extends HoistModel {
|
|
|
77
77
|
},
|
|
78
78
|
{
|
|
79
79
|
id: 'directories',
|
|
80
|
+
title: 'Dir. Groups',
|
|
80
81
|
omit: !this.roleModel.moduleConfig.directoryGroupsSupported,
|
|
81
82
|
content: directoryMembers
|
|
82
83
|
},
|
|
@@ -46,9 +46,9 @@ export class RoleFormModel extends HoistModel {
|
|
|
46
46
|
@computed
|
|
47
47
|
get hasDirtyMembers(): boolean {
|
|
48
48
|
return (
|
|
49
|
-
this.usersGridModel.store.
|
|
50
|
-
this.directoryGroupsGridModel.store.
|
|
51
|
-
this.rolesGridModel.store.
|
|
49
|
+
this.usersGridModel.store.isDirty ||
|
|
50
|
+
this.directoryGroupsGridModel.store.isDirty ||
|
|
51
|
+
this.rolesGridModel.store.isDirty
|
|
52
52
|
);
|
|
53
53
|
}
|
|
54
54
|
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { GridConfig } from '@xh/hoist/cmp/grid';
|
|
2
|
+
import { HoistProps, SelectOption } from '@xh/hoist/core';
|
|
3
|
+
export interface JsonSearchButtonProps extends HoistProps {
|
|
4
|
+
/** Descriptive label for the type of records being searched - will be auto-pluralized. */
|
|
5
|
+
subjectName: string;
|
|
6
|
+
/** Endpoint to search and return matches - Hoist `JsonSearchController` action expected. */
|
|
7
|
+
docSearchUrl: string;
|
|
8
|
+
/** Config for GridModel used to display search results. */
|
|
9
|
+
gridModelConfig: GridConfig;
|
|
10
|
+
/** Field names on returned results to enable for grouping in the search results grid. */
|
|
11
|
+
groupByOptions: Array<SelectOption | any>;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Main entry point component for the JSON search feature. Supported out-of-the-box for a limited
|
|
15
|
+
* set of Hoist artifacts that hold JSON values: JSONBlob, Configs, and User Preferences.
|
|
16
|
+
*/
|
|
17
|
+
export declare const jsonSearchButton: import("@xh/hoist/core").ElementFactory<JsonSearchButtonProps>;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { GridConfig, GridModel } from '@xh/hoist/cmp/grid';
|
|
2
|
+
import { HoistModel, TaskObserver } from '@xh/hoist/core';
|
|
3
|
+
/**
|
|
4
|
+
* @internal
|
|
5
|
+
*/
|
|
6
|
+
export declare class JsonSearchImplModel extends HoistModel {
|
|
7
|
+
xhImpl: boolean;
|
|
8
|
+
private matchingNodesUrl;
|
|
9
|
+
gridModel: GridModel;
|
|
10
|
+
docLoadTask: TaskObserver;
|
|
11
|
+
nodeLoadTask: TaskObserver;
|
|
12
|
+
groupBy: string;
|
|
13
|
+
isOpen: boolean;
|
|
14
|
+
error: any;
|
|
15
|
+
path: string;
|
|
16
|
+
readerContentType: 'document' | 'matches';
|
|
17
|
+
pathFormat: 'XPath' | 'JSONPath';
|
|
18
|
+
readerContent: string;
|
|
19
|
+
matchingNodeCount: number;
|
|
20
|
+
get subjectName(): string;
|
|
21
|
+
get docSearchUrl(): string;
|
|
22
|
+
get gridModelConfig(): GridConfig;
|
|
23
|
+
get selectedRecord(): import("../../../data").StoreRecord;
|
|
24
|
+
get groupByOptions(): any[];
|
|
25
|
+
toggleSearchIsOpen(): void;
|
|
26
|
+
constructor();
|
|
27
|
+
onLinked(): void;
|
|
28
|
+
loadMatchingDocsAsync(): Promise<void>;
|
|
29
|
+
private loadReaderContentAsync;
|
|
30
|
+
private convertToXPath;
|
|
31
|
+
private setGroupBy;
|
|
32
|
+
}
|
|
@@ -68,7 +68,7 @@ export declare class TabContainerModel extends HoistModel implements Persistable
|
|
|
68
68
|
refreshMode: RefreshMode;
|
|
69
69
|
emptyText: ReactNode;
|
|
70
70
|
refreshContextModel: RefreshContextModel;
|
|
71
|
-
|
|
71
|
+
protected lastActiveTabId: string;
|
|
72
72
|
constructor({ tabs, defaultTabId, route, switcher, track, renderMode, refreshMode, persistWith, emptyText, xhImpl }: TabContainerConfig);
|
|
73
73
|
/** Set/replace all tabs within the container. */
|
|
74
74
|
setTabs(tabs: Array<TabModel | TabConfig>): void;
|
|
@@ -110,10 +110,10 @@ export declare class TabContainerModel extends HoistModel implements Persistable
|
|
|
110
110
|
setPersistableState(state: PersistableState<{
|
|
111
111
|
activeTabId: string;
|
|
112
112
|
}>): void;
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
113
|
+
protected setActiveTabIdInternal(id: any): void;
|
|
114
|
+
protected syncWithRouter(): void;
|
|
115
|
+
protected forwardRouterToTab(id: any): void;
|
|
116
|
+
protected calculateActiveTabId(tabs: any): any;
|
|
117
117
|
}
|
|
118
118
|
export interface AddTabOptions {
|
|
119
119
|
/** Index in tab collection where tab is to be added. */
|
package/build/types/core/XH.d.ts
CHANGED
|
@@ -9,9 +9,9 @@ import { AppContainerModel } from '../appcontainer/AppContainerModel';
|
|
|
9
9
|
import { BannerModel } from '../appcontainer/BannerModel';
|
|
10
10
|
import { ToastModel } from '../appcontainer/ToastModel';
|
|
11
11
|
import '../styles/XH.scss';
|
|
12
|
-
import { AppSpec, AppState, AppSuspendData, BannerSpec, ExceptionHandler, ExceptionHandlerOptions, HoistAppModel, HoistException, HoistService, HoistServiceClass, HoistUser, MessageSpec, PageState, PlainObject, SizingMode, TaskObserver, Theme, ToastSpec, TrackOptions } from './';
|
|
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 = "28.0";
|
|
15
15
|
/**
|
|
16
16
|
* Top-level Singleton model for Hoist. This is the main entry point for the API.
|
|
17
17
|
*
|
|
@@ -193,13 +193,13 @@ export declare class XHApi {
|
|
|
193
193
|
/**
|
|
194
194
|
* Trigger a full reload of the current application.
|
|
195
195
|
*
|
|
196
|
-
* @param
|
|
197
|
-
*
|
|
196
|
+
* @param opts - options to govern reload. To support legacy usages, a provided
|
|
197
|
+
* string will be treated as `ReloadAppOptions.path`.
|
|
198
198
|
*
|
|
199
199
|
* This method will reload the entire application document in the browser - to trigger a
|
|
200
200
|
* refresh of the loadable content within the app, use {@link refreshAppAsync} instead.
|
|
201
201
|
*/
|
|
202
|
-
reloadApp(
|
|
202
|
+
reloadApp(opts?: ReloadAppOptions | string): void;
|
|
203
203
|
/**
|
|
204
204
|
* Refresh the current application.
|
|
205
205
|
*
|
|
@@ -41,6 +41,10 @@ export declare abstract class PersistenceProvider<S = any> {
|
|
|
41
41
|
* target without thrashing.
|
|
42
42
|
*/
|
|
43
43
|
static create<S>(cfg: PersistenceProviderConfig<S>): PersistenceProvider<S>;
|
|
44
|
+
/**
|
|
45
|
+
* Merge PersistOptions, respecting provider types, with later options overriding earlier ones.
|
|
46
|
+
*/
|
|
47
|
+
static mergePersistOptions(defaults: PersistOptions, ...overrides: PersistOptions[]): PersistOptions;
|
|
44
48
|
/** Read persisted state at this provider's path. */
|
|
45
49
|
read(): PersistableState<S>;
|
|
46
50
|
/** Persist JSON-serializable state to this provider's path. */
|
|
@@ -19,6 +19,15 @@ export interface HoistUser {
|
|
|
19
19
|
hasRole(s: string): boolean;
|
|
20
20
|
hasGate(s: string): boolean;
|
|
21
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* Options governing XH.reloadApp().
|
|
24
|
+
*/
|
|
25
|
+
export interface ReloadAppOptions {
|
|
26
|
+
/** Relative path to reload (e.g. 'mobile/'). Defaults to the existing location pathname. */
|
|
27
|
+
path?: string;
|
|
28
|
+
/** Should the query parameters be removed from the url before reload. Default false. */
|
|
29
|
+
removeQueryParams?: boolean;
|
|
30
|
+
}
|
|
22
31
|
/**
|
|
23
32
|
* Options for showing a "toast" notification that appears and then automatically dismisses.
|
|
24
33
|
*/
|
|
@@ -275,6 +275,8 @@ export declare class Store extends HoistBase {
|
|
|
275
275
|
/** Records removed locally which have not been committed.*/
|
|
276
276
|
get removedRecords(): StoreRecord[];
|
|
277
277
|
/** Records modified locally since they were last loaded. */
|
|
278
|
+
get dirtyRecords(): StoreRecord[];
|
|
279
|
+
/** Alias for {@link Store.dirtyRecords} */
|
|
278
280
|
get modifiedRecords(): StoreRecord[];
|
|
279
281
|
/**
|
|
280
282
|
* Root records in this store, respecting any filter (if applied).
|
|
@@ -292,6 +294,8 @@ export declare class Store extends HoistBase {
|
|
|
292
294
|
*/
|
|
293
295
|
get summaryRecord(): StoreRecord;
|
|
294
296
|
/** True if the store has changes which need to be committed. */
|
|
297
|
+
get isDirty(): boolean;
|
|
298
|
+
/** Alias for {@link Store.isDirty} */
|
|
295
299
|
get isModified(): boolean;
|
|
296
300
|
/**
|
|
297
301
|
* Set a filter on this store.
|
|
@@ -51,6 +51,8 @@ export declare class StoreRecord {
|
|
|
51
51
|
/** True if the StoreRecord has never been committed. */
|
|
52
52
|
get isAdd(): boolean;
|
|
53
53
|
/** True if the StoreRecord has been modified since it was last committed. */
|
|
54
|
+
get isDirty(): boolean;
|
|
55
|
+
/** Alias for {@link StoreRecord.isDirty} */
|
|
54
56
|
get isModified(): boolean;
|
|
55
57
|
/** False if the StoreRecord has been added or modified. */
|
|
56
58
|
get isCommitted(): boolean;
|
|
@@ -61,6 +61,7 @@ export declare const autoRefreshAppOption: ({ formFieldProps, inputProps }?: Aut
|
|
|
61
61
|
flexGrow?: string | number;
|
|
62
62
|
flexShrink?: string | number;
|
|
63
63
|
flexWrap?: import("csstype").Property.FlexWrap;
|
|
64
|
+
gap?: string | number;
|
|
64
65
|
alignItems?: string;
|
|
65
66
|
alignSelf?: string;
|
|
66
67
|
alignContent?: string;
|
|
@@ -59,6 +59,7 @@ export declare const themeAppOption: ({ formFieldProps, inputProps }?: ThemeAppO
|
|
|
59
59
|
flexGrow?: string | number;
|
|
60
60
|
flexShrink?: string | number;
|
|
61
61
|
flexWrap?: import("csstype").Property.FlexWrap;
|
|
62
|
+
gap?: string | number;
|
|
62
63
|
alignItems?: string;
|
|
63
64
|
alignSelf?: string;
|
|
64
65
|
alignContent?: string;
|
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
import { Alert, Button, ButtonGroup, Callout, Card, Checkbox, ControlGroup, Dialog, Drawer, EditableText, FileInput, FormGroup, Hotkey, Hotkeys, InputGroup, Label, Menu, MenuDivider, MenuItem, Navbar, NavbarDivider, NavbarGroup, NavbarHeading, NumericInput, OverflowList, Overlay2 as Overlay, Popover, Radio, RadioGroup, RangeSlider, Slider, Switch, Tab, Tabs, Tag, TagInput, Text, TextArea, Tooltip, Tree } from '@blueprintjs/core';
|
|
3
3
|
import { DatePicker3 as DatePicker } from '@blueprintjs/datetime2';
|
|
4
4
|
export { Alert, Button, ButtonGroup, Callout, Card, Checkbox, ControlGroup, DatePicker, Dialog, Drawer, EditableText, FileInput, FormGroup, Hotkeys, Hotkey, InputGroup, Label, Menu, MenuItem, MenuDivider, Navbar, NavbarDivider, NavbarGroup, NavbarHeading, NumericInput, OverflowList, Overlay, Popover, Radio, RadioGroup, RangeSlider, Slider, Switch, Tab, Tabs, Tag, TagInput, TextArea, Text, Tooltip, Tree };
|
|
5
|
-
export declare const alert: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").AlertProps>, button: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").ButtonProps>, controlGroup: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").ControlGroupProps>, checkbox: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").CheckboxProps>, dialog: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").DialogProps>, datePicker: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/datetime2").DatePicker3Props>, menuDivider: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").MenuDividerProps>, menuItem: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").MenuItemProps>, navbarDivider: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").NavbarDividerProps>, numericInput: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").HTMLInputProps & import("@blueprintjs/core").NumericInputProps>, overflowList: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").OverflowListProps<any>>, popover: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").PopoverProps<import("@blueprintjs/core").DefaultPopoverTargetHTMLProps>>, radio: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").ControlProps>, rangeSlider: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").RangeSliderProps>, slider: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").SliderProps>, switchControl: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").SwitchProps>, textArea: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").TextAreaProps>, tree: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").TreeProps<unknown>>, tagInput: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").TagInputProps>, fileInput: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").FileInputProps>, overlay: import("@xh/hoist/core").ElementFactory<
|
|
5
|
+
export declare const alert: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").AlertProps>, button: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").ButtonProps>, controlGroup: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").ControlGroupProps>, checkbox: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").CheckboxProps>, dialog: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").DialogProps>, datePicker: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/datetime2").DatePicker3Props>, menuDivider: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").MenuDividerProps>, menuItem: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").MenuItemProps>, navbarDivider: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").NavbarDividerProps>, numericInput: import("@xh/hoist/core").ElementFactory<Omit<import("@blueprintjs/core").HTMLInputProps, "size"> & import("@blueprintjs/core").NumericInputProps>, overflowList: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").OverflowListProps<any>>, popover: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").PopoverProps<import("@blueprintjs/core").DefaultPopoverTargetHTMLProps>>, radio: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").ControlProps>, rangeSlider: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").RangeSliderProps>, slider: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").SliderProps>, switchControl: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").SwitchProps>, textArea: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").TextAreaProps>, tree: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").TreeProps<unknown>>, tagInput: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").TagInputProps>, fileInput: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").FileInputProps>, overlay: import("@xh/hoist/core").ElementFactory<Omit<import("@blueprintjs/core").Overlay2Props, "ref"> & import("react").RefAttributes<import("@blueprintjs/core").OverlayInstance>>, tooltip: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").TooltipProps<import("@blueprintjs/core").DefaultPopoverTargetHTMLProps>>;
|
|
6
6
|
export declare const buttonGroup: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").ButtonGroupProps>, callout: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").CalloutProps>, card: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").CardProps>, drawer: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").DrawerProps>, editableText: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").EditableTextProps>, formGroup: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").FormGroupProps>, hotkey: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").HotkeyProps>, hotkeys: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").HotkeysProps>, inputGroup: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").InputGroupProps>, label: import("@xh/hoist/core").ElementFactory<import("react").AllHTMLAttributes<HTMLLabelElement> & import("react").RefAttributes<HTMLLabelElement>>, menu: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").MenuProps>, navbar: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").NavbarProps>, navbarHeading: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").NavbarHeadingProps>, navbarGroup: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").NavbarGroupProps>, radioGroup: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").RadioGroupProps>, tabs: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").TabsProps>, tab: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").TabProps>, tag: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").TagProps>, text: import("@xh/hoist/core").ElementFactory<import("@blueprintjs/core").TextProps>;
|
|
@@ -13,13 +13,10 @@ export declare const swiper: import("@xh/hoist/core").ElementFactory<import("rea
|
|
|
13
13
|
onAutoplayResume?: (swiper: import("swiper/types/swiper-class").default) => void;
|
|
14
14
|
onAutoplayTimeLeft?: (swiper: import("swiper/types/swiper-class").default, timeLeft: number, percentage: number) => void;
|
|
15
15
|
onAutoplay?: (swiper: import("swiper/types/swiper-class").default) => void;
|
|
16
|
+
onKeyPress?: (swiper: import("swiper/types/swiper-class").default, keyCode: string) => void;
|
|
16
17
|
onHashChange?: (swiper: import("swiper/types/swiper-class").default) => void;
|
|
17
18
|
onHashSet?: (swiper: import("swiper/types/swiper-class").default) => void;
|
|
18
|
-
onKeyPress?: (swiper: import("swiper/types/swiper-class").default, keyCode: string) => void;
|
|
19
19
|
onScroll?: (swiper: import("swiper/types/swiper-class").default, event: WheelEvent) => void;
|
|
20
|
-
onScrollbarDragStart?: (swiper: import("swiper/types/swiper-class").default, event: MouseEvent | PointerEvent | TouchEvent) => void;
|
|
21
|
-
onScrollbarDragMove?: (swiper: import("swiper/types/swiper-class").default, event: MouseEvent | PointerEvent | TouchEvent) => void;
|
|
22
|
-
onScrollbarDragEnd?: (swiper: import("swiper/types/swiper-class").default, event: MouseEvent | PointerEvent | TouchEvent) => void;
|
|
23
20
|
onNavigationHide?: (swiper: import("swiper/types/swiper-class").default) => void;
|
|
24
21
|
onNavigationShow?: (swiper: import("swiper/types/swiper-class").default) => void;
|
|
25
22
|
onNavigationPrev?: (swiper: import("swiper/types/swiper-class").default) => void;
|
|
@@ -28,6 +25,9 @@ export declare const swiper: import("@xh/hoist/core").ElementFactory<import("rea
|
|
|
28
25
|
onPaginationUpdate?: (swiper: import("swiper/types/swiper-class").default, paginationEl: HTMLElement) => void;
|
|
29
26
|
onPaginationHide?: (swiper: import("swiper/types/swiper-class").default) => void;
|
|
30
27
|
onPaginationShow?: (swiper: import("swiper/types/swiper-class").default) => void;
|
|
28
|
+
onScrollbarDragStart?: (swiper: import("swiper/types/swiper-class").default, event: MouseEvent | PointerEvent | TouchEvent) => void;
|
|
29
|
+
onScrollbarDragMove?: (swiper: import("swiper/types/swiper-class").default, event: MouseEvent | PointerEvent | TouchEvent) => void;
|
|
30
|
+
onScrollbarDragEnd?: (swiper: import("swiper/types/swiper-class").default, event: MouseEvent | PointerEvent | TouchEvent) => void;
|
|
31
31
|
onZoomChange?: (swiper: import("swiper/types/swiper-class").default, scale: number, imageEl: HTMLElement, slideEl: HTMLElement) => void;
|
|
32
32
|
onInit?: (swiper: import("swiper/types/swiper-class").default) => any;
|
|
33
33
|
onBeforeDestroy?: (swiper: import("swiper/types/swiper-class").default) => void;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { HoistBase } from '@xh/hoist/core';
|
|
2
|
-
import { Token
|
|
2
|
+
import { Token } from '@xh/hoist/security/Token';
|
|
3
|
+
import { AccessTokenSpec, TokenMap } from './Types';
|
|
3
4
|
export type LoginMethod = 'REDIRECT' | 'POPUP';
|
|
4
|
-
export interface BaseOAuthClientConfig<S> {
|
|
5
|
+
export interface BaseOAuthClientConfig<S extends AccessTokenSpec> {
|
|
5
6
|
/** Client ID (GUID) of your app registered with your Oauth provider. */
|
|
6
7
|
clientId: string;
|
|
7
8
|
/**
|
|
@@ -23,24 +24,16 @@ export interface BaseOAuthClientConfig<S> {
|
|
|
23
24
|
* Governs an optional refresh timer that will work to keep the tokens fresh.
|
|
24
25
|
*
|
|
25
26
|
* A typical refresh will use the underlying provider cache, and should not result in
|
|
26
|
-
* network activity. However, if any token
|
|
27
|
+
* network activity. However, if any token would expire before the next autoRefresh,
|
|
27
28
|
* this client will force a call to the underlying provider to get the token.
|
|
28
29
|
*
|
|
29
30
|
* In order to allow aging tokens to be replaced in a timely manner, this value should be
|
|
30
31
|
* significantly shorter than both the minimum token lifetime that will be
|
|
31
|
-
* returned by the underlying API
|
|
32
|
+
* returned by the underlying API.
|
|
32
33
|
*
|
|
33
34
|
* Default is -1, disabling this behavior.
|
|
34
35
|
*/
|
|
35
36
|
autoRefreshSecs?: number;
|
|
36
|
-
/**
|
|
37
|
-
* During auto-refresh, if the remaining lifetime for any token is below this threshold,
|
|
38
|
-
* force the provider to skip the local cache and go directly to the underlying provider for
|
|
39
|
-
* new tokens and refresh tokens.
|
|
40
|
-
*
|
|
41
|
-
* Default is -1, disabling this behavior.
|
|
42
|
-
*/
|
|
43
|
-
autoRefreshSkipCacheSecs?: number;
|
|
44
37
|
/**
|
|
45
38
|
* Scopes to request - if any - beyond the core `['openid', 'email']` scopes, which
|
|
46
39
|
* this client will always request.
|
|
@@ -63,13 +56,12 @@ export interface BaseOAuthClientConfig<S> {
|
|
|
63
56
|
* suitable concrete implementation to power a client-side OauthService. See `MsalClient` and
|
|
64
57
|
* `AuthZeroClient`
|
|
65
58
|
*
|
|
66
|
-
* Initialize such a service and this client within
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
* flow as necessary.
|
|
59
|
+
* Initialize such a service and this client within an app's primary {@link HoistAuthModel} to use
|
|
60
|
+
* the tokens it acquires to authenticate with the Hoist server. (Note this requires a suitable
|
|
61
|
+
* server-side `AuthenticationService` implementation to validate the token and actually resolve
|
|
62
|
+
* the user.) On init, the client impl will initiate a pop-up or redirect flow as necessary.
|
|
71
63
|
*/
|
|
72
|
-
export declare abstract class BaseOAuthClient<C extends BaseOAuthClientConfig<S>, S> extends HoistBase {
|
|
64
|
+
export declare abstract class BaseOAuthClient<C extends BaseOAuthClientConfig<S>, S extends AccessTokenSpec> extends HoistBase {
|
|
73
65
|
/** Config loaded from UI server + init method. */
|
|
74
66
|
protected config: C;
|
|
75
67
|
/** ID Scopes */
|
|
@@ -101,9 +93,12 @@ export declare abstract class BaseOAuthClient<C extends BaseOAuthClientConfig<S>
|
|
|
101
93
|
*/
|
|
102
94
|
getAccessTokenAsync(key: string): Promise<Token>;
|
|
103
95
|
/**
|
|
104
|
-
* Get all
|
|
96
|
+
* Get all configured tokens.
|
|
105
97
|
*/
|
|
106
|
-
getAllTokensAsync(
|
|
98
|
+
getAllTokensAsync(opts?: {
|
|
99
|
+
eagerOnly?: boolean;
|
|
100
|
+
useCache?: boolean;
|
|
101
|
+
}): Promise<TokenMap>;
|
|
107
102
|
/**
|
|
108
103
|
* The last authenticated OAuth username.
|
|
109
104
|
*
|
|
@@ -144,7 +139,10 @@ export declare abstract class BaseOAuthClient<C extends BaseOAuthClientConfig<S>
|
|
|
144
139
|
protected restoreRedirectState(key: string): void;
|
|
145
140
|
/** Call after requesting the provider library redirect the user away for auth. */
|
|
146
141
|
protected maskAfterRedirectAsync(): Promise<void>;
|
|
147
|
-
protected fetchAllTokensAsync(
|
|
142
|
+
protected fetchAllTokensAsync(opts?: {
|
|
143
|
+
eagerOnly?: boolean;
|
|
144
|
+
useCache?: boolean;
|
|
145
|
+
}): Promise<TokenMap>;
|
|
148
146
|
protected getLocalStorage(key: string, defaultValue?: any): any;
|
|
149
147
|
protected setLocalStorage(key: string, value: any): void;
|
|
150
148
|
private fetchIdTokenSafeAsync;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Token } from './Token';
|
|
2
|
+
export type TokenMap = Record<string, Token>;
|
|
3
|
+
export interface AccessTokenSpec {
|
|
4
|
+
/**
|
|
5
|
+
* Mode governing when the access token should be requested from provider.
|
|
6
|
+
* eager (default) - initiate lookup on initialization, but do not block on failure.
|
|
7
|
+
* lazy - lookup when requested by client.
|
|
8
|
+
*/
|
|
9
|
+
fetchMode: 'eager' | 'lazy';
|
|
10
|
+
/** Scopes for the desired access token.*/
|
|
11
|
+
scopes: string[];
|
|
12
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Auth0ClientOptions } from '@auth0/auth0-spa-js';
|
|
2
|
-
import { Token
|
|
2
|
+
import { Token } from '@xh/hoist/security/Token';
|
|
3
|
+
import { AccessTokenSpec, TokenMap } from '../Types';
|
|
3
4
|
import { BaseOAuthClient, BaseOAuthClientConfig } from '../BaseOAuthClient';
|
|
4
5
|
export interface AuthZeroClientConfig extends BaseOAuthClientConfig<AuthZeroTokenSpec> {
|
|
5
6
|
/** Domain of your app registered with Auth0. */
|
|
@@ -24,9 +25,7 @@ export interface AuthZeroClientConfig extends BaseOAuthClientConfig<AuthZeroToke
|
|
|
24
25
|
*/
|
|
25
26
|
authZeroClientOptions?: Partial<Auth0ClientOptions>;
|
|
26
27
|
}
|
|
27
|
-
export interface AuthZeroTokenSpec {
|
|
28
|
-
/** Scopes for the desired access token.*/
|
|
29
|
-
scopes: string[];
|
|
28
|
+
export interface AuthZeroTokenSpec extends AccessTokenSpec {
|
|
30
29
|
/**
|
|
31
30
|
* Audience (i.e. API) identifier for AccessToken. Must be registered with Auth0.
|
|
32
31
|
* Note that this is required to ensure that issued token is a JWT and not an opaque string.
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as msal from '@azure/msal-browser';
|
|
2
2
|
import { LogLevel } from '@azure/msal-browser';
|
|
3
|
-
import { Token
|
|
3
|
+
import { Token } from '@xh/hoist/security/Token';
|
|
4
|
+
import { AccessTokenSpec, TokenMap } from '../Types';
|
|
4
5
|
import { BaseOAuthClient, BaseOAuthClientConfig } from '../BaseOAuthClient';
|
|
5
6
|
export interface MsalClientConfig extends BaseOAuthClientConfig<MsalTokenSpec> {
|
|
6
7
|
/**
|
|
@@ -44,9 +45,7 @@ export interface MsalClientConfig extends BaseOAuthClientConfig<MsalTokenSpec> {
|
|
|
44
45
|
*/
|
|
45
46
|
msalClientOptions?: Partial<msal.Configuration>;
|
|
46
47
|
}
|
|
47
|
-
export interface MsalTokenSpec {
|
|
48
|
-
/** Scopes for the desired access token. */
|
|
49
|
-
scopes: string[];
|
|
48
|
+
export interface MsalTokenSpec extends AccessTokenSpec {
|
|
50
49
|
/**
|
|
51
50
|
* Scopes to be added to the scopes requested during interactive and SSO logins.
|
|
52
51
|
* See the `scopes` property on `PopupRequest`, `RedirectRequest`, and `SSORequest`
|
|
@@ -415,7 +415,9 @@ export class FilterChooserModel extends HoistModel {
|
|
|
415
415
|
}: FilterChooserPersistOptions) {
|
|
416
416
|
if (persistValue) {
|
|
417
417
|
const status = {initialized: false},
|
|
418
|
-
persistWith = isObject(persistValue)
|
|
418
|
+
persistWith = isObject(persistValue)
|
|
419
|
+
? PersistenceProvider.mergePersistOptions(rootPersistWith, persistValue)
|
|
420
|
+
: rootPersistWith;
|
|
419
421
|
PersistenceProvider.create({
|
|
420
422
|
persistOptions: {
|
|
421
423
|
path: `${path}.value`,
|
|
@@ -432,7 +434,9 @@ export class FilterChooserModel extends HoistModel {
|
|
|
432
434
|
}
|
|
433
435
|
|
|
434
436
|
if (persistFavorites) {
|
|
435
|
-
const persistWith = isObject(persistFavorites)
|
|
437
|
+
const persistWith = isObject(persistFavorites)
|
|
438
|
+
? PersistenceProvider.mergePersistOptions(rootPersistWith, persistFavorites)
|
|
439
|
+
: rootPersistWith,
|
|
436
440
|
provider = PersistenceProvider.create({
|
|
437
441
|
persistOptions: {
|
|
438
442
|
path: `${path}.favorites`,
|