Skip to content

Commit 0a7685d

Browse files
authored
Relocating the PConnect HOC outside of the createPConnectComponent function (#363)
1 parent 512faec commit 0a7685d

File tree

2 files changed

+149
-153
lines changed

2 files changed

+149
-153
lines changed

packages/react-sdk-components/src/bridge/react_pconnect.jsx

Lines changed: 148 additions & 152 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ import StoreContext from './Context/StoreContext';
1616

1717
import { SdkComponentMap } from './helpers/sdk_component_map';
1818

19-
const isClassIDCompare = (key, prev) => {
20-
return !(key === 'classID' && !prev[key]);
19+
const isClassIDCompare = (key, prev, next) => {
20+
return !(key === 'classID' && (!prev[key] || !next[key]));
2121
};
2222

2323
const routingInfoCompare = (next, prev) => {
@@ -88,19 +88,17 @@ const connectRedux = (component, c11nEnv) => {
8888
areStatePropsEqual: (next, prev) => {
8989
const allStateProps = c11nEnv.getStateProps();
9090
for (const key of Object.keys(allStateProps)) {
91-
if (
92-
(isClassIDCompare(key, prev) && !shallowEqual(next[key], prev[key])) ||
93-
(next.routingInfo && !PCore.isDeepEqual(next.routingInfo, prev.routingInfo))
94-
) {
95-
return false;
96-
}
97-
}
98-
99-
// status === ".pyStatusWork" condition was not allowing the CaseSummary component to re-render,
100-
// hence got rid of that
101-
for (const key of Object.keys(prev)) {
102-
if (!PCore.isDeepEqual(next[key], prev[key])) {
103-
return false;
91+
if (Object.prototype.hasOwnProperty.call(allStateProps, key)) {
92+
if (key === 'inheritedProps' && next.inheritedProps && !PCore.isDeepEqual(next.inheritedProps, prev.inheritedProps)) {
93+
return false;
94+
}
95+
if (
96+
key !== 'inheritedProps' &&
97+
((isClassIDCompare(key, prev, next) && !shallowEqual(next[key], prev[key])) ||
98+
(next.routingInfo && !PCore.isDeepEqual(next.routingInfo, prev.routingInfo)))
99+
) {
100+
return false;
101+
}
104102
}
105103
}
106104
/* TODO For some rawConfig we are not getting routingInfo under allStateProps */
@@ -161,172 +159,160 @@ const getComponent = c11nEnv => {
161159
};
162160

163161
/**
164-
*
165-
* @param {*} declarative
166-
* @returns {React.Components<Props, State>}
167-
162+
* JEA - add Type info via JSdoc syntax...
163+
* @extends {React.Components<Props, State>}
164+
* createPConnectComponent - Class to create/initialize a PConnect (c11nEnv) object
165+
* to pre-process meta data of each componnet.
166+
* - Wraps each child in a component with PConnect
167+
* - Process all actions and make them avaiable in props
168+
* - Filters all properties in metadata and keeps them
169+
* __internal for re-render process through connect
168170
*/
169-
const createPConnectComponent = () => {
170-
/**
171-
* JEA - add Type info via JSdoc syntax...
172-
* @extends {React.Components<Props, State>}
173-
* createPConnectComponent - Class to create/initialize a PConnect (c11nEnv) object
174-
* to pre-process meta data of each componnet.
175-
* - Wraps each child in a component with PConnect
176-
* - Process all actions and make them avaiable in props
177-
* - Filters all properties in metadata and keeps them
178-
* __internal for re-render process through connect
179-
*/
180-
class PConnect extends Component {
181-
constructor(props) {
182-
super(props);
183-
const { getPConnect } = this.props;
184-
this.state = {
185-
hasError: false
186-
};
171+
class PConnect extends Component {
172+
constructor(props) {
173+
super(props);
174+
const { getPConnect } = this.props;
175+
this.state = {
176+
hasError: false
177+
};
178+
179+
this.eventHandler = this.eventHandler.bind(this);
180+
this.changeHandler = this.changeHandler.bind(this);
181+
182+
this.c11nEnv = getPConnect();
183+
// eslint-disable-next-line react/no-unused-class-component-methods
184+
this.Control = getComponent(this.c11nEnv);
185+
this.actionsAPI = this.c11nEnv.getActionsApi();
186+
187+
this.processActions(this.c11nEnv);
188+
}
187189

188-
this.eventHandler = this.eventHandler.bind(this);
189-
this.changeHandler = this.changeHandler.bind(this);
190+
static getDerivedStateFromError(error) {
191+
// Update state so the next render will show the fallback UI.
192+
return {
193+
hasError: true,
194+
error
195+
};
196+
}
190197

191-
this.c11nEnv = getPConnect();
192-
// eslint-disable-next-line react/no-unused-class-component-methods
193-
this.Control = getComponent(this.c11nEnv);
194-
this.actionsAPI = this.c11nEnv.getActionsApi();
198+
componentDidMount() {
199+
this.c11nEnv.addFormField();
200+
setVisibilityForList(this.c11nEnv, true);
201+
}
195202

196-
this.processActions(this.c11nEnv);
197-
}
203+
componentDidCatch(error, info) {
204+
// eslint-disable-next-line no-console
205+
console.error(`Error while Rendering the component ${this.componentName} : `, error, info.componentStack);
206+
}
198207

199-
static getDerivedStateFromError(error) {
200-
// Update state so the next render will show the fallback UI.
201-
return {
202-
hasError: true,
203-
error
204-
};
208+
componentWillUnmount() {
209+
if (this.c11nEnv.removeFormField) {
210+
this.c11nEnv.removeFormField();
211+
setVisibilityForList(this.c11nEnv, false);
205212
}
213+
}
206214

207-
componentDidMount() {
208-
this.c11nEnv.addFormField();
209-
setVisibilityForList(this.c11nEnv, true);
215+
/*
216+
* processActions to see all actions in meta and adds event in props.
217+
* Attaches common handler (eventHandler) for all actions.
218+
*/
219+
processActions() {
220+
if (this.c11nEnv.isEditable()) {
221+
this.c11nEnv.setAction('onChange', this.changeHandler);
222+
this.c11nEnv.setAction('onBlur', this.eventHandler);
210223
}
224+
}
211225

212-
componentDidCatch(error, info) {
213-
// eslint-disable-next-line no-console
214-
console.error(`Error while Rendering the component ${this.componentName} : `, error, info.componentStack);
215-
}
226+
// Using separate handle for change as in case of dropdown, native click is mapped to react change
227+
changeHandler(event) {
228+
this.actionsAPI.changeHandler(this.c11nEnv, event);
229+
// getActionProcessor().changeHandler(this.c11nEnv, event);
230+
}
216231

217-
componentWillUnmount() {
218-
if (this.c11nEnv.removeFormField) {
219-
this.c11nEnv.removeFormField();
220-
setVisibilityForList(this.c11nEnv, false);
221-
}
222-
}
232+
eventHandler(event) {
233+
this.actionsAPI.eventHandler(this.c11nEnv, event);
234+
// getActionProcessor().eventHandler(this.c11nEnv, event);
235+
}
223236

224-
/*
225-
* processActions to see all actions in meta and adds event in props.
226-
* Attaches common handler (eventHandler) for all actions.
227-
*/
228-
processActions() {
229-
if (this.c11nEnv.isEditable()) {
230-
this.c11nEnv.setAction('onChange', this.changeHandler);
231-
this.c11nEnv.setAction('onBlur', this.eventHandler);
232-
}
237+
createChildren() {
238+
const { getPConnect } = this.props;
239+
if (getPConnect().hasChildren() && getPConnect().getChildren()) {
240+
return (
241+
getPConnect()
242+
.getChildren()
243+
// eslint-disable-next-line react/no-array-index-key
244+
.map((childProps, index) => <PConnect key={`${this.getKey(childProps)}_${index}`} {...childProps} />)
245+
);
233246
}
247+
return null;
248+
}
234249

235-
// Using separate handle for change as in case of dropdown, native click is mapped to react change
236-
changeHandler(event) {
237-
this.actionsAPI.changeHandler(this.c11nEnv, event);
238-
// getActionProcessor().changeHandler(this.c11nEnv, event);
239-
}
250+
getKey(props = this.props) {
251+
const { getPConnect } = props;
252+
const viewName = getPConnect().getConfigProps().name || getPConnect().getCurrentView();
253+
let key = !viewName ? createUID() : `${viewName}!${getPConnect().getCurrentClassID() || createUID()}`;
240254

241-
eventHandler(event) {
242-
this.actionsAPI.eventHandler(this.c11nEnv, event);
243-
// getActionProcessor().eventHandler(this.c11nEnv, event);
255+
// In the case of pyDetails the key must be unique for each instance
256+
if (viewName && viewName.toUpperCase() === 'PYDETAILS') {
257+
key += `!${getPConnect().getCaseInfo().getID()}`;
244258
}
245259

246-
createChildren() {
247-
const { getPConnect } = this.props;
248-
if (getPConnect().hasChildren() && getPConnect().getChildren()) {
249-
return (
250-
getPConnect()
251-
.getChildren()
252-
// eslint-disable-next-line react/no-array-index-key
253-
.map((childProps, index) => <PConnect key={`${this.getKey(childProps)}_${index}`} {...childProps} />)
254-
);
255-
}
256-
return null;
257-
}
258-
259-
getKey(props = this.props) {
260-
const { getPConnect } = props;
261-
const viewName = getPConnect().getConfigProps().name || getPConnect().getCurrentView();
262-
let key = !viewName ? createUID() : `${viewName}!${getPConnect().getCurrentClassID() || createUID()}`;
260+
return key.toUpperCase();
261+
}
263262

264-
// In the case of pyDetails the key must be unigue for each instance
265-
if (viewName && viewName.toUpperCase() === 'PYDETAILS') {
266-
key += `!${getPConnect().getCaseInfo().getID()}`;
267-
}
263+
render() {
264+
const { hasError } = this.state;
265+
const { getPConnect, additionalProps, ...otherProps } = this.props;
268266

269-
return key.toUpperCase();
267+
if (hasError) {
268+
// You can render any custom fallback UI
269+
// console.log(`react_pconnect error: used to return: <ErrorBoundary getPConnect={() => this.c11nEnv} isInternalError />`);
270+
return <ErrorBoundary getPConnect={() => this.c11nEnv} isInternalError />;
270271
}
271272

272-
render() {
273-
const { hasError } = this.state;
274-
const { getPConnect, additionalProps, ...otherProps } = this.props;
275-
276-
if (hasError) {
277-
// You can render any custom fallback UI
278-
// console.log(`react_pconnect error: used to return: <ErrorBoundary getPConnect={() => this.c11nEnv} isInternalError />`);
279-
return <ErrorBoundary getPConnect={() => this.c11nEnv} isInternalError />;
280-
}
281-
282-
const props = this.c11nEnv.getConfigProps();
283-
const actions = this.c11nEnv.getActions();
284-
const finalProps = {
285-
...props,
286-
getPConnect,
287-
...actions,
288-
additionalProps,
289-
...otherProps
290-
};
291-
292-
// If the new component is a reference node then mark with a unique key
293-
if (['reference', 'View'].includes(getPConnect().getComponentName()) && !finalProps.key) {
294-
finalProps.key = this.getKey();
295-
}
296-
297-
// console.log(`react_pconnect: used to return: <this.Control {...finalProps} />`);
298-
299-
return <this.Control {...finalProps}>{this.createChildren()}</this.Control>;
273+
const props = this.c11nEnv.getConfigProps();
274+
const actions = this.c11nEnv.getActions();
275+
const finalProps = {
276+
...props,
277+
getPConnect,
278+
...actions,
279+
additionalProps,
280+
...otherProps
281+
};
282+
283+
// If the new component is a reference node then mark with a unique key
284+
if (['reference', 'View'].includes(getPConnect().getComponentName()) && !finalProps.key) {
285+
finalProps.key = this.getKey();
300286
}
301-
}
302287

303-
// eslint-disable-next-line react/static-property-placement
304-
PConnect.propTypes = {
305-
// __internal: PropTypes.object.isRequired,
306-
// meta: PropTypes.object.isRequired,
307-
// configObject: PropTypes.object.isRequired,
308-
getPConnect: PropTypes.func.isRequired,
309-
additionalProps: PropTypes.shape({
310-
noLabel: PropTypes.bool,
311-
readOnly: PropTypes.bool
312-
}),
313-
validatemessage: PropTypes.string
314-
};
288+
// console.log(`react_pconnect: used to return: <this.Control {...finalProps} />`);
315289

316-
// eslint-disable-next-line react/static-property-placement
317-
PConnect.defaultProps = {
318-
additionalProps: {},
319-
validatemessage: ''
320-
};
290+
return <this.Control {...finalProps}>{this.createChildren()}</this.Control>;
291+
}
292+
}
293+
// eslint-disable-next-line react/static-property-placement
294+
PConnect.propTypes = {
295+
// __internal: PropTypes.object.isRequired,
296+
// meta: PropTypes.object.isRequired,
297+
// configObject: PropTypes.object.isRequired,
298+
getPConnect: PropTypes.func.isRequired,
299+
additionalProps: PropTypes.shape({
300+
noLabel: PropTypes.bool,
301+
readOnly: PropTypes.bool
302+
}),
303+
validatemessage: PropTypes.string
304+
};
321305

322-
return PConnect;
306+
// eslint-disable-next-line react/static-property-placement
307+
PConnect.defaultProps = {
308+
additionalProps: {},
309+
validatemessage: ''
323310
};
324311

325312
// Move these into SdkConstellationReady so PCore is available
326313
document.addEventListener('SdkConstellationReady', () => {
327314
PCore.registerComponentCreator((c11nEnv, additionalProps = {}) => {
328-
const PConnectComp = createPConnectComponent();
329-
return createElement(PConnectComp, {
315+
return createElement(PConnect, {
330316
...c11nEnv,
331317
...c11nEnv.getPConnect().getConfigProps(),
332318
...c11nEnv.getPConnect().getActions(),
@@ -365,6 +351,16 @@ document.addEventListener('SdkConstellationReady', () => {
365351
});
366352
});
367353

354+
/**
355+
*
356+
* @param {*} declarative
357+
* @returns {React.Components<Props, State>}
358+
359+
*/
360+
const createPConnectComponent = () => {
361+
return PConnect;
362+
};
363+
368364
export default createPConnectComponent;
369365

370366
/* These APIs need to be exposed for authoring bridge

packages/react-sdk-components/tests/e2e/Digv2/ComplexFields/DataReference.spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ test.describe('E2E test', () => {
217217
await selectProducts.click();
218218
await page.locator('li:has-text("Mobile")').click();
219219
await page.locator('li:has-text("Telivision")').click();
220-
await expect(selectProducts).toBeVisible();
220+
await selectProducts.click();
221221

222222
await page.locator('button:has-text("Next")').click();
223223

0 commit comments

Comments
 (0)