asab_webui_shell 25.1.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 (90) hide show
  1. package/CHANGELOG.md +218 -0
  2. package/LICENSE +28 -0
  3. package/README.md +3 -0
  4. package/dist/actions.js +22 -0
  5. package/dist/components/branding/BrandImage.js +72 -0
  6. package/dist/components/locationReplace.js +51 -0
  7. package/dist/config/ConfigReducer.js +22 -0
  8. package/dist/config/ConfigService.js +169 -0
  9. package/dist/containers/AdvancedMode/reducer.js +28 -0
  10. package/dist/containers/Alerts/alerts.scss +9 -0
  11. package/dist/containers/Alerts/index.js +81 -0
  12. package/dist/containers/Alerts/reducer.js +68 -0
  13. package/dist/containers/Application.js +773 -0
  14. package/dist/containers/Application.scss +104 -0
  15. package/dist/containers/AttentionRequired/reducer.js +30 -0
  16. package/dist/containers/FullscreenMode/reducer.js +28 -0
  17. package/dist/containers/Header/ApplicationScreenTitle/ApplicationScreenTitle.js +47 -0
  18. package/dist/containers/Header/ApplicationScreenTitle/ApplicationScreenTitle.scss +8 -0
  19. package/dist/containers/Header/ApplicationScreenTitle/index.js +31 -0
  20. package/dist/containers/Header/Help/HelpButton.js +58 -0
  21. package/dist/containers/Header/Help/HelpButton.scss +15 -0
  22. package/dist/containers/Header/Help/HelpService.js +34 -0
  23. package/dist/containers/Header/Preview/PreviewFlag.js +34 -0
  24. package/dist/containers/Header/Preview/PreviewService.js +34 -0
  25. package/dist/containers/Header/header.scss +24 -0
  26. package/dist/containers/Header/index.js +39 -0
  27. package/dist/containers/Header/reducer.js +53 -0
  28. package/dist/containers/Navigation/index.js +66 -0
  29. package/dist/containers/Navigation/reducer.js +56 -0
  30. package/dist/containers/RouteErrorHandler/ErrorContainer.js +46 -0
  31. package/dist/containers/RouteErrorHandler/index.js +80 -0
  32. package/dist/containers/Router/ApplicationRouter.js +78 -0
  33. package/dist/containers/Router/index.js +50 -0
  34. package/dist/containers/Router/reducer.js +28 -0
  35. package/dist/containers/Sidebar/NavbarBrand.js +59 -0
  36. package/dist/containers/Sidebar/SidebarBottomItem.js +55 -0
  37. package/dist/containers/Sidebar/SidebarIcon.js +21 -0
  38. package/dist/containers/Sidebar/SidebarItem.js +209 -0
  39. package/dist/containers/Sidebar/SidebarItemRenderer.js +30 -0
  40. package/dist/containers/Sidebar/index.js +86 -0
  41. package/dist/containers/Sidebar/reducer.js +35 -0
  42. package/dist/containers/Sidebar/sidebar.scss +176 -0
  43. package/dist/containers/Sidepanel/Sidepanel.js +60 -0
  44. package/dist/containers/Sidepanel/Sidepanel.scss +20 -0
  45. package/dist/containers/Toast/ToastComponent.js +31 -0
  46. package/dist/containers/Toast/ToastComponent.jsx +28 -0
  47. package/dist/containers/Toast/ToastContainer.js +80 -0
  48. package/dist/containers/Toast/ToastContainer.jsx +59 -0
  49. package/dist/containers/Toast/reducer.js +55 -0
  50. package/dist/containers/Toast/reducer.jsx +45 -0
  51. package/dist/index.js +48 -0
  52. package/dist/modules/about/AboutScreen.js +84 -0
  53. package/dist/modules/about/index.js +41 -0
  54. package/dist/modules/auth/actions.js +11 -0
  55. package/dist/modules/auth/api.js +214 -0
  56. package/dist/modules/auth/components/SessionExpirationAlert.js +35 -0
  57. package/dist/modules/auth/header.js +109 -0
  58. package/dist/modules/auth/header.scss +9 -0
  59. package/dist/modules/auth/index.js +761 -0
  60. package/dist/modules/auth/reducer.js +36 -0
  61. package/dist/modules/auth/screens/AccessControlScreen.js +78 -0
  62. package/dist/modules/auth/screens/InvitationScreen.js +161 -0
  63. package/dist/modules/i18n/actions.js +7 -0
  64. package/dist/modules/i18n/dropdown.js +77 -0
  65. package/dist/modules/i18n/index.js +44 -0
  66. package/dist/modules/i18n/reducer.js +26 -0
  67. package/dist/modules/i18n/service.js +158 -0
  68. package/dist/modules/tenant/TenantDropdown.js +53 -0
  69. package/dist/modules/tenant/access/AccessDeniedCard.js +107 -0
  70. package/dist/modules/tenant/access/AccessDeniedCard.scss +6 -0
  71. package/dist/modules/tenant/actions.js +10 -0
  72. package/dist/modules/tenant/index.js +41 -0
  73. package/dist/modules/tenant/reducer.js +26 -0
  74. package/dist/modules/tenant/service.js +228 -0
  75. package/dist/screens/InvalidRouteScreen.js +30 -0
  76. package/dist/screens/InvalidRouteScreen.scss +19 -0
  77. package/dist/screens/SuspenseScreen.js +43 -0
  78. package/dist/screens/SuspenseScreen.scss +9 -0
  79. package/dist/screens/UnauthorizedAccessScreen.js +79 -0
  80. package/dist/screens/UnauthorizedAccessScreen.scss +19 -0
  81. package/dist/services/AttentionRequiredService.js +169 -0
  82. package/dist/services/BrandingService.js +104 -0
  83. package/dist/services/HeaderService.js +84 -0
  84. package/dist/services/ReduxService.js +25 -0
  85. package/dist/services/TitleService.js +45 -0
  86. package/dist/theme/ThemeButton.js +39 -0
  87. package/dist/theme/ThemeReducer.js +20 -0
  88. package/dist/theme/ThemeService.js +52 -0
  89. package/dist/theme/actions.js +7 -0
  90. package/package.json +41 -0
