@pega/angular-sdk-overrides 0.23.5 → 0.24.1

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 (37) hide show
  1. package/lib/designSystemExtension/material-case-summary/material-case-summary.component.html +5 -2
  2. package/lib/designSystemExtension/material-case-summary/material-case-summary.component.ts +3 -1
  3. package/lib/designSystemExtension/operator/operator.component.ts +6 -4
  4. package/lib/field/auto-complete/auto-complete.component.ts +1 -1
  5. package/lib/field/check-box/check-box.component.html +16 -15
  6. package/lib/field/check-box/check-box.component.scss +14 -1
  7. package/lib/field/check-box/check-box.component.ts +127 -44
  8. package/lib/field/group/group.component.html +1 -1
  9. package/lib/field/group/group.component.ts +4 -0
  10. package/lib/field/multiselect/multiselect.component.html +34 -0
  11. package/lib/field/multiselect/multiselect.component.scss +7 -0
  12. package/lib/field/multiselect/multiselect.component.spec.ts +21 -0
  13. package/lib/field/multiselect/multiselect.component.ts +363 -0
  14. package/lib/field/multiselect/utils.ts +209 -0
  15. package/lib/field/rich-text/rich-text.component.html +1 -1
  16. package/lib/field/time/time.component.html +1 -0
  17. package/lib/field/time/time.component.ts +2 -0
  18. package/lib/field/url/url.component.html +1 -0
  19. package/lib/field/url/url.component.ts +2 -0
  20. package/lib/infra/Containers/view-container/view-container.component.ts +7 -6
  21. package/lib/infra/multi-step/multi-step.component.scss +1 -0
  22. package/lib/infra/navbar/navbar.component.html +3 -3
  23. package/lib/infra/navbar/navbar.component.ts +4 -2
  24. package/lib/template/case-summary/case-summary.component.ts +37 -3
  25. package/lib/template/field-value-list/field-value-list.component.html +7 -2
  26. package/lib/template/field-value-list/field-value-list.component.ts +1 -0
  27. package/lib/template/list-view/list-view.component.html +4 -4
  28. package/lib/template/list-view/list-view.component.ts +21 -24
  29. package/lib/template/list-view/utils.ts +4 -2
  30. package/lib/template/simple-table-manual/helpers.ts +1 -1
  31. package/lib/template/simple-table-manual/simple-table-manual.component.html +1 -1
  32. package/lib/template/simple-table-manual/simple-table-manual.component.ts +44 -7
  33. package/lib/template/wss-nav-bar/wss-nav-bar.component.html +1 -1
  34. package/lib/template/wss-nav-bar/wss-nav-bar.component.ts +2 -1
  35. package/lib/widget/attachment/attachment.component.html +9 -1
  36. package/lib/widget/attachment/attachment.component.ts +4 -1
  37. package/package.json +1 -1
