asab_webui_shell 27.3.3 → 27.3.5

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.
@@ -214,6 +214,74 @@ class Application extends _react.Component {
214
214
  }
215
215
  return service_url.replace(/\/$/, '') + "/" + service_path;
216
216
  }
217
+ /**
218
+ * Safely parses JSON and preserves numeric precision by converting configured keys to BigInt.
219
+ *
220
+ * WHY THIS EXISTS:
221
+ * JavaScript loses precision for integers larger than Number.MAX_SAFE_INTEGER.
222
+ * This helper allows selected JSON numeric fields to be converted into BigInt
223
+ * based on keys configured in `this.JSONParseBigInt`.
224
+ *
225
+ * WHERE THIS IS USED:
226
+ * 1. Axios response interceptor
227
+ * - Default JSON parsing is disabled via `transformResponse`.
228
+ * - JSON responses are manually parsed here to preserve BigInt values.
229
+ *
230
+ * 2. WebSocket message processing
231
+ * - WebSocket frames arrive as raw strings.
232
+ * - `event.data` is parsed using this helper before being passed
233
+ * to message handlers and UI logic.
234
+ *
235
+ * CONFIGURATION:
236
+ * `this.JSONParseBigInt` must be a Set containing JSON keys
237
+ * whose numeric values should be converted to BigInt.
238
+ *
239
+ * USAGE EXAMPLES:
240
+ *
241
+ * Axios (response interceptor):
242
+ * response.data = this.jsonParseWithBigInt(response.data);
243
+ *
244
+ * WebSocket:
245
+ * ws.onmessage = (event) => {
246
+ * // event.data is a string received from the WebSocket frame
247
+ * const message = app.jsonParseWithBigInt(event.data);
248
+ * ...
249
+ * };
250
+ * BEHAVIOR:
251
+ * - If source is not a string → returns it unchanged
252
+ * - If no BigInt keys are configured → falls back to JSON.parse
253
+ * - Only explicitly configured keys are converted to BigInt
254
+ */
255
+ jsonParseWithBigInt(source) {
256
+ // If the input is not a string, return it immediately (no parsing needed)
257
+ if (typeof source !== 'string') {
258
+ return source;
259
+ }
260
+
261
+ // Save reference to 'this' for accessing instance properties
262
+ var that = this;
263
+
264
+ // Fast path: if no BigInt keys are configured, parse the JSON normally
265
+ if (!that.JSONParseBigInt || that.JSONParseBigInt.size === 0) {
266
+ return JSON.parse(source);
267
+ }
268
+
269
+ // Parse the JSON string with a custom reviver function to handle BigInt
270
+ return JSON.parse(source, (key, value, context) => {
271
+ try {
272
+ // Convert numeric values to BigInt only for explicitly configured keys
273
+ if (that.JSONParseBigInt.has(key) && typeof value === 'number' && (context === null || context === void 0 ? void 0 : context.source) !== undefined) {
274
+ // Convert the numeric value to a BigInt to avoid precision loss
275
+ return BigInt(context.source);
276
+ }
277
+ } catch (e) {
278
+ console.error("Error converting to BigInt:", e, "key:", key, "value:", value);
279
+ }
280
+
281
+ // For all other keys/values, return the value as-is
282
+ return value;
283
+ });
284
+ }
217
285
 
