@pega/dx-component-builder-sdk 25.1.10 → 25.1.12

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.
Files changed (52) hide show
  1. package/package.json +1 -1
  2. package/src/tasks/create/templates/SDK-Angular/field/Boolean/boolean.component.ts.mustache +18 -149
  3. package/src/tasks/create/templates/SDK-Angular/field/Date/date.component.html.mustache +1 -1
  4. package/src/tasks/create/templates/SDK-Angular/field/Date/date.component.ts.mustache +29 -150
  5. package/src/tasks/create/templates/SDK-Angular/field/DateTime/date-time.component.ts.mustache +31 -149
  6. package/src/tasks/create/templates/SDK-Angular/field/Decimal/decimal.component.ts.mustache +37 -163
  7. package/src/tasks/create/templates/SDK-Angular/field/Decimal-Currency/decimal-currency.component.ts.mustache +34 -169
  8. package/src/tasks/create/templates/SDK-Angular/field/Decimal-Percentage/decimal-percentage.component.ts.mustache +36 -154
  9. package/src/tasks/create/templates/SDK-Angular/field/Integer/integer.component.ts.mustache +18 -157
  10. package/src/tasks/create/templates/SDK-Angular/field/Picklist/picklist.component.ts.mustache +24 -148
  11. package/src/tasks/create/templates/SDK-Angular/field/Picklist-Autocomplete/demo.stories.tsx.mustache +7 -2
  12. package/src/tasks/create/templates/SDK-Angular/field/Picklist-Autocomplete/picklist-autocomplete.component.ts.mustache +28 -162
  13. package/src/tasks/create/templates/SDK-Angular/field/Picklist-RadioButtons/picklist-radio-buttons.component.ts.mustache +35 -161
  14. package/src/tasks/create/templates/SDK-Angular/field/Text/text.component.ts.mustache +29 -144
  15. package/src/tasks/create/templates/SDK-Angular/field/Text-Email/text-email.component.ts.mustache +15 -155
  16. package/src/tasks/create/templates/SDK-Angular/field/Text-Input/text.component.ts.mustache +15 -155
  17. package/src/tasks/create/templates/SDK-Angular/field/Text-Paragraph/text-paragraph.component.ts.mustache +18 -152
  18. package/src/tasks/create/templates/SDK-Angular/field/Text-Phone/text-phone.component.ts.mustache +29 -142
  19. package/src/tasks/create/templates/SDK-Angular/field/Text-URL/text-url.component.ts.mustache +16 -154
  20. package/src/tasks/create/templates/SDK-Angular/field/TimeOfDay/time-of-day.component.ts.mustache +17 -151
  21. package/src/tasks/create/templates/SDK-Angular/template/DETAILS/details.component.ts.mustache +0 -1
  22. package/src/tasks/create/templates/SDK-Angular/template/DETAILS-region/details.component.ts.mustache +0 -1
  23. package/src/tasks/create/templates/SDK-Angular/template/FORM/form.component.ts.mustache +10 -3
  24. package/src/tasks/create/templates/SDK-Angular/template/FORM-region/form.component.ts.mustache +0 -1
  25. package/src/tasks/create/templates/SDK-Angular/template/PAGE/page.component.ts.mustache +0 -1
  26. package/src/tasks/create/templates/SDK-Angular/widget/CASE/case.component.ts.mustache +0 -1
  27. package/src/tasks/create/templates/SDK-Angular/widget/PAGE/page.component.ts.mustache +0 -1
  28. package/src/tasks/create/templates/SDK-Angular/widget/PAGE-CASE/page-case.component.html.mustache +2 -2
  29. package/src/tasks/create/templates/SDK-Angular/widget/PAGE-CASE/page-case.component.ts.mustache +4 -4
  30. package/src/tasks/create/templates/SDK-React/field/Boolean/index.tsx.mustache +96 -4
  31. package/src/tasks/create/templates/SDK-React/field/Picklist-RadioButtons/index.tsx.mustache +48 -1
  32. package/src/tasks/validator/index.js +3 -2
  33. package/src/util.js +3 -3
  34. package/tests/assets/sdk-r/components/create/override-sdk/infra/Assignment/Assignment.tsx +2 -2
  35. package/tests/assets/sdk-r/components/create/override-sdk/infra/NavBar/NavBar.tsx +13 -3
  36. package/tests/assets/sdk-r/components/create/override-sdk/infra/Stages/Stages.tsx +2 -3
  37. package/tests/assets/sdk-r/components/create/override-sdk/template/CaseView/CaseView.tsx +3 -2
  38. package/tests/assets/sdk-r/components/createAll/custom-sdk/field/Pega_DXIL_MyBoolean/index.tsx +93 -4
  39. package/tests/assets/sdk-r/components/createAll/custom-sdk/field/Pega_DXIL_MyRadiobuttons/index.tsx +45 -1
  40. package/tests/assets/sdk-r/components/createAll/override-sdk/infra/Assignment/Assignment.tsx +2 -2
  41. package/tests/assets/sdk-r/components/createAll/override-sdk/infra/NavBar/NavBar.tsx +13 -3
  42. package/tests/assets/sdk-r/components/createAll/override-sdk/infra/Stages/Stages.tsx +2 -3
  43. package/tests/assets/sdk-r/components/createAll/override-sdk/template/CaseView/CaseView.tsx +3 -2
  44. /package/tests/assets/sdk-a/components/createAll/custom-constellation/field/{Pega_DXIL_MyRadioButtons → Pega_DXIL_MyRadiobuttons}/PConnProps.d.ts +0 -0
  45. /package/tests/assets/sdk-a/components/createAll/custom-constellation/field/{Pega_DXIL_MyRadioButtons → Pega_DXIL_MyRadiobuttons}/create-nonce.ts +0 -0
  46. /package/tests/assets/sdk-a/components/createAll/custom-constellation/field/{Pega_DXIL_MyRadioButtons → Pega_DXIL_MyRadiobuttons}/demo.stories.tsx +0 -0
  47. /package/tests/assets/sdk-a/components/createAll/custom-constellation/field/{Pega_DXIL_MyRadioButtons → Pega_DXIL_MyRadiobuttons}/event-utils.ts +0 -0
  48. /package/tests/assets/sdk-a/components/createAll/custom-constellation/field/{Pega_DXIL_MyRadioButtons → Pega_DXIL_MyRadiobuttons}/index.tsx +0 -0
  49. /package/tests/assets/sdk-a/components/createAll/custom-constellation/field/{Pega_DXIL_MyRadioButtons → Pega_DXIL_MyRadiobuttons}/mock.ts +0 -0
  50. /package/tests/assets/sdk-a/components/createAll/custom-constellation/field/{Pega_DXIL_MyRadioButtons → Pega_DXIL_MyRadiobuttons}/styles.ts +0 -0
  51. /package/tests/assets/sdk-a/components/createAll/custom-constellation/field/{Pega_DXIL_MyRadioButtons → Pega_DXIL_MyRadiobuttons}/suggestions-handler.ts +0 -0
  52. /package/tests/assets/sdk-a/components/createAll/custom-constellation/field/{Pega_DXIL_MyRadioButtons → Pega_DXIL_MyRadiobuttons}/textformat-utils.tsx +0 -0
