@pega/sdk 0.0.13 → 0.0.15

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 (139) hide show
  1. package/README.md +46 -6
  2. package/dist/index.js +50 -24
  3. package/package.json +42 -3
  4. package/templates/angular-sdk-reference/extra-webpack.config.cjs +23 -0
  5. package/templates/angular-sdk-reference/index.html +12 -0
  6. package/templates/angular-sdk-reference/src/app/pconnect-renderer.component.ts +153 -0
  7. package/templates/angular-sdk-reference/src/components/component-map.ts +90 -0
  8. package/templates/angular-sdk-reference/src/components/fields/auto-complete/auto-complete.component.ts +304 -0
  9. package/templates/angular-sdk-reference/src/components/fields/checkbox/checkbox.component.ts +89 -0
  10. package/templates/angular-sdk-reference/src/components/fields/currency/currency.component.ts +112 -0
  11. package/templates/angular-sdk-reference/src/components/fields/date-input/date-input.component.ts +101 -0
  12. package/templates/angular-sdk-reference/src/components/fields/dropdown/dropdown.component.ts +118 -0
  13. package/templates/angular-sdk-reference/src/components/fields/email/email.component.ts +104 -0
  14. package/templates/angular-sdk-reference/src/components/fields/integer/integer.component.ts +106 -0
  15. package/templates/angular-sdk-reference/src/components/fields/phone/phone.component.ts +104 -0
  16. package/templates/angular-sdk-reference/src/components/fields/radio-buttons/radio-buttons.component.ts +113 -0
  17. package/templates/angular-sdk-reference/src/components/fields/text-area/text-area.component.ts +111 -0
  18. package/templates/angular-sdk-reference/src/components/fields/text-input/text-input.component.ts +110 -0
  19. package/templates/angular-sdk-reference/src/components/fields/url-input/url-input.component.ts +113 -0
  20. package/templates/angular-sdk-reference/src/components/helpers/sdk-helpers.ts +93 -0
  21. package/templates/angular-sdk-reference/src/components/infra/assignment/assignment.component.ts +206 -0
  22. package/templates/angular-sdk-reference/src/components/infra/case-summary/case-summary.component.ts +75 -0
  23. package/templates/angular-sdk-reference/src/components/infra/case-view/case-view.component.ts +126 -0
  24. package/templates/angular-sdk-reference/src/components/infra/flow-container/flow-container.component.ts +411 -0
  25. package/templates/angular-sdk-reference/src/components/infra/reference/reference.component.ts +158 -0
  26. package/templates/angular-sdk-reference/src/components/infra/region/region.component.ts +39 -0
  27. package/templates/angular-sdk-reference/src/components/infra/root-container/root-container.component.ts +199 -0
  28. package/templates/angular-sdk-reference/src/components/infra/stages/stages.component.ts +89 -0
  29. package/templates/angular-sdk-reference/src/components/infra/view/view.component.ts +144 -0
  30. package/templates/angular-sdk-reference/src/components/infra/view-container/view-container.component.ts +191 -0
  31. package/templates/angular-sdk-reference/src/components/templates/default-form/default-form.component.ts +105 -0
  32. package/templates/angular-sdk-reference/src/components/templates/narrow-wide/narrow-wide.component.ts +37 -0
  33. package/templates/angular-sdk-reference/src/components/templates/one-column/one-column.component.ts +37 -0
  34. package/templates/angular-sdk-reference/src/components/templates/two-column/two-column.component.ts +37 -0
  35. package/templates/angular-sdk-reference/src/components/templates/wide-narrow/wide-narrow.component.ts +37 -0
  36. package/templates/angular-sdk-reference/tsconfig.app.json +13 -0
  37. package/templates/react-sdk-reference/.ai-common/agents/embedded-flow-expert.md +75 -34
  38. package/templates/react-sdk-reference/.ai-common/agents/implementation-expert.md +74 -38
  39. package/templates/react-sdk-reference/.ai-common/global/ai-agent-instructions-embedded.md +33 -1
  40. package/templates/react-sdk-reference/.ai-common/global/ai-agent-instructions.md +57 -22
  41. package/templates/react-sdk-reference/.ai-common/instructions/embedded-component.md +25 -10
  42. package/templates/react-sdk-reference/.ai-common/prompts/add-component.md +40 -19
  43. package/templates/react-sdk-reference/.ai-common/prompts/component-manifest.json +62 -1
  44. package/templates/react-sdk-reference/.ai-common/prompts/embedded-component-manifest.md +26 -4
  45. package/templates/react-sdk-reference/.ai-common/prompts/generate-all-components.md +84 -33
  46. package/templates/react-sdk-reference/.ai-common/prompts/generate-dse-components.md +46 -26
  47. package/templates/react-sdk-reference/.ai-common/prompts/generate-embedded-components.md +28 -15
  48. package/templates/react-sdk-reference/.ai-common/prompts/generate-field-components.md +24 -6
  49. package/templates/react-sdk-reference/.ai-common/prompts/generate-infra-components.md +24 -6
  50. package/templates/react-sdk-reference/.ai-common/prompts/generate-template-components.md +24 -6
  51. package/templates/react-sdk-reference/.ai-common/prompts/generate-widget-components.md +24 -6
  52. package/templates/react-sdk-reference/.ai-common/prompts/identify-components.md +2 -0
  53. package/templates/react-sdk-reference/.ai-common/prompts/replace-design-system.md +44 -17
  54. package/templates/react-sdk-reference/.ai-common/skills/connect-pega-server.md +14 -1
  55. package/templates/react-sdk-reference/.ai-common/skills/design-system-extension-skills/AssignmentHeader.md +79 -0
  56. package/templates/react-sdk-reference/.ai-common/skills/design-system-extension-skills/Toast.md +96 -0
  57. package/templates/react-sdk-reference/.ai-common/skills/design-system-extension.md +56 -35
  58. package/templates/react-sdk-reference/.ai-common/skills/embedded-flow/analyze-customer-repo.md +29 -3
  59. package/templates/react-sdk-reference/.ai-common/skills/embedded-flow/run-and-verify-integration.md +97 -37
  60. package/templates/react-sdk-reference/.ai-common/skills/embedded-flow/wire-integration.md +91 -60
  61. package/templates/react-sdk-reference/.ai-common/skills/field-components.md +88 -30
  62. package/templates/react-sdk-reference/.ai-common/skills/field-skills/AutoComplete.md +133 -101
  63. package/templates/react-sdk-reference/.ai-common/skills/field-skills/EmbeddedData.md +385 -0
  64. package/templates/react-sdk-reference/.ai-common/skills/field-skills/EmbeddedDataMulti.md +506 -0
  65. package/templates/react-sdk-reference/.ai-common/skills/field-skills/ObjectReference.md +549 -86
  66. package/templates/react-sdk-reference/.ai-common/skills/field-skills/UserReference.md +181 -83
  67. package/templates/react-sdk-reference/.ai-common/skills/infra-components.md +13 -1
  68. package/templates/react-sdk-reference/.ai-common/skills/portal-flow/run-and-verify-portal.md +290 -0
  69. package/templates/react-sdk-reference/.ai-common/skills/template-components.md +13 -1
  70. package/templates/react-sdk-reference/.ai-common/skills/template-skills/ListView.md +125 -153
  71. package/templates/react-sdk-reference/.ai-common/skills/template-skills/SimpleTable.md +90 -81
  72. package/templates/react-sdk-reference/.ai-common/skills/widget-components.md +13 -1
  73. package/templates/react-sdk-reference/assets/icons/trash.svg +3 -0
  74. package/templates/react-sdk-reference/index.html +0 -1
  75. package/templates/react-sdk-reference/package.json +2 -2
  76. package/templates/react-sdk-reference/package.minimal.json +2 -2
  77. package/templates/react-sdk-reference/sdk-config.json +3 -3
  78. package/templates/react-sdk-reference/src/FallbackComponent.tsx +1 -1
  79. package/templates/react-sdk-reference/src/MashupApp.tsx +33 -78
  80. package/templates/react-sdk-reference/src/PortalApp.tsx +23 -100
  81. package/templates/react-sdk-reference/src/components/component-map.ts +15 -1
  82. package/templates/react-sdk-reference/src/components/designSystemExtension/AssignmentHeader/AssignmentHeader.tsx +15 -0
  83. package/templates/react-sdk-reference/src/components/designSystemExtension/AssignmentHeader/index.tsx +1 -0
  84. package/templates/react-sdk-reference/src/components/designSystemExtension/FieldGroup/FieldGroup.tsx +1 -1
  85. package/templates/react-sdk-reference/src/components/designSystemExtension/FieldGroupList/FieldGroupList.tsx +1 -1
  86. package/templates/react-sdk-reference/src/components/designSystemExtension/FieldValueList/FieldValueList.tsx +16 -4
  87. package/templates/react-sdk-reference/src/components/designSystemExtension/ModalDialog/ModalDialog.tsx +26 -0
  88. package/templates/react-sdk-reference/src/components/designSystemExtension/ModalDialog/index.tsx +1 -0
  89. package/templates/react-sdk-reference/src/components/designSystemExtension/Toast/Toast.tsx +35 -0
  90. package/templates/react-sdk-reference/src/components/designSystemExtension/Toast/index.tsx +1 -0
  91. package/templates/react-sdk-reference/src/components/field/AutoComplete/AutoComplete.tsx +362 -24
  92. package/templates/react-sdk-reference/src/components/field/CancelAlert/CancelAlert.tsx +1 -1
  93. package/templates/react-sdk-reference/src/components/field/Checkbox/Checkbox.tsx +3 -1
  94. package/templates/react-sdk-reference/src/components/field/Currency/Currency.tsx +6 -3
  95. package/templates/react-sdk-reference/src/components/field/Date/Date.tsx +2 -1
  96. package/templates/react-sdk-reference/src/components/field/DateTime/DateTime.tsx +2 -1
  97. package/templates/react-sdk-reference/src/components/field/Decimal/Decimal.tsx +4 -3
  98. package/templates/react-sdk-reference/src/components/field/Dropdown/Dropdown.tsx +2 -0
  99. package/templates/react-sdk-reference/src/components/field/Email/Email.tsx +2 -1
  100. package/templates/react-sdk-reference/src/components/field/EmbeddedDataMulti/EmbeddedDataMulti.tsx +121 -0
  101. package/templates/react-sdk-reference/src/components/field/EmbeddedDataMulti/config-ext.json +7 -0
  102. package/templates/react-sdk-reference/src/components/field/EmbeddedDataMulti/index.tsx +1 -0
  103. package/templates/react-sdk-reference/src/components/field/Integer/Integer.tsx +2 -1
  104. package/templates/react-sdk-reference/src/components/field/Location/Location.tsx +1 -1
  105. package/templates/react-sdk-reference/src/components/field/Multiselect/Multiselect.tsx +40 -20
  106. package/templates/react-sdk-reference/src/components/field/ObjectReference/ObjectReference.tsx +554 -49
  107. package/templates/react-sdk-reference/src/components/field/ObjectReference/utils.ts +111 -20
  108. package/templates/react-sdk-reference/src/components/field/Percentage/Percentage.tsx +4 -3
  109. package/templates/react-sdk-reference/src/components/field/Phone/Phone.tsx +2 -1
  110. package/templates/react-sdk-reference/src/components/field/SelectableCard/SelectableCard.tsx +2 -1
  111. package/templates/react-sdk-reference/src/components/field/TextArea/TextArea.tsx +2 -1
  112. package/templates/react-sdk-reference/src/components/field/TextInput/TextInput.tsx +2 -1
  113. package/templates/react-sdk-reference/src/components/field/Time/Time.tsx +2 -1
  114. package/templates/react-sdk-reference/src/components/field/URL/URL.tsx +2 -1
  115. package/templates/react-sdk-reference/src/components/field/UserReference/UserReference.tsx +1 -1
  116. package/templates/react-sdk-reference/src/components/helpers/field-utils.ts +44 -0
  117. package/templates/react-sdk-reference/src/components/helpers/simpleTableHelpers.ts +19 -7
  118. package/templates/react-sdk-reference/src/components/infra/ModalViewContainer/DataViewActionButtons/DataViewActionButtons.tsx +97 -0
  119. package/templates/react-sdk-reference/src/components/infra/ModalViewContainer/DataViewActionButtons/index.tsx +1 -0
  120. package/templates/react-sdk-reference/src/components/infra/ModalViewContainer/ListViewActionButtons/ListViewActionButtons.tsx +53 -0
  121. package/templates/react-sdk-reference/src/components/infra/ModalViewContainer/ListViewActionButtons/index.tsx +1 -0
  122. package/templates/react-sdk-reference/src/components/template/AdvancedSearch/SearchGroups/SearchGroups.tsx +2 -2
  123. package/templates/react-sdk-reference/src/components/template/CaseSummary/CaseSummary.tsx +3 -1
  124. package/templates/react-sdk-reference/src/components/template/DataReference/SearchForm.tsx +4 -4
  125. package/templates/react-sdk-reference/src/components/template/HierarchicalForm/HierarchicalForm.tsx +2 -2
  126. package/templates/react-sdk-reference/src/components/template/InlineDashboard/InlineDashboard.tsx +1 -1
  127. package/templates/react-sdk-reference/src/components/template/ListView/ListView.tsx +7 -3
  128. package/templates/react-sdk-reference/src/components/template/SimpleTable/SimpleTableManual/SimpleTableManual.tsx +173 -99
  129. package/templates/react-sdk-reference/src/components/template/SimpleTable/SimpleTableSelect/SimpleTableSelect.tsx +63 -56
  130. package/templates/react-sdk-reference/src/components/widget/ToDo/ToDo.tsx +1 -1
  131. package/templates/react-sdk-reference/vite.config.ts +26 -4
  132. package/templates/react-sdk-reference/.ai-common/instructions/dse-component.md +0 -47
  133. package/templates/react-sdk-reference/.ai-common/instructions/field-component.md +0 -50
  134. package/templates/react-sdk-reference/.ai-common/instructions/infra-component.md +0 -76
  135. package/templates/react-sdk-reference/.ai-common/instructions/template-component.md +0 -43
  136. package/templates/react-sdk-reference/.ai-common/instructions/widget-component.md +0 -45
  137. package/templates/react-sdk-reference/.ai-common/skills/embedded-flow/authenticate.md +0 -311
  138. package/templates/react-sdk-reference/pega-constellationjs-0.26.3-local.tgz +0 -0
  139. package/templates/react-sdk-reference/pega-sdk-react-0.1.0.tgz +0 -0
