asab_webui_shell 25.1.8 → 25.1.10
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.
|
@@ -124,6 +124,10 @@ var Application = /*#__PURE__*/function (_Component) {
|
|
|
124
124
|
_this.ReduxService.addReducer("sidebar", _reducer2["default"]);
|
|
125
125
|
_this.ReduxService.addReducer("navigation", _reducer4["default"]);
|
|
126
126
|
_this.ReduxService.addReducer("router", _reducer5["default"]);
|
|
127
|
+
|
|
128
|
+
// The application can provide a list of keys that should be automatically parsed as BigInt, when received from the server in Axios call
|
|
129
|
+
// This is important to preserve 64bit numbers from the server such as IP addresses, timestamps etc.
|
|
130
|
+
_this.JSONParseBigInt = new Set(props === null || props === void 0 ? void 0 : props.bigint);
|
|
127
131
|
_this._handleKeyUp = _this._handleKeyUp.bind(_this);
|
|
128
132
|
_this.state = {
|
|
129
133
|
networking: 0,
|
|
@@ -337,6 +341,10 @@ var Application = /*#__PURE__*/function (_Component) {
|
|
|
337
341
|
return undefined;
|
|
338
342
|
}
|
|
339
343
|
var axios = _axios["default"].create(_objectSpread(_objectSpread({}, props), {}, {
|
|
344
|
+
transformResponse: function transformResponse(res) {
|
|
345
|
+
return res;
|
|
346
|
+
},
|
|
347
|
+
// Disable implicit JSON parsing, we explicitly parse JSON in the interceptor ( https://stackoverflow.com/questions/41013082/disable-json-parsing-in-axios )
|
|
340
348
|
baseURL: service_url
|
|
341
349
|
}));
|
|
342
350
|
|
|
@@ -370,9 +378,49 @@ var Application = /*#__PURE__*/function (_Component) {
|
|
|
370
378
|
return Promise.reject(error);
|
|
371
379
|
});
|
|
372
380
|
|
|
373
|
-
// We want to remove networking indicator when we
|
|
381
|
+
// We want to remove the networking indicator when we receive the response
|
|
374
382
|
axios.interceptors.response.use(function (response) {
|
|
383
|
+
var _response$headers$con;
|
|
384
|
+
// Call the `popNetworkingIndicator` method to remove the networking indicator (e.g., loading spinner)
|
|
375
385
|
that.popNetworkingIndicator();
|
|
386
|
+
|
|
387
|
+
/*
|
|
388
|
+
Custom flag to control JSON parsing for specific requests.
|
|
389
|
+
If 'skipJsonParsing' is set to true in the request config,
|
|
390
|
+
we return the raw response and skip automatic JSON parsing in the interceptor.
|
|
391
|
+
This is useful when we need to get the response as plain text (e.g., for retrieving raw content).
|
|
392
|
+
*/
|
|
393
|
+
if (response.config.skipJsonParsing) {
|
|
394
|
+
return response;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// Check if the response content type is 'application/json' or starts with 'application/json'
|
|
398
|
+
if (response !== null && response !== void 0 && (_response$headers$con = response.headers['content-type']) !== null && _response$headers$con !== void 0 && _response$headers$con.startsWith('application/json')) {
|
|
399
|
+
// If the response is JSON, then parse it with respect to BigInt
|
|
400
|
+
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse
|
|
401
|
+
try {
|
|
402
|
+
// Parse the response data using a custom reviver function
|
|
403
|
+
response.data = JSON.parse(response.data,
|
|
404
|
+
// Custom reviver function to handle BigInt values
|
|
405
|
+
function (key, value, context) {
|
|
406
|
+
// If there is no data in the JSONParseBigInt, return the value immediately
|
|
407
|
+
if (that.JSONParseBigInt.size === 0) {
|
|
408
|
+
return value;
|
|
409
|
+
}
|
|
410
|
+
// Check if the key is in the `JSONParseBigInt` set and the value is a number
|
|
411
|
+
if (that.JSONParseBigInt.has(key) && typeof value === 'number') {
|
|
412
|
+
// Convert the number to a BigInt
|
|
413
|
+
return BigInt(context.source);
|
|
414
|
+
}
|
|
415
|
+
// Return the original value if no conversion is needed
|
|
416
|
+
return value;
|
|
417
|
+
});
|
|
418
|
+
} catch (e) {
|
|
419
|
+
// Log any errors that occur during JSON parsing
|
|
420
|
+
console.error("Error in axios.interceptors.response", e);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
// If the request was satisfied (application/json and presence of BigInt) return the modified object. If not, we return unchanged object
|
|
376
424
|
return response;
|
|
377
425
|
}, function (error) {
|
|
378
426
|
that.popNetworkingIndicator();
|
|
@@ -27,6 +27,14 @@ function InvitationScreen(props) {
|
|
|
27
27
|
_useState4 = (0, _slicedToArray2["default"])(_useState3, 2),
|
|
28
28
|
isInvitationSuccessful = _useState4[0],
|
|
29
29
|
setIsInvitationSuccessful = _useState4[1];
|
|
30
|
+
var _useState5 = (0, _react.useState)(undefined),
|
|
31
|
+
_useState6 = (0, _slicedToArray2["default"])(_useState5, 2),
|
|
32
|
+
registrationUrl = _useState6[0],
|
|
33
|
+
setRegistrationUrl = _useState6[1];
|
|
34
|
+
var _useState7 = (0, _react.useState)(undefined),
|
|
35
|
+
_useState8 = (0, _slicedToArray2["default"])(_useState7, 2),
|
|
36
|
+
urlCopied = _useState8[0],
|
|
37
|
+
setUrlCopied = _useState8[1];
|
|
30
38
|
var tenant = (0, _reactRedux.useSelector)(function (state) {
|
|
31
39
|
var _state$tenant;
|
|
32
40
|
return (_state$tenant = state.tenant) === null || _state$tenant === void 0 ? void 0 : _state$tenant.current;
|
|
@@ -36,6 +44,25 @@ function InvitationScreen(props) {
|
|
|
36
44
|
var navigate = (0, _reactRouterDom.useNavigate)();
|
|
37
45
|
var SeaCatAuthAPI = props.app.axiosCreate('seacat-auth');
|
|
38
46
|
|
|
47
|
+
// Copy registration URL if there is any
|
|
48
|
+
var copyRegistrationUrl = function copyRegistrationUrl() {
|
|
49
|
+
if (!registrationUrl) {
|
|
50
|
+
console.error('No registration URL to copy.');
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
navigator.clipboard.writeText(registrationUrl).then(function () {
|
|
54
|
+
setUrlCopied(true);
|
|
55
|
+
var timeoutId = setTimeout(function () {
|
|
56
|
+
return setUrlCopied(false);
|
|
57
|
+
}, 3000);
|
|
58
|
+
return function () {
|
|
59
|
+
clearTimeout(timeoutId);
|
|
60
|
+
};
|
|
61
|
+
})["catch"](function (error) {
|
|
62
|
+
console.error('Failed to copy registration URL: ', error);
|
|
63
|
+
});
|
|
64
|
+
};
|
|
65
|
+
|
|
39
66
|
// Validate email input
|
|
40
67
|
var emailValidation = function emailValidation(e) {
|
|
41
68
|
e.preventDefault();
|
|
@@ -45,7 +72,7 @@ function InvitationScreen(props) {
|
|
|
45
72
|
// Send invitation to the specified email
|
|
46
73
|
var sendInvitation = /*#__PURE__*/function () {
|
|
47
74
|
var _ref = (0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee(e) {
|
|
48
|
-
var body, _response$data, response;
|
|
75
|
+
var body, _response$data, _response$data2, response, _response$data3, _e$response, _e$response2;
|
|
49
76
|
return _regenerator["default"].wrap(function _callee$(_context) {
|
|
50
77
|
while (1) switch (_context.prev = _context.next) {
|
|
51
78
|
case 0:
|
|
@@ -66,29 +93,57 @@ function InvitationScreen(props) {
|
|
|
66
93
|
case 8:
|
|
67
94
|
setIsInvitationSuccessful(true);
|
|
68
95
|
setEmailValue('');
|
|
69
|
-
|
|
96
|
+
if (response !== null && response !== void 0 && (_response$data2 = response.data) !== null && _response$data2 !== void 0 && _response$data2.registration_url) {
|
|
97
|
+
setRegistrationUrl(response === null || response === void 0 || (_response$data3 = response.data) === null || _response$data3 === void 0 ? void 0 : _response$data3.registration_url);
|
|
98
|
+
} else {
|
|
99
|
+
setRegistrationUrl(undefined);
|
|
100
|
+
}
|
|
101
|
+
_context.next = 17;
|
|
70
102
|
break;
|
|
71
|
-
case
|
|
72
|
-
_context.prev =
|
|
103
|
+
case 13:
|
|
104
|
+
_context.prev = 13;
|
|
73
105
|
_context.t0 = _context["catch"](2);
|
|
74
106
|
setIsInvitationSuccessful(false);
|
|
75
|
-
|
|
107
|
+
if (_context.t0 !== null && _context.t0 !== void 0 && (_e$response = _context.t0.response) !== null && _e$response !== void 0 && (_e$response = _e$response.data) !== null && _e$response !== void 0 && _e$response.registration_url) {
|
|
108
|
+
setRegistrationUrl(_context.t0 === null || _context.t0 === void 0 || (_e$response2 = _context.t0.response) === null || _e$response2 === void 0 || (_e$response2 = _e$response2.data) === null || _e$response2 === void 0 ? void 0 : _e$response2.registration_url);
|
|
109
|
+
} else {
|
|
110
|
+
setRegistrationUrl(undefined);
|
|
111
|
+
}
|
|
112
|
+
case 17:
|
|
76
113
|
case "end":
|
|
77
114
|
return _context.stop();
|
|
78
115
|
}
|
|
79
|
-
}, _callee, null, [[2,
|
|
116
|
+
}, _callee, null, [[2, 13]]);
|
|
80
117
|
}));
|
|
81
118
|
return function sendInvitation(_x) {
|
|
82
119
|
return _ref.apply(this, arguments);
|
|
83
120
|
};
|
|
84
121
|
}();
|
|
85
122
|
|
|
123
|
+
// Component that displays the registration URL with a copy button
|
|
124
|
+
var CopyableRegistrationUrl = function CopyableRegistrationUrl(_ref2) {
|
|
125
|
+
var registrationUrl = _ref2.registrationUrl;
|
|
126
|
+
return /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, /*#__PURE__*/_react["default"].createElement(_reactstrap.FormText, null, t('InvitationScreen|If you want to invite the user manually, message them the registration URL below:')), /*#__PURE__*/_react["default"].createElement(_reactstrap.InputGroup, null, /*#__PURE__*/_react["default"].createElement(_reactstrap.Input, {
|
|
127
|
+
readOnly: true,
|
|
128
|
+
value: registrationUrl
|
|
129
|
+
}), /*#__PURE__*/_react["default"].createElement(_reactstrap.Button, {
|
|
130
|
+
outline: true,
|
|
131
|
+
color: "primary",
|
|
132
|
+
className: "text-nowrap",
|
|
133
|
+
onClick: copyRegistrationUrl
|
|
134
|
+
}, /*#__PURE__*/_react["default"].createElement("i", {
|
|
135
|
+
className: urlCopied ? 'bi bi-clipboard-check pe-2' : 'bi bi-clipboard pe-2',
|
|
136
|
+
title: t('InvitationScreen|Copy to clipboard')
|
|
137
|
+
}), urlCopied ? t('InvitationScreen|Copied!') : t('InvitationScreen|Copy URL'))));
|
|
138
|
+
};
|
|
139
|
+
|
|
86
140
|
// Display for successful invitation
|
|
87
141
|
var SuccessfulInvitationCardBody = function SuccessfulInvitationCardBody() {
|
|
88
|
-
return /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, /*#__PURE__*/_react["default"].createElement("h6", null, t('InvitationScreen|Invitation
|
|
142
|
+
return /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, /*#__PURE__*/_react["default"].createElement("h6", null, t('InvitationScreen|Invitation was sent successfully')), registrationUrl && /*#__PURE__*/_react["default"].createElement(CopyableRegistrationUrl, {
|
|
143
|
+
registrationUrl: registrationUrl
|
|
144
|
+
}), /*#__PURE__*/_react["default"].createElement("div", {
|
|
89
145
|
className: "mt-2"
|
|
90
146
|
}, /*#__PURE__*/_react["default"].createElement(_reactstrap.Button, {
|
|
91
|
-
block: true,
|
|
92
147
|
onClick: function onClick() {
|
|
93
148
|
return navigate('/auth/credentials');
|
|
94
149
|
},
|
|
@@ -99,10 +154,11 @@ function InvitationScreen(props) {
|
|
|
99
154
|
|
|
100
155
|
// Display for unsuccessful invitation
|
|
101
156
|
var UnsuccessfulInvitationCardBody = function UnsuccessfulInvitationCardBody() {
|
|
102
|
-
return /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, /*#__PURE__*/_react["default"].createElement("h6", null, t('InvitationScreen|Invitation
|
|
157
|
+
return /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, /*#__PURE__*/_react["default"].createElement("h6", null, t('InvitationScreen|Invitation was not sent')), registrationUrl ? /*#__PURE__*/_react["default"].createElement(CopyableRegistrationUrl, {
|
|
158
|
+
registrationUrl: registrationUrl
|
|
159
|
+
}) : /*#__PURE__*/_react["default"].createElement(_reactstrap.FormText, null, t('InvitationScreen|The user could not be invited')), /*#__PURE__*/_react["default"].createElement("div", {
|
|
103
160
|
className: "mt-2"
|
|
104
161
|
}, /*#__PURE__*/_react["default"].createElement(_reactstrap.Button, {
|
|
105
|
-
block: true,
|
|
106
162
|
onClick: function onClick() {
|
|
107
163
|
return setIsInvitationSuccessful(undefined);
|
|
108
164
|
},
|
|
@@ -132,7 +188,7 @@ function InvitationScreen(props) {
|
|
|
132
188
|
className: "flex-fill"
|
|
133
189
|
}, /*#__PURE__*/_react["default"].createElement("h3", null, /*#__PURE__*/_react["default"].createElement("i", {
|
|
134
190
|
className: "bi bi-person-plus pe-2"
|
|
135
|
-
}), t('InvitationScreen|Invite other users')))), /*#__PURE__*/_react["default"].createElement(_reactstrap.CardBody, null, /*#__PURE__*/_react["default"].createElement(_reactstrap.Label, null, t('InvitationScreen|Enter the email
|
|
191
|
+
}), t('InvitationScreen|Invite other users')))), /*#__PURE__*/_react["default"].createElement(_reactstrap.CardBody, null, /*#__PURE__*/_react["default"].createElement(_reactstrap.Label, null, t('InvitationScreen|Enter the user\'s email address')), /*#__PURE__*/_react["default"].createElement(_reactstrap.InputGroup, null, /*#__PURE__*/_react["default"].createElement(_reactstrap.InputGroupText, null, /*#__PURE__*/_react["default"].createElement("i", {
|
|
136
192
|
className: "bi bi-envelope-at"
|
|
137
193
|
})), /*#__PURE__*/_react["default"].createElement(_reactstrap.Input, {
|
|
138
194
|
name: "email",
|
|
@@ -157,5 +213,5 @@ function InvitationScreen(props) {
|
|
|
157
213
|
}, "\xA0"), /*#__PURE__*/_react["default"].createElement(_reactstrap.Button, {
|
|
158
214
|
color: "primary",
|
|
159
215
|
disabled: emailValue === '' // Disable button if input is empty
|
|
160
|
-
}, t('InvitationScreen|
|
|
216
|
+
}, t('InvitationScreen|Invite'))))))));
|
|
161
217
|
}
|