@xh/hoist 73.0.0-SNAPSHOT.1745976013413 → 73.0.0-SNAPSHOT.1746050068813

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 (57) hide show
  1. package/CHANGELOG.md +10 -1
  2. package/admin/AdminUtils.ts +5 -0
  3. package/admin/App.scss +6 -0
  4. package/admin/AppModel.ts +19 -7
  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/Rest.ts +8 -0
  8. package/admin/columns/Tracking.ts +144 -42
  9. package/admin/columns/index.ts +1 -0
  10. package/admin/tabs/activity/tracking/ActivityTracking.scss +18 -0
  11. package/admin/tabs/activity/tracking/ActivityTrackingModel.ts +309 -210
  12. package/admin/tabs/activity/tracking/ActivityTrackingPanel.ts +81 -51
  13. package/admin/tabs/activity/tracking/chart/AggChartModel.ts +218 -0
  14. package/admin/tabs/activity/tracking/chart/AggChartPanel.ts +61 -0
  15. package/admin/tabs/activity/tracking/datafields/DataFieldsEditor.ts +147 -0
  16. package/admin/tabs/activity/tracking/datafields/DataFieldsEditorModel.ts +133 -0
  17. package/admin/tabs/activity/tracking/detail/ActivityDetailModel.ts +123 -59
  18. package/admin/tabs/activity/tracking/detail/ActivityDetailView.ts +110 -54
  19. package/admin/tabs/client/ClientTab.ts +2 -4
  20. package/admin/tabs/client/clients/ClientsModel.ts +10 -11
  21. package/admin/tabs/cluster/instances/memory/MemoryMonitorModel.ts +1 -2
  22. package/admin/tabs/general/GeneralTab.ts +2 -0
  23. package/build/types/admin/AdminUtils.d.ts +2 -0
  24. package/build/types/admin/AppModel.d.ts +4 -1
  25. package/build/types/admin/{tabs/client/clients/ClientsColumns.d.ts → columns/Clients.d.ts} +3 -7
  26. package/build/types/admin/columns/Core.d.ts +5 -5
  27. package/build/types/admin/columns/Rest.d.ts +1 -0
  28. package/build/types/admin/columns/Tracking.d.ts +13 -4
  29. package/build/types/admin/columns/index.d.ts +1 -0
  30. package/build/types/admin/tabs/activity/tracking/ActivityTrackingModel.d.ts +31 -28
  31. package/build/types/admin/tabs/activity/tracking/chart/AggChartModel.d.ts +33 -0
  32. package/build/types/admin/tabs/activity/tracking/chart/AggChartPanel.d.ts +2 -0
  33. package/build/types/admin/tabs/activity/tracking/datafields/DataFieldsEditor.d.ts +2 -0
  34. package/build/types/admin/tabs/activity/tracking/datafields/DataFieldsEditorModel.d.ts +46 -0
  35. package/build/types/admin/tabs/activity/tracking/detail/ActivityDetailModel.d.ts +14 -1
  36. package/build/types/cmp/form/FormModel.d.ts +19 -30
  37. package/build/types/cmp/form/field/SubformsFieldModel.d.ts +25 -22
  38. package/build/types/core/HoistBase.d.ts +2 -2
  39. package/build/types/data/cube/CubeField.d.ts +4 -5
  40. package/build/types/desktop/cmp/appOption/AutoRefreshAppOption.d.ts +3 -3
  41. package/build/types/desktop/cmp/appOption/ThemeAppOption.d.ts +3 -3
  42. package/cmp/error/ErrorBoundaryModel.ts +1 -1
  43. package/cmp/form/FormModel.ts +20 -28
  44. package/cmp/form/field/SubformsFieldModel.ts +28 -22
  45. package/cmp/grid/columns/DatesTimes.ts +1 -2
  46. package/cmp/grid/impl/GridHScrollbar.ts +1 -2
  47. package/core/HoistBase.ts +12 -12
  48. package/data/cube/CubeField.ts +17 -18
  49. package/package.json +1 -1
  50. package/svc/TrackService.ts +2 -0
  51. package/tsconfig.tsbuildinfo +1 -1
  52. package/admin/tabs/activity/tracking/charts/ChartsModel.ts +0 -218
  53. package/admin/tabs/activity/tracking/charts/ChartsPanel.ts +0 -76
  54. package/build/types/admin/tabs/activity/tracking/charts/ChartsModel.d.ts +0 -34
  55. package/build/types/admin/tabs/activity/tracking/charts/ChartsPanel.d.ts +0 -2
  56. /package/admin/tabs/{client → general}/feedback/FeedbackPanel.ts +0 -0
  57. /package/build/types/admin/tabs/{client → general}/feedback/FeedbackPanel.d.ts +0 -0
