@xh/hoist 74.1.0 → 74.1.1
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 +14 -0
- package/build/types/cmp/grouping/GroupingChooserModel.d.ts +1 -0
- package/build/types/core/types/Interfaces.d.ts +1 -1
- package/build/types/desktop/cmp/grouping/GroupingChooser.d.ts +14 -3
- package/build/types/desktop/cmp/panel/Panel.d.ts +1 -1
- package/cmp/grouping/GroupingChooserModel.ts +5 -0
- package/core/exception/ExceptionHandler.ts +1 -1
- package/core/types/Interfaces.ts +2 -2
- package/desktop/cmp/grouping/GroupingChooser.scss +25 -10
- package/desktop/cmp/grouping/GroupingChooser.ts +123 -45
- package/desktop/cmp/panel/Panel.ts +1 -1
- package/package.json +1 -1
- package/svc/TrackService.ts +4 -3
- package/tsconfig.tsbuildinfo +1 -1
- package/utils/js/LangUtils.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v74.1.1 - 2025-07-02
|
|
4
|
+
|
|
5
|
+
### 🎁 New Features
|
|
6
|
+
|
|
7
|
+
* Further refinements to the `GroupingChooser` desktop UI.
|
|
8
|
+
* Added new props `favoritesSide` and `favoritesTitle`.
|
|
9
|
+
* Deprecated `popoverTitle` prop - use `editorTitle` instead.
|
|
10
|
+
* Moved "Save as Favorite" button to a new compact toolbar within the popover.
|
|
11
|
+
|
|
12
|
+
### 🐞 Bug Fixes
|
|
13
|
+
|
|
14
|
+
* Fixed a bug where `TrackService` was not properly verifying that tracked `data` was below the
|
|
15
|
+
configured `maxDataLength` limit.
|
|
16
|
+
|
|
3
17
|
## v74.1.0 - 2025-06-30
|
|
4
18
|
|
|
5
19
|
### 🎁 New Features
|
|
@@ -177,7 +177,7 @@ export interface TrackOptions {
|
|
|
177
177
|
/** Correlation ID to save along with track log. */
|
|
178
178
|
correlationId?: string;
|
|
179
179
|
/** App-supplied data to save along with track log.*/
|
|
180
|
-
data?: PlainObject |
|
|
180
|
+
data?: PlainObject | Array<unknown>;
|
|
181
181
|
/**
|
|
182
182
|
* Set true to log on the server all primitive values in the 'data' property.
|
|
183
183
|
* May also be specified as list of specific property keys that should be logged.
|
|
@@ -1,19 +1,30 @@
|
|
|
1
1
|
import { GroupingChooserModel } from '@xh/hoist/cmp/grouping';
|
|
2
|
+
import { Side } from '@xh/hoist/core';
|
|
2
3
|
import { ButtonProps } from '@xh/hoist/desktop/cmp/button';
|
|
3
4
|
import '@xh/hoist/desktop/register';
|
|
4
5
|
import './GroupingChooser.scss';
|
|
6
|
+
import { ReactNode } from 'react';
|
|
5
7
|
export interface GroupingChooserProps extends ButtonProps<GroupingChooserModel> {
|
|
8
|
+
/** Title for value-editing portion of popover, or null to suppress. */
|
|
9
|
+
editorTitle?: ReactNode;
|
|
6
10
|
/** Text to represent empty state (i.e. value = null or []) */
|
|
7
11
|
emptyText?: string;
|
|
12
|
+
/**
|
|
13
|
+
* Side of the popover, relative to the value-editing controls, on which the Favorites list
|
|
14
|
+
* should be rendered, if enabled.
|
|
15
|
+
*/
|
|
16
|
+
favoritesSide?: Side;
|
|
17
|
+
/** Title for favorites-list portion of popover, or null to suppress. */
|
|
18
|
+
favoritesTitle?: ReactNode;
|
|
8
19
|
/** Min height in pixels of the popover menu itself. */
|
|
9
20
|
popoverMinHeight?: number;
|
|
10
21
|
/** Position of popover relative to target button. */
|
|
11
22
|
popoverPosition?: 'bottom' | 'top';
|
|
12
|
-
/**
|
|
13
|
-
popoverTitle?:
|
|
23
|
+
/** @deprecated - use `editorTitle` instead */
|
|
24
|
+
popoverTitle?: ReactNode;
|
|
14
25
|
/**
|
|
15
26
|
* Width in pixels of the popover menu itself.
|
|
16
|
-
* If unspecified, will default based on
|
|
27
|
+
* If unspecified, will default based on favorites enabled status + side.
|
|
17
28
|
*/
|
|
18
29
|
popoverWidth?: number;
|
|
19
30
|
/** True (default) to style target button as an input field - blends better in toolbars. */
|
|
@@ -44,7 +44,7 @@ export interface PanelProps extends HoistProps<PanelModel>, Omit<BoxProps, 'titl
|
|
|
44
44
|
*/
|
|
45
45
|
tbar?: Some<ReactNode>;
|
|
46
46
|
/**
|
|
47
|
-
* A toolbar to be docked at the
|
|
47
|
+
* A toolbar to be docked at the bottom of the panel.
|
|
48
48
|
* If specified as an array, items will be passed as children to a Toolbar component.
|
|
49
49
|
*/
|
|
50
50
|
bbar?: Some<ReactNode>;
|
|
@@ -266,6 +266,11 @@ export class GroupingChooserModel extends HoistModel {
|
|
|
266
266
|
);
|
|
267
267
|
}
|
|
268
268
|
|
|
269
|
+
@computed
|
|
270
|
+
get hasFavorites() {
|
|
271
|
+
return !isEmpty(this.favorites);
|
|
272
|
+
}
|
|
273
|
+
|
|
269
274
|
@action
|
|
270
275
|
setFavorites(favorites: string[][]) {
|
|
271
276
|
this.favorites = favorites.filter(v => this.validateValue(v));
|
|
@@ -202,7 +202,7 @@ export class ExceptionHandler {
|
|
|
202
202
|
XH.track({
|
|
203
203
|
category: 'Client Error',
|
|
204
204
|
severity: exception.isRoutine ? 'INFO' : 'ERROR',
|
|
205
|
-
message: exception.message
|
|
205
|
+
message: exception.message || 'Client Error',
|
|
206
206
|
correlationId: exception.correlationId,
|
|
207
207
|
data,
|
|
208
208
|
logData: ['userAlerted']
|
package/core/types/Interfaces.ts
CHANGED
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import {RuleLike} from '@xh/hoist/data';
|
|
9
|
-
import {MouseEvent, ReactElement, ReactNode, isValidElement} from 'react';
|
|
10
9
|
import {isString} from 'lodash';
|
|
10
|
+
import {isValidElement, MouseEvent, ReactElement, ReactNode} from 'react';
|
|
11
11
|
import {LoadSpec} from '../load';
|
|
12
12
|
import {Intent, PlainObject, Thunkable} from './Types';
|
|
13
13
|
|
|
@@ -224,7 +224,7 @@ export interface TrackOptions {
|
|
|
224
224
|
correlationId?: string;
|
|
225
225
|
|
|
226
226
|
/** App-supplied data to save along with track log.*/
|
|
227
|
-
data?: PlainObject |
|
|
227
|
+
data?: PlainObject | Array<unknown>;
|
|
228
228
|
|
|
229
229
|
/**
|
|
230
230
|
* Set true to log on the server all primitive values in the 'data' property.
|
|
@@ -34,8 +34,14 @@
|
|
|
34
34
|
position: relative;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
&-popover {
|
|
38
|
+
// 60/40 split in favor of favorites in left/right orientation
|
|
39
|
+
&--faves-right,
|
|
40
|
+
&--faves-left {
|
|
41
|
+
.xh-grouping-chooser__editor {
|
|
42
|
+
width: 40%;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
39
45
|
}
|
|
40
46
|
|
|
41
47
|
&__list {
|
|
@@ -121,8 +127,23 @@
|
|
|
121
127
|
}
|
|
122
128
|
|
|
123
129
|
&__favorites {
|
|
124
|
-
|
|
125
|
-
|
|
130
|
+
&--top {
|
|
131
|
+
border-bottom: 1px solid var(--xh-popup-border-color);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
&--right {
|
|
135
|
+
flex: 1;
|
|
136
|
+
border-left: 1px solid var(--xh-popup-border-color);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
&--bottom {
|
|
140
|
+
border-top: 1px solid var(--xh-popup-border-color);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
&--left {
|
|
144
|
+
flex: 1;
|
|
145
|
+
border-right: 1px solid var(--xh-popup-border-color);
|
|
146
|
+
}
|
|
126
147
|
|
|
127
148
|
--xh-menu-border: none;
|
|
128
149
|
|
|
@@ -130,14 +151,8 @@
|
|
|
130
151
|
padding: 0;
|
|
131
152
|
}
|
|
132
153
|
|
|
133
|
-
&__add-btn {
|
|
134
|
-
flex: none;
|
|
135
|
-
margin: var(--xh-pad-px) auto;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
154
|
&__favorite {
|
|
139
155
|
align-items: center;
|
|
140
|
-
max-width: 50vw;
|
|
141
156
|
|
|
142
157
|
.xh-button {
|
|
143
158
|
padding: 0 !important;
|
|
@@ -5,37 +5,61 @@
|
|
|
5
5
|
* Copyright © 2025 Extremely Heavy Industries Inc.
|
|
6
6
|
*/
|
|
7
7
|
import {GroupingChooserModel} from '@xh/hoist/cmp/grouping';
|
|
8
|
-
import {
|
|
9
|
-
|
|
8
|
+
import {
|
|
9
|
+
box,
|
|
10
|
+
div,
|
|
11
|
+
filler,
|
|
12
|
+
fragment,
|
|
13
|
+
hbox,
|
|
14
|
+
hframe,
|
|
15
|
+
placeholder,
|
|
16
|
+
vbox,
|
|
17
|
+
vframe
|
|
18
|
+
} from '@xh/hoist/cmp/layout';
|
|
19
|
+
import {hoistCmp, Side, uses} from '@xh/hoist/core';
|
|
10
20
|
import {button, ButtonProps} from '@xh/hoist/desktop/cmp/button';
|
|
11
21
|
import {select} from '@xh/hoist/desktop/cmp/input';
|
|
12
22
|
import {panel} from '@xh/hoist/desktop/cmp/panel';
|
|
13
23
|
import '@xh/hoist/desktop/register';
|
|
24
|
+
import {toolbar} from '@xh/hoist/desktop/cmp/toolbar';
|
|
14
25
|
import {Icon} from '@xh/hoist/icon';
|
|
15
26
|
import {menu, menuItem, popover} from '@xh/hoist/kit/blueprint';
|
|
16
27
|
import {dragDropContext, draggable, droppable} from '@xh/hoist/kit/react-beautiful-dnd';
|
|
17
|
-
import {elemWithin, getTestId} from '@xh/hoist/utils/js';
|
|
28
|
+
import {apiDeprecated, elemWithin, getTestId} from '@xh/hoist/utils/js';
|
|
18
29
|
import {splitLayoutProps} from '@xh/hoist/utils/react';
|
|
19
30
|
import classNames from 'classnames';
|
|
20
|
-
import {compact, isEmpty, sortBy} from 'lodash';
|
|
31
|
+
import {compact, isEmpty, isNil, isUndefined, sortBy} from 'lodash';
|
|
21
32
|
import './GroupingChooser.scss';
|
|
33
|
+
import {ReactNode} from 'react';
|
|
22
34
|
|
|
23
35
|
export interface GroupingChooserProps extends ButtonProps<GroupingChooserModel> {
|
|
36
|
+
/** Title for value-editing portion of popover, or null to suppress. */
|
|
37
|
+
editorTitle?: ReactNode;
|
|
38
|
+
|
|
24
39
|
/** Text to represent empty state (i.e. value = null or []) */
|
|
25
40
|
emptyText?: string;
|
|
26
41
|
|
|
42
|
+
/**
|
|
43
|
+
* Side of the popover, relative to the value-editing controls, on which the Favorites list
|
|
44
|
+
* should be rendered, if enabled.
|
|
45
|
+
*/
|
|
46
|
+
favoritesSide?: Side;
|
|
47
|
+
|
|
48
|
+
/** Title for favorites-list portion of popover, or null to suppress. */
|
|
49
|
+
favoritesTitle?: ReactNode;
|
|
50
|
+
|
|
27
51
|
/** Min height in pixels of the popover menu itself. */
|
|
28
52
|
popoverMinHeight?: number;
|
|
29
53
|
|
|
30
54
|
/** Position of popover relative to target button. */
|
|
31
55
|
popoverPosition?: 'bottom' | 'top';
|
|
32
56
|
|
|
33
|
-
/**
|
|
34
|
-
popoverTitle?:
|
|
57
|
+
/** @deprecated - use `editorTitle` instead */
|
|
58
|
+
popoverTitle?: ReactNode;
|
|
35
59
|
|
|
36
60
|
/**
|
|
37
61
|
* Width in pixels of the popover menu itself.
|
|
38
|
-
* If unspecified, will default based on
|
|
62
|
+
* If unspecified, will default based on favorites enabled status + side.
|
|
39
63
|
*/
|
|
40
64
|
popoverWidth?: number;
|
|
41
65
|
|
|
@@ -58,10 +82,13 @@ export const [GroupingChooser, groupingChooser] = hoistCmp.withFactory<GroupingC
|
|
|
58
82
|
{
|
|
59
83
|
model,
|
|
60
84
|
className,
|
|
85
|
+
editorTitle = 'Group By',
|
|
61
86
|
emptyText = 'Ungrouped',
|
|
87
|
+
favoritesSide = 'right',
|
|
88
|
+
favoritesTitle = 'Favorites',
|
|
62
89
|
popoverWidth,
|
|
63
90
|
popoverMinHeight,
|
|
64
|
-
popoverTitle
|
|
91
|
+
popoverTitle,
|
|
65
92
|
popoverPosition = 'bottom',
|
|
66
93
|
styleButtonAsInput = true,
|
|
67
94
|
testId,
|
|
@@ -72,9 +99,18 @@ export const [GroupingChooser, groupingChooser] = hoistCmp.withFactory<GroupingC
|
|
|
72
99
|
const {editorIsOpen, value, allowEmpty, persistFavorites} = model,
|
|
73
100
|
isOpen = editorIsOpen,
|
|
74
101
|
label = isEmpty(value) && allowEmpty ? emptyText : model.getValueLabel(value),
|
|
75
|
-
[layoutProps, buttonProps] = splitLayoutProps(rest)
|
|
102
|
+
[layoutProps, buttonProps] = splitLayoutProps(rest),
|
|
103
|
+
favesClassNameMod = `faves-${persistFavorites ? favoritesSide : 'disabled'}`,
|
|
104
|
+
favesTB = isTB(favoritesSide);
|
|
105
|
+
|
|
106
|
+
if (!isUndefined(popoverTitle)) {
|
|
107
|
+
apiDeprecated('GroupingChooser.popoverTitle', {
|
|
108
|
+
msg: `Update to use 'editorTitle' instead`
|
|
109
|
+
});
|
|
110
|
+
editorTitle = popoverTitle;
|
|
111
|
+
}
|
|
76
112
|
|
|
77
|
-
popoverWidth = popoverWidth || (persistFavorites ? 500 : 250);
|
|
113
|
+
popoverWidth = popoverWidth || (persistFavorites && !favesTB ? 500 : 250);
|
|
78
114
|
|
|
79
115
|
return box({
|
|
80
116
|
ref,
|
|
@@ -83,7 +119,7 @@ export const [GroupingChooser, groupingChooser] = hoistCmp.withFactory<GroupingC
|
|
|
83
119
|
item: popover({
|
|
84
120
|
isOpen,
|
|
85
121
|
popoverRef: model.popoverRef,
|
|
86
|
-
popoverClassName:
|
|
122
|
+
popoverClassName: `xh-grouping-chooser-popover xh-grouping-chooser-popover--${favesClassNameMod} xh-popup--framed`,
|
|
87
123
|
// Left align editor to keep in place when button changing size when commitOnChange: true
|
|
88
124
|
position: `${popoverPosition}-left`,
|
|
89
125
|
minimal: false,
|
|
@@ -103,10 +139,12 @@ export const [GroupingChooser, groupingChooser] = hoistCmp.withFactory<GroupingC
|
|
|
103
139
|
})
|
|
104
140
|
),
|
|
105
141
|
content: popoverCmp({
|
|
142
|
+
editorTitle,
|
|
143
|
+
emptyText,
|
|
144
|
+
favoritesSide,
|
|
145
|
+
favoritesTitle,
|
|
106
146
|
popoverWidth,
|
|
107
147
|
popoverMinHeight,
|
|
108
|
-
popoverTitle,
|
|
109
|
-
emptyText,
|
|
110
148
|
testId
|
|
111
149
|
}),
|
|
112
150
|
onInteraction: (nextOpenState, e) => {
|
|
@@ -127,35 +165,62 @@ export const [GroupingChooser, groupingChooser] = hoistCmp.withFactory<GroupingC
|
|
|
127
165
|
//------------------
|
|
128
166
|
// Editor
|
|
129
167
|
//------------------
|
|
130
|
-
const popoverCmp = hoistCmp.factory<
|
|
131
|
-
render({
|
|
168
|
+
const popoverCmp = hoistCmp.factory<Partial<GroupingChooserProps>>({
|
|
169
|
+
render({
|
|
170
|
+
model,
|
|
171
|
+
editorTitle,
|
|
172
|
+
emptyText,
|
|
173
|
+
favoritesSide,
|
|
174
|
+
favoritesTitle,
|
|
175
|
+
popoverWidth,
|
|
176
|
+
popoverMinHeight,
|
|
177
|
+
testId
|
|
178
|
+
}) {
|
|
179
|
+
const favesTB = isTB(favoritesSide),
|
|
180
|
+
isFavesFirst = favoritesSide === 'left' || favoritesSide === 'top',
|
|
181
|
+
items = [
|
|
182
|
+
editor({
|
|
183
|
+
editorTitle,
|
|
184
|
+
emptyText,
|
|
185
|
+
testId: getTestId(testId, 'editor')
|
|
186
|
+
}),
|
|
187
|
+
favoritesChooser({
|
|
188
|
+
// Omit if favorites generally disabled, or if none saved yet AND in top/bottom
|
|
189
|
+
// orientation - the empty state looks clumsy in that case. Show when empty in
|
|
190
|
+
// left/right orientation to avoid large jump in popover width.
|
|
191
|
+
omit: !model.persistFavorites || (!model.hasFavorites && favesTB),
|
|
192
|
+
favoritesSide,
|
|
193
|
+
favoritesTitle,
|
|
194
|
+
testId: getTestId(testId, 'favorites')
|
|
195
|
+
})
|
|
196
|
+
],
|
|
197
|
+
itemsContainer = favesTB ? vframe : hframe;
|
|
198
|
+
|
|
199
|
+
if (isFavesFirst) {
|
|
200
|
+
items.reverse();
|
|
201
|
+
}
|
|
202
|
+
|
|
132
203
|
return panel({
|
|
204
|
+
className: 'xh-grouping-chooser-popover__inner',
|
|
133
205
|
width: popoverWidth,
|
|
134
206
|
minHeight: popoverMinHeight,
|
|
135
|
-
items:
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
testId: getTestId(testId, 'editor')
|
|
141
|
-
}),
|
|
142
|
-
favoritesChooser({
|
|
143
|
-
omit: !model.persistFavorites,
|
|
144
|
-
testId: getTestId(testId, 'favorites')
|
|
145
|
-
})
|
|
146
|
-
]
|
|
207
|
+
items: itemsContainer({items}),
|
|
208
|
+
bbar: toolbar({
|
|
209
|
+
compact: true,
|
|
210
|
+
omit: !model.persistFavorites,
|
|
211
|
+
items: [filler(), favoritesAddBtn({testId})]
|
|
147
212
|
})
|
|
148
213
|
});
|
|
149
214
|
}
|
|
150
215
|
});
|
|
151
216
|
|
|
152
217
|
const editor = hoistCmp.factory<GroupingChooserModel>({
|
|
153
|
-
render({
|
|
218
|
+
render({editorTitle, emptyText, testId}) {
|
|
154
219
|
return vbox({
|
|
155
220
|
className: 'xh-grouping-chooser__editor',
|
|
156
221
|
testId,
|
|
157
222
|
items: [
|
|
158
|
-
div({className: 'xh-popup__title', item:
|
|
223
|
+
div({className: 'xh-popup__title', item: editorTitle, omit: isNil(editorTitle)}),
|
|
159
224
|
dimensionList({emptyText}),
|
|
160
225
|
addDimensionControl()
|
|
161
226
|
]
|
|
@@ -330,26 +395,23 @@ function getDimOptions(dims, model) {
|
|
|
330
395
|
// Favorites
|
|
331
396
|
//------------------
|
|
332
397
|
const favoritesChooser = hoistCmp.factory<GroupingChooserModel>({
|
|
333
|
-
render({model, testId}) {
|
|
334
|
-
const {favoritesOptions: options,
|
|
335
|
-
items = isEmpty(options)
|
|
336
|
-
? [menuItem({text: 'No favorites saved.', disabled: true})]
|
|
337
|
-
: options.map(it => favoriteMenuItem(it));
|
|
398
|
+
render({model, favoritesSide, favoritesTitle, testId}) {
|
|
399
|
+
const {favoritesOptions: options, hasFavorites} = model;
|
|
338
400
|
|
|
339
401
|
return vbox({
|
|
340
|
-
className:
|
|
402
|
+
className: `xh-grouping-chooser__favorites xh-grouping-chooser__favorites--${favoritesSide}`,
|
|
341
403
|
testId,
|
|
342
404
|
items: [
|
|
343
|
-
div({
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
405
|
+
div({
|
|
406
|
+
className: 'xh-popup__title',
|
|
407
|
+
item: favoritesTitle,
|
|
408
|
+
omit: isNil(favoritesTitle)
|
|
409
|
+
}),
|
|
410
|
+
hasFavorites
|
|
411
|
+
? menu({
|
|
412
|
+
items: options.map(it => favoriteMenuItem(it))
|
|
413
|
+
})
|
|
414
|
+
: placeholder('No favorites saved.')
|
|
353
415
|
]
|
|
354
416
|
});
|
|
355
417
|
}
|
|
@@ -372,3 +434,19 @@ const favoriteMenuItem = hoistCmp.factory<GroupingChooserModel>({
|
|
|
372
434
|
});
|
|
373
435
|
}
|
|
374
436
|
});
|
|
437
|
+
|
|
438
|
+
const favoritesAddBtn = hoistCmp.factory<GroupingChooserModel>({
|
|
439
|
+
render({model, testId}) {
|
|
440
|
+
return button({
|
|
441
|
+
text: 'Save as Favorite',
|
|
442
|
+
icon: Icon.favorite(),
|
|
443
|
+
className: 'xh-grouping-chooser__favorites__add-btn',
|
|
444
|
+
testId: getTestId(testId, 'favorites-add-btn'),
|
|
445
|
+
omit: !model.persistFavorites,
|
|
446
|
+
disabled: !model.isAddFavoriteEnabled,
|
|
447
|
+
onClick: () => model.addPendingAsFavorite()
|
|
448
|
+
});
|
|
449
|
+
}
|
|
450
|
+
});
|
|
451
|
+
|
|
452
|
+
const isTB = (favoritesSide: Side) => favoritesSide === 'top' || favoritesSide === 'bottom';
|
|
@@ -84,7 +84,7 @@ export interface PanelProps extends HoistProps<PanelModel>, Omit<BoxProps, 'titl
|
|
|
84
84
|
tbar?: Some<ReactNode>;
|
|
85
85
|
|
|
86
86
|
/**
|
|
87
|
-
* A toolbar to be docked at the
|
|
87
|
+
* A toolbar to be docked at the bottom of the panel.
|
|
88
88
|
* If specified as an array, items will be passed as children to a Toolbar component.
|
|
89
89
|
*/
|
|
90
90
|
bbar?: Some<ReactNode>;
|
package/package.json
CHANGED
package/svc/TrackService.ts
CHANGED
|
@@ -132,10 +132,11 @@ export class TrackService extends HoistService {
|
|
|
132
132
|
if (options.logData !== undefined) ret.logData = options.logData;
|
|
133
133
|
if (options.elapsed !== undefined) ret.elapsed = options.elapsed;
|
|
134
134
|
|
|
135
|
-
const {maxDataLength} = this.conf
|
|
136
|
-
|
|
135
|
+
const {maxDataLength} = this.conf,
|
|
136
|
+
dataLength = JSON.stringify(ret.data)?.length ?? 0;
|
|
137
|
+
if (dataLength > maxDataLength) {
|
|
137
138
|
this.logWarn(
|
|
138
|
-
`Track log includes ${
|
|
139
|
+
`Track log includes ${dataLength} chars of JSON data`,
|
|
139
140
|
`exceeds limit of ${maxDataLength}`,
|
|
140
141
|
'data will not be persisted',
|
|
141
142
|
options.data
|