@@ -0,0 +1,363 @@
1
+ import { CommonModule } from '@angular/common';
2
+ import { Component, forwardRef, Input, OnDestroy, OnInit } from '@angular/core';
3
+ import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
4
+ import { MatAutocompleteModule, MatAutocompleteSelectedEvent, MatAutocompleteTrigger } from '@angular/material/autocomplete';
5
+ import { MatChipsModule } from '@angular/material/chips';
6
+ import { MatCheckboxModule } from '@angular/material/checkbox';
7
+ import { MatOptionModule } from '@angular/material/core';
8
+ import { MatFormFieldModule } from '@angular/material/form-field';
9
+ import { MatInputModule } from '@angular/material/input';
10
+ import { MatIconModule } from '@angular/material/icon';
11
+ import { AngularPConnectData, AngularPConnectService } from '@pega/angular-sdk-components';
12
+ import { ComponentMapperComponent } from '@pega/angular-sdk-components';
13
+ import { Utils } from '@pega/angular-sdk-components';
14
+ import { doSearch, getDisplayFieldsMetaData, getGroupDataForItemsTree, preProcessColumns } from './utils';
15
+ import { deleteInstruction, insertInstruction } from '@pega/angular-sdk-components';
16
+
17
+ @Component({
18
+ selector: 'app-multiselect',
19
+ templateUrl: './multiselect.component.html',
20
+ styleUrls: ['./multiselect.component.scss'],
21
+ standalone: true,
22
+ imports: [
23
+ CommonModule,
24
+ ReactiveFormsModule,
25
+ MatFormFieldModule,
26
+ MatInputModule,
27
+ MatAutocompleteModule,
28
+ MatOptionModule,
29
+ MatCheckboxModule,
30
+ MatIconModule,
31
+ MatChipsModule,
32
+ forwardRef(() => ComponentMapperComponent)
33
+ ]
34
+ })
35
+ export class MultiselectComponent implements OnInit, OnDestroy {
36
+ @Input() pConn$: typeof PConnect;
37
+ @Input() formGroup$: FormGroup;
38
+
39
+ // Used with AngularPConnect
40
+ angularPConnectData: AngularPConnectData = {};
41
+
42
+ label$ = '';
43
+ value$ = '';
44
+ bRequired$ = false;
45
+ bDisabled$ = false;
46
+ bVisible$ = true;
47
+ controlName$: string;
48
+ bHasForm$ = true;
49
+ listType: string;
50
+ placeholder: string;
51
+ fieldControl = new FormControl('', null);
52
+ parameters: {};
53
+ hideLabel: boolean;
54
+ configProps$: any;
55
+
56
+ referenceList: any;
57
+ selectionKey: string;
58
+ primaryField: string;
59
+ initialCaseClass: any;
60
+ showSecondaryInSearchOnly = false;
61
+ isGroupData = false;
62
+ referenceType;
63
+ secondaryFields;
64
+ groupDataSource = [];
65
+ matchPosition = 'contains';
66
+ maxResultsDisplay;
67
+ groupColumnsConfig = [{}];
68
+ selectionList;
69
+ listActions: any;
70
+ selectedItems: any[] = [];
71
+ itemsTreeBaseData = [];
72
+ displayFieldMeta: any;
73
+ dataApiObj: any;
74
+ itemsTree: any[] = [];
75
+ trigger: any;
76
+
77
+ constructor(
78
+ private angularPConnect: AngularPConnectService,
79
+ private utils: Utils
80
+ ) {}
81
+
82
+ ngOnInit(): void {
83
+ // First thing in initialization is registering and subscribing to the AngularPConnect service
84
+ this.angularPConnectData = this.angularPConnect.registerAndSubscribeComponent(this, this.onStateChange);
85
+ this.controlName$ = this.angularPConnect.getComponentID(this);
86
+
87
+ // Then, continue on with other initialization
88
+ this.checkAndUpdate();
89
+
90
+ if (this.formGroup$) {
91
+ // add control to formGroup
92
+ this.formGroup$.addControl(this.controlName$, this.fieldControl);
93
+ this.fieldControl.setValue(this.value$);
94
+ this.bHasForm$ = true;
95
+ } else {
96
+ this.bHasForm$ = false;
97
+ }
98
+ }
99
+
100
+ ngOnDestroy(): void {
101
+ if (this.formGroup$) {
102
+ this.formGroup$.removeControl(this.controlName$);
103
+ }
104
+
105
+ if (this.angularPConnectData.unsubscribeFn) {
106
+ this.angularPConnectData.unsubscribeFn();
107
+ }
108
+ }
109
+
110
+ // Callback passed when subscribing to store change
111
+ onStateChange() {
112
+ this.checkAndUpdate();
113
+ }
114
+
115
+ checkAndUpdate() {
116
+ // Should always check the bridge to see if the component should
117
+ // update itself (re-render)
118
+ const bUpdateSelf = this.angularPConnect.shouldComponentUpdate(this);
119
+
120
+ // ONLY call updateSelf when the component should update
121
+ if (bUpdateSelf) {
122
+ this.updateSelf();
123
+ }
124
+ }
125
+
126
+ // updateSelf
127
+ updateSelf() {
128
+ this.configProps$ = this.pConn$.resolveConfigProps(this.pConn$.getConfigProps());
129
+
130
+ let { datasource = [], columns = [{}] } = this.configProps$;
131
+ this.setPropertyValuesFromProps();
132
+
133
+ if (this.referenceList.length > 0) {
134
+ datasource = this.referenceList;
135
+ columns = [
136
+ {
137
+ value: this.primaryField,
138
+ display: 'true',
139
+ useForSearch: true,
140
+ primary: 'true'
141
+ },
142
+ {
143
+ value: this.selectionKey,
144
+ setProperty: this.selectionKey,
145
+ key: 'true'
146
+ }
147
+ ];
148
+ let secondaryColumns: any = [];
149
+ if (this.secondaryFields) {
150
+ secondaryColumns = this.secondaryFields.map(secondaryField => ({
151
+ value: secondaryField,
152
+ display: 'true',
153
+ secondary: 'true',
154
+ useForSearch: 'true'
155
+ }));
156
+ } else {
157
+ secondaryColumns = [
158
+ {
159
+ value: this.selectionKey,
160
+ display: 'true',
161
+ secondary: 'true',
162
+ useForSearch: 'true'
163
+ }
164
+ ];
165
+ }
166
+ if (this.referenceType === 'Case') {
167
+ columns = [...columns, ...secondaryColumns];
168
+ }
169
+ }
170
+
171
+ this.value$ = this.value$ ? this.value$ : '';
172
+ const contextName = this.pConn$.getContextName();
173
+
174
+ const dataConfig = {
175
+ dataSource: datasource,
176
+ groupDataSource: this.groupDataSource,
177
+ isGroupData: this.isGroupData,
178
+ showSecondaryInSearchOnly: this.showSecondaryInSearchOnly,
179
+ parameters: this.parameters,
180
+ matchPosition: this.matchPosition,
181
+ listType: this.listType,
182
+ maxResultsDisplay: this.maxResultsDisplay || '100',
183
+ columns: preProcessColumns(columns),
184
+ groupColumnsConfig: preProcessColumns(this.groupColumnsConfig)
185
+ };
186
+
187
+ const groupsDisplayFieldMeta = this.listType !== 'associated' ? getDisplayFieldsMetaData(dataConfig.groupColumnsConfig) : null;
188
+
189
+ this.itemsTreeBaseData = getGroupDataForItemsTree(this.groupDataSource, groupsDisplayFieldMeta, this.showSecondaryInSearchOnly) || [];
190
+
191
+ this.itemsTree = this.isGroupData ? getGroupDataForItemsTree(this.groupDataSource, groupsDisplayFieldMeta, this.showSecondaryInSearchOnly) : [];
192
+
193
+ this.displayFieldMeta = this.listType !== 'associated' ? getDisplayFieldsMetaData(dataConfig.columns) : null;
194
+
195
+ this.listActions = this.pConn$.getListActions();
196
+ this.pConn$.setReferenceList(this.selectionList);
197
+
198
+ if (this.configProps$.visibility != null) {
199
+ this.bVisible$ = this.utils.getBooleanValue(this.configProps$.visibility);
200
+ }
201
+
202
+ // disabled
203
+ if (this.configProps$.disabled != undefined) {
204
+ this.bDisabled$ = this.utils.getBooleanValue(this.configProps$.disabled);
205
+ }
206
+
207
+ if (this.bDisabled$) {
208
+ this.fieldControl.disable();
209
+ } else {
210
+ this.fieldControl.enable();
211
+ }
212
+
213
+ if (this.listType !== 'associated') {
214
+ PCore.getDataApi()
215
+ ?.init(dataConfig, contextName)
216
+ .then(async dataObj => {
217
+ this.dataApiObj = dataObj;
218
+ if (!this.isGroupData) {
219
+ this.getCaseListBasedOnParams(this.value$ ?? '', '', [...this.selectedItems], [...this.itemsTree]);
220
+ }
221
+ });
222
+ }
223
+ }
224
+
225
+ setPropertyValuesFromProps() {
226
+ this.label$ = this.configProps$.label;
227
+ this.placeholder = this.configProps$.placeholder || '';
228
+ this.listType = this.configProps$.listType ? this.configProps$.listType : '';
229
+ this.hideLabel = this.configProps$.hideLabel;
230
+ this.parameters = this.configProps$?.parameters ? this.configProps$?.parameters : {};
231
+ this.referenceList = this.configProps$?.referenceList;
232
+ this.selectionKey = this.configProps$?.selectionKey;
233
+ this.primaryField = this.configProps$?.primaryField;
234
+ this.initialCaseClass = this.configProps$?.initialCaseClass;
235
+ this.showSecondaryInSearchOnly = this.configProps$?.showSecondaryInSearchOnly ? this.configProps$?.showSecondaryInSearchOnly : false;
236
+ this.isGroupData = this.configProps$?.isGroupData ? this.configProps$.isGroupData : false;
237
+ this.referenceType = this.configProps$?.referenceType;
238
+ this.secondaryFields = this.configProps$?.secondaryFields;
239
+ this.groupDataSource = this.configProps$?.groupDataSource ? this.configProps$?.groupDataSource : [];
240
+ this.matchPosition = this.configProps$?.matchPosition ? this.configProps$?.matchPosition : 'contains';
241
+ this.maxResultsDisplay = this.configProps$?.maxResultsDisplay;
242
+ this.groupColumnsConfig = this.configProps$?.groupColumnsConfig ? this.configProps$?.groupColumnsConfig : [{}];
243
+ this.selectionList = this.configProps$?.selectionList;
244
+ this.value$ = this.configProps$?.value;
245
+ }
246
+
247
+ // main search function trigger
248
+ getCaseListBasedOnParams(searchText, group, selectedRows, currentItemsTree, isTriggeredFromSearch = false) {
249
+ if (this.referenceList && this.referenceList.length > 0) {
250
+ this.listActions.getSelectedRows(true).then(result => {
251
+ selectedRows =
252
+ result.length > 0
253
+ ? result.map(item => {
254
+ return {
255
+ id: item[this.selectionKey.startsWith('.') ? this.selectionKey.substring(1) : this.selectionKey],
256
+ primary: item[this.primaryField.startsWith('.') ? this.primaryField.substring(1) : this.primaryField]
257
+ };
258
+ })
259
+ : [];
260
+ this.selectedItems = selectedRows;
261
+
262
+ const initalItemsTree = isTriggeredFromSearch || !currentItemsTree ? [...this.itemsTreeBaseData] : [...currentItemsTree];
263
+
264
+ doSearch(
265
+ searchText,
266
+ group,
267
+ this.initialCaseClass,
268
+ this.displayFieldMeta,
269
+ this.dataApiObj,
270
+ initalItemsTree,
271
+ this.isGroupData,
272
+ this.showSecondaryInSearchOnly,
273
+ selectedRows || []
274
+ ).then(res => {
275
+ this.itemsTree = res || [];
276
+ if (this.trigger) {
277
+ this.trigger.openPanel();
278
+ }
279
+ });
280
+ });
281
+ }
282
+ }
283
+
284
+ fieldOnChange(event: Event) {
285
+ this.value$ = (event.target as HTMLInputElement).value;
286
+ this.getCaseListBasedOnParams(this.value$, '', [...this.selectedItems], [...this.itemsTree], true);
287
+ }
288
+
289
+ optionChanged(event: MatAutocompleteSelectedEvent) {
290
+ this.angularPConnectData.actions?.onChange(this, event);
291
+ }
292
+
293
+ optionClicked = (event: Event, data: any, trigger?: MatAutocompleteTrigger): void => {
294
+ event.stopPropagation();
295
+ this.toggleSelection(data, trigger);
296
+ };
297
+
298
+ toggleSelection = (data: any, trigger?: MatAutocompleteTrigger): void => {
299
+ data.selected = !data.selected;
300
+ this.trigger = trigger;
301
+ this.itemsTree.map((ele: any) => {
302
+ if (ele.id === data.id) {
303
+ ele.selected = data.selected;
304
+ }
305
+ return ele;
306
+ });
307
+
308
+ if (data.selected === true) {
309
+ this.selectedItems.push(data);
310
+ } else {
311
+ const index = this.selectedItems.findIndex(value => value.id === data.id);
312
+ this.selectedItems.splice(index, 1);
313
+ }
314
+
315
+ this.value$ = '';
316
+ // if this is a referenceList case
317
+ if (this.referenceList) this.setSelectedItemsForReferenceList(data);
318
+
319
+ this.getCaseListBasedOnParams(this.value$, '', [...this.selectedItems], [...this.itemsTree], true);
320
+ };
321
+
322
+ removeChip = (data: any): void => {
323
+ if (data) {
324
+ data = this.itemsTree.filter((ele: any) => {
325
+ return ele.id === data.id;
326
+ });
327
+ this.toggleSelection(data[0]);
328
+ }
329
+ };
330
+
331
+ setSelectedItemsForReferenceList(data: any) {
332
+ // Clear error messages if any
333
+ const propName = (this.pConn$.getStateProps() as any).selectionList;
334
+ this.pConn$.clearErrorMessages({
335
+ property: propName,
336
+ category: '',
337
+ context: ''
338
+ });
339
+ const { selected } = data;
340
+ if (selected) {
341
+ insertInstruction(this.pConn$, this.selectionList, this.selectionKey, this.primaryField, data);
342
+ } else {
343
+ deleteInstruction(this.pConn$, this.selectionList, this.selectionKey, data);
344
+ }
345
+ }
346
+
347
+ getErrorMessage() {
348
+ let errMessage = '';
349
+
350
+ // look for validation messages for json, pre-defined or just an error pushed from workitem (400)
351
+ if (this.fieldControl.hasError('message')) {
352
+ errMessage = this.angularPConnectData.validateMessage ?? '';
353
+ return errMessage;
354
+ }
355
+ if (this.fieldControl.hasError('required')) {
356
+ errMessage = 'You must enter a value';
357
+ } else if (this.fieldControl.errors) {
358
+ errMessage = this.fieldControl.errors.toString();
359
+ }
360
+
361
+ return errMessage;
362
+ }
363
+ }
@@ -0,0 +1,209 @@
1
+ import cloneDeep from 'lodash/cloneDeep';
2
+
3
+ export function setVisibilityForList(c11nEnv, visibility) {
4
+ const { selectionMode, selectionList, renderMode, referenceList } = c11nEnv.getComponentConfig();
5
+ // usecase:multiselect, fieldgroup, editable table
6
+ if ((selectionMode === PCore.getConstants().LIST_SELECTION_MODE.MULTI && selectionList) || (renderMode === 'Editable' && referenceList)) {
7
+ c11nEnv.getListActions().setVisibility(visibility);
8
+ }
9
+ }
10
+
11
+ function preProcessColumns(columns) {
12
+ return columns?.map(col => {
13
+ const tempColObj = { ...col };
14
+ tempColObj.value = col.value && col.value.startsWith('.') ? col.value.substring(1) : col.value;
15
+ if (tempColObj.setProperty) {
16
+ tempColObj.setProperty = col.setProperty && col.setProperty.startsWith('.') ? col.setProperty.substring(1) : col.setProperty;
17
+ }
18
+ return tempColObj;
19
+ });
20
+ }
21
+
22
+ function getDisplayFieldsMetaData(columns) {
23
+ const displayColumns = columns?.filter(col => col.display === 'true');
24
+ const metaDataObj: any = {
25
+ key: '',
26
+ primary: '',
27
+ secondary: []
28
+ };
29
+ const keyCol = columns?.filter(col => col.key === 'true');
30
+ metaDataObj.key = keyCol?.length > 0 ? keyCol[0].value : 'auto';
31
+ const itemsRecordsColumn = columns?.filter(col => col.itemsRecordsColumn === 'true');
32
+ if (itemsRecordsColumn?.length > 0) {
33
+ metaDataObj.itemsRecordsColumn = itemsRecordsColumn[0].value;
34
+ }
35
+ const itemsGroupKeyColumn = columns?.filter(col => col.itemsGroupKeyColumn === 'true');
36
+ if (itemsGroupKeyColumn?.length > 0) {
37
+ metaDataObj.itemsGroupKeyColumn = itemsGroupKeyColumn[0].value;
38
+ }
39
+ for (let index = 0; index < displayColumns?.length; index += 1) {
40
+ if (displayColumns[index].secondary === 'true') {
41
+ metaDataObj.secondary.push(displayColumns[index].value);
42
+ } else if (displayColumns[index].primary === 'true') {
43
+ metaDataObj.primary = displayColumns[index].value;
44
+ }
45
+ }
46
+ return metaDataObj;
47
+ }
48
+
49
+ function createSingleTreeObejct(entry, displayFieldMeta, showSecondaryData, selected) {
50
+ const secondaryArr: any = [];
51
+ displayFieldMeta.secondary.forEach(col => {
52
+ secondaryArr.push(entry[col]);
53
+ });
54
+ const isSelected = selected.some(item => item.id === entry[displayFieldMeta.key]);
55
+
56
+ return {
57
+ id: entry[displayFieldMeta.key],
58
+ primary: entry[displayFieldMeta.primary],
59
+ secondary: showSecondaryData ? secondaryArr : [],
60
+ selected: isSelected
61
+ };
62
+ }
63
+
64
+ function putItemsDataInItemsTree(listObjData, displayFieldMeta, itemsTree, showSecondaryInSearchOnly, selected) {
65
+ let newTreeItems = itemsTree.slice();
66
+ const showSecondaryData = !showSecondaryInSearchOnly;
67
+ for (const obj of listObjData) {
68
+ const items = obj[displayFieldMeta.itemsRecordsColumn].map(entry => createSingleTreeObejct(entry, displayFieldMeta, showSecondaryData, selected));
69
+
70
+ newTreeItems = newTreeItems.map(caseObject => {
71
+ if (caseObject.id === obj[displayFieldMeta.itemsGroupKeyColumn]) {
72
+ caseObject.items = [...items];
73
+ }
74
+ return caseObject;
75
+ });
76
+ }
77
+ return newTreeItems;
78
+ }
79
+
80
+ function prepareSearchResults(listObjData, displayFieldMeta) {
81
+ const searchResults: any = [];
82
+ for (const obj of listObjData) {
83
+ searchResults.push(...obj[displayFieldMeta.itemsRecordsColumn]);
84
+ }
85
+ return searchResults;
86
+ }
87
+
88
+ async function doSearch(
89
+ searchText,
90
+ clickedGroup,
91
+ initialCaseClass,
92
+ displayFieldMeta,
93
+ dataApiObj, // deep clone of the dataApiObj
94
+ itemsTree,
95
+ isGroupData,
96
+ showSecondaryInSearchOnly,
97
+ selected
98
+ ) {
99
+ let searchTextForUngroupedData = '';
100
+ if (dataApiObj) {
101
+ // creating dataApiObject in grouped data cases
102
+ if (isGroupData) {
103
+ dataApiObj = cloneDeep(dataApiObj);
104
+ dataApiObj.fetchedNQData = false;
105
+ dataApiObj.cache = {};
106
+
107
+ // if we have no search text and no group selected, return the original tree
108
+ if (searchText === '' && clickedGroup === '') {
109
+ return itemsTree;
110
+ }
111
+
112
+ // setting the inital search text & search classes in ApiObject
113
+ dataApiObj.parameters[Object.keys(dataApiObj.parameters)[1]] = searchText;
114
+ dataApiObj.parameters[Object.keys(dataApiObj.parameters)[0]] = initialCaseClass;
115
+
116
+ // if we have a selected group
117
+ if (clickedGroup) {
118
+ // check if the data for this group is already present and no search text
119
+ if (searchText === '') {
120
+ const containsData = itemsTree.find(item => item.id === clickedGroup);
121
+ // do not make API call when items of respective group are already fetched
122
+ if (containsData?.items?.length) return itemsTree;
123
+ }
124
+
125
+ dataApiObj.parameters[Object.keys(dataApiObj.parameters)[0]] = JSON.stringify([clickedGroup]);
126
+ }
127
+ } else {
128
+ searchTextForUngroupedData = searchText;
129
+ }
130
+
131
+ // search API call
132
+ const response = await dataApiObj.fetchData(searchTextForUngroupedData).catch(() => {
133
+ return itemsTree;
134
+ });
135
+
136
+ let listObjData = response.data;
137
+ let newItemsTree = [];
138
+ if (isGroupData) {
139
+ if (searchText) {
140
+ listObjData = prepareSearchResults(listObjData, displayFieldMeta);
141
+ } else {
142
+ newItemsTree = putItemsDataInItemsTree(listObjData, displayFieldMeta, itemsTree, showSecondaryInSearchOnly, selected);
143
+ return newItemsTree;
144
+ }
145
+ }
146
+ const showSecondaryData = showSecondaryInSearchOnly ? !!searchText : true;
147
+ if (listObjData !== undefined && listObjData.length > 0) {
148
+ newItemsTree = listObjData.map(entry => createSingleTreeObejct(entry, displayFieldMeta, showSecondaryData, selected));
149
+ }
150
+ return newItemsTree;
151
+ }
152
+
153
+ return itemsTree;
154
+ }
155
+
156
+ function setValuesToPropertyList(searchText, assocProp, items, columns, actions, updatePropertyInRedux = true) {
157
+ const setPropertyList = columns
158
+ ?.filter(col => col.setProperty)
159
+ .map(col => {
160
+ return {
161
+ source: col.value,
162
+ target: col.setProperty,
163
+ key: col.key,
164
+ primary: col.primary
165
+ };
166
+ });
167
+ const valueToSet: any = [];
168
+ if (setPropertyList.length > 0) {
169
+ setPropertyList.forEach(prop => {
170
+ items.forEach(item => {
171
+ if (prop.key === 'true' && item) {
172
+ valueToSet.push(item.id);
173
+ } else if (prop.primary === 'true' || !item) {
174
+ valueToSet.push(searchText);
175
+ }
176
+ });
177
+
178
+ if (updatePropertyInRedux) {
179
+ // BUG-666851 setting options so that the store values are replaced and not merged
180
+ const options = {
181
+ isArrayDeepMerge: false
182
+ };
183
+ if (prop.target === 'Associated property') {
184
+ actions.updateFieldValue(assocProp, valueToSet, options);
185
+ } else {
186
+ actions.updateFieldValue(`.${prop.target}`, valueToSet, options);
187
+ }
188
+ }
189
+ });
190
+ }
191
+ return valueToSet;
192
+ }
193
+
194
+ function getGroupDataForItemsTree(groupDataSource, groupsDisplayFieldMeta, showSecondaryInSearchOnly) {
195
+ return groupDataSource?.map(group => {
196
+ const secondaryArr: any = [];
197
+ groupsDisplayFieldMeta.secondary.forEach(col => {
198
+ secondaryArr.push(group[col]);
199
+ });
200
+ return {
201
+ id: group[groupsDisplayFieldMeta.key],
202
+ primary: group[groupsDisplayFieldMeta.primary],
203
+ secondary: showSecondaryInSearchOnly ? [] : secondaryArr,
204
+ items: []
205
+ };
206
+ });
207
+ }
208
+
209
+ export { preProcessColumns, getDisplayFieldsMetaData, doSearch, setValuesToPropertyList, getGroupDataForItemsTree };
@@ -1,5 +1,5 @@
1
1
  <div *ngIf="displayMode$; else noDisplayMode">