@@ -1,17 +1,23 @@
1
- import { useEffect, useState } from 'react';
2
- import { TextField } from '@mui/material';
3
- import Autocomplete from '@mui/material/Autocomplete';
1
+ import { useEffect, useState, useCallback } from 'react';
2
+ import type { ReactNode } from 'react';
3
+ import { TextField, Paper, Button, Divider } from '@mui/material';
4
+ import AddIcon from '@mui/icons-material/Add';
5
+ import Autocomplete, { createFilterOptions } from '@mui/material/Autocomplete';
4
6
  import isDeepEqual from 'fast-deep-equal/react';
5
7
 
6
8
  import Utils from '../../helpers/utils';
7
9
  import { getDataPage } from '../../helpers/data_page';
8
10
  import handleEvent from '../../helpers/event-utils';
11
+ import { useStatus, getFieldSx } from '../../helpers/field-utils';
9
12
  import { getComponentFromRegistry } from '@pega/sdk-react';
10
13
  import type { PConnFieldProps } from '@pega/sdk-react';
11
14
 
12
15
  interface IOption {
13
16
  key: string;
14
17
  value: string;
18
+ secondary?: ReactNode[];
19
+ secondaryRaw?: string[];
20
+ group?: string;
15
21
  }
16
22
 
17
23
  const preProcessColumns = (columnList) => {
@@ -22,6 +28,18 @@ const preProcessColumns = (columnList) => {
22
28
  });
