@xh/hoist 73.0.0-SNAPSHOT.1745973083869 → 73.0.0-SNAPSHOT.1746025071597

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 (50) hide show
  1. package/CHANGELOG.md +7 -1
  2. package/admin/AdminUtils.ts +0 -5
  3. package/admin/App.scss +6 -0
  4. package/admin/AppModel.ts +5 -17
  5. package/admin/{tabs/client/clients/ClientsColumns.ts → columns/Clients.ts} +20 -53
  6. package/admin/columns/Core.ts +34 -35
  7. package/admin/columns/Tracking.ts +74 -44
  8. package/admin/columns/index.ts +1 -0
  9. package/admin/tabs/activity/tracking/ActivityTracking.scss +0 -18
  10. package/admin/tabs/activity/tracking/ActivityTrackingModel.ts +205 -296
  11. package/admin/tabs/activity/tracking/ActivityTrackingPanel.ts +51 -81
  12. package/admin/tabs/activity/tracking/charts/ChartsModel.ts +218 -0
  13. package/admin/tabs/activity/tracking/charts/ChartsPanel.ts +76 -0
  14. package/admin/tabs/activity/tracking/detail/ActivityDetailModel.ts +60 -114
  15. package/admin/tabs/activity/tracking/detail/ActivityDetailView.ts +40 -63
  16. package/admin/tabs/client/clients/ClientsModel.ts +10 -11
  17. package/admin/tabs/cluster/instances/memory/MemoryMonitorModel.ts +2 -1
  18. package/build/types/admin/AdminUtils.d.ts +0 -2
  19. package/build/types/admin/AppModel.d.ts +1 -4
  20. package/build/types/admin/{tabs/client/clients/ClientsColumns.d.ts → columns/Clients.d.ts} +3 -7
  21. package/build/types/admin/columns/Core.d.ts +5 -5
  22. package/build/types/admin/columns/Tracking.d.ts +7 -4
  23. package/build/types/admin/columns/index.d.ts +1 -0
  24. package/build/types/admin/tabs/activity/tracking/ActivityTrackingModel.d.ts +26 -30
  25. package/build/types/admin/tabs/activity/tracking/charts/ChartsModel.d.ts +34 -0
  26. package/build/types/admin/tabs/activity/tracking/charts/ChartsPanel.d.ts +2 -0
  27. package/build/types/admin/tabs/activity/tracking/detail/ActivityDetailModel.d.ts +1 -13
  28. package/build/types/cmp/form/FormModel.d.ts +40 -17
  29. package/build/types/cmp/form/field/SubformsFieldModel.d.ts +18 -20
  30. package/build/types/core/HoistBase.d.ts +2 -2
  31. package/build/types/data/cube/CubeField.d.ts +5 -4
  32. package/build/types/desktop/cmp/appOption/AutoRefreshAppOption.d.ts +3 -3
  33. package/build/types/desktop/cmp/appOption/ThemeAppOption.d.ts +3 -3
  34. package/cmp/error/ErrorBoundaryModel.ts +1 -1
  35. package/cmp/form/FormModel.ts +112 -20
  36. package/cmp/form/field/SubformsFieldModel.ts +22 -28
  37. package/cmp/grid/impl/GridHScrollbar.ts +2 -1
  38. package/core/HoistBase.ts +12 -12
  39. package/data/cube/CubeField.ts +18 -17
  40. package/package.json +1 -1
  41. package/svc/TrackService.ts +2 -0
  42. package/tsconfig.tsbuildinfo +1 -1
  43. package/admin/tabs/activity/tracking/chart/AggChartModel.ts +0 -218
  44. package/admin/tabs/activity/tracking/chart/AggChartPanel.ts +0 -61
  45. package/admin/tabs/activity/tracking/datafields/DataFieldsEditor.ts +0 -147
  46. package/admin/tabs/activity/tracking/datafields/DataFieldsEditorModel.ts +0 -133
  47. package/build/types/admin/tabs/activity/tracking/chart/AggChartModel.d.ts +0 -33
  48. package/build/types/admin/tabs/activity/tracking/chart/AggChartPanel.d.ts +0 -2
  49. package/build/types/admin/tabs/activity/tracking/datafields/DataFieldsEditor.d.ts +0 -2
  50. package/build/types/admin/tabs/activity/tracking/datafields/DataFieldsEditorModel.d.ts +0 -46