@@ -0,0 +1,773 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ var _typeof = require("@babel/runtime/helpers/typeof");
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports["default"] = void 0;
9
+ var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
10
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
11
+ var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
12
+ var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
13
+ var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
14
+ var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));
15
+ var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));
16
+ var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
17
+ var _react = _interopRequireWildcard(require("react"));
18
+ var _reactRedux = require("react-redux");
19
+ var _redux = require("redux");
20
+ var _axios = _interopRequireDefault(require("axios"));
21
+ var _asab_webui_components = require("asab_webui_components");
22
+ var _Header = _interopRequireDefault(require("./Header"));
23
+ var _Sidebar = _interopRequireDefault(require("./Sidebar"));
24
+ var _ToastContainer = _interopRequireDefault(require("./Toast/ToastContainer.js"));
25
+ var _NavbarBrand = _interopRequireDefault(require("./Sidebar/NavbarBrand.js"));
26
+ var _Alerts = _interopRequireDefault(require("./Alerts"));
27
+ var _Navigation = _interopRequireDefault(require("./Navigation"));
28
+ var _Router = _interopRequireDefault(require("./Router"));
29
+ var _Sidepanel = _interopRequireDefault(require("./Sidepanel/Sidepanel.js"));
30
+ var _reducer = _interopRequireDefault(require("./Alerts/reducer"));
31
+ var _reducer2 = _interopRequireDefault(require("./Sidebar/reducer"));
32
+ var _reducer3 = _interopRequireDefault(require("./Header/reducer"));
33
+ var _reducer4 = _interopRequireDefault(require("./Navigation/reducer"));
34
+ var _reducer5 = _interopRequireDefault(require("./Router/reducer"));
35
+ var _reducer6 = _interopRequireDefault(require("./FullscreenMode/reducer"));
36
+ var _reducer7 = _interopRequireDefault(require("./AdvancedMode/reducer"));
37
+ var _reducer8 = _interopRequireDefault(require("./AttentionRequired/reducer"));
38
+ var _ReduxService = _interopRequireDefault(require("../services/ReduxService"));
39
+ var _AttentionRequiredService = _interopRequireDefault(require("../services/AttentionRequiredService"));
40
+ var _ConfigService = _interopRequireDefault(require("../config/ConfigService"));
41
+ var _HeaderService = _interopRequireDefault(require("../services/HeaderService"));
42
+ var _ThemeService = _interopRequireDefault(require("../theme/ThemeService"));
43
+ var _BrandingService = _interopRequireDefault(require("../services/BrandingService"));
44
+ var _TitleService = _interopRequireDefault(require("../services/TitleService"));
45
+ var _HelpService = _interopRequireDefault(require("./Header/Help/HelpService"));
46
+ var _PreviewService = _interopRequireDefault(require("./Header/Preview/PreviewService"));
47
+ var _AccessDeniedCard = _interopRequireDefault(require("../modules/tenant/access/AccessDeniedCard"));
48
+ var _ApplicationRouter = _interopRequireDefault(require("./Router/ApplicationRouter"));
49
+ var _SuspenseScreen = _interopRequireDefault(require("../screens/SuspenseScreen"));
50
+ require("./Application.scss");
51
+ var _actions = require("../actions");
52
+ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
53
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { "default": e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n["default"] = e, t && t.set(e, n), n; }
54
+ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
55
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
56
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
57
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
58
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2["default"])(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
59
+ function _callSuper(t, o, e) { return o = (0, _getPrototypeOf2["default"])(o), (0, _possibleConstructorReturn2["default"])(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], (0, _getPrototypeOf2["default"])(t).constructor) : o.apply(t, e)); }
60
+ function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
61
+ var Application = /*#__PURE__*/function (_Component) {
62
+ /*
63
+ Example of use hasSidebar.
64
+ It must be set in Application.
65
+ If not set, it is considered as true.
66
+
67
+ ...
68
+
69
+ const config = {
70
+ hasSidebar: false,
71
+ }
72
+
73
+
74
+ ReactDOM.render((
75
+ <BrowserRouter>
76
+ <Application modules={modules} {...config}/>
77
+ </BrowserRouter>
78
+ ), document.getElementById('app'));
79
+
80
+ ...
81
+
82
+ Example of settings in Module of the Application
83
+ Following above settings, this will show the item in
84
+ the header and when the screen is diminished (e.g. screening
85
+ using the mobile phone), the item is moved to the sidebar and
86
+ it is accessible by the sidebar toggler button.
87
+
88
+ ...
89
+
90
+ app.Navigation.addItem({
91
+ name: 'Item 1',
92
+ url: '',
93
+ });
94
+
95
+ ...
96
+ */
97
+
98
+ function Application(props) {
99
+ var _this;
100
+ (0, _classCallCheck2["default"])(this, Application);
101
+ _this = _callSuper(this, Application, [props]);
102
+ _this.Modules = [];
103
+ _this.Services = {};
104
+ _this.ReduxService = new _ReduxService["default"](_this, "ReduxService");
105
+ _this.ConfigService = new _ConfigService["default"](_this, "ConfigService");
106
+ _this.Config = _this.ConfigService.Config;
107
+ _this.Router = new _Router["default"](_this);
108
+ _this.Navigation = new _Navigation["default"](_this);
109
+ _this.SplashscreenRequestors = new Set(); // If not empty, the splash screen will be rendered
110
+ _this.AxiosInterceptors = new Set();
111
+ _this.WebSocketInterceptors = new Set();
112
+ _this.AttentionRequiredService = new _AttentionRequiredService["default"](_this, "AttentionRequired");
113
+ _this.HeaderService = new _HeaderService["default"](_this, "HeaderService");
114
+ _this.ThemeService = new _ThemeService["default"](_this, "ThemeService");
115
+ _this.BrandingService = new _BrandingService["default"](_this, "BrandingService");
116
+ _this.TitleService = new _TitleService["default"](_this, "TitleService");
117
+ _this.HelpService = new _HelpService["default"](_this, "HelpService");
118
+ _this.PreviewService = new _PreviewService["default"](_this, "PreviewService");
119
+ _this.ReduxService.addReducer("attentionrequired", _reducer8["default"]);
120
+ _this.ReduxService.addReducer("alerts", _reducer["default"]);
121
+ _this.ReduxService.addReducer("advmode", _reducer7["default"]);
122
+ _this.ReduxService.addReducer("fullscreenmode", _reducer6["default"]);
123
+ _this.ReduxService.addReducer("header", _reducer3["default"]);
124
+ _this.ReduxService.addReducer("sidebar", _reducer2["default"]);
125
+ _this.ReduxService.addReducer("navigation", _reducer4["default"]);
126
+ _this.ReduxService.addReducer("router", _reducer5["default"]);
127
+ _this._handleKeyUp = _this._handleKeyUp.bind(_this);
128
+ _this.state = {
129
+ networking: 0,
130
+ // If more than zero, some networking activity is happening
131
+ splashscreenRequestors: 0
132
+ };
133
+ var composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || _redux.compose;
134
+ _this.Store = (0, _redux.createStore)((0, _redux.combineReducers)(_this.ReduxService.Reducers), composeEnhancers((0, _redux.applyMiddleware)()));
135
+ _this.ConfigService.addDefaults(props.configdefaults);
136
+ _this.Config.dispatch(_this.Store);
137
+ _this.addSplashScreenRequestor(_this);
138
+ _this.state.splashscreenRequestors = _this.SplashscreenRequestors.size;
139
+ var that = _this;
140
+ function modules_init() {
141
+ return _modules_init.apply(this, arguments);
142
+ }
143
+ function _modules_init() {
144
+ _modules_init = (0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee2() {
145
+ var i, modcandidate, modloaded, mod, _mod, ret;
146
+ return _regenerator["default"].wrap(function _callee2$(_context2) {
147
+ while (1) switch (_context2.prev = _context2.next) {
148
+ case 0:
149
+ _context2.t0 = _regenerator["default"].keys(props.modules);
150
+ case 1:
151
+ if ((_context2.t1 = _context2.t0()).done) {
152
+ _context2.next = 29;
153
+ break;
154
+ }
155
+ i = _context2.t1.value;
156
+ // The candidate can be:
157
+ // 1. { Module } from "asab_webui_components"
158
+ // 2. A promise that loads the remote module from the federated application
159
+ modcandidate = props.modules[i];
160
+ modloaded = void 0;
161
+ if (!(modcandidate.prototype instanceof _asab_webui_components.Module)) {
162
+ _context2.next = 10;
163
+ break;
164
+ }
165
+ // This is a Module from "asab_webui_components"
166
+ mod = new modcandidate(that);
167
+ that.Modules.push(mod);
168
+ _context2.next = 25;
169
+ break;
170
+ case 10:
171
+ _context2.prev = 10;
172
+ _context2.next = 13;
173
+ return Promise.resolve(modcandidate);
174
+ case 13:
175
+ modloaded = _context2.sent;
176
+ _context2.next = 20;
177
+ break;
178
+ case 16:
179
+ _context2.prev = 16;
180
+ _context2.t2 = _context2["catch"](10);
181
+ if (_context2.t2 instanceof Error && _context2.t2.name == 'ScriptExternalLoadError') {
182
+ // The initial load of the remote failed; it is ok in development environment
183
+ console.warn("Failed to load a remote module: ScriptExternalLoadError:", _context2.t2.message);
184
+ } else {
185
+ console.error(_context2.t2);
186
+ }
187
+ return _context2.abrupt("continue", 1);
188
+ case 20:
189
+ if (!(!modloaded["default"].prototype instanceof _asab_webui_components.Module)) {
190
+ _context2.next = 23;
191
+ break;
192
+ }
193
+ console.error("The default object from the remote is not a Module - skipping");
194
+ return _context2.abrupt("continue", 1);
195
+ case 23:
196
+ _mod = new modloaded["default"](that); // We expect 'export default class ...Module extends Module'
197
+ that.Modules.push(_mod);
198
+ case 25:
199
+ that.Store.replaceReducer((0, _redux.combineReducers)(that.ReduxService.Reducers));
200
+ that.Config.dispatch(that.Store);
201
+ _context2.next = 1;
202
+ break;
203
+ case 29:
204
+ _context2.t3 = _regenerator["default"].keys(that.Modules);
205
+ case 30:
206
+ if ((_context2.t4 = _context2.t3()).done) {
207
+ _context2.next = 37;
208
+ break;
209
+ }
210
+ i = _context2.t4.value;
211
+ ret = that.Modules[i].initialize(); // Transform result in the promise
212
+ // It unifies synchronous and asynchronous `initialize()` calls
213
+ _context2.next = 35;
214
+ return Promise.resolve(ret);
215
+ case 35:
216
+ _context2.next = 30;
217
+ break;
218
+ case 37:
219
+ case "end":
220
+ return _context2.stop();
221
+ }
222
+ }, _callee2, null, [[10, 16]]);
223
+ }));
224
+ return _modules_init.apply(this, arguments);
225
+ }
226
+ modules_init().then(/*#__PURE__*/(0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee() {
227
+ var i, ret;
228
+ return _regenerator["default"].wrap(function _callee$(_context) {
229
+ while (1) switch (_context.prev = _context.next) {
230
+ case 0:
231
+ that.Store.replaceReducer((0, _redux.combineReducers)(that.ReduxService.Reducers));
232
+ that.Config.dispatch(that.Store);
233
+
234
+ // Initialize all services
235
+ _context.t0 = _regenerator["default"].keys(that.Services);
236
+ case 3:
237
+ if ((_context.t1 = _context.t0()).done) {
238
+ _context.next = 11;
239
+ break;
240
+ }
241
+ i = _context.t1.value;
242
+ ret = that.Services[i].initialize(); // Transform result in the promise
243
+ // It unifies synchronous and asynchronous `initialize()` calls
244
+ _context.next = 8;
245
+ return Promise.resolve(ret);
246
+ case 8:
247
+ that.Config.dispatch(that.Store);
248
+ _context.next = 3;
249
+ break;
250
+ case 11:
251
+ that.removeSplashScreenRequestor(that);
252
+ case 12:
253
+ case "end":
254
+ return _context.stop();
255
+ }
256
+ }, _callee);
257
+ })));
258
+ return _this;
259
+ }
260
+ (0, _inherits2["default"])(Application, _Component);
261
+ return (0, _createClass2["default"])(Application, [{
262
+ key: "getServiceURL",
263
+ value: function getServiceURL(service) {
264
+ // Handle if service is unknown => return undefined
265
+ if (service == undefined) {
266
+ console.warn("Service is undefined!");
267
+ return undefined;
268
+ }
269
+
270
+ // Handle if SERVICES not provided, empty object will be used as default
271
+ var services = this.Config.get('SERVICES') ? this.Config.get('SERVICES') : {};
272
+
273
+ // Handle if service is not in SERVICES => use service as service_path
274
+ var service_path = services[service] ? services[service] : service;
275
+
276
+ // If service_path is complete URL, then return that URL
277
+ if (service_path.toString().indexOf('http://') !== -1 || service_path.toString().indexOf('https://') !== -1) {
278
+ return service_path;
279
+ }
280
+ // If service_path is complete WebSocket URL, then return that URL
281
+ if (service_path.toString().indexOf('ws://') !== -1 || service_path.toString().indexOf('wss://') !== -1) {
282
+ return service_path;
283
+ }
284
+
285
+ // Obtain BASE_URL
286
+ var BASE_URL = undefined;
287
+ if (this.Config.get('BASE_URL') == undefined) {
288
+ // If BASE_URL has not been defined => take browser URL as BASE_URL
289
+ BASE_URL = window.location.protocol + '//' + window.location.host + window.location.pathname.replace(/\/$/, '');
290
+ } else if (this.Config.get('BASE_URL').toString().indexOf('http://') !== -1 || this.Config.get('BASE_URL').toString().indexOf('https://') !== -1) {
291
+ // If BASE_URL has been defined => take defined BASE_URL as BASE_URL
292
+ BASE_URL = this.Config.get('BASE_URL');
293
+ } else {
294
+ // If BASE_URL has been defined but with relative path => take browser URL as BASE_URL and append relative path from BASE_URL behind the browser URL
295
+ var relative_base_url = this.Config.get('BASE_URL');
296
+ // Check if trailing slash has been added on first place of a BASE_URL string and if so, remove it
297
+ if (relative_base_url.indexOf("/", 0) == 0) {
298
+ relative_base_url = relative_base_url.substring(1);
299
+ }
300
+ BASE_URL = window.location.protocol + '//' + window.location.host + window.location.pathname.replace(/\/$/, '') + '/' + relative_base_url.replace(/\/$/, '');
301
+ }
302
+
303
+ // Compose service_url
304
+ var service_url = undefined;
305
+ if (this.Config.get('API_PATH') == undefined) {
306
+ // If API_PATH has not been defined => use /api to compose service_url
307
+ service_url = BASE_URL.replace(/\/$/, '') + '/api';
308
+ } else if (this.Config.get('API_PATH').toString().indexOf('http://') !== -1 || this.Config.get('API_PATH').toString().indexOf('https://') !== -1) {
309
+ // If API_PATH has been defined but with absolute URL => use API_PATH as service_url
310
+ service_url = this.Config.get('API_PATH');
311
+ } else {
312
+ // If API_PATH has been defined => use API_PATH to compose service_url
313
+ var api_path = this.Config.get('API_PATH');
314
+ // Check if trailing slash has been added on first place of a API_PATH string and if so, remove it
315
+ if (api_path.indexOf("/", 0) == 0) {
316
+ api_path = api_path.substring(1);
317
+ }
318
+ service_url = BASE_URL.replace(/\/$/, '') + "/" + api_path;
319
+ }
320
+ return service_url.replace(/\/$/, '') + "/" + service_path;
321
+ }
322
+
323
+ /*
324
+ * Creates an AXIOS object for communication with TeskaLabs API's
325
+ *
326
+ * IMPORTANT NOTE:
327
+ * Bearer token will be sent to any URL specified in the API / Services configuration.
328
+ * axiosCreate must only be used for creating http sessions
329
+ * towards TeskaLabs API's, since it adds Bearer token to all calls.
330
+ */
331
+ }, {
332
+ key: "axiosCreate",
333
+ value: function axiosCreate(service, props) {
334
+ var service_url = this.getServiceURL(service);
335
+ if (service_url == undefined) {
336
+ this.addAlert('danger', "ASABApplicationContainer|Service URL is undefined, please check service paths passed to axios", 5, true);
337
+ return undefined;
338
+ }
339
+ var axios = _axios["default"].create(_objectSpread(_objectSpread({}, props), {}, {
340
+ baseURL: service_url
341
+ }));
342
+
343
+ // Iterate through custom interceptors
344
+ var _iterator = _createForOfIteratorHelper(this.AxiosInterceptors.keys()),
345
+ _step;
346
+ try {
347
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
348
+ var interceptor = _step.value;
349
+ this.interceptorRequest(axios, interceptor);
350
+ }
351
+ } catch (err) {
352
+ _iterator.e(err);
353
+ } finally {
354
+ _iterator.f();
355
+ }
356
+ var that = this;
357
+
358
+ /*
359
+ We want to be notified when networking activity is taking place,
360
+ thus we use pushNetworkingIndicator.
361
+ Default request headers are X-App and X-Request-Id which
362
+ define recognition of the requests from the service perspective
363
+ */
364
+ axios.interceptors.request.use(function (config) {
365
+ that.pushNetworkingIndicator();
366
+ config.headers['X-App'] = "webui"; // Include X-App header in every axios API request
367
+ config.headers['X-Request-Id'] = that._generateUID(); // Include X-Request-Id header in every axios API request
368
+ return config;
369
+ }, function (error) {
370
+ return Promise.reject(error);
371
+ });
372
+
373
+ // We want to remove networking indicator when we recieve the response
374
+ axios.interceptors.response.use(function (response) {
375
+ that.popNetworkingIndicator();
376
+ return response;
377
+ }, function (error) {
378
+ that.popNetworkingIndicator();
379
+ return Promise.reject(error);
380
+ });
381
+ return axios;
382
+ }
383
+
384
+ // Internal method for generating random UID's
385
+ }, {
386
+ key: "_generateUID",
387
+ value: function _generateUID() {
388
+ /*
389
+ - Math.random() * 0x100000000: Generates a random floating-point number between 0 and 0x100000000.
390
+ - >>> 0: Applies a bitwise unsigned right shift by 0, effectively converting the floating-point number to a 32-bit unsigned integer.
391
+ - toString(36): Converts the integer to a base-36 string, using the digits 0-9 and letters a-z.
392
+ */
393
+ return (Math.random() * 0x100000000 >>> 0).toString(36) + (Math.random() * 0x100000000 >>> 0).toString(36) + (Math.random() * 0x100000000 >>> 0).toString(36) + (Math.random() * 0x100000000 >>> 0).toString(36);
394
+ }
395
+ }, {
396
+ key: "interceptorRequest",
397
+ value: function interceptorRequest(axios, interceptor) {
398
+ // Add a request interceptor
399
+ axios.interceptors.request.use(interceptor, function (error) {
400
+ return Promise.reject(error);
401
+ });
402
+ }
403
+ }, {
404
+ key: "addAxiosInterceptor",
405
+ value: function addAxiosInterceptor(interceptor) {
406
+ this.AxiosInterceptors.add(interceptor);
407
+ }
408
+ }, {
409
+ key: "removeAxiosInterceptor",
410
+ value: function removeAxiosInterceptor(interceptor) {
411
+ this.AxiosInterceptors["delete"](interceptor);
412
+ }
413
+ }, {
414
+ key: "addWebSocketInterceptor",
415
+ value: function addWebSocketInterceptor(interceptor) {
416
+ this.WebSocketInterceptors.add(interceptor);
417
+ }
418
+ }, {
419
+ key: "removeWebSocketInterceptor",
420
+ value: function removeWebSocketInterceptor(interceptor) {
421
+ this.WebSocketInterceptors["delete"](interceptor);
422
+ }
423
+ }, {
424
+ key: "getWebSocketURL",
425
+ value: function getWebSocketURL(service, subpath) {
426
+ // Handle if service is unknown => return undefined
427
+ var service_url = this.getServiceURL(service);
428
+ if (service_url == undefined) {
429
+ return undefined;
430
+ }
431
+
432
+ // Handle if subpath is unknown => subpath = ""
433
+ if (subpath == undefined) {
434
+ subpath = "";
435
+ }
436
+
437
+ // If service_path is complete WebSocket URL, then return that URL
438
+ if (service_url.toString().indexOf('ws://') !== -1 || service_url.toString().indexOf('wss://') !== -1) {
439
+ return service_url;
440
+ }
441
+
442
+ // Replace http:// or https:// protocol with ws:// or wss://
443
+ var ws_service_url = service_url.replace(/(http)(s)?\:\/\//, "ws$2://");
444
+ return ws_service_url + subpath;
445
+ }
446
+ }, {
447
+ key: "createWebSocket",
448
+ value: function createWebSocket(service, subpath) {
449
+ var socket_url = this.getWebSocketURL(service, subpath);
450
+ if (socket_url == undefined) {
451
+ this.addAlert('danger', "ASABApplicationContainer|WebSocket URL is undefined, please check service and subpath passed to WebSocket", 5, true);
452
+ return undefined;
453
+ }
454
+
455
+ /*
456
+ Adding ws interceptors to the ws subprotocols (e.g. to pass auth token).
457
+ "asab" subprotocol is given by default for consumer (any websocket service)
458
+ which require this particular value to authenticate websocket connection,
459
+ since some browsers (Chrome, Safari, ...) requires Sec-Websocket-Accept
460
+ response header.
461
+ Another default subprotocols are "app_webui" and "request_id_<uid>"
462
+ which define recognition of the requests from the service perspective
463
+ */
464
+ var subprotocols = ["asab", "app_webui", "request_id_".concat(this._generateUID())];
465
+ var _iterator2 = _createForOfIteratorHelper(this.WebSocketInterceptors.keys()),
466
+ _step2;
467
+ try {
468
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
469
+ var interceptor = _step2.value;
470
+ // Avoid pushing undefined interceptor values
471
+ if (interceptor) {
472
+ subprotocols.push(interceptor);
473
+ }
474
+ }
475
+
476
+ // Create new WebSocket based on socket URL
477
+ } catch (err) {
478
+ _iterator2.e(err);
479
+ } finally {
480
+ _iterator2.f();
481
+ }
482
+ var socket = new WebSocket(socket_url, subprotocols);
483
+ return socket;
484
+ }
485
+
486
+ // Display and hide networking indicator
487
+ }, {
488
+ key: "pushNetworkingIndicator",
489
+ value: function pushNetworkingIndicator() {
490
+ this.setState(function (prevState, props) {
491
+ return {
492
+ networking: prevState.networking + 1
493
+ };
494
+ });
495
+ }
496
+ }, {
497
+ key: "popNetworkingIndicator",
498
+ value: function popNetworkingIndicator() {
499
+ this.setState(function (prevState, props) {
500
+ return {
501
+ networking: prevState.networking - 1
502
+ };
503
+ });
504
+ }
505
+ }, {
506
+ key: "registerService",
507
+ value: function registerService(service) {
508
+ if (service.Name in this.Services) {
509
+ console.warn("Service ".concat(service.Name, " is already registered."));
510
+ return;
511
+ }
512
+ this.Services[service.Name] = service;
513
+ }
514
+ }, {
515
+ key: "locateService",
516
+ value: function locateService(name) {
517
+ if (!name in this.Services) {
518
+ console.warn("Service ".concat(name, " doesn't exist."));
519
+ return null;
520
+ }
521
+ return this.Services[name];
522
+ }
523
+
524
+ // This function handles keystroke events and performs enabling/disabling of mods
525
+ }, {
526
+ key: "_handleKeyUp",
527
+ value: function _handleKeyUp(event) {
528
+ // CTRL+SHIFT+F enables the fullscreen mode
529
+ if (event.ctrlKey && event.shiftKey && event.code === 'KeyF') {
530
+ this.setFullScreenMode('on');
531
+ }
532
+
533
+ // CTRL+Q (Windows) or CTRL+1 (Linux) enables the advanced mode
534
+ if (event.ctrlKey && event.code === 'KeyQ' || event.code === 'Digit1' && event.ctrlKey) {
535
+ this.setAdvancedMode(0);
536
+ }
537
+ }
538
+ }, {
539
+ key: "componentDidMount",
540
+ value: function componentDidMount() {
541
+ document.addEventListener("keyup", this._handleKeyUp, false);
542
+ }
543
+ }, {
544
+ key: "componentWillUnmount",
545
+ value: function componentWillUnmount() {
546
+ document.removeEventListener("keyup", this._handleKeyUp, false);
547
+ }
548
+
549
+ // Splash screen
550
+ }, {
551
+ key: "addSplashScreenRequestor",
552
+ value: function addSplashScreenRequestor(obj) {
553
+ var origLen = this.SplashscreenRequestors.size;
554
+ this.SplashscreenRequestors.add(obj);
555
+ if (origLen != this.SplashscreenRequestors.size) {
556
+ this.state.splashscreenRequestors = this.SplashscreenRequestors.size;
557
+ }
558
+ var splashscreen = document.getElementById('app-splashscreen'); // See public/index.html`
559
+ splashscreen === null || splashscreen === void 0 || splashscreen.classList.remove("d-none");
560
+ }
561
+ }, {
562
+ key: "removeSplashScreenRequestor",
563
+ value: function removeSplashScreenRequestor(obj) {
564
+ var origLen = this.SplashscreenRequestors.size;
565
+ this.SplashscreenRequestors["delete"](obj);
566
+ if (origLen != this.SplashscreenRequestors.size) {
567
+ this.setState({
568
+ splashscreenRequestors: this.SplashscreenRequestors.size
569
+ });
570
+ }
571
+ if (this.SplashscreenRequestors.size == 0) {
572
+ var splashscreen = document.getElementById('app-splashscreen'); // See public/index.html
573
+ splashscreen === null || splashscreen === void 0 || splashscreen.classList.add("d-none");
574
+ }
575
+ }
576
+
577
+ // Alerts
578
+ /*
579
+ levels:
580
+ * danger
581
+ * warning
582
+ * info
583
+ * success
584
+ */
585
+ }, {
586
+ key: "addAlert",
587
+ value: function addAlert(level, message) {
588
+ var expire = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 5;
589
+ var shouldBeTranslated = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
590
+ var component = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null;
591
+ this.Store.dispatch({
592
+ type: _actions.ADD_ALERT,
593
+ level: level,
594
+ message: message,
595
+ expire: expire,
596
+ shouldBeTranslated: shouldBeTranslated,
597
+ component: component
598
+ });
599
+ }
600
+
601
+ /*
602
+ Alert from exception suppose to be used ONLY for exception cases.
603
+ By default it requires:
604
+ - exception - this is comming from the try{...}catch(exception){...} . It is important to pass the whole exception.
605
+ - message - this is the custom message written by developer based on the situation
606
+ Additional options are:
607
+ - expire - expiration of the aler (by default set to 30s)
608
+ - shouldBeTranslated - boolean for cases where is not possible to use useTranslation hook (by default false)
609
+ - component - option to pass additional component of the alert message e.g. button (by default null)
610
+ addAlertFromException will always use "danger" color as its background and the full exception will be printed into the console
611
+ */
612
+ }, {
613
+ key: "addAlertFromException",
614
+ value: function addAlertFromException(exception, message) {
615
+ var _exception$response;
616
+ var expire = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 30;
617
+ var shouldBeTranslated = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
618
+ var component = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null;
619
+ console.error(exception); // Log the whole exception in the browser
620
+ var exceptionMessage = /*#__PURE__*/_react["default"].createElement("span", null, message);
621
+ /*
622
+ If the exception has an error_dict in the response data (error in the new format),
623
+ the ErrorHandler component is used to display the error,
624
+ along with the exception message in the form-text class.
625
+ */
626
+ if (exception !== null && exception !== void 0 && (_exception$response = exception.response) !== null && _exception$response !== void 0 && (_exception$response = _exception$response.data) !== null && _exception$response !== void 0 && _exception$response.error_dict) {
627
+ exceptionMessage = /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, /*#__PURE__*/_react["default"].createElement(_asab_webui_components.ErrorHandler, {
628
+ error: exception.response.data
629
+ }), (exception === null || exception === void 0 ? void 0 : exception.message) && /*#__PURE__*/_react["default"].createElement("div", {
630
+ className: "form-text"
631
+ }, exception.message));
632
+ } else {
633
+ var _exception$response2;
634
+ /*
635
+ Capture the cases when service returns a message in the exception response data.
636
+ Add hoc messages are displayed in form-text class on the new line
637
+ */
638
+ if (exception !== null && exception !== void 0 && (_exception$response2 = exception.response) !== null && _exception$response2 !== void 0 && (_exception$response2 = _exception$response2.data) !== null && _exception$response2 !== void 0 && _exception$response2.message) {
639
+ exceptionMessage = /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, /*#__PURE__*/_react["default"].createElement("h5", null, exceptionMessage), /*#__PURE__*/_react["default"].createElement("div", {
640
+ className: "mt-2",
641
+ style: {
642
+ whiteSpace: 'pre-wrap'
643
+ }
644
+ }, exception.response.data.message));
645
+ } else {
646
+ // Exception message is always present in the exception
647
+ exceptionMessage = /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, /*#__PURE__*/_react["default"].createElement("h5", null, exceptionMessage), (exception === null || exception === void 0 ? void 0 : exception.message) && /*#__PURE__*/_react["default"].createElement("div", {
648
+ className: "mt-2"
649
+ }, exception.message));
650
+ }
651
+ }
652
+ this.Store.dispatch({
653
+ type: _actions.ADD_ALERT,
654
+ level: "danger",
655
+ message: exceptionMessage,
656
+ expire: expire,
657
+ shouldBeTranslated: shouldBeTranslated,
658
+ component: component
659
+ });
660
+ }
661
+ }, {
662
+ key: "setAdvancedMode",
663
+ value: function setAdvancedMode(enabled) {
664
+ if (enabled === 0) {
665
+ var state = this.Store.getState();
666
+ enabled = !state.advmode.enabled;
667
+ }
668
+ this.Store.dispatch({
669
+ type: _actions.SET_ADVANCED_MODE,
670
+ enabled: enabled
671
+ });
672
+ if (enabled) {
673
+ this.addAlert('warning', "ASABApplicationContainer|Advanced mode enabled", 1, true);
674
+ } else {
675
+ this.addAlert('success', "ASABApplicationContainer|Advanced mode disabled", 1, true);
676
+ }
677
+ }
678
+
679
+ /*
680
+ This method toggles the full-screen mode of the application container.
681
+ It takes a parameter called "status" to indicate whether to turn the full-screen mode on or off.
682
+ */
683
+ }, {
684
+ key: "setFullScreenMode",
685
+ value: function setFullScreenMode(status) {
686
+ var state = this.Store.getState();
687
+ if (status === 'on' && state.fullscreenmode.status === 'on') {
688
+ status = 'off';
689
+ }
690
+ this.Store.dispatch({
691
+ type: _actions.SET_FULLSCREEN_MODE,
692
+ status: status
693
+ });
694
+ if (status === 'on') {
695
+ document.body.classList.add('fullscreen');
696
+ this.addAlert('info', 'ASABApplicationContainer|Fullscreen mode turned on. To turn it off, press CTRL + SHIFT + F.', 30, true);
697
+ } else {
698
+ document.body.classList.remove('fullscreen');
699
+ this.addAlert('info', 'ASABApplicationContainer|Fullscreen mode turned off', 30, true);
700
+ }
701
+ }
702
+ }, {
703
+ key: "setFlag",
704
+ value: function setFlag(name) {
705
+ var _this2 = this;
706
+ (0, _react.useEffect)(function () {
707
+ _this2.Store.dispatch({
708
+ type: _actions.SET_FLAG,
709
+ flag: name
710
+ });
711
+ return function () {
712
+ _this2.Store.dispatch({
713
+ type: _actions.SET_FLAG,
714
+ flag: undefined
715
+ });
716
+ };
717
+ }, [name]);
718
+ }
719
+ }, {
720
+ key: "render",
721
+ value: function render() {
722
+ if (this.state.splashscreenRequestors > 0) return (
723
+ /*#__PURE__*/
724
+ // When splashscreenRequestors is requested, the application is not rendered.
725
+ // This prevents race conditions during application init time.
726
+ _react["default"].createElement(_asab_webui_components.PubSubProvider, {
727
+ app: this
728
+ }, /*#__PURE__*/_react["default"].createElement(_reactRedux.Provider, {
729
+ store: this.Store
730
+ }, /*#__PURE__*/_react["default"].createElement(_react.Suspense, {
731
+ fallback: /*#__PURE__*/_react["default"].createElement("div", null)
732
+ }, /*#__PURE__*/_react["default"].createElement(_Alerts["default"], {
733
+ app: this
734
+ }), /*#__PURE__*/_react["default"].createElement("main", {
735
+ id: "app-main"
736
+ }, /*#__PURE__*/_react["default"].createElement(_AccessDeniedCard["default"], {
737
+ app: this
738
+ })))))
739
+ );
740
+ return /*#__PURE__*/_react["default"].createElement(_asab_webui_components.PubSubProvider, {
741
+ app: this
742
+ }, /*#__PURE__*/_react["default"].createElement(_reactRedux.Provider, {
743
+ store: this.Store
744
+ }, /*#__PURE__*/_react["default"].createElement(_react.Suspense, {
745
+ fallback: /*#__PURE__*/_react["default"].createElement("div", null)
746
+ }, /*#__PURE__*/_react["default"].createElement("div", {
747
+ id: "app-networking-indicator",
748
+ className: "progress-bar progress-bar-animated progress-bar-striped" + (this.state.networking == 0 ? " transparent" : "")
749
+ }), /*#__PURE__*/_react["default"].createElement(_Alerts["default"], {
750
+ app: this
751
+ }), /*#__PURE__*/_react["default"].createElement(_NavbarBrand["default"], {
752
+ app: this
753
+ }), /*#__PURE__*/_react["default"].createElement(_Sidebar["default"], {
754
+ app: this
755
+ }), /*#__PURE__*/_react["default"].createElement(_ToastContainer["default"], {
756
+ app: this
757
+ }), /*#__PURE__*/_react["default"].createElement(_Header["default"], {
758
+ app: this
759
+ }), /*#__PURE__*/_react["default"].createElement("main", {
760
+ id: "app-main"
761
+ }, /*#__PURE__*/_react["default"].createElement(_react.Suspense, {
762
+ fallback: /*#__PURE__*/_react["default"].createElement(_SuspenseScreen["default"], {
763
+ app: this
764
+ }) /*The suspense that captures lazy loading of the federated apps*/
765
+ }, /*#__PURE__*/_react["default"].createElement(_ApplicationRouter["default"], {
766
+ app: this
767
+ }))), /*#__PURE__*/_react["default"].createElement(_Sidepanel["default"], {
768
+ app: this
769
+ }))));
770
+ }
771
+ }]);
772
+ }(_react.Component);
773
+ var _default = exports["default"] = Application;