@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.
- package/CHANGELOG.md +39 -3
- package/admin/differ/DifferModel.ts +5 -7
- package/appcontainer/AppContainerModel.ts +8 -10
- package/appcontainer/AppStateModel.ts +3 -2
- package/appcontainer/PageStateModel.ts +1 -2
- package/appcontainer/SizingModeModel.ts +2 -2
- package/cmp/ag-grid/AgGrid.ts +4 -3
- package/cmp/ag-grid/AgGridModel.ts +19 -14
- package/cmp/chart/Chart.ts +4 -3
- package/cmp/dataview/DataViewModel.ts +2 -2
- package/cmp/filter/FilterChooserModel.ts +5 -5
- package/cmp/grid/Grid.ts +9 -7
- package/cmp/grid/GridContextMenu.ts +2 -2
- package/cmp/grid/GridModel.ts +13 -21
- package/cmp/grid/Types.ts +6 -5
- package/cmp/grid/columns/Column.ts +12 -12
- package/cmp/grid/columns/ColumnGroup.ts +17 -6
- package/cmp/grid/helpers/GridCountLabel.ts +5 -4
- package/cmp/grid/impl/ColumnWidthCalculator.ts +3 -3
- package/cmp/grid/impl/GridPersistenceModel.ts +11 -4
- package/cmp/grid/impl/Utils.ts +1 -1
- package/cmp/grid/renderers/MultiFieldRenderer.ts +28 -22
- package/cmp/grouping/GroupingChooserModel.ts +2 -2
- package/cmp/relativetimestamp/RelativeTimestamp.ts +5 -2
- package/cmp/tab/TabContainerModel.ts +2 -2
- package/cmp/zoneGrid/ZoneGridModel.ts +1 -1
- package/cmp/zoneGrid/impl/ZoneGridPersistenceModel.ts +10 -4
- package/core/HoistBase.ts +48 -8
- package/core/HoistBaseDecorators.ts +11 -6
- package/core/HoistComponent.ts +1 -3
- package/core/elem.ts +2 -2
- package/core/exception/ExceptionHandler.ts +4 -4
- package/core/impl/InstallServices.ts +2 -8
- package/core/load/LoadSupport.ts +10 -11
- package/core/model/HoistModel.ts +1 -1
- package/data/Store.ts +1 -1
- package/data/UrlStore.ts +3 -3
- package/data/cube/aggregate/UniqueAggregator.ts +3 -5
- package/data/filter/CompoundFilter.ts +5 -3
- package/data/filter/FieldFilter.ts +4 -3
- package/data/filter/Filter.ts +2 -3
- package/data/filter/FunctionFilter.ts +2 -1
- package/data/impl/RecordSet.ts +5 -5
- package/desktop/appcontainer/ToastSource.ts +1 -1
- package/desktop/cmp/button/ColChooserButton.ts +7 -5
- package/desktop/cmp/button/ZoneMapperButton.ts +7 -5
- package/desktop/cmp/dash/canvas/DashCanvasModel.ts +2 -2
- package/desktop/cmp/dash/container/DashContainerModel.ts +2 -2
- package/desktop/cmp/dock/DockViewModel.ts +21 -11
- package/desktop/cmp/dock/impl/DockView.ts +4 -2
- package/desktop/cmp/form/FormField.ts +2 -2
- package/desktop/cmp/grid/editors/BooleanEditor.ts +5 -1
- package/desktop/cmp/input/DateInput.ts +1 -3
- package/desktop/cmp/panel/Panel.ts +4 -2
- package/desktop/cmp/panel/PanelModel.ts +5 -5
- package/desktop/cmp/rest/Actions.ts +15 -9
- package/desktop/cmp/treemap/TreeMap.ts +7 -10
- package/inspector/instances/InstancesModel.ts +6 -6
- package/mobile/cmp/button/ColAutosizeButton.ts +4 -3
- package/mobile/cmp/button/ColChooserButton.ts +4 -3
- package/mobile/cmp/button/ExpandCollapseButton.ts +4 -3
- package/mobile/cmp/button/ZoneMapperButton.ts +4 -3
- package/mobile/cmp/input/DateInput.ts +1 -1
- package/mobile/cmp/input/Select.ts +3 -3
- package/mobile/cmp/panel/Panel.ts +4 -2
- package/package.json +2 -2
- package/svc/AutoRefreshService.ts +3 -3
- package/svc/ChangelogService.ts +3 -3
- package/svc/EnvironmentService.ts +1 -1
- package/svc/FetchService.ts +5 -5
- package/svc/GridAutosizeService.ts +4 -7
- package/svc/GridExportService.ts +3 -8
- package/svc/IdentityService.ts +1 -1
- package/svc/TrackService.ts +9 -15
- package/svc/WebSocketService.ts +14 -15
- package/utils/async/AsyncUtils.ts +3 -2
- package/utils/async/Timer.ts +5 -4
- package/utils/datetime/LocalDate.ts +13 -13
- package/utils/js/BrowserUtils.ts +8 -8
- package/utils/js/Decorators.ts +18 -3
- package/utils/js/LangUtils.ts +10 -9
- package/utils/js/LogUtils.ts +66 -26
- 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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
14
|
+
import {action, bindable, makeObservable, observable} from '@xh/hoist/mobx';
|
|
14
15
|
import {pluralize} from '@xh/hoist/utils/js';
|
|
15
|
-
import {
|
|
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
|
-
|
|
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
|
|
118
|
-
* authentication and initialization of
|
|
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.
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
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
|
|
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
|
|
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}
|
|
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
|
-
|
|
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
|
-
|
|
51
|
+
this.logWarn(`Missing required JSON pref 'xhSizingMode' - add via Admin Console.`);
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
|
package/cmp/ag-grid/AgGrid.ts
CHANGED
|
@@ -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
|
-
|
|
64
|
-
'
|
|
65
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
/**
|
|
471
|
-
|
|
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
|
-
|
|
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:
|
|
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():
|
|
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
|
-
|
|
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
|
-
|
|
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 = [];
|
package/cmp/chart/Chart.ts
CHANGED
|
@@ -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
|
-
|
|
65
|
-
'Highcharts
|
|
66
|
-
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
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:
|
|
49
|
+
| ((agParams: GetContextMenuItemsParams, gridModel: GridModel) => GridContextMenuItemLike[]);
|
package/cmp/grid/GridModel.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1364
|
-
'Unable to start editing
|
|
1365
|
-
|
|
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
|
-
|
|
1385
|
-
'Unable to start editing
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
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
|
-
|
|
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,
|
|
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:
|
|
58
|
-
nodeB:
|
|
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:
|
|
171
|
-
agNodeB:
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|