@pega/angular-sdk-overrides 0.23.7 → 0.24.2

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 (39) 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/material-vertical-tabs/material-vertical-tabs.component.html +1 -1
  4. package/lib/designSystemExtension/operator/operator.component.ts +6 -4
  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/currency/currency.component.html +4 -4
  9. package/lib/field/currency/currency.component.ts +31 -19
  10. package/lib/field/date-time/date-time.component.html +5 -5
  11. package/lib/field/date-time/date-time.component.ts +8 -39
  12. package/lib/field/decimal/decimal.component.html +13 -4
  13. package/lib/field/decimal/decimal.component.ts +41 -5
  14. package/lib/field/multiselect/multiselect.component.html +34 -0
  15. package/lib/field/multiselect/multiselect.component.scss +7 -0
  16. package/lib/field/multiselect/multiselect.component.spec.ts +21 -0
  17. package/lib/field/multiselect/multiselect.component.ts +363 -0
  18. package/lib/field/multiselect/utils.ts +209 -0
  19. package/lib/field/percentage/percentage.component.html +4 -3
  20. package/lib/field/percentage/percentage.component.ts +24 -5
  21. package/lib/field/user-reference/user-reference.component.html +50 -45
  22. package/lib/field/user-reference/user-reference.component.ts +33 -15
  23. package/lib/infra/Containers/flow-container/flow-container.component.ts +15 -9
  24. package/lib/infra/assignment/assignment.component.ts +30 -1
  25. package/lib/infra/multi-step/multi-step.component.html +1 -1
  26. package/lib/infra/navbar/navbar.component.html +4 -4
  27. package/lib/infra/navbar/navbar.component.ts +7 -3
  28. package/lib/template/case-summary/case-summary.component.ts +37 -3
  29. package/lib/template/case-view/case-view.component.html +1 -1
  30. package/lib/template/wss-nav-bar/wss-nav-bar.component.html +1 -1
  31. package/lib/template/wss-nav-bar/wss-nav-bar.component.ts +2 -1
  32. package/lib/widget/attachment/attachment.component.html +9 -1
  33. package/lib/widget/attachment/attachment.component.ts +4 -1
  34. package/lib/widget/case-history/case-history.component.ts +1 -1
  35. package/lib/widget/file-utility/file-utility.component.html +2 -2
  36. package/lib/widget/file-utility/file-utility.component.ts +13 -13
  37. package/lib/widget/list-utility/list-utility.component.html +1 -1
  38. package/lib/widget/todo/todo.component.html +3 -3
  39. package/package.json +1 -1
@@ -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 };
@@ -6,13 +6,14 @@
6
6
  <div [formGroup]="formGroup$" *ngIf="bVisible$">
7
7
  <mat-form-field class="psdk-full-width" subscriptSizing="dynamic" [hintLabel]="helperText">
8
8
  <mat-label>{{ label$ }}</mat-label>
9
- <!-- <span matPrefix>% &nbsp;</span> -->
10
9
  <input
10
+ type="text"
11
11
  matInput
12
+ currencyMask
13
+ [options]="{ prefix: '', suffix: '%', thousands: currSep, decimal: currDec, align: 'left', nullable: true }"
12
14
  [placeholder]="placeholder"
13
- type="number"
14
15
  step=".01"
15
- [value]="value$"
16
+ [formControlName]="controlName$"
16
17
  [required]="bRequired$"
17
18
  [formControl]="fieldControl"
18
19
  [attr.data-test-id]="testId"
@@ -4,12 +4,17 @@ import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
4
4
  import { MatInputModule } from '@angular/material/input';
5
5
  import { MatFormFieldModule } from '@angular/material/form-field';
6
6
  import { interval } from 'rxjs';
7
+ import { NgxCurrencyDirective } from 'ngx-currency';
7
8
  import { AngularPConnectData, AngularPConnectService } from '@pega/angular-sdk-components';
8
9
  import { Utils } from '@pega/angular-sdk-components';
