@dhis2-ui/header-bar 7.0.1 → 7.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/build/cjs/features/the_headerbar_contains_a_profile_menu/the_user_can_log_out.js +34 -3
- package/build/cjs/features/the_headerbar_contains_a_profile_menu.feature +9 -0
- package/build/cjs/profile/profile-menu.js +29 -3
- package/build/es/features/the_headerbar_contains_a_profile_menu/the_user_can_log_out.js +34 -3
- package/build/es/features/the_headerbar_contains_a_profile_menu.feature +9 -0
- package/build/es/profile/profile-menu.js +23 -4
- package/package.json +12 -9
|
@@ -1,11 +1,42 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
require("../common/index");
|
|
4
|
-
|
|
5
3
|
var _steps = require("cypress-cucumber-preprocessor/steps");
|
|
6
4
|
|
|
5
|
+
var _index = require("../common/index");
|
|
6
|
+
|
|
7
|
+
const logoutUrl = `${_index.baseUrl}dhis-web-commons-security/logout.action`;
|
|
7
8
|
(0, _steps.Then)('contains a link to log out the user', () => {
|
|
8
9
|
cy.get('[data-test="headerbar-profile-menu"] > li').should(lis => {
|
|
9
|
-
|
|
10
|
+
const menuItem = lis.eq(4);
|
|
11
|
+
expect(menuItem).to.be.visible;
|
|
12
|
+
expect(menuItem.find('a')).to.have.attr('href', logoutUrl);
|
|
10
13
|
});
|
|
14
|
+
});
|
|
15
|
+
(0, _steps.And)('there is no loading mask', () => {
|
|
16
|
+
cy.get('[data-test="headerbar-profile-menu-loading-mask"]').should('not.exist');
|
|
17
|
+
});
|
|
18
|
+
(0, _steps.Then)('the user clicks the link to log out', () => {
|
|
19
|
+
cy.get('[data-test="headerbar-profile-menu"] > li:nth-child(5)').trigger('click');
|
|
20
|
+
});
|
|
21
|
+
(0, _steps.Then)('a loading mask covers the screen', () => {
|
|
22
|
+
cy.get('[data-test="headerbar-profile-menu-loading-mask"]').should('be.visible');
|
|
23
|
+
}); // Currently not working
|
|
24
|
+
|
|
25
|
+
(0, _steps.And)('clearSensitiveCaches is called', async () => {
|
|
26
|
+
// Open caches to test 'clearSensitiveCaches':
|
|
27
|
+
// A keepable cache
|
|
28
|
+
await caches.open('workbox-precache-v2-asdf'); // Other, potentially-sensitive cache
|
|
29
|
+
|
|
30
|
+
await caches.open('test-cache'); // Todo: wait for function to resolve (loading mask goes away?)
|
|
31
|
+
|
|
32
|
+
const keys = await caches.keys(); // Static asset caches are kept
|
|
33
|
+
|
|
34
|
+
expect(keys).to.include('workbox-precache-v2-asdf'); // Others are removed
|
|
35
|
+
|
|
36
|
+
expect(keys).not.to.include('test-cache');
|
|
37
|
+
}); // Currently not working
|
|
38
|
+
|
|
39
|
+
(0, _steps.Then)('the window navigates to the logout URL', () => {// (Currently unable to stub window.location.assign;
|
|
40
|
+
// would be done in 'Then the user clicks link to log out')
|
|
41
|
+
// cy.get('@locationAssign').should('be.calledWith', logoutUrl)
|
|
11
42
|
});
|
|
@@ -57,6 +57,15 @@ Feature: The HeaderBar contains a profile menu
|
|
|
57
57
|
Given the HeaderBar loads without an error
|
|
58
58
|
When the user opens the menu
|
|
59
59
|
Then contains a link to log out the user
|
|
60
|
+
And there is no loading mask
|
|
61
|
+
|
|
62
|
+
# The following are omitted because of testing complications
|
|
63
|
+
# around navigation:
|
|
64
|
+
|
|
65
|
+
# Then the user clicks the link to log out
|
|
66
|
+
# Then a loading mask covers the screen
|
|
67
|
+
# And clearSensitiveCaches is called
|
|
68
|
+
# Then the window navigates to the logout URL
|
|
60
69
|
|
|
61
70
|
Scenario: The profile menu closes when the user clicks outside
|
|
62
71
|
Given the HeaderBar loads without an error
|
|
@@ -9,8 +9,14 @@ var _style = _interopRequireDefault(require("styled-jsx/style"));
|
|
|
9
9
|
|
|
10
10
|
var _card = require("@dhis2-ui/card");
|
|
11
11
|
|
|
12
|
+
var _center = require("@dhis2-ui/center");
|
|
13
|
+
|
|
12
14
|
var _divider = require("@dhis2-ui/divider");
|
|
13
15
|
|
|
16
|
+
var _layer = require("@dhis2-ui/layer");
|
|
17
|
+
|
|
18
|
+
var _loader = require("@dhis2-ui/loader");
|
|
19
|
+
|
|
14
20
|
var _menu = require("@dhis2-ui/menu");
|
|
15
21
|
|
|
16
22
|
var _appRuntime = require("@dhis2/app-runtime");
|
|
@@ -21,7 +27,7 @@ var _uiConstants = require("@dhis2/ui-constants");
|
|
|
21
27
|
|
|
22
28
|
var _uiIcons = require("@dhis2/ui-icons");
|
|
23
29
|
|
|
24
|
-
var _react =
|
|
30
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
25
31
|
|
|
26
32
|
var _joinPath = require("../join-path.js");
|
|
27
33
|
|
|
@@ -29,8 +35,18 @@ var _index = _interopRequireDefault(require("../locales/index.js"));
|
|
|
29
35
|
|
|
30
36
|
var _profileHeader = require("./profile-header.js");
|
|
31
37
|
|
|
38
|
+
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
39
|
+
|
|
40
|
+
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
41
|
+
|
|
32
42
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
33
43
|
|
|
44
|
+
const LoadingMask = () => /*#__PURE__*/_react.default.createElement(_layer.Layer, {
|
|
45
|
+
translucent: true,
|
|
46
|
+
disablePortal: true,
|
|
47
|
+
dataTest: "headerbar-profile-menu-loading-mask"
|
|
48
|
+
}, /*#__PURE__*/_react.default.createElement(_center.Center, null, /*#__PURE__*/_react.default.createElement(_loader.CircularLoader, null)));
|
|
49
|
+
|
|
34
50
|
const ProfileContents = ({
|
|
35
51
|
name,
|
|
36
52
|
email,
|
|
@@ -40,6 +56,7 @@ const ProfileContents = ({
|
|
|
40
56
|
const {
|
|
41
57
|
baseUrl
|
|
42
58
|
} = (0, _appRuntime.useConfig)();
|
|
59
|
+
const [loading, setLoading] = (0, _react.useState)(false);
|
|
43
60
|
return /*#__PURE__*/_react.default.createElement(_card.Card, null, /*#__PURE__*/_react.default.createElement("div", {
|
|
44
61
|
className: "jsx-2099675810"
|
|
45
62
|
}, /*#__PURE__*/_react.default.createElement(_profileHeader.ProfileHeader, {
|
|
@@ -80,13 +97,22 @@ const ProfileContents = ({
|
|
|
80
97
|
color: _uiConstants.colors.grey700
|
|
81
98
|
})
|
|
82
99
|
}), /*#__PURE__*/_react.default.createElement(_menu.MenuItem, {
|
|
83
|
-
href: (0, _joinPath.joinPath)(baseUrl, 'dhis-web-commons-security/logout.action'),
|
|
100
|
+
href: (0, _joinPath.joinPath)(baseUrl, 'dhis-web-commons-security/logout.action') // NB: By MenuItem implementation, this callback
|
|
101
|
+
// overwrites default navigation behavior but maintains
|
|
102
|
+
// the href attribute
|
|
103
|
+
,
|
|
104
|
+
onClick: async () => {
|
|
105
|
+
setLoading(true);
|
|
106
|
+
await (0, _appRuntime.clearSensitiveCaches)();
|
|
107
|
+
setLoading(false);
|
|
108
|
+
window.location.assign((0, _joinPath.joinPath)(baseUrl, 'dhis-web-commons-security/logout.action'));
|
|
109
|
+
},
|
|
84
110
|
label: _index.default.t('Logout'),
|
|
85
111
|
value: "logout",
|
|
86
112
|
icon: /*#__PURE__*/_react.default.createElement(_uiIcons.IconLogOut24, {
|
|
87
113
|
color: _uiConstants.colors.grey700
|
|
88
114
|
})
|
|
89
|
-
}))), /*#__PURE__*/_react.default.createElement(_style.default, {
|
|
115
|
+
}))), loading && /*#__PURE__*/_react.default.createElement(LoadingMask, null), /*#__PURE__*/_react.default.createElement(_style.default, {
|
|
90
116
|
id: "2099675810"
|
|
91
117
|
}, ["div.jsx-2099675810{width:100%;padding:0;}", "ul.jsx-2099675810{padding:0;margin:0;}", "a.jsx-2099675810,a.jsx-2099675810:hover,a.jsx-2099675810:focus,a.jsx-2099675810:active,a.jsx-2099675810:visited{-webkit-text-decoration:none;text-decoration:none;display:block;}"]));
|
|
92
118
|
};
|
|
@@ -1,7 +1,38 @@
|
|
|
1
|
-
import '
|
|
2
|
-
import {
|
|
1
|
+
import { And, Then } from 'cypress-cucumber-preprocessor/steps';
|
|
2
|
+
import { baseUrl } from '../common/index';
|
|
3
|
+
const logoutUrl = `${baseUrl}dhis-web-commons-security/logout.action`;
|
|
3
4
|
Then('contains a link to log out the user', () => {
|
|
4
5
|
cy.get('[data-test="headerbar-profile-menu"] > li').should(lis => {
|
|
5
|
-
|
|
6
|
+
const menuItem = lis.eq(4);
|
|
7
|
+
expect(menuItem).to.be.visible;
|
|
8
|
+
expect(menuItem.find('a')).to.have.attr('href', logoutUrl);
|
|
6
9
|
});
|
|
10
|
+
});
|
|
11
|
+
And('there is no loading mask', () => {
|
|
12
|
+
cy.get('[data-test="headerbar-profile-menu-loading-mask"]').should('not.exist');
|
|
13
|
+
});
|
|
14
|
+
Then('the user clicks the link to log out', () => {
|
|
15
|
+
cy.get('[data-test="headerbar-profile-menu"] > li:nth-child(5)').trigger('click');
|
|
16
|
+
});
|
|
17
|
+
Then('a loading mask covers the screen', () => {
|
|
18
|
+
cy.get('[data-test="headerbar-profile-menu-loading-mask"]').should('be.visible');
|
|
19
|
+
}); // Currently not working
|
|
20
|
+
|
|
21
|
+
And('clearSensitiveCaches is called', async () => {
|
|
22
|
+
// Open caches to test 'clearSensitiveCaches':
|
|
23
|
+
// A keepable cache
|
|
24
|
+
await caches.open('workbox-precache-v2-asdf'); // Other, potentially-sensitive cache
|
|
25
|
+
|
|
26
|
+
await caches.open('test-cache'); // Todo: wait for function to resolve (loading mask goes away?)
|
|
27
|
+
|
|
28
|
+
const keys = await caches.keys(); // Static asset caches are kept
|
|
29
|
+
|
|
30
|
+
expect(keys).to.include('workbox-precache-v2-asdf'); // Others are removed
|
|
31
|
+
|
|
32
|
+
expect(keys).not.to.include('test-cache');
|
|
33
|
+
}); // Currently not working
|
|
34
|
+
|
|
35
|
+
Then('the window navigates to the logout URL', () => {// (Currently unable to stub window.location.assign;
|
|
36
|
+
// would be done in 'Then the user clicks link to log out')
|
|
37
|
+
// cy.get('@locationAssign').should('be.calledWith', logoutUrl)
|
|
7
38
|
});
|
|
@@ -57,6 +57,15 @@ Feature: The HeaderBar contains a profile menu
|
|
|
57
57
|
Given the HeaderBar loads without an error
|
|
58
58
|
When the user opens the menu
|
|
59
59
|
Then contains a link to log out the user
|
|
60
|
+
And there is no loading mask
|
|
61
|
+
|
|
62
|
+
# The following are omitted because of testing complications
|
|
63
|
+
# around navigation:
|
|
64
|
+
|
|
65
|
+
# Then the user clicks the link to log out
|
|
66
|
+
# Then a loading mask covers the screen
|
|
67
|
+
# And clearSensitiveCaches is called
|
|
68
|
+
# Then the window navigates to the logout URL
|
|
60
69
|
|
|
61
70
|
Scenario: The profile menu closes when the user clicks outside
|
|
62
71
|
Given the HeaderBar loads without an error
|
|
@@ -1,16 +1,25 @@
|
|
|
1
1
|
import _JSXStyle from "styled-jsx/style";
|
|
2
2
|
import { Card } from '@dhis2-ui/card';
|
|
3
|
+
import { Center } from '@dhis2-ui/center';
|
|
3
4
|
import { Divider } from '@dhis2-ui/divider';
|
|
5
|
+
import { Layer } from '@dhis2-ui/layer';
|
|
6
|
+
import { CircularLoader } from '@dhis2-ui/loader';
|
|
4
7
|
import { MenuItem } from '@dhis2-ui/menu';
|
|
5
|
-
import { useConfig } from '@dhis2/app-runtime';
|
|
8
|
+
import { useConfig, clearSensitiveCaches } from '@dhis2/app-runtime';
|
|
6
9
|
import propTypes from '@dhis2/prop-types';
|
|
7
10
|
import { colors } from '@dhis2/ui-constants';
|
|
8
11
|
import { IconSettings24, IconInfo24, IconLogOut24, IconUser24, IconQuestion24 } from '@dhis2/ui-icons';
|
|
9
|
-
import React from 'react';
|
|
12
|
+
import React, { useState } from 'react';
|
|
10
13
|
import { joinPath } from '../join-path.js';
|
|
11
14
|
import i18n from '../locales/index.js';
|
|
12
15
|
import { ProfileHeader } from './profile-header.js';
|
|
13
16
|
|
|
17
|
+
const LoadingMask = () => /*#__PURE__*/React.createElement(Layer, {
|
|
18
|
+
translucent: true,
|
|
19
|
+
disablePortal: true,
|
|
20
|
+
dataTest: "headerbar-profile-menu-loading-mask"
|
|
21
|
+
}, /*#__PURE__*/React.createElement(Center, null, /*#__PURE__*/React.createElement(CircularLoader, null)));
|
|
22
|
+
|
|
14
23
|
const ProfileContents = ({
|
|
15
24
|
name,
|
|
16
25
|
email,
|
|
@@ -20,6 +29,7 @@ const ProfileContents = ({
|
|
|
20
29
|
const {
|
|
21
30
|
baseUrl
|
|
22
31
|
} = useConfig();
|
|
32
|
+
const [loading, setLoading] = useState(false);
|
|
23
33
|
return /*#__PURE__*/React.createElement(Card, null, /*#__PURE__*/React.createElement("div", {
|
|
24
34
|
className: "jsx-2099675810"
|
|
25
35
|
}, /*#__PURE__*/React.createElement(ProfileHeader, {
|
|
@@ -60,13 +70,22 @@ const ProfileContents = ({
|
|
|
60
70
|
color: colors.grey700
|
|
61
71
|
})
|
|
62
72
|
}), /*#__PURE__*/React.createElement(MenuItem, {
|
|
63
|
-
href: joinPath(baseUrl, 'dhis-web-commons-security/logout.action'),
|
|
73
|
+
href: joinPath(baseUrl, 'dhis-web-commons-security/logout.action') // NB: By MenuItem implementation, this callback
|
|
74
|
+
// overwrites default navigation behavior but maintains
|
|
75
|
+
// the href attribute
|
|
76
|
+
,
|
|
77
|
+
onClick: async () => {
|
|
78
|
+
setLoading(true);
|
|
79
|
+
await clearSensitiveCaches();
|
|
80
|
+
setLoading(false);
|
|
81
|
+
window.location.assign(joinPath(baseUrl, 'dhis-web-commons-security/logout.action'));
|
|
82
|
+
},
|
|
64
83
|
label: i18n.t('Logout'),
|
|
65
84
|
value: "logout",
|
|
66
85
|
icon: /*#__PURE__*/React.createElement(IconLogOut24, {
|
|
67
86
|
color: colors.grey700
|
|
68
87
|
})
|
|
69
|
-
}))), /*#__PURE__*/React.createElement(_JSXStyle, {
|
|
88
|
+
}))), loading && /*#__PURE__*/React.createElement(LoadingMask, null), /*#__PURE__*/React.createElement(_JSXStyle, {
|
|
70
89
|
id: "2099675810"
|
|
71
90
|
}, ["div.jsx-2099675810{width:100%;padding:0;}", "ul.jsx-2099675810{padding:0;margin:0;}", "a.jsx-2099675810,a.jsx-2099675810:hover,a.jsx-2099675810:focus,a.jsx-2099675810:active,a.jsx-2099675810:visited{-webkit-text-decoration:none;text-decoration:none;display:block;}"]));
|
|
72
91
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dhis2-ui/header-bar",
|
|
3
|
-
"version": "7.0
|
|
3
|
+
"version": "7.1.0",
|
|
4
4
|
"description": "UI HeaderBar",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -33,15 +33,18 @@
|
|
|
33
33
|
"styled-jsx": "^4"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@dhis2-ui/box": "7.0
|
|
37
|
-
"@dhis2-ui/card": "7.0
|
|
38
|
-
"@dhis2-ui/
|
|
39
|
-
"@dhis2-ui/
|
|
40
|
-
"@dhis2-ui/
|
|
41
|
-
"@dhis2-ui/
|
|
36
|
+
"@dhis2-ui/box": "7.1.0",
|
|
37
|
+
"@dhis2-ui/card": "7.1.0",
|
|
38
|
+
"@dhis2-ui/center": "7.1.0",
|
|
39
|
+
"@dhis2-ui/divider": "7.1.0",
|
|
40
|
+
"@dhis2-ui/input": "7.1.0",
|
|
41
|
+
"@dhis2-ui/layer": "7.1.0",
|
|
42
|
+
"@dhis2-ui/loader": "7.1.0",
|
|
43
|
+
"@dhis2-ui/logo": "7.1.0",
|
|
44
|
+
"@dhis2-ui/menu": "7.1.0",
|
|
42
45
|
"@dhis2/prop-types": "^1.6.4",
|
|
43
|
-
"@dhis2/ui-constants": "7.0
|
|
44
|
-
"@dhis2/ui-icons": "7.0
|
|
46
|
+
"@dhis2/ui-constants": "7.1.0",
|
|
47
|
+
"@dhis2/ui-icons": "7.1.0",
|
|
45
48
|
"classnames": "^2.3.1",
|
|
46
49
|
"moment": "^2.29.1",
|
|
47
50
|
"prop-types": "^15.7.2"
|