@xh/hoist 71.0.0-SNAPSHOT.1736191971390 → 71.0.0-SNAPSHOT.1736192713803

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.
@@ -15,7 +15,7 @@ export declare class DataAccess<T> {
15
15
  state: ViewUserState;
16
16
  }>;
17
17
  /** Fetch the latest version of a view. */
18
- fetchViewAsync(token: String): Promise<View<T>>;
18
+ fetchViewAsync(info: ViewInfo): Promise<View<T>>;
19
19
  /** Create a new view, owned by the current user.*/
20
20
  createViewAsync(spec: ViewCreateSpec): Promise<View<T>>;
21
21
  /** Update all aspects of a view's metadata.*/
@@ -183,7 +183,9 @@ export declare class ViewManagerModel<T = PlainObject> extends HoistModel {
183
183
  */
184
184
  private constructor();
185
185
  doLoadAsync(loadSpec: LoadSpec): Promise<void>;
186
- selectViewAsync(token: string): Promise<void>;
186
+ selectViewAsync(info: ViewInfo, opts?: {
187
+ alertUnsavedChanges: boolean;
188
+ }): Promise<void>;
187
189
  saveAsAsync(spec: ViewCreateSpec): Promise<void>;
188
190
  saveAsync(): Promise<void>;
189
191
  resetAsync(): Promise<void>;
@@ -48,14 +48,14 @@ export class DataAccess<T> {
48
48
  }
49
49
 
50
50
  /** Fetch the latest version of a view. */
51
- async fetchViewAsync(token: String): Promise<View<T>> {
51
+ async fetchViewAsync(info: ViewInfo): Promise<View<T>> {
52
52
  const {model} = this;
53
- if (!token) return View.createDefault(model);
53
+ if (!info) return View.createDefault(model);
54
54
  try {
55
- const raw = await XH.fetchJson({url: 'xhView/get', params: {token}});
55
+ const raw = await XH.fetchJson({url: 'xhView/get', params: {token: info.token}});
56
56
  return View.fromBlob(raw, model);
57
57
  } catch (e) {
58
- throw XH.exception({message: `Unable to fetch view with token ${token}`, cause: e});
58
+ throw XH.exception({message: `Unable to fetch ${info.typedName}`, cause: e});
59
59
  }
60
60
  }
61
61
 
@@ -21,7 +21,7 @@ import {fmtDateTime} from '@xh/hoist/format';
21
21
  import {action, bindable, makeObservable, observable, comparer, runInAction} from '@xh/hoist/mobx';
22
22
  import {olderThan, SECONDS} from '@xh/hoist/utils/datetime';
23
23
  import {executeIfFunction, pluralize, throwIf} from '@xh/hoist/utils/js';
24
- import {find, isEqual, isNil, isNull, isUndefined, lowerCase} from 'lodash';
24
+ import {find, isEqual, isNil, isNull, isUndefined, lowerCase, uniqBy} from 'lodash';
25
25
  import {ReactNode} from 'react';
26
26
  import {ViewInfo} from './ViewInfo';
27
27
  import {View} from './View';
@@ -337,7 +337,7 @@ export class ViewManagerModel<T = PlainObject> extends HoistModel {
337
337
  if (!view.isDefault) {
338
338
  const latestInfo = find(views, {token: view.token});
339
339
  if (latestInfo && latestInfo.lastUpdated > view.lastUpdated) {
340
- this.loadViewAsync(view.token, this.pendingValue);
340
+ this.loadViewAsync(latestInfo, this.pendingValue);
341
341
  }
342
342
  }
343
343
  } catch (e) {
@@ -346,18 +346,23 @@ export class ViewManagerModel<T = PlainObject> extends HoistModel {
346
346
  }
347
347
  }
348
348
 
349
- async selectViewAsync(token: string): Promise<void> {
349
+ async selectViewAsync(info: ViewInfo, opts = {alertUnsavedChanges: true}): Promise<void> {
350
350
  // ensure any pending auto-save gets completed
351
351
  if (this.isValueDirty && this.isViewAutoSavable) {
352
352
  await this.maybeAutoSaveAsync();
353
353
  }
354
354
 
355
355
  // if still dirty, require confirm
356
- if (this.isValueDirty && this.view.isOwned && !(await this.confirmDiscardChangesAsync())) {
356
+ if (
357
+ opts.alertUnsavedChanges &&
358
+ this.isValueDirty &&
359
+ this.view.isOwned &&
360
+ !(await this.confirmDiscardChangesAsync())
361
+ ) {
357
362
  return;
358
363
  }
359
364
 
360
- return this.loadViewAsync(token);
365
+ await this.loadViewAsync(info).catch(e => this.handleException(e));
361
366
  }
362
367
 
363
368
  async saveAsAsync(spec: ViewCreateSpec): Promise<void> {
@@ -394,7 +399,7 @@ export class ViewManagerModel<T = PlainObject> extends HoistModel {
394
399
  }
395
400
 
396
401
  async resetAsync(): Promise<void> {
397
- await this.loadViewAsync(this.view.info.token).catch(e => this.handleException(e));
402
+ await this.loadViewAsync(this.view.info).catch(e => this.handleException(e));
398
403
  }
399
404
 
400
405
  //--------------------------------
@@ -478,7 +483,7 @@ export class ViewManagerModel<T = PlainObject> extends HoistModel {
478
483
  const {views} = this;
479
484
 
480
485
  if (toDelete.some(view => view.isCurrentView) && !views.some(view => view.isCurrentView)) {
481
- await this.loadViewAsync(this.initialViewSpec?.(views)?.token);
486
+ await this.loadViewAsync(this.initialViewSpec?.(views));
482
487
  }
483
488
 
484
489
  if (exception) throw exception;
@@ -564,13 +569,13 @@ export class ViewManagerModel<T = PlainObject> extends HoistModel {
564
569
  }
565
570
 
566
571
  private async loadViewAsync(
567
- token: String,
572
+ info: ViewInfo,
568
573
  pendingValue: PendingValue<T> = null
569
574
  ): Promise<void> {
570
575
  return this.dataAccess
571
- .fetchViewAsync(token)
576
+ .fetchViewAsync(info)
572
577
  .thenAction(latest => {
573
- this.setAsView(latest, pendingValue?.token == token ? pendingValue : null);
578
+ this.setAsView(latest, pendingValue?.token == info?.token ? pendingValue : null);
574
579
  this.providers.forEach(it => it.pushStateToTarget());
575
580
  this.lastPushed = Date.now();
576
581
  })
@@ -604,7 +609,7 @@ export class ViewManagerModel<T = PlainObject> extends HoistModel {
604
609
  this.pendingValue = pendingValue;
605
610
  // Ensure we update meta-data as well.
606
611
  if (!view.isDefault) {
607
- this.views = this.views.map(v => (v.token === view.token ? view.info : v));
612
+ this.views = uniqBy([view.info, ...this.views], 'token');
608
613
  }
609
614
  }
610
615
 
@@ -644,7 +649,7 @@ export class ViewManagerModel<T = PlainObject> extends HoistModel {
644
649
 
645
650
  private async maybeConfirmSaveAsync(view: View, pendingValue: PendingValue<T>) {
646
651
  // Get latest from server for reference
647
- const latest = await this.dataAccess.fetchViewAsync(view.info.token),
652
+ const latest = await this.dataAccess.fetchViewAsync(view.info),
648
653
  isGlobal = latest.isGlobal,
649
654
  isStale = latest.lastUpdated > pendingValue.baseUpdated;
650
655
  if (!isStale && !isGlobal) return true;
@@ -63,7 +63,7 @@ function getNavMenuItems(model: ViewManagerModel): ReactNode[] {
63
63
  className: 'xh-view-manager__menu-item',
64
64
  icon: view.isDefault ? Icon.check() : Icon.placeholder(),
65
65
  text: `Default ${startCase(typeDisplayName)}`,
66
- onClick: () => model.selectViewAsync(null).catchDefault()
66
+ onClick: () => model.selectViewAsync(null)
67
67
  })
68
68
  );
69
69
  }
@@ -168,6 +168,6 @@ function viewMenuItem(view: ViewInfo, model: ViewManagerModel): ReactNode {
168
168
  text: view.name,
169
169
  title: title.join(' | '),
170
170
  icon,
171
- onClick: () => model.selectViewAsync(view.token).catchDefault()
171
+ onClick: () => model.selectViewAsync(view)
172
172
  });
173
173
  }
@@ -86,7 +86,7 @@ export class ManageDialogModel extends HoistModel {
86
86
  }
87
87
 
88
88
  activateSelectedViewAndClose() {
89
- this.viewManagerModel.selectViewAsync(this.selectedView.token).catchDefault();
89
+ this.viewManagerModel.selectViewAsync(this.selectedView);
90
90
  this.close();
91
91
  }
92
92
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xh/hoist",
3
- "version": "71.0.0-SNAPSHOT.1736191971390",
3
+ "version": "71.0.0-SNAPSHOT.1736192713803",
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",