@dhis2-ui/header-bar 8.4.16 → 8.5.0-beta.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.
Files changed (53) hide show
  1. package/build/cjs/__e2e__/header-bar.stories.e2e.js +40 -0
  2. package/build/cjs/__e2e__/stories/common.js +99 -32
  3. package/build/cjs/__e2e__/stories/with-debug-info-edge-cases.js +45 -0
  4. package/build/cjs/__e2e__/stories/with-update-available-notification.js +38 -0
  5. package/build/cjs/apps.js +1 -1
  6. package/build/cjs/debug-info/debug-info-menu-item.js +67 -0
  7. package/build/cjs/debug-info/debug-info-modal.js +59 -0
  8. package/build/cjs/debug-info/debug-info-table.js +47 -0
  9. package/build/cjs/debug-info/use-debug-info.js +28 -0
  10. package/build/cjs/features/the_headerbar_should_display_app_update_notification/index.js +34 -0
  11. package/build/cjs/features/the_headerbar_should_display_app_update_notification.feature +22 -0
  12. package/build/cjs/features/the_headerbar_should_display_debug_version_infos/index.js +69 -0
  13. package/build/cjs/features/the_headerbar_should_display_debug_version_infos.feature +52 -0
  14. package/build/cjs/header-bar-context.js +46 -0
  15. package/build/cjs/header-bar.js +22 -11
  16. package/build/cjs/header-bar.stories.js +70 -72
  17. package/build/cjs/locales/en/translations.json +12 -1
  18. package/build/cjs/profile/use-on-doc-click.js +30 -0
  19. package/build/cjs/profile/use-on-doc-click.test.js +42 -0
  20. package/build/cjs/profile-menu/index.js +18 -0
  21. package/build/cjs/{profile → profile-menu}/profile-header.js +0 -0
  22. package/build/cjs/{profile → profile-menu}/profile-menu.js +23 -15
  23. package/build/cjs/profile-menu/update-notification.js +70 -0
  24. package/build/cjs/profile.js +52 -62
  25. package/build/es/__e2e__/header-bar.stories.e2e.js +5 -3
  26. package/build/es/__e2e__/stories/common.js +96 -33
  27. package/build/es/__e2e__/stories/with-debug-info-edge-cases.js +22 -0
  28. package/build/es/__e2e__/stories/with-update-available-notification.js +19 -0
  29. package/build/es/apps.js +1 -1
  30. package/build/es/debug-info/debug-info-menu-item.js +48 -0
  31. package/build/es/debug-info/debug-info-modal.js +41 -0
  32. package/build/es/debug-info/debug-info-table.js +35 -0
  33. package/build/es/debug-info/use-debug-info.js +15 -0
  34. package/build/es/features/the_headerbar_should_display_app_update_notification/index.js +31 -0
  35. package/build/es/features/the_headerbar_should_display_app_update_notification.feature +22 -0
  36. package/build/es/features/the_headerbar_should_display_debug_version_infos/index.js +66 -0
  37. package/build/es/features/the_headerbar_should_display_debug_version_infos.feature +52 -0
  38. package/build/es/header-bar-context.js +25 -0
  39. package/build/es/header-bar.js +21 -11
  40. package/build/es/header-bar.stories.js +65 -71
  41. package/build/es/locales/en/translations.json +12 -1
  42. package/build/es/profile/use-on-doc-click.js +20 -0
  43. package/build/es/profile/use-on-doc-click.test.js +38 -0
  44. package/build/es/profile-menu/index.js +1 -0
  45. package/build/es/{profile → profile-menu}/profile-header.js +0 -0
  46. package/build/es/{profile → profile-menu}/profile-menu.js +23 -17
  47. package/build/es/profile-menu/update-notification.js +51 -0
  48. package/build/es/profile.js +49 -64
  49. package/package.json +15 -13
  50. package/build/cjs/features/the_headerbar_displays_instance_and_app_infos/index.js +0 -15
  51. package/build/cjs/features/the_headerbar_displays_instance_and_app_infos.feature +0 -29
  52. package/build/es/features/the_headerbar_displays_instance_and_app_infos/index.js +0 -12
  53. package/build/es/features/the_headerbar_displays_instance_and_app_infos.feature +0 -29