package/CHANGELOG.md CHANGED
@@ -4,12 +4,18 @@
4
4
 
5
5
  ### 💥 Breaking Changes (upgrade difficulty: 🟢 TRIVIAL - minor upgrade to Hoist Core)
6
6
 
7
- Requires `hoist-core >= 30.0` with new APIs to support the consolidated Admin Console "Clients" tab.
7
+ Requires `hoist-core >= 30.0` with new APIs to support the consolidated Admin Console "Clients" tab
8
+ and new properties on `TrackLog`.
8
9
 
9
10
  ### 🎁 New Features
10
11
 
11
12
  * Added a new "Clients" Admin Console tab- a consolidated view of all websocket-connected clients
12
13
  across all instances in the cluster.
14
+ * Updated `FormModel` to support `persistWith` for storing and recalling its values, including
15
+ developer options to persist all or a provided subset of fields.
16
+ * Enhanced all activity tracking messages with new `tabId` and `loadId` properties, to disambiguate
17
+ tracking activity for users with multiple browser tabs and multiple full refreshes/restarts of a
18
+ client app within the same tab.
13
19
 
14
20
  ### 🐞 Bug Fixes
15
21
 
@@ -4,7 +4,6 @@
4
4
  *
5
5
  * Copyright © 2025 Extremely Heavy Industries Inc.
6
6
  */
7
- import {AppModel} from '@xh/hoist/admin/AppModel';
8
7
  import {XH} from '@xh/hoist/core';
9
8
  import {LocalDate} from '@xh/hoist/utils/datetime';
10
9
 
@@ -22,7 +21,3 @@ export function exportFilename(moduleName: string): string {
22
21
  export function exportFilenameWithDate(moduleName: string): () => string {
23
22
  return () => `${XH.appCode}-${moduleName}-${LocalDate.today()}`;
24
23
  }
25
-
26
- export function getAppModel<T extends AppModel>() {
27
- return XH.appModel as T;
28
- }
package/admin/App.scss CHANGED
@@ -25,6 +25,12 @@
25
25
  height: 80vh;
26
26
  width: 80vw;
27
27
  }
28
+
29
+ .xh-badge-col {
30
+ --xh-badge-font-size: 0.9em;
31
+ background-color: var(--xh-intent-primary-darker);
32
+ font-family: var(--xh-font-family-mono);
33
+ }
28
34
  }
29
35
 