2
- <component-mapper *ngIf="bVisible$ !== false" name="FieldValueList" [props]="{ label$, value$, displayMode$ }"></component-mapper>
2
+ <component-mapper *ngIf="bVisible$ !== false" name="FieldValueList" [props]="{ label$, value$, displayMode$, isHtml$: true }"></component-mapper>
3
3
  </div>
4
4
  <ng-template #noDisplayMode>
5
5
  <div *ngIf="!bReadonly$; else noEdit">
@@ -12,6 +12,7 @@
12
12
  type="time"
13
13
  [value]="value$"
14
14
  [required]="bRequired$"
15
+ [attr.data-test-id]="testId"
15
16
  [formControl]="fieldControl"
16
17
  (change)="fieldOnChange($event)"
17
18
  (blur)="fieldOnBlur($event)"
@@ -36,6 +36,7 @@ export class TimeComponent implements OnInit, OnDestroy {
36
36
  bVisible$ = true;
37
37
  displayMode$?: string = '';
38
38
  controlName$: string;
39
+ testId = '';
39
40
  bHasForm$ = true;
40
41
  componentReference = '';
41
42
  helperText: string;
@@ -100,6 +101,7 @@ export class TimeComponent implements OnInit, OnDestroy {
100
101
  // moved this from ngOnInit() and call this from there instead...
101
102
  this.configProps$ = this.pConn$.resolveConfigProps(this.pConn$.getConfigProps()) as TimeProps;
102
103
 
104
+ this.testId = this.configProps$.testId;
103
105
  this.label$ = this.configProps$.label;
104
106
  this.displayMode$ = this.configProps$.displayMode;
105
107
 
@@ -12,6 +12,7 @@
12
12
  type="url"
13
13
  [value]="value$"
14
14
  [required]="bRequired$"
15
+ [attr.data-test-id]="testId"
15
16
  [formControl]="fieldControl"
16
17
  (change)="fieldOnChange($event)"
17
18
  (blur)="fieldOnBlur($event)"
@@ -36,6 +36,7 @@ export class UrlComponent implements OnInit, OnDestroy {
36
36
  bVisible$ = true;
37
37
  displayMode$?: string = '';
38
38
  controlName$: string;
39
+ testId = '';
39
40
  bHasForm$ = true;
40
41
  componentReference = '';
41
42
  helperText: string;
@@ -106,6 +107,7 @@ export class UrlComponent implements OnInit, OnDestroy {
106
107
  this.value$ = this.configProps$.value;
107
108
  }
108
109
 
110
+ this.testId = this.configProps$.testId;
109
111
  this.label$ = this.configProps$.label;
110
112
  this.displayMode$ = this.configProps$.displayMode;
111
113
  this.helperText = this.configProps$.helperText;
@@ -118,17 +118,18 @@ export class ViewContainerComponent implements OnInit, OnDestroy {
118
118
  /* NOTE: setContainerLimit use is temporary. It is a non-public, unsupported API. */
119
119
  PCore.getContainerUtils().setContainerLimit(`${APP.APP}/${name}`, limit);
120
120
  }
121
- }
122
121
 
123
- if (sessionStorage.getItem('hasViewContainer') == 'false') {
124
- // @ts-ignore - Property 'getMetadata' is private and only accessible within class
125
- if (this.pConn$.getMetadata().children) {
122
+ if (!PCore.checkIfSemanticURL()) {
126
123
  containerMgr.addContainerItem(this.dispatchObject);
127
124
  }
128
-
129
- sessionStorage.setItem('hasViewContainer', 'true');
130
125
  }
131
126
 
127
+ // if (sessionStorage.getItem('hasViewContainer') == 'false') {
128
+ // // @ts-ignore - Property 'getMetadata' is private and only accessible within class
129
+
130
+ // sessionStorage.setItem('hasViewContainer', 'true');
131
+ // }
132
+
132
133
  // cannot call checkAndUpdate becasue first time through, will call updateSelf and that is incorrect (causes issues).
133
134
  // however, need angularPConnect to be initialized with currentProps for future updates, so calling shouldComponentUpdate directly
134
135
  // without checking to update here in init, will initialize and this is correct
@@ -163,6 +163,7 @@ mat-horizontal-stepper {
163
163
  .psdk-horizontal-stepper-header-container {
164
164
  white-space: nowrap;
165
165
  display: flex;
166
+ flex-wrap: wrap;
166
167
  align-items: center;
167
168
  text-align: left;
168
169
  }
@@ -22,7 +22,7 @@
22
22
  *ngFor="let caseType of caseTypes$"
23
23
  (click)="navPanelCreateCaseType(caseType.pyClassName, caseType.pyFlowType)"
24
24
  >
25
- <span class="psdk-nav-button-span">{{ caseType.pyLabel }}</span>
25
+ <span class="psdk-nav-button-span">{{ localeUtils.getLocaleValue(caseType.pyLabel, '', localeReference) }}</span>
26
26
  </mat-list-item>
27
27
  </mat-list>
28
28
  </mat-list>
@@ -32,7 +32,7 @@
32
32
  <mat-list-item (click)="navPanelButtonClick(page)">
33
33
  <div class="flex-box">
34
34
  <img class="psdk-nav-svg-icon" src="{{ page.iconName }}" />
35
- <span class="psdk-nav-button-span">{{ localizedVal(page.pyLabel, localeCategory) }}</span>
35
+ <span class="psdk-nav-button-span">{{ localeUtils.getLocaleValue(page.pyLabel, '', localeReference) }}</span>
36
36
  </div>
37
37
  </mat-list-item>
38
38
  </mat-list>
@@ -48,7 +48,7 @@
48
48
  </mat-list-item>
49
49
  <mat-menu #menu="matMenu">
50
50
  <button mat-menu-item>Profile</button>
51
- <button mat-menu-item (click)="navPanelLogoutClick()">{{ localizedVal('Logoff', localeCategory) }}</button>
51
+ <button mat-menu-item (click)="navPanelLogoutClick()">{{ localizedVal('Log off', localeCategory) }}</button>
52
52
  </mat-menu>
53
53
  </mat-list>
54
54
  </div>