@@ -0,0 +1,52 @@
1
+ Feature: The HeaderBar should display debug version infos
2
+
3
+ Scenario: The debug version infos are displayed in the profile menu
4
+ Given the HeaderBar is rendered with an app name and app version in runtime context
5
+ When the user opens the profile menu
6
+ Then the instance version should be displayed
7
+ And the app's name and version should be displayed
8
+
9
+ Scenario: The debug version info modal is displayed when clicking on the menu item
10
+ Given the HeaderBar is rendered with an app name and app version in runtime context
11
+ When the user opens the profile menu
12
+ When the user clicks the debug info menu item
13
+ Then the debug info modal should be shown
14
+
15
+ Scenario: The debug version info modal displays debug info
16
+ Given the HeaderBar is rendered with an app name and app version in runtime context
17
+ When the user opens the profile menu
18
+ When the user clicks the debug info menu item
19
+ Then the debug info modal should contain debug info
20
+
21
+ Scenario: The debug version info should be copied to clipboard
22
+ Given the HeaderBar is rendered with an app name and app version in runtime context
23
+ When the user opens the profile menu
24
+ When the user clicks the debug info menu item
25
+ When the user clicks the copy debug info button
26
+ Then the debug info should be copied to clipboard
27
+ And the debug info copied to clipboard alert should be shown
28
+ And the debug info modal should not be shown
29
+
30
+ Scenario: The debug version infos are displayed with unknown dhis2 version in the profile menu
31
+ Given the HeaderBar is rendered without an instance version in runtime context
32
+ When the user opens the profile menu
33
+ Then the instance version should show as unknown
34
+ And the app's name and version should be displayed
35
+
36
+ Scenario: The debug version infos are displayed with unknown app name and version in the profile menu
37
+ Given the HeaderBar is rendered without app name or app version in runtime context
38
+ When the user opens the profile menu
39
+ Then the instance version should be displayed
40
+ And the unknown app with unknown version should be displayed
41
+
42
+ Scenario: The debug version infos are displayed with unknown app name in the profile menu
43
+ Given the HeaderBar is rendered without app name in runtime context
44
+ When the user opens the profile menu
45
+ Then the instance version should be displayed
46
+ And the unknown app with app's version should be displayed
47
+
48
+ Scenario: The debug version infos are displayed with unknown app version in the profile menu
49
+ Given the HeaderBar is rendered with an app name but without app version in runtime context
50
+ When the user opens the profile menu
51
+ Then the instance version should be displayed
52
+ And the app's name with unknown version should be displayed
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.useHeaderBarContext = exports.HeaderBarContextProvider = void 0;
7
+
8
+ var _propTypes = _interopRequireDefault(require("prop-types"));
9
+
10
+ var _react = _interopRequireWildcard(require("react"));
11
+
12
+ 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); }
13
+
14
+ 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; }
15
+
16
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
17
+
18
+ const headerBarContext = /*#__PURE__*/(0, _react.createContext)({
19
+ updateAvailable: false,
20
+ onApplyAvailableUpdate: () => {}
21
+ });
22
+
23
+ const HeaderBarContextProvider = _ref => {
24
+ let {
25
+ updateAvailable,
26
+ onApplyAvailableUpdate,
27
+ children
28
+ } = _ref;
29
+ return /*#__PURE__*/_react.default.createElement(headerBarContext.Provider, {
30
+ value: {
31
+ updateAvailable,
32
+ onApplyAvailableUpdate
33
+ }
34
+ }, children);
35
+ };
36
+
37
+ exports.HeaderBarContextProvider = HeaderBarContextProvider;
38
+ HeaderBarContextProvider.propTypes = {
39
+ children: _propTypes.default.node,
40
+ updateAvailable: _propTypes.default.bool,
41
+ onApplyAvailableUpdate: _propTypes.default.func
42
+ };
43
+
44
+ const useHeaderBarContext = () => (0, _react.useContext)(headerBarContext);
45
+
46
+ exports.useHeaderBarContext = useHeaderBarContext;
@@ -17,6 +17,8 @@ var _react = _interopRequireWildcard(require("react"));
17
17
 
