@pega/react-sdk-overrides 0.23.20 → 0.23.22

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.
@@ -15,7 +15,7 @@ import StoreContext from '@pega/react-sdk-components/lib/bridge/Context/StoreCon
15
15
  import DayjsUtils from '@date-io/dayjs';
16
16
  import { MuiPickersUtilsProvider } from '@material-ui/pickers';
17
17
 
18
- import { addContainerItem, getToDoAssignments } from './helpers';
18
+ import { addContainerItem, getToDoAssignments, showBanner } from './helpers';
19
19
 
20
20
  declare const PCore;
21
21
 
@@ -171,7 +171,7 @@ export default function FlowContainer(props) {
171
171
 
172
172
  if (bLoadChildren && oWorkData) {
173
173
  // debugger;
174
- setContainerName(oWorkData.caseInfo.assignments[0].name);
174
+ setContainerName(oWorkData.caseInfo.assignments?.[0].name);
175
175
  }
176
176
 
177
177
  // debugger;
@@ -253,7 +253,7 @@ export default function FlowContainer(props) {
253
253
 
254
254
  const caseActions = ourPConn.getValue(CASE_CONSTS.CASE_INFO_ACTIONS);
255
255
  const activeActionID = ourPConn.getValue(CASE_CONSTS.ACTIVE_ACTION_ID);
256
- const activeAction = caseActions.find(action => action.ID === activeActionID);
256
+ const activeAction = caseActions?.find(action => action.ID === activeActionID);
257
257
  if (activeAction) {
258
258
  activeActionLabel = activeAction.name;
259
259
  }
@@ -312,7 +312,6 @@ export default function FlowContainer(props) {
312
312
  }
313
313
  }
314
314
 
315
-
316
315
  // if have caseMessage show message and end
317
316
  const theCaseMessages = thePConn.getValue('caseMessages');
318
317
 
@@ -337,75 +336,75 @@ export default function FlowContainer(props) {
337
336
  }
338
337
 
339
338
  // this check in routingInfo, mimic React to check and get the internals of the
340
- // flowContainer and force updates to pConnect/redux
341
- if (routingInfo && loadingInfo !== undefined) {
342
- // debugging/investigation help
343
- // console.log(`${thePConn.getComponentName()}: >>routingInfo: ${JSON.stringify(routingInfo)}`);
344
-
345
- const currentOrder = routingInfo.accessedOrder;
346
- const currentItems = routingInfo.items;
347
- const type = routingInfo.type;
348
- if (currentOrder && currentItems) {
349
- // JA - making more similar to React version
350
- const key = currentOrder[currentOrder.length - 1];
351
-
352
- // save off itemKey to be used for finishAssignment, etc.
353
- // debugger;
354
- setItemKey(key);
355
-
356
- if (
357
- currentOrder.length > 0 &&
358
- currentItems[key] &&
359
- currentItems[key].view &&
360
- type === 'single' &&
361
- !Utils.isEmptyObject(currentItems[key].view)
362
- ) {
363
- const currentItem = currentItems[key];
364
- const rootView = currentItem.view;
365
- const { context } = rootView.config;
366
- const config = { meta: rootView };
367
-
368
- config['options'] = {
369
- context: currentItem.context,
370
- pageReference: context || localPConn.getPageReference(),
371
- hasForm: true,
372
- isFlowContainer: true,
373
- containerName: localPConn.getContainerName(),
374
- containerItemName: key,
375
- parentPageReference: localPConn.getPageReference()
376
- };
377
-
378
- const configObject = PCore.createPConnect(config);
379
-
380
- // Since we're setting an array, need to add in an appropriate key
381
- // to remove React warning.
382
- configObject['key'] = config['options'].parentPageReference;
383
-
384
- // keep track of these changes
385
- const theNewChildren: Array<Object> = [];
386
- theNewChildren.push(configObject);
387
- setArNewChildren(theNewChildren);
388
-
389
- // JEA - adapted from Constellation DX Components FlowContainer since we want to render children that are React components
390
- const root = createElement(createPConnectComponent(), configObject);
391
- setArNewChildrenAsReact([root]);
392
-
393
- const oWorkItem = configObject.getPConnect(); // was theNewChildren[0].getPConnect()
394
- const oWorkData = oWorkItem.getDataObject();
395
-
396
- // check if have oWorkData, there are times due to timing of state change, when this
397
- // may not be available
398
- if (oWorkData) {
399
- setContainerName(getActiveViewLabel() || oWorkData.caseInfo.assignments[0].name);
400
- }
339
+ // flowContainer and force updates to pConnect/redux
340
+ if (routingInfo && loadingInfo !== undefined) {
341
+ // debugging/investigation help
342
+ // console.log(`${thePConn.getComponentName()}: >>routingInfo: ${JSON.stringify(routingInfo)}`);
343
+
344
+ const currentOrder = routingInfo.accessedOrder;
345
+ const currentItems = routingInfo.items;
346
+ const type = routingInfo.type;
347
+ if (currentOrder && currentItems) {
348
+ // JA - making more similar to React version
349
+ const key = currentOrder[currentOrder.length - 1];
350
+
351
+ // save off itemKey to be used for finishAssignment, etc.
352
+ // debugger;
353
+ setItemKey(key);
354
+
355
+ if (
356
+ currentOrder.length > 0 &&
357
+ currentItems[key] &&
358
+ currentItems[key].view &&
359
+ type === 'single' &&
360
+ !Utils.isEmptyObject(currentItems[key].view)
361
+ ) {
362
+ const currentItem = currentItems[key];
363
+ const rootView = currentItem.view;
364
+ const { context } = rootView.config;
365
+ const config = { meta: rootView };
366
+
367
+ config['options'] = {
368
+ context: currentItem.context,
369
+ pageReference: context || localPConn.getPageReference(),
370
+ hasForm: true,
371
+ isFlowContainer: true,
372
+ containerName: localPConn.getContainerName(),
373
+ containerItemName: key,
374
+ parentPageReference: localPConn.getPageReference()
375
+ };
376
+
377
+ const configObject = PCore.createPConnect(config);
378
+
379
+ // Since we're setting an array, need to add in an appropriate key
380
+ // to remove React warning.
381
+ configObject['key'] = config['options'].parentPageReference;
382
+
383
+ // keep track of these changes
384
+ const theNewChildren: Array<Object> = [];
385
+ theNewChildren.push(configObject);
386
+ setArNewChildren(theNewChildren);
387
+
388
+ // JEA - adapted from Constellation DX Components FlowContainer since we want to render children that are React components
389
+ const root = createElement(createPConnectComponent(), configObject);
390
+ setArNewChildrenAsReact([root]);
391
+
392
+ const oWorkItem = configObject.getPConnect(); // was theNewChildren[0].getPConnect()
393
+ const oWorkData = oWorkItem.getDataObject();
394
+
395
+ // check if have oWorkData, there are times due to timing of state change, when this
396
+ // may not be available
397
+ if (oWorkData) {
398
+ setContainerName(getActiveViewLabel() || oWorkData.caseInfo.assignments?.[0].name);
401
399
  }
402
400
  }
403
401
  }
402
+ }
404
403
  }, [props]);
405
404
 
406
405
  const caseId = thePConn.getCaseSummary().content.pyID;
407
406
  const urgency = getPConnect().getCaseSummary().assignments
408
- ? getPConnect().getCaseSummary().assignments[0].urgency
407
+ ? getPConnect().getCaseSummary().assignments?.[0].urgency
409
408
  : '';
410
409
  const operatorInitials = Utils.getInitials(PCore.getEnvironmentInfo().getOperatorName());
411
410
  let instructionText = thePConn.getCaseSummary()?.assignments?.[0]?.instructions;
@@ -413,6 +412,8 @@ export default function FlowContainer(props) {
413
412
  instructionText = '';
414
413
  }
415
414
 
415
+ const bShowBanner = showBanner(getPConnect);
416
+
416
417
  return (
417
418
  <div style={{ textAlign: 'left' }} id={buildName} className='psdk-flow-container-top'>
418
419
  {!bShowConfirm &&
@@ -465,7 +466,7 @@ export default function FlowContainer(props) {
465
466
  <Alert severity='success'>{caseMessages}</Alert>
466
467
  </div>
467
468
  )}
468
- {bShowConfirm && <Card className={classes.root}>{arNewChildrenAsReact}</Card>}
469
+ {bShowConfirm && bShowBanner && <div>{arNewChildrenAsReact}</div>}
469
470
  </div>
470
471
  );
471
472
  }
@@ -1,24 +1,33 @@
1
- import React, { useEffect, useState } from "react";
2
- import PropTypes from "prop-types";
1
+ import React, { useEffect, useState } from 'react';
2
+ import PropTypes from 'prop-types';
3
3
  import { makeStyles } from '@material-ui/core/styles';
4
-
4
+ import { Utils } from '@pega/react-sdk-components/lib/components/helpers/utils';
5
+ import Avatar from '@material-ui/core/Avatar';
5
6
  import { NavContext } from '@pega/react-sdk-components/lib/components/helpers/reactContextHelpers';
6
7
  import './AppShell.css';
7
8
 
8
- // AppShell can emit NavBar
9
+ // AppShell can emit NavBar or WssNavBar
9
10
  import NavBar from '@pega/react-sdk-components/lib/components/infra/NavBar';
11
+ import WssNavBar from '@pega/react-sdk-components/lib/components/template/WssNavBar';
10
12
 
11
- const useStyles = makeStyles((theme) => ({
13
+ const useStyles = makeStyles(theme => ({
12
14
  root: {
13
- display: 'flex',
15
+ display: 'flex'
14
16
  },
15
17
  content: {
16
18
  flexGrow: 1,
17
19
  height: '100vh',
18
20
  overflow: 'auto',
19
21
  marginLeft: theme.spacing(2),
20
- marginRight: theme.spacing(2),
22
+ marginRight: theme.spacing(2)
21
23
  },
24
+ wsscontent: {
25
+ flexGrow: 1,
26
+ height: '100vh',
27
+ overflow: 'auto',
28
+ marginLeft: theme.spacing(1),
29
+ marginRight: theme.spacing(1)
30
+ }
22
31
  }));
23
32
 
24
33
  declare const PCore;
@@ -31,53 +40,176 @@ export default function AppShell(props) {
31
40
  showAppName,
32
41
  children,
33
42
  getPConnect,
43
+ portalTemplate,
44
+ portalName,
45
+ portalLogo,
46
+ navDisplayOptions
34
47
  } = props;
35
48
  const [open, setOpen] = useState(true);
36
-
49
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars, no-unused-vars
50
+ const [activeTab, setActiveTab] = useState(!pages ? null : pages[0]?.pyRuleName);
37
51
  const pConn = getPConnect();
38
52
  const envInfo = PCore.getEnvironmentInfo();
39
-
40
- const appNameToDisplay = showAppName ? envInfo.getApplicationLabel() : "";
41
-
53
+ const imageKey = envInfo.getOperatorImageInsKey();
54
+ const userName = envInfo.getOperatorName();
55
+ const currentUserInitials = Utils.getInitials(userName);
56
+ const appNameToDisplay = showAppName ? envInfo.getApplicationLabel() : '';
57
+ const portalClass = pConn.getValue('.classID');
58
+ const envPortalName = envInfo.getPortalName();
59
+ const localeUtils = PCore.getLocaleUtils();
42
60
  const classes = useStyles();
43
-
61
+ const actionsAPI = pConn.getActionsApi();
62
+ const localeReference = pConn.getValue('.pyLocaleReference');
63
+ const [imageBlobUrl, setImageBlobUrl] = useState(null);
44
64
  // useState for appName and mapChildren - note these are ONLY updated once (on component mount!)
45
65
  // eslint-disable-next-line @typescript-eslint/no-unused-vars, no-unused-vars
46
- const [appName, setAppName] = useState("");
66
+ const [appName, setAppName] = useState('');
47
67
  // eslint-disable-next-line @typescript-eslint/no-unused-vars, no-unused-vars
48
68
  const [mapChildren, setMapChildren] = useState([]);
49
69
 
50
70
  // Initial setting of appName and mapChildren
51
- useEffect( () => {
71
+ useEffect(() => {
52
72
  setAppName(PCore.getEnvironmentInfo().getApplicationName());
53
73
 
54
74
  const tempMap = pConn.getChildren().map((child, index) => {
55
75
  const theChildComp = child.getPConnect().getComponentName();
56
76
  const theKey = `.${index}`;
57
- return <div id={theChildComp} key={theKey} style={{border: "solid 1px silver", margin: "1px"}}>{theChildComp} will be here</div>
77
+ return (
78
+ <div id={theChildComp} key={theKey} style={{ border: 'solid 1px silver', margin: '1px' }}>
79
+ {theChildComp} will be here
80
+ </div>
81
+ );
58
82
  });
59
83
 
60
- setMapChildren(tempMap)
84
+ setMapChildren(tempMap);
85
+ }, []);
61
86
 
87
+ const [iconURL, setIconURL] = useState('');
88
+ const [fullIconURL, setFullIconURL] = useState('');
89
+ useEffect(() => {
90
+ // using the default icon then fetch it from the static folder (not auth involved)
91
+ if (
92
+ !portalLogo ||
93
+ portalLogo.toLowerCase().includes('pzpega-logo-mark') ||
94
+ portalLogo.toLowerCase().includes('py-logo') ||
95
+ portalLogo.toLowerCase().includes('py-full-logo')
96
+ ) {
97
+ const portalLogoImage = Utils.getIconPath(PCore.getAssetLoader().getStaticServerUrl()).concat(
98
+ 'pzpega-logo-mark.svg'
99
+ );
100
+ setIconURL(portalLogoImage);
101
+ setFullIconURL(`${PCore.getAssetLoader().getStaticServerUrl()}static/py-full-logo.svg`);
102
+ }
103
+ // not using default icon to fetch it using the way which uses authentication
104
+ else {
105
+ PCore.getAssetLoader()
106
+ .getSvcImage(portalLogo)
107
+ .then(blob => window.URL.createObjectURL(blob))
108
+ .then(data => {
109
+ setIconURL(data);
110
+ setFullIconURL(data);
111
+ })
112
+ .catch(() => {
113
+ // eslint-disable-next-line no-console
114
+ console.error(
115
+ `Unable to load the image for the portal logo/icon with the insName:${portalLogo}`
116
+ );
117
+ });
118
+ }
119
+ }, [portalLogo]);
120
+
121
+ useEffect(() => {
122
+ if (imageKey && portalTemplate === 'wss') {
123
+ PCore.getAssetLoader()
124
+ .getSvcImage(imageKey)
125
+ .then(blob => window.URL.createObjectURL(blob))
126
+ .then(imagePath => setImageBlobUrl(imagePath));
127
+ }
62
128
  }, []);
63
129
 
130
+ const getOperator = () => {
131
+ return {
132
+ avatar: portalTemplate !== 'wss' ? <Avatar /> : { name: userName, imageSrc: imageBlobUrl },
133
+ name: userName,
134
+ currentUserInitials
135
+ };
136
+ };
137
+
138
+ function showPage(viewName, className) {
139
+ actionsAPI.showPage(viewName, className);
140
+ }
141
+
142
+ function openURL(URL) {
143
+ window.open(URL, '_blank');
144
+ }
145
+
146
+ const links = !pages
147
+ ? []
148
+ : pages.map(page => {
149
+ const name = localeUtils.getLocaleValue(page.pyLabel, '', localeReference);
150
+ return {
151
+ text: name,
152
+ name,
153
+ icon: page.pxPageViewIcon.replace('pi pi-', ''),
154
+ active: page.pyRuleName === activeTab,
155
+ onClick: () =>
156
+ !page.pyURLContent || page.pyURLContent === ''
157
+ ? showPage(page.pyRuleName, page.pyClassName)
158
+ : openURL(page.pyURLContent)
159
+ };
160
+ });
161
+
64
162
  if (pConn.hasChildren()) {
65
163
  // const theChildren = pConn.getChildren();
66
164
  // const mapChildCompNames = theChildren.map((child) => { return child.getPConnect().getComponentName()});
67
-
68
165
  // debugging/investigation help
69
166
  // console.log(`AppShell has children: ${theChildren.length}`);
70
167
  // console.log(`--> ${mapChildCompNames.map((name) => {return name;})}`);
71
168
  }
72
169
 
73
- return (
170
+ if (portalTemplate === 'wss') {
171
+ return (
172
+ <div id='AppShell'>
173
+ <WssNavBar
174
+ portalName={portalName}
175
+ imageSrc={iconURL}
176
+ fullImageSrc={fullIconURL}
177
+ appName={localeUtils.getLocaleValue(
178
+ appNameToDisplay,
179
+ '',
180
+ `${portalClass}!PORTAL!${envPortalName}`.toUpperCase()
181
+ )}
182
+ appInfo={{
183
+ imageSrc: iconURL,
184
+ appName: localeUtils.getLocaleValue(
185
+ appNameToDisplay,
186
+ '',
187
+ `${portalClass}!PORTAL!${envPortalName}`.toUpperCase()
188
+ ),
189
+ onClick: links[0] && links[0].onClick ? links[0].onClick : undefined
190
+ }}
191
+ navLinks={links.filter((link, index) => {
192
+ return index !== 0;
193
+ })}
194
+ operator={getOperator()}
195
+ navDisplayOptions={navDisplayOptions}
196
+ />
197
+ <div className={classes.wsscontent}>{children}</div>
198
+ </div>
74
199
 
75
- <NavContext.Provider value={{open, setOpen}}>
76
- <div id="AppShell" className={classes.root}>
77
- <NavBar pConn={getPConnect()} appName={appNameToDisplay} pages={pages} caseTypes={caseTypes}></NavBar>
78
- <div className={classes.content}>
79
- {children}
80
- </div>
200
+ );
201
+ }
202
+
203
+ return (
204
+ <NavContext.Provider value={{ open, setOpen }}>
205
+ <div id='AppShell' className={classes.root}>
206
+ <NavBar
207
+ pConn={getPConnect()}
208
+ appName={appNameToDisplay}
209
+ pages={pages}
210
+ caseTypes={caseTypes}
211
+ ></NavBar>
212
+ <div className={classes.content}>{children}</div>
81
213
  </div>
82
214
  </NavContext.Provider>
83
215
  );
@@ -86,12 +218,12 @@ export default function AppShell(props) {
86
218
  AppShell.defaultProps = {
87
219
  pages: [],
88
220
  caseTypes: [],
89
- children: [],
221
+ children: []
90
222
  };
91
223
  AppShell.propTypes = {
92
- showAppName: PropTypes.bool/* .isRequired */,
224
+ showAppName: PropTypes.bool /* .isRequired */,
93
225
  pages: PropTypes.arrayOf(PropTypes.object),
94
226
  caseTypes: PropTypes.arrayOf(PropTypes.object),
95
227
  children: PropTypes.arrayOf(PropTypes.node),
96
- getPConnect: PropTypes.func.isRequired,
228
+ getPConnect: PropTypes.func.isRequired
97
229
  };
@@ -0,0 +1,61 @@
1
+ import { useMemo, Children } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import Banner from '@pega/react-sdk-components/lib/components/designSystemExtension/Banner';
4
+ import React from 'react';
5
+
6
+ /*
7
+ * BannerPage template.
8
+ */
9
+ export default function BannerPage(props) {
10
+ const {
11
+ children,
12
+ layout,
13
+ heading,
14
+ message,
15
+ imageTheme,
16
+ backgroundImage,
17
+ backgroundColor,
18
+ tintImage
19
+ } = props;
20
+
21
+ const childArray = useMemo(() => {
22
+ return Children.toArray(children);
23
+ }, [children]);
24
+
25
+ return (
26
+ <Banner
27
+ variant={layout}
28
+ a={childArray[0]}
29
+ b={childArray[1]}
30
+ banner={{
31
+ variant: imageTheme,
32
+ backgroundColor,
33
+ title: heading,
34
+ message,
35
+ backgroundImage,
36
+ tintImage
37
+ }}
38
+ />
39
+ );
40
+ }
41
+
42
+ BannerPage.propTypes = {
43
+ children: PropTypes.arrayOf(PropTypes.node).isRequired,
44
+ layout: PropTypes.string,
45
+ heading: PropTypes.string,
46
+ message: PropTypes.string,
47
+ imageTheme: PropTypes.string,
48
+ backgroundImage: PropTypes.string,
49
+ backgroundColor: PropTypes.string,
50
+ tintImage: PropTypes.bool
51
+ };
52
+
53
+ BannerPage.defaultProps = {
54
+ layout: 'two-column',
55
+ heading: '',
56
+ message: '',
57
+ imageTheme: 'light',
58
+ backgroundImage: '',
59
+ backgroundColor: '',
60
+ tintImage: false
61
+ };
@@ -0,0 +1 @@
1
+ export { default } from './BannerPage';
@@ -7,11 +7,25 @@ import React from 'react';
7
7
  import { getToDoAssignments } from '@pega/react-sdk-components/lib/components/infra/Containers/FlowContainer/helpers';
8
8
  import ToDo from '@pega/react-sdk-components/lib/components/widget/ToDo';
9
9
  import Details from '@pega/react-sdk-components/lib/components/template/Details/Details';
10
- import { Button } from '@material-ui/core';
10
+ import { Button, Card, makeStyles } from '@material-ui/core';
11
11
 
12
12
  declare const PCore;
13
13
 
14
+ const useStyles = makeStyles(theme => ({
15
+ root: {
16
+ paddingRight: theme.spacing(1),
17
+ paddingLeft: theme.spacing(1),
18
+ paddingTop: theme.spacing(1),
19
+ paddingBottom: theme.spacing(1),
20
+ marginRight: theme.spacing(1),
21
+ marginLeft: theme.spacing(1),
22
+ marginTop: theme.spacing(1),
23
+ marginBottom: theme.spacing(1)
24
+ }
25
+ }));
26
+
14
27
  export default function Confirmation(props) {
28
+ const classes = useStyles();
15
29
  const CONSTS = PCore.getConstants();
16
30
  const [showConfirmView, setShowConfirmView] = useState(true);
17
31
  const { showTasks, getPConnect, datasource } = props;
@@ -38,8 +52,8 @@ export default function Confirmation(props) {
38
52
  const detailProps = { ...props, showLabel: false };
39
53
  const showDetails = detailProps?.children?.[0]?.props?.getPConnect()?.getChildren()?.length > 0;
40
54
  return showConfirmView ? (
41
- <Fragment>
42
- <h2>{props.showLabel ? props.label : ''}</h2>
55
+ <Card className={classes.root}>
56
+ <h2 id='confirm-label'>{props.showLabel ? props.label : ''}</h2>
43
57
  {showDetails ? <Details {...detailProps} /> : undefined}
44
58
  {showTasks ? (
45
59
  toDoList && toDoList.length > 0 ? (
@@ -49,6 +63,7 @@ export default function Confirmation(props) {
49
63
  getPConnect={getPConnect}
50
64
  type={CONSTS.TODO}
51
65
  headerText='Open Tasks'
66
+ isConfirm
52
67
  />
53
68
  ) : undefined
54
69
  ) : undefined}
@@ -57,15 +72,18 @@ export default function Confirmation(props) {
57
72
  Done
58
73
  </Button>
59
74
  </div>
60
- </Fragment>
75
+ </Card>
61
76
  ) : toDoList && toDoList.length > 0 ? (
62
- <ToDo
63
- {...props}
64
- datasource={{ source: toDoList }}
65
- getPConnect={getPConnect}
66
- type={CONSTS.TODO}
67
- headerText='Tasks'
68
- />
77
+ <Card className={classes.root}>
78
+ <ToDo
79
+ {...props}
80
+ datasource={{ source: toDoList }}
81
+ getPConnect={getPConnect}
82
+ type={CONSTS.TODO}
83
+ headerText='Tasks'
84
+ isConfirm
85
+ />
86
+ </Card>
69
87
  ) : null;
70
88
  }
71
89
 
@@ -0,0 +1,5 @@
1
+ .link-style {
2
+ color: white !important;
3
+ text-transform: capitalize !important;
4
+ font-size: 1rem !important;
5
+ }