@xh/hoist 79.0.0-SNAPSHOT.1767027974015 → 79.0.0-SNAPSHOT.1767029174152

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 CHANGED
@@ -54,6 +54,8 @@
54
54
  * `RelativeTimestampProps.options` - provide directly as top-level props
55
55
 
56
56
  * Improved the efficiency and logging of MsalClient.
57
+ * Improved protections against running stale versions of client app code.
58
+
57
59
 
58
60
  ### 📚 Libraries
59
61
  * react-grid-layout `1.5.0 → 2.1.1`
@@ -40,7 +40,7 @@ import {
40
40
  TrackService,
41
41
  WebSocketService
42
42
  } from '@xh/hoist/svc';
43
- import {checkMinVersion, createSingleton, throwIf} from '@xh/hoist/utils/js';
43
+ import {createSingleton, throwIf} from '@xh/hoist/utils/js';
44
44
  import {compact, isEmpty} from 'lodash';
45
45
  import {AboutDialogModel} from './AboutDialogModel';
46
46
  import {BannerSourceModel} from './BannerSourceModel';
@@ -60,7 +60,6 @@ import {AppStateModel} from './AppStateModel';
60
60
  import {PageStateModel} from './PageStateModel';
61
61
  import {RouterModel} from './RouterModel';
62
62
  import {installServicesAsync} from '../core/impl/InstallServices';
63
- import {MIN_HOIST_CORE_VERSION} from '../core/XH';
64
63
 
65
64
  /**
66
65
  * Root object for Framework GUI State.
@@ -237,13 +236,6 @@ export class AppContainerModel extends HoistModel {
237
236
  await installServicesAsync(TrackService);
238
237
  await installServicesAsync([EnvironmentService, PrefService, JsonBlobService]);
239
238
 
240
- // Confirm hoist-core version after environment service loaded.
241
- const hcVersion = XH.getEnv('hoistCoreVersion');
242
- throwIf(
243
- !checkMinVersion(hcVersion, MIN_HOIST_CORE_VERSION),
244
- `This version of Hoist React requires the server to run Hoist Core ≥ v${MIN_HOIST_CORE_VERSION}. Version ${hcVersion} detected.`
245
- );
246
-
247
239
  await installServicesAsync([
248
240
  AlertBannerService,
249
241
  AutoRefreshService,
@@ -201,12 +201,27 @@ export interface GridConfig {
201
201
  * Flags for experimental features. These features are designed for early client-access and
202
202
  * testing, but are not yet part of the Hoist API.
203
203
  */
204
- experimental?: PlainObject;
204
+ experimental?: GridExperimentalFlags;
205
205
  /** Extra app-specific data for the GridModel. */
206
206
  appData?: PlainObject;
207
207
  /** @internal */
208
208
  xhImpl?: boolean;
209
209
  }
210
+ interface GridExperimentalFlags {
211
+ /**
212
+ * Set to true to enable more optimal row sorting in cases where only small subsets of rows are
213
+ * updated in configurations where rows have many siblings.
214
+ * See https://www.ag-grid.com/javascript-data-grid/grid-options/#reference-sort-deltaSort for
215
+ * more details on where this option may improve (or degrade) performance.
216
+ */
217
+ deltaSort?: boolean;
218
+ /**
219
+ * Set to true to disable scroll optimization for large grids, where we proactively update the
220
+ * row heights in ag-grid whenever the data changes to avoid hitching while quickly scrolling
221
+ * through large grids.
222
+ */
223
+ disableScrollOptimization?: boolean;
224
+ }
210
225
  /**
211
226
  * Core Model for a Grid, specifying the grid's data store, column definitions,
212
227
  * sorting/grouping/selection state, and context menu configuration.
@@ -253,7 +268,7 @@ export declare class GridModel extends HoistModel {
253
268
  lockColumnGroups: boolean;
254
269
  headerMenuDisplay: 'always' | 'hover';
255
270
  colDefaults: Partial<ColumnSpec>;
256
- experimental: PlainObject;
271
+ experimental: GridExperimentalFlags;
257
272
  onKeyDown: (e: KeyboardEvent) => void;
258
273
  onRowClicked: (e: RowClickedEvent) => void;
259
274
  onRowDoubleClicked: (e: RowDoubleClickedEvent) => void;
@@ -576,6 +591,10 @@ export declare class GridModel extends HoistModel {
576
591
  * Sorts ungrouped items to the bottom.
577
592
  */
578
593
  defaultGroupSortFn: (a: string, b: string) => number;
594
+ /** @internal */
595
+ get deltaSort(): boolean;
596
+ /** @internal */
597
+ get disableScrollOptimization(): boolean;
579
598
  private buildColumn;
580
599
  private autosizeColsInternalAsync;
581
600
  private gatherLeaves;
@@ -601,3 +620,4 @@ export declare class GridModel extends HoistModel {
601
620
  private createGroupBorderFn;
602
621
  private getDefaultStateForColumn;
603
622
  }
