@carbonorm/carbonreact 3.6.2 → 4.0.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.
- package/README.md +1 -1
- package/dist/CarbonReact.d.ts +17 -8
- package/dist/components/Alert/Alert.d.ts +5 -1
- package/dist/components/Errors/BackendThrowable.d.ts +4 -1
- package/dist/components/WebSocket/CarbonWebSocket.d.ts +3 -1
- package/dist/hoc/KeysMatching.d.ts +1 -1
- package/dist/hoc/SubsetMatching.d.ts +4 -0
- package/dist/hoc/deleteRestfulObjectArrays.d.ts +17 -3
- package/dist/hoc/updateRestfulObjectArrays.d.ts +25 -11
- package/dist/index.cjs.js +156 -169
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.esm.js +157 -170
- package/dist/index.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/CarbonReact.tsx +36 -21
- package/src/components/Alert/Alert.tsx +32 -29
- package/src/components/Errors/BackendThrowable.tsx +11 -8
- package/src/components/WebSocket/CarbonWebSocket.tsx +21 -15
- package/src/hoc/KeysMatching.ts +4 -2
- package/src/hoc/SubsetMatching.ts +6 -0
- package/src/hoc/deleteRestfulObjectArrays.tsx +51 -52
- package/src/hoc/updateRestfulObjectArrays.tsx +97 -97
- package/src/index.ts +1 -0
- package/src/variables/C6.tsx +1 -1
- package/dist/variables/C6.d.ts +0 -842
package/dist/index.d.ts
CHANGED
|
@@ -28,6 +28,7 @@ export { default as CarbonWebSocket } from "./components/WebSocket/CarbonWebSock
|
|
|
28
28
|
export * from "./components/WebSocket/CarbonWebSocket";
|
|
29
29
|
export * from "./hoc/GlobalHistory";
|
|
30
30
|
export * from "./hoc/KeysMatching";
|
|
31
|
+
export * from "./hoc/SubsetMatching";
|
|
31
32
|
export { default as addValidSQL } from "./hoc/addValidSQL";
|
|
32
33
|
export * from "./hoc/addValidSQL";
|
|
33
34
|
export { default as changed } from "./hoc/changed";
|
package/dist/index.esm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import react, { useRef, useState, useEffect, Component, createContext,
|
|
1
|
+
import react, { useRef, useState, useEffect, Component, createContext, lazy } from 'react';
|
|
2
2
|
import { toastOptions, clearCache, timeout, axiosInstance, isVerbose, checkAllRequestsComplete } from '@carbonorm/carbonnode';
|
|
3
3
|
import { useNavigate } from 'react-router-dom';
|
|
4
4
|
import { toast, ToastContainer } from 'react-toastify';
|
|
@@ -1409,11 +1409,11 @@ function hexToRgb (hex) {
|
|
|
1409
1409
|
|
|
1410
1410
|
var styles = {"maintenance-hero":"C5KSPNF","maintenanceHero":"C5KSPNF","httpStatusCode":"NhyRQts","centeredContainer":"nA4Uno6","errorTextGeneral":"yJAgaUs","errorKeys":"SRIoY4m","error-values":"xQIsoNw","errorValues":"xQIsoNw","error-pre":"C6eWpJ3","errorPre":"C6eWpJ3","line-number":"NFRyo7M","lineNumber":"NFRyo7M","cl":"vR2jbfr","slide":"OO2C-Wp"};
|
|
1411
1411
|
|
|
1412
|
-
var BackendThrowable = () => {
|
|
1413
|
-
const
|
|
1414
|
-
const currentThrowable =
|
|
1415
|
-
console.log([
|
|
1416
|
-
return jsxRuntime_2("div", { className: styles.maintenanceHero, children: [jsxRuntime_1("h1", { className: styles.httpStatusCode, children: currentThrowable?.status || 500 }), jsxRuntime_1(OutsideClickHandler, { onOutsideClick: () =>
|
|
1412
|
+
var BackendThrowable = (props) => {
|
|
1413
|
+
const { instance } = props;
|
|
1414
|
+
const currentThrowable = instance.state.backendThrowable[0];
|
|
1415
|
+
console.log([instance.state.backendThrowable, currentThrowable]);
|
|
1416
|
+
return jsxRuntime_2("div", { className: styles.maintenanceHero, children: [jsxRuntime_1("h1", { className: styles.httpStatusCode, children: currentThrowable?.status || 500 }), jsxRuntime_1(OutsideClickHandler, { onOutsideClick: () => instance.setState(currentState => ({ backendThrowable: currentState.backendThrowable.slice(1) })), children: jsxRuntime_1("div", { className: styles.centeredContainer, children: Object.keys(currentThrowable).map((key, index) => {
|
|
1417
1417
|
const valueIsString = typeof currentThrowable[key] === 'string';
|
|
1418
1418
|
const valueIsCode = 'THROWN NEAR' === key;
|
|
1419
1419
|
return jsxRuntime_2("div", { children: [jsxRuntime_2("div", { className: styles.errorTextGeneral, children: [" > ", jsxRuntime_1("span", { className: styles.errorKeys, children: key }), ":", valueIsString
|
|
@@ -3922,14 +3922,14 @@ function Popup({ open = true, handleClose, children, maxWidth, }) {
|
|
|
3922
3922
|
const isProduction = window.location.host.split(".")[0] === "www";
|
|
3923
3923
|
|
|
3924
3924
|
function addAlert(props) {
|
|
3925
|
-
|
|
3925
|
+
props.instance.setState(previousState => ({
|
|
3926
3926
|
alertsWaiting: previousState.alertsWaiting.length === 0
|
|
3927
3927
|
? [props]
|
|
3928
3928
|
: [...previousState.alertsWaiting, props]
|
|
3929
3929
|
}));
|
|
3930
3930
|
}
|
|
3931
|
-
function Alert() {
|
|
3932
|
-
const { alertsWaiting, backendThrowable } =
|
|
3931
|
+
function Alert({ instance }) {
|
|
3932
|
+
const { alertsWaiting, backendThrowable } = instance.state;
|
|
3933
3933
|
let alert = undefined;
|
|
3934
3934
|
const alertWaiting = alertsWaiting.length + backendThrowable.length;
|
|
3935
3935
|
if (backendThrowable.length !== 0) {
|
|
@@ -3944,8 +3944,9 @@ function Alert() {
|
|
|
3944
3944
|
color: 'primary',
|
|
3945
3945
|
});
|
|
3946
3946
|
}
|
|
3947
|
-
const backendThrowable =
|
|
3947
|
+
const backendThrowable = instance.state.backendThrowable[0];
|
|
3948
3948
|
alert = {
|
|
3949
|
+
instance: instance,
|
|
3949
3950
|
title: "Oh no! An issue occurred!",
|
|
3950
3951
|
text: backendThrowable?.['DropInGaming\\PHP\\Errors\\DropException'] ?? 'An unknown issue occurred. Please try again.',
|
|
3951
3952
|
timeout: 0,
|
|
@@ -3956,7 +3957,7 @@ function Alert() {
|
|
|
3956
3957
|
backendThrowable: backendThrowable,
|
|
3957
3958
|
then: (value) => {
|
|
3958
3959
|
if (value === 'Expand') {
|
|
3959
|
-
|
|
3960
|
+
instance.setState(previousState => {
|
|
3960
3961
|
let backendThrowable = previousState.backendThrowable.pop();
|
|
3961
3962
|
if (backendThrowable === undefined) {
|
|
3962
3963
|
return {
|
|
@@ -3970,7 +3971,7 @@ function Alert() {
|
|
|
3970
3971
|
});
|
|
3971
3972
|
}
|
|
3972
3973
|
else {
|
|
3973
|
-
|
|
3974
|
+
instance.setState(previousState => ({
|
|
3974
3975
|
backendThrowable: previousState.backendThrowable.slice(1)
|
|
3975
3976
|
}));
|
|
3976
3977
|
}
|
|
@@ -3984,15 +3985,14 @@ function Alert() {
|
|
|
3984
3985
|
return null;
|
|
3985
3986
|
}
|
|
3986
3987
|
const timeout = alert?.timeout || 15000;
|
|
3987
|
-
const
|
|
3988
|
-
const dig = getStyles();
|
|
3988
|
+
const styles = getStyles();
|
|
3989
3989
|
let cancelTimeout = null;
|
|
3990
3990
|
const handleClose = () => {
|
|
3991
3991
|
if (null !== cancelTimeout) {
|
|
3992
3992
|
clearTimeout(cancelTimeout);
|
|
3993
3993
|
}
|
|
3994
3994
|
if (alert?.backendThrowable === undefined) {
|
|
3995
|
-
|
|
3995
|
+
instance.setState(previousState => ({
|
|
3996
3996
|
alertsWaiting: previousState.alertsWaiting.slice(1)
|
|
3997
3997
|
}));
|
|
3998
3998
|
}
|
|
@@ -4006,25 +4006,26 @@ function Alert() {
|
|
|
4006
4006
|
handleClose();
|
|
4007
4007
|
}, timeout);
|
|
4008
4008
|
}
|
|
4009
|
-
return jsxRuntime_1(Popup, { handleClose: handleClose, children: jsxRuntime_2("div", { className: classNames("model-content",
|
|
4009
|
+
return jsxRuntime_1(Popup, { handleClose: handleClose, children: jsxRuntime_2("div", { className: classNames("model-content", styles.rounded0, styles.border0), style: {
|
|
4010
4010
|
maxWidth: '75vw',
|
|
4011
4011
|
maxHeight: '75vh',
|
|
4012
|
-
}, children: [jsxRuntime_2("div", { className: classNames(
|
|
4012
|
+
}, children: [jsxRuntime_2("div", { className: classNames(styles.modalHeader, styles.rounded0, styles.border0, {
|
|
4013
4013
|
// icon?: "warning" | "error" | "success" | "info" | "question"
|
|
4014
|
-
[
|
|
4015
|
-
[
|
|
4016
|
-
[
|
|
4017
|
-
[
|
|
4018
|
-
[
|
|
4019
|
-
}), children: [jsxRuntime_2("h3", { className: classNames(
|
|
4020
|
-
jsxRuntime_2("div", { className: classNames(
|
|
4021
|
-
|
|
4014
|
+
[styles.bg_primary]: "info" === alert.icon || alert.icon === undefined || alert.icon === null,
|
|
4015
|
+
[styles.bg_success]: "success" === alert.icon,
|
|
4016
|
+
[styles.bg_warning]: "warning" === alert.icon,
|
|
4017
|
+
[styles.bg_danger]: "error" === alert.icon, // TODO - change to red
|
|
4018
|
+
[styles.bgPrimary]: "question" === alert.icon,
|
|
4019
|
+
}), children: [jsxRuntime_2("h3", { className: classNames(styles.modalTitle, styles.textDark), id: "staticBackdropLabel", children: ["#", alertWaiting, " ", alert.title] }), jsxRuntime_1("div", { onClick: handleClose, children: jsxRuntime_1(FontAwesomeIcon, { icon: faClose, size: 'xl' }) })] }), jsxRuntime_1("div", { className: classNames(styles.modalBody, styles.border0, styles.textWhite), children: jsxRuntime_2("div", { className: styles.textCenter, children: [alert.text, alert.component] }) }), undefined !== alert.buttons &&
|
|
4020
|
+
jsxRuntime_2("div", { className: classNames(styles.modalFooter, styles.border0, styles.rounded0), children: [alert.footerText &&
|
|
4021
|
+
jsxRuntime_1("div", { className: classNames(styles.textCenter, styles.textWhite), children: alert.footerText }), alert.buttons?.map((button, index) => {
|
|
4022
|
+
return jsxRuntime_1("button", { className: classNames(styles.btn, styles.btnLg, {
|
|
4022
4023
|
// todo - color: "default" | "primary" | "secondary" | "inherit" | "danger" | "info" | "success" | "warning" | undefined,
|
|
4023
|
-
[
|
|
4024
|
-
[
|
|
4025
|
-
[
|
|
4026
|
-
[
|
|
4027
|
-
}, "btn-Yes",
|
|
4024
|
+
[styles.bg_success]: "success" === button.color,
|
|
4025
|
+
[styles.bg_danger]: "danger" === button.color,
|
|
4026
|
+
[styles.bg_primary]: "primary" === button.color,
|
|
4027
|
+
[styles.bg_warning]: "warning" === button.color,
|
|
4028
|
+
}, "btn-Yes", styles.rounded0), onClick: () => {
|
|
4028
4029
|
handleClose();
|
|
4029
4030
|
alert?.then?.(button.value ?? button.text);
|
|
4030
4031
|
}, children: button.text }, index);
|
|
@@ -4062,14 +4063,16 @@ const useEffectOnce = (effect) => {
|
|
|
4062
4063
|
* @function connect
|
|
4063
4064
|
* This function establishes a connection with the websocket and also ensures constant reconnection if connection closes
|
|
4064
4065
|
**/
|
|
4065
|
-
function initiateWebsocket(
|
|
4066
|
-
|
|
4066
|
+
function initiateWebsocket(props) {
|
|
4067
|
+
let { instance, TABLES = undefined, WsLiveUpdates = undefined, url = 'ws' + (window.location.protocol === 'https:' ? 's' : '') + '://' + window.location.host + '/carbonorm/websocket', timeoutSeconds = 250, heartbeatSeconds = 60 } = props;
|
|
4068
|
+
const { websocket } = instance.state;
|
|
4067
4069
|
if (!("WebSocket" in window)) {
|
|
4068
4070
|
// todo - store that this has been shown in the state
|
|
4069
4071
|
addAlert({
|
|
4070
4072
|
title: 'Browser does not support websockets, live updates will fail. You may need to refresh the page to see the newest content.',
|
|
4071
4073
|
text: 'Please use a modern browser.',
|
|
4072
4074
|
icon: 'warning',
|
|
4075
|
+
instance
|
|
4073
4076
|
});
|
|
4074
4077
|
}
|
|
4075
4078
|
if (false === (undefined === websocket || null === websocket)) {
|
|
@@ -4078,14 +4081,14 @@ function initiateWebsocket({ TABLES = undefined, WsLiveUpdates = undefined, url
|
|
|
4078
4081
|
let connectInterval;
|
|
4079
4082
|
const connection = new WebSocket(url);
|
|
4080
4083
|
console.log("Connecting websocket url", url);
|
|
4081
|
-
|
|
4084
|
+
instance.setState({
|
|
4082
4085
|
websocket: connection
|
|
4083
4086
|
}, () => {
|
|
4084
4087
|
connection.onopen = () => {
|
|
4085
4088
|
console.log('WebSocket Client Connected To :: ' + url);
|
|
4086
4089
|
clearTimeout(connectInterval); // clear Interval on open of websocket connection
|
|
4087
4090
|
function heartbeat() {
|
|
4088
|
-
const { websocket } =
|
|
4091
|
+
const { websocket } = instance.state;
|
|
4089
4092
|
if (!websocket)
|
|
4090
4093
|
return;
|
|
4091
4094
|
if (websocket.readyState !== 1)
|
|
@@ -4100,7 +4103,7 @@ function initiateWebsocket({ TABLES = undefined, WsLiveUpdates = undefined, url
|
|
|
4100
4103
|
if (message.data === 'pong') {
|
|
4101
4104
|
return;
|
|
4102
4105
|
}
|
|
4103
|
-
|
|
4106
|
+
instance.setState((prevState) => ({
|
|
4104
4107
|
websocketEvents: prevState.websocketEvents.concat(message),
|
|
4105
4108
|
websocketData: prevState.websocketData.concat(parsedData), // JSON.parse no good - base64?
|
|
4106
4109
|
}), () => {
|
|
@@ -4124,7 +4127,7 @@ function initiateWebsocket({ TABLES = undefined, WsLiveUpdates = undefined, url
|
|
|
4124
4127
|
}
|
|
4125
4128
|
console.log('todo - going to impl REST', TABLE_NAME, METHOD, REQUEST_PRIMARY_KEY, parsedData?.REST);
|
|
4126
4129
|
const TABLE_NAME_SHORT = TABLE_NAME.substring(TABLE_PREFIX.length);
|
|
4127
|
-
const currentCache =
|
|
4130
|
+
const currentCache = instance.state[TABLE_NAME_SHORT];
|
|
4128
4131
|
// just because we have a websocket update, doesn't mean we need the update
|
|
4129
4132
|
// check to see if the primary key is in the current cache
|
|
4130
4133
|
const c6Table = TABLES[TABLE_NAME_SHORT] ?? null;
|
|
@@ -4161,7 +4164,7 @@ function initiateWebsocket({ TABLES = undefined, WsLiveUpdates = undefined, url
|
|
|
4161
4164
|
}
|
|
4162
4165
|
});
|
|
4163
4166
|
};
|
|
4164
|
-
window.addEventListener("focus", () => initiateWebsocket());
|
|
4167
|
+
window.addEventListener("focus", () => initiateWebsocket(props));
|
|
4165
4168
|
// websocket onclose event listener
|
|
4166
4169
|
connection.addEventListener('close', event => {
|
|
4167
4170
|
let reason;
|
|
@@ -4170,7 +4173,7 @@ function initiateWebsocket({ TABLES = undefined, WsLiveUpdates = undefined, url
|
|
|
4170
4173
|
const retrySeconds = Math.min(5000, (timeoutSeconds + timeoutSeconds) * 1000);
|
|
4171
4174
|
timeoutSeconds = retrySeconds;
|
|
4172
4175
|
console.log(`WebSocket reconnect will be attempted in ${retrySeconds} second(s).`);
|
|
4173
|
-
connectInterval = setTimeout(() => initiateWebsocket(), retrySeconds);
|
|
4176
|
+
connectInterval = setTimeout(() => initiateWebsocket(props), retrySeconds);
|
|
4174
4177
|
};
|
|
4175
4178
|
// See https://www.rfc-editor.org/rfc/rfc6455#section-7.4.1
|
|
4176
4179
|
switch (event.code) {
|
|
@@ -4234,6 +4237,106 @@ function CarbonWebSocket (props) {
|
|
|
4234
4237
|
return null;
|
|
4235
4238
|
}
|
|
4236
4239
|
|
|
4240
|
+
var eUpdateInsertMethod;
|
|
4241
|
+
(function (eUpdateInsertMethod) {
|
|
4242
|
+
eUpdateInsertMethod[eUpdateInsertMethod["REPLACE"] = 0] = "REPLACE";
|
|
4243
|
+
eUpdateInsertMethod[eUpdateInsertMethod["FIRST"] = 1] = "FIRST";
|
|
4244
|
+
eUpdateInsertMethod[eUpdateInsertMethod["LAST"] = 2] = "LAST";
|
|
4245
|
+
})(eUpdateInsertMethod || (eUpdateInsertMethod = {}));
|
|
4246
|
+
/**
|
|
4247
|
+
* Updates or inserts objects in a stateful array, merging new data with existing objects.
|
|
4248
|
+
* @param instance - The React component instance.
|
|
4249
|
+
* @param dataOrCallback - Array of objects or a callback function returning an array of objects.
|
|
4250
|
+
* @param stateKey - The key in the state where the data array is stored.
|
|
4251
|
+
* @param uniqueObjectId - The unique identifier(s) for objects, typically the primary key of the table.
|
|
4252
|
+
* @param insertUpdateOrder - The order in which new data should be inserted/updated.
|
|
4253
|
+
* @param callback - Optional callback function to run after state update.
|
|
4254
|
+
*/
|
|
4255
|
+
function updateRestfulObjectArrays({ instance, dataOrCallback, stateKey, uniqueObjectId, insertUpdateOrder = eUpdateInsertMethod.LAST, callback, }) {
|
|
4256
|
+
const uniqueObjectIds = Array.isArray(uniqueObjectId) ? uniqueObjectId : [uniqueObjectId];
|
|
4257
|
+
instance.setState((previousBootstrapState, props) => {
|
|
4258
|
+
let newOrReplacementData = [];
|
|
4259
|
+
if (Array.isArray(dataOrCallback)) {
|
|
4260
|
+
newOrReplacementData = dataOrCallback;
|
|
4261
|
+
}
|
|
4262
|
+
else if (typeof dataOrCallback === "function") {
|
|
4263
|
+
newOrReplacementData = dataOrCallback(previousBootstrapState, props);
|
|
4264
|
+
}
|
|
4265
|
+
else {
|
|
4266
|
+
throw new Error("The dataOrCallback parameter must be an array or function");
|
|
4267
|
+
}
|
|
4268
|
+
if (newOrReplacementData === null) {
|
|
4269
|
+
return null;
|
|
4270
|
+
}
|
|
4271
|
+
const findUniqueObjectIds = (item, value) => {
|
|
4272
|
+
return uniqueObjectIds.every((id) => item[id] === value[id]);
|
|
4273
|
+
};
|
|
4274
|
+
const previousStateProperty = previousBootstrapState[stateKey] ?? [];
|
|
4275
|
+
let updatedData = newOrReplacementData.map((value) => {
|
|
4276
|
+
const existingObject = previousStateProperty?.find((item) => findUniqueObjectIds(item, value)) || {};
|
|
4277
|
+
return { ...existingObject, ...value };
|
|
4278
|
+
});
|
|
4279
|
+
const filterOutUpdated = (array) => {
|
|
4280
|
+
return array?.filter((item) => !updatedData.some((value) => findUniqueObjectIds(item, value))) ?? [];
|
|
4281
|
+
};
|
|
4282
|
+
let newState = {};
|
|
4283
|
+
switch (insertUpdateOrder) {
|
|
4284
|
+
case eUpdateInsertMethod.LAST:
|
|
4285
|
+
newState[stateKey] = [
|
|
4286
|
+
...filterOutUpdated(previousStateProperty),
|
|
4287
|
+
...updatedData,
|
|
4288
|
+
];
|
|
4289
|
+
break;
|
|
4290
|
+
case eUpdateInsertMethod.FIRST:
|
|
4291
|
+
newState[stateKey] = [
|
|
4292
|
+
...updatedData,
|
|
4293
|
+
...filterOutUpdated(previousStateProperty),
|
|
4294
|
+
];
|
|
4295
|
+
break;
|
|
4296
|
+
case eUpdateInsertMethod.REPLACE:
|
|
4297
|
+
newState[stateKey] = [
|
|
4298
|
+
...(previousStateProperty?.map((oldObject) => {
|
|
4299
|
+
const index = updatedData.findIndex((item) => findUniqueObjectIds(item, oldObject));
|
|
4300
|
+
if (index !== -1) {
|
|
4301
|
+
return updatedData.splice(index, 1)[0];
|
|
4302
|
+
}
|
|
4303
|
+
return oldObject;
|
|
4304
|
+
}) ?? []),
|
|
4305
|
+
...updatedData,
|
|
4306
|
+
];
|
|
4307
|
+
break;
|
|
4308
|
+
default:
|
|
4309
|
+
throw new Error("The insertUpdateOrder (eUpdateInsertMethod) was not implemented");
|
|
4310
|
+
}
|
|
4311
|
+
return newState;
|
|
4312
|
+
}, callback);
|
|
4313
|
+
}
|
|
4314
|
+
|
|
4315
|
+
function deleteRestfulObjectArrays({ instance, dataOrCallback, stateKey, uniqueObjectId, callback }) {
|
|
4316
|
+
const uniqueObjectIds = Array.isArray(uniqueObjectId) ? uniqueObjectId : [uniqueObjectId];
|
|
4317
|
+
instance.setState((previousBootstrapState, props) => {
|
|
4318
|
+
let newOrReplacementData = [];
|
|
4319
|
+
if (Array.isArray(dataOrCallback)) {
|
|
4320
|
+
newOrReplacementData = dataOrCallback;
|
|
4321
|
+
}
|
|
4322
|
+
else if (typeof dataOrCallback === 'function') {
|
|
4323
|
+
const callbackReturn = dataOrCallback(previousBootstrapState, props);
|
|
4324
|
+
if (callbackReturn === null) {
|
|
4325
|
+
return null; // No updates needed (noop)
|
|
4326
|
+
}
|
|
4327
|
+
newOrReplacementData = callbackReturn;
|
|
4328
|
+
}
|
|
4329
|
+
else {
|
|
4330
|
+
throw new Error('The dataOrCallback parameter was not an array or function');
|
|
4331
|
+
}
|
|
4332
|
+
const previousStateProperty = previousBootstrapState[stateKey];
|
|
4333
|
+
const updatedStateProperty = previousStateProperty?.filter(item => !newOrReplacementData.some(value => uniqueObjectIds.every(uniqueId => value[uniqueId] === item[uniqueId]))) ?? [];
|
|
4334
|
+
return {
|
|
4335
|
+
[stateKey]: updatedStateProperty
|
|
4336
|
+
};
|
|
4337
|
+
}, callback);
|
|
4338
|
+
}
|
|
4339
|
+
|
|
4237
4340
|
const initialRequiredCarbonORMState = {
|
|
4238
4341
|
alertsWaiting: [],
|
|
4239
4342
|
backendThrowable: [],
|
|
@@ -4254,27 +4357,32 @@ function isJsonString(str) {
|
|
|
4254
4357
|
}
|
|
4255
4358
|
return true;
|
|
4256
4359
|
}
|
|
4257
|
-
// Create a context
|
|
4258
4360
|
const persistentStateMap = new Map();
|
|
4259
4361
|
class CarbonReact extends Component {
|
|
4260
4362
|
context = createContext(this.state);
|
|
4261
4363
|
// Private static member
|
|
4364
|
+
// we actually implement this in the constructor todo - test this
|
|
4262
4365
|
static instance;
|
|
4263
|
-
|
|
4264
|
-
|
|
4265
|
-
|
|
4266
|
-
|
|
4267
|
-
|
|
4268
|
-
|
|
4269
|
-
|
|
4366
|
+
target;
|
|
4367
|
+
updateRestfulObjectArrays = (rest) => updateRestfulObjectArrays({
|
|
4368
|
+
instance: this,
|
|
4369
|
+
...rest
|
|
4370
|
+
});
|
|
4371
|
+
deleteRestfulObjectArrays = (rest) => deleteRestfulObjectArrays({
|
|
4372
|
+
instance: this,
|
|
4373
|
+
...rest
|
|
4374
|
+
});
|
|
4270
4375
|
static lastLocation = window.location.pathname;
|
|
4271
4376
|
// @link https://github.com/welldone-software/why-did-you-render
|
|
4272
4377
|
// noinspection JSUnusedGlobalSymbols
|
|
4273
4378
|
static whyDidYouRender = true;
|
|
4274
4379
|
constructor(props) {
|
|
4275
4380
|
super(props);
|
|
4381
|
+
this.target = new.target;
|
|
4276
4382
|
console.log('CarbonORM TSX CONSTRUCTOR');
|
|
4277
|
-
|
|
4383
|
+
// this is the magic that allows each class that's extends this to have a static instance - a singleton pattern
|
|
4384
|
+
// new.target is a meta-property introduced in ES6 that references the constructor that was directly invoked with the new keyword.
|
|
4385
|
+
Object.assign(new.target, {
|
|
4278
4386
|
instance: this
|
|
4279
4387
|
});
|
|
4280
4388
|
if (this.props.instanceId && persistentStateMap.has(this.props.instanceId)) {
|
|
@@ -4319,11 +4427,11 @@ class CarbonReact extends Component {
|
|
|
4319
4427
|
console.log('%c color (' + colorHex + ')', 'color: ' + colorHex);
|
|
4320
4428
|
const nest = jsxRuntime_1(Nest, { position: 'fixed', backgroundColor: '', color: hexToRgb(colorHex), count: 100 });
|
|
4321
4429
|
if (this.state.backendThrowable.length > 0) {
|
|
4322
|
-
return jsxRuntime_2(jsxRuntime_3, { children: [nest, jsxRuntime_1(BackendThrowable, {})] });
|
|
4430
|
+
return jsxRuntime_2(jsxRuntime_3, { children: [nest, jsxRuntime_1(BackendThrowable, { instance: CarbonReact.instance })] });
|
|
4323
4431
|
}
|
|
4324
4432
|
const Context = this.context.Provider;
|
|
4325
4433
|
return jsxRuntime_2(jsxRuntime_3, { children: [jsxRuntime_1(GlobalHistory, {}), this.props.websocket &&
|
|
4326
|
-
jsxRuntime_1(CarbonWebSocket, { ...(true === this.props.websocket ? {} : this.props.websocket) }), jsxRuntime_1(Context, { value: this.state, children: this.props.children }), jsxRuntime_1(ToastContainer, {})] });
|
|
4434
|
+
jsxRuntime_1(CarbonWebSocket, { ...(true === this.props.websocket ? {} : this.props.websocket), instance: CarbonReact.instance }), jsxRuntime_1(Context, { value: this.state, children: this.props.children }), jsxRuntime_1(ToastContainer, {})] });
|
|
4327
4435
|
}
|
|
4328
4436
|
}
|
|
4329
4437
|
|
|
@@ -4382,44 +4490,6 @@ function addValidSQL$1 (sql) {
|
|
|
4382
4490
|
addValidSQL.push({ [expect.getState().currentTestName.replaceAll(" ", "_").toLowerCase()]: sql });
|
|
4383
4491
|
}
|
|
4384
4492
|
|
|
4385
|
-
//ObjectType, UniqueIdType extends keyof ObjectType
|
|
4386
|
-
// @link https://www.typescriptlang.org/docs/handbook/2/mapped-types.html
|
|
4387
|
-
function deleteRestfulObjectArrays(dataOrCallback, stateKey, uniqueObjectId, callback) {
|
|
4388
|
-
const uniqueObjectIds = uniqueObjectId instanceof Array ? uniqueObjectId : [uniqueObjectId];
|
|
4389
|
-
return CarbonReact.instance.setState((previousBootstrapState, props) => {
|
|
4390
|
-
let newOrReplacementData = [];
|
|
4391
|
-
if (dataOrCallback instanceof Array) {
|
|
4392
|
-
newOrReplacementData = dataOrCallback;
|
|
4393
|
-
}
|
|
4394
|
-
else if (dataOrCallback instanceof Function) {
|
|
4395
|
-
let callbackReturn = dataOrCallback(previousBootstrapState, props);
|
|
4396
|
-
if (null === callbackReturn) {
|
|
4397
|
-
return;
|
|
4398
|
-
}
|
|
4399
|
-
newOrReplacementData = callbackReturn;
|
|
4400
|
-
}
|
|
4401
|
-
else {
|
|
4402
|
-
throw Error('The dataOrCallback parameter was not an array or function');
|
|
4403
|
-
}
|
|
4404
|
-
const previousStateProperty = previousBootstrapState[stateKey];
|
|
4405
|
-
return {
|
|
4406
|
-
[stateKey]: [
|
|
4407
|
-
...previousStateProperty?.filter(item => false === (newOrReplacementData?.find(value => {
|
|
4408
|
-
let isMatch = true;
|
|
4409
|
-
uniqueObjectIds.find(uniqueObjectId => {
|
|
4410
|
-
if (value[uniqueObjectId] !== item[uniqueObjectId]) {
|
|
4411
|
-
isMatch = false;
|
|
4412
|
-
return true;
|
|
4413
|
-
}
|
|
4414
|
-
return false;
|
|
4415
|
-
});
|
|
4416
|
-
return isMatch;
|
|
4417
|
-
}) || false)) || []
|
|
4418
|
-
]
|
|
4419
|
-
};
|
|
4420
|
-
}, callback);
|
|
4421
|
-
}
|
|
4422
|
-
|
|
4423
4493
|
// @link https://stackoverflow.com/questions/31721250/how-to-target-edge-browser-with-javascript
|
|
4424
4494
|
// Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) \
|
|
4425
4495
|
// Chrome/107.0.0.0 Safari/537.36 Edg/107.0.1418.26
|
|
@@ -4559,89 +4629,6 @@ function setupTests ({ sqlDirectory = './logs/rest/', logsDirectory = './logs/te
|
|
|
4559
4629
|
}, 65000);
|
|
4560
4630
|
}
|
|
4561
4631
|
|
|
4562
|
-
var eUpdateInsertMethod;
|
|
4563
|
-
(function (eUpdateInsertMethod) {
|
|
4564
|
-
eUpdateInsertMethod[eUpdateInsertMethod["REPLACE"] = 0] = "REPLACE";
|
|
4565
|
-
eUpdateInsertMethod[eUpdateInsertMethod["FIRST"] = 1] = "FIRST";
|
|
4566
|
-
eUpdateInsertMethod[eUpdateInsertMethod["LAST"] = 2] = "LAST";
|
|
4567
|
-
})(eUpdateInsertMethod || (eUpdateInsertMethod = {}));
|
|
4568
|
-
/**
|
|
4569
|
-
*
|
|
4570
|
-
* merged with existing objects.uniqueObjectId || {}.
|
|
4571
|
-
* @param dataOrCallback
|
|
4572
|
-
* @param uniqueObjectId - the uniqueObjectId of the object to update; typically the primary key of the table.
|
|
4573
|
-
* @param stateKey -
|
|
4574
|
-
* @param insertUpdateOrder
|
|
4575
|
-
* @param callback - if you want to do something with the updated state, you can pass a callback here. Run as the second
|
|
4576
|
-
* parameter of setState.
|
|
4577
|
-
*/
|
|
4578
|
-
function updateRestfulObjectArrays(dataOrCallback, stateKey, uniqueObjectId, insertUpdateOrder = eUpdateInsertMethod.LAST, callback) {
|
|
4579
|
-
const uniqueObjectIds = uniqueObjectId instanceof Array ? uniqueObjectId : [uniqueObjectId];
|
|
4580
|
-
const bootstrap = CarbonReact.instance;
|
|
4581
|
-
return bootstrap.setState((previousBootstrapState, props) => {
|
|
4582
|
-
let newOrReplacementData = [];
|
|
4583
|
-
if (dataOrCallback instanceof Array) {
|
|
4584
|
-
newOrReplacementData = dataOrCallback;
|
|
4585
|
-
}
|
|
4586
|
-
else if (dataOrCallback instanceof Function) {
|
|
4587
|
-
newOrReplacementData = dataOrCallback(previousBootstrapState, props);
|
|
4588
|
-
}
|
|
4589
|
-
else {
|
|
4590
|
-
throw Error('The dataOrCallback parameter was not an array or function');
|
|
4591
|
-
}
|
|
4592
|
-
const findUniqueObjectIds = (item, value) => {
|
|
4593
|
-
let isMatch = true;
|
|
4594
|
-
uniqueObjectIds.find(uniqueObjectId => {
|
|
4595
|
-
if (value[uniqueObjectId] !== item[uniqueObjectId]) {
|
|
4596
|
-
isMatch = false;
|
|
4597
|
-
return true;
|
|
4598
|
-
}
|
|
4599
|
-
return false;
|
|
4600
|
-
});
|
|
4601
|
-
return isMatch;
|
|
4602
|
-
};
|
|
4603
|
-
const previousStateProperty = previousBootstrapState[stateKey];
|
|
4604
|
-
let updatedData = newOrReplacementData?.map(value => {
|
|
4605
|
-
return {
|
|
4606
|
-
...previousStateProperty?.find(previousValue => findUniqueObjectIds(previousValue, value)) || {},
|
|
4607
|
-
...value
|
|
4608
|
-
};
|
|
4609
|
-
}) ?? [];
|
|
4610
|
-
switch (insertUpdateOrder) {
|
|
4611
|
-
default:
|
|
4612
|
-
throw Error('The insertUpdateOrder (eUpdateInsertMethod) was not implemented');
|
|
4613
|
-
case eUpdateInsertMethod.LAST:
|
|
4614
|
-
return {
|
|
4615
|
-
[stateKey]: null === newOrReplacementData ? null : [
|
|
4616
|
-
...updatedData,
|
|
4617
|
-
...(previousStateProperty?.filter(item => false === (updatedData?.find(value => findUniqueObjectIds(item, value)) || false)) ?? [])
|
|
4618
|
-
]
|
|
4619
|
-
};
|
|
4620
|
-
case eUpdateInsertMethod.FIRST:
|
|
4621
|
-
return {
|
|
4622
|
-
[stateKey]: null === newOrReplacementData ? null : [
|
|
4623
|
-
...(previousStateProperty?.filter(item => false === (updatedData?.find(value => findUniqueObjectIds(item, value)) || false)) ?? []),
|
|
4624
|
-
...updatedData,
|
|
4625
|
-
]
|
|
4626
|
-
};
|
|
4627
|
-
case eUpdateInsertMethod.REPLACE: {
|
|
4628
|
-
return {
|
|
4629
|
-
[stateKey]: [
|
|
4630
|
-
...(previousStateProperty?.map(oldObject => {
|
|
4631
|
-
const index = updatedData.findIndex(item => findUniqueObjectIds(item, oldObject));
|
|
4632
|
-
if (-1 === index) {
|
|
4633
|
-
return oldObject;
|
|
4634
|
-
}
|
|
4635
|
-
return updatedData.splice(index, 1).pop();
|
|
4636
|
-
}) ?? []),
|
|
4637
|
-
...updatedData
|
|
4638
|
-
]
|
|
4639
|
-
};
|
|
4640
|
-
}
|
|
4641
|
-
}
|
|
4642
|
-
}, callback);
|
|
4643
|
-
}
|
|
4644
|
-
|
|
4645
4632
|
// @link https://stackoverflow.com/questions/6735414/php-data-uri-to-file
|
|
4646
4633
|
// @link https://www.tutorialspoint.com/convert-image-to-data-uri-with-javascript
|
|
4647
4634
|
async function toDataURL(src, fileType, callback) {
|