@pega/angular-sdk-overrides 25.1.13 → 26.1.10
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/alert/alert.component.html +4 -1
- package/lib/designSystemExtension/alert/alert.component.scss +9 -10
- package/lib/designSystemExtension/alert/alert.component.ts +6 -2
- package/lib/designSystemExtension/field-group/field-group.component.ts +11 -3
- package/lib/designSystemExtension/material-case-summary/material-case-summary.component.html +51 -36
- package/lib/designSystemExtension/material-case-summary/material-case-summary.component.scss +12 -0
- package/lib/designSystemExtension/material-case-summary/material-case-summary.component.ts +11 -0
- package/lib/designSystemExtension/operator/operator.component.html +5 -3
- package/lib/designSystemExtension/operator/operator.component.scss +7 -0
- package/lib/designSystemExtension/operator/operator.component.ts +2 -1
- package/lib/designSystemExtension/rich-text-editor/rich-text-editor.component.html +100 -10
- package/lib/designSystemExtension/rich-text-editor/rich-text-editor.component.scss +141 -1
- package/lib/designSystemExtension/rich-text-editor/rich-text-editor.component.spec.ts +1 -1
- package/lib/designSystemExtension/rich-text-editor/rich-text-editor.component.ts +240 -72
- package/lib/field/auto-complete/auto-complete.component.html +46 -5
- package/lib/field/auto-complete/auto-complete.component.scss +92 -0
- package/lib/field/auto-complete/auto-complete.component.ts +350 -23
- package/lib/field/cancel-alert/cancel-alert.component.ts +38 -15
- package/lib/field/check-box/check-box.component.html +8 -6
- package/lib/field/check-box/check-box.component.ts +9 -2
- package/lib/field/currency/currency.component.html +2 -1
- package/lib/field/currency/currency.component.ts +10 -1
- package/lib/field/date/date.component.html +2 -1
- package/lib/field/date/date.component.ts +2 -0
- package/lib/field/date-time/date-time.component.html +2 -1
- package/lib/field/date-time/date-time.component.scss +46 -40
- package/lib/field/date-time/date-time.component.ts +29 -0
- package/lib/field/decimal/decimal.component.html +2 -1
- package/lib/field/decimal/decimal.component.ts +2 -0
- package/lib/field/dropdown/dropdown.component.html +4 -1
- package/lib/field/dropdown/dropdown.component.ts +18 -19
- package/lib/field/email/email.component.html +2 -1
- package/lib/field/email/email.component.ts +2 -2
- package/lib/field/embedded-data-multi/embedded-data-multi.component.html +3 -0
- package/lib/field/embedded-data-multi/embedded-data-multi.component.scss +0 -0
- package/lib/field/embedded-data-multi/embedded-data-multi.component.ts +173 -0
- package/lib/field/field.base.ts +27 -1
- package/lib/field/group/group.component.html +1 -1
- package/lib/field/group/group.component.ts +15 -5
- package/lib/field/integer/integer.component.html +2 -1
- package/lib/field/integer/integer.component.ts +4 -2
- package/lib/field/location/location.component.html +2 -1
- package/lib/field/location/location.component.ts +3 -1
- package/lib/field/multiselect/multiselect.component.html +1 -1
- package/lib/field/multiselect/multiselect.component.ts +23 -4
- package/lib/field/multiselect/utils.ts +5 -3
- package/lib/field/object-reference/object-reference.component.html +30 -15
- package/lib/field/object-reference/object-reference.component.ts +818 -94
- package/lib/field/percentage/percentage.component.html +2 -1
- package/lib/field/percentage/percentage.component.ts +10 -1
- package/lib/field/phone/phone.component.html +2 -1
- package/lib/field/phone/phone.component.ts +2 -1
- package/lib/field/radio-buttons/radio-buttons.component.html +2 -1
- package/lib/field/radio-buttons/radio-buttons.component.ts +10 -1
- package/lib/field/rich-text/rich-text.component.scss +1 -166
- package/lib/field/rich-text/rich-text.component.spec.ts +1 -1
- package/lib/field/rich-text/rich-text.component.ts +1 -1
- package/lib/field/selectable-card/selectable-card.component.html +1 -0
- package/lib/field/selectable-card/selectable-card.component.ts +31 -16
- package/lib/field/semantic-link/semantic-link.component.html +1 -1
- package/lib/field/semantic-link/semantic-link.component.scss +4 -0
- package/lib/field/semantic-link/semantic-link.component.ts +13 -7
- package/lib/field/text-area/text-area.component.html +2 -1
- package/lib/field/text-area/text-area.component.ts +2 -1
- package/lib/field/text-input/text-input.component.html +2 -1
- package/lib/field/text-input/text-input.component.ts +2 -1
- package/lib/field/time/time.component.html +2 -1
- package/lib/field/time/time.component.ts +2 -1
- package/lib/field/url/url.component.html +2 -1
- package/lib/field/url/url.component.ts +2 -1
- package/lib/field/user-reference/user-reference.component.html +4 -2
- package/lib/field/user-reference/user-reference.component.ts +11 -6
- package/lib/infra/Containers/flow-container/flow-container.component.html +1 -1
- package/lib/infra/Containers/flow-container/flow-container.component.ts +35 -46
- package/lib/infra/Containers/modal-view-container/data-view-action-buttons/data-view-action-buttons.component.html +12 -0
- package/lib/infra/Containers/modal-view-container/data-view-action-buttons/data-view-action-buttons.component.spec.ts +130 -0
- package/lib/infra/Containers/modal-view-container/data-view-action-buttons/data-view-action-buttons.component.ts +77 -0
- package/lib/infra/Containers/modal-view-container/modal-view-container.component.html +35 -8
- package/lib/infra/Containers/modal-view-container/modal-view-container.component.ts +185 -194
- package/lib/infra/Containers/view-container/view-container.component.ts +32 -35
- package/lib/infra/assignment/assignment.component.html +2 -1
- package/lib/infra/assignment/assignment.component.ts +42 -15
- package/lib/infra/defer-load/defer-load.component.ts +6 -3
- package/lib/infra/multi-step/multi-step.component.html +25 -33
- package/lib/infra/multi-step/multi-step.component.scss +67 -125
- package/lib/infra/multi-step/multi-step.component.ts +11 -0
- package/lib/infra/navbar/navbar.component.ts +33 -36
- package/lib/infra/reference/reference.component.ts +1 -2
- package/lib/infra/root-container/root-container.component.ts +33 -38
- package/lib/infra/view/view.component.ts +21 -40
- package/lib/template/advanced-search/advanced-search.component.ts +0 -1
- package/lib/template/advanced-search/search-groups/search-groups.component.ts +2 -3
- package/lib/template/app-shell/app-shell.component.ts +13 -13
- package/lib/template/base/details-template-base.ts +41 -14
- package/lib/template/case-summary/case-summary.component.ts +15 -1
- package/lib/template/case-view/case-view.component.html +13 -1
- package/lib/template/case-view/case-view.component.spec.ts +119 -10
- package/lib/template/case-view/case-view.component.ts +52 -3
- package/lib/template/data-reference/data-reference.component.ts +2 -4
- package/lib/template/data-reference/search-form/search-form.component.html +1 -1
- package/lib/template/data-reference/search-form/search-form.component.ts +9 -1
- package/lib/template/data-reference/search-form/tabsData.ts +0 -1
- package/lib/template/default-form/default-form.component.html +19 -3
- package/lib/template/default-form/default-form.component.ts +13 -3
- package/lib/template/details/details.component.html +23 -3
- package/lib/template/details/details.component.scss +9 -2
- package/lib/template/details/details.component.ts +3 -70
- package/lib/template/details-narrow-wide/details-narrow-wide.component.html +21 -2
- package/lib/template/details-narrow-wide/details-narrow-wide.component.scss +8 -1
- package/lib/template/details-narrow-wide/details-narrow-wide.component.ts +3 -39
- package/lib/template/details-one-column/details-one-column.component.html +23 -1
- package/lib/template/details-one-column/details-one-column.component.scss +14 -0
- package/lib/template/details-one-column/details-one-column.component.ts +3 -40
- package/lib/template/details-three-column/details-three-column.component.html +21 -2
- package/lib/template/details-three-column/details-three-column.component.scss +8 -1
- package/lib/template/details-three-column/details-three-column.component.ts +3 -48
- package/lib/template/details-two-column/details-two-column.component.html +21 -2
- package/lib/template/details-two-column/details-two-column.component.scss +8 -1
- package/lib/template/details-two-column/details-two-column.component.ts +3 -46
- package/lib/template/details-wide-narrow/details-wide-narrow.component.html +21 -2
- package/lib/template/details-wide-narrow/details-wide-narrow.component.scss +8 -1
- package/lib/template/details-wide-narrow/details-wide-narrow.component.ts +3 -43
- package/lib/template/field-group-template/field-group-template.component.ts +19 -6
- package/lib/template/field-value-list/field-value-list.component.scss +17 -0
- package/lib/template/list-view/list-view.component.ts +47 -11
- package/lib/template/self-service-case-view/self-service-case-view.component.html +13 -1
- package/lib/template/self-service-case-view/self-service-case-view.component.spec.ts +96 -11
- package/lib/template/self-service-case-view/self-service-case-view.component.ts +52 -3
- package/lib/template/simple-table/simple-table.component.ts +6 -0
- package/lib/template/simple-table-manual/helpers.ts +84 -16
- package/lib/template/simple-table-manual/simple-table-manual.component.html +30 -14
- package/lib/template/simple-table-manual/simple-table-manual.component.scss +8 -2
- package/lib/template/simple-table-manual/simple-table-manual.component.ts +131 -43
- package/lib/template/single-reference-readonly/single-reference-readonly.component.html +0 -0
- package/lib/template/single-reference-readonly/single-reference-readonly.component.scss +2 -3
- package/lib/template/single-reference-readonly/single-reference-readonly.component.ts +7 -8
- package/lib/template/wss-nav-bar/wss-nav-bar.component.ts +19 -21
- package/lib/widget/attachment/AttachmentUtils.ts +19 -11
- package/lib/widget/attachment/attachment.component.html +16 -6
- package/lib/widget/attachment/attachment.component.ts +14 -4
- package/lib/widget/case-history/case-history.component.ts +6 -2
- package/lib/widget/feed-container/feed-container.component.ts +1 -199
- package/lib/widget/file-utility/file-utility.component.ts +26 -30
- package/lib/widget/todo/todo.component.ts +7 -2
- package/package.json +2 -2
- package/lib/designSystemExtension/material-details/material-details.component.html +0 -40
- package/lib/designSystemExtension/material-details/material-details.component.scss +0 -116
- package/lib/designSystemExtension/material-details/material-details.component.spec.ts +0 -24
- package/lib/designSystemExtension/material-details/material-details.component.ts +0 -31
- package/lib/designSystemExtension/material-details-fields/material-details-fields.component.html +0 -29
- package/lib/designSystemExtension/material-details-fields/material-details-fields.component.scss +0 -34
- package/lib/designSystemExtension/material-details-fields/material-details-fields.component.spec.ts +0 -22
- package/lib/designSystemExtension/material-details-fields/material-details-fields.component.ts +0 -37
|
@@ -9,6 +9,7 @@ import { MatFormFieldModule } from '@angular/material/form-field';
|
|
|
9
9
|
import { AngularPConnectData, AngularPConnectService } from '@pega/angular-sdk-components';
|
|
10
10
|
import { Utils } from '@pega/angular-sdk-components';
|
|
11
11
|
import { ComponentMapperComponent } from '@pega/angular-sdk-components';
|
|
12
|
+
import { FieldWarningDirective } from '@pega/angular-sdk-components';
|
|
12
13
|
import { PConnFieldProps } from '@pega/angular-sdk-components';
|
|
13
14
|
import { map, Observable, startWith } from 'rxjs';
|
|
14
15
|
import { handleEvent } from '@pega/angular-sdk-components';
|
|
@@ -38,6 +39,7 @@ interface UserReferenceProps extends Omit<PConnFieldProps, 'value'> {
|
|
|
38
39
|
MatOptionModule,
|
|
39
40
|
MatInputModule,
|
|
40
41
|
MatAutocompleteModule,
|
|
42
|
+
FieldWarningDirective,
|
|
41
43
|
forwardRef(() => ComponentMapperComponent)
|
|
42
44
|
]
|
|
43
45
|
})
|
|
@@ -54,6 +56,7 @@ export class UserReferenceComponent implements OnInit, OnDestroy {
|
|
|
54
56
|
options$: any;
|
|
55
57
|
bReadonly$: boolean;
|
|
56
58
|
bRequired$: boolean;
|
|
59
|
+
bFieldMessageVisible$ = false;
|
|
57
60
|
showAsFormattedText$?: boolean;
|
|
58
61
|
displayAs$?: string;
|
|
59
62
|
testId: string;
|
|
@@ -158,12 +161,17 @@ export class UserReferenceComponent implements OnInit, OnDestroy {
|
|
|
158
161
|
this.testId = props.testId;
|
|
159
162
|
this.onRecordChange = props?.onRecordChange;
|
|
160
163
|
|
|
161
|
-
const { label, displayAs, value, showAsFormattedText, helperText, placeholder, displayMode } = props;
|
|
164
|
+
const { label, displayAs, value, showAsFormattedText, helperText, placeholder, displayMode, messageConfig = {}, showFieldMessage } = props;
|
|
165
|
+
const { readOnly, required } = props;
|
|
166
|
+
[this.bReadonly$, this.bRequired$] = [readOnly, required].map(prop => prop === true || (typeof prop === 'string' && prop === 'true'));
|
|
167
|
+
|
|
168
|
+
const isMessageVisible = this.utils.getBooleanValue(messageConfig.visibility);
|
|
169
|
+
this.bFieldMessageVisible$ = this.utils.getBooleanValue(showFieldMessage) && isMessageVisible && !this.bReadonly$;
|
|
162
170
|
|
|
163
171
|
this.label$ = label;
|
|
164
172
|
this.showAsFormattedText$ = showAsFormattedText;
|
|
165
173
|
this.displayAs$ = displayAs;
|
|
166
|
-
this.helperText = helperText;
|
|
174
|
+
this.helperText = this.bFieldMessageVisible$ ? (messageConfig.content ?? '') : helperText;
|
|
167
175
|
this.placeholder = placeholder || '';
|
|
168
176
|
this.displayMode$ = displayMode;
|
|
169
177
|
|
|
@@ -173,9 +181,6 @@ export class UserReferenceComponent implements OnInit, OnDestroy {
|
|
|
173
181
|
this.value$ = value || '';
|
|
174
182
|
}
|
|
175
183
|
|
|
176
|
-
const { readOnly, required } = props;
|
|
177
|
-
[this.bReadonly$, this.bRequired$] = [readOnly, required].map(prop => prop === true || (typeof prop === 'string' && prop === 'true'));
|
|
178
|
-
|
|
179
184
|
this.actionsApi = this.pConn$.getActionsApi();
|
|
180
185
|
this.propName = this.pConn$.getStateProps().value;
|
|
181
186
|
|
|
@@ -229,7 +234,7 @@ export class UserReferenceComponent implements OnInit, OnDestroy {
|
|
|
229
234
|
let key = '';
|
|
230
235
|
if (event?.target?.value) {
|
|
231
236
|
const index = this.options$?.findIndex(element => element.value === event.target.value);
|
|
232
|
-
key = index > -1 ?
|
|
237
|
+
key = index > -1 ? this.options$[index].key : event.target.value;
|
|
233
238
|
}
|
|
234
239
|
const value = key;
|
|
235
240
|
handleEvent(this.actionsApi, 'changeNblur', this.propName, value);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<div style="text-align: left" class="psdk-flow-container-top">
|
|
2
2
|
<div *ngIf="!bShowConfirm">
|
|
3
3
|
<div *ngIf="!todo_showTodo$">
|
|
4
|
-
<h2 *ngIf="
|
|
4
|
+
<h2 *ngIf="containerName$">{{ containerName$ }}</h2>
|
|
5
5
|
<div *ngIf="banners.length">
|
|
6
6
|
<component-mapper name="AlertBanner" [props]="{ banners }"></component-mapper>
|
|
7
7
|
</div>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Component, OnInit, Input, ChangeDetectorRef,
|
|
1
|
+
import { Component, OnInit, Input, ChangeDetectorRef, forwardRef, OnDestroy, Injector } from '@angular/core';
|
|
2
2
|
import { CommonModule } from '@angular/common';
|
|
3
3
|
import { FormBuilder, FormGroup } from '@angular/forms';
|
|
4
4
|
import { MatCardModule } from '@angular/material/card';
|
|
@@ -75,7 +75,6 @@ export class FlowContainerComponent extends FlowContainerBaseComponent implement
|
|
|
75
75
|
private cdRef: ChangeDetectorRef,
|
|
76
76
|
private psService: ProgressSpinnerService,
|
|
77
77
|
private fb: FormBuilder,
|
|
78
|
-
private ngZone: NgZone,
|
|
79
78
|
private utils: Utils
|
|
80
79
|
) {
|
|
81
80
|
super(injector);
|
|
@@ -123,6 +122,7 @@ export class FlowContainerComponent extends FlowContainerBaseComponent implement
|
|
|
123
122
|
'clearBannerMessages',
|
|
124
123
|
() => {
|
|
125
124
|
this.banners = [];
|
|
125
|
+
this.cdRef.markForCheck();
|
|
126
126
|
},
|
|
127
127
|
'clearBannerMessages'
|
|
128
128
|
);
|
|
@@ -188,10 +188,9 @@ export class FlowContainerComponent extends FlowContainerBaseComponent implement
|
|
|
188
188
|
}
|
|
189
189
|
|
|
190
190
|
showPageMessages(completeProps: FlowContainerProps) {
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
});
|
|
191
|
+
const pageMessages = completeProps.pageMessages;
|
|
192
|
+
this.banners = [{ messages: pageMessages?.map(msg => this.localizedVal(msg.message, 'Messages')), variant: 'urgent' }];
|
|
193
|
+
this.cdRef.markForCheck();
|
|
195
194
|
}
|
|
196
195
|
|
|
197
196
|
getTodoVisibilty() {
|
|
@@ -279,12 +278,8 @@ export class FlowContainerComponent extends FlowContainerBaseComponent implement
|
|
|
279
278
|
|
|
280
279
|
// this.containerName$ = oWorkMeta["name"];
|
|
281
280
|
if (bLoadChildren && oWorkData) {
|
|
282
|
-
this.containerName$ = this.localizedVal(
|
|
283
|
-
|
|
284
|
-
undefined,
|
|
285
|
-
this.localeReference
|
|
286
|
-
);
|
|
287
|
-
this.isMultiStep = this.utils.getBooleanValue(oWorkData.caseInfo.assignments?.[0]?.isMultiStep);
|
|
281
|
+
this.containerName$ = this.localizedVal(this.getActiveViewLabel() || oWorkData.caseInfo.assignments?.[0].name, undefined, this.localeReference);
|
|
282
|
+
this.isMultiStep = this.utils.getBooleanValue(oWorkData.caseInfo.assignments?.[0].isMultiStep);
|
|
288
283
|
}
|
|
289
284
|
|
|
290
285
|
// turn off spinner
|
|
@@ -388,8 +383,7 @@ export class FlowContainerComponent extends FlowContainerBaseComponent implement
|
|
|
388
383
|
const { CASE_INFO: CASE_CONSTS } = PCore.getConstants();
|
|
389
384
|
|
|
390
385
|
setTimeout(() => {
|
|
391
|
-
|
|
392
|
-
/*
|
|
386
|
+
/*
|
|
393
387
|
*** renove this commmented out code when React/WC is updated
|
|
394
388
|
*** this code is replace with the call to "getToDoAssigments" function below
|
|
395
389
|
|
|
@@ -407,32 +401,32 @@ export class FlowContainerComponent extends FlowContainerBaseComponent implement
|
|
|
407
401
|
const caseActions = localPConn.getValue(CASE_CONSTS.CASE_INFO_ACTIONS);
|
|
408
402
|
*/
|
|
409
403
|
|
|
410
|
-
|
|
404
|
+
const todoAssignments = getToDoAssignments(this.pConn$);
|
|
411
405
|
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
406
|
+
if (todoAssignments && todoAssignments.length > 0) {
|
|
407
|
+
this.todo_caseInfoID$ = this.pConn$.getValue(CASE_CONSTS.CASE_INFO_ID);
|
|
408
|
+
this.todo_datasource$ = { source: todoAssignments };
|
|
409
|
+
}
|
|
416
410
|
|
|
417
|
-
|
|
418
|
-
|
|
411
|
+
/* remove this commented out code when update React/WC */
|
|
412
|
+
// let kid = this.pConn$.getChildren()[0];
|
|
419
413
|
|
|
420
|
-
|
|
421
|
-
|
|
414
|
+
// kid.getPConnect() can be a Reference component. So normalize it just in case
|
|
415
|
+
// let todoKid = kid.getPConnect().getChildren()[0];
|
|
422
416
|
|
|
423
|
-
|
|
417
|
+
// this.todo_pConn$ = todoKid.getPConnect();
|
|
424
418
|
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
419
|
+
/* code change here to note for React/WC */
|
|
420
|
+
// todo now needs pConn to open the work item on click "go"
|
|
421
|
+
this.todo_pConn$ = this.pConn$;
|
|
428
422
|
|
|
429
|
-
|
|
430
|
-
|
|
423
|
+
// still needs the context of the original work item
|
|
424
|
+
this.todo_context$ = localPConn.getContextName();
|
|
431
425
|
|
|
432
|
-
|
|
426
|
+
this.todo_showTodo$ = true;
|
|
433
427
|
|
|
434
|
-
|
|
435
|
-
|
|
428
|
+
this.psService.sendMessage(false);
|
|
429
|
+
this.cdRef.markForCheck();
|
|
436
430
|
});
|
|
437
431
|
}
|
|
438
432
|
|
|
@@ -537,24 +531,19 @@ export class FlowContainerComponent extends FlowContainerBaseComponent implement
|
|
|
537
531
|
const normalizedConfigObjectAsPConnect = normalizedConfigObject.getComponent();
|
|
538
532
|
|
|
539
533
|
// makes sure Angular tracks these changes
|
|
540
|
-
this.
|
|
541
|
-
|
|
542
|
-
// what comes back now in configObject is the children of the flowContainer
|
|
534
|
+
this.buildName$ = this.getBuildName();
|
|
535
|
+
// what comes back now in configObject is the children of the flowContainer
|
|
543
536
|
|
|
544
|
-
|
|
545
|
-
|
|
537
|
+
this.arChildren$ = [];
|
|
538
|
+
this.arChildren$.push(normalizedConfigObjectAsPConnect);
|
|
546
539
|
|
|
547
|
-
|
|
540
|
+
this.psService.sendMessage(false);
|
|
548
541
|
|
|
549
|
-
|
|
550
|
-
|
|
542
|
+
const oWorkItem = configObject.getPConnect();
|
|
543
|
+
const oWorkData: any = oWorkItem.getDataObject();
|
|
551
544
|
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
undefined,
|
|
555
|
-
this.localeReference
|
|
556
|
-
);
|
|
557
|
-
});
|
|
545
|
+
this.containerName$ = this.localizedVal(this.getActiveViewLabel() || oWorkData.caseInfo.assignments?.[0]?.name, undefined, this.localeReference);
|
|
546
|
+
this.cdRef.markForCheck();
|
|
558
547
|
}
|
|
559
548
|
|
|
560
549
|
getBuildName(): string {
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<mat-grid-list cols="2" rowHeight="4.25rem">
|
|
2
|
+
<mat-grid-tile>
|
|
3
|
+
<button mat-raised-button variant="contained" color="secondary" [disabled]="bDisabled$" (click)="onCancel()">
|
|
4
|
+
{{ localizedVal('Cancel', localeCategory) }}
|
|
5
|
+
</button>
|
|
6
|
+
</mat-grid-tile>
|
|
7
|
+
<mat-grid-tile>
|
|
8
|
+
<button mat-raised-button variant="contained" color="primary" [disabled]="bDisabled$" (click)="onSubmit()">
|
|
9
|
+
{{ localizedVal(primaryLabel$, localeCategory) }}
|
|
10
|
+
</button>
|
|
11
|
+
</mat-grid-tile>
|
|
12
|
+
</mat-grid-list>
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { provideZonelessChangeDetection } from '@angular/core';
|
|
2
|
+
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
3
|
+
|
|
4
|
+
import { DataViewActionButtonsComponent } from './data-view-action-buttons.component';
|
|
5
|
+
|
|
6
|
+
const RESOURCE_STATUS = { CREATE: 'CREATE', UPDATE: 'UPDATE', OPEN_FLOW_ACTION: 'OPEN_FLOW_ACTION' };
|
|
7
|
+
const DATA_EVENTS = { DATA_OBJECT_CREATED: 'DataObjectCreated', DATA_OBJECT_UPDATED: 'DataObjectUpdated' };
|
|
8
|
+
|
|
9
|
+
describe('DataViewActionButtonsComponent', () => {
|
|
10
|
+
let component: DataViewActionButtonsComponent;
|
|
11
|
+
let fixture: ComponentFixture<DataViewActionButtonsComponent>;
|
|
12
|
+
let actionsApi: {
|
|
13
|
+
createDataObject: jasmine.Spy;
|
|
14
|
+
updateDataObject: jasmine.Spy;
|
|
15
|
+
submitDataObjectAction: jasmine.Spy;
|
|
16
|
+
cancelDataObject: jasmine.Spy;
|
|
17
|
+
};
|
|
18
|
+
let publishSpy: jasmine.Spy;
|
|
19
|
+
|
|
20
|
+
beforeEach(async () => {
|
|
21
|
+
publishSpy = jasmine.createSpy('publish');
|
|
22
|
+
// PCore is read in a field initializer, so it must exist before the component is created.
|
|
23
|
+
(globalThis as any).PCore = {
|
|
24
|
+
getLocaleUtils: () => ({ getLocaleValue: (value: string) => value }),
|
|
25
|
+
getConstants: () => ({ RESOURCE_STATUS, PUB_SUB_EVENTS: { DATA_EVENTS } }),
|
|
26
|
+
getPubSubUtils: () => ({ publish: publishSpy })
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
await TestBed.configureTestingModule({
|
|
30
|
+
imports: [DataViewActionButtonsComponent],
|
|
31
|
+
providers: [provideZonelessChangeDetection()]
|
|
32
|
+
}).compileComponents();
|
|
33
|
+
|
|
34
|
+
fixture = TestBed.createComponent(DataViewActionButtonsComponent);
|
|
35
|
+
component = fixture.componentInstance;
|
|
36
|
+
|
|
37
|
+
actionsApi = {
|
|
38
|
+
createDataObject: jasmine.createSpy('createDataObject').and.returnValue(Promise.resolve()),
|
|
39
|
+
updateDataObject: jasmine.createSpy('updateDataObject').and.returnValue(Promise.resolve()),
|
|
40
|
+
submitDataObjectAction: jasmine.createSpy('submitDataObjectAction').and.returnValue(Promise.resolve()),
|
|
41
|
+
cancelDataObject: jasmine.createSpy('cancelDataObject').and.returnValue({})
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
component.pConn$ = { getActionsApi: () => actionsApi } as any;
|
|
45
|
+
component.context$ = 'app/modal_1';
|
|
46
|
+
component.dataRecordKeys$ = '{"pyGUID":"abc-123"}';
|
|
47
|
+
component.classID$ = 'My-Data-Class';
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('should create', () => {
|
|
51
|
+
expect(component).toBeTruthy();
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it('labels the primary button "Update" when editing an existing record', () => {
|
|
55
|
+
component.dataObjectAction$ = RESOURCE_STATUS.UPDATE;
|
|
56
|
+
expect(component.primaryLabel$).toBe('Update');
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('labels the primary button "Submit" when creating a record', () => {
|
|
60
|
+
component.dataObjectAction$ = RESOURCE_STATUS.CREATE;
|
|
61
|
+
expect(component.primaryLabel$).toBe('Submit');
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('labels the primary button "Submit" for a record action', () => {
|
|
65
|
+
component.dataObjectAction$ = RESOURCE_STATUS.OPEN_FLOW_ACTION;
|
|
66
|
+
expect(component.primaryLabel$).toBe('Submit');
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('creates the record and publishes the created event', async () => {
|
|
70
|
+
component.dataObjectAction$ = RESOURCE_STATUS.CREATE;
|
|
71
|
+
|
|
72
|
+
component.onSubmit();
|
|
73
|
+
await fixture.whenStable();
|
|
74
|
+
|
|
75
|
+
expect(actionsApi.createDataObject).toHaveBeenCalledWith('app/modal_1');
|
|
76
|
+
expect(publishSpy).toHaveBeenCalledWith(DATA_EVENTS.DATA_OBJECT_CREATED, { classId: 'My-Data-Class', data: undefined });
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('parses the serialised record keys before updating', async () => {
|
|
80
|
+
component.dataObjectAction$ = RESOURCE_STATUS.UPDATE;
|
|
81
|
+
|
|
82
|
+
component.onSubmit();
|
|
83
|
+
await fixture.whenStable();
|
|
84
|
+
|
|
85
|
+
expect(actionsApi.updateDataObject).toHaveBeenCalledWith('app/modal_1', { pyGUID: 'abc-123' });
|
|
86
|
+
expect(publishSpy).toHaveBeenCalledWith(DATA_EVENTS.DATA_OBJECT_UPDATED, { classId: 'My-Data-Class' });
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('submits a record action with its parsed keys and action ID', async () => {
|
|
90
|
+
component.dataObjectAction$ = RESOURCE_STATUS.OPEN_FLOW_ACTION;
|
|
91
|
+
component.actionID$ = 'updateCVV';
|
|
92
|
+
|
|
93
|
+
component.onSubmit();
|
|
94
|
+
await fixture.whenStable();
|
|
95
|
+
|
|
96
|
+
expect(actionsApi.submitDataObjectAction).toHaveBeenCalledWith('app/modal_1', { pyGUID: 'abc-123' }, 'updateCVV');
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('disables both buttons while a save is in flight', () => {
|
|
100
|
+
let resolveSave: () => void = () => {};
|
|
101
|
+
actionsApi.createDataObject.and.returnValue(
|
|
102
|
+
new Promise<void>(resolve => {
|
|
103
|
+
resolveSave = resolve;
|
|
104
|
+
})
|
|
105
|
+
);
|
|
106
|
+
component.dataObjectAction$ = RESOURCE_STATUS.CREATE;
|
|
107
|
+
|
|
108
|
+
component.onSubmit();
|
|
109
|
+
|
|
110
|
+
expect(component.bDisabled$).toBeTrue();
|
|
111
|
+
resolveSave();
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it('re-enables the buttons and publishes nothing when the save is rejected', async () => {
|
|
115
|
+
actionsApi.createDataObject.and.returnValue(Promise.reject(new Error('rejected')));
|
|
116
|
+
component.dataObjectAction$ = RESOURCE_STATUS.CREATE;
|
|
117
|
+
|
|
118
|
+
component.onSubmit();
|
|
119
|
+
await fixture.whenStable();
|
|
120
|
+
|
|
121
|
+
expect(publishSpy).not.toHaveBeenCalled();
|
|
122
|
+
expect(component.bDisabled$).toBeFalse();
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it('discards the edit through the engine on cancel', () => {
|
|
126
|
+
component.onCancel();
|
|
127
|
+
|
|
128
|
+
expect(actionsApi.cancelDataObject).toHaveBeenCalledWith('app/modal_1');
|
|
129
|
+
});
|
|
130
|
+
});
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { CommonModule } from '@angular/common';
|
|
2
|
+
import { ChangeDetectorRef, Component, Input } from '@angular/core';
|
|
3
|
+
import { MatButtonModule } from '@angular/material/button';
|
|
4
|
+
import { MatGridListModule } from '@angular/material/grid-list';
|
|
5
|
+
|
|
6
|
+
@Component({
|
|
7
|
+
selector: 'app-data-view-action-buttons',
|
|
8
|
+
templateUrl: './data-view-action-buttons.component.html',
|
|
9
|
+
imports: [CommonModule, MatGridListModule, MatButtonModule]
|
|
10
|
+
})
|
|
11
|
+
export class DataViewActionButtonsComponent {
|
|
12
|
+
@Input() pConn$: typeof PConnect;
|
|
13
|
+
@Input() context$: string;
|
|
14
|
+
@Input() dataObjectAction$: string;
|
|
15
|
+
@Input() actionID$ = '';
|
|
16
|
+
// The container item publishes the record keys JSON-serialised.
|
|
17
|
+
@Input() dataRecordKeys$ = '';
|
|
18
|
+
@Input() classID$ = '';
|
|
19
|
+
|
|
20
|
+
localizedVal = PCore.getLocaleUtils().getLocaleValue;
|
|
21
|
+
localeCategory = 'Data Object';
|
|
22
|
+
bDisabled$ = false;
|
|
23
|
+
|
|
24
|
+
constructor(private cdRef: ChangeDetectorRef) {}
|
|
25
|
+
|
|
26
|
+
get primaryLabel$(): string {
|
|
27
|
+
return this.dataObjectAction$ === PCore.getConstants().RESOURCE_STATUS.UPDATE ? 'Update' : 'Submit';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
onCancel() {
|
|
31
|
+
// The engine drops the container item, which collapses the modal.
|
|
32
|
+
this.pConn$.getActionsApi().cancelDataObject(this.context$);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
onSubmit() {
|
|
36
|
+
const { RESOURCE_STATUS, PUB_SUB_EVENTS } = PCore.getConstants();
|
|
37
|
+
const { DATA_OBJECT_CREATED, DATA_OBJECT_UPDATED } = PUB_SUB_EVENTS.DATA_EVENTS;
|
|
38
|
+
const actionsApi = this.pConn$.getActionsApi();
|
|
39
|
+
const { publish } = PCore.getPubSubUtils();
|
|
40
|
+
|
|
41
|
+
let submitAction: Promise<any>;
|
|
42
|
+
let publishCompleted: (data?: any) => void;
|
|
43
|
+
|
|
44
|
+
switch (this.dataObjectAction$) {
|
|
45
|
+
case RESOURCE_STATUS.UPDATE:
|
|
46
|
+
submitAction = actionsApi.updateDataObject(this.context$, this.getRecordKeys());
|
|
47
|
+
publishCompleted = () => publish(DATA_OBJECT_UPDATED, { classId: this.classID$ });
|
|
48
|
+
break;
|
|
49
|
+
case RESOURCE_STATUS.OPEN_FLOW_ACTION:
|
|
50
|
+
submitAction = actionsApi.submitDataObjectAction(this.context$, this.getRecordKeys(), this.actionID$);
|
|
51
|
+
publishCompleted = () => publish(DATA_OBJECT_UPDATED, { classId: this.classID$, actionID: this.actionID$ });
|
|
52
|
+
break;
|
|
53
|
+
default:
|
|
54
|
+
submitAction = actionsApi.createDataObject(this.context$);
|
|
55
|
+
publishCompleted = data => publish(DATA_OBJECT_CREATED, { classId: this.classID$, data });
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
this.bDisabled$ = true;
|
|
59
|
+
|
|
60
|
+
submitAction
|
|
61
|
+
.then(data => {
|
|
62
|
+
publishCompleted(data);
|
|
63
|
+
})
|
|
64
|
+
.catch(() => {
|
|
65
|
+
// Keep the modal open so the server error banner is visible and the edit can be corrected.
|
|
66
|
+
})
|
|
67
|
+
.finally(() => {
|
|
68
|
+
this.bDisabled$ = false;
|
|
69
|
+
// Change detection is zoneless, so this async reset needs to be flagged explicitly.
|
|
70
|
+
this.cdRef.markForCheck();
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
private getRecordKeys(): Record<string, any> {
|
|
75
|
+
return this.dataRecordKeys$ ? JSON.parse(this.dataRecordKeys$) : {};
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -1,15 +1,36 @@
|
|
|
1
|
-
<div
|
|
2
|
-
<div class="psdk-modal-view-container-top" id="{{
|
|
3
|
-
<h3 *ngIf="title
|
|
1
|
+
<div *ngFor="let modal of modalStack; trackBy: trackByModalKey" id="dialog" class="psdk-dialog-background">
|
|
2
|
+
<div class="psdk-modal-view-container-top" id="{{ modal.key }}">
|
|
3
|
+
<h3 *ngIf="modal.title != ''">{{ modal.title }}</h3>
|
|
4
4
|
<component-mapper
|
|
5
5
|
name="Assignment"
|
|
6
|
-
[props]="{
|
|
6
|
+
[props]="{
|
|
7
|
+
pConn$: modal.createdViewPConn$,
|
|
8
|
+
formGroup$,
|
|
9
|
+
arChildren$: modal.arChildren$,
|
|
10
|
+
itemKey$: modal.key,
|
|
11
|
+
isCreateStage$: true,
|
|
12
|
+
updateToken$: modal.updateToken,
|
|
13
|
+
isInModal$: true
|
|
14
|
+
}"
|
|
7
15
|
></component-mapper>
|
|
8
|
-
<div *ngIf="
|
|
16
|
+
<div *ngIf="modal.isMultiRecordData">
|
|
9
17
|
<component-mapper
|
|
10
18
|
name="ListViewActionButtons"
|
|
11
|
-
[props]="{ pConn$: createdViewPConn$, context
|
|
12
|
-
[outputEvents]="{ closeActionsDialog:
|
|
19
|
+
[props]="{ pConn$: modal.createdViewPConn$, context$: modal.context }"
|
|
20
|
+
[outputEvents]="{ closeActionsDialog: closeModalFor(modal.key) }"
|
|
21
|
+
></component-mapper>
|
|
22
|
+
</div>
|
|
23
|
+
<div *ngIf="modal.isDataObjectModal">
|
|
24
|
+
<component-mapper
|
|
25
|
+
name="DataViewActionButtons"
|
|
26
|
+
[props]="{
|
|
27
|
+
pConn$: modal.createdViewPConn$,
|
|
28
|
+
context$: modal.context,
|
|
29
|
+
classID$: modal.dataObjectClassId,
|
|
30
|
+
dataObjectAction$: modal.dataObjectAction,
|
|
31
|
+
dataRecordKeys$: modal.dataRecordKeys,
|
|
32
|
+
actionID$: modal.dataObjectActionID
|
|
33
|
+
}"
|
|
13
34
|
></component-mapper>
|
|
14
35
|
</div>
|
|
15
36
|
</div>
|
|
@@ -18,7 +39,13 @@
|
|
|
18
39
|
<div *ngIf="bShowCancelAlert$">
|
|
19
40
|
<component-mapper
|
|
20
41
|
name="CancelAlert"
|
|
21
|
-
[props]="{
|
|
42
|
+
[props]="{
|
|
43
|
+
bShowAlert$: bShowCancelAlert$,
|
|
44
|
+
pConn$: cancelPConn$,
|
|
45
|
+
hideDelete: cancelHideDelete$,
|
|
46
|
+
isDataObject: cancelIsDataObject$,
|
|
47
|
+
skipReleaseLockRequest: cancelSkipReleaseLockRequest$
|
|
48
|
+
}"
|
|
22
49
|
[parent]="this"
|
|
23
50
|
[outputEvents]="{ onAlertState$: onAlertState }"
|
|
24
51
|
></component-mapper>
|