@xh/hoist 71.0.0-SNAPSHOT.1734551243081 → 71.0.0-SNAPSHOT.1734627276913
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/build/types/cmp/viewmanager/ViewManagerModel.d.ts +8 -6
- package/cmp/viewmanager/ViewManagerModel.ts +14 -7
- package/desktop/cmp/viewmanager/ViewManager.ts +13 -3
- package/desktop/cmp/viewmanager/ViewMenu.ts +1 -20
- package/desktop/cmp/viewmanager/dialog/ManageDialogModel.ts +9 -5
- package/desktop/cmp/viewmanager/dialog/ViewMultiPanel.ts +2 -4
- package/package.json +1 -1
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -2,7 +2,7 @@ import { HoistModel, LoadSpec, PersistOptions, PlainObject, TaskObserver, Thunka
|
|
|
2
2
|
import type { ViewManagerProvider } from '@xh/hoist/core';
|
|
3
3
|
import { ViewInfo } from './ViewInfo';
|
|
4
4
|
import { View } from './View';
|
|
5
|
-
import {
|
|
5
|
+
import { ViewCreateSpec, ViewUpdateSpec } from './ViewToBlobApi';
|
|
6
6
|
export interface ViewManagerConfig {
|
|
7
7
|
/**
|
|
8
8
|
* True (default) to allow user to opt in to automatically saving changes to their current view.
|
|
@@ -143,11 +143,9 @@ export declare class ViewManagerModel<T = PlainObject> extends HoistModel {
|
|
|
143
143
|
* @internal
|
|
144
144
|
*/
|
|
145
145
|
providers: ViewManagerProvider<any>[];
|
|
146
|
-
/**
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
*/
|
|
150
|
-
api: ViewToBlobApi<T>;
|
|
146
|
+
/** Data access for persisting views. */
|
|
147
|
+
private api;
|
|
148
|
+
/** Last time changes were pushed to linked persistence providers */
|
|
151
149
|
private lastPushed;
|
|
152
150
|
get isValueDirty(): boolean;
|
|
153
151
|
get isViewSavable(): boolean;
|
|
@@ -179,6 +177,10 @@ export declare class ViewManagerModel<T = PlainObject> extends HoistModel {
|
|
|
179
177
|
userUnpin(view: ViewInfo): void;
|
|
180
178
|
isUserPinned(view: ViewInfo): boolean | null;
|
|
181
179
|
validateViewNameAsync(name: string, existing?: ViewInfo): Promise<string>;
|
|
180
|
+
/** Update all aspects of a view's metadata.*/
|
|
181
|
+
updateViewInfoAsync(view: ViewInfo, updates: ViewUpdateSpec): Promise<View<T>>;
|
|
182
|
+
/** Promote a view to global visibility/ownership status. */
|
|
183
|
+
makeViewGlobalAsync(view: ViewInfo): Promise<View<T>>;
|
|
182
184
|
deleteViewsAsync(toDelete: ViewInfo[]): Promise<void>;
|
|
183
185
|
private initAsync;
|
|
184
186
|
private loadViewAsync;
|
|
@@ -29,7 +29,7 @@ import {runInAction} from 'mobx';
|
|
|
29
29
|
import {ReactNode} from 'react';
|
|
30
30
|
import {ViewInfo} from './ViewInfo';
|
|
31
31
|
import {View} from './View';
|
|
32
|
-
import {ViewToBlobApi, ViewCreateSpec} from './ViewToBlobApi';
|
|
32
|
+
import {ViewToBlobApi, ViewCreateSpec, ViewUpdateSpec} from './ViewToBlobApi';
|
|
33
33
|
|
|
34
34
|
export interface ViewManagerConfig {
|
|
35
35
|
/**
|
|
@@ -201,13 +201,10 @@ export class ViewManagerModel<T = PlainObject> extends HoistModel {
|
|
|
201
201
|
*/
|
|
202
202
|
providers: ViewManagerProvider<any>[] = [];
|
|
203
203
|
|
|
204
|
-
/**
|
|
205
|
-
|
|
206
|
-
* @internal
|
|
207
|
-
*/
|
|
208
|
-
api: ViewToBlobApi<T>;
|
|
204
|
+
/** Data access for persisting views. */
|
|
205
|
+
private api: ViewToBlobApi<T>;
|
|
209
206
|
|
|
210
|
-
|
|
207
|
+
/** Last time changes were pushed to linked persistence providers */
|
|
211
208
|
private lastPushed: number = null;
|
|
212
209
|
|
|
213
210
|
//---------------
|
|
@@ -442,6 +439,16 @@ export class ViewManagerModel<T = PlainObject> extends HoistModel {
|
|
|
442
439
|
return null;
|
|
443
440
|
}
|
|
444
441
|
|
|
442
|
+
/** Update all aspects of a view's metadata.*/
|
|
443
|
+
async updateViewInfoAsync(view: ViewInfo, updates: ViewUpdateSpec): Promise<View<T>> {
|
|
444
|
+
return this.api.updateViewInfoAsync(view, updates);
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
/** Promote a view to global visibility/ownership status. */
|
|
448
|
+
async makeViewGlobalAsync(view: ViewInfo): Promise<View<T>> {
|
|
449
|
+
return this.api.makeViewGlobalAsync(view);
|
|
450
|
+
}
|
|
451
|
+
|
|
445
452
|
async deleteViewsAsync(toDelete: ViewInfo[]): Promise<void> {
|
|
446
453
|
let exception;
|
|
447
454
|
try {
|
|
@@ -64,14 +64,24 @@ export const [ViewManager, viewManager] = hoistCmp.withFactory<ViewManagerProps>
|
|
|
64
64
|
showRevertButton = 'never',
|
|
65
65
|
buttonSide = 'right'
|
|
66
66
|
}: ViewManagerProps) {
|
|
67
|
-
const
|
|
67
|
+
const {loadModel} = model,
|
|
68
|
+
locModel = useLocalModel(() => new ViewManagerLocalModel(model)),
|
|
68
69
|
save = saveButton({model: locModel, mode: showSaveButton, ...saveButtonProps}),
|
|
69
70
|
revert = revertButton({model: locModel, mode: showRevertButton, ...revertButtonProps}),
|
|
70
71
|
menu = popover({
|
|
71
72
|
disabled: !locModel.isVisible, // Prevent orphaned popover menu
|
|
72
73
|
item: menuButton({model: locModel, ...menuButtonProps}),
|
|
73
|
-
content:
|
|
74
|
-
|
|
74
|
+
content: loadModel.isPending
|
|
75
|
+
? box({
|
|
76
|
+
item: spinner({compact: true}),
|
|
77
|
+
alignItems: 'center',
|
|
78
|
+
justifyContent: 'center',
|
|
79
|
+
height: 30,
|
|
80
|
+
width: 30
|
|
81
|
+
})
|
|
82
|
+
: viewMenu({model: locModel}),
|
|
83
|
+
onOpening: () => model.refreshAsync(),
|
|
84
|
+
placement: 'bottom',
|
|
75
85
|
popoverClassName: 'xh-view-manager__popover'
|
|
76
86
|
});
|
|
77
87
|
return fragment(
|
|
@@ -5,15 +5,12 @@
|
|
|
5
5
|
* Copyright © 2024 Extremely Heavy Industries Inc.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import {box} from '@xh/hoist/cmp/layout';
|
|
9
|
-
import {spinner} from '@xh/hoist/cmp/spinner';
|
|
10
8
|
import {hoistCmp} from '@xh/hoist/core';
|
|
11
9
|
import {ViewManagerModel, ViewInfo} from '@xh/hoist/cmp/viewmanager';
|
|
12
10
|
import {switchInput} from '@xh/hoist/desktop/cmp/input';
|
|
13
11
|
import {Icon} from '@xh/hoist/icon';
|
|
14
12
|
import {menu, menuDivider, menuItem} from '@xh/hoist/kit/blueprint';
|
|
15
|
-
import {
|
|
16
|
-
import {consumeEvent, pluralize} from '@xh/hoist/utils/js';
|
|
13
|
+
import {pluralize} from '@xh/hoist/utils/js';
|
|
17
14
|
import {Dictionary} from 'express-serve-static-core';
|
|
18
15
|
import {each, filter, groupBy, isEmpty, orderBy, some, startCase} from 'lodash';
|
|
19
16
|
import {ReactNode} from 'react';
|
|
@@ -83,7 +80,6 @@ function getOtherMenuItems(model: ViewManagerLocalModel): ReactNode[] {
|
|
|
83
80
|
isViewSavable,
|
|
84
81
|
views,
|
|
85
82
|
isValueDirty,
|
|
86
|
-
loadModel,
|
|
87
83
|
typeDisplayName
|
|
88
84
|
} = parent;
|
|
89
85
|
|
|
@@ -126,21 +122,6 @@ function getOtherMenuItems(model: ViewManagerLocalModel): ReactNode[] {
|
|
|
126
122
|
disabled: isEmpty(views),
|
|
127
123
|
text: `Manage ${pluralName}...`,
|
|
128
124
|
onClick: () => model.manageDialogModel.open()
|
|
129
|
-
}),
|
|
130
|
-
menuItem({
|
|
131
|
-
icon: !loadModel.isPending
|
|
132
|
-
? Icon.refresh()
|
|
133
|
-
: box({
|
|
134
|
-
height: 20,
|
|
135
|
-
item: spinner({width: 16.25, height: 16.25})
|
|
136
|
-
}),
|
|
137
|
-
disabled: loadModel.isPending,
|
|
138
|
-
text: `Refresh ${pluralName}`,
|
|
139
|
-
onClick: e => {
|
|
140
|
-
// Ensure at least 100ms delay to render spinner
|
|
141
|
-
Promise.all([wait(100), parent.refreshAsync()]).linkTo(loadModel);
|
|
142
|
-
consumeEvent(e);
|
|
143
|
-
}
|
|
144
125
|
})
|
|
145
126
|
];
|
|
146
127
|
}
|
|
@@ -17,7 +17,7 @@ import {viewsGrid} from '@xh/hoist/desktop/cmp/viewmanager/dialog/ManageDialog';
|
|
|
17
17
|
import {Icon} from '@xh/hoist/icon';
|
|
18
18
|
import {action, bindable, computed, makeObservable, observable, runInAction} from '@xh/hoist/mobx';
|
|
19
19
|
import {pluralize} from '@xh/hoist/utils/js';
|
|
20
|
-
import {capitalize, compact, isEmpty, some, startCase} from 'lodash';
|
|
20
|
+
import {capitalize, compact, every, isEmpty, some, startCase} from 'lodash';
|
|
21
21
|
import {ReactNode} from 'react';
|
|
22
22
|
import {ViewPanelModel} from './ViewPanelModel';
|
|
23
23
|
|
|
@@ -128,7 +128,11 @@ export class ManageDialogModel extends HoistModel {
|
|
|
128
128
|
|
|
129
129
|
@action
|
|
130
130
|
togglePinned(views: ViewInfo[]) {
|
|
131
|
-
|
|
131
|
+
const allPinned = every(views, 'isPinned'),
|
|
132
|
+
{viewManagerModel} = this;
|
|
133
|
+
views.forEach(v =>
|
|
134
|
+
allPinned ? viewManagerModel.userUnpin(v) : viewManagerModel.userPin(v)
|
|
135
|
+
);
|
|
132
136
|
this.refreshAsync();
|
|
133
137
|
}
|
|
134
138
|
|
|
@@ -173,7 +177,7 @@ export class ManageDialogModel extends HoistModel {
|
|
|
173
177
|
|
|
174
178
|
private async doUpdateAsync(view: ViewInfo, update: ViewUpdateSpec) {
|
|
175
179
|
const {viewManagerModel} = this;
|
|
176
|
-
await viewManagerModel.
|
|
180
|
+
await viewManagerModel.updateViewInfoAsync(view, update);
|
|
177
181
|
await viewManagerModel.refreshAsync();
|
|
178
182
|
await this.refreshAsync();
|
|
179
183
|
}
|
|
@@ -235,7 +239,7 @@ export class ManageDialogModel extends HoistModel {
|
|
|
235
239
|
if (!confirmed) return;
|
|
236
240
|
|
|
237
241
|
const {viewManagerModel} = this;
|
|
238
|
-
const updated = await viewManagerModel.
|
|
242
|
+
const updated = await viewManagerModel.makeViewGlobalAsync(view);
|
|
239
243
|
await viewManagerModel.refreshAsync();
|
|
240
244
|
await this.refreshAsync();
|
|
241
245
|
await this.selectViewAsync(updated.info); // reselect -- will have moved tabs!
|
|
@@ -293,7 +297,7 @@ export class ManageDialogModel extends HoistModel {
|
|
|
293
297
|
{field: 'name', flex: true},
|
|
294
298
|
{field: 'group', hidden: true},
|
|
295
299
|
{field: 'owner', hidden: true},
|
|
296
|
-
{field: 'lastUpdated', ...dateTimeCol},
|
|
300
|
+
{field: 'lastUpdated', ...dateTimeCol, hidden: true},
|
|
297
301
|
{
|
|
298
302
|
field: 'isPinned',
|
|
299
303
|
width: 40,
|
|
@@ -11,7 +11,7 @@ import {button} from '@xh/hoist/desktop/cmp/button';
|
|
|
11
11
|
import {panel} from '@xh/hoist/desktop/cmp/panel';
|
|
12
12
|
import {Icon} from '@xh/hoist/icon';
|
|
13
13
|
import {pluralize} from '@xh/hoist/utils/js';
|
|
14
|
-
import {every, isEmpty
|
|
14
|
+
import {every, isEmpty} from 'lodash';
|
|
15
15
|
import {ManageDialogModel} from './ManageDialogModel';
|
|
16
16
|
|
|
17
17
|
export const viewMultiPanel = hoistCmp.factory<ManageDialogModel>({
|
|
@@ -38,8 +38,7 @@ const buttons = hoistCmp.factory<ManageDialogModel>({
|
|
|
38
38
|
render({model}) {
|
|
39
39
|
const views = model.selectedViews,
|
|
40
40
|
allEditable = every(views, 'isEditable'),
|
|
41
|
-
allPinned = every(views, 'isPinned')
|
|
42
|
-
allUnpinned = !some(views, 'isPinned');
|
|
41
|
+
allPinned = every(views, 'isPinned');
|
|
43
42
|
|
|
44
43
|
return vbox({
|
|
45
44
|
style: {gap: 10, alignItems: 'center'},
|
|
@@ -52,7 +51,6 @@ const buttons = hoistCmp.factory<ManageDialogModel>({
|
|
|
52
51
|
}),
|
|
53
52
|
width: 200,
|
|
54
53
|
outlined: true,
|
|
55
|
-
omit: !(allPinned || allUnpinned),
|
|
56
54
|
onClick: () => model.togglePinned(views)
|
|
57
55
|
}),
|
|
58
56
|
button({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xh/hoist",
|
|
3
|
-
"version": "71.0.0-SNAPSHOT.
|
|
3
|
+
"version": "71.0.0-SNAPSHOT.1734627276913",
|
|
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",
|