18
18
  var _apps = _interopRequireDefault(require("./apps.js"));
19
19
 
20
+ var _headerBarContext = require("./header-bar-context.js");
21
+
20
22
  var _joinPath = require("./join-path.js");
21
23
 
22
24
  var _index = _interopRequireDefault(require("./locales/index.js"));
@@ -63,9 +65,12 @@ const HeaderBar = _ref => {
63
65
 
64
66
  let {
65
67
  appName,
66
- className
68
+ className,
69
+ updateAvailable,
70
+ onApplyAvailableUpdate
67
71
  } = _ref;
68
72
  const {
73
+ appName: configAppName,
69
74
  baseUrl,
70
75
  pwaEnabled,
71
76
  headerbar: {
@@ -84,10 +89,11 @@ const HeaderBar = _ref => {
84
89
  icon: getPath(app.icon),
85
90
  defaultAction: getPath(app.defaultAction)
86
91
  }));
87
- }, [data]); // See https://jira.dhis2.org/browse/LIBS-180
92
+ }, [data, baseUrl]); // See https://jira.dhis2.org/browse/LIBS-180
88
93
 
89
94
  if (!loading && !error) {
90
- // TODO: This will run every render which is probably wrong! Also, setting the global locale shouldn't be done in the headerbar
95
+ // TODO: This will run every render which is probably wrong!
96
+ // Also, setting the global locale shouldn't be done in the headerbar
91
97
  const locale = data.user.settings.keyUiLocale || 'en';
92
98
 
93
99
  _index.default.setDefaultNamespace('default');
@@ -95,15 +101,18 @@ const HeaderBar = _ref => {
95
101
  _index.default.changeLanguage(locale);
96
102
  }
97
103
 
98
- return /*#__PURE__*/_react.default.createElement("header", {
99
- className: _style.default.dynamic([["3517276904", [_uiConstants.colors.white]]]) + " " + (className || "")
104
+ return /*#__PURE__*/_react.default.createElement(_headerBarContext.HeaderBarContextProvider, {
105
+ updateAvailable: updateAvailable,
106
+ onApplyAvailableUpdate: onApplyAvailableUpdate
107
+ }, /*#__PURE__*/_react.default.createElement("header", {
108
+ className: _style.default.dynamic([["3860078320", [_uiConstants.colors.white]]]) + " " + (className || "")
100
109
  }, /*#__PURE__*/_react.default.createElement("div", {
101
- className: _style.default.dynamic([["3517276904", [_uiConstants.colors.white]]]) + " " + "main"
110
+ className: _style.default.dynamic([["3860078320", [_uiConstants.colors.white]]]) + " " + "main"
102
111
  }, !loading && !error && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_logo.Logo, null), /*#__PURE__*/_react.default.createElement(_title.Title, {
103
- app: appName,
112
+ app: appName || configAppName,
104
113
  instance: data.title.applicationTitle
105
114
  }), /*#__PURE__*/_react.default.createElement("div", {
106
- className: _style.default.dynamic([["3517276904", [_uiConstants.colors.white]]]) + " " + "right-control-spacer"
115
+ className: _style.default.dynamic([["3860078320", [_uiConstants.colors.white]]]) + " " + "right-control-spacer"
107
116
  }), (pwaEnabled || showOnlineStatus) && /*#__PURE__*/_react.default.createElement(_onlineStatus.OnlineStatus, null), /*#__PURE__*/_react.default.createElement(_notifications.Notifications, {
108
117
  interpretations: data.notifications.unreadInterpretations,
109
118
  messages: data.notifications.unreadMessageConversations,
@@ -118,13 +127,15 @@ const HeaderBar = _ref => {
118
127
  }))), (pwaEnabled || showOnlineStatus) && !loading && !error && /*#__PURE__*/_react.default.createElement(_onlineStatus.OnlineStatus, {
119
128
  dense: true
120
129
  }), /*#__PURE__*/_react.default.createElement(_style.default, {
121
- id: "3517276904",
130
+ id: "3860078320",
122
131
  dynamic: [_uiConstants.colors.white]
123
- }, [".main.__jsx-style-dynamic-selector{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;background-color:#2c6693;border-bottom:1px solid rgba(32,32,32,0.15);color:".concat(_uiConstants.colors.white, ";height:48px;}"), ".right-control-spacer.__jsx-style-dynamic-selector{margin-left:auto;}"]));
132
+ }, [".main.__jsx-style-dynamic-selector{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;background-color:#2c6693;border-bottom:1px solid rgba(32,32,32,0.15);color:".concat(_uiConstants.colors.white, ";height:48px;}"), ".right-control-spacer.__jsx-style-dynamic-selector{margin-left:auto;}"])));
124
133
  };