@@ -22,12 +22,26 @@ interface {{COMPONENT_CLASS_NAME}}Props extends Omit<PConnFieldProps, 'value'> {
22
22
  primaryField: string;
23
23
  readonlyContextList: any;
24
24
  referenceList: string;
25
+ variant?: string;
26
+ hideFieldLabels: boolean;
27
+ additionalProps: any;
28
+ imagePosition: string;
29
+ imageSize: string;
30
+ showImageDescription: string;
31
+ renderMode: string;
32
+ image: string;
25
33
  }
26
34
 
27
35
  const useStyles = makeStyles(() => ({
28
36
  checkbox: {
29
37
  display: 'flex',
30
38
  flexDirection: 'column'
39
+ },
40
+ selectableCard: {
41
+ display: 'grid',
42
+ gridTemplateColumns: 'repeat(auto-fit, minmax(min(100%, 40ch), 1fr))',
43
+ gridAutoRows: '1fr',
44
+ gap: '0.5rem'
31
45
  }
32
46
  }));
33
47
 
@@ -37,7 +51,7 @@ const useStyles = makeStyles(() => ({
37
51
  export default function {{COMPONENT_CLASS_NAME}}(props: {{COMPONENT_CLASS_NAME}}Props) {
38
52
  // Get emitted components from map (so we can get any override that may exist)
39
53
  const FieldValueList = getComponentFromMap('FieldValueList');
40
-
54
+ const SelectableCard = getComponentFromMap('SelectableCard');
41
55
  const {
42
56
  getPConnect,
43
57
  label,
@@ -60,8 +74,20 @@ export default function {{COMPONENT_CLASS_NAME}}(props: {{COMPONENT_CLASS_NAME}}
60
74
  selectionList,
61
75
  primaryField,
62
76
  referenceList,
63
- readonlyContextList: selectedvalues
77
+ readonlyContextList: selectedvalues,
78
+ variant,
79
+ hideFieldLabels,
80
+ additionalProps,
81
+ imagePosition,
82
+ imageSize,
83
+ showImageDescription,
84
+ renderMode,
85
+ image
64
86
  } = props;
87
+
88
+ const readOnlyMode = renderMode === 'ReadOnly' || displayMode === 'DISPLAY_ONLY' || readOnly;
89
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
90
+ const [theSelectedButton, setSelectedButton] = useState(value);
65
91
  const classes = useStyles();
66
92
  const helperTextToDisplay = validatemessage || helperText;
67
93
  const thePConn = getPConnect();
@@ -75,12 +101,18 @@ export default function {{COMPONENT_CLASS_NAME}}(props: {{COMPONENT_CLASS_NAME}}
75
101
  }, [value]);
76
102
 
77
103
  useEffect(() => {
78
- if (referenceList?.length > 0) {
104
+ if (referenceList?.length > 0 && !readOnlyMode) {
79
105
  thePConn.setReferenceList(selectionList);
80
106
  updateNewInstuctions(thePConn, selectionList);
81
107
  }
82
108
  }, [thePConn]);
83
109
 
110
+
111
+ useEffect(() => {
112
+ // This update theSelectedButton which will update the UI to show the selected button correctly
113
+ setSelectedButton(value);
114
+ }, [value]);
115
+
84
116
  if (displayMode === 'DISPLAY_ONLY') {
85
117
  return <FieldValueList name={hideLabel ? '' : caption} value={value ? trueLabel : falseLabel} />;
86
118
  }
@@ -96,7 +128,67 @@ export default function {{COMPONENT_CLASS_NAME}}(props: {{COMPONENT_CLASS_NAME}}
96
128
  const handleBlur = event => {
97
129
  thePConn.getValidationApi().validate(event.target.checked);
98
130
  };
99
-
131
+ const handleCheckboxChange = (event, item) => {
132
+ if (event.target.checked) {
133
+ insertInstruction(thePConn, selectionList, selectionKey, primaryField, item);
134
+ } else {
135
+ deleteInstruction(thePConn, selectionList, selectionKey, item);
136
+ }
137
+ thePConn.clearErrorMessages({ property: selectionList });
138
+ };
139
+ const actions = thePConn.getActionsApi();
140
+ const commonProps = {
141
+ ...additionalProps,
142
+ className: 'standard',
143
+ disabled,
144
+ readOnly,
145
+ onClick: (actions as any).onClick
146
+ };
147
+ if (variant === 'card') {
148
+ return (
149
+ <div>
150
+ {{! pick new delimiters for mustache }}
151
+ {{=<% %>=}}
152
+ <h4 style={{ marginTop: 0, marginBottom: 0 }}>{label}</h4>
153
+ <div className={classes.selectableCard}>
154
+ <SelectableCard
155
+ {...commonProps}
156
+ testId={testId}
157
+ displayMode={displayMode}
158
+ dataSource={datasource}
159
+ getPConnect={getPConnect}
160
+ readOnly={renderMode === 'ReadOnly' || displayMode === 'DISPLAY_ONLY' || readOnly}
161
+ onChange={e => {
162
+ e.stopPropagation();
163
+ const recordKey = selectionKey?.split('.').pop();
164
+ const selectedItem = datasource?.source?.find(item => item[recordKey as any] === e.target.id) ?? {};
165
+ handleCheckboxChange(e, {
166
+ id: selectedItem[recordKey as any],
167
+ primary: selectedItem[recordKey as any]
168
+ });
169
+ }}
170
+ onBlur={() => {
171
+ thePConn.getValidationApi().validate(selectedvalues, selectionList);
172
+ }}
173
+ hideFieldLabels={hideFieldLabels}
174
+ recordKey={selectionKey?.split('.').pop()}
175
+ cardLabel={primaryField.split('.').pop()}
176
+ image={{
177
+ imagePosition,
178
+ imageSize,
179
+ showImageDescription,
180
+ imageField: image?.split('.').pop(),
181
+ imageDescription: (thePConn?.getRawMetadata()?.config as any).imageDescription?.split('.').pop()
182
+ }}
183
+ readOnlyList={selectedvalues}
184
+ type='checkbox'
185
+ showNoValue={(renderMode === 'ReadOnly' || readOnly || displayMode === 'DISPLAY_ONLY') && selectedvalues.length === 0}
186
+ <%={{ }}=%> {{! revert delimiters for mustache }}
187
+ />
188
+ </div>
189
+ </div>
190
+ );
191
+ }
100
192
  const handleChangeMultiMode = (event, element) => {
101
193
  if (event.target.checked) {
102
194
  insertInstruction(thePConn, selectionList, selectionKey, primaryField, {
@@ -13,6 +13,13 @@ interface {{COMPONENT_CLASS_NAME}}Props extends PConnFieldProps {
13
13
  // If any, enter additional props that only exist on this componentName
14
14
  inline: boolean;
15
15
  fieldMetadata?: any;
16
+ variant?: string;
17
+ hideFieldLabels?: boolean;
18
+ additionalProps?: any;
19
+ imagePosition?: string;
20
+ imageSize?: string;
21
+ showImageDescription?: boolean;
22
+ datasource?: any;
16
23
  }
17
24
 
18
25
  // Duplicated runtime code from React SDK
@@ -21,6 +28,7 @@ interface {{COMPONENT_CLASS_NAME}}Props extends PConnFieldProps {
21
28
  export default function {{COMPONENT_CLASS_NAME}}(props: {{COMPONENT_CLASS_NAME}}Props) {
22
29
  // Get emitted components from map (so we can get any override that may exist)
23
30
  const FieldValueList = getComponentFromMap('FieldValueList');
31
+ const SelectableCard = getComponentFromMap('SelectableCard');
24
32
 
25
33
  const {
26
34
  getPConnect,
@@ -34,7 +42,14 @@ export default function {{COMPONENT_CLASS_NAME}}(props: {{COMPONENT_CLASS_NAME}}
34
42
  inline,
35
43
  displayMode,
36
44
  hideLabel,
37
- fieldMetadata
45
+ fieldMetadata,
46
+ variant,
47
+ hideFieldLabels,
48
+ additionalProps,
49
+ datasource,
50
+ imagePosition,
51
+ imageSize,
52
+ showImageDescription
38
53
  } = props;
39
54
  const [theSelectedButton, setSelectedButton] = useState(value);
40
55
 
@@ -93,6 +108,38 @@ export default function {{COMPONENT_CLASS_NAME}}(props: {{COMPONENT_CLASS_NAME}}
93
108
  thePConn.getValidationApi().validate(event.target.value, ''); // 2nd arg empty string until typedef marked correctly as optional
94
109
  };
95
110
 
111
+ if (variant === 'card') {
112
+ const stateProps = thePConn.getStateProps();
113
+ return (
114
+ <div>
115
+ {{! pick new delimiters for mustache }}
116
+ {{=<% %>=}}
117
+ <h4 style={{ marginTop: 0, marginBottom: 0 }}>{label}</h4>
118
+ <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(min(200px, 100%), 1fr))', gap: '1rem' }}>
119
+ <SelectableCard
120
+ hideFieldLabels={hideFieldLabels}
121
+ additionalProps={additionalProps}
122
+ getPConnect={getPConnect}
123
+ dataSource={datasource}
124
+ image={{
125
+ imagePosition,
126
+ imageSize,
127
+ showImageDescription,
128
+ imageField: stateProps.image?.split('.').pop(),
129
+ imageDescription: stateProps.imageDescription?.split('.').pop()
130
+ }}
131
+ onChange={handleChange}
132
+ recordKey={stateProps.value?.split('.').pop()}
133
+ cardLabel={stateProps.primaryField?.split('.').pop()}
134
+ radioBtnValue={value}
135
+ type='radio'
136
+ setIsRadioCardSelected={displayMode !== 'DISPLAY_ONLY' ? setSelectedButton : undefined}
137
+ <%={{ }}=%> {{! revert delimiters for mustache }}
138
+ />
139
+ </div>
140
+ </div>
141
+ );
142
+ }
96
143
  return (
97
144
  <Styled{{COMPONENT_CLASS_NAME}}Wrapper>
98
145
  <FormControl variant='standard' error={status === 'error'} required={required}>
@@ -39,6 +39,8 @@ const allowedOverrideSubtypes = [
39
39
  ...COMPONENT_SCHEMA.subtype.template.map(({ value }) => value),
40
40
  ...COMPONENT_SCHEMA.subtype.widget.map(({ value }) => value)
41
41
  ]),
42
+ 'Text-Location',
43
+ 'SEARCH',
42
44
  'ACTION',
43
45
  'DATA_CAPTURE',
44
46
  'SUMMARY',
@@ -368,8 +370,7 @@ export default async (option, category = CATEGORY_CUSTOM) => {
368
370
  let data;
369
371
  try {
370
372
  data = JSON.parse(configData);
371
- }
372
- catch (er) {
373
+ } catch (er) {
373
374
  throw new Error(`Invalid schema json in config.json: ${er}`);
374
375
  }
375
376
 
package/src/util.js CHANGED
@@ -784,7 +784,7 @@ export const showVersion = () => {
784
784
  if (nodeMajorVersion < 24) {
785
785
  console.log(
786
786
  chalk.redBright(
787
- `DX Component Builder SDK - requires node v24.14.1 or greater, current version: ${process.version}`
787
+ `DX Component Builder SDK - requires node v24.4.1 or greater, current version: ${process.version}`
788
788
  )
789
789
  );
790
790
  process.exit(1);
@@ -792,7 +792,7 @@ export const showVersion = () => {
792
792
  else if ( nodeMajorVersion == 24 && nodeMinorVersion < 4) {
793
793
  console.log(
794
794
  chalk.redBright(
795
- `DX Component Builder SDK - requires node v24.14.1 or greater, current version: ${process.version}`
795
+ `DX Component Builder SDK - requires node v24.4.1 or greater, current version: ${process.version}`
796
796
  )
797
797
  );
798
798
  process.exit(1);
@@ -800,7 +800,7 @@ export const showVersion = () => {
800
800
  else if (nodeMajorVersion == 24 && nodeMinorVersion == 4 && nodePatchVersion < 1 ) {
801
801
  console.log(
802
802
  chalk.redBright(
803
- `DX Component Builder SDK - requires node v24.14.1 or greater, current version: ${process.version}`
803
+ `DX Component Builder SDK - requires node v24.4.1 or greater, current version: ${process.version}`
804
804
  )
805
805
  );
806
806
  process.exit(1);
@@ -33,8 +33,8 @@ export default function Assignment(props: PropsWithChildren<AssignmentProps>) {
33
33
 
34
34
  const actionsAPI = thePConn.getActionsApi();
35
35
  const localizedVal = PCore.getLocaleUtils().getLocaleValue;
36
+ const localizationService = thePConn.getLocalizationService();
36
37
  const localeCategory = 'Assignment';
37
- const localeReference = getPConnect()?.getCaseLocaleReference();
38
38
 
39
39
  // store off bound functions to above pointers
40
40
  const finishAssignment = actionsAPI.finishAssignment.bind(actionsAPI);
@@ -76,7 +76,7 @@ export default function Assignment(props: PropsWithChildren<AssignmentProps>) {
76
76
  function getStepsInfo(steps, formedSteps: any = []) {
77
77
  steps.forEach(step => {
78
78
  if (step.name) {
79
- step.name = PCore.getLocaleUtils().getLocaleValue(step.name, undefined, localeReference);
79
+ step.name = localizationService.getLocalizedText(step.name);
80
80
  }
81
81
  if (step.steps) {
82
82
  formedSteps = getStepsInfo(step.steps, formedSteps);
@@ -133,9 +133,19 @@ export default function NavBar(props: NavBarProps) {
133
133
  const portalLogoImage = Utils.getIconPath(Utils.getSDKStaticConentUrl()).concat('pzpega-logo-mark.svg');
134
134
  const portalOperator = PCore.getEnvironmentInfo().getOperatorName();
135
135
  const portalApp = PCore.getEnvironmentInfo().getApplicationLabel();
136
-
136
+ // @ts-ignore
137
+ const localeReference = PCore.getLocaleUtils().getPortalLocaleReference() || pConn.getValue('.pyLocaleReference');
137
138
  useEffect(() => {
138
- setNavPages(JSON.parse(JSON.stringify(pages)));
139
+ const updatedPages = pages.map((page: any) => {
140
+ const destinationObject: any = {};
141
+ pConn.resolveConfigProps(
142
+ { defaultHeading: page.pyDefaultHeading || page.pyLabel, localeReference: page.pyLocalizationReference },
143
+ destinationObject
144
+ );
145
+ const name = localeUtils.getLocaleValue(destinationObject.defaultHeading, '', destinationObject.localeReference || localeReference);
146
+ return { ...page, name };
147
+ });
148
+ setNavPages(updatedPages);
139
149
  }, [pages]);
140
150
 
141
151
  function navPanelButtonClick(oPageData: any) {
@@ -249,7 +259,7 @@ export default function NavBar(props: NavBarProps) {
249
259
  {navPages.map(page => (
250
260
  <ListItemButton onClick={() => navPanelButtonClick(page)} key={page.pyLabel}>
251
261
  <ListItemIcon>{iconMap[page.pxPageViewIcon]}</ListItemIcon>
252
- <ListItemText primary={localeUtils.getLocaleValue(page.pyLabel, '', localeUtils.getCaseLocaleReference(page.pyClassName))} />
262
+ <ListItemText primary={page.name} />
253
263
  </ListItemButton>
254
264
  ))}
255
265
  </List>
@@ -57,14 +57,13 @@ export default function Stages(props: StagesProps) {
57
57
 
58
58
  const { getPConnect, stages } = props;
59
59
  const pConn = getPConnect();
60
- const key = getPConnect()?.getCaseLocaleReference();
61
-
60
+ const localizationService = pConn.getLocalizationService();
62
61
  const filteredStages = getFilteredStages(stages);
63
62
  const currentStageID = pConn.getValue(PCore.getConstants().CASE_INFO.STAGEID, ''); // 2nd arg empty string until typedef allows optional
64
63
  const stagesObj = filteredStages.map((stage, index, arr) => {
65
64
  const theID = stage.ID || stage.id;
66
65
  return {
67
- name: PCore.getLocaleUtils().getLocaleValue(stage.name, undefined, key),
66
+ name: localizationService.getLocalizedText(stage.name),
68
67
  id: theID,
69
68
  complete: stage.visited_status === 'completed',
70
69
  current: theID === currentStageID,
@@ -70,8 +70,9 @@ export default function CaseView(props: PropsWithChildren<CaseViewProps>) {
70
70
  const editAction = availableActions.find(action => action.ID === 'pyUpdateCaseDetails');
71
71
 
72
72
  const localizedVal = PCore.getLocaleUtils().getLocaleValue;
73
+ const localizationService = thePConn.getLocalizationService();
73
74
  const localeCategory = 'CaseView';
74
- const localeKey = thePConn?.getCaseLocaleReference();
75
+
75
76
  /**
76
77
  *
77
78
  * @param inName the metadata <em>name</em> that will cause a region to be returned
@@ -214,7 +215,7 @@ export default function CaseView(props: PropsWithChildren<CaseViewProps>) {
214
215
  className={classes.caseViewHeader}
215
216
  title={
216
217
  <Typography variant='h6' component='div' id='case-name'>
217
- {PCore.getLocaleUtils().getLocaleValue(header, '', localeKey)}
218
+ {localizationService.getLocalizedText(header)}
218
219
  </Typography>
219
220
  }
220
221
  subheader={
@@ -22,12 +22,26 @@ interface PegaDxilMyBooleanProps extends Omit<PConnFieldProps, 'value'> {
22
22
  primaryField: string;
23
23
  readonlyContextList: any;
24
24
  referenceList: string;
25
+ variant?: string;
26
+ hideFieldLabels: boolean;
27
+ additionalProps: any;
28
+ imagePosition: string;
29
+ imageSize: string;
30
+ showImageDescription: string;
31
+ renderMode: string;
32
+ image: string;
25
33
  }
26
34
 
27
35
  const useStyles = makeStyles(() => ({
28
36
  checkbox: {
29
37
  display: 'flex',
30
38
  flexDirection: 'column'
39
+ },
40
+ selectableCard: {
41
+ display: 'grid',
42
+ gridTemplateColumns: 'repeat(auto-fit, minmax(min(100%, 40ch), 1fr))',
43
+ gridAutoRows: '1fr',
44
+ gap: '0.5rem'
31
45
  }
32
46
  }));
33
47
 
@@ -37,7 +51,7 @@ const useStyles = makeStyles(() => ({
37
51
  export default function PegaDxilMyBoolean(props: PegaDxilMyBooleanProps) {
38
52
  // Get emitted components from map (so we can get any override that may exist)
39
53
  const FieldValueList = getComponentFromMap('FieldValueList');
40
-
54
+ const SelectableCard = getComponentFromMap('SelectableCard');
41
55
  const {
42
56
  getPConnect,
43
57
  label,
@@ -60,8 +74,20 @@ export default function PegaDxilMyBoolean(props: PegaDxilMyBooleanProps) {
60
74
  selectionList,
61
75
  primaryField,
62
76
  referenceList,
63
- readonlyContextList: selectedvalues
77
+ readonlyContextList: selectedvalues,
78
+ variant,
79
+ hideFieldLabels,
80
+ additionalProps,
81
+ imagePosition,
82
+ imageSize,
83
+ showImageDescription,
84
+ renderMode,
85
+ image
64
86
  } = props;
87
+
88
+ const readOnlyMode = renderMode === 'ReadOnly' || displayMode === 'DISPLAY_ONLY' || readOnly;
89
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
90
+ const [theSelectedButton, setSelectedButton] = useState(value);
65
91
  const classes = useStyles();
66
92
  const helperTextToDisplay = validatemessage || helperText;
67
93
  const thePConn = getPConnect();
@@ -75,12 +101,18 @@ export default function PegaDxilMyBoolean(props: PegaDxilMyBooleanProps) {
75
101
  }, [value]);
76
102
 
77
103
  useEffect(() => {
78
- if (referenceList?.length > 0) {
104
+ if (referenceList?.length > 0 && !readOnlyMode) {
79
105
  thePConn.setReferenceList(selectionList);
80
106
  updateNewInstuctions(thePConn, selectionList);
81
107
  }
82
108
  }, [thePConn]);
83
109
 
110
+
111
+ useEffect(() => {
112
+ // This update theSelectedButton which will update the UI to show the selected button correctly
113
+ setSelectedButton(value);
114
+ }, [value]);
115
+
84
116
  if (displayMode === 'DISPLAY_ONLY') {
85
117
  return <FieldValueList name={hideLabel ? '' : caption} value={value ? trueLabel : falseLabel} />;
86
118
  }
@@ -96,7 +128,64 @@ export default function PegaDxilMyBoolean(props: PegaDxilMyBooleanProps) {
96
128
  const handleBlur = event => {
97
129
  thePConn.getValidationApi().validate(event.target.checked);
98
130
  };
99
-
131
+ const handleCheckboxChange = (event, item) => {
132
+ if (event.target.checked) {
133
+ insertInstruction(thePConn, selectionList, selectionKey, primaryField, item);
134
+ } else {
135
+ deleteInstruction(thePConn, selectionList, selectionKey, item);
136
+ }
137
+ thePConn.clearErrorMessages({ property: selectionList });
138
+ };
139
+ const actions = thePConn.getActionsApi();
140
+ const commonProps = {
141
+ ...additionalProps,
142
+ className: 'standard',
143
+ disabled,
144
+ readOnly,
145
+ onClick: (actions as any).onClick
146
+ };
147
+ if (variant === 'card') {
148
+ return (
149
+ <div>
150
+ <h4 style={{ marginTop: 0, marginBottom: 0 }}>{label}</h4>
151
+ <div className={classes.selectableCard}>
152
+ <SelectableCard
153
+ {...commonProps}
154
+ testId={testId}
155
+ displayMode={displayMode}
156
+ dataSource={datasource}
157
+ getPConnect={getPConnect}
158
+ readOnly={renderMode === 'ReadOnly' || displayMode === 'DISPLAY_ONLY' || readOnly}
159
+ onChange={e => {
160
+ e.stopPropagation();
161
+ const recordKey = selectionKey?.split('.').pop();
162
+ const selectedItem = datasource?.source?.find(item => item[recordKey as any] === e.target.id) ?? {};
163
+ handleCheckboxChange(e, {
164
+ id: selectedItem[recordKey as any],
165
+ primary: selectedItem[recordKey as any]
166
+ });
167
+ }}
168
+ onBlur={() => {
169
+ thePConn.getValidationApi().validate(selectedvalues, selectionList);
170
+ }}
171
+ hideFieldLabels={hideFieldLabels}
172
+ recordKey={selectionKey?.split('.').pop()}
173
+ cardLabel={primaryField.split('.').pop()}
174
+ image={{
175
+ imagePosition,
176
+ imageSize,
177
+ showImageDescription,
178
+ imageField: image?.split('.').pop(),
179
+ imageDescription: (thePConn?.getRawMetadata()?.config as any).imageDescription?.split('.').pop()
180
+ }}
181
+ readOnlyList={selectedvalues}
182
+ type='checkbox'
183
+ showNoValue={(renderMode === 'ReadOnly' || readOnly || displayMode === 'DISPLAY_ONLY') && selectedvalues.length === 0}
184
+ />
185
+ </div>
186
+ </div>
187
+ );
188
+ }
100
189
  const handleChangeMultiMode = (event, element) => {
101
190
  if (event.target.checked) {
102
191
  insertInstruction(thePConn, selectionList, selectionKey, primaryField, {
@@ -13,6 +13,13 @@ interface PegaDxilMyRadiobuttonsProps extends PConnFieldProps {
13
13
  // If any, enter additional props that only exist on this componentName
14
14
  inline: boolean;
15
15
  fieldMetadata?: any;
16
+ variant?: string;
17
+ hideFieldLabels?: boolean;
18
+ additionalProps?: any;
19
+ imagePosition?: string;
20
+ imageSize?: string;
21
+ showImageDescription?: boolean;
22
+ datasource?: any;
16
23
  }
17
24
 
18
25
  // Duplicated runtime code from React SDK
@@ -21,6 +28,7 @@ interface PegaDxilMyRadiobuttonsProps extends PConnFieldProps {
21
28
  export default function PegaDxilMyRadiobuttons(props: PegaDxilMyRadiobuttonsProps) {
22
29
  // Get emitted components from map (so we can get any override that may exist)
23
30
  const FieldValueList = getComponentFromMap('FieldValueList');
31
+ const SelectableCard = getComponentFromMap('SelectableCard');
24
32
 
25
33
  const {
26
34
  getPConnect,
@@ -34,7 +42,14 @@ export default function PegaDxilMyRadiobuttons(props: PegaDxilMyRadiobuttonsProp
34
42
  inline,
35
43
  displayMode,
36
44
  hideLabel,
37
- fieldMetadata
45
+ fieldMetadata,
46
+ variant,
47
+ hideFieldLabels,
48
+ additionalProps,
49
+ datasource,
50
+ imagePosition,
51
+ imageSize,
52
+ showImageDescription
38
53
  } = props;
39
54
  const [theSelectedButton, setSelectedButton] = useState(value);
40
55
 
@@ -93,6 +108,35 @@ export default function PegaDxilMyRadiobuttons(props: PegaDxilMyRadiobuttonsProp
93
108
  thePConn.getValidationApi().validate(event.target.value, ''); // 2nd arg empty string until typedef marked correctly as optional
94
109
  };
95
110
 
111
+ if (variant === 'card') {
112
+ const stateProps = thePConn.getStateProps();
113
+ return (
114
+ <div>
115
+ <h4 style={{ marginTop: 0, marginBottom: 0 }}>{label}</h4>
116
+ <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(min(200px, 100%), 1fr))', gap: '1rem' }}>
117
+ <SelectableCard
118
+ hideFieldLabels={hideFieldLabels}
119
+ additionalProps={additionalProps}
120
+ getPConnect={getPConnect}
121
+ dataSource={datasource}
122
+ image={{
123
+ imagePosition,
124
+ imageSize,
125
+ showImageDescription,
126
+ imageField: stateProps.image?.split('.').pop(),
127
+ imageDescription: stateProps.imageDescription?.split('.').pop()
128
+ }}
129
+ onChange={handleChange}
130
+ recordKey={stateProps.value?.split('.').pop()}
131
+ cardLabel={stateProps.primaryField?.split('.').pop()}
132
+ radioBtnValue={value}
133
+ type='radio'
134
+ setIsRadioCardSelected={displayMode !== 'DISPLAY_ONLY' ? setSelectedButton : undefined}
135
+ />
136
+ </div>
137
+ </div>
138
+ );
139
+ }
96
140
  return (
97
141
  <StyledPegaDxilMyRadiobuttonsWrapper>
98
142
  <FormControl variant='standard' error={status === 'error'} required={required}>
@@ -33,8 +33,8 @@ export default function Assignment(props: PropsWithChildren<AssignmentProps>) {
33
33
 
34
34
  const actionsAPI = thePConn.getActionsApi();
35
35
  const localizedVal = PCore.getLocaleUtils().getLocaleValue;
36
+ const localizationService = thePConn.getLocalizationService();
36
37
  const localeCategory = 'Assignment';
37
- const localeReference = getPConnect()?.getCaseLocaleReference();
38
38
 
39
39
  // store off bound functions to above pointers
40
40
  const finishAssignment = actionsAPI.finishAssignment.bind(actionsAPI);
@@ -76,7 +76,7 @@ export default function Assignment(props: PropsWithChildren<AssignmentProps>) {
76
76
  function getStepsInfo(steps, formedSteps: any = []) {
77
77
  steps.forEach(step => {
78
78
  if (step.name) {
79
- step.name = PCore.getLocaleUtils().getLocaleValue(step.name, undefined, localeReference);
79
+ step.name = localizationService.getLocalizedText(step.name);
80
80
  }
81
81
  if (step.steps) {
82
82
  formedSteps = getStepsInfo(step.steps, formedSteps);
@@ -133,9 +133,19 @@ export default function NavBar(props: NavBarProps) {
133
133
  const portalLogoImage = Utils.getIconPath(Utils.getSDKStaticConentUrl()).concat('pzpega-logo-mark.svg');
134
134
  const portalOperator = PCore.getEnvironmentInfo().getOperatorName();
135
135
  const portalApp = PCore.getEnvironmentInfo().getApplicationLabel();
136
-
136
+ // @ts-ignore
137
+ const localeReference = PCore.getLocaleUtils().getPortalLocaleReference() || pConn.getValue('.pyLocaleReference');
137
138
  useEffect(() => {
138
- setNavPages(JSON.parse(JSON.stringify(pages)));
139
+ const updatedPages = pages.map((page: any) => {
140
+ const destinationObject: any = {};
141
+ pConn.resolveConfigProps(
142
+ { defaultHeading: page.pyDefaultHeading || page.pyLabel, localeReference: page.pyLocalizationReference },
143
+ destinationObject
144
+ );
145
+ const name = localeUtils.getLocaleValue(destinationObject.defaultHeading, '', destinationObject.localeReference || localeReference);
146
+ return { ...page, name };
147
+ });
148
+ setNavPages(updatedPages);
139
149
  }, [pages]);
140
150
 
141
151
  function navPanelButtonClick(oPageData: any) {
@@ -249,7 +259,7 @@ export default function NavBar(props: NavBarProps) {
249
259
  {navPages.map(page => (
250
260
  <ListItemButton onClick={() => navPanelButtonClick(page)} key={page.pyLabel}>
251
261
  <ListItemIcon>{iconMap[page.pxPageViewIcon]}</ListItemIcon>
252
- <ListItemText primary={localeUtils.getLocaleValue(page.pyLabel, '', localeUtils.getCaseLocaleReference(page.pyClassName))} />
262
+ <ListItemText primary={page.name} />
253
263
  </ListItemButton>
254
264
  ))}
255
265
  </List>
@@ -57,14 +57,13 @@ export default function Stages(props: StagesProps) {
57
57
 
58
58
  const { getPConnect, stages } = props;
59
59
  const pConn = getPConnect();
60
- const key = getPConnect()?.getCaseLocaleReference();
61
-
60
+ const localizationService = pConn.getLocalizationService();
62
61
  const filteredStages = getFilteredStages(stages);
63
62
  const currentStageID = pConn.getValue(PCore.getConstants().CASE_INFO.STAGEID, ''); // 2nd arg empty string until typedef allows optional
64
63
  const stagesObj = filteredStages.map((stage, index, arr) => {
65
64
  const theID = stage.ID || stage.id;
66
65
  return {
67
- name: PCore.getLocaleUtils().getLocaleValue(stage.name, undefined, key),
66
+ name: localizationService.getLocalizedText(stage.name),
68
67
  id: theID,
69
68
  complete: stage.visited_status === 'completed',
70
69
  current: theID === currentStageID,
@@ -70,8 +70,9 @@ export default function CaseView(props: PropsWithChildren<CaseViewProps>) {
70
70
  const editAction = availableActions.find(action => action.ID === 'pyUpdateCaseDetails');
71
71
 
72
72
  const localizedVal = PCore.getLocaleUtils().getLocaleValue;
73
+ const localizationService = thePConn.getLocalizationService();
73
74
  const localeCategory = 'CaseView';
74
- const localeKey = thePConn?.getCaseLocaleReference();
75
+
75
76
  /**
76
77
  *
77
78
  * @param inName the metadata <em>name</em> that will cause a region to be returned
@@ -214,7 +215,7 @@ export default function CaseView(props: PropsWithChildren<CaseViewProps>) {
214
215
  className={classes.caseViewHeader}
215
216
  title={
216
217
  <Typography variant='h6' component='div' id='case-name'>
217
- {PCore.getLocaleUtils().getLocaleValue(header, '', localeKey)}
218
+ {localizationService.getLocalizedText(header)}
218
219
  </Typography>
219
220
  }
220
221
  subheader={