@xh/hoist 44.0.0 → 44.1.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 +25 -0
- package/SECURITY.md +23 -0
- package/admin/AppModel.js +30 -8
- package/admin/tabs/monitor/MonitorTab.js +12 -18
- package/admin/tabs/monitor/Tile.scss +8 -5
- package/admin/tabs/server/ServerTab.js +4 -0
- package/admin/tabs/server/ehcache/EhCachePanel.js +10 -3
- package/admin/tabs/server/environment/ServerEnvModel.js +68 -0
- package/admin/tabs/server/environment/ServerEnvPanel.js +36 -0
- package/admin/tabs/{monitor → server/memory}/MemoryMonitorModel.js +2 -2
- package/admin/tabs/{monitor → server/memory}/MemoryMonitorPanel.js +2 -1
- package/admin/tabs/server/services/ServicePanel.js +10 -3
- package/appcontainer/AppContainerModel.js +3 -0
- package/appcontainer/OptionsDialogModel.js +13 -6
- package/appcontainer/ViewportSizeModel.js +49 -0
- package/cmp/ag-grid/AgGrid.scss +7 -5
- package/cmp/grid/columns/Column.js +163 -34
- package/core/XH.js +18 -0
- package/desktop/appcontainer/AppContainer.js +2 -2
- package/desktop/cmp/grid/editors/DateEditor.js +87 -1
- package/desktop/cmp/input/DateInput.js +6 -2
- package/desktop/cmp/input/Select.js +7 -3
- package/kit/blueprint/styles.scss +34 -6
- package/kit/onsen/theme.scss +1 -29
- package/mobile/cmp/menu/impl/Menu.js +48 -30
- package/mobile/cmp/menu/impl/Menu.scss +17 -6
- package/package.json +1 -1
- package/styles/vars.scss +14 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v44.1.0 - 2021-11-08
|
|
4
|
+
|
|
5
|
+
### 🎁 New Features
|
|
6
|
+
|
|
7
|
+
* Changes to App Options are now tracked in the admin activity tab.
|
|
8
|
+
* New Server > Environment tab added to Admin Console to display UI server environment variables and
|
|
9
|
+
JVM system properties. (Requires `hoist-core >= 10.1` to enable this optional feature.)
|
|
10
|
+
* Provided observable getters `XH.viewportSize`, `XH.isPortrait` and `XH.isLandscape` to allow apps
|
|
11
|
+
to react to changes in viewport size and orientation.
|
|
12
|
+
|
|
13
|
+
### 🐞 Bug Fixes
|
|
14
|
+
|
|
15
|
+
* Desktop inline grid editor `DateInput` now reliably shows its date picker pop-up aligned with the
|
|
16
|
+
grid cell under edit.
|
|
17
|
+
* Desktop `Select.hideDropdownIndicator` now defaults to `true` on tablet devices due to UX bugs
|
|
18
|
+
with the select library component and touch devices.
|
|
19
|
+
* Ensure `Column.autosizeBufferPx` is respected if provided.
|
|
20
|
+
|
|
21
|
+
### ✨ Style
|
|
22
|
+
|
|
23
|
+
* New `--xh-menu-item` CSS vars added, with tweaks to default desktop menu styling.
|
|
24
|
+
* Highlight background color added to mobile menu items while pressed.
|
|
25
|
+
|
|
26
|
+
[Commit Log](https://github.com/xh/hoist-react/compare/v44.0.0...v44.1.0)
|
|
27
|
+
|
|
3
28
|
## v44.0.0 - 2021-10-26
|
|
4
29
|
|
|
5
30
|
⚠ NOTE - apps must update to `hoist-core >= 10.0.0` when taking this hoist-react update.
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
Extremely Heavy takes the security of its code and clients very seriously, and we welcome any and
|
|
4
|
+
all reports of possible vulnerabilities or security-related issues with both Hoist code and its
|
|
5
|
+
declared dependencies.
|
|
6
|
+
|
|
7
|
+
## Reporting a Vulnerability
|
|
8
|
+
|
|
9
|
+
To report any issues, or if you have any questions, please contact us immediately at support@xh.io.
|
|
10
|
+
We will respond to all genuine, security-related reports or questions within one US business day.
|
|
11
|
+
|
|
12
|
+
## Secure Usage
|
|
13
|
+
|
|
14
|
+
Hoist is a toolkit designed to allow professional developers to build advanced enterprise web
|
|
15
|
+
applications with the support of XH in the form of direct development, co-development, and/or
|
|
16
|
+
consulting services. As such, many decisions critical to the security of Hoist-powered applications
|
|
17
|
+
are highly specific to implementation choices made during the design and development process,
|
|
18
|
+
including but not limited to the choice of other project dependencies, creation and interaction
|
|
19
|
+
with any Hoist or third-party server APIs, input sanitization, authentication protocols, and more.
|
|
20
|
+
|
|
21
|
+
Hoist is not and does not claim to be fully secure "out of the box" - it is dependent upon
|
|
22
|
+
application developers to make and implement security decisions appropriate to their particular
|
|
23
|
+
application and its deployment.
|
package/admin/AppModel.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Copyright © 2021 Extremely Heavy Industries Inc.
|
|
6
6
|
*/
|
|
7
7
|
import {TabContainerModel} from '@xh/hoist/cmp/tab';
|
|
8
|
-
import {HoistAppModel, managed} from '@xh/hoist/core';
|
|
8
|
+
import {HoistAppModel, managed, XH} from '@xh/hoist/core';
|
|
9
9
|
import {Icon} from '@xh/hoist/icon';
|
|
10
10
|
import {activityTab} from './tabs/activity/ActivityTab';
|
|
11
11
|
import {generalTab} from './tabs/general/GeneralTab';
|
|
@@ -69,8 +69,10 @@ export class AppModel extends HoistAppModel {
|
|
|
69
69
|
children: [
|
|
70
70
|
{name: 'logViewer', path: '/logViewer'},
|
|
71
71
|
{name: 'logLevels', path: '/logLevels'},
|
|
72
|
+
{name: 'environment', path: '/environment'},
|
|
72
73
|
{name: 'services', path: '/services'},
|
|
73
74
|
{name: 'ehCache', path: '/ehCache'},
|
|
75
|
+
{name: 'memory', path: '/memory'},
|
|
74
76
|
{name: 'webSockets', path: '/webSockets'}
|
|
75
77
|
]
|
|
76
78
|
},
|
|
@@ -79,8 +81,7 @@ export class AppModel extends HoistAppModel {
|
|
|
79
81
|
path: '/monitor',
|
|
80
82
|
children: [
|
|
81
83
|
{name: 'status', path: '/status'},
|
|
82
|
-
{name: 'config', path: '/config'}
|
|
83
|
-
{name: 'memory', path: '/memory'}
|
|
84
|
+
{name: 'config', path: '/config'}
|
|
84
85
|
]
|
|
85
86
|
},
|
|
86
87
|
{
|
|
@@ -97,11 +98,32 @@ export class AppModel extends HoistAppModel {
|
|
|
97
98
|
|
|
98
99
|
createTabs() {
|
|
99
100
|
return [
|
|
100
|
-
{
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
101
|
+
{
|
|
102
|
+
id: 'general',
|
|
103
|
+
icon: Icon.info(),
|
|
104
|
+
content: generalTab
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
id: 'activity',
|
|
108
|
+
icon: Icon.analytics(),
|
|
109
|
+
content: activityTab
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
id: 'server',
|
|
113
|
+
icon: Icon.server(),
|
|
114
|
+
content: serverTab
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
id: 'monitor',
|
|
118
|
+
icon: Icon.shieldCheck(),
|
|
119
|
+
content: monitorTab,
|
|
120
|
+
omit: !XH.getConf('xhEnableMonitoring', true)
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
id: 'userData',
|
|
124
|
+
icon: Icon.users(),
|
|
125
|
+
content: userDataTab
|
|
126
|
+
}
|
|
105
127
|
];
|
|
106
128
|
}
|
|
107
129
|
}
|
|
@@ -4,27 +4,21 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Copyright © 2021 Extremely Heavy Industries Inc.
|
|
6
6
|
*/
|
|
7
|
-
import {XH} from '@xh/hoist/core';
|
|
8
|
-
import {memoryMonitorPanel} from '@xh/hoist/admin/tabs/monitor/MemoryMonitorPanel';
|
|
9
7
|
import {tabContainer} from '@xh/hoist/cmp/tab';
|
|
10
8
|
import {hoistCmp} from '@xh/hoist/core';
|
|
11
9
|
import {Icon} from '@xh/hoist/icon';
|
|
12
10
|
import {monitorEditorPanel} from './MonitorEditorPanel';
|
|
13
11
|
import {monitorResultsPanel} from './MonitorResultsPanel';
|
|
14
12
|
|
|
15
|
-
export const monitorTab = hoistCmp.factory(
|
|
16
|
-
(
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
);
|
|
13
|
+
export const monitorTab = hoistCmp.factory(() => {
|
|
14
|
+
return tabContainer({
|
|
15
|
+
model: {
|
|
16
|
+
route: 'default.monitor',
|
|
17
|
+
switcher: {orientation: 'left'},
|
|
18
|
+
tabs: [
|
|
19
|
+
{id: 'status', icon: Icon.shieldCheck(), content: monitorResultsPanel},
|
|
20
|
+
{id: 'config', icon: Icon.settings(), content: monitorEditorPanel}
|
|
21
|
+
]
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
});
|
|
@@ -7,15 +7,18 @@
|
|
|
7
7
|
|
|
8
8
|
.xh-status-tile {
|
|
9
9
|
color: white;
|
|
10
|
-
border:
|
|
11
|
-
border-radius: var(--xh-border-radius);
|
|
10
|
+
border: var(--xh-border-solid);
|
|
12
11
|
overflow: hidden;
|
|
13
12
|
|
|
14
|
-
|
|
13
|
+
.xh-dark & {
|
|
14
|
+
border-color: white;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
&-ok { background-color: var(--xh-intent-success-darker); }
|
|
15
18
|
|
|
16
|
-
&-warn { background-color: var(--xh-
|
|
19
|
+
&-warn { background-color: var(--xh-intent-warning-darker); }
|
|
17
20
|
|
|
18
|
-
&-fail { background-color: var(--xh-
|
|
21
|
+
&-fail { background-color: var(--xh-intent-danger-darker); }
|
|
19
22
|
|
|
20
23
|
&-inactive { background-color: var(--xh-gray-dark); }
|
|
21
24
|
|
|
@@ -4,12 +4,14 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Copyright © 2021 Extremely Heavy Industries Inc.
|
|
6
6
|
*/
|
|
7
|
+
import {serverEnvPanel} from '@xh/hoist/admin/tabs/server/environment/ServerEnvPanel';
|
|
7
8
|
import {tabContainer} from '@xh/hoist/cmp/tab';
|
|
8
9
|
import {hoistCmp, XH} from '@xh/hoist/core';
|
|
9
10
|
import {Icon} from '@xh/hoist/icon';
|
|
10
11
|
import {ehCachePanel} from './ehcache/EhCachePanel';
|
|
11
12
|
import {logLevelPanel} from './logLevel/LogLevelPanel';
|
|
12
13
|
import {logViewer} from './logViewer/LogViewer';
|
|
14
|
+
import {memoryMonitorPanel} from './memory/MemoryMonitorPanel';
|
|
13
15
|
import {servicePanel} from './services/ServicePanel';
|
|
14
16
|
import {webSocketPanel} from './websocket/WebSocketPanel';
|
|
15
17
|
|
|
@@ -21,6 +23,8 @@ export const serverTab = hoistCmp.factory(
|
|
|
21
23
|
tabs: [
|
|
22
24
|
{id: 'logViewer', icon: Icon.fileText(), content: logViewer, omit: !XH.getConf('xhEnableLogViewer', true)},
|
|
23
25
|
{id: 'logLevels', icon: Icon.settings(), content: logLevelPanel},
|
|
26
|
+
{id: 'memory', title: 'Memory Monitor', icon: Icon.server(), content: memoryMonitorPanel},
|
|
27
|
+
{id: 'environment', icon: Icon.globe(), content: serverEnvPanel},
|
|
24
28
|
{id: 'services', icon: Icon.gears(), content: servicePanel},
|
|
25
29
|
{id: 'ehCache', icon: Icon.database(), title: 'Caches', content: ehCachePanel},
|
|
26
30
|
{id: 'webSockets', title: 'WebSockets', icon: Icon.bolt(), content: webSocketPanel}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Copyright © 2021 Extremely Heavy Industries Inc.
|
|
6
6
|
*/
|
|
7
7
|
import {grid, gridCountLabel} from '@xh/hoist/cmp/grid';
|
|
8
|
-
import {filler} from '@xh/hoist/cmp/layout';
|
|
8
|
+
import {filler, span} from '@xh/hoist/cmp/layout';
|
|
9
9
|
import {storeFilterField} from '@xh/hoist/cmp/store';
|
|
10
10
|
import {creates, hoistCmp} from '@xh/hoist/core';
|
|
11
11
|
import {button, exportButton} from '@xh/hoist/desktop/cmp/button';
|
|
@@ -20,15 +20,22 @@ export const ehCachePanel = hoistCmp.factory({
|
|
|
20
20
|
return panel({
|
|
21
21
|
mask: 'onLoad',
|
|
22
22
|
tbar: [
|
|
23
|
+
Icon.info(),
|
|
24
|
+
span({
|
|
25
|
+
item: 'Hibernate (Ehcache) caches for server-side domain objects',
|
|
26
|
+
className: 'xh-bold'
|
|
27
|
+
}),
|
|
28
|
+
filler(),
|
|
23
29
|
button({
|
|
24
30
|
icon: Icon.reset(),
|
|
25
31
|
text: 'Clear All',
|
|
26
32
|
intent: 'danger',
|
|
27
33
|
onClick: () => model.clearAllAsync()
|
|
28
34
|
}),
|
|
29
|
-
|
|
35
|
+
'-',
|
|
30
36
|
gridCountLabel({unit: 'cache'}),
|
|
31
|
-
|
|
37
|
+
'-',
|
|
38
|
+
storeFilterField({matchMode: 'any'}),
|
|
32
39
|
exportButton()
|
|
33
40
|
],
|
|
34
41
|
item: grid()
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import {GridModel} from '@xh/hoist/cmp/grid';
|
|
2
|
+
import {HoistModel, managed, XH} from '@xh/hoist/core';
|
|
3
|
+
import {FieldType} from '@xh/hoist/data';
|
|
4
|
+
import {checkMinVersion} from '@xh/hoist/utils/js';
|
|
5
|
+
import {forOwn} from 'lodash';
|
|
6
|
+
|
|
7
|
+
const {STRING} = FieldType;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Model/tab to list server-side environment variables and JVM system properties, as loaded from
|
|
11
|
+
* a dedicated admin-only endpoint.
|
|
12
|
+
*/
|
|
13
|
+
export class ServerEnvModel extends HoistModel {
|
|
14
|
+
|
|
15
|
+
/** @member {GridModel} */
|
|
16
|
+
@managed gridModel;
|
|
17
|
+
|
|
18
|
+
get minVersionWarning() {
|
|
19
|
+
const minVersion = '10.1.0',
|
|
20
|
+
currVersion = XH.environmentService.get('hoistCoreVersion');
|
|
21
|
+
return checkMinVersion(currVersion, minVersion) ? null : `This feature requires Hoist Core v${minVersion} or greater.`;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
constructor() {
|
|
25
|
+
super();
|
|
26
|
+
|
|
27
|
+
this.gridModel = new GridModel({
|
|
28
|
+
groupBy: 'type',
|
|
29
|
+
sortBy: 'name',
|
|
30
|
+
enableExport: true,
|
|
31
|
+
store: {idSpec: XH.genId},
|
|
32
|
+
columns: [
|
|
33
|
+
{
|
|
34
|
+
field: {name: 'type', type: STRING},
|
|
35
|
+
hidden: true
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
field: {name: 'name', type: STRING},
|
|
39
|
+
width: 300,
|
|
40
|
+
cellClass: 'xh-font-family-mono'
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
field: {name: 'value', type: STRING},
|
|
44
|
+
flex: 1,
|
|
45
|
+
cellClass: 'xh-font-family-mono',
|
|
46
|
+
autoHeight: true
|
|
47
|
+
}
|
|
48
|
+
]
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async doLoadAsync(loadSpec) {
|
|
53
|
+
if (this.minVersionWarning) return;
|
|
54
|
+
|
|
55
|
+
const resp = await XH.fetchJson({url: 'envAdmin'}),
|
|
56
|
+
data = [];
|
|
57
|
+
|
|
58
|
+
forOwn(resp.environment, (value, name) => {
|
|
59
|
+
data.push({type: 'Environment Variables', value, name});
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
forOwn(resp.properties, (value, name) => {
|
|
63
|
+
data.push({type: 'System Properties', value, name});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
this.gridModel.loadData(data);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import {ServerEnvModel} from '@xh/hoist/admin/tabs/server/environment/ServerEnvModel';
|
|
2
|
+
import {grid, gridCountLabel} from '@xh/hoist/cmp/grid';
|
|
3
|
+
import {filler, placeholder, span} from '@xh/hoist/cmp/layout';
|
|
4
|
+
import {storeFilterField} from '@xh/hoist/cmp/store';
|
|
5
|
+
import {creates, hoistCmp} from '@xh/hoist/core';
|
|
6
|
+
import {exportButton} from '@xh/hoist/desktop/cmp/button';
|
|
7
|
+
import {errorMessage} from '@xh/hoist/desktop/cmp/error';
|
|
8
|
+
import {panel} from '@xh/hoist/desktop/cmp/panel';
|
|
9
|
+
import {Icon} from '@xh/hoist/icon';
|
|
10
|
+
|
|
11
|
+
export const serverEnvPanel = hoistCmp.factory({
|
|
12
|
+
model: creates(ServerEnvModel),
|
|
13
|
+
|
|
14
|
+
/** @param {ServerEnvModel} model */
|
|
15
|
+
render({model}) {
|
|
16
|
+
const {lastLoadException, minVersionWarning} = model;
|
|
17
|
+
if (minVersionWarning) return placeholder(minVersionWarning);
|
|
18
|
+
|
|
19
|
+
return panel({
|
|
20
|
+
tbar: [
|
|
21
|
+
Icon.info(),
|
|
22
|
+
span({
|
|
23
|
+
item: 'Server-side environment variables and JVM system properties',
|
|
24
|
+
className: 'xh-bold'
|
|
25
|
+
}),
|
|
26
|
+
filler(),
|
|
27
|
+
gridCountLabel({unit: 'entries'}),
|
|
28
|
+
'-',
|
|
29
|
+
storeFilterField({matchMode: 'any'}),
|
|
30
|
+
exportButton()
|
|
31
|
+
],
|
|
32
|
+
item: lastLoadException ? errorMessage({error: lastLoadException}) : grid(),
|
|
33
|
+
mask: 'onLoad'
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
});
|
|
@@ -6,11 +6,11 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import {ChartModel} from '@xh/hoist/cmp/chart';
|
|
8
8
|
import {GridModel} from '@xh/hoist/cmp/grid';
|
|
9
|
-
import {HoistModel,
|
|
9
|
+
import {HoistModel, managed, XH} from '@xh/hoist/core';
|
|
10
10
|
import {fmtTime} from '@xh/hoist/format';
|
|
11
11
|
import {checkMinVersion} from '@xh/hoist/utils/js';
|
|
12
12
|
import {forOwn, sortBy} from 'lodash';
|
|
13
|
-
import * as MCol from '
|
|
13
|
+
import * as MCol from '../../monitor/MonitorColumns';
|
|
14
14
|
|
|
15
15
|
export class MemoryMonitorModel extends HoistModel {
|
|
16
16
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {MemoryMonitorModel} from '@xh/hoist/admin/tabs/
|
|
1
|
+
import {MemoryMonitorModel} from '@xh/hoist/admin/tabs/server/memory/MemoryMonitorModel';
|
|
2
2
|
import {chart} from '@xh/hoist/cmp/chart';
|
|
3
3
|
import {grid, gridCountLabel} from '@xh/hoist/cmp/grid';
|
|
4
4
|
import {filler, placeholder} from '@xh/hoist/cmp/layout';
|
|
@@ -30,6 +30,7 @@ export const memoryMonitorPanel = hoistCmp.factory({
|
|
|
30
30
|
}),
|
|
31
31
|
filler(),
|
|
32
32
|
gridCountLabel({unit: 'snapshot'}),
|
|
33
|
+
'-',
|
|
33
34
|
exportButton()
|
|
34
35
|
],
|
|
35
36
|
items: [
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Copyright © 2021 Extremely Heavy Industries Inc.
|
|
6
6
|
*/
|
|
7
7
|
import {grid, gridCountLabel} from '@xh/hoist/cmp/grid';
|
|
8
|
-
import {filler} from '@xh/hoist/cmp/layout';
|
|
8
|
+
import {filler, span} from '@xh/hoist/cmp/layout';
|
|
9
9
|
import {storeFilterField} from '@xh/hoist/cmp/store';
|
|
10
10
|
import {creates, hoistCmp} from '@xh/hoist/core';
|
|
11
11
|
import {button, exportButton} from '@xh/hoist/desktop/cmp/button';
|
|
@@ -20,6 +20,12 @@ export const servicePanel = hoistCmp.factory({
|
|
|
20
20
|
return panel({
|
|
21
21
|
mask: 'onLoad',
|
|
22
22
|
tbar: [
|
|
23
|
+
Icon.info(),
|
|
24
|
+
span({
|
|
25
|
+
item: 'Service classes for server-side Hoist and application-level business logic',
|
|
26
|
+
className: 'xh-bold'
|
|
27
|
+
}),
|
|
28
|
+
filler(),
|
|
23
29
|
button({
|
|
24
30
|
icon: Icon.reset(),
|
|
25
31
|
text: 'Clear Selected',
|
|
@@ -27,9 +33,10 @@ export const servicePanel = hoistCmp.factory({
|
|
|
27
33
|
onClick: () => model.clearCachesAsync(),
|
|
28
34
|
disabled: model.gridModel.selModel.isEmpty
|
|
29
35
|
}),
|
|
30
|
-
|
|
36
|
+
'-',
|
|
31
37
|
gridCountLabel({unit: 'service'}),
|
|
32
|
-
|
|
38
|
+
'-',
|
|
39
|
+
storeFilterField({matchMode: 'any'}),
|
|
33
40
|
exportButton()
|
|
34
41
|
],
|
|
35
42
|
item: grid({
|
|
@@ -15,6 +15,7 @@ import {ImpersonationBarModel} from './ImpersonationBarModel';
|
|
|
15
15
|
import {MessageSourceModel} from './MessageSourceModel';
|
|
16
16
|
import {OptionsDialogModel} from './OptionsDialogModel';
|
|
17
17
|
import {SizingModeModel} from './SizingModeModel';
|
|
18
|
+
import {ViewportSizeModel} from './ViewportSizeModel';
|
|
18
19
|
import {ThemeModel} from './ThemeModel';
|
|
19
20
|
import {ToastSourceModel} from './ToastSourceModel';
|
|
20
21
|
|
|
@@ -42,6 +43,7 @@ export class AppContainerModel extends HoistModel {
|
|
|
42
43
|
|
|
43
44
|
@managed refreshContextModel = new RootRefreshContextModel();
|
|
44
45
|
@managed sizingModeModel = new SizingModeModel();
|
|
46
|
+
@managed viewportSizeModel = new ViewportSizeModel();
|
|
45
47
|
@managed themeModel = new ThemeModel();
|
|
46
48
|
|
|
47
49
|
init() {
|
|
@@ -58,6 +60,7 @@ export class AppContainerModel extends HoistModel {
|
|
|
58
60
|
this.toastSourceModel,
|
|
59
61
|
this.refreshContextModel,
|
|
60
62
|
this.sizingModeModel,
|
|
63
|
+
this.viewportSizeModel,
|
|
61
64
|
this.themeModel
|
|
62
65
|
];
|
|
63
66
|
models.forEach(it => {
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
import {FormModel} from '@xh/hoist/cmp/form';
|
|
8
8
|
import {HoistModel, managed, TaskObserver, XH} from '@xh/hoist/core';
|
|
9
9
|
import {action, computed, makeObservable, observable} from '@xh/hoist/mobx';
|
|
10
|
-
import {assign} from 'lodash';
|
|
10
|
+
import {assign, mapValues, pickBy} from 'lodash';
|
|
11
11
|
import {AppOption} from './AppOption';
|
|
12
12
|
|
|
13
13
|
/**
|
|
@@ -113,11 +113,18 @@ export class OptionsDialogModel extends HoistModel {
|
|
|
113
113
|
}
|
|
114
114
|
|
|
115
115
|
async doSaveAsync() {
|
|
116
|
-
const {formModel} = this
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
116
|
+
const {formModel} = this,
|
|
117
|
+
dirtyFields = pickBy(formModel.fields, {isDirty: true}),
|
|
118
|
+
promises = this.options
|
|
119
|
+
.filter(o => dirtyFields[o.name])
|
|
120
|
+
.map(o => o.setValueAsync(o.name, dirtyFields[o.name].value));
|
|
120
121
|
await Promise.allSettled(promises);
|
|
121
|
-
|
|
122
|
+
await XH.prefService.pushPendingAsync();
|
|
123
|
+
|
|
124
|
+
XH.track({
|
|
125
|
+
message: 'Changed options',
|
|
126
|
+
category: 'App',
|
|
127
|
+
data: mapValues(dirtyFields, f => ({value: f.value, oldValue: f.initialValue}))
|
|
128
|
+
});
|
|
122
129
|
}
|
|
123
130
|
}
|
|
@@ -0,0 +1,49 @@
|
|
|
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 © 2021 Extremely Heavy Industries Inc.
|
|
6
|
+
*/
|
|
7
|
+
import {HoistModel} from '@xh/hoist/core';
|
|
8
|
+
import {action, computed, observable, makeObservable} from '@xh/hoist/mobx';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Track observable width / height of the browser viewport, and provide observable
|
|
12
|
+
* access to device orientation
|
|
13
|
+
*
|
|
14
|
+
* @private
|
|
15
|
+
*/
|
|
16
|
+
export class ViewportSizeModel extends HoistModel {
|
|
17
|
+
|
|
18
|
+
/** @member {Object} - contains `width` and `height` in pixels */
|
|
19
|
+
@observable.ref size;
|
|
20
|
+
|
|
21
|
+
/** @returns {boolean} */
|
|
22
|
+
@computed
|
|
23
|
+
get isPortrait() {
|
|
24
|
+
return this.size.width < this.size.height;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** @returns {boolean} */
|
|
28
|
+
get isLandscape() {
|
|
29
|
+
return !this.isPortrait;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
constructor() {
|
|
33
|
+
super();
|
|
34
|
+
makeObservable(this);
|
|
35
|
+
window.addEventListener('resize', () => this.setViewportSize());
|
|
36
|
+
this.setViewportSize();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
//---------------------
|
|
40
|
+
// Implementation
|
|
41
|
+
//---------------------
|
|
42
|
+
@action
|
|
43
|
+
setViewportSize() {
|
|
44
|
+
this.size = {
|
|
45
|
+
width: window.innerWidth,
|
|
46
|
+
height: window.innerHeight
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
}
|
package/cmp/ag-grid/AgGrid.scss
CHANGED
|
@@ -391,21 +391,23 @@
|
|
|
391
391
|
}
|
|
392
392
|
|
|
393
393
|
//------------------------
|
|
394
|
-
// Context Menu
|
|
394
|
+
// Context Menu
|
|
395
395
|
//------------------------
|
|
396
396
|
.ag-theme-balham .ag-menu,
|
|
397
397
|
.ag-theme-balham-dark .ag-menu {
|
|
398
398
|
font-family: var(--xh-font-family);
|
|
399
|
+
font-size: var(--xh-menu-item-font-size-px);
|
|
400
|
+
color: var(--xh-menu-item-text-color);
|
|
399
401
|
|
|
400
402
|
// Minimal/high-contrast bg
|
|
401
|
-
background-color: var(--xh-bg);
|
|
402
|
-
border: var(--xh-border
|
|
403
|
+
background-color: var(--xh-menu-bg);
|
|
404
|
+
border: var(--xh-menu-border);
|
|
403
405
|
|
|
404
406
|
// Matching box-shadow of Blueprint context menu popover
|
|
405
407
|
box-shadow: 0 0 0 1px rgba(16, 22, 26, 0.2), 0 2px 4px rgba(16, 22, 26, 0.4), 0 8px 24px rgba(16, 22, 26, 0.4);
|
|
406
408
|
|
|
407
409
|
.ag-menu-option.ag-menu-option-active {
|
|
408
|
-
background-color: var(--xh-
|
|
410
|
+
background-color: var(--xh-menu-item-highlight-bg);
|
|
409
411
|
}
|
|
410
412
|
|
|
411
413
|
.ag-menu-option-icon {
|
|
@@ -421,6 +423,6 @@
|
|
|
421
423
|
|
|
422
424
|
// Keep the submenu caret in the standard text color
|
|
423
425
|
.ag-menu-option-popup-pointer {
|
|
424
|
-
color: var(--xh-text-color);
|
|
426
|
+
color: var(--xh-menu-item-text-color);
|
|
425
427
|
}
|
|
426
428
|
}
|