@@ -1,218 +0,0 @@
1
- /*
2
- * This file belongs to Hoist, an application development toolkit
3
- * developed by Extremely Heavy Industries (www.xh.io | info@xh.io)
4
- *
5
- * Copyright © 2025 Extremely Heavy Industries Inc.
6
- */
7
- import {ChartModel} from '@xh/hoist/cmp/chart';
8
- import {br, fragment} from '@xh/hoist/cmp/layout';
9
- import {HoistModel, managed, lookup} from '@xh/hoist/core';
10
- import {capitalizeWords, fmtDate} from '@xh/hoist/format';
11
- import {bindable, makeObservable} from '@xh/hoist/mobx';
12
- import {LocalDate} from '@xh/hoist/utils/datetime';
13
- import {filter, sortBy, isEmpty} from 'lodash';
14
- import moment from 'moment';
15
- import {PanelModel} from '@xh/hoist/desktop/cmp/panel';
16
- import {ActivityTrackingModel} from '../ActivityTrackingModel';
17
- import {ONE_DAY} from '@xh/hoist/utils/datetime/DateTimeUtils';
18
-
19
- export class ChartsModel extends HoistModel {
20
- @managed panelModel = new PanelModel({
21
- modalSupport: {width: '90vw', height: '60vh'},
22
- side: 'bottom',
23
- defaultSize: 370
24
- });
25
-
26
- @lookup(ActivityTrackingModel)
27
- activityTrackingModel: ActivityTrackingModel;
28
-
29
- /** metric to chart on Y axis - one of:
30
- * + entryCount - count of total track log entries within the primary dim group.
31
- * + count - count of unique secondary dim values within the primary dim group.
32
- * + elapsed - avg elapsed time in ms for the primary dim group.
33
- */
34
- @bindable
35
- metric: 'entryCount' | 'count' | 'elapsed' = 'entryCount';
36
-
37
- /** show weekends on the activity chart */
38
- @bindable
39
- incWeekends: boolean = false;
40
-
41
- @managed
42
- categoryChartModel: ChartModel = new ChartModel({
43
- highchartsConfig: {
44
- chart: {type: 'column', animation: false},
45
- plotOptions: {column: {animation: false}},
46
- legend: {enabled: false},
47
- title: {text: null},
48
- xAxis: {type: 'category', title: {}},
49
- yAxis: [{title: {text: null}, allowDecimals: false}]
50
- }
51
- });
52
-
53
- @managed
54
- timeseriesChartModel: ChartModel = new ChartModel({
55
- highchartsConfig: {
56
- chart: {type: 'line', animation: false},
57
- plotOptions: {
58
- line: {
59
- events: {
60
- click: e => this.selectRow(e)
61
- },
62
- width: 1,
63
- animation: false,
64
- step: 'left'
65
- }
66
- },
67
- legend: {enabled: false},
68
- title: {text: null},
69
- xAxis: {
70
- type: 'datetime',
71
- title: {},
72
- units: [
73
- ['day', [1]],
74
- ['week', [2]],
75
- ['month', [1]]
76
- ],
77
- labels: {
78
- formatter: function () {
79
- return fmtDate(this.value, 'D MMM');
80
- }
81
- }
82
- },
83
- yAxis: [{title: {text: null}, allowDecimals: false}]
84
- }
85
- });
86
-
87
- get showAsTimeseries(): boolean {
88
- return this.dimensions[0] === 'day';
89
- }
90
-
91
- get chartModel(): ChartModel {
92
- return this.showAsTimeseries ? this.timeseriesChartModel : this.categoryChartModel;
93
- }
94
-
95
- get primaryDim(): string {
96
- return this.dimensions[0];
97
- }
98
-
99
- get secondaryDim(): string {
100
- const {dimensions} = this;
101
- return dimensions.length >= 2 ? dimensions[1] : null;
102
- }
103
-
104
- get data() {
105
- const roots = this.activityTrackingModel.gridModel.store.allRootRecords;
106
- return roots.length ? roots[0].children : [];
107
- }
108
-
109
- get dimensions() {
110
- return this.activityTrackingModel.dimensions;
111
- }
112
-
113
- constructor() {
114
- super();
115
- makeObservable(this);
116
- }
117
-
118
- getLabelForMetric(metric, multiline) {
119
- switch (metric) {
120
- case 'count':
121
- return multiline
122
- ? fragment(`Unique`, br(), `${this.getUnitsForDim(this.secondaryDim)} Count`)
123
- : `Unique ${this.getUnitsForDim(this.secondaryDim)} Count`;
124
- case 'entryCount':
125
- return multiline ? fragment('Total', br(), 'Entry Count') : 'Total Entry Count';
126
- case 'elapsed':
127
- return 'Elapsed ms';
128
- default:
129
- return '???';
130
- }
131
- }
132
-
133
- //-----------------
134
- // Implementation
135
- //-----------------
136
-
137
- private selectRow(e) {
138
- const date = moment(e.point.x).format('YYYY-MM-DD'),
139
- id = `root>>day=[${date}]`;
140
- this.activityTrackingModel.gridModel.selectAsync(id);
141
- }
142
-
143
- override onLinked() {
144
- this.addReaction({
145
- track: () => [this.data, this.metric, this.incWeekends],
146
- run: () => this.loadChart()
147
- });
148
- }
149
-
150
- private loadChart() {
151
- const {showAsTimeseries, chartModel, primaryDim} = this,
152
- series = this.getSeriesData();
153
-
154
- if (!showAsTimeseries) {
155
- chartModel.updateHighchartsConfig({
156
- xAxis: {title: {text: this.getUnitsForDim(primaryDim)}}
157
- });
158
- }
159
-
160
- chartModel.setSeries(series);
161
- }
162
-
163
- private getSeriesData() {
164
- const {data, metric, primaryDim, showAsTimeseries} = this,
165
- metricLabel = this.getLabelForMetric(metric, false);
166
- let sortedData = sortBy(data, aggRow => {
167
- const {cubeLabel} = aggRow.data;
168
- switch (primaryDim) {
169
- case 'day':
170
- return LocalDate.from(cubeLabel).timestamp;
171
- case 'month':
172
- return moment(cubeLabel, 'MMM YYYY').valueOf();
173
- default:
174
- return cubeLabel;
175
- }
176
- }),
177
- chartData = sortedData.map(aggRow => {
178
- const {cubeLabel} = aggRow.data,
179
- xVal = showAsTimeseries ? LocalDate.from(cubeLabel).timestamp : cubeLabel,
180
- yVal = Math.round(aggRow.data[metric]);
181
- return [xVal, yVal];
182
- });
183
-
184
- // Insert data where no activity was logged
185
- if (showAsTimeseries) {
186
- const fillData = [];
187
- for (let i = 1; i < chartData.length; i++) {
188
- const skippedDayCount = Math.floor(
189
- (chartData[i][0] - chartData[i - 1][0]) / ONE_DAY - 1
190
- );
191
- if (skippedDayCount > 0) {
192
- for (let j = 1; j <= skippedDayCount; j++) {
193
- const skippedDate = chartData[i - 1][0] + j * ONE_DAY;
194
- fillData.push([skippedDate, 0]);
195
- }
196
- }
197
- }
198
- if (!isEmpty(fillData)) {
199
- chartData.push(...fillData);
200
- chartData = sortBy(chartData, data => data[0]);
201
- }
202
-
203
- if (!this.incWeekends) {
204
- chartData = filter(chartData, data => LocalDate.from(data[0]).isWeekday);
205
- }
206
- }
207
- return [{name: metricLabel, data: chartData}];
208
- }
209
-
210
- private getUnitsForDim(dim) {
211
- return (
212
- {
213
- username: 'User',
214
- msg: 'Message'
215
- }[dim] ?? capitalizeWords(dim)
216
- );
217
- }
218
- }
@@ -1,76 +0,0 @@
1
- /*
2
- * This file belongs to Hoist, an application development toolkit
3
- * developed by Extremely Heavy Industries (www.xh.io | info@xh.io)
4
- *
5
- * Copyright © 2025 Extremely Heavy Industries Inc.
6
- */
7
- import {chart} from '@xh/hoist/cmp/chart';
8
- import {hoistCmp, creates} from '@xh/hoist/core';
9
- import {button} from '@xh/hoist/desktop/cmp/button';
10
- import {buttonGroupInput} from '@xh/hoist/desktop/cmp/input';
11
- import {panel} from '@xh/hoist/desktop/cmp/panel';
12
- import {Icon} from '@xh/hoist/icon/Icon';
13
- import {toolbar} from '@xh/hoist/desktop/cmp/toolbar';
14
- import {checkbox} from '@xh/hoist/desktop/cmp/input';
15
- import {hspacer} from '@xh/hoist/cmp/layout';
16
- import {ChartsModel} from './ChartsModel';
17
-
18
- export const chartsPanel = hoistCmp.factory({
19
- model: creates(ChartsModel),
20
- render({model, ...props}) {
21
- const {chartModel, activityTrackingModel, panelModel} = model,
22
- {isModal} = panelModel;
23
- return panel({
24
- title: !isModal ? 'Aggregate Activity Chart' : activityTrackingModel.queryDisplayString,
25
- icon: Icon.chartBar(),
26
- model: panelModel,
27
- compactHeader: !isModal,
28
- item: chart({model: chartModel}),
29
- bbar: bbar(),
30
- height: '100%',
31
- ...props
32
- });
33
- }
34
- });
35
-
36
- const bbar = hoistCmp.factory<ChartsModel>(() =>
37
- toolbar(metricSwitcher({multiline: true}), hspacer(), incWeekendsCheckbox())
38
- );
39
-
40
- const incWeekendsCheckbox = hoistCmp.factory<ChartsModel>(({model}) =>
41
- checkbox({
42
- omit: !model.showAsTimeseries,
43
- bind: 'incWeekends',
44
- label: 'Inc Wknds'
45
- })
46
- );
47
-
48
- const metricSwitcher = hoistCmp.factory<ChartsModel>(({model, multiline}) => {
49
- return buttonGroupInput({
50
- className: 'xh-admin-activity-panel__metric-switcher',
51
- bind: 'metric',
52
- outlined: true,
53
- flex: 2,
54
- items: [
55
- button({
56
- text: model.getLabelForMetric('entryCount', multiline),
57
- value: 'entryCount',
58
- outlined: true,
59
- flex: 1
60
- }),
61
- button({
62
- text: model.getLabelForMetric('count', multiline),
63
- value: 'count',
64
- outlined: true,
65
- flex: 1,
66
- omit: !model.secondaryDim
67
- }),
68
- button({
69
- text: model.getLabelForMetric('elapsed', multiline),
70
- value: 'elapsed',
71
- outlined: true,
72
- flex: 1
73
- })
74
- ]
75
- });
76
- });
@@ -1,34 +0,0 @@
1
- /// <reference types="react" />
2
- import { ChartModel } from '@xh/hoist/cmp/chart';
3
- import { HoistModel } from '@xh/hoist/core';
4
- import { PanelModel } from '@xh/hoist/desktop/cmp/panel';
5
- import { ActivityTrackingModel } from '../ActivityTrackingModel';
6
- export declare class ChartsModel extends HoistModel {
7
- panelModel: PanelModel;
8
- activityTrackingModel: ActivityTrackingModel;
9
- /** metric to chart on Y axis - one of:
10
- * + entryCount - count of total track log entries within the primary dim group.
11
- * + count - count of unique secondary dim values within the primary dim group.
12
- * + elapsed - avg elapsed time in ms for the primary dim group.
13
- */
14
- metric: 'entryCount' | 'count' | 'elapsed';
15
- /** show weekends on the activity chart */
16
- incWeekends: boolean;
17
- categoryChartModel: ChartModel;
18
- timeseriesChartModel: ChartModel;
19
- get showAsTimeseries(): boolean;
20
- get chartModel(): ChartModel;
21
- get primaryDim(): string;
22
- get secondaryDim(): string;
23
- get data(): import("../../../../../data").StoreRecord[];
24
- get dimensions(): string[];
25
- constructor();
26
- getLabelForMetric(metric: any, multiline: any): string | import("react").ReactElement<{
27
- children?: import("react").ReactNode;
28
- }, any>;
29
- private selectRow;
30
- onLinked(): void;
31
- private loadChart;
32
- private getSeriesData;
33
- private getUnitsForDim;
34
- }
@@ -1,2 +0,0 @@
1
- import { ChartsModel } from './ChartsModel';
2
- export declare const chartsPanel: import("@xh/hoist/core").ElementFactory<import("@xh/hoist/core").DefaultHoistProps<ChartsModel>>;