9
10
  import { ComponentMapperComponent } from '@pega/angular-sdk-components';
11
+ import { handleEvent } from '@pega/angular-sdk-components';
12
+ import { getCurrencyCharacters } from '@pega/angular-sdk-components';
10
13
  import { PConnFieldProps } from '@pega/angular-sdk-components';
11
14
 
12
15
  interface PercentageProps extends PConnFieldProps {
16
+ showGroupSeparators?: string;
17
+ decimalPrecision?: number;
13
18
  // If any, enter additional props that only exist on Percentage here
14
19
  }
15
20
 
@@ -18,7 +23,7 @@ interface PercentageProps extends PConnFieldProps {
18
23
  templateUrl: './percentage.component.html',
19
24
  styleUrls: ['./percentage.component.scss'],
20
25
  standalone: true,
21
- imports: [CommonModule, ReactiveFormsModule, MatFormFieldModule, MatInputModule, forwardRef(() => ComponentMapperComponent)]
26
+ imports: [CommonModule, ReactiveFormsModule, MatFormFieldModule, MatInputModule, NgxCurrencyDirective, forwardRef(() => ComponentMapperComponent)]
22
27
  })
23
28
  export class PercentageComponent implements OnInit, OnDestroy {
24
29
  @Input() pConn$: typeof PConnect;
@@ -41,7 +46,8 @@ export class PercentageComponent implements OnInit, OnDestroy {
41
46
  testId: string;
42
47
  helperText: string;
43
48
  placeholder: string;
44
-
49
+ currDec: string;
50
+ currSep: string;
45
51
  fieldControl = new FormControl<number | null>(null, null);
46
52
 
47
53
  constructor(
@@ -113,6 +119,11 @@ export class PercentageComponent implements OnInit, OnDestroy {
113
119
  }
114
120
  this.helperText = this.configProps$.helperText;
115
121
  this.placeholder = this.configProps$.placeholder || '';
122
+ const showGroupSeparators = this.configProps$.showGroupSeparators;
123
+
124
+ const theSymbols = getCurrencyCharacters('');
125
+ this.currDec = theSymbols.theDecimalIndicator || '2';
126
+ this.currSep = showGroupSeparators ? theSymbols.theDigitGroupSeparator : '';
116
127
 
117
128
  // timeout and detectChanges to avoid ExpressionChangedAfterItHasBeenCheckedError
118
129
  setTimeout(() => {
@@ -158,9 +169,17 @@ export class PercentageComponent implements OnInit, OnDestroy {
158
169
  }
159
170
 
160
171
  fieldOnBlur(event: any) {
161
- // PConnect wants to use eventHandler for onBlur
162
-
163
- this.angularPConnectData.actions?.onBlur(this, event);
172
+ const actionsApi = this.pConn$?.getActionsApi();
173
+ const propName = (this.pConn$?.getStateProps() as any).value;
174
+ let value = event?.target?.value;
175
+ value = value?.replace('%', '');
176
+ if (this.currSep === ',') {
177
+ value = value.replace(/,/g, '');
178
+ } else {
179
+ value = value?.replace(/\./g, '');
180
+ value = value?.replace(/,/g, '.');
181
+ }
182
+ handleEvent(actionsApi, 'changeNblur', propName, value);
164
183
  }
165
184
 
166
185
  getErrorMessage() {
@@ -1,48 +1,53 @@
1
1
  <div class="psdk-user-reference">
2
- <div *ngIf="type === 'operator'">
3
- <component-mapper name="Operator" [props]="{ pConn$ }"></component-mapper>
4
- </div>
5
- <div [formGroup]="formGroup$" *ngIf="type === 'dropdown'">
6
- <mat-form-field class="psdk-full-width" subscriptSizing="dynamic" [hintLabel]="helperText">
7
- <mat-select
8
- [value]="value$"
9
- [required]="bRequired$"
10
- [formControl]="fieldControl"
11
- [attr.data-test-id]="testId"
12
- (selectionChange)="fieldOnChange($event)"
13
- >
14
- <mat-option *ngFor="let opt of options$" [value]="opt.key">
15
- {{ opt.value }}
16
- </mat-option>
17
- </mat-select>
18
- <mat-label>{{ label$ }}</mat-label>
19
- <mat-error *ngIf="fieldControl.invalid">
20
- {{ getErrorMessage() }}
21
- </mat-error>
22
- </mat-form-field>
23
- </div>
24
- <div [formGroup]="formGroup$" *ngIf="type === 'searchbox'">
25
- <mat-form-field class="psdk-full-width" subscriptSizing="dynamic" [hintLabel]="helperText">
26
- <mat-label>{{ label$ }}</mat-label>
27
- <input
28
- matInput
29
- [placeholder]="placeholder"
30
- [formControl]="fieldControl"
31
- [value]="value$"
32
- [required]="bRequired$"
33
- [matAutocomplete]="auto"
34
- [attr.data-test-id]="testId"
35
- (change)="fieldOnChange($event)"
36
- (blur)="fieldOnBlur($event)"
37
- />
38
- <mat-autocomplete #auto="matAutocomplete">
39
- <mat-option *ngFor="let opt of options$" [value]="opt.value">
40
- <span>{{ opt.value }}</span>
41
- </mat-option>
42
- </mat-autocomplete>
43
- <mat-error *ngIf="fieldControl.invalid">
44
- {{ getErrorMessage() }}
45
- </mat-error>
46
- </mat-form-field>
2
+ <div *ngIf="displayMode$; else noDisplayMode">
3
+ <component-mapper name="FieldValueList" [props]="{ label$, value$, displayMode$ }"></component-mapper>
47
4
  </div>
5
+ <ng-template #noDisplayMode>
6
+ <div *ngIf="type === 'operator'">
7
+ <component-mapper name="Operator" [props]="{ pConn$ }"></component-mapper>
8
+ </div>
9
+ <div [formGroup]="formGroup$" *ngIf="type === 'dropdown'">
10
+ <mat-form-field class="psdk-full-width" subscriptSizing="dynamic" [hintLabel]="helperText">
11
+ <mat-select
12
+ [value]="value$"
13
+ [required]="bRequired$"
14
+ [formControl]="fieldControl"
15
+ [attr.data-test-id]="testId"
16
+ (selectionChange)="fieldOnChange($event)"
17
+ >
18
+ <mat-option *ngFor="let opt of options$" [value]="opt.key">
19
+ {{ opt.value }}
20
+ </mat-option>
21
+ </mat-select>
22
+ <mat-label>{{ label$ }}</mat-label>
23
+ <mat-error *ngIf="fieldControl.invalid">
24
+ {{ getErrorMessage() }}
25
+ </mat-error>
26
+ </mat-form-field>
27
+ </div>
28
+ <div [formGroup]="formGroup$" *ngIf="type === 'searchbox'">
29
+ <mat-form-field class="psdk-full-width" subscriptSizing="dynamic" [hintLabel]="helperText">
30
+ <mat-label>{{ label$ }}</mat-label>
31
+ <input
32
+ matInput
33
+ [placeholder]="placeholder"
34
+ [formControl]="fieldControl"
35
+ [value]="value$"
36
+ [required]="bRequired$"
37
+ [matAutocomplete]="auto"
38
+ [attr.data-test-id]="testId"
39
+ (change)="fieldOnChange($event)"
40
+ (blur)="fieldOnBlur($event)"
41
+ />
42
+ <mat-autocomplete #auto="matAutocomplete">
43
+ <mat-option *ngFor="let opt of filteredOptions | async" [value]="opt.value">
44
+ <span>{{ opt.value }}</span>
45
+ </mat-option>
46
+ </mat-autocomplete>
47
+ <mat-error *ngIf="fieldControl.invalid">
48
+ {{ getErrorMessage() }}
49
+ </mat-error>
50
+ </mat-form-field>
51
+ </div>
52
+ </ng-template>
48
53
  </div>
@@ -10,6 +10,7 @@ import { AngularPConnectData, AngularPConnectService } from '@pega/angular-sdk-c
10
10
  import { Utils } from '@pega/angular-sdk-components';
11
11
  import { ComponentMapperComponent } from '@pega/angular-sdk-components';
12
12
  import { PConnFieldProps } from '@pega/angular-sdk-components';
13
+ import { map, Observable, startWith } from 'rxjs';
13
14
 
14
15
  const OPERATORS_DP = 'D_pyGetOperatorsForCurrentApplication';
15
16
  const DROPDOWN_LIST = 'Drop-down list';
@@ -57,6 +58,9 @@ export class UserReferenceComponent implements OnInit, OnDestroy {
57
58
  testId: string;
58
59
  helperText: string;
59
60
  placeholder: string;
61
+ displayMode$?: string;
62
+ filteredOptions: Observable<any[]>;
63
+ filterValue = '';
60
64
 
61
65
  fieldControl = new FormControl('', null);
62
66
 
@@ -65,19 +69,24 @@ export class UserReferenceComponent implements OnInit, OnDestroy {
65
69
  private utils: Utils
66
70
  ) {}
67
71
 
68
- ngOnInit(): void {
72
+ async ngOnInit(): Promise<void> {
69
73
  // First thing in initialization is registering and subscribing to the AngularPConnect service
70
74
  this.angularPConnectData = this.angularPConnect.registerAndSubscribeComponent(this, this.onStateChange);
71
75
 
72
76
  this.controlName$ = this.angularPConnect.getComponentID(this);
73
77
 
74
- this.checkAndUpdate();
78
+ await this.checkAndUpdate();
75
79
 
76
80
  if (this.formGroup$) {
77
81
  // add control to formGroup
78
82
  this.formGroup$.addControl(this.controlName$, this.fieldControl);
79
83
  this.fieldControl.setValue(this.value$);
80
84
  }
85
+
86
+ this.filteredOptions = this.fieldControl.valueChanges.pipe(
87
+ startWith(''),
88
+ map(value => this._filter(value || ''))
89
+ );
81
90
  }
82
91
 
83
92
  ngOnDestroy() {
@@ -105,32 +114,38 @@ export class UserReferenceComponent implements OnInit, OnDestroy {
105
114
  }
106
115
 
107
116
  // Callback passed when subscribing to store change
108
- onStateChange() {
109
- this.checkAndUpdate();
117
+ async onStateChange() {
118
+ await this.checkAndUpdate();
119
+ }
120
+
121
+ private _filter(value: string): string[] {
122
+ const filterVal = (value || this.filterValue).toLowerCase();
123
+ return this.options$?.filter(option => option.value?.toLowerCase().includes(filterVal));
110
124
  }
111
125
 
112
- checkAndUpdate() {
126
+ async checkAndUpdate() {
113
127
  // Should always check the bridge to see if the component should
114
128
  // update itself (re-render)
115
129
  const bUpdateSelf = this.angularPConnect.shouldComponentUpdate(this);
116
130
 
117
131
  // ONLY call updateSelf when the component should update
118
132
  if (bUpdateSelf) {
119
- this.updateSelf();
133
+ await this.updateSelf();
120
134
  }
121
135
  }
122
136
 
123
- updateSelf() {
137
+ async updateSelf() {
124
138
  const props = this.pConn$.getConfigProps() as UserReferenceProps;
125
139
  this.testId = props.testId;
126
140
 
127
- const { label, displayAs, value, showAsFormattedText, helperText, placeholder } = props;
141
+ const { label, displayAs, value, showAsFormattedText, helperText, placeholder, displayMode } = props;
128
142
 
129
143
  this.label$ = label;
130
144
  this.showAsFormattedText$ = showAsFormattedText;
131
145
  this.displayAs$ = displayAs;
132
146
  this.helperText = helperText;
133
147
  this.placeholder = placeholder || '';
148
+ this.displayMode$ = displayMode;
134
149
 
135
150
  const { readOnly, required } = props;
136
151
  [this.bReadonly$, this.bRequired$] = [readOnly, required].map(prop => prop === true || (typeof prop === 'string' && prop === 'true'));
@@ -158,18 +173,18 @@ export class UserReferenceComponent implements OnInit, OnDestroy {
158
173
  const queryPayload = {
159
174
  dataViewName: OPERATORS_DP
160
175
  };
161
- PCore.getRestClient()
162
- .invokeRestApi('getListData', { queryPayload } as any, '') // 3rd arg empty string until typedef marked correctly
163
- .then((resp: any) => {
176
+ try {
177
+ const resp: any = await PCore.getRestClient().invokeRestApi('getListData', { queryPayload } as any, ''); // 3rd arg empty string until typedef marked correctly
178
+ if (resp?.data) {
164
179
  const ddDataSource = resp.data.data.map(listItem => ({
165
180
  key: listItem.pyUserIdentifier,
166
181
  value: listItem.pyUserName
167
182
  }));
168
183
  this.options$ = ddDataSource;
169
- })
170
- .catch(err => {
171
- console.log(err);
172
- });
184
+ }
185
+ } catch (error) {
186
+ console.log(error);
187
+ }
173
188
  }
174
189
  }
175
190
 
@@ -177,6 +192,9 @@ export class UserReferenceComponent implements OnInit, OnDestroy {
177
192
  if (event?.value === 'Select') {
178
193
  event.value = '';
179
194
  }
195
+ if (event?.target) {
196
+ this.filterValue = (event.target as HTMLInputElement).value;
197
+ }
180
198
  this.angularPConnectData.actions?.onChange(this, event);
181
199
  }
182
200
 
@@ -274,24 +274,30 @@ export class FlowContainerComponent implements OnInit, OnDestroy {
274
274
  hasAssignments() {
275
275
  let hasAssignments = false;
276
276
  // @ts-ignore - second parameter pageReference for getValue method should be optional
277
- const assignmentsList = this.pConn$.getValue(this.pCoreConstants.CASE_INFO.D_CASE_ASSIGNMENTS_RESULTS);
278
- const thisOperator = PCore.getEnvironmentInfo().getOperatorIdentifier();
277
+ const assignmentsList: any[] = this.pConn$.getValue(this.pCoreConstants.CASE_INFO.D_CASE_ASSIGNMENTS_RESULTS);
278
+ // const thisOperator = PCore.getEnvironmentInfo().getOperatorIdentifier();
279
279
  // 8.7 includes assignments in Assignments List that may be assigned to
280
280
  // a different operator. So, see if there are any assignments for
281
281
  // the current operator
282
+ const isEmbedded = window.location.href.includes('embedded');
282
283
  let bAssignmentsForThisOperator = false;
283
284
 
285
+ if (isEmbedded) {
286
+ const thisOperator = PCore.getEnvironmentInfo().getOperatorIdentifier();
287
+ for (const assignment of assignmentsList) {
288
+ if (assignment.assigneeInfo.ID === thisOperator) {
289
+ bAssignmentsForThisOperator = true;
290
+ }
291
+ }
292
+ } else {
293
+ bAssignmentsForThisOperator = true;
294
+ }
295
+
284
296
  // Bail if there is no assignmentsList
285
297
  if (!assignmentsList) {
286
298
  return hasAssignments;
287
299
  }
288
300
 
289
- for (const assignment of assignmentsList) {
290
- if ((assignment as any).assigneeInfo.ID === thisOperator) {
291
- bAssignmentsForThisOperator = true;
292
- }
293
- }
294
-
295
301
  const hasChildCaseAssignments = this.hasChildCaseAssignments();
296
302
 
297
303
  if (bAssignmentsForThisOperator || hasChildCaseAssignments || this.isCaseWideLocalAction()) {
@@ -469,7 +475,7 @@ export class FlowContainerComponent implements OnInit, OnDestroy {
469
475
  PCore.getPubSubUtils().publish('assignmentFinished');
470
476
 
471
477
  this.psService.sendMessage(false);
472
- } else if (this.bHasCaseMessages$) {
478
+ } else {
473
479
  this.bHasCaseMessages$ = false;
474
480
  this.bShowConfirm = false;
475
481
  }
@@ -60,6 +60,8 @@ export class AssignmentComponent implements OnInit, OnDestroy, OnChanges {
60
60
  cancelAssignment: any;
61
61
  cancelCreateStageAssignment: any;
62
62
  showPage: any;
63
+ approveCase: any;
64
+ rejectCase: any;
63
65
 
64
66
  // itemKey: string = ""; // JA - this is what Nebula/Constellation uses to pass to finishAssignment, navigateToStep
65
67
 
@@ -205,6 +207,8 @@ export class AssignmentComponent implements OnInit, OnDestroy, OnChanges {
205
207
  this.showPage = actionsAPI.showPage.bind(actionsAPI);
206
208
 
207
209
  this.cancelCreateStageAssignment = actionsAPI.cancelCreateStageAssignment.bind(actionsAPI);
210
+ this.approveCase = actionsAPI.approveCase?.bind(actionsAPI);
211
+ this.rejectCase = actionsAPI.rejectCase?.bind(actionsAPI);
208
212
 
209
213
  this.createButtons();
210
214
  }
@@ -411,11 +415,23 @@ export class AssignmentComponent implements OnInit, OnDestroy, OnChanges {
411
415
  }
412
416
  break;
413
417
 
418
+ case 'rejectCase': {
419
+ const rejectPromise = this.rejectCase(this.itemKey$);
420
+
421
+ rejectPromise
422
+ .then(() => {})
423
+ .catch(() => {
424
+ this.psService.sendMessage(false);
425
+ this.snackBar.open(`${this.localizedVal('Rejection failed!', this.localeCategory)}`, 'Ok');
426
+ });
427
+
428
+ break;
429
+ }
430
+
414
431
  default:
415
432
  break;
416
433
  }
417
434
  } else if (sButtonType == 'primary') {
418
- // eslint-disable-next-line sonarjs/no-small-switch
419
435
  switch (sAction) {
420
436
  case 'finishAssignment':
421
437
  this.erService.sendMessage('publish', '');
@@ -437,6 +453,19 @@ export class AssignmentComponent implements OnInit, OnDestroy, OnChanges {
437
453
  this.erService.sendMessage('show', this.localizedVal('Please fix errors on form.', this.localeCategory));
438
454
  }
439
455
  break;
456
+
457
+ case 'approveCase': {
458
+ const approvePromise = this.approveCase(this.itemKey$);
459
+
460
+ approvePromise
461
+ .then(() => {})
462
+ .catch(() => {
463
+ this.psService.sendMessage(false);
464
+ this.snackBar.open(`${this.localizedVal('Approve failed!', this.localeCategory)}`, 'Ok');
465
+ });
466
+
467
+ break;
468
+ }
440
469
  default:
441
470
  break;
442
471
  }
@@ -54,7 +54,7 @@
54
54
  <span>{{ i + 1 }}</span>
55
55
  </div>
56
56
  </div>
57
- <div class="{{ _getHLabelClass(mainStep.visited_status) }}">
57
+ <div id="multi-step-label" class="{{ _getHLabelClass(mainStep.visited_status) }}">
58
58
  <div class="psdk-horizontal-step-text-label">
59
59
  {{ mainStep.name }}
60
60
  </div>
@@ -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,14 +32,14 @@
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>
39
39
  </div>
40
40
  <div class="psdk-nav-divider"></div>
41
41
  <div>
42
- <mat-list>
42
+ <mat-list id="profile">
43
43
  <mat-list-item [matMenuTriggerFor]="menu" class="psdk-profile-list-item">
44
44
  <div class="flex-box">
45
45
  <div class="psdk-nav-oper-avatar">{{ portalOperatorInitials$ }}</div>
@@ -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>