@carbonorm/carbonreact 3.4.7 → 3.5.0

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/package.json CHANGED
@@ -1,21 +1,25 @@
1
1
  {
2
2
  "name": "@carbonorm/carbonreact",
3
- "version": "3.4.7",
3
+ "license": "MIT",
4
+ "version": "3.5.0",
4
5
  "browser": "dist/index.umd.js",
5
6
  "module": "dist/index.esm.js",
6
7
  "main": "dist/index.cjs.js",
7
8
  "types": "dist/index.d.ts",
8
9
  "type": "module",
9
10
  "dependencies": {
10
- "@carbonorm/carbonnode": "^1.2.16",
11
+ "@carbonorm/carbonnode": "^1.4.0",
11
12
  "@fortawesome/fontawesome-svg-core": "^6.4.0",
12
13
  "@fortawesome/free-solid-svg-icons": "^6.4.0",
13
14
  "@fortawesome/react-fontawesome": "^0.2.0",
15
+ "@testing-library/react": "^14.0.0",
14
16
  "ansi-colors": "^4.1.3",
15
17
  "axios": "^1.4.0",
16
18
  "bootstrap": "^5.3.1",
17
19
  "classnames": "^2.3.2",
18
20
  "heic2any": "^0.0.4",
21
+ "jest": "^29.5.0",
22
+ "jest-config": "^29.5.0",
19
23
  "qs": "^6.11.1",
20
24
  "react": "^18.2.0",
21
25
  "react-dom": "^18.2.0",
@@ -34,7 +38,6 @@
34
38
  "@rollup/plugin-commonjs": "^11.0.1",
35
39
  "@rollup/plugin-node-resolve": "^7.0.0",
36
40
  "@rollup/plugin-typescript": "^11.1.2",
37
- "@testing-library/react": "^14.0.0",
38
41
  "@types/jest": "^29.5.4",
39
42
  "@types/ms": "^0.7.31",
40
43
  "@types/node": "^18.17.14",
@@ -46,8 +49,6 @@
46
49
  "classnames": "^2.3.2",
47
50
  "css-loader": "^6.8.1",
48
51
  "deepmerge": "^4.3.1",
49
- "jest": "^29.5.0",
50
- "jest-config": "^29.5.0",
51
52
  "livereload": "^0.9.3",
52
53
  "postcss": "^8.4.27",
53
54
  "postcss-nested": "^6.0.1",
@@ -3,7 +3,6 @@ import changed from "hoc/changed";
3
3
  import {GlobalHistory} from "hoc/GlobalHistory";
4
4
  import hexToRgb from "hoc/hexToRgb";
5
5
  import {Component, ReactNode} from 'react';
6
- import {BrowserRouter} from 'react-router-dom';
7
6
  import {ToastContainer} from 'react-toastify';
8
7
  import 'react-toastify/dist/ReactToastify.min.css';
9
8
  import BackendThrowable from 'components/Errors/BackendThrowable';
@@ -12,7 +11,6 @@ import {initialRestfulObjectsState, iRestfulObjectArrayTypes} from "variables/C6
12
11
  import CarbonWebSocket from "./components/WebSocket/CarbonWebSocket";
13
12
 
14
13
 
15
-
16
14
  // our central container, single page application is best with the DigApi
17
15
  export interface iCarbonReactState {
18
16
  alertsWaiting: any[],
@@ -44,18 +42,17 @@ export function isJsonString(str) {
44
42
  return true;
45
43
  }
46
44
 
47
- const CarbonReact= class <P = {}, S = {}> extends Component<{
45
+ const CarbonReact = class<P = {}, S = {}> extends Component<{
48
46
  children?: ReactNode | ReactNode[],
47
+ shouldStatePersist?: boolean,
49
48
  } & P, S & iCarbonReactState> {
50
49
 
51
50
  static instance: Component<{
52
51
  children?: ReactNode | ReactNode[],
53
52
  } & any, any & iCarbonReactState>;
54
53
 
54
+ static persistentState?: iCarbonReactState = undefined
55
55
  static lastLocation = window.location.pathname;
56
- static websocketUrl = (window.location.protocol === 'https:' ? 'wss://' : 'ws://') + window.location.host + ':8888/ws';
57
- static websocketTimeoutSeconds : number = 250;
58
- static websocketHeartbeatSeconds : number = 250;
59
56
 
60
57
  // @link https://github.com/welldone-software/why-did-you-render
61
58
  // noinspection JSUnusedGlobalSymbols
@@ -65,7 +62,15 @@ const CarbonReact= class <P = {}, S = {}> extends Component<{
65
62
 
66
63
  super(props);
67
64
 
68
- this.state = initialCarbonReactState as unknown as S & iCarbonReactState;
65
+ if (CarbonReact.persistentState !== undefined && this.props.shouldStatePersist !== false) {
66
+
67
+ this.state = CarbonReact.persistentState as S & iCarbonReactState;
68
+
69
+ } else {
70
+
71
+ this.state = initialCarbonReactState as unknown as S & iCarbonReactState;
72
+
73
+ }
69
74
 
70
75
  // This should only ever be done here, when the full state is being trashed.
71
76
  clearCache({
@@ -81,7 +86,7 @@ const CarbonReact= class <P = {}, S = {}> extends Component<{
81
86
 
82
87
  }
83
88
 
84
- static getState<S>() : S {
89
+ static getState<S>(): S {
85
90
  return CarbonReact.instance.state;
86
91
  }
87
92
 
@@ -90,7 +95,18 @@ const CarbonReact= class <P = {}, S = {}> extends Component<{
90
95
  nextState: Readonly<iCarbonReactState>,
91
96
  _nextContext: any): boolean {
92
97
 
98
+ if (this.props.shouldStatePersist === false) {
99
+
100
+ CarbonReact.persistentState = undefined;
101
+
102
+ } else {
103
+
104
+ CarbonReact.persistentState = nextState;
105
+
106
+ }
107
+
93
108
  changed(this.constructor.name + ' (DigApi)', 'props', this.props, nextProps);
109
+
94
110
  changed(this.constructor.name + ' (DigApi)', 'state', this.state, nextState);
95
111
 
96
112
  return true
@@ -127,12 +143,12 @@ const CarbonReact= class <P = {}, S = {}> extends Component<{
127
143
 
128
144
  }
129
145
 
130
- return <BrowserRouter>
146
+ return <>
131
147
  <GlobalHistory/>
132
- <CarbonWebSocket />
148
+ <CarbonWebSocket/>
133
149
  {this.props.children}
134
150
  <ToastContainer/>
135
- </BrowserRouter>;
151
+ </>;
136
152
 
137
153
  }
138
154
 
@@ -20,16 +20,9 @@ export default function Popup({
20
20
  maxWidth,
21
21
  }: PropsWithChildren<iPopupProperties>) : ReactElement {
22
22
 
23
- if (false === open) {
24
-
25
- // @link https://legacy.reactjs.org/docs/conditional-rendering.html#preventing-component-from-rendering
26
- return <></>;
27
-
28
- }
29
-
30
23
  const dig = getStyles()
31
24
 
32
- return <div className={classNames(dig.modal, dig.fade, dig.show, dig.dBlock)}
25
+ return <div className={classNames(dig.modal, dig.fade, { [dig.show]: open}, dig.dBlock)}
33
26
  style={{backgroundColor: "rgba(0,0,0,0.8)"}}
34
27
  id="exampleModalCenter"
35
28
  tabIndex={-1} aria-labelledby="exampleModalCenterTitle"
@@ -1,25 +1,28 @@
1
1
  import CarbonReact, {isJsonString} from "CarbonReact";
2
2
  import {addAlert} from "../Alert/Alert";
3
3
  import {useEffectOnce} from "../../api/hoc/useEffectOnce";
4
- import {tC6Tables} from "@carbonorm/carbonnode";
4
+ import {tC6Tables, tWsLiveUpdate} from "@carbonorm/carbonnode";
5
5
 
6
6
 
7
7
  export interface iCarbonWebSocketProps {
8
8
  url?: string,
9
9
  timeoutSeconds?: number,
10
10
  heartbeatSeconds?: number,
11
- TABLES?: tC6Tables
11
+ TABLES?: tC6Tables,
12
+ WsLiveUpdates?: tWsLiveUpdate,
12
13
  }
13
14
 
14
15
  /**
15
16
  * @function connect
16
17
  * This function establishes a connection with the websocket and also ensures constant reconnection if connection closes
17
18
  **/
18
- export function initiateWebsocket({TABLES = undefined,
19
+ export function initiateWebsocket({
20
+ TABLES = undefined,
21
+ WsLiveUpdates = undefined,
19
22
  url = 'ws://localhost:8080/ws',
20
23
  timeoutSeconds = 250,
21
24
  heartbeatSeconds = 60
22
- }: iCarbonWebSocketProps = {}) {
25
+ }: iCarbonWebSocketProps = {}) {
23
26
 
24
27
  const {websocket} = CarbonReact.instance.state;
25
28
 
@@ -79,19 +82,95 @@ export function initiateWebsocket({TABLES = undefined,
79
82
 
80
83
  const parsedData = isJsonString(message?.data) ? JSON.parse(message?.data) : message?.data;
81
84
 
85
+ if (message.data === 'pong') {
86
+ return;
87
+ }
88
+
82
89
  CarbonReact.instance.setState((prevState: Readonly<any>) => ({
83
90
  websocketEvents: prevState.websocketEvents.concat(message),
84
91
  websocketData: prevState.websocketData.concat(parsedData), // JSON.parse no good - base64?
85
- }));
92
+ }), () => {
93
+
94
+ if (undefined === TABLES) {
95
+
96
+ console.log('WebSocket updates without the TABLES property passed will not automatically update the state.')
97
+
98
+ return;
99
+
100
+ }
101
+
102
+ if (undefined === WsLiveUpdates) {
103
+
104
+ console.log('WebSocket updates without the WsLiveUpdates property passed will not automatically update the state.')
105
+
106
+ return;
107
+
108
+ }
109
+
110
+ if (parsedData?.REST) {
111
+
112
+ const TABLE_NAME: string = parsedData?.REST?.TABLE_NAME;
113
+
114
+ const TABLE_PREFIX: string = parsedData?.REST?.TABLE_PREFIX;
115
+
116
+ const METHOD: string = parsedData?.REST?.METHOD;
117
+
118
+ const REQUEST: { [key:string]: any } = parsedData?.REST?.REQUEST;
119
+
120
+ const REQUEST_PRIMARY_KEY: {
121
+ [key: string]: string
122
+ } = parsedData?.REST?.REQUEST_PRIMARY_KEY ?? null;
123
+
124
+ if (null === REQUEST_PRIMARY_KEY) {
125
+
126
+ console.log('WebSocket updates without a primary key are not yet supported.')
127
+
128
+ return;
129
+
130
+ }
131
+
132
+ console.log('todo - going to impl REST', TABLE_NAME, METHOD, REQUEST_PRIMARY_KEY, parsedData?.REST)
133
+
134
+ const TABLE_NAME_SHORT = TABLE_NAME.substring(TABLE_PREFIX.length);
135
+
136
+ const currentCache: [] = CarbonReact.instance.state[TABLE_NAME_SHORT]
137
+
138
+ // just because we have a websocket update, doesn't mean we need the update
139
+ // check to see if the primary key is in the current cache
140
+ const c6Table = TABLES[TABLE_NAME_SHORT] ?? null;
141
+
142
+ if (null === c6Table) {
143
+
144
+ console.error('WebSocket update could not find (' + TABLE_NAME_SHORT + ') in the TABLES property passed.', TABLES)
145
+
146
+ return;
147
+
148
+ }
149
+
150
+ const primaryKeyKeys = Object.keys(REQUEST_PRIMARY_KEY)
151
+
152
+ const elementsToUpdate = currentCache.filter((row: any) => {
153
+ for (const element of primaryKeyKeys) {
154
+ if (REQUEST_PRIMARY_KEY[element] !== row[element]) {
155
+ return false
156
+ }
157
+ }
158
+ return true
159
+ })
86
160
 
87
- console.info('todo - going to impl TABLES', TABLES)
88
161
 
89
- /*if (undefined !== TABLES) {
162
+ const updatedElements = elementsToUpdate.map((row: any) => {
163
+ return {
164
+ ...row,
165
+ ...REQUEST
166
+ }
167
+ })
90
168
 
91
- TABLES.
169
+ WsLiveUpdates[TABLE_NAME_SHORT][METHOD]({}, updatedElements)
92
170
 
171
+ }
93
172
 
94
- }*/
173
+ });
95
174
 
96
175
  };
97
176