@xh/hoist 71.0.0-SNAPSHOT.1731709792477 → 71.0.0-SNAPSHOT.1732369566945
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 +5 -0
- package/admin/tabs/cluster/ClusterTabModel.ts +35 -15
- package/build/types/admin/tabs/cluster/ClusterTabModel.d.ts +6 -4
- package/build/types/core/persist/viewmanager/Types.d.ts +3 -1
- package/build/types/core/persist/viewmanager/ViewManagerModel.d.ts +10 -19
- package/build/types/core/persist/viewmanager/impl/BuildViewTree.d.ts +8 -0
- package/build/types/desktop/cmp/dash/container/DashContainerModel.d.ts +1 -4
- package/build/types/desktop/cmp/viewmanager/ViewManager.d.ts +16 -2
- package/build/types/desktop/cmp/viewmanager/index.d.ts +0 -2
- package/build/types/svc/JsonBlobService.d.ts +2 -2
- package/core/persist/viewmanager/Types.ts +3 -1
- package/core/persist/viewmanager/ViewManagerModel.ts +110 -156
- package/core/persist/viewmanager/impl/BuildViewTree.ts +68 -0
- package/core/persist/viewmanager/impl/ManageDialogModel.ts +2 -0
- package/core/persist/viewmanager/impl/SaveDialogModel.ts +1 -1
- package/desktop/cmp/dash/container/DashContainerModel.ts +34 -32
- package/desktop/cmp/viewmanager/ViewManager.ts +97 -50
- package/desktop/cmp/viewmanager/{cmp → impl}/ManageDialog.ts +1 -1
- package/desktop/cmp/viewmanager/index.ts +0 -2
- package/package.json +1 -1
- package/svc/JsonBlobService.ts +3 -6
- package/tsconfig.tsbuildinfo +1 -1
- /package/build/types/desktop/cmp/viewmanager/{cmp → impl}/ManageDialog.d.ts +0 -0
- /package/build/types/desktop/cmp/viewmanager/{cmp → impl}/SaveDialog.d.ts +0 -0
- /package/desktop/cmp/viewmanager/{cmp → impl}/SaveDialog.ts +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -32,6 +32,10 @@ export class ClusterTabModel extends HoistModel {
|
|
|
32
32
|
|
|
33
33
|
@lookup(TabModel) private tabModel: TabModel;
|
|
34
34
|
|
|
35
|
+
@managed readonly gridModel: GridModel = this.createGridModel();
|
|
36
|
+
@managed readonly tabContainerModel: TabContainerModel = this.createTabContainerModel();
|
|
37
|
+
@managed readonly timer: Timer;
|
|
38
|
+
|
|
35
39
|
shutdownAction: RecordActionSpec = {
|
|
36
40
|
icon: Icon.skull(),
|
|
37
41
|
text: 'Shutdown Instance',
|
|
@@ -41,10 +45,6 @@ export class ClusterTabModel extends HoistModel {
|
|
|
41
45
|
recordsRequired: 1
|
|
42
46
|
};
|
|
43
47
|
|
|
44
|
-
@managed readonly gridModel: GridModel = this.createGridModel();
|
|
45
|
-
@managed readonly tabContainerModel: TabContainerModel = this.createTabContainerModel();
|
|
46
|
-
@managed readonly timer: Timer;
|
|
47
|
-
|
|
48
48
|
get instance(): PlainObject {
|
|
49
49
|
return this.gridModel.selectedRecord?.data;
|
|
50
50
|
}
|
|
@@ -59,7 +59,16 @@ export class ClusterTabModel extends HoistModel {
|
|
|
59
59
|
|
|
60
60
|
override async doLoadAsync(loadSpec: LoadSpec) {
|
|
61
61
|
const {gridModel} = this;
|
|
62
|
-
|
|
62
|
+
|
|
63
|
+
let data = await XH.fetchJson({
|
|
64
|
+
url: 'clusterAdmin/allInstances',
|
|
65
|
+
// Tighter default timeout for background auto-refresh, to ensure we report connectivity
|
|
66
|
+
// issues promptly. This call should be quick, but still allow full default timeout for
|
|
67
|
+
// a manual refresh.
|
|
68
|
+
timeout: loadSpec.isAutoRefresh ? this.autoRefreshTimeout : undefined,
|
|
69
|
+
loadSpec
|
|
70
|
+
});
|
|
71
|
+
|
|
63
72
|
data = data.map(row => ({
|
|
64
73
|
...row,
|
|
65
74
|
isLocal: row.name == XH.environmentService.serverInstance,
|
|
@@ -78,7 +87,7 @@ export class ClusterTabModel extends HoistModel {
|
|
|
78
87
|
runFn: () => {
|
|
79
88
|
if (this.tabModel?.isActive) this.autoRefreshAsync();
|
|
80
89
|
},
|
|
81
|
-
interval:
|
|
90
|
+
interval: this.autoRefreshInterval,
|
|
82
91
|
delay: true
|
|
83
92
|
});
|
|
84
93
|
|
|
@@ -96,6 +105,16 @@ export class ClusterTabModel extends HoistModel {
|
|
|
96
105
|
);
|
|
97
106
|
}
|
|
98
107
|
|
|
108
|
+
formatInstance(instance: PlainObject): ReactNode {
|
|
109
|
+
const content = [instance.name];
|
|
110
|
+
if (instance.isPrimary) content.push(badge({item: 'primary', intent: 'primary'}));
|
|
111
|
+
if (instance.isLocal) content.push(badge('local'));
|
|
112
|
+
return hbox(content);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
//------------------
|
|
116
|
+
// Implementation
|
|
117
|
+
//------------------
|
|
99
118
|
private createGridModel() {
|
|
100
119
|
return new GridModel({
|
|
101
120
|
store: {
|
|
@@ -161,7 +180,7 @@ export class ClusterTabModel extends HoistModel {
|
|
|
161
180
|
});
|
|
162
181
|
}
|
|
163
182
|
|
|
164
|
-
createTabContainerModel() {
|
|
183
|
+
private createTabContainerModel() {
|
|
165
184
|
return new TabContainerModel({
|
|
166
185
|
route: 'default.cluster',
|
|
167
186
|
switcher: false,
|
|
@@ -187,14 +206,7 @@ export class ClusterTabModel extends HoistModel {
|
|
|
187
206
|
});
|
|
188
207
|
}
|
|
189
208
|
|
|
190
|
-
|
|
191
|
-
const content = [instance.name];
|
|
192
|
-
if (instance.isPrimary) content.push(badge({item: 'primary', intent: 'primary'}));
|
|
193
|
-
if (instance.isLocal) content.push(badge('local'));
|
|
194
|
-
return hbox(content);
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
async shutdownInstanceAsync(instance: PlainObject) {
|
|
209
|
+
private async shutdownInstanceAsync(instance: PlainObject) {
|
|
198
210
|
if (
|
|
199
211
|
!(await XH.confirm({
|
|
200
212
|
message: `Are you SURE you want to shutdown instance ${instance.name}?`,
|
|
@@ -216,4 +228,12 @@ export class ClusterTabModel extends HoistModel {
|
|
|
216
228
|
.linkTo({observer: this.loadModel, message: 'Attempting instance shutdown'})
|
|
217
229
|
.catchDefault();
|
|
218
230
|
}
|
|
231
|
+
|
|
232
|
+
private get autoRefreshInterval(): number {
|
|
233
|
+
return XH.getConf('xhAdminAppConfig', {}).clusterTabAutoRefreshInterval ?? 4 * SECONDS;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
private get autoRefreshTimeout(): number {
|
|
237
|
+
return XH.getConf('xhAdminAppConfig', {}).clusterTabAutoRefreshTimeout ?? 2 * SECONDS;
|
|
238
|
+
}
|
|
219
239
|
}
|
|
@@ -9,17 +9,19 @@ export declare class ClusterTabModel extends HoistModel {
|
|
|
9
9
|
localStorageKey: string;
|
|
10
10
|
};
|
|
11
11
|
private tabModel;
|
|
12
|
-
shutdownAction: RecordActionSpec;
|
|
13
12
|
readonly gridModel: GridModel;
|
|
14
13
|
readonly tabContainerModel: TabContainerModel;
|
|
15
14
|
readonly timer: Timer;
|
|
15
|
+
shutdownAction: RecordActionSpec;
|
|
16
16
|
get instance(): PlainObject;
|
|
17
17
|
get instanceName(): string;
|
|
18
18
|
get isMultiInstance(): boolean;
|
|
19
19
|
doLoadAsync(loadSpec: LoadSpec): Promise<void>;
|
|
20
20
|
constructor();
|
|
21
|
-
private createGridModel;
|
|
22
|
-
createTabContainerModel(): TabContainerModel;
|
|
23
21
|
formatInstance(instance: PlainObject): ReactNode;
|
|
24
|
-
|
|
22
|
+
private createGridModel;
|
|
23
|
+
private createTabContainerModel;
|
|
24
|
+
private shutdownInstanceAsync;
|
|
25
|
+
private get autoRefreshInterval();
|
|
26
|
+
private get autoRefreshTimeout();
|
|
25
27
|
}
|
|
@@ -19,8 +19,10 @@ export interface View<T extends PlainObject = PlainObject> {
|
|
|
19
19
|
isShared: boolean;
|
|
20
20
|
lastUpdated: number;
|
|
21
21
|
lastUpdatedBy: string;
|
|
22
|
-
/** User-supplied descriptive name. */
|
|
22
|
+
/** User-supplied descriptive name, including folder designating prefix. */
|
|
23
23
|
name: string;
|
|
24
|
+
/** User-supplied descriptive name, without folder designating prefix. */
|
|
25
|
+
shortName: string;
|
|
24
26
|
/** Original creator of the view, and the only user with access to it if not shared. */
|
|
25
27
|
owner: string;
|
|
26
28
|
token: string;
|
|
@@ -75,15 +75,16 @@ export declare class ViewManagerModel<T extends PlainObject = PlainObject> exten
|
|
|
75
75
|
pendingValue: T;
|
|
76
76
|
/** Loaded saved view definitions - both private and shared. */
|
|
77
77
|
views: View<T>[];
|
|
78
|
-
/**
|
|
78
|
+
/** Currently selected view, or null if in default mode. Token only will be set during pre-loading.*/
|
|
79
79
|
selectedToken: string;
|
|
80
|
+
selectedView: View<T>;
|
|
80
81
|
/** List of tokens for the user's favorite views. */
|
|
81
82
|
favorites: string[];
|
|
82
83
|
/**
|
|
83
84
|
* True if user has opted-in to automatically saving changes to personal views (if auto-save
|
|
84
85
|
* generally available as per `enableAutoSave`).
|
|
85
86
|
*/
|
|
86
|
-
|
|
87
|
+
autoSave: boolean;
|
|
87
88
|
/**
|
|
88
89
|
* TaskObserver linked to {@link selectViewAsync}. If a change to the active view is likely to
|
|
89
90
|
* require intensive layout/grid work, consider masking affected components with this observer.
|
|
@@ -99,17 +100,9 @@ export declare class ViewManagerModel<T extends PlainObject = PlainObject> exten
|
|
|
99
100
|
*/
|
|
100
101
|
providers: ViewManagerProvider<any>[];
|
|
101
102
|
get enableSharing(): boolean;
|
|
102
|
-
get selectedView(): View<T>;
|
|
103
|
-
get isSharedViewSelected(): boolean;
|
|
104
103
|
get canSave(): boolean;
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
* that button might be disabled due to no changes having been made. Works in concert with the
|
|
108
|
-
* desktop ViewManager component's `showSaveButton` prop.
|
|
109
|
-
*/
|
|
110
|
-
get canShowSaveButton(): boolean;
|
|
111
|
-
get enableAutoSaveToggle(): boolean;
|
|
112
|
-
get disabledAutoSaveReason(): string;
|
|
104
|
+
get canAutoSave(): boolean;
|
|
105
|
+
get autoSaveUnavailableReason(): string;
|
|
113
106
|
get isDirty(): boolean;
|
|
114
107
|
get isShared(): boolean;
|
|
115
108
|
get favoriteViews(): View<T>[];
|
|
@@ -124,31 +117,29 @@ export declare class ViewManagerModel<T extends PlainObject = PlainObject> exten
|
|
|
124
117
|
private constructor();
|
|
125
118
|
doLoadAsync(loadSpec: LoadSpec): Promise<void>;
|
|
126
119
|
selectViewAsync(token: string): Promise<void>;
|
|
127
|
-
saveAsync(
|
|
120
|
+
saveAsync(): Promise<void>;
|
|
128
121
|
saveAsAsync(): Promise<void>;
|
|
129
122
|
resetAsync(): Promise<void>;
|
|
130
123
|
setPendingValue(pendingValue: T): void;
|
|
131
124
|
openManageDialog(): void;
|
|
132
125
|
closeManageDialog(): void;
|
|
133
|
-
getHierarchyDisplayName(name: string): string;
|
|
134
126
|
toggleFavorite(token: string): void;
|
|
135
127
|
addFavorite(token: string): void;
|
|
136
128
|
removeFavorite(token: string): void;
|
|
137
129
|
isFavorite(token: string): boolean;
|
|
138
130
|
getPersistableState(): PersistableState<ViewManagerModelPersistState>;
|
|
139
131
|
setPersistableState(state: PersistableState<ViewManagerModelPersistState>): void;
|
|
132
|
+
private selectViewInternalAsync;
|
|
140
133
|
private processRaw;
|
|
141
134
|
private setValue;
|
|
142
135
|
private cleanValue;
|
|
143
136
|
private confirmSaveForSharedViewAsync;
|
|
144
137
|
private maybeAutoSaveAsync;
|
|
145
|
-
private buildViewTree;
|
|
146
|
-
private getNameHierarchySubstring;
|
|
147
|
-
private isFolderForEntry;
|
|
148
138
|
private onFavoritesChange;
|
|
149
139
|
}
|
|
150
140
|
interface ViewManagerModelPersistState {
|
|
151
|
-
selectedToken
|
|
152
|
-
favorites
|
|
141
|
+
selectedToken?: string;
|
|
142
|
+
favorites?: string[];
|
|
143
|
+
autoSave?: boolean;
|
|
153
144
|
}
|
|
154
145
|
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { View, ViewManagerModel, ViewTree } from '@xh/hoist/core/persist/viewmanager';
|
|
2
|
+
/**
|
|
3
|
+
* Create a menu-friendly, tree representation of a set of views, using the `\`
|
|
4
|
+
* in view names to create folders.
|
|
5
|
+
*
|
|
6
|
+
* @internal
|
|
7
|
+
*/
|
|
8
|
+
export declare function buildViewTree(views: View[], model: ViewManagerModel): ViewTree[];
|
|
@@ -104,10 +104,7 @@ export declare class DashContainerModel extends DashModel<DashContainerViewSpec,
|
|
|
104
104
|
* This method will clear the persistent state saved for this component, if any.
|
|
105
105
|
*/
|
|
106
106
|
restoreDefaultsAsync(): Promise<void>;
|
|
107
|
-
/**
|
|
108
|
-
* Load state into the DashContainer, recreating its layout and contents
|
|
109
|
-
* @param state - State to load
|
|
110
|
-
*/
|
|
107
|
+
/** Load state into the DashContainer, recreating its layout and contents */
|
|
111
108
|
loadStateAsync(state: DashViewState[]): Promise<void>;
|
|
112
109
|
/**
|
|
113
110
|
* Add a view to the container.
|
|
@@ -3,11 +3,25 @@ import { HoistProps } from '@xh/hoist/core';
|
|
|
3
3
|
import './ViewManager.scss';
|
|
4
4
|
import { ViewManagerModel } from '@xh/hoist/core/persist/viewmanager/ViewManagerModel';
|
|
5
5
|
import { ButtonProps } from '@xh/hoist/desktop/cmp/button';
|
|
6
|
+
/**
|
|
7
|
+
* Visibility options for save/revert button.
|
|
8
|
+
*
|
|
9
|
+
* 'never' to hide button.
|
|
10
|
+
* 'whenDirty' to only show when persistence state is dirty and button is therefore enabled.
|
|
11
|
+
* 'always' will always show button, unless autoSave is active.
|
|
12
|
+
*
|
|
13
|
+
* Note that we never show the button when 'autoSave' is active because it would never be enabled
|
|
14
|
+
* for more than a flash.
|
|
15
|
+
*/
|
|
16
|
+
export type ViewManagerStateButtonMode = 'whenDirty' | 'always' | 'never';
|
|
6
17
|
export interface ViewManagerProps extends HoistProps<ViewManagerModel> {
|
|
7
18
|
menuButtonProps?: Partial<ButtonProps>;
|
|
8
19
|
saveButtonProps?: Partial<ButtonProps>;
|
|
9
|
-
|
|
10
|
-
|
|
20
|
+
revertButtonProps?: Partial<ButtonProps>;
|
|
21
|
+
/** Default 'whenDirty' */
|
|
22
|
+
showSaveButton?: ViewManagerStateButtonMode;
|
|
23
|
+
/** Default 'never' */
|
|
24
|
+
showRevertButton?: ViewManagerStateButtonMode;
|
|
11
25
|
/** True to render private views in sub-menu (Default false)*/
|
|
12
26
|
showPrivateViewsInSubMenu?: boolean;
|
|
13
27
|
/** True to render shared views in sub-menu (Default false)*/
|
|
@@ -42,11 +42,11 @@ export declare class JsonBlobService extends HoistService {
|
|
|
42
42
|
/** Retrieve a single JSONBlob by its unique token. */
|
|
43
43
|
getAsync(token: string): Promise<JsonBlob>;
|
|
44
44
|
/** Retrieve all blobs of a particular type that are visible to the current user. */
|
|
45
|
-
listAsync(
|
|
45
|
+
listAsync(spec: {
|
|
46
46
|
type: string;
|
|
47
47
|
includeValue?: boolean;
|
|
48
48
|
loadSpec?: LoadSpec;
|
|
49
|
-
}): Promise<
|
|
49
|
+
}): Promise<JsonBlob[]>;
|
|
50
50
|
/** Persist a new JSONBlob back to the server. */
|
|
51
51
|
createAsync({ acl, description, type, meta, name, value }: Partial<JsonBlob>): Promise<JsonBlob>;
|
|
52
52
|
/** Modify mutable properties of an existing JSONBlob, as identified by its unique token. */
|
|
@@ -20,8 +20,10 @@ export interface View<T extends PlainObject = PlainObject> {
|
|
|
20
20
|
isShared: boolean;
|
|
21
21
|
lastUpdated: number;
|
|
22
22
|
lastUpdatedBy: string;
|
|
23
|
-
/** User-supplied descriptive name. */
|
|
23
|
+
/** User-supplied descriptive name, including folder designating prefix. */
|
|
24
24
|
name: string;
|
|
25
|
+
/** User-supplied descriptive name, without folder designating prefix. */
|
|
26
|
+
shortName: string;
|
|
25
27
|
/** Original creator of the view, and the only user with access to it if not shared. */
|
|
26
28
|
owner: string;
|
|
27
29
|
token: string;
|