asab_webui_shell 27.7.0 → 27.7.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.
@@ -11,6 +11,7 @@ var _react = _interopRequireWildcard(require("react"));
11
11
  var _axios = _interopRequireDefault(require("axios"));
12
12
  var _asab_webui_components = require("asab_webui_components");
13
13
  var _jsonParseWithBigInt2 = require("../utils/jsonParseWithBigInt");
14
+ var _statusAlerts = require("../utils/statusAlerts.js");
14
15
  var _Header = _interopRequireDefault(require("./Header"));
15
16
  var _Sidebar = _interopRequireDefault(require("./Sidebar"));
16
17
  var _ToastContainer = _interopRequireDefault(require("./Toast/ToastContainer.js"));
@@ -35,6 +36,7 @@ var _HelpService = _interopRequireDefault(require("./Header/Help/HelpService"));
35
36
  var _AccessDeniedCard = _interopRequireDefault(require("../modules/tenant/access/AccessDeniedCard"));
36
37
  var _ApplicationRouter = _interopRequireDefault(require("./Router/ApplicationRouter"));
37
38
  var _SuspenseScreen = _interopRequireDefault(require("../screens/SuspenseScreen"));
39
+ var _OfflineIndication = require("../modules/attentionrequired/components/OfflineIndication.js");
38
40
  require("./Application.scss");
39
41
  var _actions = require("../actions");
40
42
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
@@ -93,6 +95,7 @@ class Application extends _react.Component {
93
95
  // Clear print-ready timeout handler
94
96
  this._clearPrintReadyTimeout = this._clearPrintReadyTimeout.bind(this);
95
97
  this._printReadyTimeout = null;
98
+ this._offlineIndicationTimeout = null;
96
99
  this.state = {
97
100
  networking: 0,
98
101
  // If more than zero, some networking activity is happening
@@ -549,6 +552,7 @@ class Application extends _react.Component {
549
552
  this._unsubscribeConnectivity();
550
553
  this._unsubscribeConnectivity = null;
551
554
  }
555
+ this._clearOfflineIndicationTimeout();
552
556
  this._clearPrintReadyTimeout();
553
557
  document.body.removeAttribute('print-ready');
554
558
  }
@@ -558,6 +562,12 @@ class Application extends _react.Component {
558
562
  this._printReadyTimeout = null;
559
563
  }
560
564
  }
565
+ _clearOfflineIndicationTimeout() {
566
+ if (this._offlineIndicationTimeout !== null) {
567
+ clearTimeout(this._offlineIndicationTimeout);
568
+ this._offlineIndicationTimeout = null;
569
+ }
570
+ }
561
571
 
562
572
  // Splash screen
563
573
 
@@ -625,30 +635,50 @@ class Application extends _react.Component {
625
635
  addAlertFromException will always use "danger" color as its background and the full exception will be printed into the console
626
636
  */
627
637
  addAlertFromException(exception, message) {
628
- var _exception$response, _this$AppStore$dispat2, _this$AppStore2;
638
+ var _exception$response, _exception$response2, _this$AppStore$dispat3, _this$AppStore3;
629
639
  var expire = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 30;
630
640
  var shouldBeTranslated = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
631
641
  var component = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null;
632
642
  console.error(exception); // Log the whole exception in the browser
643
+
644
+ var exceptionStatus = exception === null || exception === void 0 || (_exception$response = exception.response) === null || _exception$response === void 0 ? void 0 : _exception$response.status;
645
+ // Indicate gateway timeout if the response status is 502, 503 or 504 and if so, then dont continue with the alert and display the offline indication
646
+ if ((exceptionStatus === 502 || exceptionStatus === 503 || exceptionStatus === 504) && this._indicateGatewayTimeout()) {
647
+ return;
648
+ }
649
+ // Handle specific response statuses and set the appropriate level and message
650
+ var statusAlert = _statusAlerts.STATUS_ALERTS[exceptionStatus];
651
+ if (statusAlert) {
652
+ var _this$AppStore$dispat2, _this$AppStore2;
653
+ (_this$AppStore$dispat2 = (_this$AppStore2 = this.AppStore).dispatch) === null || _this$AppStore$dispat2 === void 0 || _this$AppStore$dispat2.call(_this$AppStore2, {
654
+ type: _actions.ADD_ALERT,
655
+ level: statusAlert.level,
656
+ message: statusAlert.message,
657
+ expire: expire,
658
+ shouldBeTranslated: true,
659
+ component: component
660
+ });
661
+ return;
662
+ }
633
663
  var exceptionMessage = /*#__PURE__*/_react.default.createElement("span", null, message);
634
664
  /*
635
665
  If the exception has an error_dict in the response data (error in the new format),
636
666
  the ErrorHandler component is used to display the error,
637
667
  along with the exception message in the form-text class.
638
668
  */
639
- 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) {
669
+ 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.error_dict) {
640
670
  exceptionMessage = /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_asab_webui_components.ErrorHandler, {
641
671
  error: exception.response.data
642
672
  }), (exception === null || exception === void 0 ? void 0 : exception.message) && /*#__PURE__*/_react.default.createElement("div", {
643
673
  className: "form-text"
644
674
  }, exception.message));
