asab_webui_shell 26.1.3 → 26.2.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.
@@ -25,9 +25,7 @@ var _reducer4 = _interopRequireDefault(require("./Navigation/reducer"));
25
25
  var _reducer5 = _interopRequireDefault(require("./Router/reducer"));
26
26
  var _reducer6 = _interopRequireDefault(require("./FullscreenMode/reducer"));
27
27
  var _reducer7 = _interopRequireDefault(require("./AdvancedMode/reducer"));
28
- var _reducer8 = _interopRequireDefault(require("./AttentionRequired/reducer"));
29
28
  var _ReduxService = _interopRequireDefault(require("../services/ReduxService"));
30
- var _AttentionRequiredService = _interopRequireDefault(require("../services/AttentionRequiredService"));
31
29
  var _ConfigService = _interopRequireDefault(require("../config/ConfigService"));
32
30
  var _HeaderService = _interopRequireDefault(require("../services/HeaderService"));
33
31
  var _ThemeService = _interopRequireDefault(require("../theme/ThemeService"));
@@ -91,7 +89,6 @@ class Application extends _react.Component {
91
89
  this.Config = this.ConfigService.Config;
92
90
 
93
91
  // Register reducers which are not part of any app service
94
- this.ReduxService.addReducer("attentionrequired", _reducer8.default);
95
92
  this.ReduxService.addReducer("alerts", _reducer.default);
96
93
  this.ReduxService.addReducer("advmode", _reducer7.default);
97
94
  this.ReduxService.addReducer("fullscreenmode", _reducer6.default);
@@ -104,7 +101,6 @@ class Application extends _react.Component {
104
101
  this.SplashscreenRequestors = new Set(); // If not empty, the splash screen will be rendered
105
102
  this.AxiosInterceptors = new Set();
106
103
  this.WebSocketInterceptors = new Set();
107
- this.AttentionRequiredService = new _AttentionRequiredService.default(this, "AttentionRequired");
108
104
  this.HeaderService = new _HeaderService.default(this, "HeaderService");
109
105
  this.ThemeService = new _ThemeService.default(this, "ThemeService");
110
106
  this.BrandingService = new _BrandingService.default(this, "BrandingService");
@@ -38,7 +38,7 @@ var SidebarItem = _ref => {
38
38
  var [isActive, setActive] = (0, _react.useState)(false);
39
39
  var lowercasedItemName = item === null || item === void 0 || (_item$name = item.name) === null || _item$name === void 0 ? void 0 : _item$name.toLowerCase();
40
40
  // Attention requred flag
41
- var itemBeacon = beacon ? beacon["beacon.".concat(lowercasedItemName)] : attentionRequired["beacon.".concat(lowercasedItemName)];
41
+ var itemBeacon = beacon ? beacon["beacon.".concat(lowercasedItemName)] : attentionRequired === null || attentionRequired === void 0 ? void 0 : attentionRequired["beacon.".concat(lowercasedItemName)];
42
42
  (0, _react.useEffect)(() => {
43
43
  // TODO: refactor the handling of active and open states, since it does not behave as expected in some cases
44
44
  if (isOpen && !isActive) {
package/dist/index.js CHANGED
@@ -16,6 +16,12 @@ Object.defineProperty(exports, "Application", {
16
16
  return _Application.default;
17
17
  }
18
18
  });
19
+ Object.defineProperty(exports, "AttentionRequiredModule", {
20
+ enumerable: true,
21
+ get: function get() {
22
+ return _index2.default;
23
+ }
24
+ });
19
25
  Object.defineProperty(exports, "AuthModule", {
20
26
  enumerable: true,
21
27
  get: function get() {
@@ -46,4 +52,5 @@ var _BrandImage = require("./components/branding/BrandImage");
46
52
  var _i18n = _interopRequireDefault(require("./modules/i18n"));
47
53
  var _tenant = _interopRequireDefault(require("./modules/tenant"));
48
54
  var _auth = _interopRequireDefault(require("./modules/auth"));
49
- var _about = _interopRequireDefault(require("./modules/about"));
55
+ var _about = _interopRequireDefault(require("./modules/about"));
56
+ var _index2 = _interopRequireDefault(require("./modules/attentionrequired/index.js"));
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.default = void 0;
8
+ var _react = _interopRequireDefault(require("react"));
9
+ var _asab_webui_components = require("asab_webui_components");
10
+ var _service = _interopRequireDefault(require("./service.js"));
11
+ var _reducer = _interopRequireDefault(require("./reducer.js"));
12
+ class AttentionRequiredModule extends _asab_webui_components.Module {
13
+ constructor(app) {
14
+ var name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "AttentionRequiredModule";
15
+ super(app, name);
16
+ this.App = app;
17
+ this.AttentionRequiredService = new _service.default(app, "AttentionRequiredService");
18
+ this.App.ReduxService.addReducer("attentionrequired", _reducer.default);
19
+ }
20
+ }
21
+ exports.default = AttentionRequiredModule;
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ import { Module } from 'asab_webui_components';
3
+ import AttentionRequiredService from './service.jsx';
4
+ import reducer from './reducer.jsx';
5
+
6
+ export default class AttentionRequiredModule extends Module {
7
+
8
+ constructor(app, name = "AttentionRequiredModule") {
9
+ super(app, name);
10
+ this.App = app;
11
+
12
+ this.AttentionRequiredService = new AttentionRequiredService(app, "AttentionRequiredService");
13
+
14
+ this.App.ReduxService.addReducer("attentionrequired", reducer);
15
+ }
16
+
17
+ }
@@ -0,0 +1,20 @@
1
+ import { SET_ATTENTION_REQUIRED_BEACON } from "../../actions";
2
+
3
+ const initialState = {
4
+ beacon: {},
5
+ }
6
+
7
+ // Reducer for attention required, returning beacon
8
+ export default function attentionRequiredReducer(state = initialState, action) {
9
+ switch (action.type) {
10
+ case SET_ATTENTION_REQUIRED_BEACON: {
11
+ return {
12
+ ...state,
13
+ beacon: action.beacon
14
+ }
15
+ }
16
+
17
+ default:
18
+ return state;
19
+ }
20
+ }
@@ -5,7 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.default = void 0;
7
7
  var _asab_webui_components = require("asab_webui_components");
8
- var _actions = require("../actions");
8
+ var _actions = require("../../actions");
9
9
  // Service handling attention required
10
10
  class AttentionRequiredService extends _asab_webui_components.Service {
11
11
  constructor(app) {
@@ -101,6 +101,7 @@ class AttentionRequiredService extends _asab_webui_components.Service {
101
101
  distributeData(data) {
102
102
  var _this$App2, _this$App2$dispatch;
103
103
  var transformedData = this.transformData(data);
104
+ // TODO: use a pubsub instead of the appstore dispatch
104
105
  (_this$App2 = this.App) === null || _this$App2 === void 0 || (_this$App2 = _this$App2.AppStore) === null || _this$App2 === void 0 || (_this$App2$dispatch = _this$App2.dispatch) === null || _this$App2$dispatch === void 0 || _this$App2$dispatch.call(_this$App2, {
105
106
  type: _actions.SET_ATTENTION_REQUIRED_BEACON,
106
107
  beacon: transformedData
@@ -0,0 +1,141 @@
1
+ import { Service } from 'asab_webui_components';
2
+ import { SET_ATTENTION_REQUIRED_BEACON } from '../../actions';
3
+
4
+ // Service handling attention required
5
+ export default class AttentionRequiredService extends Service {
6
+
7
+ constructor(app, serviceName="AttentionRequiredService"){
8
+ super(app, serviceName);
9
+ this.beaconWebSocket = null; // beacon websocket variable
10
+ this.reconnectTimeout = null; // timeout variable
11
+ this.reconnectInterval = 5000; // initial reconnection interval (5 seconds)
12
+ }
13
+
14
+ // Start beacon websocket connection on initialization
15
+ initialize() {
16
+ this.connectBeaconWebSocket();
17
+ }
18
+
19
+ // Method for connection to beacon websocket
20
+ connectBeaconWebSocket() {
21
+ // Retrieve current tenant
22
+ const currentTenant = this.App?.Services?.TenantService?.getCurrentTenant();
23
+ // Gracefully reconnect if tenant was not found
24
+ if (!currentTenant) {
25
+ console.error("Beacon WebSocket error: Tenant was not found!");
26
+ this.reconnectBeaconWebSocket();
27
+ return;
28
+ }
29
+
30
+ const BeaconServiceClient = this.App.createWebSocket('asab-remote-control', `/beacon/${currentTenant}/ws`);
31
+ this.beaconWebSocket = BeaconServiceClient;
32
+
33
+ this.beaconWebSocket.onopen = () => {
34
+ // TODO: may be removed
35
+ console.log('Beacon WebSocket connection established.');
36
+ };
37
+
38
+ this.beaconWebSocket.onmessage = (message) => {
39
+ try {
40
+ const data = JSON.parse(message.data);
41
+ // TODO: implement some type based recognition
42
+ this.distributeData(data);
43
+ } catch (e) {
44
+ console.error("Error parsing Beacon WebSocket message data:", e);
45
+ this.distributeData({});
46
+ }
47
+ };
48
+
49
+ this.beaconWebSocket.onerror = (error) => {
50
+ console.error("Beacon WebSocket error:", error);
51
+ console.error("Beacon WebSocket is attempting to reconnect...");
52
+ this.distributeData({});
53
+ this.reconnectBeaconWebSocket();
54
+ };
55
+
56
+ this.beaconWebSocket.onclose = () => {
57
+ /*
58
+ WebSocket connection is closed by the browser automatically when user
59
+ leaves the application (not the screen).
60
+ */
61
+ if (this.beaconWebSocket) {
62
+ // Close the WebSocket connection
63
+ this.beaconWebSocket.close();
64
+
65
+ // Clean up event listeners
66
+ this.beaconWebSocket.onopen = null;
67
+ this.beaconWebSocket.onmessage = null;
68
+ this.beaconWebSocket.onerror = null;
69
+ this.beaconWebSocket.onclose = null;
70
+
71
+ // Set WebSocket reference to null to free up memory
72
+ this.beaconWebSocket = null;
73
+ }
74
+
75
+ // Clear the reconnect timeout if it exists
76
+ if (this.reconnectTimeout) {
77
+ clearTimeout(this.reconnectTimeout);
78
+ this.reconnectTimeout = null;
79
+ }
80
+
81
+ console.log("Beacon WebSocket connection closed.");
82
+ };
83
+ }
84
+
85
+ // Method for reconnection to beacon websocket
86
+ reconnectBeaconWebSocket() {
87
+ if (this.reconnectTimeout) {
88
+ clearTimeout(this.reconnectTimeout);
89
+ }
90
+ this.reconnectTimeout = setTimeout(() => {
91
+ this.connectBeaconWebSocket();
92
+ }, this.reconnectInterval); // Retry connection after the reconnection interval
93
+
94
+ // Increase reconnection time by 5s, the limit is 60s (so that we dont overload the server)
95
+ if ((this.reconnectInterval + 5000) <= 60000) {
96
+ this.reconnectInterval += 5000;
97
+ }
98
+ }
99
+
100
+ // Method for distributing the data into Application store
101
+ distributeData(data) {
102
+ const transformedData = this.transformData(data);
103
+ // TODO: use a pubsub instead of the appstore dispatch
104
+ this.App?.AppStore?.dispatch?.({ type: SET_ATTENTION_REQUIRED_BEACON, beacon: transformedData });
105
+ }
106
+
107
+ // Transform and group beacon data
108
+ transformData(inputData) {
109
+ // Validate if input data are array
110
+ if (!Array.isArray(inputData)) {
111
+ return {};
112
+ }
113
+
114
+ return inputData.reduce((acc, entry) => {
115
+ const { type, _c, reference_path } = entry;
116
+
117
+ // Identify the dynamic key (it could be 'library', 'configuration', 'services', etc.)
118
+ const dynamicKey = Object.keys(entry).find(key => (typeof entry[key] === 'object') && (entry[key] !== null) && !Array.isArray(entry[key]));
119
+
120
+ if (!dynamicKey) {
121
+ // Skip if no valid dynamic key is found
122
+ return acc;
123
+ }
124
+
125
+ const data = entry[dynamicKey];
126
+ // Ensure type is present in the accumulator
127
+ if (!acc[type]) {
128
+ acc[type] = {
129
+ count: 0,
130
+ data: []
131
+ };
132
+ }
133
+ // Push each entry into the data array
134
+ acc[type].data.push(data);
135
+ // Increment count for the type
136
+ acc[type].count += 1;
137
+
138
+ return acc;
139
+ }, {});
140
+ };
141
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "asab_webui_shell",
3
- "version": "26.1.3",
3
+ "version": "26.2.1",
4
4
  "license": "BSD-3-Clause",
5
5
  "description": "TeskaLabs ASAB WebUI Shell Application",
6
6
  "contributors": [