30
36
  .xh-units-label {
package/admin/AppModel.ts CHANGED
@@ -7,21 +7,21 @@
7
7
  import {clusterTab} from '@xh/hoist/admin/tabs/cluster/ClusterTab';
8
8
  import {GridModel} from '@xh/hoist/cmp/grid';
9
9
  import {TabConfig, TabContainerModel} from '@xh/hoist/cmp/tab';
10
- import {ViewManagerModel} from '@xh/hoist/cmp/viewmanager';
11
- import {HoistAppModel, XH} from '@xh/hoist/core';
10
+ import {HoistAppModel, managed, XH} from '@xh/hoist/core';
12
11
  import {Icon} from '@xh/hoist/icon';
13
12
  import {without} from 'lodash';
14
13
  import {Route} from 'router5';
15
14
  import {activityTrackingPanel} from './tabs/activity/tracking/ActivityTrackingPanel';
16
- import {clientTab} from './tabs/client/ClientTab';
17
15
  import {generalTab} from './tabs/general/GeneralTab';
18
16
  import {monitorTab} from './tabs/monitor/MonitorTab';
19
17
  import {userDataTab} from './tabs/userData/UserDataTab';
18
+ import {clientTab} from './tabs/client/ClientTab';
20
19
 
21
20
  export class AppModel extends HoistAppModel {
22
- tabModel: TabContainerModel;
21
+ static instance: AppModel;
23
22
 
24
- viewManagerModels: Record<string, ViewManagerModel> = {};
23
+ @managed
24
+ tabModel: TabContainerModel;
25
25
 
26
26
  static get readonly() {
27
27
  return !XH.getUser().isHoistAdmin;
@@ -40,11 +40,6 @@ export class AppModel extends HoistAppModel {
40
40
  GridModel.DEFAULT_AUTOSIZE_MODE = 'managed';
41
41
  }
42
42
 
43
- override async initAsync() {
44
- await this.initViewManagerModelsAsync();
45
- await super.initAsync();
46
- }
47
-
48
43
  override getRoutes(): Route[] {
49
44
  return [
50
45
  {
@@ -166,11 +161,4 @@ export class AppModel extends HoistAppModel {
166
161
  const appCodes = without(XH.clientApps, XH.clientAppCode, 'mobile');
167
162
  return appCodes.find(it => it === 'app') ?? appCodes[0];
168
163
  }
169
-
170
- async initViewManagerModelsAsync() {
171
- this.viewManagerModels.activityTracking = await ViewManagerModel.createAsync({
172
- type: 'xhAdminActivityTrackingView',
173
- typeDisplayName: 'View'
174
- });
175
- }
176
164
  }
@@ -4,11 +4,19 @@
4
4
  *
5
5
  * Copyright © 2025 Extremely Heavy Industries Inc.
6
6
  */
7
- import {badgeCol} from '@xh/hoist/admin/columns';
8
7
  import * as Col from '@xh/hoist/cmp/grid/columns';
9
8
  import {ColumnSpec} from '@xh/hoist/cmp/grid/columns';
10
9
  import {Icon} from '@xh/hoist/icon';
11
10
 
11
+ export const createdTime: ColumnSpec = {
12
+ field: {
13
+ name: 'createdTime',
14
+ type: 'date',
15
+ displayName: 'Created'
16
+ },
17
+ ...Col.compactDate
18
+ };
19
+
12
20
  export const isOpen: ColumnSpec = {
13
21
  field: {name: 'isOpen', type: 'bool'},
14
22
  headerName: '',
@@ -29,23 +37,14 @@ export const key: ColumnSpec = {
29
37
  width: 160
30
38
  };
31
39
 
32
- export const createdTime: ColumnSpec = {
40
+ export const lastReceivedTime: ColumnSpec = {
33
41
  field: {
34
- name: 'createdTime',
42
+ name: 'lastReceivedTime',
35
43
  type: 'date',
36
- displayName: 'Created'
37
- },
38
- ...Col.compactDate
39
- };
40
-
41
- export const sentMessageCount: ColumnSpec = {
42
- field: {
43
- name: 'sentMessageCount',
44
- type: 'int',
45
- displayName: 'Sent'
44
+ displayName: 'Last Received'
46
45
  },
47
- ...Col.number,
48
- width: 90
46
+ ...Col.compactDate,
47
+ width: 140
49
48
  };
50
49
 
51
50
  export const lastSentTime: ColumnSpec = {
@@ -68,44 +67,12 @@ export const receivedMessageCount: ColumnSpec = {
68
67
  width: 90
69
68
  };
70
69
 
71
- export const lastReceivedTime: ColumnSpec = {
72
- field: {
73
- name: 'lastReceivedTime',
74
- type: 'date',
75
- displayName: 'Last Received'
76
- },
77
- ...Col.compactDate,
78
- width: 140
79
- };
80
-
81
- export const appVersion: ColumnSpec = {
82
- field: {
83
- name: 'appVersion',
84
- displayName: 'Version',
85
- type: 'string'
86
- },
87
- width: 120
88
- };
89
-
90
- export const appBuild: ColumnSpec = {
91
- field: {
92
- name: 'appBuild',
93
- displayName: 'Build',
94
- type: 'string'
95
- },
96
- width: 120
97
- };
98
- export const loadId: ColumnSpec = {
99
- field: {
100
- name: 'loadId',
101
- type: 'string'
102
- },
103
- ...badgeCol
104
- };
105
- export const tabId: ColumnSpec = {
70
+ export const sentMessageCount: ColumnSpec = {
106
71
  field: {
107
- name: 'tabId',
108
- type: 'string'
72
+ name: 'sentMessageCount',
73
+ type: 'int',
74
+ displayName: 'Sent'
109
75
  },
110
- ...badgeCol
76
+ ...Col.number,
77
+ width: 90
111
78
  };
@@ -11,15 +11,29 @@ import {dateTimeRenderer} from '@xh/hoist/format';
11
11
  import {Icon} from '@xh/hoist/icon';
12
12
  import copy from 'clipboard-copy';
13
13
 
14
- export const name: ColumnSpec = {
15
- field: {name: 'name', type: 'string'},
16
- width: 200
14
+ export const badgeCol: ColumnSpec = {
15
+ autosizable: false,
16
+ width: 100,
17
+ renderer: badgeRenderer
17
18
  };
18
19
 
19
- export const type: ColumnSpec = {
20
- field: {name: 'type', type: 'string'},
21
- width: 100
22
- };
20
+ export function badgeRenderer(v) {
21
+ return v
22
+ ? badge({
23
+ item: v,
24
+ className: 'xh-badge-col',
25
+ style: {cursor: 'copy'},
26
+ title: 'Double-click to copy',
27
+ onDoubleClick: () => {
28
+ copy(v);
29
+ XH.toast({
30
+ icon: Icon.copy(),
31
+ message: `Copied ${v}`
32
+ });
33
+ }
34
+ })
35
+ : '-';
36
+ }
23
37
 
24
38
  export const description: ColumnSpec = {
25
39
  field: {name: 'description', type: 'string'},
@@ -27,11 +41,9 @@ export const description: ColumnSpec = {
27
41
  minWidth: 200
28
42
  };
29
43
 
30
- export const notes: ColumnSpec = {
31
- field: {name: 'notes', type: 'string'},
32
- minWidth: 60,
33
- flex: true,
34
- tooltip: true
44
+ export const name: ColumnSpec = {
45
+ field: {name: 'name', type: 'string'},
46
+ width: 200
35
47
  };
36
48
 
37
49
  export const note: ColumnSpec = {
@@ -45,33 +57,20 @@ export const note: ColumnSpec = {
45
57
  tooltip: true
46
58
  };
47
59
 
60
+ export const notes: ColumnSpec = {
61
+ field: {name: 'notes', type: 'string'},
62
+ minWidth: 60,
63
+ flex: true,
64
+ tooltip: true
65
+ };
66
+
48
67
  export const timestampNoYear: ColumnSpec = {
49
68
  field: {name: 'timestamp', type: 'date'},
50
69
  ...dateTimeSec,
51
70
  renderer: dateTimeRenderer({fmt: 'MMM DD HH:mm:ss.SSS'})
52
71
  };
53
72
 
54
- export function badgeRenderer(v) {
55
- return v
56
- ? badge({
57
- item: v,
58
- className: 'xh-font-family-mono',
59
- style: {cursor: 'copy'},
60
- intent: 'primary',
61
- title: 'Double-click to copy',
62
- onDoubleClick: () => {
63
- copy(v);
64
- XH.toast({
65
- icon: Icon.copy(),
66
- message: `Copied ${v}`
67
- });
68
- }
69
- })
70
- : '-';
71
- }
72
-
73
- export const badgeCol: ColumnSpec = {
74
- autosizable: false,
75
- width: 90,
76
- renderer: badgeRenderer
73
+ export const type: ColumnSpec = {
74
+ field: {name: 'type', type: 'string'},
75
+ width: 100
77
76
  };
@@ -4,13 +4,22 @@
4
4
  *
5
5
  * Copyright © 2025 Extremely Heavy Industries Inc.
6
6
  */
7
- import {badgeRenderer} from '@xh/hoist/admin/columns';
7
+ import {badgeCol, badgeRenderer} from '@xh/hoist/admin/columns';
8
8
  import {RangeAggregator} from '@xh/hoist/admin/tabs/activity/aggregators/RangeAggregator';
9
9
  import * as Col from '@xh/hoist/cmp/grid/columns';
10
10
  import {ColumnSpec} from '@xh/hoist/cmp/grid/columns';
11
11
  import {fmtDate, fmtSpan, numberRenderer} from '@xh/hoist/format';
12
12
  import {Icon} from '@xh/hoist/icon';
13
13
 
14
+ export const appBuild: ColumnSpec = {
15
+ field: {
16
+ name: 'appBuild',
17
+ displayName: 'Build',
18
+ type: 'string'
19
+ },
20
+ width: 120
21
+ };
22
+
14
23
  export const appEnvironment: ColumnSpec = {
15
24
  field: {
16
25
  name: 'appEnvironment',
@@ -21,8 +30,12 @@ export const appEnvironment: ColumnSpec = {
21
30
  };
22
31
 
23
32
  export const appVersion: ColumnSpec = {
24
- field: {name: 'appVersion', type: 'string'},
25
- width: 130
33
+ field: {
34
+ name: 'appVersion',
35
+ displayName: 'Version',
36
+ type: 'string'
37
+ },
38
+ width: 120
26
39
  };
27
40
 
28
41
  export const browser: ColumnSpec = {
@@ -35,24 +48,25 @@ export const browser: ColumnSpec = {
35
48
  width: 100
36
49
  };
37
50
 
38
- export const severity: ColumnSpec = {
51
+ export const category: ColumnSpec = {
39
52
  field: {
40
- name: 'severity',
53
+ name: 'category',
41
54
  type: 'string',
42
55
  isDimension: true,
43
56
  aggregator: 'UNIQUE'
44
57
  },
45
- width: 80
58
+ width: 100
46
59
  };
47
60
 
48
- export const category: ColumnSpec = {
61
+ export const correlationId: ColumnSpec = {
49
62
  field: {
50
- name: 'category',
63
+ name: 'correlationId',
51
64
  type: 'string',
52
- isDimension: true,
53
- aggregator: 'UNIQUE'
65
+ displayName: 'Correlation ID'
54
66
  },
55
- width: 100
67
+ renderer: badgeRenderer,
68
+ width: 180,
69
+ autosizeBufferPx: 20
56
70
  };
57
71
 
58
72
  export const data: ColumnSpec = {
@@ -71,6 +85,20 @@ export const day: ColumnSpec = {
71
85
  displayName: 'App Day'
72
86
  };
73
87
 
88
+ export const dayRange: ColumnSpec = {
89
+ field: {
90
+ name: 'dayRange',
91
+ type: 'json',
92
+ aggregator: new RangeAggregator(),
93
+ displayName: 'App Day Range'
94
+ },
95
+ align: 'right',
96
+ width: 200,
97
+ renderer: dayRangeRenderer,
98
+ exportValue: dayRangeRenderer,
99
+ comparator: dayRangeComparator
100
+ };
101
+
74
102
  export const device: ColumnSpec = {
75
103
  field: {
76
104
  name: 'device',
@@ -117,24 +145,33 @@ export const entryId: ColumnSpec = {
117
145
  align: 'right'
118
146
  };
119
147
 
120
- export const correlationId: ColumnSpec = {
148
+ export const error: ColumnSpec = {
121
149
  field: {
122
- name: 'correlationId',
150
+ name: 'error',
151
+ type: 'string'
152
+ },
153
+ width: 250,
154
+ autosizeMaxWidth: 400,
155
+ renderer: e => fmtSpan(e, {className: 'xh-font-family-mono xh-font-size-small'})
156
+ };
157
+
158
+ export const instance: ColumnSpec = {
159
+ field: {
160
+ name: 'instance',
123
161
  type: 'string',
124
- displayName: 'Correlation ID'
162
+ isDimension: true,
163
+ aggregator: 'UNIQUE'
125
164
  },
126
165
  renderer: badgeRenderer,
127
166
  width: 100
128
167
  };
129
168
 
130
- export const error: ColumnSpec = {
169
+ export const loadId: ColumnSpec = {
131
170
  field: {
132
- name: 'error',
171
+ name: 'loadId',
133
172
  type: 'string'
134
173
  },
135
- width: 250,
136
- autosizeMaxWidth: 400,
137
- renderer: e => fmtSpan(e, {className: 'xh-font-family-mono xh-font-size-small'})
174
+ ...badgeCol
138
175
  };
139
176
 
140
177
  export const msg: ColumnSpec = {
@@ -149,25 +186,32 @@ export const msg: ColumnSpec = {
149
186
  autosizeMaxWidth: 400
150
187
  };
151
188
 
152
- export const url: ColumnSpec = {
189
+ export const severity: ColumnSpec = {
153
190
  field: {
154
- name: 'url',
191
+ name: 'severity',
155
192
  type: 'string',
156
- displayName: 'URL'
193
+ isDimension: true,
194
+ aggregator: 'UNIQUE'
157
195
  },
158
- width: 250,
159
- autosizeMaxWidth: 400
196
+ width: 80
160
197
  };
161
198
 
162
- export const instance: ColumnSpec = {
199
+ export const tabId: ColumnSpec = {
163
200
  field: {
164
- name: 'instance',
201
+ name: 'tabId',
202
+ type: 'string'
203
+ },
204
+ ...badgeCol
205
+ };
206
+
207
+ export const url: ColumnSpec = {
208
+ field: {
209
+ name: 'url',
165
210
  type: 'string',
166
- isDimension: true,
167
- aggregator: 'UNIQUE'
211
+ displayName: 'URL'
168
212
  },
169
- renderer: badgeRenderer,
170
- width: 100
213
+ width: 250,
214
+ autosizeMaxWidth: 400
171
215
  };
172
216
 
173
217
  export const userAgent: ColumnSpec = {
@@ -207,20 +251,6 @@ export const userMessageFlag: ColumnSpec = {
207
251
  }
208
252
  };
209
253
 
210
- export const dayRange: ColumnSpec = {
211
- field: {
212
- name: 'dayRange',
213
- type: 'json',
214
- aggregator: new RangeAggregator(),
215
- displayName: 'App Day Range'
216
- },
217
- align: 'right',
218
- width: 200,
219
- renderer: dayRangeRenderer,
220
- exportValue: dayRangeRenderer,
221
- comparator: dayRangeComparator
222
- };
223
-
224
254
  //-----------------------
225
255
  // Implementation
226
256
  //-----------------------
@@ -1,3 +1,4 @@
1
+ export * from './Clients';
1
2
  export * from './Core';
2
3
  export * from './Rest';
3
4
  export * from './Tracking';
@@ -31,24 +31,6 @@
31
31
  margin-right: var(--xh-pad-half-px);
32
32
  }
33
33
  }
34
-
35
- &__data-fields-editor {
36
- width: 50vw;
37
- min-width: 700px;
38
- max-width: 1000px;
39
- min-height: 200px;
40
-
41
- &__row {
42
- align-items: flex-start;
43
- flex: none;
44
- margin-left: 5px;
45
- margin-right: 5px;
46
-
47
- &:first-child {
48
- margin-top: 5px;
49
- }
50
- }
51
- }
52
34
  }
53
35
 
54
36
  .xh-admin-activity-detail {