218
286
  /*
219
287
  * Creates an AXIOS object for communication with TeskaLabs API's
@@ -291,22 +359,8 @@ class Application extends _react.Component {
291
359
  // If the response is JSON, then parse it with respect to BigInt
292
360
  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse
293
361
  try {
294
- // Parse the response data using a custom reviver function
295
- response.data = JSON.parse(response.data,
296
- // Custom reviver function to handle BigInt values
297
- (key, value, context) => {
298
- // If there is no data in the JSONParseBigInt, return the value immediately
299
- if (that.JSONParseBigInt.size === 0) {
300
- return value;
301
- }
302
- // Check if the key is in the `JSONParseBigInt` set and the value is a number
303
- if (that.JSONParseBigInt.has(key) && typeof value === 'number') {
304
- // Convert the number to a BigInt
305
- return BigInt(context.source);
306
- }
307
- // Return the original value if no conversion is needed
308
- return value;
309
- });
362
+ // Parse the response data using jsonParseWithBigInt reviver function
363
+ response.data = that.jsonParseWithBigInt(response.data);
310
364
  } catch (e) {
311
365
  // Log any errors that occur during JSON parsing
312
366
  console.error("Error in axios.interceptors.response", e);
@@ -435,6 +489,7 @@ class Application extends _react.Component {
435
489
  this.setState(prevState => ({
436
490
  printReadyIndicators: prevState.printReadyIndicators + 1
437
491
  }));
492
+ console.log('print-ready', document.body.getAttribute('print-ready'), 'push');
438
493
  }
439
494
  popPrintReadyIndicator() {
440
495
  this.setState(prevState => {
@@ -446,6 +501,7 @@ class Application extends _react.Component {
446
501
  printReadyIndicators: Math.max(nextValue, 0)
447
502
  };
448
503
  });
504
+ console.log('print-ready', document.body.getAttribute('print-ready'), 'pop');
449
505
  }
450
506
  registerService(service) {
451
507
  if (service.Name in this.Services) {
@@ -496,11 +552,13 @@ class Application extends _react.Component {
496
552
  if (this.state.printReadyIndicators === 0) {
497
553
  document.body.setAttribute('print-ready', 'true');
498
554
  this._printReadyTimeout = null;
555
+ console.log('print-ready', document.body.getAttribute('print-ready'), 'set true');
499
556
  }
500
557
  }, 1500); // Add 1500ms delay to ensure that the print-ready attribute is set after the last print-ready indicator is popped
501
558
  } else {
502
559
  this._clearPrintReadyTimeout();
503
560
  document.body.setAttribute('print-ready', 'false');
561
+ console.log('print-ready', document.body.getAttribute('print-ready'), 'set false');
504
562
  }
505
563
  }
506
564
  componentWillUnmount() {
@@ -513,6 +571,7 @@ class Application extends _react.Component {
513
571
  }
514
572
  this._clearPrintReadyTimeout();
515
573
  document.body.removeAttribute('print-ready');
574
+ console.log('print-ready', document.body.getAttribute('print-ready'), 'unmount removed');
516
575
  }
517
576
  _clearPrintReadyTimeout() {
518
577
  if (this._printReadyTimeout !== null) {
@@ -547,6 +606,7 @@ class Application extends _react.Component {
547
606
  if (this.SplashscreenRequestors.size == 0) {
548
607
  var splashscreen = document.getElementById('app-splashscreen'); // See public/index.html
549
608
  splashscreen === null || splashscreen === void 0 || splashscreen.classList.add("d-none");
609
+ console.log('print-ready', document.body.getAttribute('print-ready'), 'splash last removed, pop');
550
610
  // Decrement print-ready indicator value if no splash screen requestors are present
551
611
  this.popPrintReadyIndicator();
552
612
  }
@@ -36,15 +36,18 @@ function UnauthorizedAccessScreen(props) {
36
36
  if (!isAuthorized) {
37
37
  document.body.setAttribute('print-ready', 'true');
38
38
  document.body.setAttribute('print-unauthorized', 'true');
39
+ console.log('print-ready', document.body.getAttribute('print-ready'), 'UnauthorizedAccessScreen set true');
39
40
  } else {
40
41
  document.body.removeAttribute('print-ready');
41
42
  document.body.removeAttribute('print-unauthorized');
43
+ console.log('print-ready', document.body.getAttribute('print-ready'), 'UnauthorizedAccessScreen cleared');
42
44
  }
43
45
 
44
46
  // Cleanup function to remove the attributes when the component unmounts
45
47
  return () => {
46
48
  document.body.removeAttribute('print-ready');
47
49
  document.body.removeAttribute('print-unauthorized');
50
+ console.log('print-ready', document.body.getAttribute('print-ready'), 'UnauthorizedAccessScreen cleanup');
48
51
  };
49
52
  }, [isAuthorized]);
50
53
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "asab_webui_shell",
3
- "version": "27.3.3",
3
+ "version": "27.3.5",
4
4
  "license": "BSD-3-Clause",
5
5
  "description": "TeskaLabs ASAB WebUI Shell Application",
6
6
  "contributors": [