@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.
- package/lib/designSystemExtension/material-case-summary/material-case-summary.component.html +5 -2
- package/lib/designSystemExtension/material-case-summary/material-case-summary.component.ts +3 -1
- package/lib/designSystemExtension/material-vertical-tabs/material-vertical-tabs.component.html +1 -1
- package/lib/designSystemExtension/operator/operator.component.ts +6 -4
- package/lib/field/check-box/check-box.component.html +16 -15
- package/lib/field/check-box/check-box.component.scss +14 -1
- package/lib/field/check-box/check-box.component.ts +127 -44
- package/lib/field/currency/currency.component.html +4 -4
- package/lib/field/currency/currency.component.ts +31 -19
- package/lib/field/date-time/date-time.component.html +5 -5
- package/lib/field/date-time/date-time.component.ts +8 -39
- package/lib/field/decimal/decimal.component.html +13 -4
- package/lib/field/decimal/decimal.component.ts +41 -5
- package/lib/field/multiselect/multiselect.component.html +34 -0
- package/lib/field/multiselect/multiselect.component.scss +7 -0
- package/lib/field/multiselect/multiselect.component.spec.ts +21 -0
- package/lib/field/multiselect/multiselect.component.ts +363 -0
- package/lib/field/multiselect/utils.ts +209 -0
- package/lib/field/percentage/percentage.component.html +4 -3
- package/lib/field/percentage/percentage.component.ts +24 -5
- package/lib/field/user-reference/user-reference.component.html +50 -45
- package/lib/field/user-reference/user-reference.component.ts +33 -15
- package/lib/infra/Containers/flow-container/flow-container.component.ts +15 -9
- package/lib/infra/assignment/assignment.component.ts +30 -1
- package/lib/infra/multi-step/multi-step.component.html +1 -1
- package/lib/infra/navbar/navbar.component.html +4 -4
- package/lib/infra/navbar/navbar.component.ts +7 -3
- package/lib/template/case-summary/case-summary.component.ts +37 -3
- package/lib/template/case-view/case-view.component.html +1 -1
- package/lib/template/wss-nav-bar/wss-nav-bar.component.html +1 -1
- package/lib/template/wss-nav-bar/wss-nav-bar.component.ts +2 -1
- package/lib/widget/attachment/attachment.component.html +9 -1
- package/lib/widget/attachment/attachment.component.ts +4 -1
- package/lib/widget/case-history/case-history.component.ts +1 -1
- package/lib/widget/file-utility/file-utility.component.html +2 -2
- package/lib/widget/file-utility/file-utility.component.ts +13 -13
- package/lib/widget/list-utility/list-utility.component.html +1 -1
- package/lib/widget/todo/todo.component.html +3 -3
- 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>% </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
|
-
[
|
|
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
|
-
|
|
162
|
-
|
|
163
|
-
|
|
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="
|
|
3
|
-
<component-mapper name="
|
|
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
|
-
|
|
162
|
-
.invokeRestApi('getListData', { queryPayload } as any, '') // 3rd arg empty string until typedef marked correctly
|
|
163
|
-
|
|
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
|
-
|
|
171
|
-
|
|
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
|
|
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">{{
|
|
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('
|
|
51
|
+
<button mat-menu-item (click)="navPanelLogoutClick()">{{ localizedVal('Log off', localeCategory) }}</button>
|
|
52
52
|
</mat-menu>
|
|
53
53
|
</mat-list>
|
|
54
54
|
</div>
|