@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.
@@ -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
- expect(lis.eq(4)).to.be.visible;
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 = _interopRequireDefault(require("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 '../common/index';
2
- import { Then } from 'cypress-cucumber-preprocessor/steps';
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
- expect(lis.eq(4)).to.be.visible;
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.1",
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.1",
37
- "@dhis2-ui/card": "7.0.1",
38
- "@dhis2-ui/divider": "7.0.1",
39
- "@dhis2-ui/input": "7.0.1",
40
- "@dhis2-ui/logo": "7.0.1",
41
- "@dhis2-ui/menu": "7.0.1",
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.1",
44
- "@dhis2/ui-icons": "7.0.1",
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"