645
675
  } else {
646
- var _exception$response2;
676
+ var _exception$response3;
647
677
  /*
648
678
  Capture the cases when service returns a message in the exception response data.
649
679
  Add hoc messages are displayed in form-text class on the new line
650
680
  */
651
- 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) {
681
+ if (exception !== null && exception !== void 0 && (_exception$response3 = exception.response) !== null && _exception$response3 !== void 0 && (_exception$response3 = _exception$response3.data) !== null && _exception$response3 !== void 0 && _exception$response3.message) {
652
682
  exceptionMessage = /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("h5", null, exceptionMessage), /*#__PURE__*/_react.default.createElement("div", {
653
683
  className: "mt-2",
654
684
  style: {
@@ -662,7 +692,7 @@ class Application extends _react.Component {
662
692
  }, exception.message));
663
693
  }
664
694
  }
665
- (_this$AppStore$dispat2 = (_this$AppStore2 = this.AppStore).dispatch) === null || _this$AppStore$dispat2 === void 0 || _this$AppStore$dispat2.call(_this$AppStore2, {
695
+ (_this$AppStore$dispat3 = (_this$AppStore3 = this.AppStore).dispatch) === null || _this$AppStore$dispat3 === void 0 || _this$AppStore$dispat3.call(_this$AppStore3, {
666
696
  type: _actions.ADD_ALERT,
667
697
  level: "danger",
668
698
  message: exceptionMessage,
@@ -672,17 +702,46 @@ class Application extends _react.Component {
672
702
  });
673
703
  }
674
704
 
705
+ /*
706
+ Show OfflineIndication in the header for a limited time
707
+ Each subsequent 504 resets the timer so the badge stays visible while gateway timeouts keep occurring
708
+ Returns true when the indication was shown, false when HeaderService is unavailable
709
+ */
710
+ _indicateGatewayTimeout() {
711
+ var durationMs = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 30000;
712
+ var headerService = this.locateService('HeaderService');
713
+ if (!headerService) {
714
+ return false;
715
+ }
716
+ var isVisible = headerService.Items.some(item => item.component === _OfflineIndication.OfflineIndication);
717
+ if (!isVisible) {
718
+ headerService.addComponent({
719
+ component: _OfflineIndication.OfflineIndication,
720
+ componentProps: {
721
+ title: 'General|Full or partial loss of connectivity to a server'
722
+ },
723
+ order: 100
724
+ });
725
+ }
726
+ this._clearOfflineIndicationTimeout();
727
+ this._offlineIndicationTimeout = setTimeout(() => {
728
+ headerService.removeComponent(_OfflineIndication.OfflineIndication);
729
+ this._offlineIndicationTimeout = null;
730
+ }, durationMs);
731
+ return true;
732
+ }
733
+
675
734
  /*
676
735
  This method toggles the full-screen mode of the application container.
677
736
  It takes a parameter called "status" to indicate whether to turn the full-screen mode on or off.
678
737
  */
679
738
  setFullScreenMode(status) {
680
- var _state$fullscreenmode, _this$AppStore$dispat3, _this$AppStore3;
739
+ var _state$fullscreenmode, _this$AppStore$dispat4, _this$AppStore4;
681
740
  var state = this.AppStore.getState();
682
741
  if (status === 'on' && (state === null || state === void 0 || (_state$fullscreenmode = state.fullscreenmode) === null || _state$fullscreenmode === void 0 ? void 0 : _state$fullscreenmode.status) === 'on') {
683
742
  status = 'off';
684
743
  }
685
- (_this$AppStore$dispat3 = (_this$AppStore3 = this.AppStore).dispatch) === null || _this$AppStore$dispat3 === void 0 || _this$AppStore$dispat3.call(_this$AppStore3, {
744
+ (_this$AppStore$dispat4 = (_this$AppStore4 = this.AppStore).dispatch) === null || _this$AppStore$dispat4 === void 0 || _this$AppStore$dispat4.call(_this$AppStore4, {
686
745
  type: _actions.SET_FULLSCREEN_MODE,
687
746
  status: status
688
747
  });
@@ -754,9 +813,9 @@ Application.prototype._initConnectivitySubscription = function () {
754
813
  if (this.PubSub && typeof this.PubSub.subscribe === 'function') {
755
814
  if (!this._unsubscribeConnectivity) {
756
815
  this._unsubscribeConnectivity = this.PubSub.subscribe('Application.status!', value => {
757
- var _this$AppStore$dispat4, _this$AppStore4;
816
+ var _this$AppStore$dispat5, _this$AppStore5;
758
817
  // Prefer store so UI updates predictably
759
- (_this$AppStore$dispat4 = (_this$AppStore4 = this.AppStore).dispatch) === null || _this$AppStore$dispat4 === void 0 || _this$AppStore$dispat4.call(_this$AppStore4, {
818
+ (_this$AppStore$dispat5 = (_this$AppStore5 = this.AppStore).dispatch) === null || _this$AppStore$dispat5 === void 0 || _this$AppStore$dispat5.call(_this$AppStore5, {
760
819
  type: _actions.SET_CONNECTIVITY_STATUS,
761
820
  status: value.status
762
821
  });
@@ -8,11 +8,13 @@ exports.OfflineIndication = OfflineIndication;
8
8
  var _react = _interopRequireDefault(require("react"));
9
9
  var _reactI18next = require("react-i18next");
10
10
  // Header badge for displaying offline status
11
- function OfflineIndication() {
11
+ function OfflineIndication(_ref) {
12
+ var _ref$title = _ref.title,
13
+ title = _ref$title === void 0 ? 'General|You are offline. Functionality of the Application may be limited.' : _ref$title;
12
14
  var _useTranslation = (0, _reactI18next.useTranslation)(),
13
15
  t = _useTranslation.t;
14
16
  return /*#__PURE__*/_react.default.createElement("i", {
15
- title: t('General|You are offline. Functionality of the Application may be limited.'),
17
+ title: t(title),
16
18
  className: "bi bi-wifi-off mx-3",
17
19
  style: {
18
20
  fontSize: '16px'
@@ -2,11 +2,11 @@ import React from 'react';
2
2
  import { useTranslation } from 'react-i18next';
3
3
 
4
4
  // Header badge for displaying offline status
5
- export function OfflineIndication() {
5
+ export function OfflineIndication({ title = 'General|You are offline. Functionality of the Application may be limited.' }) {
6
6
  const { t } = useTranslation();
7
7
 
8
8
  return <i
9
- title={t('General|You are offline. Functionality of the Application may be limited.')}
9
+ title={t(title)}
10
10
  className='bi bi-wifi-off mx-3'
11
11
  style={{ fontSize: '16px' }} // Align with fontsize of navitems of Header
12
12
  />
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.STATUS_ALERTS = void 0;
7
+ /*
8
+ Status-specific alerts shown instead of the generic exception alert.
9
+ This is a extension to the addAlertFromException function in the Application.js file.
10
+
11
+ The 502, 503 and 504 errors are handled directly in the Application.js file, since it does not render an alert at all.
12
+ */
13
+ var STATUS_ALERTS = exports.STATUS_ALERTS = {
14
+ 408: {
15
+ level: 'warning',
16
+ message: 'General|The request timed out. Please try again.'
17
+ },
18
+ 413: {
19
+ level: 'warning',
20
+ message: 'General|The request is too large for the server to process. If you are uploading a file, please choose a smaller one.'
21
+ },
22
+ 429: {
23
+ level: 'warning',
24
+ message: 'General|Too many requests. Please wait a moment and try again.'
25
+ }
26
+ // TODO: add more response statuses if needed
27
+ };
@@ -0,0 +1,21 @@
1
+ /*
2
+ Status-specific alerts shown instead of the generic exception alert.
3
+ This is a extension to the addAlertFromException function in the Application.js file.
4
+
5
+ The 502, 503 and 504 errors are handled directly in the Application.js file, since it does not render an alert at all.
6
+ */
7
+ export const STATUS_ALERTS = {
8
+ 408: {
9
+ level: 'warning',
10
+ message: 'General|The request timed out. Please try again.',
11
+ },
12
+ 413: {
13
+ level: 'warning',
14
+ message: 'General|The request is too large for the server to process. If you are uploading a file, please choose a smaller one.',
15
+ },
16
+ 429: {
17
+ level: 'warning',
18
+ message: 'General|Too many requests. Please wait a moment and try again.',
19
+ },
20
+ // TODO: add more response statuses if needed
21
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "asab_webui_shell",
3
- "version": "27.7.0",
3
+ "version": "27.7.1",
4
4
  "license": "BSD-3-Clause",
5
5
  "description": "TeskaLabs ASAB WebUI Shell Application",
6
6
  "contributors": [