125
134
 
126
135
  exports.HeaderBar = HeaderBar;
127
136
  HeaderBar.propTypes = {
128
137
  appName: _propTypes.default.string,
129
- className: _propTypes.default.string
138
+ className: _propTypes.default.string,
139
+ updateAvailable: _propTypes.default.bool,
140
+ onApplyAvailableUpdate: _propTypes.default.func
130
141
  };
@@ -3,38 +3,20 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.default = exports.WithOnlineStatus = exports.WithLastOnlineInfo = exports.NonEnglishUserLocale = exports.NoAuthorityForInterpretationsApp = exports.Loading = exports.Error = exports.Default = exports.CustomLogoWideDimension = void 0;
6
+ exports.default = exports.WithUpdateNotification = exports.WithOnlineStatus = exports.WithLastOnlineInfo = exports.NonEnglishUserLocale = exports.NoAuthorityForInterpretationsApp = exports.Loading = exports.Error = exports.Default = exports.CustomLogoWideDimension = void 0;
7
7
 
8
8
  var _appRuntime = require("@dhis2/app-runtime");
9
9
 
10
10
  var _react = _interopRequireDefault(require("react"));
11
11
 
12
+ var _common = require("./__e2e__/stories/common.js");
13
+
12
14
  var _headerBar = require("./header-bar.js");
13
15
 
14
16
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
17
 
16
18
  const subtitle = 'The common navigation bar used in all DHIS2 apps';
17
19
  const description = "\nThe header bar is mandatory for all apps. This creates a stable, understandable point of reference for the user across all kinds of different apps. It must always be displayed fixed to the top of the screen. Do not interfere or obstruct interaction with the header bar.\n\nThe header bar is included automatically with the App Shell and should not need any configuration.\n\n#### Theme\n\nThe header bar can be themeed to suit the brand/color of your DHIS2 instance. The color of the text/icons will be automatically adjusted based on the selected color.\n\n```js\nimport { HeaderBar } from '@dhis2/ui'\n```\n";
