@xh/hoist 59.0.3 → 59.2.0
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 +59 -2
- package/admin/AdminUtils.ts +23 -0
- package/admin/tabs/activity/clienterrors/ClientErrorsModel.ts +2 -1
- package/admin/tabs/activity/feedback/FeedbackPanel.ts +3 -3
- package/admin/tabs/activity/tracking/ActivityTrackingModel.ts +2 -1
- package/admin/tabs/activity/tracking/detail/ActivityDetailModel.ts +3 -2
- package/admin/tabs/general/alertBanner/AlertBannerModel.ts +2 -2
- package/admin/tabs/general/config/ConfigPanelModel.ts +2 -2
- package/admin/tabs/general/users/UserModel.ts +2 -2
- package/admin/tabs/monitor/MonitorResultsModel.ts +48 -11
- package/admin/tabs/monitor/MonitorResultsPanel.ts +71 -8
- package/admin/tabs/server/connectionpool/ConnPoolMonitorModel.ts +2 -2
- package/admin/tabs/server/ehcache/EhCacheModel.ts +2 -2
- package/admin/tabs/server/environment/ServerEnvModel.ts +3 -3
- package/admin/tabs/server/logLevel/LogLevelPanel.ts +3 -3
- package/admin/tabs/server/logViewer/LogViewerModel.ts +2 -2
- package/admin/tabs/server/memory/MemoryMonitorModel.ts +2 -2
- package/admin/tabs/server/services/ServiceModel.ts +3 -3
- package/admin/tabs/server/websocket/WebSocketModel.ts +3 -2
- package/admin/tabs/userData/jsonblob/JsonBlobModel.ts +2 -2
- package/admin/tabs/userData/prefs/PreferenceModel.ts +2 -2
- package/admin/tabs/userData/prefs/UserPreferencePanel.ts +3 -3
- package/appcontainer/ExceptionDialogModel.ts +6 -0
- package/cmp/ag-grid/AgGrid.scss +27 -5
- package/cmp/error/ErrorBoundary.ts +68 -0
- package/cmp/error/ErrorBoundaryModel.ts +77 -0
- package/cmp/grid/Grid.scss +10 -0
- package/cmp/grid/GridModel.ts +137 -33
- package/cmp/grid/columns/ColumnGroup.ts +11 -0
- package/cmp/markdown/Markdown.ts +32 -0
- package/cmp/markdown/index.ts +1 -0
- package/core/XH.ts +5 -9
- package/core/exception/ExceptionHandler.ts +15 -0
- package/data/RecordAction.ts +1 -1
- package/data/cube/Query.ts +37 -3
- package/data/cube/View.ts +16 -4
- package/data/cube/row/BaseRow.ts +2 -2
- package/desktop/appcontainer/AppContainer.ts +17 -3
- package/desktop/appcontainer/Banner.scss +25 -0
- package/desktop/appcontainer/Banner.ts +3 -2
- package/desktop/cmp/dash/canvas/impl/DashCanvasView.ts +4 -1
- package/desktop/cmp/dash/container/DashContainerModel.ts +3 -2
- package/desktop/cmp/dash/container/impl/DashContainerUtils.ts +4 -4
- package/desktop/cmp/dash/container/impl/DashContainerView.ts +2 -1
- package/desktop/cmp/dock/DockViewModel.ts +10 -8
- package/desktop/cmp/dock/impl/DockContainer.ts +1 -0
- package/desktop/cmp/dock/impl/DockView.ts +2 -1
- package/desktop/cmp/error/ErrorMessage.scss +1 -0
- package/desktop/cmp/error/ErrorMessage.ts +61 -23
- package/desktop/cmp/input/Checkbox.scss +13 -0
- package/desktop/cmp/input/Checkbox.ts +2 -0
- package/desktop/cmp/modalsupport/ModalSupport.scss +2 -0
- package/desktop/cmp/panel/Panel.ts +37 -14
- package/desktop/cmp/panel/PanelModel.ts +35 -7
- package/desktop/cmp/panel/impl/PanelHeader.scss +5 -0
- package/desktop/cmp/panel/impl/PanelHeader.ts +53 -38
- package/desktop/cmp/tab/impl/Tab.ts +2 -1
- package/dynamics/desktop.ts +15 -17
- package/dynamics/mobile.ts +10 -8
- package/inspector/Inspector.scss +5 -10
- package/inspector/InspectorPanel.ts +2 -0
- package/inspector/instances/InstancesModel.ts +1 -1
- package/kit/react-markdown/index.ts +11 -0
- package/mobile/appcontainer/AppContainer.ts +17 -3
- package/mobile/appcontainer/Banner.scss +25 -0
- package/mobile/appcontainer/Banner.ts +3 -2
- package/mobile/cmp/error/ErrorMessage.ts +58 -18
- package/mobile/cmp/menu/impl/Menu.scss +7 -1
- package/mobile/cmp/navigator/PageModel.ts +1 -0
- package/mobile/cmp/navigator/impl/Page.ts +2 -1
- package/mobile/cmp/panel/Panel.ts +5 -1
- package/mobile/cmp/tab/impl/Tab.ts +2 -1
- package/package.json +5 -3
- package/styles/vars.scss +2 -0
- package/svc/AlertBannerService.ts +2 -2
- package/svc/GridExportService.ts +1 -1
- package/admin/tabs/monitor/MonitorResultsToolbar.ts +0 -66
- package/appcontainer/ErrorBoundary.ts +0 -36
package/CHANGELOG.md
CHANGED
|
@@ -1,13 +1,70 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 59.2.0 - 2023-10-16
|
|
4
|
+
|
|
5
|
+
### 🎁 New Features
|
|
6
|
+
|
|
7
|
+
* New `DockViewConfig.onClose` hook invoked when a user attempts to remove a `DockContainer` view
|
|
8
|
+
* Add `GridModel` APIs to lookup and show / hide entire column groups
|
|
9
|
+
* Left / right borders are now rendered along `Grid` `ColumnGroup` edges by default. Control
|
|
10
|
+
with new boolean property `ColumnGroupSpec.borders`
|
|
11
|
+
* The Cube package has been enhanced to support `Query` specific post-processing functions. See
|
|
12
|
+
new properties `Query.omitFn`, `Query.bucketSpecFn` and `Query.lockFn`. These properties default
|
|
13
|
+
to their respective properties on `Cube`.
|
|
14
|
+
|
|
15
|
+
### 🐞 Bug Fixes
|
|
16
|
+
|
|
17
|
+
* `DashContainerModel` fixes:
|
|
18
|
+
* Fix bug where `addView` would throw when adding a view to a row or column
|
|
19
|
+
* Fix bug where `allowRemove` flag was dropped from state for containers
|
|
20
|
+
* Fix bug in `DockContainer` where adding / removing views would cause other views to be remounted
|
|
21
|
+
* Fix erroneous `GridModel` warning when using a tree column within a column group
|
|
22
|
+
* Fix regression to alert banners. Resume allowing elements as messages
|
|
23
|
+
|
|
24
|
+
### ⚙️ Typescript API Adjustments
|
|
25
|
+
|
|
26
|
+
* Add type for `ActionFnData.record`
|
|
27
|
+
|
|
28
|
+
## 59.1.0 - 2023-09-20
|
|
29
|
+
|
|
30
|
+
### 🎁 New Features
|
|
31
|
+
|
|
32
|
+
* Introduced new `ErrorBoundary` component for finer-grained application handling of React Errors.
|
|
33
|
+
* Hoist now wraps `Tab`, `DashCanvasView`, `DashContainerView`, `DockView`, and `Page` in an
|
|
34
|
+
`ErrorBoundary`. This provides better isolation of application content, minimizing the chance
|
|
35
|
+
that any individual component can crash the entire app.
|
|
36
|
+
* A new `PanelModel.errorBoundary` prop allows developers to opt-in to an `ErrorBoundary`
|
|
37
|
+
wrapper around the contents of any panel.
|
|
38
|
+
* `ErrorMessage` component now provides an ability to show additional exception details.
|
|
39
|
+
* Added new `Markdown` component for rendering Markdown formatted strings as markup. This includes
|
|
40
|
+
bundling `react-markdown` in Hoist.
|
|
41
|
+
* If your app already uses `react-markdown` or similar, we recommend updating to use the
|
|
42
|
+
new `Markdown` component exported by Hoist to benefit from future upgrades.
|
|
43
|
+
* Admin-managed alert banners leverage the new markdown component to support bold, italics and
|
|
44
|
+
links within alert messages.
|
|
45
|
+
* Improved and fixed up `Panel` headers, including:
|
|
46
|
+
* Added new `Panel.headerClassName` prop for easier CSS manipulation of panel's header.
|
|
47
|
+
* Improved `Panel.collapsedTitle` prop and added `Panel.collapsedIcon` prop. These two props now
|
|
48
|
+
fully govern header display when collapsed.
|
|
49
|
+
* Improved styling for disabled `checkbox` inputs.
|
|
50
|
+
|
|
51
|
+
### ⚙️ Technical
|
|
52
|
+
* `XH.showException` has been deprecated. Use similar methods on `XH.exceptionHandler` instead.
|
|
53
|
+
|
|
54
|
+
### 📚 Libraries
|
|
55
|
+
|
|
56
|
+
* numbro `2.3 -> 2.4`
|
|
57
|
+
* react-markdown `added @ 8.0`
|
|
58
|
+
* remark-breaks `added @ 3.0`
|
|
59
|
+
|
|
3
60
|
## 59.0.3 - 2023-08-25
|
|
4
61
|
|
|
5
62
|
### ⚙️ Technical
|
|
6
63
|
|
|
7
64
|
* New `XH.flags` property to govern experimental, hotfix, or otherwise provisional features.
|
|
8
65
|
|
|
9
|
-
* Provide temporary workaround to chromium bug effecting BigNumber.
|
|
10
|
-
`applyBigNumberWorkaround`.
|
|
66
|
+
* Provide temporary workaround to chromium bug effecting BigNumber. Enabled via flag
|
|
67
|
+
`applyBigNumberWorkaround`. See https://github.com/MikeMcl/bignumber.js/issues/354.
|
|
11
68
|
|
|
12
69
|
## 59.0.2 - 2023-08-24
|
|
13
70
|
|
|
@@ -0,0 +1,23 @@
|
|
|
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 © 2023 Extremely Heavy Industries Inc.
|
|
6
|
+
*/
|
|
7
|
+
import {XH} from '@xh/hoist/core';
|
|
8
|
+
import {LocalDate} from '@xh/hoist/utils/datetime';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Generate a standardized filename for an Admin module grid export, without datestamp.
|
|
12
|
+
*/
|
|
13
|
+
export function exportFilename(moduleName: string): string {
|
|
14
|
+
return `${XH.appCode}-${moduleName}`;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Generate a standardized filename for an Admin module grid export, with current datestamp.
|
|
19
|
+
* Returned as a closure to ensure current date is evaluated at export time.
|
|
20
|
+
*/
|
|
21
|
+
export function exportFilenameWithDate(moduleName: string): () => string {
|
|
22
|
+
return () => `${XH.appCode}-${moduleName}-${LocalDate.today()}`;
|
|
23
|
+
}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Copyright © 2023 Extremely Heavy Industries Inc.
|
|
6
6
|
*/
|
|
7
|
+
import {exportFilename} from '@xh/hoist/admin/AdminUtils';
|
|
7
8
|
import {FilterChooserModel} from '@xh/hoist/cmp/filter';
|
|
8
9
|
import {FormModel} from '@xh/hoist/cmp/form';
|
|
9
10
|
import {GridModel} from '@xh/hoist/cmp/grid';
|
|
@@ -43,7 +44,7 @@ export class ClientErrorsModel extends HoistModel {
|
|
|
43
44
|
colChooserModel: true,
|
|
44
45
|
enableExport: true,
|
|
45
46
|
exportOptions: {
|
|
46
|
-
filename:
|
|
47
|
+
filename: exportFilename('client-errors'),
|
|
47
48
|
columns: 'ALL'
|
|
48
49
|
},
|
|
49
50
|
emptyText: 'No errors reported...',
|
|
@@ -4,13 +4,13 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Copyright © 2023 Extremely Heavy Industries Inc.
|
|
6
6
|
*/
|
|
7
|
+
import {exportFilenameWithDate} from '@xh/hoist/admin/AdminUtils';
|
|
7
8
|
import {AppModel} from '@xh/hoist/admin/AppModel';
|
|
8
9
|
import * as Col from '@xh/hoist/admin/columns';
|
|
9
|
-
import {hoistCmp
|
|
10
|
+
import {hoistCmp} from '@xh/hoist/core';
|
|
10
11
|
import {FieldSpec} from '@xh/hoist/data';
|
|
11
12
|
import {textArea} from '@xh/hoist/desktop/cmp/input';
|
|
12
13
|
import {deleteAction, restGrid, RestGridConfig} from '@xh/hoist/desktop/cmp/rest';
|
|
13
|
-
import {LocalDate} from '@xh/hoist/utils/datetime';
|
|
14
14
|
|
|
15
15
|
export const feedbackPanel = hoistCmp.factory(() =>
|
|
16
16
|
restGrid({modelConfig: {...modelSpec, readonly: AppModel.readonly}})
|
|
@@ -20,7 +20,7 @@ const modelSpec: RestGridConfig = {
|
|
|
20
20
|
persistWith: {localStorageKey: 'xhAdminFeedbackState'},
|
|
21
21
|
colChooserModel: true,
|
|
22
22
|
enableExport: true,
|
|
23
|
-
exportOptions: {filename:
|
|
23
|
+
exportOptions: {filename: exportFilenameWithDate('feedback')},
|
|
24
24
|
emptyText: 'No feedback reported...',
|
|
25
25
|
store: {
|
|
26
26
|
url: 'rest/feedbackAdmin',
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Copyright © 2023 Extremely Heavy Industries Inc.
|
|
6
6
|
*/
|
|
7
|
+
import {exportFilename} from '@xh/hoist/admin/AdminUtils';
|
|
7
8
|
import {GroupingChooserModel} from '@xh/hoist/cmp/grouping';
|
|
8
9
|
import {FilterChooserModel} from '@xh/hoist/cmp/filter';
|
|
9
10
|
import {FormModel} from '@xh/hoist/cmp/form';
|
|
@@ -159,7 +160,7 @@ export class ActivityTrackingModel extends HoistModel {
|
|
|
159
160
|
},
|
|
160
161
|
colChooserModel: true,
|
|
161
162
|
enableExport: true,
|
|
162
|
-
exportOptions: {filename:
|
|
163
|
+
exportOptions: {filename: exportFilename('activity-summary')},
|
|
163
164
|
emptyText: 'No activity reported...',
|
|
164
165
|
sortBy: ['cubeLabel'],
|
|
165
166
|
columns: [
|
|
@@ -4,9 +4,10 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Copyright © 2023 Extremely Heavy Industries Inc.
|
|
6
6
|
*/
|
|
7
|
+
import {exportFilename} from '@xh/hoist/admin/AdminUtils';
|
|
7
8
|
import {FormModel} from '@xh/hoist/cmp/form';
|
|
8
9
|
import {GridModel} from '@xh/hoist/cmp/grid';
|
|
9
|
-
import {managed, HoistModel,
|
|
10
|
+
import {managed, HoistModel, lookup} from '@xh/hoist/core';
|
|
10
11
|
import {action, observable, makeObservable} from '@xh/hoist/mobx';
|
|
11
12
|
import {fmtJson} from '@xh/hoist/format';
|
|
12
13
|
import * as Col from '@xh/hoist/admin/columns';
|
|
@@ -34,7 +35,7 @@ export class ActivityDetailModel extends HoistModel {
|
|
|
34
35
|
filterModel: true,
|
|
35
36
|
exportOptions: {
|
|
36
37
|
columns: 'ALL',
|
|
37
|
-
filename:
|
|
38
|
+
filename: exportFilename('activity-detail')
|
|
38
39
|
},
|
|
39
40
|
emptyText: 'Select a group on the left to see detailed tracking logs.',
|
|
40
41
|
columns: [
|
|
@@ -11,7 +11,7 @@ import {HoistModel, LoadSpec, managed, XH, Intent, PlainObject} from '@xh/hoist/
|
|
|
11
11
|
import {dateIs, required} from '@xh/hoist/data';
|
|
12
12
|
import {action, makeObservable, observable} from '@xh/hoist/mobx';
|
|
13
13
|
import {AppModel} from '@xh/hoist/admin/AppModel';
|
|
14
|
-
import
|
|
14
|
+
import {some, sortBy, without} from 'lodash';
|
|
15
15
|
import {computed} from 'mobx';
|
|
16
16
|
|
|
17
17
|
export class AlertBannerModel extends HoistModel {
|
|
@@ -151,7 +151,7 @@ export class AlertBannerModel extends HoistModel {
|
|
|
151
151
|
@computed
|
|
152
152
|
get currentValuesSavedAsPreset() {
|
|
153
153
|
const {message, intent, iconName, enableClose} = this.formModel.values;
|
|
154
|
-
return
|
|
154
|
+
return some(this.savedPresets, {message, intent, iconName, enableClose});
|
|
155
155
|
}
|
|
156
156
|
|
|
157
157
|
async loadPresetsAsync() {
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Copyright © 2023 Extremely Heavy Industries Inc.
|
|
6
6
|
*/
|
|
7
|
+
import {exportFilenameWithDate} from '@xh/hoist/admin/AdminUtils';
|
|
7
8
|
import {AppModel} from '@xh/hoist/admin/AppModel';
|
|
8
9
|
import * as Col from '@xh/hoist/admin/columns';
|
|
9
10
|
import {HoistModel, LoadSpec, managed, XH} from '@xh/hoist/core';
|
|
@@ -18,7 +19,6 @@ import {
|
|
|
18
19
|
RestStore
|
|
19
20
|
} from '@xh/hoist/desktop/cmp/rest';
|
|
20
21
|
import {action, makeObservable, observable} from '@xh/hoist/mobx';
|
|
21
|
-
import {LocalDate} from '@xh/hoist/utils/datetime';
|
|
22
22
|
import {isNil, truncate} from 'lodash';
|
|
23
23
|
import {DifferModel} from '../../../differ/DifferModel';
|
|
24
24
|
import {RegroupDialogModel} from '../../../regroup/RegroupDialogModel';
|
|
@@ -49,7 +49,7 @@ export class ConfigPanelModel extends HoistModel {
|
|
|
49
49
|
persistWith: this.persistWith,
|
|
50
50
|
colChooserModel: true,
|
|
51
51
|
enableExport: true,
|
|
52
|
-
exportOptions: {filename:
|
|
52
|
+
exportOptions: {filename: exportFilenameWithDate('configs')},
|
|
53
53
|
selModel: 'multiple',
|
|
54
54
|
store: new RestStore({
|
|
55
55
|
url: 'rest/configAdmin',
|
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Copyright © 2023 Extremely Heavy Industries Inc.
|
|
6
6
|
*/
|
|
7
|
+
import {exportFilenameWithDate} from '@xh/hoist/admin/AdminUtils';
|
|
7
8
|
import * as Col from '@xh/hoist/admin/columns';
|
|
8
9
|
import {GridModel} from '@xh/hoist/cmp/grid';
|
|
9
10
|
import {HoistModel, LoadSpec, managed, XH} from '@xh/hoist/core';
|
|
10
11
|
import {bindable, makeObservable} from '@xh/hoist/mobx';
|
|
11
|
-
import {LocalDate} from '@xh/hoist/utils/datetime';
|
|
12
12
|
import {keyBy, keys} from 'lodash';
|
|
13
13
|
|
|
14
14
|
export class UserModel extends HoistModel {
|
|
@@ -28,7 +28,7 @@ export class UserModel extends HoistModel {
|
|
|
28
28
|
persistWith: this.persistWith,
|
|
29
29
|
colChooserModel: true,
|
|
30
30
|
enableExport: true,
|
|
31
|
-
exportOptions: {filename:
|
|
31
|
+
exportOptions: {filename: exportFilenameWithDate('users')},
|
|
32
32
|
store: {idSpec: 'username'},
|
|
33
33
|
sortBy: 'username',
|
|
34
34
|
columns: [
|
|
@@ -5,18 +5,17 @@
|
|
|
5
5
|
* Copyright © 2023 Extremely Heavy Industries Inc.
|
|
6
6
|
*/
|
|
7
7
|
import {HoistModel, LoadSpec, managed, XH} from '@xh/hoist/core';
|
|
8
|
-
import {
|
|
8
|
+
import {Icon} from '@xh/hoist/icon';
|
|
9
|
+
import {action, computed, makeObservable, observable} from '@xh/hoist/mobx';
|
|
9
10
|
import {Timer} from '@xh/hoist/utils/async';
|
|
10
11
|
import {SECONDS} from '@xh/hoist/utils/datetime';
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {min, sortBy} from 'lodash';
|
|
12
|
+
import {pluralize} from '@xh/hoist/utils/js';
|
|
13
|
+
import {isEqual, min, sortBy} from 'lodash';
|
|
14
14
|
|
|
15
15
|
export class MonitorResultsModel extends HoistModel {
|
|
16
16
|
@observable.ref results = [];
|
|
17
17
|
@observable lastRun = null;
|
|
18
18
|
@managed timer = null;
|
|
19
|
-
viewRef = createObservableRef<HTMLElement>();
|
|
20
19
|
|
|
21
20
|
@computed
|
|
22
21
|
get passed(): number {
|
|
@@ -38,6 +37,18 @@ export class MonitorResultsModel extends HoistModel {
|
|
|
38
37
|
return this.results.filter(monitor => monitor.status === 'INACTIVE').length;
|
|
39
38
|
}
|
|
40
39
|
|
|
40
|
+
get countsByStatus() {
|
|
41
|
+
const {passed, warned, failed, inactive} = this;
|
|
42
|
+
return {OK: passed, WARN: warned, FAIL: failed, INACTIVE: inactive};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
get worstStatus() {
|
|
46
|
+
if (this.failed) return 'FAIL';
|
|
47
|
+
if (this.warned) return 'WARN';
|
|
48
|
+
if (this.passed) return 'OK';
|
|
49
|
+
return 'INACTIVE';
|
|
50
|
+
}
|
|
51
|
+
|
|
41
52
|
constructor() {
|
|
42
53
|
super();
|
|
43
54
|
makeObservable(this);
|
|
@@ -50,7 +61,7 @@ export class MonitorResultsModel extends HoistModel {
|
|
|
50
61
|
}
|
|
51
62
|
|
|
52
63
|
override async doLoadAsync(loadSpec: LoadSpec) {
|
|
53
|
-
if (!
|
|
64
|
+
if (!XH.pageIsVisible) return;
|
|
54
65
|
|
|
55
66
|
return XH.fetchJson({url: 'monitorAdmin/results', loadSpec})
|
|
56
67
|
.then(rows => {
|
|
@@ -76,16 +87,42 @@ export class MonitorResultsModel extends HoistModel {
|
|
|
76
87
|
//-------------------
|
|
77
88
|
@action
|
|
78
89
|
private completeLoad(vals) {
|
|
90
|
+
const prevCounts = this.countsByStatus;
|
|
79
91
|
this.results = sortBy(Object.values(vals), 'sortOrder');
|
|
80
|
-
this.getLastRun();
|
|
81
|
-
}
|
|
82
92
|
|
|
83
|
-
|
|
84
|
-
|
|
93
|
+
const counts = this.countsByStatus,
|
|
94
|
+
worst = this.worstStatus;
|
|
95
|
+
|
|
96
|
+
let intent = null,
|
|
97
|
+
icon = null;
|
|
98
|
+
switch (worst) {
|
|
99
|
+
case 'FAIL':
|
|
100
|
+
intent = 'danger';
|
|
101
|
+
icon = Icon.error();
|
|
102
|
+
break;
|
|
103
|
+
case 'WARN':
|
|
104
|
+
intent = 'warning';
|
|
105
|
+
icon = Icon.warning();
|
|
106
|
+
break;
|
|
107
|
+
case 'OK':
|
|
108
|
+
intent = 'success';
|
|
109
|
+
icon = Icon.checkCircle();
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// This is imperfect, in that e.g. two monitors could swap their status and we would not
|
|
113
|
+
// alert, but this approach is easy and seemed reasonable enough for this low-stakes toast.
|
|
114
|
+
if (!isEqual(prevCounts, counts) && worst !== 'INACTIVE') {
|
|
115
|
+
XH.toast({
|
|
116
|
+
message: `Status update: ${pluralize('monitor', counts[worst], true)} @ ${worst}`,
|
|
117
|
+
timeout: 6000,
|
|
118
|
+
icon,
|
|
119
|
+
intent
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
|
|
85
123
|
const lastRun = min(
|
|
86
124
|
this.results.filter(monitor => monitor.status !== 'UNKNOWN').map(it => it.date)
|
|
87
125
|
);
|
|
88
|
-
|
|
89
126
|
this.lastRun = lastRun ? new Date(lastRun) : null;
|
|
90
127
|
}
|
|
91
128
|
}
|
|
@@ -4,27 +4,37 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Copyright © 2023 Extremely Heavy Industries Inc.
|
|
6
6
|
*/
|
|
7
|
+
import {AppModel} from '@xh/hoist/admin/AppModel';
|
|
8
|
+
import {filler, hbox, label, placeholder, tileFrame} from '@xh/hoist/cmp/layout';
|
|
9
|
+
import {relativeTimestamp} from '@xh/hoist/cmp/relativetimestamp';
|
|
7
10
|
import {creates, hoistCmp} from '@xh/hoist/core';
|
|
8
|
-
import {
|
|
11
|
+
import {button, modalToggleButton} from '@xh/hoist/desktop/cmp/button';
|
|
9
12
|
import {panel} from '@xh/hoist/desktop/cmp/panel';
|
|
13
|
+
import {toolbar, toolbarSep} from '@xh/hoist/desktop/cmp/toolbar';
|
|
14
|
+
import {Icon} from '@xh/hoist/icon';
|
|
10
15
|
import {isEmpty} from 'lodash';
|
|
11
|
-
|
|
12
|
-
import './MonitorResultsPanel.scss';
|
|
16
|
+
import {errorMessage} from '../../../desktop/cmp/error';
|
|
13
17
|
import {MonitorResultsModel} from './MonitorResultsModel';
|
|
14
|
-
import
|
|
18
|
+
import './MonitorResultsPanel.scss';
|
|
15
19
|
import {tile} from './Tile';
|
|
16
|
-
import {errorMessage} from '../../../desktop/cmp/error';
|
|
17
20
|
|
|
18
21
|
export const monitorResultsPanel = hoistCmp.factory({
|
|
19
22
|
model: creates(MonitorResultsModel),
|
|
20
23
|
|
|
21
24
|
render({model}) {
|
|
22
25
|
return panel({
|
|
23
|
-
ref: model.viewRef,
|
|
24
26
|
mask: 'onLoad',
|
|
25
27
|
className: 'xh-monitor-results-panel',
|
|
26
|
-
tbar:
|
|
27
|
-
item: body()
|
|
28
|
+
tbar: tbar(),
|
|
29
|
+
item: body(),
|
|
30
|
+
modelConfig: {
|
|
31
|
+
modalSupport: {
|
|
32
|
+
width: '100vw',
|
|
33
|
+
height: '100vh'
|
|
34
|
+
},
|
|
35
|
+
collapsible: false,
|
|
36
|
+
resizable: false
|
|
37
|
+
}
|
|
28
38
|
});
|
|
29
39
|
}
|
|
30
40
|
});
|
|
@@ -48,3 +58,56 @@ const body = hoistCmp.factory<MonitorResultsModel>(({model}) => {
|
|
|
48
58
|
items: results.map(check => tile({check}))
|
|
49
59
|
});
|
|
50
60
|
});
|
|
61
|
+
|
|
62
|
+
const tbar = hoistCmp.factory<MonitorResultsModel>(({model}) => {
|
|
63
|
+
const {passed, warned, failed, inactive, results} = model,
|
|
64
|
+
getClassName = hide => {
|
|
65
|
+
return `xh-monitor-result-count ${hide ? 'xh-monitor-result-count--hidden' : ''}`;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
return toolbar(
|
|
69
|
+
button({
|
|
70
|
+
icon: Icon.refresh(),
|
|
71
|
+
text: 'Run all now',
|
|
72
|
+
disabled: isEmpty(results),
|
|
73
|
+
omit: AppModel.readonly,
|
|
74
|
+
onClick: () => model.forceRunAllMonitorsAsync()
|
|
75
|
+
}),
|
|
76
|
+
hbox({
|
|
77
|
+
className: getClassName(!failed),
|
|
78
|
+
items: [
|
|
79
|
+
toolbarSep(),
|
|
80
|
+
Icon.error({prefix: 'fas', className: 'xh-red'}),
|
|
81
|
+
label(`${failed} failed`)
|
|
82
|
+
]
|
|
83
|
+
}),
|
|
84
|
+
hbox({
|
|
85
|
+
className: getClassName(!warned),
|
|
86
|
+
items: [
|
|
87
|
+
toolbarSep(),
|
|
88
|
+
Icon.warning({prefix: 'fas', className: 'xh-orange'}),
|
|
89
|
+
label(`${warned} warned`)
|
|
90
|
+
]
|
|
91
|
+
}),
|
|
92
|
+
hbox({
|
|
93
|
+
className: getClassName(!passed),
|
|
94
|
+
items: [
|
|
95
|
+
toolbarSep(),
|
|
96
|
+
Icon.checkCircle({prefix: 'fas', className: 'xh-green'}),
|
|
97
|
+
label(`${passed} passed`)
|
|
98
|
+
]
|
|
99
|
+
}),
|
|
100
|
+
hbox({
|
|
101
|
+
className: getClassName(!inactive),
|
|
102
|
+
items: [
|
|
103
|
+
toolbarSep(),
|
|
104
|
+
Icon.disabled({prefix: 'fas', className: 'xh-gray'}),
|
|
105
|
+
label(`${inactive} inactive`)
|
|
106
|
+
]
|
|
107
|
+
}),
|
|
108
|
+
filler(),
|
|
109
|
+
relativeTimestamp({bind: 'lastRun'}),
|
|
110
|
+
'-',
|
|
111
|
+
modalToggleButton()
|
|
112
|
+
);
|
|
113
|
+
});
|
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Copyright © 2023 Extremely Heavy Industries Inc.
|
|
6
6
|
*/
|
|
7
|
+
import {exportFilenameWithDate} from '@xh/hoist/admin/AdminUtils';
|
|
7
8
|
import {ChartModel} from '@xh/hoist/cmp/chart';
|
|
8
9
|
import {GridModel} from '@xh/hoist/cmp/grid';
|
|
9
10
|
import {HoistModel, LoadSpec, managed, PlainObject, XH} from '@xh/hoist/core';
|
|
10
11
|
import {fmtTime} from '@xh/hoist/format';
|
|
11
12
|
import {bindable} from '@xh/hoist/mobx';
|
|
12
|
-
import {LocalDate} from '@xh/hoist/utils/datetime';
|
|
13
13
|
import {forOwn, sortBy} from 'lodash';
|
|
14
14
|
import * as MCol from '../../monitor/MonitorColumns';
|
|
15
15
|
|
|
@@ -35,7 +35,7 @@ export class ConnPoolMonitorModel extends HoistModel {
|
|
|
35
35
|
|
|
36
36
|
this.gridModel = new GridModel({
|
|
37
37
|
enableExport: true,
|
|
38
|
-
exportOptions: {filename:
|
|
38
|
+
exportOptions: {filename: exportFilenameWithDate('conn-pool-monitor')},
|
|
39
39
|
filterModel: true,
|
|
40
40
|
sortBy: 'timestamp|desc',
|
|
41
41
|
store: {idSpec: 'timestamp'},
|
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Copyright © 2023 Extremely Heavy Industries Inc.
|
|
6
6
|
*/
|
|
7
|
+
import {exportFilenameWithDate} from '@xh/hoist/admin/AdminUtils';
|
|
7
8
|
import {GridModel} from '@xh/hoist/cmp/grid';
|
|
8
9
|
import * as Col from '@xh/hoist/cmp/grid/columns';
|
|
9
10
|
import {HoistModel, LoadSpec, managed, XH} from '@xh/hoist/core';
|
|
10
11
|
import {UrlStore} from '@xh/hoist/data';
|
|
11
|
-
import {LocalDate} from '@xh/hoist/utils/datetime';
|
|
12
12
|
import {trimEnd} from 'lodash';
|
|
13
13
|
|
|
14
14
|
export class EhCacheModel extends HoistModel {
|
|
@@ -19,7 +19,7 @@ export class EhCacheModel extends HoistModel {
|
|
|
19
19
|
persistWith: this.persistWith,
|
|
20
20
|
colChooserModel: true,
|
|
21
21
|
enableExport: true,
|
|
22
|
-
exportOptions: {filename:
|
|
22
|
+
exportOptions: {filename: exportFilenameWithDate('eh-caches')},
|
|
23
23
|
store: new UrlStore({
|
|
24
24
|
url: 'ehCacheAdmin/listCaches',
|
|
25
25
|
fields: [
|
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Copyright © 2023 Extremely Heavy Industries Inc.
|
|
6
6
|
*/
|
|
7
|
+
import {exportFilenameWithDate} from '@xh/hoist/admin/AdminUtils';
|
|
7
8
|
import {GridModel} from '@xh/hoist/cmp/grid';
|
|
8
9
|
import {HoistModel, LoadSpec, managed, XH} from '@xh/hoist/core';
|
|
9
|
-
import {LocalDate} from '@xh/hoist/utils/datetime';
|
|
10
10
|
import {forOwn} from 'lodash';
|
|
11
11
|
|
|
12
12
|
/**
|
|
@@ -23,8 +23,8 @@ export class ServerEnvModel extends HoistModel {
|
|
|
23
23
|
groupBy: 'type',
|
|
24
24
|
sortBy: 'name',
|
|
25
25
|
enableExport: true,
|
|
26
|
-
exportOptions: {filename:
|
|
27
|
-
store: {idSpec:
|
|
26
|
+
exportOptions: {filename: exportFilenameWithDate('env')},
|
|
27
|
+
store: {idSpec: data => `${data.type}-${data.name}`},
|
|
28
28
|
columns: [
|
|
29
29
|
{
|
|
30
30
|
field: {name: 'type', type: 'string'},
|
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Copyright © 2023 Extremely Heavy Industries Inc.
|
|
6
6
|
*/
|
|
7
|
+
import {exportFilenameWithDate} from '@xh/hoist/admin/AdminUtils';
|
|
7
8
|
import {AppModel} from '@xh/hoist/admin/AppModel';
|
|
8
9
|
import * as Col from '@xh/hoist/admin/columns';
|
|
9
|
-
import {hoistCmp
|
|
10
|
+
import {hoistCmp} from '@xh/hoist/core';
|
|
10
11
|
import {FieldSpec} from '@xh/hoist/data';
|
|
11
12
|
import {restGrid, RestGridConfig} from '@xh/hoist/desktop/cmp/rest';
|
|
12
|
-
import {LocalDate} from '@xh/hoist/utils/datetime';
|
|
13
13
|
import * as LogLevelCol from './LogLevelColumns';
|
|
14
14
|
|
|
15
15
|
export const logLevelPanel = hoistCmp.factory(() =>
|
|
@@ -20,7 +20,7 @@ const modelSpec: RestGridConfig = {
|
|
|
20
20
|
persistWith: {localStorageKey: 'xhAdminLogLevelState'},
|
|
21
21
|
colChooserModel: true,
|
|
22
22
|
enableExport: true,
|
|
23
|
-
exportOptions: {filename:
|
|
23
|
+
exportOptions: {filename: exportFilenameWithDate('log-levels')},
|
|
24
24
|
store: {
|
|
25
25
|
url: 'rest/logLevelAdmin',
|
|
26
26
|
fieldDefaults: {disableXssProtection: true},
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Copyright © 2023 Extremely Heavy Industries Inc.
|
|
6
6
|
*/
|
|
7
|
+
import {exportFilenameWithDate} from '@xh/hoist/admin/AdminUtils';
|
|
7
8
|
import {AppModel} from '@xh/hoist/admin/AppModel';
|
|
8
9
|
import {GridModel} from '@xh/hoist/cmp/grid';
|
|
9
10
|
import {HoistModel, LoadSpec, managed, XH} from '@xh/hoist/core';
|
|
@@ -11,7 +12,6 @@ import {RecordActionSpec} from '@xh/hoist/data';
|
|
|
11
12
|
import {compactDateRenderer, fmtNumber} from '@xh/hoist/format';
|
|
12
13
|
import {Icon} from '@xh/hoist/icon';
|
|
13
14
|
import {makeObservable, observable} from '@xh/hoist/mobx';
|
|
14
|
-
import {LocalDate} from '@xh/hoist/utils/datetime';
|
|
15
15
|
import download from 'downloadjs';
|
|
16
16
|
import {createRef} from 'react';
|
|
17
17
|
import {LogDisplayModel} from './LogDisplayModel';
|
|
@@ -149,7 +149,7 @@ export class LogViewerModel extends HoistModel {
|
|
|
149
149
|
private createGridModel() {
|
|
150
150
|
return new GridModel({
|
|
151
151
|
enableExport: true,
|
|
152
|
-
exportOptions: {filename:
|
|
152
|
+
exportOptions: {filename: exportFilenameWithDate('logs')},
|
|
153
153
|
selModel: 'multiple',
|
|
154
154
|
store: {
|
|
155
155
|
idSpec: 'filename',
|
|
@@ -4,13 +4,13 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Copyright © 2023 Extremely Heavy Industries Inc.
|
|
6
6
|
*/
|
|
7
|
+
import {exportFilenameWithDate} from '@xh/hoist/admin/AdminUtils';
|
|
7
8
|
import {ChartModel} from '@xh/hoist/cmp/chart';
|
|
8
9
|
import {GridModel} from '@xh/hoist/cmp/grid';
|
|
9
10
|
import {HoistModel, LoadSpec, managed, XH} from '@xh/hoist/core';
|
|
10
11
|
import {lengthIs, required} from '@xh/hoist/data';
|
|
11
12
|
import {fmtTime} from '@xh/hoist/format';
|
|
12
13
|
import {Icon} from '@xh/hoist/icon';
|
|
13
|
-
import {LocalDate} from '@xh/hoist/utils/datetime';
|
|
14
14
|
import {forOwn, sortBy} from 'lodash';
|
|
15
15
|
import * as MCol from '../../monitor/MonitorColumns';
|
|
16
16
|
|
|
@@ -31,7 +31,7 @@ export class MemoryMonitorModel extends HoistModel {
|
|
|
31
31
|
|
|
32
32
|
this.gridModel = new GridModel({
|
|
33
33
|
enableExport: true,
|
|
34
|
-
exportOptions: {filename:
|
|
34
|
+
exportOptions: {filename: exportFilenameWithDate('memory-monitor')},
|
|
35
35
|
filterModel: true,
|
|
36
36
|
sortBy: 'timestamp|desc',
|
|
37
37
|
store: {idSpec: 'timestamp'},
|
|
@@ -4,21 +4,21 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Copyright © 2023 Extremely Heavy Industries Inc.
|
|
6
6
|
*/
|
|
7
|
+
import {exportFilenameWithDate} from '@xh/hoist/admin/AdminUtils';
|
|
7
8
|
import {GridModel} from '@xh/hoist/cmp/grid';
|
|
8
9
|
import {HoistModel, LoadSpec, managed, XH} from '@xh/hoist/core';
|
|
9
10
|
import {UrlStore} from '@xh/hoist/data';
|
|
10
|
-
import {LocalDate} from '@xh/hoist/utils/datetime';
|
|
11
11
|
import {isEmpty, lowerFirst} from 'lodash';
|
|
12
12
|
|
|
13
13
|
export class ServiceModel extends HoistModel {
|
|
14
14
|
@managed
|
|
15
15
|
gridModel: GridModel = new GridModel({
|
|
16
16
|
enableExport: true,
|
|
17
|
-
exportOptions: {filename:
|
|
17
|
+
exportOptions: {filename: exportFilenameWithDate('services')},
|
|
18
18
|
hideHeaders: true,
|
|
19
19
|
store: new UrlStore({
|
|
20
20
|
url: 'serviceAdmin/listServices',
|
|
21
|
-
idSpec:
|
|
21
|
+
idSpec: data => `${data.provider}-${data.name}`,
|
|
22
22
|
processRawData: this.processRawData,
|
|
23
23
|
fields: [
|
|
24
24
|
{name: 'provider', type: 'string'},
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Copyright © 2023 Extremely Heavy Industries Inc.
|
|
6
6
|
*/
|
|
7
|
+
import {exportFilenameWithDate} from '@xh/hoist/admin/AdminUtils';
|
|
7
8
|
import * as Col from '@xh/hoist/admin/columns';
|
|
8
9
|
import {GridModel} from '@xh/hoist/cmp/grid';
|
|
9
10
|
import {div, p} from '@xh/hoist/cmp/layout';
|
|
@@ -12,7 +13,7 @@ import {textInput} from '@xh/hoist/desktop/cmp/input';
|
|
|
12
13
|
import {Icon} from '@xh/hoist/icon';
|
|
13
14
|
import {makeObservable, observable, runInAction} from '@xh/hoist/mobx';
|
|
14
15
|
import {Timer} from '@xh/hoist/utils/async';
|
|
15
|
-
import {
|
|
16
|
+
import {SECONDS} from '@xh/hoist/utils/datetime';
|
|
16
17
|
import {isDisplayed} from '@xh/hoist/utils/js';
|
|
17
18
|
import {isEmpty} from 'lodash';
|
|
18
19
|
import {createRef} from 'react';
|
|
@@ -37,7 +38,7 @@ export class WebSocketModel extends HoistModel {
|
|
|
37
38
|
this.gridModel = new GridModel({
|
|
38
39
|
emptyText: 'No clients connected.',
|
|
39
40
|
enableExport: true,
|
|
40
|
-
exportOptions: {filename:
|
|
41
|
+
exportOptions: {filename: exportFilenameWithDate('ws-connections')},
|
|
41
42
|
selModel: 'multiple',
|
|
42
43
|
store: {
|
|
43
44
|
idSpec: 'key',
|