23
29
  };
24
30
 
31
+ const getPropertyName = (rawValue: string): string => {
32
+ let propName;
33
+ if (rawValue.startsWith('@USER ')) {
34
+ propName = rawValue.substring(6).trim();
35
+ } else if (rawValue.startsWith('@P ')) {
36
+ propName = rawValue.substring(3).trim();
37
+ } else {
38
+ propName = rawValue.trim();
39
+ }
40
+ return propName.startsWith('.') ? propName.substring(1) : propName;
41
+ };
42
+
25
43
  const getDisplayFieldsMetaData = (columnList) => {
26
44
  const displayColumns = columnList.filter((col) => col.display === 'true');
27
45
  const metaDataObj: any = { key: '', primary: '', secondary: [] };
@@ -49,6 +67,19 @@ interface AutoCompleteProps extends PConnFieldProps {
49
67
  parameters?: any;
50
68
  datasource: any;
51
69
  columns: any[];
70
+ showFieldMessage?: boolean;
71
+ messageConfig?: {
72
+ content?: string;
73
+ visibility?: boolean;
74
+ };
75
+ variant?: string;
76
+ showCreateNew?: boolean;
77
+ onCreateNew?: () => void;
78
+ createNewLabel?: string;
79
+ createNewRecord?: () => Promise<unknown>;
80
+ contextClass?: string;
81
+ referenceType?: string;
82
+ allowCreatingRecords?: boolean;
52
83
  }
53
84
 
54
85
  export default function AutoComplete(props: AutoCompleteProps) {
@@ -68,10 +99,16 @@ export default function AutoComplete(props: AutoCompleteProps) {
68
99
  displayMode,
69
100
  deferDatasource,
70
101
  datasourceMetadata,
71
- status,
72
102
  helperText,
73
103
  hideLabel,
74
104
  onRecordChange,
105
+ showFieldMessage,
106
+ messageConfig = {},
107
+ onCreateNew,
108
+ createNewLabel = 'Create new',
109
+ createNewRecord,
110
+ contextClass,
111
+ referenceType,
75
112
  } = props;
76
113
 
77
114
  const context = getPConnect().getContextName();
@@ -79,13 +116,21 @@ export default function AutoComplete(props: AutoCompleteProps) {
79
116
  const [inputValue, setInputValue] = useState('');
80
117
  const [options, setOptions] = useState<IOption[]>([]);
81
118
  const [theDatasource, setDatasource] = useState(null);
82
- let selectedValue: any = '';
83
- const helperTextToDisplay = validatemessage || helperText;
119
+ let selectedValue: any = null;
120
+ const eligibleForFieldWarning = showFieldMessage && messageConfig.visibility && !readOnly;
121
+ const helperTextToDisplay = validatemessage || (eligibleForFieldWarning ? messageConfig.content : helperText);
84
122
 
85
123
  const thePConn = getPConnect();
86
124
  const actionsApi = thePConn.getActionsApi();
87
125
  const propName = (thePConn.getStateProps() as any).value;
88
126
 
127
+ const status = useStatus({
128
+ showFieldMessage,
129
+ messageVisibility: messageConfig.visibility,
130
+ validatemessage,
131
+ readOnly,
132
+ });
133
+
89
134
  if (!isDeepEqual(datasource, theDatasource)) {
90
135
  // inbound datasource is different, so update theDatasource (to trigger useEffect)
91
136
  setDatasource(datasource);
@@ -130,6 +175,34 @@ export default function AutoComplete(props: AutoCompleteProps) {
130
175
  },
131
176
  ];
132
177
  }
178
+ // Add secondary columns from columnsFormatter metadata
179
+ const columnsFormatter = (thePConn.getRawMetadata?.()?.config as any)?.columnsFormatter;
180
+ if (Array.isArray(columnsFormatter) && columnsFormatter.length > 0) {
181
+ columnsFormatter.forEach((formatter) => {
182
+ if (formatter.config?.value) {
183
+ columns.push({
184
+ value: getPropertyName(formatter.config.value),
185
+ display: 'true',
186
+ useForSearch: true,
187
+ secondary: 'true',
188
+ });
189
+ }
190
+ });
191
+ }
192
+
193
+ const groupsFields = (thePConn.getRawMetadata?.()?.config as any)?.groupsFields;
194
+ const groupKeyFields: string[] = Array.isArray(groupsFields)
195
+ ? groupsFields.map((entry: any) => getPropertyName(entry?.config?.value || '')).filter(Boolean)
196
+ : [];
197
+ const isGrouped = groupKeyFields.length > 0;
198
+
199
+ // Group fields must be requested so they come back in the data page response
200
+ groupKeyFields.forEach((field) => {
201
+ if (!columns.find((col) => col.value === field || col.value === `.${field}`)) {
202
+ columns.push({ value: field, display: 'false', useForSearch: false });
203
+ }
204
+ });
205
+
133
206
  columns = preProcessColumns(columns);
134
207
 
135
208
  useEffect(() => {
@@ -138,26 +211,88 @@ export default function AutoComplete(props: AutoCompleteProps) {
138
211
  }
139
212
  }, [theDatasource]);
140
213
 
214
+ const buildOptionsFromResults = (results: any[]): IOption[] => {
215
+ const optionsData: IOption[] = [];
216
+ const displayColumn = getDisplayFieldsMetaData(columns);
217
+ results?.forEach((element) => {
218
+ const val = element[displayColumn.primary]?.toString() || '';
219
+ let secondaryNodes: ReactNode[] = [];
220
+ let secondaryRaw: string[] = [];
221
+
222
+ if (Array.isArray(columnsFormatter) && columnsFormatter.length > 0) {
223
+ columnsFormatter.forEach((formatter, idx) => {
224
+ if (formatter.config?.value) {
225
+ const fmtPropName = getPropertyName(formatter.config.value);
226
+ secondaryRaw.push(element[fmtPropName]?.toString() || '');
227
+
228
+ try {
229
+ const fieldMeta = {
230
+ meta: {
231
+ ...formatter,
232
+ config: {
233
+ ...formatter.config,
234
+ displayMode: 'DISPLAY_ONLY',
235
+ contextName: context,
236
+ variant: 'inline-compact',
237
+ },
238
+ },
239
+ useCustomContext: element,
240
+ };
241
+ const configObj = (PCore as any).createPConnect(fieldMeta);
242
+ const resolvedPConn = configObj.getPConnect();
243
+ const resolvedProps = resolvedPConn.resolveConfigProps(resolvedPConn.getConfigProps());
244
+ const Component = getComponentFromRegistry(formatter.type);
245
+ if (Component) {
246
+ secondaryNodes.push(
247
+ <Component
248
+ key={idx}
249
+ {...resolvedProps}
250
+ getPConnect={() => resolvedPConn}
251
+ displayMode="DISPLAY_ONLY"
252
+ />,
253
+ );
254
+ } else {
255
+ secondaryNodes.push(element[fmtPropName]?.toString() || '');
256
+ }
257
+ } catch {
258
+ secondaryNodes.push(element[fmtPropName]?.toString() || '');
259
+ }
260
+ }
261
+ });
262
+ } else {
263
+ secondaryRaw = displayColumn.secondary.map((col) => element[col]?.toString()).filter(Boolean);
264
+ secondaryNodes = [...secondaryRaw];
265
+ }
266
+
267
+ optionsData.push({
268
+ key: String(element[displayColumn.key] ?? element.pyGUID ?? ''),
269
+ value: val,
270
+ ...(secondaryNodes.length > 0 && { secondary: secondaryNodes }),
271
+ ...(secondaryRaw.length > 0 && { secondaryRaw }),
272
+ ...(isGrouped && { group: element[groupKeyFields[0]]?.toString() || '' }),
273
+ });
274
+ });
275
+ // MUI only renders groups correctly when options are contiguous by group
276
+ if (isGrouped) {
277
+ optionsData.sort((a, b) => (a.group || '').localeCompare(b.group || ''));
278
+ }
279
+ return optionsData;
280
+ };
281
+
141
282
  useEffect(() => {
142
283
  if (!displayMode && listType !== 'associated') {
143
- getDataPage(datasource, parameters, context).then((results: any) => {
144
- const optionsData: any[] = [];
145
- const displayColumn = getDisplayFieldsMetaData(columns);
146
- results?.forEach((element) => {
147
- const val = element[displayColumn.primary]?.toString();
148
- const obj = {
149
- key: element[displayColumn.key] || element.pyGUID,
150
- value: val,
151
- };
152
- optionsData.push(obj);
284
+ getDataPage(datasource, parameters, context)
285
+ .then((results: any) => {
286
+ setOptions(buildOptionsFromResults(results));
287
+ })
288
+ .catch((e) => {
289
+ console.error(e);
153
290
  });
154
- setOptions(optionsData);
155
- });
156
291
  }
157
292
  }, []);
158
293
 
159
294
  if (displayMode === 'DISPLAY_ONLY') {
160
- return <FieldValueList name={hideLabel ? '' : label} value={value} />;
295
+ return <FieldValueList name={hideLabel ? '' : label} value={value} variant={props.variant} />;
161
296
  }
162
297
 
163
298
  if (displayMode === 'STACKED_LARGE_VAL') {
@@ -173,18 +308,192 @@ export default function AutoComplete(props: AutoCompleteProps) {
173
308
  }
174
309
  }
175
310
 
311
+ useEffect(() => {
312
+ setInputValue(selectedValue || '');
313
+ }, [selectedValue]);
314
+
176
315
  const handleChange = (event: object, newValue) => {
177
316
  const val = newValue ? newValue.key : '';
178
- handleEvent(actionsApi, 'changeNblur', propName, val);
317
+ if (!newValue) {
318
+ setInputValue('');
319
+ }
320
+ actionsApi.updateFieldValue(propName, val);
321
+ const changePromise = (actionsApi as any).triggerFieldChange(propName, val);
179
322
  if (onRecordChange) {
180
- onRecordChange(event);
323
+ if (changePromise && changePromise.then) {
324
+ changePromise
325
+ .then(() => {
326
+ onRecordChange({ ...event, id: val });
327
+ })
328
+ .catch((e) => {
329
+ console.error(e);
330
+ });
331
+ } else {
332
+ onRecordChange({ ...event, id: val });
333
+ }
181
334
  }
182
335
  };
183
336
 
184
- const handleInputValue = (event, newInputValue) => {
185
- setInputValue(newInputValue);
337
+ const handleInputValue = (event, newInputValue, reason) => {
338
+ if (reason === 'selectOption') {
339
+ setInputValue(newInputValue);
340
+ }
341
+ };
342
+
343
+ // Mirrors setValuesToOtherAdditionalFields in constellation-frontend
344
+ const setValuesToAdditionalFields = (record: Record<string, unknown>) => {
345
+ const setPropertyList = columns
346
+ .filter((col) => col.setProperty)
347
+ .map((col) => ({
348
+ source: col.value,
349
+ target: col.setProperty,
350
+ key: col.key,
351
+ primary: col.primary,
352
+ }));
353
+
354
+ setPropertyList.forEach((prop) => {
355
+ let valueToSet: string;
356
+ if (prop.key === 'true') {
357
+ valueToSet = record[prop.source]?.toString() || (record as any).pyGUID || '';
358
+ } else {
359
+ valueToSet = record[prop.source]?.toString() || '';
360
+ }
361
+
362
+ if (prop.target === 'Associated property') {
363
+ handleEvent(actionsApi, 'changeNblur', propName, valueToSet);
364
+ } else {
365
+ const target = typeof prop.target === 'string' ? prop.target : '';
366
+ const targetProp = target.startsWith('.') ? target : `.${target}`;
367
+ (actionsApi as any).updateFieldValue(targetProp, valueToSet, { associatedProperty: propName });
368
+ (actionsApi as any).triggerFieldChange(targetProp, valueToSet);
369
+ }
370
+ });
186
371
  };
187
372
 
373
+ const refreshOptionsList = () => {
374
+ if (!displayMode && listType !== 'associated') {
375
+ getDataPage(datasource, parameters, context)
376
+ .then((results: any) => {
377
+ setOptions(buildOptionsFromResults(results));
378
+ })
379
+ .catch((e) => {
380
+ console.error(e);
381
+ });
382
+ }
383
+ };
384
+
385
+ const createNewButtonHandler = () => {
386
+ if (onCreateNew) {
387
+ onCreateNew();
388
+ return;
389
+ }
390
+
391
+ if (!contextClass) return;
392
+
393
+ const normalizedReferenceType = typeof referenceType === 'string' ? referenceType.toLowerCase() : '';
394
+ const isDataReference = normalizedReferenceType === 'data';
395
+ const { CREATE_STAGE_DONE } = PCore.getConstants().PUB_SUB_EVENTS.CASE_EVENTS;
396
+ const DATA_OBJECT_CREATED = (PCore.getConstants().PUB_SUB_EVENTS as any).DATA_EVENTS?.DATA_OBJECT_CREATED;
397
+ const eventType = isDataReference && DATA_OBJECT_CREATED ? DATA_OBJECT_CREATED : CREATE_STAGE_DONE;
398
+
399
+ const createNewCallback = isDataReference
400
+ ? (data: { classId?: string; data?: { responseData?: Record<string, unknown> } }) => {
401
+ PCore.getDataApi().clearContextedCache(context);
402
+
403
+ const responseData = data?.data?.responseData;
404
+ if (responseData) {
405
+ setValuesToAdditionalFields(responseData);
406
+ const displayColumn = getDisplayFieldsMetaData(columns);
407
+ if (onRecordChange) {
408
+ const newKey = responseData[displayColumn.key]?.toString() || (responseData as any).pyGUID;
409
+ onRecordChange({ id: newKey });
410
+ }
411
+ }
412
+
413
+ refreshOptionsList();
414
+ PCore.getPubSubUtils().unsubscribe(eventType, contextClass);
415
+ }
416
+ : (data: { caseId?: string; caseType?: string; ID?: string }) => {
417
+ PCore.getDataApi().clearContextedCache(context);
418
+
419
+ const newCaseId = data.caseId?.split(' ').pop();
420
+ if (data.caseType === contextClass) {
421
+ const selectKey = data.ID || newCaseId;
422
+
423
+ if (selectKey && listType !== 'associated' && datasource) {
424
+ getDataPage(datasource, parameters, context)
425
+ .then((results: any) => {
426
+ setOptions(buildOptionsFromResults(results));
427
+
428
+ const displayColumn = getDisplayFieldsMetaData(columns);
429
+ const newRecord = results?.find(
430
+ (el: any) => el.ID === data.ID || (el[displayColumn.key] || el.pyGUID) === selectKey,
431
+ );
432
+ if (newRecord) {
433
+ setValuesToAdditionalFields(newRecord);
434
+ } else {
435
+ handleEvent(actionsApi, 'changeNblur', propName, selectKey);
436
+ }
437
+ if (onRecordChange) {
438
+ onRecordChange({ id: selectKey });
439
+ }
440
+ })
441
+ .catch((e) => {
442
+ console.error(e);
443
+ });
444
+ }
445
+ PCore.getPubSubUtils().unsubscribe(eventType, contextClass);
446
+ }
447
+ };
448
+
449
+ const triggerCreate = createNewRecord
450
+ ? createNewRecord()
451
+ : isDataReference
452
+ ? getPConnect().getActionsApi().showDataObjectCreateView(contextClass)
453
+ : thePConn.getActionsApi().createWork(contextClass, {
454
+ openCaseViewAfterCreate: false,
455
+ startingFields: {},
456
+ } as any);
457
+
458
+ Promise.resolve(triggerCreate)
459
+ .then(() => {
460
+ PCore.getPubSubUtils().subscribe(eventType, createNewCallback, contextClass);
461
+ refreshOptionsList();
462
+ })
463
+ .catch((e) => {
464
+ console.error(e);
465
+ });
466
+ };
467
+
468
+ const showCreateButton = props.allowCreatingRecords === true;
469
+
470
+ const CustomPaper = useCallback(
471
+ (paperProps: React.HTMLAttributes<HTMLElement>) => {
472
+ return (
473
+ <Paper {...paperProps}>
474
+ {paperProps.children}
475
+ {showCreateButton && (
476
+ <>
477
+ <Divider />
478
+ <Button
479
+ fullWidth
480
+ startIcon={<AddIcon />}
481
+ onMouseDown={(event) => {
482
+ event.preventDefault();
483
+ }}
484
+ onClick={createNewButtonHandler}
485
+ sx={{ justifyContent: 'flex-start', textTransform: 'none', py: 1, px: 2 }}
486
+ >
487
+ {createNewLabel}
488
+ </Button>
489
+ </>
490
+ )}
491
+ </Paper>
492
+ );
493
+ },
494
+ [showCreateButton, createNewButtonHandler, createNewLabel],
495
+ );
496
+
188
497
  if (readOnly) {
189
498
  const theValAsString = options?.find((opt) => opt.key === value)?.value;
190
499
  return <TextInput {...props} value={theValAsString} />;
@@ -193,18 +502,46 @@ export default function AutoComplete(props: AutoCompleteProps) {
193
502
  // key/value structure to what Autocomplete expects
194
503
  return (
195
504
  <Autocomplete
505
+ slots={{ paper: CustomPaper }}
196
506
  options={options}
197
507
  getOptionLabel={(option: IOption) => {
198
508
  return option.value ? option.value : '';
199
509
  }}
510
+ {...(isGrouped && { groupBy: (option: IOption) => option.group || '' })}
200
511
  isOptionEqualToValue={(option: any) => {
201
512
  return option.value ? option.value : '';
202
513
  }}
203
514
  fullWidth
204
515
  onChange={handleChange}
205
516
  value={selectedValue}
206
- inputValue={inputValue || selectedValue}
517
+ inputValue={inputValue}
207
518
  onInputChange={handleInputValue}
519
+ filterOptions={createFilterOptions<IOption>({
520
+ stringify: (option) => {
521
+ const parts = [option.value || ''];
522
+ if (option.secondaryRaw) {
523
+ parts.push(...option.secondaryRaw);
524
+ }
525
+ return parts.join(' ');
526
+ },
527
+ })}
528
+ renderOption={(renderProps, option: IOption) => (
529
+ <li {...renderProps} key={option.key}>
530
+ <div>
531
+ <span>{option.value}</span>
532
+ {option.secondary && option.secondary.length > 0 && (
533
+ <div style={{ display: 'flex', flexWrap: 'wrap', alignItems: 'center' }}>
534
+ {option.secondary.map((sec, i) => (
535
+ <span key={i} style={{ display: 'inline-flex', alignItems: 'center' }}>
536
+ {sec}
537
+ {i < option.secondary!.length - 1 && <span style={{ margin: '0 4px' }}>{'\u00B7'}</span>}
538
+ </span>
539
+ ))}
540
+ </div>
541
+ )}
542
+ </div>
543
+ </li>
544
+ )}
208
545
  renderInput={(params) => (
209
546
  <TextField
210
547
  {...params}
@@ -217,6 +554,7 @@ export default function AutoComplete(props: AutoCompleteProps) {
217
554
  error={status === 'error'}
218
555
  label={label}
219
556
  data-test-id={testId}
557
+ sx={getFieldSx(status)}
220
558
  />
221
559
  )}
222
560
  />
@@ -143,7 +143,7 @@ export default function CancelAlert(props: CancelAlertProps) {
143
143
  <p>{localizedVal(content, localeCategory)}</p>
144
144
  </div>
145
145
  <div className="action-controls">
146
- <Grid container spacing={4} justifyContent="space-between">
146
+ <Grid container spacing={4} sx={{ justifyContent: 'space-between' }}>
147
147
  <Grid>{leftButton}</Grid>
148
148
  <Grid>{rightButton}</Grid>
149
149
  </Grid>
@@ -109,7 +109,9 @@ export default function CheckboxComponent(props: CheckboxProps) {
109
109
  }, [value]);
110
110
 
111
111
  if (displayMode === 'DISPLAY_ONLY') {
112
- return <FieldValueList name={hideLabel ? '' : caption} value={value ? trueLabel : falseLabel} />;
112
+ return (
113
+ <FieldValueList name={hideLabel ? '' : caption} value={value ? trueLabel : falseLabel} variant={props.variant} />
114
+ );
113
115
  }
114
116
 
115
117
  if (displayMode === 'STACKED_LARGE_VAL') {
@@ -11,6 +11,7 @@ import { getCurrencyCharacters, getCurrencyOptions } from './currency-utils';
11
11
  as per the locale.
12
12
  */
13
13
  interface CurrrencyProps extends PConnFieldProps {
14
+ variant?: string;
14
15
  // If any, enter additional props that only exist on Currency here
15
16
  currencyISOCode?: string;
16
17
  allowDecimals: boolean;
@@ -43,12 +44,12 @@ export default function Currency(props: CurrrencyProps) {
43
44
  const actions = pConn.getActionsApi();
44
45
  const propName = (pConn.getStateProps() as any).value;
45
46
  const helperTextToDisplay = validatemessage || helperText;
46
- const [values, setValues] = useState(value.toString());
47
+ const [values, setValues] = useState(value?.toString() ?? '');
47
48
 
48
49
  const testProps: any = { 'data-test-id': testId };
49
50
 
50
51
  useEffect(() => {
51
- setValues(value.toString());
52
+ setValues(value?.toString() ?? '');
52
53
  }, [value]);
53
54
 
54
55
  // currencySymbols looks like this: { theCurrencySymbol: '$', theDecimalIndicator: '.', theSeparator: ',' }
@@ -74,7 +75,7 @@ export default function Currency(props: CurrrencyProps) {
74
75
  };
75
76
 
76
77
  if (displayMode === 'DISPLAY_ONLY') {
77
- return <FieldValueList name={hideLabel ? '' : label} value={formattedValue} />;
78
+ return <FieldValueList name={hideLabel ? '' : label} value={formattedValue} variant={props.variant} />;
78
79
  }
79
80
 
80
81
  if (displayMode === 'STACKED_LARGE_VAL') {
@@ -92,7 +93,9 @@ export default function Currency(props: CurrrencyProps) {
92
93
  return (
93
94
  <NumericFormat
94
95
  valueIsNumericString
96
+ fullWidth
95
97
  variant={readOnly ? 'standard' : 'outlined'}
98
+ size="small"
96
99
  label={label}
97
100
  helperText={helperTextToDisplay}
98
101
  placeholder={placeholder ?? ''}
@@ -14,6 +14,7 @@ function getFormattedDate(date) {
14
14
  }
15
15
 
16
16
  interface DateProps extends PConnFieldProps {
17
+ variant?: string;
17
18
  // If any, enter additional props that only exist on Date here
18
19
  }
19
20
 
@@ -60,7 +61,7 @@ export default function Date(props: DateProps) {
60
61
  const formattedDate = format(props.value, 'date', {
61
62
  format: dateFormatInfo.dateFormatString,
62
63
  });
63
- return <FieldValueList name={hideLabel ? '' : label} value={formattedDate} />;
64
+ return <FieldValueList name={hideLabel ? '' : label} value={formattedDate} variant={props.variant} />;
64
65
  }
65
66
 
66
67
  if (displayMode === 'STACKED_LARGE_VAL') {
@@ -9,6 +9,7 @@ import { getComponentFromRegistry } from '@pega/sdk-react';
9
9
  import type { PConnFieldProps } from '@pega/sdk-react';
10
10
 
11
11
  interface DateTimeProps extends PConnFieldProps {
12
+ variant?: string;
12
13
  // If any, enter additional props that only exist on DateTime here
13
14
  }
14
15
 
@@ -60,7 +61,7 @@ export default function DateTime(props: DateTimeProps) {
60
61
  const formattedDateTime = format(props.value, 'datetime', {
61
62
  format: `${dateFormatInfo.dateFormatString} hh:mm a`,
62
63
  });
63
- return <FieldValueList name={hideLabel ? '' : label} value={formattedDateTime} />;
64
+ return <FieldValueList name={hideLabel ? '' : label} value={formattedDateTime} variant={props.variant} />;
64
65
  }
65
66
 
66
67
  if (displayMode === 'STACKED_LARGE_VAL') {
@@ -12,6 +12,7 @@ as per the locale.
12
12
  */
13
13
 
14
14
  interface DecimalProps extends PConnFieldProps {
15
+ variant?: string;
15
16
  // If any, enter additional props that only exist on Decimal here
16
17
  currencyISOCode?: string;
17
18
  decimalPrecision?: number;
@@ -44,7 +45,7 @@ export default function Decimal(props: DecimalProps) {
44
45
  formatter,
45
46
  } = props;
46
47
 
47
- const [values, setValues] = useState(value.toString());
48
+ const [values, setValues] = useState(value?.toString() ?? '');
48
49
 
49
50
  const pConn = getPConnect();
50
51
  const actions = pConn.getActionsApi();
@@ -59,7 +60,7 @@ export default function Decimal(props: DecimalProps) {
59
60
  const theCurrencyOptions = getCurrencyOptions(currencyISOCode);
60
61
 
61
62
  useEffect(() => {
62
- setValues(value.toString());
63
+ setValues(value?.toString() ?? '');
63
64
  }, [value]);
64
65
 
65
66
  let readOnlyProp = {}; // Note: empty if NOT ReadOnly
@@ -76,7 +77,7 @@ export default function Decimal(props: DecimalProps) {
76
77
  }
77
78
 
78
79
  if (displayMode === 'DISPLAY_ONLY') {
79
- return <FieldValueList name={hideLabel ? '' : label} value={formattedValue} />;
80
+ return <FieldValueList name={hideLabel ? '' : label} value={formattedValue} variant={props.variant} />;
80
81
  }
81
82
 
82
83
  if (displayMode === 'STACKED_LARGE_VAL') {
@@ -47,6 +47,7 @@ const getDisplayFieldsMetaData = (columnList) => {
47
47
  };
48
48
 
49
49
  interface DropdownProps extends PConnFieldProps {
50
+ variant?: string;
50
51
  // If any, enter additional props that only exist on Dropdown here
51
52
  datasource?: any[];
52
53
  onRecordChange?: any;
@@ -183,6 +184,7 @@ export default function Dropdown(props: DropdownProps) {
183
184
  localePath,
184
185
  thePConn.getLocaleRuleNameFromKeys(localeClass, localeContext, localeName),
185
186
  )}
187
+ variant={props.variant}
186
188
  />
187
189
  );
188
190
  }
@@ -7,6 +7,7 @@ import type { PConnFieldProps } from '@pega/sdk-react';
7
7
  import handleEvent from '../../helpers/event-utils';
8
8
 
9
9
  interface EmailProps extends PConnFieldProps {
10
+ variant?: string;
10
11
  // If any, enter additional props that only exist on Date here
11
12
  }
12
13
 
@@ -44,7 +45,7 @@ export default function Email(props: EmailProps) {
44
45
  }, [value]);
45
46
 
46
47
  if (displayMode === 'DISPLAY_ONLY') {
47
- return <FieldValueList name={hideLabel ? '' : label} value={value} />;
48
+ return <FieldValueList name={hideLabel ? '' : label} value={value} variant={props.variant} />;
48
49
  }
49
50
 
50
51
  if (displayMode === 'STACKED_LARGE_VAL') {