18
- var _default = {
19
- title: 'Header Bar',
20
- component: _headerBar.HeaderBar,
21
- parameters: {
22
- componentSubtitle: subtitle,
23
- docs: {
24
- description: {
25
- component: description
26
- }
27
- }
28
- },
29
- args: {
30
- appName: 'Example!'
31
- }
32
- };
33
- exports.default = _default;
34
- const mockConfig = {
35
- baseUrl: 'https://debug.dhis2.org/dev/',
36
- apiVersion: 33
37
- };
38
20
  const customData = {
39
21
  'systemSettings/applicationTitle': {
40
22
  applicationTitle: 'Foobar'
@@ -155,77 +137,86 @@ const customAuthoritiesData = { ...customData,
155
137
  authorities: ['M_dhis-web-messaging']
156
138
  }
157
139
  };
140
+ var _default = {
141
+ title: 'Header Bar',
142
+ component: _headerBar.HeaderBar,
143
+ parameters: {
144
+ componentSubtitle: subtitle,
145
+ docs: {
146
+ description: {
147
+ component: description
148
+ }
149
+ }
150
+ },
151
+ decorators: [(0, _common.createDecoratorProvider)()]
152
+ };
153
+ exports.default = _default;
158
154
 
159
- const Default = args => /*#__PURE__*/_react.default.createElement(_appRuntime.Provider, {
160
- config: mockConfig
161
- }, /*#__PURE__*/_react.default.createElement(_appRuntime.CustomDataProvider, {
155
+ const Default = () => /*#__PURE__*/_react.default.createElement(_appRuntime.CustomDataProvider, {
162
156
  data: customData
163
- }, /*#__PURE__*/_react.default.createElement(_headerBar.HeaderBar, args)));
157
+ }, /*#__PURE__*/_react.default.createElement(_headerBar.HeaderBar, {
158
+ appName: "Example!"
159
+ }));
164
160
 
165
161
  exports.Default = Default;
166
162
 
167
- const CustomLogoWideDimension = args => /*#__PURE__*/_react.default.createElement(_appRuntime.Provider, {
168
- config: mockConfig
169
- }, /*#__PURE__*/_react.default.createElement(_appRuntime.CustomDataProvider, {
163
+ const CustomLogoWideDimension = () => /*#__PURE__*/_react.default.createElement(_appRuntime.CustomDataProvider, {
170
164
  data: customLogoData
171
- }, /*#__PURE__*/_react.default.createElement(_headerBar.HeaderBar, args)));
165
+ }, /*#__PURE__*/_react.default.createElement(_headerBar.HeaderBar, {
166
+ appName: "Example!"
167
+ }));
172
168
 
173
169
  exports.CustomLogoWideDimension = CustomLogoWideDimension;
174
170
  CustomLogoWideDimension.storyName = 'Custom Logo (wide dimension)';
175
171
 
176
- const NonEnglishUserLocale = args => /*#__PURE__*/_react.default.createElement(_appRuntime.Provider, {
177
- config: mockConfig
178
- }, /*#__PURE__*/_react.default.createElement(_appRuntime.CustomDataProvider, {
172
+ const NonEnglishUserLocale = () => /*#__PURE__*/_react.default.createElement(_appRuntime.CustomDataProvider, {
179
173
  data: customLocaleData
180
- }, /*#__PURE__*/_react.default.createElement(_headerBar.HeaderBar, args)));
174
+ }, /*#__PURE__*/_react.default.createElement(_headerBar.HeaderBar, {
175
+ appName: "Exemple!"
176
+ }));
181
177
 
182
178
  exports.NonEnglishUserLocale = NonEnglishUserLocale;
183
- NonEnglishUserLocale.args = {
184
- appName: 'Exemple!'
185
- };
186
179
  NonEnglishUserLocale.storyName = 'Non-english user locale';
187
180
 
188
- const NoAuthorityForInterpretationsApp = args => /*#__PURE__*/_react.default.createElement(_appRuntime.Provider, {
189
- config: mockConfig
190
- }, /*#__PURE__*/_react.default.createElement(_appRuntime.CustomDataProvider, {
181
+ const NoAuthorityForInterpretationsApp = () => /*#__PURE__*/_react.default.createElement(_appRuntime.CustomDataProvider, {
191
182
  data: customAuthoritiesData
192
- }, /*#__PURE__*/_react.default.createElement(_headerBar.HeaderBar, args)));
183
+ }, /*#__PURE__*/_react.default.createElement(_headerBar.HeaderBar, {
184
+ appName: "Example!"
185
+ }));
193
186
 
194
187
  exports.NoAuthorityForInterpretationsApp = NoAuthorityForInterpretationsApp;
195
188
  NoAuthorityForInterpretationsApp.storyName = 'No authority for interpretations app';
196
189
 
197
- const Loading = args => /*#__PURE__*/_react.default.createElement(_appRuntime.Provider, {
198
- config: mockConfig
199
- }, /*#__PURE__*/_react.default.createElement(_appRuntime.CustomDataProvider, {
190
+ const Loading = () => /*#__PURE__*/_react.default.createElement(_appRuntime.CustomDataProvider, {
200
191
  options: {
201
192
  loadForever: true
202
193
  }
203
- }, /*#__PURE__*/_react.default.createElement(_headerBar.HeaderBar, args)));
194
+ }, /*#__PURE__*/_react.default.createElement(_headerBar.HeaderBar, {
195
+ appName: "Example!"
196
+ }));
204
197
 
205
198
  exports.Loading = Loading;
206
199
  Loading.storyName = 'Loading...';
207
200
 
208
- const Error = args => /*#__PURE__*/_react.default.createElement(_appRuntime.Provider, {
209
- config: mockConfig
210
- }, /*#__PURE__*/_react.default.createElement(_appRuntime.CustomDataProvider, {
201
+ const Error = () => /*#__PURE__*/_react.default.createElement(_appRuntime.CustomDataProvider, {
211
202
  data: {}
212
- }, /*#__PURE__*/_react.default.createElement(_headerBar.HeaderBar, args)));
203
+ }, /*#__PURE__*/_react.default.createElement(_headerBar.HeaderBar, {
204
+ appName: "Exemple!"
205
+ }));
213
206
 
214
207
  exports.Error = Error;
215
208
  Error.storyName = 'Error!';
216
209
 
217
- const WithOnlineStatus = args => {
218
- const config = { ...mockConfig,
219
- pwaEnabled: true
220
- };
221
- return /*#__PURE__*/_react.default.createElement(_appRuntime.Provider, {
222
- config: config
223
- }, /*#__PURE__*/_react.default.createElement(_appRuntime.CustomDataProvider, {
224
- data: customData
225
- }, /*#__PURE__*/_react.default.createElement(_headerBar.HeaderBar, args)));
226
- };
210
+ const WithOnlineStatus = () => /*#__PURE__*/_react.default.createElement(_appRuntime.CustomDataProvider, {
211
+ data: customData
212
+ }, /*#__PURE__*/_react.default.createElement(_headerBar.HeaderBar, {
213
+ appName: "Exemple!"
214
+ }));
227
215
 
228
216
  exports.WithOnlineStatus = WithOnlineStatus;
217
+ WithOnlineStatus.decorators = [(0, _common.createDecoratorProvider)({ ..._common.providerConfig,
218
+ pwaEnabled: true
219
+ })];
229
220
  WithOnlineStatus.parameters = {
230
221
  docs: {
231
222
  description: {
@@ -237,21 +228,19 @@ WithOnlineStatus.parameters = {
237
228
  }
238
229
  };
239
230
 
240
- const WithLastOnlineInfo = args => {
241
- const config = { ...mockConfig,
242
- pwaEnabled: true,
243
- headerbar: {
244
- onlineStatusInfo: 'LAST_ONLINE'
245
- }
246
- };
247
- return /*#__PURE__*/_react.default.createElement(_appRuntime.Provider, {
248
- config: config
249
- }, /*#__PURE__*/_react.default.createElement(_appRuntime.CustomDataProvider, {
250
- data: customData
251
- }, /*#__PURE__*/_react.default.createElement(_headerBar.HeaderBar, args)));
252
- };
231
+ const WithLastOnlineInfo = () => /*#__PURE__*/_react.default.createElement(_appRuntime.CustomDataProvider, {
232
+ data: customData
233
+ }, /*#__PURE__*/_react.default.createElement(_headerBar.HeaderBar, {
234
+ appName: "Exemple!"
235
+ }));
253
236
 
254
237
  exports.WithLastOnlineInfo = WithLastOnlineInfo;
238
+ WithLastOnlineInfo.decorators = [(0, _common.createDecoratorProvider)({ ..._common.providerConfig,
239
+ pwaEnabled: true,
240
+ headerbar: {
241
+ onlineStatusInfo: 'LAST_ONLINE'
242
+ }
243
+ })];
255
244
  WithLastOnlineInfo.parameters = {
256
245
  docs: {
257
246
  description: {
@@ -259,4 +248,13 @@ WithLastOnlineInfo.parameters = {
259
248
  time since last online.'
260
249
  }
261
250
  }
262
- };
251
+ };
252
+
253
+ const WithUpdateNotification = () => /*#__PURE__*/_react.default.createElement(_appRuntime.CustomDataProvider, {
254
+ data: customData
255
+ }, /*#__PURE__*/_react.default.createElement(_headerBar.HeaderBar, {
256
+ appName: "Data Visualizer",
257
+ updateAvailable: true
258
+ }));
259
+
260
+ exports.WithUpdateNotification = WithUpdateNotification;
@@ -1,5 +1,13 @@
1
1
  {
2
2
  "Search apps": "Search apps",
3
+ "DHIS2 {{dhis2Version}}": "DHIS2 {{dhis2Version}}",
4
+ "DHIS2 version unknown": "DHIS2 version unknown",
5
+ "{{appName}} version unknown": "{{appName}} version unknown",
6
+ "App {{appVersion}}": "App {{appVersion}}",
7
+ "App version unknown": "App version unknown",
8
+ "Debug info": "Debug info",
9
+ "Close": "Close",
10
+ "Copy debug info": "Copy debug info",
3
11
  "Last online {{relativeTime}}": "Last online {{relativeTime}}",
4
12
  "Online": "Online",
5
13
  "Offline": "Offline",
@@ -8,5 +16,8 @@
8
16
  "Account": "Account",
9
17
  "Help": "Help",
10
18
  "About DHIS2": "About DHIS2",
11
- "Logout": "Logout"
19
+ "Logout": "Logout",
20
+ "New {{appName}} version available": "New {{appName}} version available",
21
+ "New app version available": "New app version available",
22
+ "Click to reload": "Click to reload"
12
23
  }
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.useOnDocClick = void 0;
7
+
8
+ var _react = require("react");
9
+
10
+ const useOnDocClick = (containerRef, hide) => {
11
+ const onDocClick = (0, _react.useMemo)(() => {
12
+ return evt => {
13
+ if (!containerRef.current) {
14
+ return null;
15
+ }
16
+
17
+ if (!containerRef.current.contains(evt.target)) {
18
+ hide();
19
+ }
20
+ };
21
+ }, [containerRef, hide]);
22
+ (0, _react.useEffect)(() => {
23
+ document.addEventListener('click', onDocClick);
24
+ return () => {
25
+ document.removeEventListener('click', onDocClick);
26
+ };
27
+ }, [onDocClick]);
28
+ };
29
+
30
+ exports.useOnDocClick = useOnDocClick;
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+
3
+ var _reactHooks = require("@testing-library/react-hooks");
4
+
5
+ var _useOnDocClick = require("./use-on-doc-click.js");
6
+
7
+ describe('useOnDocClick', () => {
8
+ let eventListenerMap = {};
9
+ const hide = jest.fn();
10
+ jest.spyOn(document, 'addEventListener').mockImplementation((event, callback) => {
11
+ eventListenerMap[event] = callback;
12
+ });
13
+ beforeEach(() => {
14
+ eventListenerMap = {};
15
+ });
16
+ afterEach(() => {
17
+ document.addEventListener.mockClear();
18
+ hide.mockClear();
19
+ });
20
+ it('should call the hide function when clicking outside', () => {
21
+ const el = document.createElement('span');
22
+ const containerRef = {
23
+ current: el
24
+ };
25
+ (0, _reactHooks.renderHook)(() => (0, _useOnDocClick.useOnDocClick)(containerRef, hide));
26
+ eventListenerMap.click({
27
+ target: document.body
28
+ });
29
+ expect(hide).toHaveBeenCalled();
30
+ });
31
+ it('should not call the hide function when clicking inside', () => {
32
+ const el = document.createElement('span');
33
+ const containerRef = {
34
+ current: el
35
+ };
36
+ (0, _reactHooks.renderHook)(() => (0, _useOnDocClick.useOnDocClick)(containerRef, hide));
37
+ eventListenerMap.click({
38
+ target: el
39
+ });
40
+ expect(hide).not.toHaveBeenCalled();
41
+ });
42
+ });
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+
7
+ var _profileMenu = require("./profile-menu.js");
8
+
9
+ Object.keys(_profileMenu).forEach(function (key) {
10
+ if (key === "default" || key === "__esModule") return;
11
+ if (key in exports && exports[key] === _profileMenu[key]) return;
12
+ Object.defineProperty(exports, key, {
13
+ enumerable: true,
14
+ get: function () {
15
+ return _profileMenu[key];
16
+ }
17
+ });
18
+ });
@@ -29,12 +29,16 @@ var _propTypes = _interopRequireDefault(require("prop-types"));
29
29
 
30
30
  var _react = _interopRequireWildcard(require("react"));
31
31
 
32
+ var _debugInfoMenuItem = require("../debug-info/debug-info-menu-item.js");
33
+
32
34
  var _joinPath = require("../join-path.js");
33
35
 
34
36
  var _index = _interopRequireDefault(require("../locales/index.js"));
35
37
 
36
38
  var _profileHeader = require("./profile-header.js");
37
39
 
40
+ var _updateNotification = require("./update-notification.js");
41
+
38
42
  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
43
 
40
44
  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; }
@@ -52,7 +56,9 @@ const ProfileContents = _ref => {
52
56
  name,
53
57
  email,
54
58
  avatarId,
55
- helpUrl
59
+ helpUrl,
60
+ hideProfileMenu,
61
+ showDebugInfoModal
56
62
  } = _ref;
57
63
  const {
58
64
  baseUrl
@@ -113,12 +119,21 @@ const ProfileContents = _ref => {
113
119
  icon: /*#__PURE__*/_react.default.createElement(_uiIcons.IconLogOut24, {
114
120
  color: _uiConstants.colors.grey700
115
121
  })
122
+ }), /*#__PURE__*/_react.default.createElement(_menu.MenuDivider, {
123
+ dense: true
124
+ }), /*#__PURE__*/_react.default.createElement(_debugInfoMenuItem.DebugInfoMenuItem, {
125
+ hideProfileMenu: hideProfileMenu,
126
+ showDebugInfoModal: showDebugInfoModal
127
+ }), /*#__PURE__*/_react.default.createElement(_updateNotification.UpdateNotification, {
128
+ hideProfileMenu: hideProfileMenu
116
129
  }))), loading && /*#__PURE__*/_react.default.createElement(LoadingMask, null), /*#__PURE__*/_react.default.createElement(_style.default, {
117
130
  id: "2099675810"
118
131
  }, ["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;}"]));