623
+ export {};
@@ -28,8 +28,6 @@ export declare class EnvironmentService extends HoistService {
28
28
  get appEnvironment(): AppEnvironment;
29
29
  isProduction(): boolean;
30
30
  isTest(): boolean;
31
- isMinHoistCoreVersion(version: string): boolean;
32
- isMaxHoistCoreVersion(version: string): boolean;
33
31
  /**
34
32
  * Update critical environment information from server, including current app version + build,
35
33
  * upgrade prompt mode, and alert banner.
@@ -38,6 +36,7 @@ export declare class EnvironmentService extends HoistService {
38
36
  */
39
37
  pollServerAsync(): Promise<void>;
40
38
  constructor();
39
+ private ensureVersionRunnable;
41
40
  private startPolling;
42
41
  private setServerInfo;
43
42
  private get pollIntervalMs();
package/cmp/grid/Grid.ts CHANGED
@@ -196,9 +196,10 @@ export class GridLocalModel extends HoistModel {
196
196
 
197
197
  private createDefaultAgOptions(): GridOptions {
198
198
  const {model} = this,
199
- {clicksToEdit, selModel} = model;
199
+ {clicksToEdit, selModel, deltaSort} = model;
200
200
 
201
201
  let ret: GridOptions = {
202
+ deltaSort,
202
203
  animateRows: false,
203
204
  suppressColumnVirtualisation: !model.useVirtualColumns,
204
205
  getRowId: ({data}) => data.agId,
@@ -442,6 +443,7 @@ export class GridLocalModel extends HoistModel {
442
443
  // when node is rendered in viewport.
443
444
  const {model, agOptions} = this;
444
445
  return (
446
+ !model.disableScrollOptimization &&
445
447
  agOptions.getRowHeight &&
446
448
  !agOptions.rowHeight &&
447
449
  !model.getVisibleLeafColumns().some(c => c.autoHeight)
@@ -450,6 +452,7 @@ export class GridLocalModel extends HoistModel {
450
452
 
451
453
  applyScrollOptimization() {
452
454
  if (!this.useScrollOptimization) return;
455
+
453
456
  const {agApi} = this.model,
454
457
  {getRowHeight} = this.agOptions,
455
458
  params = {api: agApi, context: null} as any;
@@ -605,6 +608,14 @@ export class GridLocalModel extends HoistModel {
605
608
  }
606
609
  }
607
610
 
611
+ // Early out if the data hasn't actually changed
612
+ if (
613
+ isEqual(pinnedTopRowData, agGridModel.getPinnedTopRowData()) &&
614
+ isEqual(pinnedBottomRowData, agGridModel.getPinnedBottomRowData())
615
+ ) {
616
+ return;
617
+ }
618
+
608
619
  agApi.updateGridOptions({
609
620
  pinnedTopRowData,
610
621
  pinnedBottomRowData
@@ -690,7 +701,9 @@ export class GridLocalModel extends HoistModel {
690
701
  model.autosizeAsync({columns});
691
702
  }
692
703
 
693
- model.noteAgExpandStateChange();
704
+ if (model.treeMode || !isEmpty(model.groupBy)) {
705
+ model.noteAgExpandStateChange();
706
+ }
694
707
 
695
708
  this.prevRs = newRs;
696
709
  this.applyScrollOptimization();
@@ -357,7 +357,7 @@ export interface GridConfig {
357
357
  * Flags for experimental features. These features are designed for early client-access and
358
358
  * testing, but are not yet part of the Hoist API.
359
359
  */
360
- experimental?: PlainObject;
360
+ experimental?: GridExperimentalFlags;
361
361
 
362
362
  /** Extra app-specific data for the GridModel. */
363
363
  appData?: PlainObject;
@@ -366,6 +366,23 @@ export interface GridConfig {
366
366
  xhImpl?: boolean;
367
367
  }
368
368
 
369
+ interface GridExperimentalFlags {
370
+ /**
371
+ * Set to true to enable more optimal row sorting in cases where only small subsets of rows are
372
+ * updated in configurations where rows have many siblings.
373
+ * See https://www.ag-grid.com/javascript-data-grid/grid-options/#reference-sort-deltaSort for
374
+ * more details on where this option may improve (or degrade) performance.
375
+ */
376
+ deltaSort?: boolean;
377
+
378
+ /**
379
+ * Set to true to disable scroll optimization for large grids, where we proactively update the
380
+ * row heights in ag-grid whenever the data changes to avoid hitching while quickly scrolling
381
+ * through large grids.
382
+ */
383
+ disableScrollOptimization?: boolean;
384
+ }
385
+
369
386
  /**
370
387
  * Core Model for a Grid, specifying the grid's data store, column definitions,
371
388
  * sorting/grouping/selection state, and context menu configuration.
@@ -420,7 +437,7 @@ export class GridModel extends HoistModel {
420
437
  lockColumnGroups: boolean;
421
438
  headerMenuDisplay: 'always' | 'hover';
422
439
  colDefaults: Partial<ColumnSpec>;
423
- experimental: PlainObject;
440
+ experimental: GridExperimentalFlags;
424
441
  onKeyDown: (e: KeyboardEvent) => void;
425
442
  onRowClicked: (e: RowClickedEvent) => void;
426
443
  onRowDoubleClicked: (e: RowDoubleClickedEvent) => void;
@@ -1565,6 +1582,16 @@ export class GridModel extends HoistModel {
1565
1582
  return a.localeCompare(b);
1566
1583
  };
1567
1584
 
1585
+ /** @internal */
1586
+ get deltaSort() {
1587
+ return !!this.experimental.deltaSort;
1588
+ }
1589
+
1590
+ /** @internal */
1591
+ get disableScrollOptimization() {
1592
+ return !!this.experimental.disableScrollOptimization;
1593
+ }
1594
+
1568
1595
  //-----------------------
1569
1596
  // Implementation
1570
1597
  //-----------------------
@@ -1887,7 +1914,7 @@ export class GridModel extends HoistModel {
1887
1914
  return new GridFilterModel({bind: this.store, ...filterModel}, this);
1888
1915
  }
1889
1916
 
1890
- private parseExperimental(experimental) {
1917
+ private parseExperimental(experimental: GridExperimentalFlags) {
1891
1918
  return {
1892
1919
  ...XH.getConf('xhGridExperimental', {}),
1893
1920
  ...experimental
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xh/hoist",
3
- "version": "79.0.0-SNAPSHOT.1767027974015",
3
+ "version": "79.0.0-SNAPSHOT.1767029174152",
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",
@@ -11,10 +11,11 @@ import {action, makeObservable, observable} from '@xh/hoist/mobx';
11
11
  import hoistPkg from '@xh/hoist/package.json';
12
12
  import {Timer} from '@xh/hoist/utils/async';
13
13
  import {MINUTES, SECONDS} from '@xh/hoist/utils/datetime';
14
- import {checkMaxVersion, checkMinVersion, deepFreeze} from '@xh/hoist/utils/js';
14
+ import {checkMinVersion, deepFreeze, throwIf} from '@xh/hoist/utils/js';
15
15
  import {defaults, isFinite} from 'lodash';
16
16
  import mobxPkg from 'mobx/package.json';
17
17
  import {version as reactVersion} from 'react';
18
+ import {MIN_HOIST_CORE_VERSION} from '../core/XH';
18
19
 
19
20
  /**
20
21
  * Load and report on the client and server environment, including software versions, timezones, and
@@ -78,6 +79,8 @@ export class EnvironmentService extends HoistService {
78
79
 
79
80
  this.setServerInfo(instanceName, serverEnv.appVersion, serverEnv.appBuild);
80
81
 
82
+ this.ensureVersionRunnable();
83
+
81
84
  this.pollConfig = pollConfig;
82
85
  this.addReaction({
83
86
  when: () => XH.appIsRunning,
@@ -104,14 +107,6 @@ export class EnvironmentService extends HoistService {
104
107
  return this.appEnvironment === 'Test';
105
108
  }
106
109
 
107
- isMinHoistCoreVersion(version: string): boolean {
108
- return checkMinVersion(this.get('hoistCoreVersion'), version);
109
- }
110
-
111
- isMaxHoistCoreVersion(version: string): boolean {
112
- return checkMaxVersion(this.get('hoistCoreVersion'), version);
113
- }
114
-
115
110
  /**
116
111
  * Update critical environment information from server, including current app version + build,
117
112
  * upgrade prompt mode, and alert banner.
@@ -165,6 +160,31 @@ export class EnvironmentService extends HoistService {
165
160
  makeObservable(this);
166
161
  }
167
162
 
163
+ private ensureVersionRunnable() {
164
+ const hcVersion = this.get('hoistCoreVersion'),
165
+ clientVersion = this.get('appVersion'),
166
+ serverVersion = this.serverVersion;
167
+
168
+ // Check for client/server mismatch version. It's an ok transitory state *during* the
169
+ // client app lifetime, but app should *never* start this way, would indicate caching issue.
170
+ throwIf(
171
+ clientVersion != serverVersion,
172
+ XH.exception(
173
+ `The version of this client (${clientVersion}) is out of sync with the
174
+ available server (${serverVersion}). Please reload to continue.`
175
+ )
176
+ );
177
+
178
+ // Confirm hoist-core/react version mismatch (developer issue)
179
+ throwIf(
180
+ !checkMinVersion(hcVersion, MIN_HOIST_CORE_VERSION),
181
+ XH.exception(
182
+ `This version of Hoist React requires the server to run
183
+ Hoist Core ≥ v${MIN_HOIST_CORE_VERSION}. Version ${hcVersion} detected.`
184
+ )
185
+ );
186
+ }
187
+
168
188
  private startPolling() {
169
189
  this.pollTimer = Timer.create({
170
190
  runFn: () => this.pollServerAsync(),