@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
@@ -37,9 +37,7 @@ import {SubformsFieldConfig, SubformsFieldModel} from './field/SubformsFieldMode
37
37
  import {isLocalDate, LocalDate} from '@xh/hoist/utils/datetime';
38
38
 
39
39
  export interface FormConfig {
40
- /**
41
- * FieldModels, or configurations to create them, for all data fields managed by this FormModel.
42
- */
40
+ /** FieldModels, or configs to create them, for all data fields managed by the model. */
43
41
  fields?: Array<BaseFieldModel | BaseFieldConfig | SubformsFieldConfig | SubformsFieldModel>;
44
42
 
45
43
  /** Map of initial values for fields in this model. */
@@ -62,28 +60,33 @@ export interface FormPersistOptions extends PersistOptions {
62
60
  excludeFields?: string[];
63
61
  }
64
62
 
63
+ export interface FormValidateOptions {
64
+ /** True to trigger display of validation errors (if any) by bound `FormField`s after validation is complete. */
65
+ display?: boolean;
66
+ }
67
+
65
68
  /**
66
- * FormModel is the main entry point for Form specification. This Model's `fields` collection holds
67
- * multiple FieldModel instances, which in turn hold the state of user edited data and the
68
- * validation rules around editing that data.
69
+ * FormModel is the main entry point for Form specification. This Model's `fields` object references
70
+ * multiple {@link FieldModel} instances, keyed by name, which in turn hold the state of user-
71
+ * edited data and the validation rules around editing that data.
69
72
  *
70
73
  * A complete representation of all fields and data within a Form can be produced via this model's
71
- * `getData()` method, making it easy to harvest all values for e.g. submission to a server.
74
+ * {@link getData} method, making it easy to harvest all values for e.g. submission to a server.
72
75
  *
73
- * Individual field values are also available as observables via this model's `values` proxy. An
74
- * application model can setup a reaction to track changes to any value and execute app-specific
76
+ * Individual field values are also available as observables via this model's {@link values} proxy.
77
+ * An application model can setup a reaction to track changes to any value and execute app-specific
75
78
  * logic such as disabling one field based on the state of another, or setting up cascading options.
76
79
  *
77
80
  * This Model provides an overall validation state, determined by the current validation state of
78
81
  * its fields as per their configured rules and constraints.
79
82
  *
80
- * FormModels can be nested via SubformsFieldModels, a specialized type of FieldModel that itself
81
- * manages a collection of child FormModels. This allows use cases where Forms support editing of
83
+ * FormModels can be nested via {@link SubformsFieldModel}s, a specialized type of FieldModel that
84
+ * itself manages a collection of child FormModels. This enables forms to support editing of
82
85
  * dynamic collections of complex objects with their own internal validation rules (e.g. a FormModel
83
86
  * representing a market order might have multiple nested FormModels to represent execution splits,
84
87
  * where each split has its own internal fields for broker, quantity, and time).
85
88
  *
86
- * @see FieldModel for details on state and validation maintained at the individual field level.
89
+ * See {@link FieldModel} for details on state/validation maintained at the individual field level.
87
90
  */
88
91
  export class FormModel extends HoistModel {
89
92
  /** Container object for FieldModel instances, keyed by field name.*/
@@ -200,7 +203,6 @@ export class FormModel extends HoistModel {
200
203
 
201
204
  /**
202
205
  * Set the value of one or more fields on this form.
203
- *
204
206
  * @param values - map of field name to value.
205
207
  */
206
208
  @action
@@ -220,9 +222,7 @@ export class FormModel extends HoistModel {
220
222
  //-----------------------------------
221
223
  /**
222
224
  * The Field that is currently focused on this form.
223
- *
224
- * @see FieldModel.focus() for important information on this method
225
- * and its limitations.
225
+ * See {@link FieldModel.focus} for important information on this method and its limitations.
226
226
  */
227
227
  @computed
228
228
  get focusedField(): BaseFieldModel {
@@ -231,9 +231,7 @@ export class FormModel extends HoistModel {
231
231
 
232
232
  /**
233
233
  * Focus a field on this form.
234
- *
235
- * @see FieldModel.focus() for important information on this method
236
- * and its limitations.
234
+ * See {@link FieldModel.focus} for important information on this method and its limitations.
237
235
  */
238
236
  focusField(name: string) {
239
237
  this.getField(name)?.focus();
@@ -266,21 +264,15 @@ export class FormModel extends HoistModel {
266
264
  return flatMap(this.fields, s => s.allErrors);
267
265
  }
268
266
 
269
- /**
270
- * Recompute all validations and return true if the form is valid.
271
- *
272
- * @param opts - set 'display' to true to trigger the display of
273
- * validation errors (if any) by bound FormField components after validation
274
- * is complete.
275
- */
276
- async validateAsync(opts?: {display?: boolean}): Promise<boolean> {
267
+ /** Recompute all validations and return true if the form is valid. */
268
+ async validateAsync(opts?: FormValidateOptions): Promise<boolean> {
277
269
  const {display = true} = opts ?? {},
278
270
  promises = map(this.fields, m => m.validateAsync({display}));
279
271
  await Promise.all(promises);
280
272
  return this.isValid;
281
273
  }
282
274
 
283
- /** Trigger the display of validation errors (if any) by bound FormField components. */
275
+ /** Trigger the display of validation errors (if any) by bound `FormField`s. */
284
276
  displayValidation() {
285
277
  forOwn(this.fields, m => m.displayValidation());
286
278
  }
@@ -15,36 +15,47 @@ import {BaseFieldModel, BaseFieldConfig} from './BaseFieldModel';
15
15
  import {FormConfig} from '../FormModel';
16
16
 
17
17
  export interface SubformsFieldConfig extends BaseFieldConfig {
18
- /** Config for FormModel representing a subform. */
18
+ /**
19
+ * Config for a {@link FormModel} to be auto-created to manage and validate the data for each
20
+ *
21
+ */
19
22
  subforms: FormConfig;
20
23
 
21
24
  /**
22
- * Initial value of this field. If a function, will be
23
- * executed dynamically when form is initialized to provide value.
25
+ * Initial value of this field. If a function, will be executed dynamically when form is
26
+ * initialized to provide value.
24
27
  */
25
28
  initialValue?: any[];
26
29
  }
27
30
 
31
+ export interface SubformAddOptions {
32
+ /** Initial values for the new object/subform. */
33
+ initialValues?: PlainObject;
34
+ /** Index within the collection where the new subform should be inserted. */
35
+ index?: number;
36
+ }
37
+
28
38
  /**
29
- * A data field in a form whose value is a collection of FormModels (subforms).
39
+ * A data field in a form whose value is a collection of nested objects - all of the same shape, but
40
+ * with arbitrary internal complexity. A dedicated {@link FormModel} is auto-created to manage and
41
+ * validate each object independently.
30
42
  *
31
- * Applications should initialize this field with an array of objects. These values will be
32
- * loaded into an array of managed FormModels which will form the value of this field.
43
+ * Applications should initialize this field with an array of objects. These values will be loaded
44
+ * into an array of managed FormModels which will form the value of this field.
33
45
  *
34
46
  * Applications should *not* modify the value property directly, unless they wish to reinitialize
35
- * all existing form contents to new values. Use the methods add() or remove() to
36
- * adjust the contents of the collection while preserving existing form state.
47
+ * all existing form contents to new values. Call {@link add} or {@link remove} on one of these
48
+ * fields to adjust the contents of its collection while preserving existing state.
37
49
  *
38
- * Validation rules for the entire collection may be specified as for any field, but
39
- * validations on the subforms will also bubble up to this field, affecting its overall
40
- * validation state.
50
+ * Validation rules for the entire collection may be specified as for any field, but validations on
51
+ * the subforms will also bubble up to this field, affecting its overall validation state.
41
52
  */
42
53
  export class SubformsFieldModel extends BaseFieldModel {
43
- // (Sub)FormModels created by this model, tracked to support cleanup.
44
- @managed
45
- private createdModels: FormModel[] = [];
54
+ /** (Sub)FormModels created by this model, tracked to support cleanup. */
55
+ @managed private createdModels: FormModel[] = [];
56
+
46
57
  private formConfig: FormConfig = null;
47
- private origInitialValues: any[];
58
+ private readonly origInitialValues: any[];
48
59
 
49
60
  constructor({subforms, initialValue = [], ...rest}: SubformsFieldConfig) {
50
61
  super(rest);
@@ -161,14 +172,9 @@ export class SubformsFieldModel extends BaseFieldModel {
161
172
  //-----------------------------
162
173
  // Collection management
163
174
  //-----------------------------
164
- /**
165
- * Add a new record (subform) to this field.
166
- *
167
- * @param initialValues - object containing initial values for new record.
168
- * @param index - index in collection where subform should be inserted.
169
- */
175
+ /** Add a new object (subform) to this field's collection. */
170
176
  @action
171
- add(opts: {initialValues?: PlainObject; index?: number} = {}) {
177
+ add(opts: SubformAddOptions = {}) {
172
178
  const {initialValues = {}, index = this.value.length} = opts,
173
179
  newSubforms = this.parseValue([initialValues]),
174
180
  newValue = clone(this.value);
@@ -4,7 +4,7 @@
4
4
  *
5
5
  * Copyright © 2025 Extremely Heavy Industries Inc.
6
6
  */
7
- import {ColumnSpec} from '@xh/hoist/cmp/grid';
7
+ import {ColumnSpec, ExcelFormat} from '@xh/hoist/cmp/grid';
8
8
  import {
9
9
  compactDateRenderer,
10
10
  dateRenderer,
@@ -12,7 +12,6 @@ import {
12
12
  dateTimeSecRenderer,
13
13
  timeRenderer
14
14
  } from '@xh/hoist/format';
15
- import {ExcelFormat} from '../enums/ExcelFormat';
16
15
 
17
16
  const defaults: ColumnSpec = {align: 'right'};
18
17
 
@@ -7,10 +7,9 @@
7
7
  import {GridLocalModel, GridModel} from '@xh/hoist/cmp/grid';
8
8
  import {div} from '@xh/hoist/cmp/layout';
9
9
  import {hoistCmp, HoistModel, HoistProps, useLocalModel} from '@xh/hoist/core';
10
- import {makeObservable} from '@xh/hoist/mobx';
10
+ import {action, makeObservable, observable} from '@xh/hoist/mobx';
11
11
  import {observeResize} from '@xh/hoist/utils/js';
12
12
  import {sumBy} from 'lodash';
13
- import {action, observable} from 'mobx';
14
13
  import {createRef, RefObject} from 'react';
15
14
 
16
15
  /**
package/core/HoistBase.ts CHANGED
@@ -4,15 +4,21 @@
4
4
  *
5
5
  * Copyright © 2025 Extremely Heavy Industries Inc.
6
6
  */
7
- import {runInAction} from 'mobx';
8
- import {XH, PersistenceProvider, PersistOptions, DebounceSpec, Some, PersistableState} from './';
9
7
  import {
10
- throwIf,
8
+ action,
9
+ autorun as mobxAutorun,
10
+ comparer,
11
+ reaction as mobxReaction,
12
+ runInAction,
13
+ when as mobxWhen
14
+ } from '@xh/hoist/mobx';
15
+ import {
11
16
  getOrCreate,
12
- logInfo,
13
17
  logDebug,
14
18
  logError,
19
+ logInfo,
15
20
  logWarn,
21
+ throwIf,
16
22
  withDebug,
17
23
  withInfo
18
24
  } from '@xh/hoist/utils/js';
@@ -25,15 +31,9 @@ import {
25
31
  isString,
26
32
  upperFirst
27
33
  } from 'lodash';
28
- import {
29
- action,
30
- comparer,
31
- autorun as mobxAutorun,
32
- reaction as mobxReaction,
33
- when as mobxWhen
34
- } from '@xh/hoist/mobx';
35
34
  import {IAutorunOptions, IReactionOptions} from 'mobx/dist/api/autorun';
36
- import {IReactionDisposer, IEqualsComparer} from 'mobx/dist/internal';
35
+ import {IEqualsComparer, IReactionDisposer} from 'mobx/dist/internal';
36
+ import {DebounceSpec, PersistableState, PersistenceProvider, PersistOptions, Some, XH} from './';
37
37
 
38
38
  export interface HoistBaseClass {
39
39
  new (...args: any[]): HoistBase;
@@ -28,23 +28,8 @@ export interface CubeFieldSpec extends FieldSpec {
28
28
  /** True to allow this field to be used for grouping.*/
29
29
  isDimension?: boolean;
30
30
 
31
- /**
32
- * Instance of a Hoist Cube Aggregator (from the aggregate package), or string alias for the
33
- * same (e.g. 'MAX').
34
- */
35
- aggregator?:
36
- | Aggregator
37
- | 'AVG'
38
- | 'AVG_STRICT'
39
- | 'CHILD_COUNT'
40
- | 'LEAF_COUNT'
41
- | 'MAX'
42
- | 'MIN'
43
- | 'NULL'
44
- | 'SINGLE'
45
- | 'SUM'
46
- | 'SUM_STRICT'
47
- | 'UNIQUE';
31
+ /** Instance of a Hoist Cube {@link Aggregator} or string token alias for one. */
32
+ aggregator?: Aggregator | AggregatorToken;
48
33
 
49
34
  /** Function to determine if aggregation should be performed at a given level of a query result. */
50
35
  canAggregateFn?: CanAggregateFn;
@@ -60,6 +45,20 @@ export interface CubeFieldSpec extends FieldSpec {
60
45
  parentDimension?: string;
61
46
  }
62
47
 
48
+ /** Convenient (and serializable) alias for one of Hoist's Cube {@link Aggregator} classes. */
49
+ export type AggregatorToken =
50
+ | 'AVG'
51
+ | 'AVG_STRICT'
52
+ | 'CHILD_COUNT'
53
+ | 'LEAF_COUNT'
54
+ | 'MAX'
55
+ | 'MIN'
56
+ | 'NULL'
57
+ | 'SINGLE'
58
+ | 'SUM'
59
+ | 'SUM_STRICT'
60
+ | 'UNIQUE';
61
+
63
62
  /**
64
63
  * @param dimension - dimension of aggregation
65
64
  * @param value - value of record on dimension
@@ -114,7 +113,7 @@ export class CubeField extends Field {
114
113
  //------------------------
115
114
  // Implementation
116
115
  //------------------------
117
- private parseAggregator(val: any): Aggregator {
116
+ private parseAggregator(val: Aggregator | AggregatorToken): Aggregator {
118
117
  if (isString(val)) {
119
118
  switch (val) {
120
119
  case 'AVG':
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xh/hoist",
3
- "version": "73.0.0-SNAPSHOT.1745976013413",
3
+ "version": "73.0.0-SNAPSHOT.1746050068813",
4
4
  "description": "Hoist add-on for building and deploying React Applications.",
5
5
  "repository": "github:xh/hoist-react",
6
6
  "homepage": "https://xh.io",
@@ -119,6 +119,8 @@ export class TrackService extends HoistService {
119
119
  msg: stripTags(options.message),
120
120
  clientUsername: XH.getUsername(),
121
121
  appVersion: XH.getEnv('clientVersion'),
122
+ loadId: XH.loadId,
123
+ tabId: XH.tabId,
122
124
  url: window.location.href,
123
125
  timestamp: Date.now()
124
126
  };