119
132
  };
120
133
 
121
134
  ProfileContents.propTypes = {
135
+ hideProfileMenu: _propTypes.default.func.isRequired,
136
+ showDebugInfoModal: _propTypes.default.func.isRequired,
122
137
  avatarId: _propTypes.default.string,
123
138
  email: _propTypes.default.string,
124
139
  helpUrl: _propTypes.default.string,
@@ -126,27 +141,20 @@ ProfileContents.propTypes = {
126
141
  };
127
142
 
128
143
  const ProfileMenu = _ref2 => {
129
- let {
130
- avatarId,
131
- name,
132
- email,
133
- helpUrl
144
+ let { ...props
134
145
  } = _ref2;
135
146
  return /*#__PURE__*/_react.default.createElement("div", {
136
147
  "data-test": "headerbar-profile-menu",
137
- className: "jsx-3620236321"
138
- }, /*#__PURE__*/_react.default.createElement(ProfileContents, {
139
- name: name,
140
- email: email,
141
- avatarId: avatarId,
142
- helpUrl: helpUrl
143
- }), /*#__PURE__*/_react.default.createElement(_style.default, {
144
- id: "3620236321"
145
- }, ["div.jsx-3620236321{z-index:10000;position:absolute;top:34px;right:-6px;width:310px;border-top:4px solid transparent;}"]));
148
+ className: "jsx-1689179824"
149
+ }, /*#__PURE__*/_react.default.createElement(ProfileContents, props), /*#__PURE__*/_react.default.createElement(_style.default, {
150
+ id: "1689179824"
151
+ }, ["div.jsx-1689179824{z-index:10000;position:absolute;top:34px;right:-6px;width:320px;border-top:4px solid transparent;}"]));
146
152
  };
147
153
 
148
154
  exports.ProfileMenu = ProfileMenu;
149
155
  ProfileMenu.propTypes = {
156
+ hideProfileMenu: _propTypes.default.func.isRequired,
157
+ showDebugInfoModal: _propTypes.default.func.isRequired,
150
158
  avatarId: _propTypes.default.string,
151
159
  email: _propTypes.default.string,
152
160
  helpUrl: _propTypes.default.string,