@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.
@@ -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 { ViewToBlobApi, ViewCreateSpec } from './ViewToBlobApi';
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
- * Data access for persisting views.
148
- * @internal
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
- * Data access for persisting views.
206
- * @internal
207
- */
208
- api: ViewToBlobApi<T>;
204
+ /** Data access for persisting views. */
205
+ private api: ViewToBlobApi<T>;
209
206
 
210
- // Last time changes were pushed to linked persistence providers
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 locModel = useLocalModel(() => new ViewManagerLocalModel(model)),
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: viewMenu({model: locModel}),
74
- placement: 'bottom-start',
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 {wait} from '@xh/hoist/promise';
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
- views.forEach(v => this.viewManagerModel.togglePinned(v));
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.api.updateViewInfoAsync(view, update);
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.api.makeViewGlobalAsync(view);
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, some} from 'lodash';
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.1734551243081",
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",