@xh/hoist 59.3.2 → 59.5.0

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.
Files changed (83) hide show
  1. package/CHANGELOG.md +39 -3
  2. package/admin/differ/DifferModel.ts +5 -7
  3. package/appcontainer/AppContainerModel.ts +8 -10
  4. package/appcontainer/AppStateModel.ts +3 -2
  5. package/appcontainer/PageStateModel.ts +1 -2
  6. package/appcontainer/SizingModeModel.ts +2 -2
  7. package/cmp/ag-grid/AgGrid.ts +4 -3
  8. package/cmp/ag-grid/AgGridModel.ts +19 -14
  9. package/cmp/chart/Chart.ts +4 -3
  10. package/cmp/dataview/DataViewModel.ts +2 -2
  11. package/cmp/filter/FilterChooserModel.ts +5 -5
  12. package/cmp/grid/Grid.ts +9 -7
  13. package/cmp/grid/GridContextMenu.ts +2 -2
  14. package/cmp/grid/GridModel.ts +13 -21
  15. package/cmp/grid/Types.ts +6 -5
  16. package/cmp/grid/columns/Column.ts +12 -12
  17. package/cmp/grid/columns/ColumnGroup.ts +17 -6
  18. package/cmp/grid/helpers/GridCountLabel.ts +5 -4
  19. package/cmp/grid/impl/ColumnWidthCalculator.ts +3 -3
  20. package/cmp/grid/impl/GridPersistenceModel.ts +11 -4
  21. package/cmp/grid/impl/Utils.ts +1 -1
  22. package/cmp/grid/renderers/MultiFieldRenderer.ts +28 -22
  23. package/cmp/grouping/GroupingChooserModel.ts +2 -2
  24. package/cmp/relativetimestamp/RelativeTimestamp.ts +5 -2
  25. package/cmp/tab/TabContainerModel.ts +2 -2
  26. package/cmp/zoneGrid/ZoneGridModel.ts +1 -1
  27. package/cmp/zoneGrid/impl/ZoneGridPersistenceModel.ts +10 -4
  28. package/core/HoistBase.ts +48 -8
  29. package/core/HoistBaseDecorators.ts +11 -6
  30. package/core/HoistComponent.ts +1 -3
  31. package/core/elem.ts +2 -2
  32. package/core/exception/ExceptionHandler.ts +4 -4
  33. package/core/impl/InstallServices.ts +2 -8
  34. package/core/load/LoadSupport.ts +10 -11
  35. package/core/model/HoistModel.ts +1 -1
  36. package/data/Store.ts +1 -1
  37. package/data/UrlStore.ts +3 -3
  38. package/data/cube/aggregate/UniqueAggregator.ts +3 -5
  39. package/data/filter/CompoundFilter.ts +5 -3
  40. package/data/filter/FieldFilter.ts +4 -3
  41. package/data/filter/Filter.ts +2 -3
  42. package/data/filter/FunctionFilter.ts +2 -1
  43. package/data/impl/RecordSet.ts +5 -5
  44. package/desktop/appcontainer/ToastSource.ts +1 -1
  45. package/desktop/cmp/button/ColChooserButton.ts +7 -5
  46. package/desktop/cmp/button/ZoneMapperButton.ts +7 -5
  47. package/desktop/cmp/dash/canvas/DashCanvasModel.ts +2 -2
  48. package/desktop/cmp/dash/container/DashContainerModel.ts +2 -2
  49. package/desktop/cmp/dock/DockViewModel.ts +21 -11
  50. package/desktop/cmp/dock/impl/DockView.ts +4 -2
  51. package/desktop/cmp/form/FormField.ts +2 -2
  52. package/desktop/cmp/grid/editors/BooleanEditor.ts +5 -1
  53. package/desktop/cmp/input/DateInput.ts +1 -3
  54. package/desktop/cmp/panel/Panel.ts +4 -2
  55. package/desktop/cmp/panel/PanelModel.ts +5 -5
  56. package/desktop/cmp/rest/Actions.ts +15 -9
  57. package/desktop/cmp/treemap/TreeMap.ts +7 -10
  58. package/inspector/instances/InstancesModel.ts +6 -6
  59. package/mobile/cmp/button/ColAutosizeButton.ts +4 -3
  60. package/mobile/cmp/button/ColChooserButton.ts +4 -3
  61. package/mobile/cmp/button/ExpandCollapseButton.ts +4 -3
  62. package/mobile/cmp/button/ZoneMapperButton.ts +4 -3
  63. package/mobile/cmp/input/DateInput.ts +1 -1
  64. package/mobile/cmp/input/Select.ts +3 -3
  65. package/mobile/cmp/panel/Panel.ts +4 -2
  66. package/package.json +2 -2
  67. package/svc/AutoRefreshService.ts +3 -3
  68. package/svc/ChangelogService.ts +3 -3
  69. package/svc/EnvironmentService.ts +1 -1
  70. package/svc/FetchService.ts +5 -5
  71. package/svc/GridAutosizeService.ts +4 -7
  72. package/svc/GridExportService.ts +3 -8
  73. package/svc/IdentityService.ts +1 -1
  74. package/svc/TrackService.ts +9 -15
  75. package/svc/WebSocketService.ts +14 -15
  76. package/utils/async/AsyncUtils.ts +3 -2
  77. package/utils/async/Timer.ts +5 -4
  78. package/utils/datetime/LocalDate.ts +13 -13
  79. package/utils/js/BrowserUtils.ts +8 -8
  80. package/utils/js/Decorators.ts +18 -3
  81. package/utils/js/LangUtils.ts +10 -9
  82. package/utils/js/LogUtils.ts +66 -26
  83. package/utils/react/LayoutPropUtils.ts +3 -3
