@xh/hoist 83.1.0 → 84.0.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 +76 -0
- package/admin/tabs/cluster/instances/logs/levels/LogLevelDialogModel.ts +106 -10
- package/admin/tabs/cluster/metrics/MetricsModel.ts +3 -3
- package/appcontainer/AppContainerModel.ts +1 -1
- package/appcontainer/README.md +20 -0
- package/assets.d.ts +34 -0
- package/build/types/cmp/ag-grid/AgGrid.d.ts +8 -19
- package/build/types/cmp/ag-grid/AgGridModel.d.ts +18 -5
- package/build/types/cmp/card/Card.d.ts +9 -4
- package/build/types/cmp/card/CardModel.d.ts +15 -2
- package/build/types/cmp/chart/Chart.d.ts +2 -2
- package/build/types/cmp/chart/ChartModel.d.ts +11 -1
- package/build/types/cmp/dataview/DataView.d.ts +4 -2
- package/build/types/cmp/dataview/DataViewModel.d.ts +16 -4
- package/build/types/cmp/filter/FilterChooserModel.d.ts +7 -1
- package/build/types/cmp/form/Form.d.ts +2 -1
- package/build/types/cmp/form/FormModel.d.ts +12 -0
- package/build/types/cmp/form/field/BaseFieldModel.d.ts +7 -0
- package/build/types/cmp/form/formfieldset/FormFieldSetModel.d.ts +7 -1
- package/build/types/cmp/grid/GridModel.d.ts +16 -1
- package/build/types/cmp/grid/GridSorter.d.ts +14 -0
- package/build/types/cmp/grid/Types.d.ts +18 -0
- package/build/types/cmp/grid/columns/Column.d.ts +40 -2
- package/build/types/cmp/grid/columns/ColumnGroup.d.ts +10 -0
- package/build/types/cmp/grouping/GroupingChooserModel.d.ts +9 -2
- package/build/types/cmp/layout/Box.d.ts +19 -7
- package/build/types/cmp/layout/Frame.d.ts +17 -5
- package/build/types/cmp/loadingindicator/LoadingIndicator.d.ts +6 -4
- package/build/types/cmp/pinpad/PinPadModel.d.ts +6 -1
- package/build/types/cmp/spinner/Spinner.d.ts +31 -10
- package/build/types/cmp/tab/TabContainerModel.d.ts +11 -0
- package/build/types/cmp/tab/TabModel.d.ts +7 -0
- package/build/types/cmp/tab/Types.d.ts +4 -0
- package/build/types/cmp/treemap/TreeMapModel.d.ts +3 -3
- package/build/types/cmp/viewmanager/ViewManagerModel.d.ts +9 -0
- package/build/types/cmp/zoneGrid/ZoneGridModel.d.ts +22 -3
- package/build/types/cmp/zoneGrid/impl/ZoneMapperModel.d.ts +6 -0
- package/build/types/core/HoistComponent.d.ts +29 -8
- package/build/types/core/HoistProps.d.ts +9 -3
- package/build/types/core/load/LoadSpec.d.ts +1 -1
- package/build/types/core/persist/provider/ViewManagerProvider.d.ts +7 -0
- package/build/types/data/Store.d.ts +35 -1
- package/build/types/data/StoreSelectionModel.d.ts +18 -2
- package/build/types/data/cube/Cube.d.ts +26 -6
- package/build/types/data/cube/Query.d.ts +10 -0
- package/build/types/data/cube/View.d.ts +21 -2
- package/build/types/data/cube/aggregate/Aggregator.d.ts +13 -0
- package/build/types/data/cube/aggregate/AverageAggregator.d.ts +1 -0
- package/build/types/data/cube/aggregate/AverageStrictAggregator.d.ts +1 -0
- package/build/types/data/cube/aggregate/ChildCountAggregator.d.ts +1 -0
- package/build/types/data/cube/aggregate/LeafCountAggregator.d.ts +1 -0
- package/build/types/data/cube/aggregate/MaxAggregator.d.ts +1 -0
- package/build/types/data/cube/aggregate/MinAggregator.d.ts +1 -0
- package/build/types/data/cube/aggregate/NullAggregator.d.ts +1 -0
- package/build/types/data/cube/aggregate/SingleAggregator.d.ts +1 -0
- package/build/types/data/cube/aggregate/SumAggregator.d.ts +1 -0
- package/build/types/data/cube/aggregate/SumStrictAggregator.d.ts +1 -0
- package/build/types/data/cube/aggregate/UniqueAggregator.d.ts +1 -0
- package/build/types/data/filter/BaseFilterFieldSpec.d.ts +9 -0
- package/build/types/data/filter/Types.d.ts +12 -0
- package/build/types/desktop/cmp/button/AppMenuButton.d.ts +5 -0
- package/build/types/desktop/cmp/button/Button.d.ts +5 -1
- package/build/types/desktop/cmp/dash/canvas/DashCanvasModel.d.ts +12 -3
- package/build/types/desktop/cmp/dash/container/DashContainerModel.d.ts +9 -0
- package/build/types/desktop/cmp/dock/DockViewModel.d.ts +7 -0
- package/build/types/desktop/cmp/filechooser/FileChooserModel.d.ts +8 -0
- package/build/types/desktop/cmp/grid/editors/BooleanEditor.d.ts +1 -0
- package/build/types/desktop/cmp/grid/editors/DateEditor.d.ts +1 -0
- package/build/types/desktop/cmp/grid/editors/NumberEditor.d.ts +1 -0
- package/build/types/desktop/cmp/grid/editors/SelectEditor.d.ts +1 -0
- package/build/types/desktop/cmp/grid/editors/TextAreaEditor.d.ts +1 -0
- package/build/types/desktop/cmp/grid/editors/TextEditor.d.ts +1 -0
- package/build/types/desktop/cmp/input/Picker.d.ts +1 -1
- package/build/types/desktop/cmp/input/SegmentedControl.d.ts +16 -2
- package/build/types/desktop/cmp/leftrightchooser/LeftRightChooserModel.d.ts +7 -0
- package/build/types/desktop/cmp/modalsupport/ModalSupportModel.d.ts +28 -2
- package/build/types/desktop/cmp/panel/Panel.d.ts +5 -2
- package/build/types/desktop/cmp/panel/PanelModel.d.ts +12 -2
- package/build/types/desktop/cmp/rest/RestGrid.d.ts +10 -0
- package/build/types/desktop/cmp/rest/RestGridModel.d.ts +9 -1
- package/build/types/desktop/cmp/toolbar/Toolbar.d.ts +4 -1
- package/build/types/format/FormatDate.d.ts +4 -4
- package/build/types/icon/Icon.d.ts +3 -0
- package/build/types/kit/blueprint/Wrappers.d.ts +12 -1
- package/build/types/mobile/cmp/navigator/NavigatorModel.d.ts +8 -0
- package/build/types/mobile/cmp/navigator/PageModel.d.ts +7 -0
- package/build/types/mobile/cmp/panel/DialogPanel.d.ts +0 -2
- package/build/types/security/BaseOAuthClient.d.ts +9 -0
- package/build/types/security/authzero/AuthZeroClient.d.ts +6 -0
- package/build/types/security/msal/MsalClient.d.ts +6 -0
- package/build/types/svc/FetchService.d.ts +10 -7
- package/build/types/svc/TraceService.d.ts +17 -2
- package/build/types/utils/async/Timer.d.ts +6 -0
- package/build/types/utils/js/LangUtils.d.ts +1 -1
- package/build/types/utils/js/TestUtils.d.ts +1 -1
- package/build/types/utils/react/index.d.ts +0 -1
- package/build/types/utils/telemetry/Span.d.ts +12 -2
- package/cmp/ag-grid/AgGrid.ts +8 -19
- package/cmp/ag-grid/AgGridModel.ts +18 -5
- package/cmp/card/Card.ts +9 -4
- package/cmp/card/CardModel.ts +15 -2
- package/cmp/chart/Chart.ts +2 -2
- package/cmp/chart/ChartModel.ts +11 -1
- package/cmp/dataview/DataView.ts +4 -2
- package/cmp/dataview/DataViewModel.ts +16 -4
- package/cmp/filter/FilterChooserModel.ts +7 -1
- package/cmp/form/Form.ts +2 -1
- package/cmp/form/FormModel.ts +12 -0
- package/cmp/form/README.md +13 -0
- package/cmp/form/field/BaseFieldModel.ts +7 -0
- package/cmp/form/formfieldset/FormFieldSetModel.ts +7 -1
- package/cmp/grid/Grid.scss +14 -8
- package/cmp/grid/GridModel.ts +16 -1
- package/cmp/grid/GridSorter.ts +14 -0
- package/cmp/grid/README.md +12 -0
- package/cmp/grid/Types.ts +18 -0
- package/cmp/grid/columns/Column.ts +40 -2
- package/cmp/grid/columns/ColumnGroup.ts +10 -0
- package/cmp/grouping/GroupingChooserModel.ts +9 -2
- package/cmp/layout/Box.ts +19 -7
- package/cmp/layout/Frame.ts +17 -5
- package/cmp/layout/README.md +16 -21
- package/cmp/loadingindicator/LoadingIndicator.scss +1 -1
- package/cmp/loadingindicator/LoadingIndicator.ts +11 -9
- package/cmp/pinpad/PinPadModel.ts +6 -1
- package/cmp/spinner/Spinner.scss +13 -0
- package/cmp/spinner/Spinner.ts +58 -20
- package/cmp/tab/TabContainerModel.ts +11 -0
- package/cmp/tab/TabModel.ts +7 -0
- package/cmp/tab/Types.ts +4 -0
- package/cmp/treemap/TreeMapModel.ts +3 -3
- package/cmp/viewmanager/ViewManagerModel.ts +9 -0
- package/cmp/zoneGrid/ZoneGridModel.ts +22 -3
- package/cmp/zoneGrid/impl/ZoneMapperModel.ts +6 -0
- package/core/ExceptionHandler.ts +1 -1
- package/core/HoistComponent.ts +36 -11
- package/core/HoistProps.ts +9 -3
- package/core/README.md +68 -6
- package/core/impl/InstanceManager.ts +1 -0
- package/core/load/LoadSpec.ts +1 -1
- package/core/persist/provider/ViewManagerProvider.ts +7 -0
- package/data/README.md +48 -124
- package/data/Store.ts +35 -1
- package/data/StoreSelectionModel.ts +18 -2
- package/data/cube/Cube.ts +26 -6
- package/data/cube/Query.ts +10 -0
- package/data/cube/README.md +236 -0
- package/data/cube/View.ts +21 -2
- package/data/cube/aggregate/Aggregator.ts +13 -0
- package/data/cube/aggregate/AverageAggregator.ts +1 -0
- package/data/cube/aggregate/AverageStrictAggregator.ts +1 -0
- package/data/cube/aggregate/ChildCountAggregator.ts +1 -0
- package/data/cube/aggregate/LeafCountAggregator.ts +1 -0
- package/data/cube/aggregate/MaxAggregator.ts +1 -0
- package/data/cube/aggregate/MinAggregator.ts +1 -0
- package/data/cube/aggregate/NullAggregator.ts +1 -0
- package/data/cube/aggregate/SingleAggregator.ts +1 -0
- package/data/cube/aggregate/SumAggregator.ts +1 -0
- package/data/cube/aggregate/SumStrictAggregator.ts +1 -0
- package/data/cube/aggregate/UniqueAggregator.ts +1 -0
- package/data/filter/BaseFilterFieldSpec.ts +9 -0
- package/data/filter/Types.ts +12 -0
- package/desktop/README.md +131 -9
- package/desktop/appcontainer/AboutDialog.ts +2 -0
- package/desktop/appcontainer/Banner.ts +5 -2
- package/desktop/appcontainer/ChangelogDialog.ts +1 -0
- package/desktop/appcontainer/ExceptionDialog.ts +4 -0
- package/desktop/appcontainer/ExceptionDialogDetails.ts +4 -1
- package/desktop/appcontainer/FeedbackDialog.ts +4 -1
- package/desktop/appcontainer/ImpersonationBar.ts +4 -0
- package/desktop/appcontainer/LockoutPanel.ts +4 -1
- package/desktop/appcontainer/LoginPanel.ts +7 -3
- package/desktop/appcontainer/Message.ts +9 -3
- package/desktop/appcontainer/OptionsDialog.ts +3 -1
- package/desktop/appcontainer/VersionBar.ts +1 -0
- package/desktop/appcontainer/suspend/IdlePanel.ts +4 -4
- package/desktop/appcontainer/suspend/SuspendPanel.ts +3 -0
- package/desktop/cmp/button/AppMenuButton.ts +5 -0
- package/desktop/cmp/button/Button.ts +14 -4
- package/desktop/cmp/dash/README.md +14 -0
- package/desktop/cmp/dash/canvas/DashCanvasModel.ts +12 -3
- package/desktop/cmp/dash/container/DashContainerModel.ts +9 -0
- package/desktop/cmp/dock/DockViewModel.ts +7 -0
- package/desktop/cmp/filechooser/FileChooserModel.ts +9 -2
- package/desktop/cmp/grid/editors/BooleanEditor.ts +1 -0
- package/desktop/cmp/grid/editors/DateEditor.ts +1 -0
- package/desktop/cmp/grid/editors/NumberEditor.ts +1 -0
- package/desktop/cmp/grid/editors/SelectEditor.ts +1 -0
- package/desktop/cmp/grid/editors/TextAreaEditor.ts +1 -0
- package/desktop/cmp/grid/editors/TextEditor.ts +1 -0
- package/desktop/cmp/input/Picker.ts +2 -2
- package/desktop/cmp/input/SegmentedControl.ts +20 -2
- package/desktop/cmp/leftrightchooser/LeftRightChooserModel.ts +7 -0
- package/desktop/cmp/modalsupport/ModalSupportModel.ts +31 -2
- package/desktop/cmp/panel/Panel.ts +29 -21
- package/desktop/cmp/panel/PanelModel.ts +12 -2
- package/desktop/cmp/panel/README.md +20 -0
- package/desktop/cmp/rest/RestGrid.ts +10 -0
- package/desktop/cmp/rest/RestGridModel.ts +9 -1
- package/desktop/cmp/toolbar/Toolbar.ts +9 -2
- package/desktop/cmp/viewmanager/ViewManager.ts +1 -1
- package/docs/README.md +9 -4
- package/docs/coding-conventions.md +29 -21
- package/docs/doc-registry.json +31 -15
- package/docs/planning/docs-roadmap-log.md +11 -0
- package/docs/planning/docs-roadmap.md +1 -0
- package/docs/upgrade-notes/v84-upgrade-notes.md +136 -0
- package/docs/version-compatibility.md +2 -0
- package/format/FormatDate.ts +4 -4
- package/icon/Icon.ts +9 -0
- package/icon/README.md +62 -22
- package/icon/index.ts +24 -0
- package/kit/README.md +8 -2
- package/kit/blueprint/Wrappers.ts +12 -1
- package/mcp/README.md +47 -26
- package/mcp/cli/ts.ts +39 -4
- package/mcp/data/ts-registry.ts +57 -17
- package/mcp/tools/typescript.ts +32 -4
- package/mobile/appcontainer/AboutDialog.ts +3 -0
- package/mobile/appcontainer/Banner.ts +2 -0
- package/mobile/appcontainer/ExceptionDialog.ts +4 -0
- package/mobile/appcontainer/ExceptionDialogDetails.ts +1 -0
- package/mobile/appcontainer/FeedbackDialog.ts +4 -1
- package/mobile/appcontainer/ImpersonationBar.ts +2 -0
- package/mobile/appcontainer/LockoutPanel.ts +2 -0
- package/mobile/appcontainer/LoginPanel.ts +7 -3
- package/mobile/appcontainer/Message.ts +9 -3
- package/mobile/appcontainer/OptionsDialog.ts +5 -1
- package/mobile/appcontainer/VersionBar.ts +1 -0
- package/mobile/appcontainer/suspend/IdlePanel.ts +5 -6
- package/mobile/appcontainer/suspend/SuspendPanel.ts +3 -0
- package/mobile/cmp/navigator/NavigatorModel.ts +8 -0
- package/mobile/cmp/navigator/PageModel.ts +7 -0
- package/mobile/cmp/panel/DialogPanel.ts +0 -2
- package/package.json +11 -11
- package/security/BaseOAuthClient.ts +9 -0
- package/security/authzero/AuthZeroClient.ts +6 -0
- package/security/msal/MsalClient.ts +6 -0
- package/styles/vars.scss +14 -0
- package/svc/FetchService.ts +25 -15
- package/svc/README.md +39 -9
- package/svc/TraceService.ts +69 -11
- package/utils/README.md +0 -1
- package/utils/async/Timer.ts +6 -0
- package/utils/js/LangUtils.ts +1 -1
- package/utils/js/TestUtils.ts +1 -1
- package/utils/react/index.ts +0 -1
- package/utils/telemetry/Span.ts +21 -4
- package/build/types/utils/react/ClassName.d.ts +0 -14
- package/utils/react/ClassName.ts +0 -24
|
@@ -37,11 +37,13 @@ export const impersonationBar = hoistCmp.factory({
|
|
|
37
37
|
enableFullscreen: true,
|
|
38
38
|
placeholder: 'Select a user to impersonate...',
|
|
39
39
|
createMessageFn: q => `Impersonate new user "${q}"`,
|
|
40
|
+
testId: 'xh-impersonation-target',
|
|
40
41
|
onCommit: model.onCommit
|
|
41
42
|
}),
|
|
42
43
|
button({
|
|
43
44
|
icon: Icon.close(),
|
|
44
45
|
minimal: true,
|
|
46
|
+
testId: 'xh-impersonation-exit-btn',
|
|
45
47
|
onClick: model.onClose
|
|
46
48
|
})
|
|
47
49
|
]
|
|
@@ -39,6 +39,7 @@ export const lockoutPanel = hoistCmp.factory<AppContainerModel>({
|
|
|
39
39
|
button({
|
|
40
40
|
icon: Icon.logout(),
|
|
41
41
|
text: 'Logout',
|
|
42
|
+
testId: 'xh-lockout-logout-btn',
|
|
42
43
|
omit: !appSpec.enableLogout,
|
|
43
44
|
onClick: () => XH.logoutAsync()
|
|
44
45
|
}),
|
|
@@ -46,6 +47,7 @@ export const lockoutPanel = hoistCmp.factory<AppContainerModel>({
|
|
|
46
47
|
button({
|
|
47
48
|
icon: Icon.impersonate(),
|
|
48
49
|
text: 'End Impersonation',
|
|
50
|
+
testId: 'xh-lockout-end-impersonation-btn',
|
|
49
51
|
omit: !identityService.isImpersonating,
|
|
50
52
|
onClick: () => identityService.endImpersonateAsync()
|
|
51
53
|
})
|
|
@@ -30,6 +30,7 @@ export const loginPanel = hoistCmp.factory({
|
|
|
30
30
|
|
|
31
31
|
return panel({
|
|
32
32
|
className: 'xh-login',
|
|
33
|
+
testId: 'xh-login',
|
|
33
34
|
items: [
|
|
34
35
|
toolbar(filler(), XH.clientAppName, filler()),
|
|
35
36
|
panel({
|
|
@@ -44,14 +45,16 @@ export const loginPanel = hoistCmp.factory({
|
|
|
44
45
|
placeholder: 'Username',
|
|
45
46
|
autoComplete: 'username',
|
|
46
47
|
autoCapitalize: 'none',
|
|
47
|
-
commitOnChange: true
|
|
48
|
+
commitOnChange: true,
|
|
49
|
+
testId: 'xh-login-username'
|
|
48
50
|
}),
|
|
49
51
|
textInput({
|
|
50
52
|
bind: 'password',
|
|
51
53
|
placeholder: 'Password',
|
|
52
54
|
autoComplete: 'current-password',
|
|
53
55
|
type: 'password',
|
|
54
|
-
commitOnChange: true
|
|
56
|
+
commitOnChange: true,
|
|
57
|
+
testId: 'xh-login-password'
|
|
55
58
|
})
|
|
56
59
|
]
|
|
57
60
|
}),
|
|
@@ -69,7 +72,8 @@ export const loginPanel = hoistCmp.factory({
|
|
|
69
72
|
icon: Icon.login(),
|
|
70
73
|
text: loginInProgress ? 'Please wait...' : 'Login',
|
|
71
74
|
disabled: !isValid || loginInProgress,
|
|
72
|
-
onClick: () => model.submitAsync()
|
|
75
|
+
onClick: () => model.submitAsync(),
|
|
76
|
+
testId: 'xh-login-btn'
|
|
73
77
|
})
|
|
74
78
|
]
|
|
75
79
|
})
|
|
@@ -31,7 +31,7 @@ export const message = hoistCmp.factory({
|
|
|
31
31
|
if (!isOpen) return null;
|
|
32
32
|
|
|
33
33
|
if (cancelProps) {
|
|
34
|
-
buttons.push(button({minimal: true, ...cancelProps}));
|
|
34
|
+
buttons.push(button({testId: 'xh-message-cancel-btn', minimal: true, ...cancelProps}));
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
if (cancelProps || confirmProps) {
|
|
@@ -46,8 +46,12 @@ export const message = hoistCmp.factory({
|
|
|
46
46
|
// Merge in formModel.isValid here in render stage to get reactivity.
|
|
47
47
|
buttons.push(
|
|
48
48
|
formModel
|
|
49
|
-
? button({
|
|
50
|
-
|
|
49
|
+
? button({
|
|
50
|
+
testId: 'xh-message-confirm-btn',
|
|
51
|
+
...confirmProps,
|
|
52
|
+
disabled: !formModel.isValid
|
|
53
|
+
})
|
|
54
|
+
: button({testId: 'xh-message-confirm-btn', ...confirmProps})
|
|
51
55
|
);
|
|
52
56
|
}
|
|
53
57
|
|
|
@@ -76,6 +80,7 @@ const inputCmp = hoistCmp.factory<MessageModel>(({model}) => {
|
|
|
76
80
|
items.push(
|
|
77
81
|
formField({
|
|
78
82
|
field: 'value',
|
|
83
|
+
testId: 'xh-message-value',
|
|
79
84
|
item: withDefault(input.item, textInput())
|
|
80
85
|
})
|
|
81
86
|
);
|
|
@@ -85,6 +90,7 @@ const inputCmp = hoistCmp.factory<MessageModel>(({model}) => {
|
|
|
85
90
|
formField({
|
|
86
91
|
label: extraConfirmLabel,
|
|
87
92
|
field: 'extraConfirm',
|
|
93
|
+
testId: 'xh-message-extra-confirm',
|
|
88
94
|
item: textInput()
|
|
89
95
|
})
|
|
90
96
|
);
|
|
@@ -30,6 +30,7 @@ export const optionsDialog = hoistCmp.factory({
|
|
|
30
30
|
title: `${XH.clientAppName} Options`,
|
|
31
31
|
icon: Icon.options(),
|
|
32
32
|
className: 'xh-options-dialog',
|
|
33
|
+
testId: 'xh-options-dialog',
|
|
33
34
|
isOpen: true,
|
|
34
35
|
item: [
|
|
35
36
|
mask({bind: loadTask, spinner: true}),
|
|
@@ -43,7 +44,8 @@ export const optionsDialog = hoistCmp.factory({
|
|
|
43
44
|
restoreDefaultsButton({
|
|
44
45
|
intent: 'danger',
|
|
45
46
|
minimal: false,
|
|
46
|
-
className: 'xh-options-dialog__restore-defaults-btn'
|
|
47
|
+
className: 'xh-options-dialog__restore-defaults-btn',
|
|
48
|
+
testId: 'xh-options-restore-defaults-btn'
|
|
47
49
|
})
|
|
48
50
|
]
|
|
49
51
|
})
|
|
@@ -54,6 +56,7 @@ export const optionsDialog = hoistCmp.factory({
|
|
|
54
56
|
button({
|
|
55
57
|
text: 'Cancel',
|
|
56
58
|
minimal: true,
|
|
59
|
+
testId: 'xh-options-cancel-btn',
|
|
57
60
|
onClick: () => model.hide()
|
|
58
61
|
}),
|
|
59
62
|
button({
|
|
@@ -62,6 +65,7 @@ export const optionsDialog = hoistCmp.factory({
|
|
|
62
65
|
intent: 'primary',
|
|
63
66
|
outlined: true,
|
|
64
67
|
disabled: !formModel.isDirty,
|
|
68
|
+
testId: 'xh-options-save-btn',
|
|
65
69
|
onClick: () => model.saveAsync()
|
|
66
70
|
})
|
|
67
71
|
]
|
|
@@ -5,15 +5,12 @@
|
|
|
5
5
|
* Copyright © 2026 Extremely Heavy Industries Inc.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {panel} from '@xh/hoist/mobile/cmp/panel';
|
|
8
|
+
import {div, img, p, vframe} from '@xh/hoist/cmp/layout';
|
|
9
|
+
import {hoistCmp, XH} from '@xh/hoist/core';
|
|
11
10
|
import {Icon} from '@xh/hoist/icon';
|
|
12
11
|
import {button} from '@xh/hoist/mobile/cmp/button';
|
|
13
|
-
|
|
14
12
|
import './IdlePanel.scss';
|
|
15
|
-
|
|
16
|
-
// @ts-ignore
|
|
13
|
+
import {panel} from '@xh/hoist/mobile/cmp/panel';
|
|
17
14
|
import idleImage from './IdlePanelImage.png';
|
|
18
15
|
|
|
19
16
|
/**
|
|
@@ -28,6 +25,7 @@ export const idlePanel = hoistCmp.factory({
|
|
|
28
25
|
render({onReactivate}) {
|
|
29
26
|
return panel({
|
|
30
27
|
className: 'xh-idle-panel',
|
|
28
|
+
testId: 'xh-idle-panel',
|
|
31
29
|
title: `${XH.clientAppName} is sleeping`,
|
|
32
30
|
icon: Icon.moon(),
|
|
33
31
|
items: [
|
|
@@ -47,6 +45,7 @@ export const idlePanel = hoistCmp.factory({
|
|
|
47
45
|
item: button({
|
|
48
46
|
text: "I'm back!",
|
|
49
47
|
flex: 1,
|
|
48
|
+
testId: 'xh-idle-reactivate-btn',
|
|
50
49
|
onClick: onReactivate
|
|
51
50
|
})
|
|
52
51
|
})
|
|
@@ -53,6 +53,7 @@ export const suspendPanel = hoistCmp.factory<AppContainerModel>({
|
|
|
53
53
|
|
|
54
54
|
return panel({
|
|
55
55
|
className: 'xh-suspend-panel',
|
|
56
|
+
testId: 'xh-suspend-panel',
|
|
56
57
|
title,
|
|
57
58
|
icon,
|
|
58
59
|
items: [
|
|
@@ -74,12 +75,14 @@ export const suspendPanel = hoistCmp.factory<AppContainerModel>({
|
|
|
74
75
|
icon: Icon.refresh(),
|
|
75
76
|
intent: 'primary',
|
|
76
77
|
flex: 1,
|
|
78
|
+
testId: 'xh-suspend-reload-btn',
|
|
77
79
|
onClick: () => XH.reloadApp()
|
|
78
80
|
}),
|
|
79
81
|
button({
|
|
80
82
|
text: 'More Details',
|
|
81
83
|
icon: Icon.detail(),
|
|
82
84
|
minimal: true,
|
|
85
|
+
testId: 'xh-suspend-details-btn',
|
|
83
86
|
omit: !exception,
|
|
84
87
|
onClick: () =>
|
|
85
88
|
XH.exceptionHandler.showExceptionDetails(exception)
|
|
@@ -14,6 +14,14 @@ import '@xh/hoist/mobile/register';
|
|
|
14
14
|
import {PageConfig, PageModel} from './PageModel';
|
|
15
15
|
import {findScrollableParent, isDraggableEl} from './impl/Utils';
|
|
16
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Configuration for a {@link NavigatorModel} - the primary stack-based navigation controller
|
|
19
|
+
* for mobile Hoist apps. Supports swipe-based page transitions, pull-to-refresh, and
|
|
20
|
+
* configurable render/refresh strategies.
|
|
21
|
+
*
|
|
22
|
+
* @see NavigatorModel
|
|
23
|
+
* @see PageConfig
|
|
24
|
+
*/
|
|
17
25
|
export interface NavigatorConfig {
|
|
18
26
|
/** Configs for PageModels, representing all supported pages within this Navigator/App. */
|
|
19
27
|
pages: PageConfig[];
|
|
@@ -19,6 +19,13 @@ import {warnIf, withDefault} from '@xh/hoist/utils/js';
|
|
|
19
19
|
import {stringify} from 'qs';
|
|
20
20
|
import {NavigatorModel} from './NavigatorModel';
|
|
21
21
|
|
|
22
|
+
/**
|
|
23
|
+
* Configuration for a {@link PageModel} - a single page within a {@link NavigatorModel}.
|
|
24
|
+
* Passed as entries in the `pages` array of a {@link NavigatorConfig}.
|
|
25
|
+
*
|
|
26
|
+
* @see PageModel
|
|
27
|
+
* @see NavigatorConfig
|
|
28
|
+
*/
|
|
22
29
|
export interface PageConfig {
|
|
23
30
|
/** Unique ID. Must match a configured Router5 route name. */
|
|
24
31
|
id: string;
|
|
@@ -20,8 +20,6 @@ export interface DialogPanelProps extends PanelProps {
|
|
|
20
20
|
*
|
|
21
21
|
* These views do not participate in navigation or routing, and are used for showing fullscreen
|
|
22
22
|
* views outside of the Navigator / TabContainer context.
|
|
23
|
-
*
|
|
24
|
-
* @see FullscreenPanel for a true fullscreen, non-floating alternative.
|
|
25
23
|
*/
|
|
26
24
|
export const [DialogPanel, dialogPanel] = hoistCmp.withFactory<DialogPanelProps>({
|
|
27
25
|
displayName: 'DialogPanel',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xh/hoist",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "84.0.1",
|
|
4
4
|
"description": "Hoist add-on for building and deploying React Applications.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -38,17 +38,17 @@
|
|
|
38
38
|
]
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@auth0/auth0-spa-js": "~2.
|
|
41
|
+
"@auth0/auth0-spa-js": "~2.19.0",
|
|
42
42
|
"@azure/msal-browser": "~4.29.0",
|
|
43
43
|
"@blueprintjs/core": "^6.3.2",
|
|
44
44
|
"@blueprintjs/datetime": "^6.0.6",
|
|
45
|
-
"@fortawesome/fontawesome-pro": "^
|
|
46
|
-
"@fortawesome/fontawesome-svg-core": "^
|
|
47
|
-
"@fortawesome/pro-light-svg-icons": "^
|
|
48
|
-
"@fortawesome/pro-regular-svg-icons": "^
|
|
49
|
-
"@fortawesome/pro-solid-svg-icons": "^
|
|
50
|
-
"@fortawesome/pro-thin-svg-icons": "^
|
|
51
|
-
"@fortawesome/react-fontawesome": "^
|
|
45
|
+
"@fortawesome/fontawesome-pro": "^7.2.0",
|
|
46
|
+
"@fortawesome/fontawesome-svg-core": "^7.2.0",
|
|
47
|
+
"@fortawesome/pro-light-svg-icons": "^7.2.0",
|
|
48
|
+
"@fortawesome/pro-regular-svg-icons": "^7.2.0",
|
|
49
|
+
"@fortawesome/pro-solid-svg-icons": "^7.2.0",
|
|
50
|
+
"@fortawesome/pro-thin-svg-icons": "^7.2.0",
|
|
51
|
+
"@fortawesome/react-fontawesome": "^3.2.0",
|
|
52
52
|
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
53
53
|
"@onsenui/fastclick": "~1.1.1",
|
|
54
54
|
"@popperjs/core": "~2.11.0",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"commander": "^14.0.3",
|
|
60
60
|
"core-js": "3.x",
|
|
61
61
|
"debounce-promise": "~3.1.0",
|
|
62
|
-
"dompurify": "~3.
|
|
62
|
+
"dompurify": "~3.4.0",
|
|
63
63
|
"fast-deep-equal": "~3.1.1",
|
|
64
64
|
"filesize": "~11.0.2",
|
|
65
65
|
"golden-layout": "~1.5.9",
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
"inter-ui": "~4.1.1",
|
|
68
68
|
"jquery": "3.x",
|
|
69
69
|
"jwt-decode": "~4.0.0",
|
|
70
|
-
"lodash": "~4.
|
|
70
|
+
"lodash": "~4.18.0",
|
|
71
71
|
"lodash-inflection": "~1.5.0",
|
|
72
72
|
"mobx": "~6.15.0",
|
|
73
73
|
"mobx-react-lite": "~4.1.0",
|
|
@@ -20,6 +20,15 @@ import ShortUniqueId from 'short-unique-id';
|
|
|
20
20
|
|
|
21
21
|
export type LoginMethod = 'REDIRECT' | 'POPUP';
|
|
22
22
|
|
|
23
|
+
/**
|
|
24
|
+
* Base configuration shared by all OAuth client implementations. Extended by
|
|
25
|
+
* {@link MsalClientConfig} and {@link AuthZeroClientConfig} with provider-specific options.
|
|
26
|
+
*
|
|
27
|
+
* See the security package README (`security/README.md`) for authentication architecture
|
|
28
|
+
* and setup guidance.
|
|
29
|
+
*
|
|
30
|
+
* @see BaseOAuthClient
|
|
31
|
+
*/
|
|
23
32
|
export interface BaseOAuthClientConfig<S extends AccessTokenSpec> {
|
|
24
33
|
/** Client ID (GUID) of your app registered with your Oauth provider. */
|
|
25
34
|
clientId: string;
|
|
@@ -15,6 +15,12 @@ import {mergeDeep, throwIf} from '@xh/hoist/utils/js';
|
|
|
15
15
|
import {flatMap, union} from 'lodash';
|
|
16
16
|
import {BaseOAuthClient, BaseOAuthClientConfig} from '../BaseOAuthClient';
|
|
17
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Configuration for an {@link AuthZeroClient} - the Auth0 OAuth client.
|
|
20
|
+
* Extends {@link BaseOAuthClientConfig} with Auth0-specific options.
|
|
21
|
+
*
|
|
22
|
+
* @see AuthZeroClient
|
|
23
|
+
*/
|
|
18
24
|
export interface AuthZeroClientConfig extends BaseOAuthClientConfig<AuthZeroTokenSpec> {
|
|
19
25
|
/** Domain of your app registered with Auth0. */
|
|
20
26
|
domain: string;
|
|
@@ -23,6 +23,12 @@ import {flatMap, union, uniq} from 'lodash';
|
|
|
23
23
|
import {BaseOAuthClient, BaseOAuthClientConfig} from '../BaseOAuthClient';
|
|
24
24
|
import {AccessTokenSpec, TokenMap} from '../Types';
|
|
25
25
|
|
|
26
|
+
/**
|
|
27
|
+
* Configuration for a {@link MsalClient} - the Microsoft Entra ID (Azure AD) OAuth client.
|
|
28
|
+
* Extends {@link BaseOAuthClientConfig} with MSAL-specific options.
|
|
29
|
+
*
|
|
30
|
+
* @see MsalClient
|
|
31
|
+
*/
|
|
26
32
|
export interface MsalClientConfig extends BaseOAuthClientConfig<MsalTokenSpec> {
|
|
27
33
|
/**
|
|
28
34
|
* Authority for your organization's tenant: `https://login.microsoftonline.com/[tenantId]`.
|
package/styles/vars.scss
CHANGED
|
@@ -575,6 +575,11 @@ body {
|
|
|
575
575
|
--xh-grid-selected-row-text-color: var(--grid-selected-row-text-color, var(--xh-grid-text-color));
|
|
576
576
|
--xh-grid-summary-row-border-color: var(--grid-summary-row-border-color, var(--xh-grid-border-color));
|
|
577
577
|
--xh-grid-text-color: var(--grid-text-color, var(--xh-text-color));
|
|
578
|
+
--xh-grid-tooltip-bg: var(--grid-tooltip-bg, var(--xh-bg-alt));
|
|
579
|
+
--xh-grid-tooltip-border: var(--grid-tooltip-border, var(--xh-border-solid));
|
|
580
|
+
--xh-grid-tooltip-border-radius: var(--grid-tooltip-border-radius, var(--xh-border-radius-px));
|
|
581
|
+
--xh-grid-tooltip-max-width: var(--grid-tooltip-max-width, 400px);
|
|
582
|
+
--xh-grid-tooltip-padding: var(--grid-tooltip-padding, var(--xh-pad-half-px));
|
|
578
583
|
--xh-grid-tree-indent: var(--grid-tree-indent, 1.2em);
|
|
579
584
|
--xh-grid-tree-icon-px: var(--grid-tree-icon-px, 10px);
|
|
580
585
|
|
|
@@ -810,6 +815,15 @@ body {
|
|
|
810
815
|
}
|
|
811
816
|
|
|
812
817
|
|
|
818
|
+
//------------------------
|
|
819
|
+
// Spinner
|
|
820
|
+
//------------------------
|
|
821
|
+
--xh-spinner-color: var(--spinner-color, #{mc('blue-grey', '400')});
|
|
822
|
+
|
|
823
|
+
&.xh-dark {
|
|
824
|
+
--xh-spinner-color: var(--spinner-color, var(--xh-blue-gray));
|
|
825
|
+
}
|
|
826
|
+
|
|
813
827
|
//------------------------
|
|
814
828
|
// Tabs
|
|
815
829
|
//------------------------
|
package/svc/FetchService.ts
CHANGED
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
XH
|
|
15
15
|
} from '@xh/hoist/core';
|
|
16
16
|
import {Exception, HoistException, TimeoutException} from '@xh/hoist/exception';
|
|
17
|
-
import {formatTraceparent, Span} from '@xh/hoist/utils/telemetry';
|
|
17
|
+
import {formatTraceparent, Span, SpanConfig} from '@xh/hoist/utils/telemetry';
|
|
18
18
|
import {PromiseTimeoutSpec} from '@xh/hoist/promise';
|
|
19
19
|
import {isLocalDate, SECONDS} from '@xh/hoist/utils/datetime';
|
|
20
20
|
import {apiDeprecated, warnIf} from '@xh/hoist/utils/js';
|
|
@@ -34,8 +34,8 @@ export interface FetchServiceDefaults {
|
|
|
34
34
|
/**
|
|
35
35
|
* Service for making managed HTTP requests, both to the app's own Hoist server and to remote APIs.
|
|
36
36
|
*
|
|
37
|
-
* Typically accessed via `XH.fetchService` or the convenience methods on XH
|
|
38
|
-
* `XH.fetchJson()`, `XH.postJson()`, `XH.putJson()`, `XH.deleteJson()`
|
|
37
|
+
* Typically accessed via `XH.fetchService` or the convenience methods on XH - `XH.fetch()`,
|
|
38
|
+
* `XH.fetchJson()`, `XH.postJson()`, `XH.putJson()`, `XH.deleteJson()` - which delegate here.
|
|
39
39
|
*
|
|
40
40
|
* Wraps the standard Fetch API with CORS enabled, credentials included, and redirects followed.
|
|
41
41
|
* Provides JSON convenience methods (`fetchJson`, `postJson`, `putJson`, `patchJson`,
|
|
@@ -197,9 +197,16 @@ export class FetchService extends HoistService {
|
|
|
197
197
|
// Implementation
|
|
198
198
|
//-----------------------
|
|
199
199
|
private async fetchInternalAsync(opts: FetchOptions): Promise<any> {
|
|
200
|
+
// If a span spec provided create, wrap, and recurse
|
|
201
|
+
if (opts.span && !(opts.span instanceof Span)) {
|
|
202
|
+
return XH.traceService.withSpanAsync(opts.span, span =>
|
|
203
|
+
this.fetchInternalAsync({...opts, span})
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
|
|
200
207
|
opts = this.withCorrelationId(opts);
|
|
201
208
|
|
|
202
|
-
// Tracing
|
|
209
|
+
// Tracing - create span for this request.
|
|
203
210
|
const span = this.startFetchSpan(opts);
|
|
204
211
|
if (span) opts = {...opts, traceId: span.traceId};
|
|
205
212
|
|
|
@@ -219,7 +226,7 @@ export class FetchService extends HoistService {
|
|
|
219
226
|
ret = ret.track({...trackOptions, correlationId: correlationId as string, loadSpec});
|
|
220
227
|
}
|
|
221
228
|
|
|
222
|
-
// Tracing
|
|
229
|
+
// Tracing - end span on completion or failure.
|
|
223
230
|
if (span) {
|
|
224
231
|
ret = ret.then(
|
|
225
232
|
value => {
|
|
@@ -282,7 +289,9 @@ export class FetchService extends HoistService {
|
|
|
282
289
|
'Content-Type': isPost ? 'application/x-www-form-urlencoded' : 'text/plain',
|
|
283
290
|
...defaultHeaders,
|
|
284
291
|
...(opts.asJson ? {Accept: 'application/json'} : {}),
|
|
285
|
-
...(span
|
|
292
|
+
...(span
|
|
293
|
+
? {traceparent: formatTraceparent(span.traceId, span.spanId, span.sampled)}
|
|
294
|
+
: {}),
|
|
286
295
|
...opts.headers
|
|
287
296
|
};
|
|
288
297
|
|
|
@@ -418,13 +427,11 @@ export class FetchService extends HoistService {
|
|
|
418
427
|
const method = opts.method ?? (opts.params ? 'POST' : 'GET'),
|
|
419
428
|
url = this.extractUrlPath(opts.url);
|
|
420
429
|
|
|
421
|
-
if (url.endsWith('submitSpans')) return null;
|
|
422
|
-
|
|
423
430
|
return traceService.createSpan({
|
|
424
431
|
name: method,
|
|
425
432
|
kind: 'client',
|
|
426
|
-
parent: opts.span,
|
|
427
|
-
tags: {'http.request.method': method, 'url.path':
|
|
433
|
+
parent: opts.span as Span,
|
|
434
|
+
tags: {'http.request.method': method, 'url.path': url, 'xh.source': 'hoist'},
|
|
428
435
|
caller: this
|
|
429
436
|
});
|
|
430
437
|
}
|
|
@@ -455,7 +462,7 @@ export class FetchService extends HoistService {
|
|
|
455
462
|
}
|
|
456
463
|
}
|
|
457
464
|
|
|
458
|
-
private qsFilterFn = (
|
|
465
|
+
private qsFilterFn = (_prefix: string, value: any) => {
|
|
459
466
|
if (isDate(value)) return value.getTime();
|
|
460
467
|
if (isLocalDate(value)) return value.isoString;
|
|
461
468
|
return value;
|
|
@@ -757,10 +764,12 @@ export interface FetchOptions {
|
|
|
757
764
|
track?: string | TrackOptions;
|
|
758
765
|
|
|
759
766
|
/**
|
|
760
|
-
*
|
|
761
|
-
*
|
|
767
|
+
* Parent span for this fetch request. Use to nest fetch calls under a business-level span.
|
|
768
|
+
*
|
|
769
|
+
* Accepts an existing Span instance, a SpanConfig, or a string span name. When a SpanConfig or
|
|
770
|
+
* string is provided, FetchService will create and manage the parent span internally.
|
|
762
771
|
*/
|
|
763
|
-
span?: Span;
|
|
772
|
+
span?: Span | SpanConfig | string;
|
|
764
773
|
|
|
765
774
|
/**
|
|
766
775
|
* Distributed trace ID for this request. Set automatically by FetchService
|
|
@@ -787,7 +796,8 @@ export interface FetchException extends HoistException {
|
|
|
787
796
|
|
|
788
797
|
/**
|
|
789
798
|
* True if exception resulted from the fetch being aborted by fetchService, or the application.
|
|
790
|
-
* @see FetchService.abort
|
|
799
|
+
* @see FetchService.abort
|
|
800
|
+
* @see FetchOptions.autoAbortKey
|
|
791
801
|
*/
|
|
792
802
|
isFetchAborted: boolean;
|
|
793
803
|
}
|
package/svc/README.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Services Package
|
|
2
2
|
|
|
3
|
+
| Section | Description |
|
|
4
|
+
|---------|-------------|
|
|
5
|
+
| [Overview](#overview) | Purpose and principles of Hoist's built-in singleton services |
|
|
6
|
+
| [Architecture](#architecture) | Service hierarchy, installation, and access via XH |
|
|
7
|
+
| [Built-in Services](#built-in-services) | Reference for all 19 built-in services by category |
|
|
8
|
+
| [Configuration Keys Reference](#configuration-keys-reference) | Soft config keys controlling service behavior |
|
|
9
|
+
| [User Preference Keys Reference](#user-preference-keys-reference) | Per-user preference keys used by services |
|
|
10
|
+
| [Creating Custom Services](#creating-custom-services) | How to create and install application services |
|
|
11
|
+
| [Common Patterns](#common-patterns) | FetchService in loads, tracking, debounced search, WebSockets |
|
|
12
|
+
| [Common Pitfalls](#common-pitfalls) | Fetch errors, native fetch, missing loadSpec, and more |
|
|
13
|
+
| [Related Packages](#related-packages) | Links to core, cmp, promise, and admin packages |
|
|
14
|
+
|
|
3
15
|
## Overview
|
|
4
16
|
|
|
5
17
|
The `/svc/` package contains Hoist's built-in singleton services - classes that provide app-wide
|
|
@@ -116,15 +128,16 @@ override async doLoadAsync(loadSpec: LoadSpec) {
|
|
|
116
128
|
|
|
117
129
|
**Configuration Options:**
|
|
118
130
|
|
|
119
|
-
| Option | Type | Description
|
|
120
|
-
|
|
121
|
-
| `url` | string | Request URL (relative URLs appended to `XH.baseUrl`)
|
|
122
|
-
| `body` | any | Request body
|
|
123
|
-
| `params` | object | Query string parameters
|
|
124
|
-
| `headers` | object | Additional headers
|
|
125
|
-
| `timeout` | number | Timeout in ms (default 30000)
|
|
126
|
-
| `autoAbortKey` | string | Cancel previous requests with same key
|
|
127
|
-
| `loadSpec` | LoadSpec | Metadata for tracking
|
|
131
|
+
| Option | Type | Description |
|
|
132
|
+
|--------|------|---------------------------------------------------------------------------------------|
|
|
133
|
+
| `url` | string | Request URL (relative URLs appended to `XH.baseUrl`) |
|
|
134
|
+
| `body` | any | Request body |
|
|
135
|
+
| `params` | object | Query string parameters |
|
|
136
|
+
| `headers` | object | Additional headers |
|
|
137
|
+
| `timeout` | number | Timeout in ms (default 30000) |
|
|
138
|
+
| `autoAbortKey` | string | Cancel previous requests with same key |
|
|
139
|
+
| `loadSpec` | LoadSpec | Metadata for tracking |
|
|
140
|
+
| `span` | `Span \| string \| SpanConfig` | Parent span for tracing. Accepts an existing `Span`, a `SpanConfig`, or a string name |
|
|
128
141
|
|
|
129
142
|
**App-Level Defaults (`FetchService.defaults`):**
|
|
130
143
|
|
|
@@ -303,6 +316,12 @@ Client-side distributed tracing — creates spans for user actions and fetch cal
|
|
|
303
316
|
Hoist server. Exceptions thrown during traced operations include a `traceId` for correlation
|
|
304
317
|
with server-side traces. Controlled by the `xhTraceConfig` soft config. Requires hoist-core 37+.
|
|
305
318
|
|
|
319
|
+
Spans are sampled at creation time using `xhTraceConfig.sampleRules` — an ordered list of
|
|
320
|
+
tag-matching rules with glob pattern support. Child spans inherit their parent's sampling
|
|
321
|
+
decision. Unsampled spans are dropped before export unless they end in error and
|
|
322
|
+
`alwaysSampleErrors` is enabled. The `traceparent` header propagates the sampling flag to
|
|
323
|
+
the server. See the hoist-core tracing documentation for full sampling configuration details.
|
|
324
|
+
|
|
306
325
|
```typescript
|
|
307
326
|
// Wrap an async operation in a span (from any HoistBase subclass)
|
|
308
327
|
await this.withSpanAsync({name: 'loadPortfolio', caller: this}, async span => {
|
|
@@ -317,6 +336,17 @@ const result = this.withSpan({name: 'computeTotals', caller: this}, span => {
|
|
|
317
336
|
|
|
318
337
|
// Simple string-only config
|
|
319
338
|
await this.withSpanAsync('loadData', async span => { ... });
|
|
339
|
+
|
|
340
|
+
// Nest a fetch call under a parent span without manual span management.
|
|
341
|
+
// FetchService accepts a string, SpanConfig, or existing Span as the `span` option.
|
|
342
|
+
const data = await XH.fetchJson({
|
|
343
|
+
url: 'api/portfolio',
|
|
344
|
+
span: 'loadPortfolio'
|
|
345
|
+
});
|
|
346
|
+
const data = await XH.fetchJson({
|
|
347
|
+
url: 'api/portfolio',
|
|
348
|
+
span: {name: 'loadPortfolio', tags: {portfolioId: id}, caller: this}
|
|
349
|
+
});
|
|
320
350
|
```
|
|
321
351
|
|
|
322
352
|
**SpanConfig:**
|