package/CHANGELOG.md CHANGED
@@ -1,10 +1,46 @@
1
1
  # Changelog
2
2
 
3
+ ## 59.5.0 - 2023-12-11
4
+
5
+ ### 🎁 New Features
6
+
7
+ * Added new `dialogWidth` and `dialogHeight` configs to `DockViewModel`.
8
+
9
+ ### 🐞 Bug Fixes
10
+
11
+ * Fixed serialization of expand/collapse state within `AgGridModel`, which was badly broken and
12
+ could trigger long browser hangs for grids with > 2 levels of nesting and numeric record IDs.
13
+ * Fixed `UniqueAggregator` to properly check equality for `Date` fields.
14
+ * Pinned `react-grid-layout@1.4.3` to avoid v1.4.4 bugs affecting `DashCanvas` interactions
15
+ (see https://github.com/react-grid-layout/react-grid-layout/issues/1990).
16
+
17
+ ## 59.4.0 - 2023-11-28
18
+
19
+ ### 💥 Breaking Changes
20
+
21
+ * The constructors for `ColumnGroup` no long accept arbitrary rest (e.g `...rest`)
22
+ arguments for applying app-specific data to the object. Instead, use the new `appData` property.
23
+
24
+ ### ⚙️ Technical
25
+
26
+ * Enhanced `LogUtils` to support logging objects (and any other non-string values). Also
27
+ added new exports for `logWarn()` and `logError()` with the same standardized formatting.
28
+ * Added standardized `LogUtils` methods to `HoistBase`, for use within Hoist models and services.
29
+
30
+ ### 🐞 Bug Fixes
31
+
32
+ * `ZoneGrid` will no longer render labels or delimiters for empty values.
33
+
34
+ ### ⚙️ Typescript API Adjustments
35
+
36
+ * Updated type for `ReactionSpec.equals` to include already-supported string shorthands.
37
+
3
38
  ## 59.3.2 - 2023-11-21
4
39
 
5
40
  ### 🐞 Bug Fixes
6
41
 
7
- * `ZoneGrid` will more gracefully handle state that has become out of sync with its mapper requirements.
42
+ * `ZoneGrid` will more gracefully handle state that has become out of sync with its mapper
43
+ requirements.
8
44
 
9
45
  ## 59.3.1 - 2023-11-10
10
46
 
@@ -55,9 +91,9 @@
55
91
  * Improved core `HoistComponent` performance by preventing unnecessary re-renderings triggered by
56
92
  spurious model lookup changes.
57
93
  * New flag `GridModel.experimental.enableFullWidthScroll` enables scrollbars to span pinned columns.
58
- * Early test release behind the flag, expected to made the default behavior in next release.
94
+ * Early test release behind the flag, expected to made the default behavior in next release.
59
95
  * Renamed `XH.getActiveModels()` to `XH.getModels()` for clarity / consistency.
60
- * API change, but not expected to impact applications.
96
+ * API change, but not expected to impact applications.
61
97
  * Added `XH.getModel()` convenience method to return the first matching model.
62
98
 
63
99
  ## 59.2.0 - 2023-10-16
@@ -6,18 +6,16 @@
6
6
  */
7
7
 
8
8
  import {GridModel} from '@xh/hoist/cmp/grid';
9
+ import {div, hbox, p} from '@xh/hoist/cmp/layout';
9
10
  import {HoistModel, LoadSpec, managed, XH} from '@xh/hoist/core';
11
+ import {RecordActionSpec} from '@xh/hoist/data';
10
12
  import {actionCol} from '@xh/hoist/desktop/cmp/grid';
11
- import {div, p} from '@xh/hoist/cmp/layout';
12
13
  import {Icon} from '@xh/hoist/icon';
13
- import {bindable, makeObservable, observable, action} from '@xh/hoist/mobx';
14
+ import {action, bindable, makeObservable, observable} from '@xh/hoist/mobx';
14
15
  import {pluralize} from '@xh/hoist/utils/js';
15
- import {hbox} from '@xh/hoist/cmp/layout';
16
- import {cloneDeep, isEqual, isString, isNil, omit, remove, trimEnd} from 'lodash';
16
+ import {cloneDeep, isEqual, isNil, isString, omit, remove, trimEnd} from 'lodash';
17
17
  import {hspacer} from '../../cmp/layout';
18
-
19
18
  import {DifferDetailModel} from './DifferDetailModel';
20
- import {RecordActionSpec} from '@xh/hoist/data';
21
19
 
22
20
  /**
23
21
  * @internal
@@ -378,7 +376,7 @@ export class DifferModel extends HoistModel {
378
376
  content = await window.navigator.clipboard.readText();
379
377
  content = JSON.parse(content);
380
378
  } catch (e) {
381
- console.warn('Error reading config from clipboard', e);
379
+ this.logWarn('Error reading config from clipboard', e);
382
380
  }
383
381
 
384
382
  this.clipboardContent = content;
@@ -114,8 +114,8 @@ export class AppContainerModel extends HoistModel {
114
114
  }
115
115
 
116
116
  /**
117
- * Called when application container first mounted in order to trigger initial
118
- * authentication and initialization of framework and application.
117
+ * Called when {@link AppContainer} first mounted.
118
+ * Triggers initial authentication and initialization of Hoist and application.
119
119
  */
120
120
  async initAsync() {
121
121
  // Avoid multiple calls, which can occur if AppContainer remounted.
@@ -196,14 +196,12 @@ export class AppContainerModel extends HoistModel {
196
196
  numbro['BigNumber'].clone();
197
197
  }
198
198
 
199
- // Confirm hoist-core version after environment service loaded
200
- const hcVersion = XH.environmentService.get('hoistCoreVersion');
201
- if (!checkMinVersion(hcVersion, MIN_HOIST_CORE_VERSION)) {
202
- throw XH.exception(`
203
- This version of Hoist React requires the server to run Hoist Core
204
- v${MIN_HOIST_CORE_VERSION} or greater. Version ${hcVersion} detected.
205
- `);
206
- }
199
+ // Confirm hoist-core version after environment service loaded.
200
+ const hcVersion = XH.getEnv('hoistCoreVersion');
201
+ throwIf(
202
+ !checkMinVersion(hcVersion, MIN_HOIST_CORE_VERSION),
203
+ `This version of Hoist React requires the server to run Hoist Core ≥ v${MIN_HOIST_CORE_VERSION}. Version ${hcVersion} detected.`
204
+ );
207
205
 
208
206
  await installServicesAsync([
209
207
  AlertBannerService,
@@ -7,7 +7,7 @@
7
7
  import {AppState, AppSuspendData, HoistModel, XH} from '@xh/hoist/core';
8
8
  import {action, makeObservable, observable, reaction} from '@xh/hoist/mobx';
9
9
  import {Timer} from '@xh/hoist/utils/async';
10
- import {getClientDeviceInfo, logDebug} from '@xh/hoist/utils/js';
10
+ import {getClientDeviceInfo} from '@xh/hoist/utils/js';
11
11
  import {isBoolean, isString} from 'lodash';
12
12
 
13
13
  /**
@@ -34,7 +34,7 @@ export class AppStateModel extends HoistModel {
34
34
  @action
35
35
  setAppState(nextState: AppState) {
36
36
  if (this.state !== nextState) {
37
- logDebug(`AppState change: ${this.state} → ${nextState}`, this);
37
+ this.logDebug(`AppState change`, `${this.state} → ${nextState}`);
38
38
  }
39
39
  this.state = nextState;
40
40
  }
@@ -87,6 +87,7 @@ export class AppStateModel extends HoistModel {
87
87
  appVersion: XH.appVersion,
88
88
  appBuild: XH.appBuild,
89
89
  locationHref: window.location.href,
90
+ wasDiscarded: window.document['wasDiscarded'],
90
91
  ...getClientDeviceInfo()
91
92
  },
92
93
  logData: ['appVersion', 'appBuild'],
@@ -6,7 +6,6 @@
6
6
  */
7
7
  import {HoistModel, PageState} from '@xh/hoist/core';
8
8
  import {action, makeObservable, observable} from '@xh/hoist/mobx';
9
- import {logDebug} from '@xh/hoist/utils/js';
10
9
 
11
10
  /**
12
11
  * Implementation of PageState maintenance.
@@ -35,7 +34,7 @@ export class PageStateModel extends HoistModel {
35
34
  private setState(nextState: PageState) {
36
35
  if (this.state == 'terminated' || this.state == nextState) return;
37
36
 
38
- logDebug(`PageState change: ${this.state} → ${nextState}`, this);
37
+ this.logDebug(`PageState change: ${this.state} → ${nextState}`);
39
38
  this.state = nextState;
40
39
  }
41
40
 
@@ -40,7 +40,7 @@ export class SizingModeModel extends HoistModel {
40
40
  platform = this.getPlatform();
41
41
 
42
42
  if (!isPlainObject(pref)) {
43
- console.warn(
43
+ this.logWarn(
44
44
  `Required pref 'xhSizingMode' must be type JSON - update via Admin Console.`
45
45
  );
46
46
  return;
@@ -48,7 +48,7 @@ export class SizingModeModel extends HoistModel {
48
48
 
49
49
  XH.setPref('xhSizingMode', {...pref, [platform]: sizingMode});
50
50
  } else {
51
- console.warn(`Missing required JSON pref 'xhSizingMode' - add via Admin Console.`);
51
+ this.logWarn(`Missing required JSON pref 'xhSizingMode' - add via Admin Console.`);
52
52
  }
53
53
  }
54
54
 
@@ -18,6 +18,7 @@ import {
18
18
  XH
19
19
  } from '@xh/hoist/core';
20
20
  import {AgGridReact, GridOptions} from '@xh/hoist/kit/ag-grid';
21
+ import {logError} from '@xh/hoist/utils/js';
21
22
  import {splitLayoutProps} from '@xh/hoist/utils/react';
22
23
  import classNames from 'classnames';
23
24
  import {isNil} from 'lodash';
@@ -60,9 +61,9 @@ export const [AgGrid, agGrid] = hoistCmp.withFactory<AgGridProps>({
60
61
 
61
62
  render({model, className, testId, ...props}, ref) {
62
63
  if (!AgGridReact) {
63
- console.error(
64
- 'ag-Grid has not been imported in to this application. Please import and ' +
65
- 'register modules in Bootstrap.js. See the XH Toolbox app for an example.'
64
+ logError(
65
+ 'AG Grid not imported/licensed by this app - import and register modules in Bootstrap.ts. See the XH Toolbox app for an example.',
66
+ AgGrid
66
67
  );
67
68
  return placeholder('ag-Grid library not available.');
68
69
  }
@@ -5,6 +5,7 @@
5
5
  * Copyright © 2023 Extremely Heavy Industries Inc.
6
6
  */
7
7
  import {HoistModel, PlainObject, SizingMode, Some} from '@xh/hoist/core';
8
+ import type {ColumnApi, GridApi, IRowNode, SortDirection} from '@xh/hoist/kit/ag-grid';
8
9
  import {action, bindable, computed, makeObservable, observable} from '@xh/hoist/mobx';
9
10
  import {throwIf} from '@xh/hoist/utils/js';
10
11
  import {
@@ -18,13 +19,11 @@ import {
18
19
  isEqual,
19
20
  isNil,
20
21
  partition,
21
- set,
22
+ setWith,
22
23
  startCase
23
24
  } from 'lodash';
24
25
  import {GridSorter, GridSorterLike} from '../grid/GridSorter';
25
26
 
26
- import type {ColumnApi, GridApi, SortDirection} from '@xh/hoist/kit/ag-grid';
27
-
28
27
  export interface AgGridModelConfig {
29
28
  sizingMode?: SizingMode;
30
29
 
@@ -177,7 +176,7 @@ export class AgGridModel extends HoistModel {
177
176
  try {
178
177
  return this[`get${startCase(type)}State`]();
179
178
  } catch (err) {
180
- console.warn(`Encountered errors retrieving ${type} state:`, err);
179
+ this.logWarn(`Encountered errors retrieving ${type} state`, err);
181
180
  errors[type] = err.toString();
182
181
  }
183
182
  };
@@ -358,7 +357,7 @@ export class AgGridModel extends HoistModel {
358
357
  col.setSort(state.sort);
359
358
  col.setSortIndex(state.sortIndex);
360
359
  } else {
361
- console.warn(
360
+ this.logWarn(
362
361
  'Could not find a secondary column to associate with the pivot column path',
363
362
  state.colId
364
363
  );
@@ -467,8 +466,12 @@ export class AgGridModel extends HoistModel {
467
466
  this._prevSortBy = sortBy;
468
467
  }
469
468
 
470
- /** @returns the current row expansion state of the grid in a serializable form. */
471
- getExpandState(): any {
469
+ /**
470
+ * @returns the current row expansion state of the grid in a serializable form.
471
+ * Returned object has keys for StoreRecordIds of top-level, expanded records and values
472
+ * of either `true` or an object with keys of StoreRecordIds of expanded child records.
473
+ */
474
+ getExpandState(): PlainObject {
472
475
  this.throwIfNotReady();
473
476
 
474
477
  const expandState = {};
@@ -487,8 +490,10 @@ export class AgGridModel extends HoistModel {
487
490
  return;
488
491
  }
489
492
 
493
+ // Note use of setWith + customizer - required to ensure that nested nodes are
494
+ // serialized as objects - see https://github.com/xh/hoist-react/issues/3550.
490
495
  const path = this.getGroupNodePath(node);
491
- set(expandState, path, true);
496
+ setWith(expandState, path, true, () => ({}));
492
497
  }
493
498
  });
494
499
 
@@ -499,7 +504,7 @@ export class AgGridModel extends HoistModel {
499
504
  * Sets the grid row expansion state
500
505
  * @param expandState - grid expand state retrieved via getExpandState()
501
506
  */
502
- setExpandState(expandState: any) {
507
+ setExpandState(expandState: PlainObject) {
503
508
  this.throwIfNotReady();
504
509
 
505
510
  const {agApi} = this;
@@ -554,7 +559,7 @@ export class AgGridModel extends HoistModel {
554
559
  * @returns the first row in the grid, after sorting and filtering, which
555
560
  * has data associated with it (i.e. not a group or other synthetic row).
556
561
  */
557
- getFirstSelectableRowNode(): PlainObject {
562
+ getFirstSelectableRowNode(): IRowNode {
558
563
  this.throwIfNotReady();
559
564
 
560
565
  let ret = null;
@@ -595,7 +600,7 @@ export class AgGridModel extends HoistModel {
595
600
  /**
596
601
  * @returns row data pinned to the bottom of the grid
597
602
  */
598
- getPinnedBottomRowData() {
603
+ getPinnedBottomRowData(): PlainObject[] {
599
604
  this.throwIfNotReady();
600
605
  return this.getPinnedRowData('Bottom');
601
606
  }
@@ -605,7 +610,7 @@ export class AgGridModel extends HoistModel {
605
610
  //------------------------
606
611
  @action
607
612
  handleGridReady({api, columnApi}) {
608
- console.debug(`AgGridModel ${this.xhId} initializing`);
613
+ this.logDebug(`Initializing`, this.xhId);
609
614
  throwIf(
610
615
  this.agApi && this.agApi != api,
611
616
  'Attempted to mount a grid on a GridModel that is already in use. ' +
@@ -617,12 +622,12 @@ export class AgGridModel extends HoistModel {
617
622
 
618
623
  @action
619
624
  handleGridUnmount() {
620
- console.debug(`AgGridModel ${this.xhId} un-initializing`);
625
+ this.logDebug(`Un-initializing`, this.xhId);
621
626
  this.agApi = null;
622
627
  this.agColumnApi = null;
623
628
  }
624
629
 
625
- private getPinnedRowData(side) {
630
+ private getPinnedRowData(side: string): PlainObject[] {
626
631
  const {agApi} = this,
627
632
  count = agApi[`getPinned${side}RowCount`](),
628
633
  ret = [];
@@ -22,6 +22,7 @@ import {useContextMenu} from '@xh/hoist/dynamics/desktop';
22
22
  import {Icon} from '@xh/hoist/icon';
23
23
  import {Highcharts} from '@xh/hoist/kit/highcharts';
24
24
  import {runInAction} from '@xh/hoist/mobx';
25
+ import {logError} from '@xh/hoist/utils/js';
25
26
  import {
26
27
  createObservableRef,
27
28
  getLayoutProps,
@@ -61,9 +62,9 @@ export const [Chart, chart] = hoistCmp.withFactory<ChartProps>({
61
62
 
62
63
  render({model, className, aspectRatio, testId, ...props}, ref) {
63
64
  if (!Highcharts) {
64
- console.error(
65
- 'Highcharts has not been imported in to this application. Please import and ' +
66
- 'register in Bootstrap.js. See the XH Toolbox app for an example.'
65
+ logError(
66
+ 'Highcharts not imported by this app - import and register modules in Bootstrap.ts. See the XH Toolbox app for an example.',
67
+ Chart
67
68
  );
68
69
  return placeholder('Highcharts library not available.');
69
70
  }
@@ -4,7 +4,7 @@
4
4
  *
5
5
  * Copyright © 2023 Extremely Heavy Industries Inc.
6
6
  */
7
- import {RowClickedEvent, RowDoubleClickedEvent} from '@ag-grid-community/core';
7
+ import {RowClickedEvent, RowDoubleClickedEvent, RowHeightParams} from '@ag-grid-community/core';
8
8
  import {
9
9
  ColumnRenderer,
10
10
  ColumnSpec,
@@ -127,7 +127,7 @@ export interface DataViewConfig {
127
127
  export type ItemHeightFn = (params: {
128
128
  record: StoreRecord;
129
129
  dataViewModel: DataViewModel;
130
- agParams: PlainObject;
130
+ agParams: RowHeightParams;
131
131
  }) => number;
132
132
 
133
133
  /**
@@ -199,7 +199,7 @@ export class FilterChooserModel extends HoistModel {
199
199
  run: state => this.provider.write(state)
200
200
  });
201
201
  } catch (e) {
202
- console.error(e);
202
+ this.logError(e);
203
203
  XH.safeDestroy(this.provider);
204
204
  this.provider = null;
205
205
  }
@@ -251,7 +251,7 @@ export class FilterChooserModel extends HoistModel {
251
251
  }
252
252
 
253
253
  // 2) Main path - set internal value.
254
- console.debug('Setting FilterChooser value:', value);
254
+ this.logDebug('Setting value', value);
255
255
  this.value = value;
256
256
 
257
257
  // 3) Set props on select input needed to display
@@ -292,7 +292,7 @@ export class FilterChooserModel extends HoistModel {
292
292
  })
293
293
  .linkTo(this.filterTask);
294
294
  } catch (e) {
295
- console.error('Failed to set value on FilterChooserModel', e);
295
+ this.logError('Failed to set value', e);
296
296
  this.value = null;
297
297
  this.selectOptions = null;
298
298
  this.selectValue = null;
@@ -490,7 +490,7 @@ export class FilterChooserModel extends HoistModel {
490
490
  if (f === null) return true;
491
491
  if (f instanceof FieldFilter) {
492
492
  if (!this.getFieldSpec(f.field)) {
493
- console.error(`Invalid Filter for FilterChooser: ${f.field}`);
493
+ this.logError(`Invalid FieldFilter - no fieldSpec configured for ${f.field}.`);
494
494
  return false;
495
495
  }
496
496
  return true;
@@ -500,7 +500,7 @@ export class FilterChooserModel extends HoistModel {
500
500
  return f.filters.every(it => this.validateFilter(it));
501
501
  }
502
502
 
503
- console.error('Invalid filter for FilterChooser', f);
503
+ this.logError('Invalid Filter - unhandled type', f);
504
504
  return false;
505
505
  }
506
506
 
package/cmp/grid/Grid.ts CHANGED
@@ -41,7 +41,7 @@ import type {
41
41
  } from '@xh/hoist/kit/ag-grid';
42
42
  import {computed, observer} from '@xh/hoist/mobx';
43
43
  import {wait} from '@xh/hoist/promise';
44
- import {consumeEvent, isDisplayed, logDebug, logWithDebug} from '@xh/hoist/utils/js';
44
+ import {consumeEvent, isDisplayed, logWithDebug} from '@xh/hoist/utils/js';
45
45
  import {createObservableRef, getLayoutProps} from '@xh/hoist/utils/react';
46
46
  import classNames from 'classnames';
47
47
  import {debounce, isEmpty, isEqual, isNil, max, maxBy, merge} from 'lodash';
@@ -634,9 +634,8 @@ export class GridLocalModel extends HoistModel {
634
634
  let transaction = null;
635
635
  if (prevCount !== 0) {
636
636
  transaction = this.genTransaction(newRs, prevRs);
637
- logDebug(this.transactionLogStr(transaction), this);
638
-
639
637
  if (!this.transactionIsEmpty(transaction)) {
638
+ this.logDebug(...this.genTxnLogMsgs(transaction));
640
639
  agApi.applyTransaction(transaction);
641
640
  }
642
641
  } else {
@@ -698,10 +697,13 @@ export class GridLocalModel extends HoistModel {
698
697
  return isEmpty(t.update) && isEmpty(t.add) && isEmpty(t.remove);
699
698
  }
700
699
 
701
- transactionLogStr(t) {
702
- return `[update: ${t.update ? t.update.length : 0} | add: ${
703
- t.add ? t.add.length : 0
704
- } | remove: ${t.remove ? t.remove.length : 0}]`;
700
+ private genTxnLogMsgs(t): string[] {
701
+ const {add, update, remove} = t;
702
+ return [
703
+ `update: ${update ? update.length : 0}`,
704
+ `add: ${add ? add.length : 0}`,
705
+ `remove: ${remove ? remove.length : 0}`
706
+ ];
705
707
  }
706
708
 
707
709
  //------------------------
@@ -4,9 +4,9 @@
4
4
  *
5
5
  * Copyright © 2023 Extremely Heavy Industries Inc.
6
6
  */
7
- import {PlainObject} from '@xh/hoist/core';
8
7
  import {GridModel} from '@xh/hoist/cmp/grid';
9
8
  import {RecordActionLike} from '@xh/hoist/data';
9
+ import {GetContextMenuItemsParams} from '@xh/hoist/kit/ag-grid';
10
10
 
11
11
  /**
12
12
  * If a String, value can be '-' for a separator, or a token supported by ag-Grid
@@ -46,4 +46,4 @@ export type GridContextMenuToken =
46
46
  */
47
47
  export type GridContextMenuSpec =
48
48
  | GridContextMenuItemLike[]
49
- | ((agParams: PlainObject, gridModel: GridModel) => GridContextMenuItemLike[]);
49
+ | ((agParams: GetContextMenuItemsParams, gridModel: GridModel) => GridContextMenuItemLike[]);
@@ -56,14 +56,7 @@ import {action, bindable, makeObservable, observable, when} from '@xh/hoist/mobx
56
56
  import {wait, waitFor} from '@xh/hoist/promise';
57
57
  import {ExportOptions} from '@xh/hoist/svc/GridExportService';
58
58
  import {SECONDS} from '@xh/hoist/utils/datetime';
59
- import {
60
- deepFreeze,
61
- logWithDebug,
62
- throwIf,
63
- warnIf,
64
- withDebug,
65
- withDefault
66
- } from '@xh/hoist/utils/js';
59
+ import {deepFreeze, logWithDebug, throwIf, warnIf, withDefault} from '@xh/hoist/utils/js';
67
60
  import equal from 'fast-deep-equal';
68
61
  import {
69
62
  castArray,
@@ -818,7 +811,7 @@ export class GridModel extends HoistModel {
818
811
 
819
812
  const indexCount = indices.length;
820
813
  if (indexCount !== records.length) {
821
- console.warn('Grid row nodes not found for all provided records.');
814
+ this.logWarn('Grid row nodes not found for all provided records.');
822
815
  }
823
816
 
824
817
  if (indexCount === 1) {
@@ -978,7 +971,7 @@ export class GridModel extends HoistModel {
978
971
 
979
972
  const invalidColIds = colIds.filter(it => !this.findColumn(this.columns, it));
980
973
  if (invalidColIds.length) {
981
- console.warn(
974
+ this.logWarn(
982
975
  'Unknown colId specified in groupBy - grid will not be grouped.',
983
976
  invalidColIds
984
977
  );
@@ -1025,7 +1018,7 @@ export class GridModel extends HoistModel {
1025
1018
  it => !it.colId?.startsWith('ag-Grid') && !this.findColumn(this.columns, it.colId)
1026
1019
  );
1027
1020
  if (invalidSorters.length) {
1028
- console.warn('GridSorter colId not found in grid columns', invalidSorters);
1021
+ this.logWarn('GridSorter colId not found in grid columns', invalidSorters);
1029
1022
  return;
1030
1023
  }
1031
1024
 
@@ -1360,10 +1353,9 @@ export class GridModel extends HoistModel {
1360
1353
 
1361
1354
  const rowIndex = agApi.getRowNode(recToEdit?.agId)?.rowIndex;
1362
1355
  if (isNil(rowIndex) || rowIndex < 0) {
1363
- console.warn(
1364
- 'Unable to start editing - ' + record
1365
- ? 'specified record not found'
1366
- : 'no records found'
1356
+ this.logWarn(
1357
+ 'Unable to start editing',
1358
+ record ? 'specified record not found' : 'no records found'
1367
1359
  );
1368
1360
  return;
1369
1361
  }
@@ -1381,11 +1373,11 @@ export class GridModel extends HoistModel {
1381
1373
  }
1382
1374
 
1383
1375
  if (!colToEdit) {
1384
- console.warn(
1385
- 'Unable to start editing - ' +
1386
- (colId
1387
- ? `column with colId ${colId} not found, or not editable`
1388
- : 'no editable columns found')
1376
+ this.logWarn(
1377
+ 'Unable to start editing',
1378
+ colId
1379
+ ? `column with colId ${colId} not found, or not editable`
1380
+ : 'no editable columns found'
1389
1381
  );
1390
1382
  return;
1391
1383
  }
@@ -1438,7 +1430,7 @@ export class GridModel extends HoistModel {
1438
1430
  try {
1439
1431
  await when(() => this.isReady, {timeout});
1440
1432
  } catch (ignored) {
1441
- withDebug(`Grid failed to enter ready state after waiting ${timeout}ms`, null, this);
1433
+ this.logDebug(`Grid failed to enter ready state after waiting ${timeout}ms`);
1442
1434
  }
1443
1435
  await wait();
1444
1436
 
package/cmp/grid/Types.ts CHANGED
@@ -5,8 +5,9 @@
5
5
  * Copyright © 2023 Extremely Heavy Industries Inc.
6
6
  */
7
7
 
8
+ import {IRowNode} from '@xh/hoist/kit/ag-grid';
8
9
  import {GridFilterFieldSpecConfig} from '@xh/hoist/cmp/grid/filter/GridFilterFieldSpec';
9
- import {HSide, PersistOptions, PlainObject, SizingMode, Some} from '@xh/hoist/core';
10
+ import {HSide, PersistOptions, SizingMode, Some} from '@xh/hoist/core';
10
11
  import {Store, StoreRecord, View} from '@xh/hoist/data';
11
12
  import {ReactElement, ReactNode} from 'react';
12
13
  import {Column} from './columns/Column';
@@ -54,8 +55,8 @@ export type GridGroupSortFn = (
54
55
  groupField: string,
55
56
  metadata: {
56
57
  gridModel: GridModel;
57
- nodeA: PlainObject;
58
- nodeB: PlainObject;
58
+ nodeA: IRowNode;
59
+ nodeB: IRowNode;
59
60
  }
60
61
  ) => number;
61
62
 
@@ -167,8 +168,8 @@ export type ColumnComparator<T = any> = (
167
168
  params: {
168
169
  recordA: StoreRecord;
169
170
  recordB: StoreRecord;
170
- agNodeA: PlainObject;
171
- agNodeB: PlainObject;
171
+ agNodeA: IRowNode;
172
+ agNodeB: IRowNode;
172
173
  column: Column;
173
174
  gridModel: GridModel;
174
175
  defaultComparator: (a: T, b: T) => number;
@@ -14,7 +14,7 @@ import {
14
14
  RecordActionSpec,
15
15
  StoreRecord
16
16
  } from '@xh/hoist/data';
17
- import {apiRemoved, throwIf, warnIf, withDefault} from '@xh/hoist/utils/js';
17
+ import {apiRemoved, logDebug, logWarn, throwIf, warnIf, withDefault} from '@xh/hoist/utils/js';
18
18
  import classNames from 'classnames';
19
19
  import {
20
20
  castArray,
@@ -932,12 +932,12 @@ export class Column {
932
932
  sortCfg = find(gridModel.sortBy, {colId}),
933
933
  sortDir = sortCfg?.sort || 'asc',
934
934
  abs = sortCfg?.abs || false,
935
- recordA = agNodeA?.data,
936
- recordB = agNodeB?.data,
935
+ recordA = agNodeA?.data as StoreRecord,
936
+ recordB = agNodeB?.data as StoreRecord,
937
937
  params = {
938
938
  recordA,
939
939
  recordB,
940
- column: this,
940
+ column: this as Column,
941
941
  gridModel,
942
942
  defaultComparator: this.defaultComparator,
943
943
  agNodeA,
@@ -962,7 +962,7 @@ export class Column {
962
962
  if (editor) {
963
963
  ret.cellEditor = forwardRef((agParams: PlainObject, ref) => {
964
964
  const props = {
965
- record: agParams.data,
965
+ record: agParams.data as StoreRecord,
966
966
  gridModel,
967
967
  column: this,
968
968
  agParams,
@@ -1056,23 +1056,23 @@ export class Column {
1056
1056
 
1057
1057
  private parseFilterable(filterable) {
1058
1058
  if (!filterable) return false;
1059
+ const {colId} = this;
1059
1060
 
1060
1061
  if (XH.isMobileApp) {
1061
- console.warn(`'filterable' is not supported on mobile and will be ignored.`);
1062
+ logDebug(
1063
+ `Column ${colId} specs 'filterable' but not supported on mobile - will be ignored.`,
1064
+ this
1065
+ );
1062
1066
  return false;
1063
1067
  }
1064
1068
 
1065
1069
  if (!this.field) {
1066
- console.warn(
1067
- `Column '${this.colId}' is not a Store field. 'filterable' will be ignored.`
1068
- );
1070
+ logWarn(`Column ${colId} is not a Store field. 'filterable' will be ignored.`, this);
1069
1071
  return false;
1070
1072
  }
1071
1073
 
1072
1074
  if (this.field === 'cubeLabel') {
1073
- console.warn(
1074
- `Column '${this.colId}' is a cube label column. 'filterable' will be ignored.`
1075
- );
1075
+ logWarn(`Column ${colId} is a cube label column. 'filterable' will be ignored.`, this);
1076
1076
  return false;
1077
1077
  }
1078
1078