@pega/angular-sdk-overrides 25.1.12 → 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.
Files changed (168) hide show
  1. package/lib/designSystemExtension/alert/alert.component.html +4 -1
  2. package/lib/designSystemExtension/alert/alert.component.scss +9 -10
  3. package/lib/designSystemExtension/alert/alert.component.ts +6 -2
  4. package/lib/designSystemExtension/field-group/field-group.component.ts +11 -3
  5. package/lib/designSystemExtension/material-case-summary/material-case-summary.component.html +51 -36
  6. package/lib/designSystemExtension/material-case-summary/material-case-summary.component.scss +12 -0
  7. package/lib/designSystemExtension/material-case-summary/material-case-summary.component.ts +11 -0
  8. package/lib/designSystemExtension/operator/operator.component.html +5 -3
  9. package/lib/designSystemExtension/operator/operator.component.scss +7 -0
  10. package/lib/designSystemExtension/operator/operator.component.ts +2 -1
  11. package/lib/designSystemExtension/rich-text-editor/rich-text-editor.component.html +100 -10
  12. package/lib/designSystemExtension/rich-text-editor/rich-text-editor.component.scss +141 -1
  13. package/lib/designSystemExtension/rich-text-editor/rich-text-editor.component.spec.ts +1 -1
  14. package/lib/designSystemExtension/rich-text-editor/rich-text-editor.component.ts +240 -72
  15. package/lib/field/auto-complete/auto-complete.component.html +46 -5
  16. package/lib/field/auto-complete/auto-complete.component.scss +92 -0
  17. package/lib/field/auto-complete/auto-complete.component.ts +350 -23
  18. package/lib/field/cancel-alert/cancel-alert.component.ts +38 -15
  19. package/lib/field/check-box/check-box.component.html +8 -6
  20. package/lib/field/check-box/check-box.component.ts +9 -2
  21. package/lib/field/currency/currency.component.html +2 -1
  22. package/lib/field/currency/currency.component.ts +10 -1
  23. package/lib/field/date/date.component.html +2 -1
  24. package/lib/field/date/date.component.ts +2 -0
  25. package/lib/field/date-time/date-time.component.html +2 -1
  26. package/lib/field/date-time/date-time.component.scss +46 -40
  27. package/lib/field/date-time/date-time.component.ts +29 -0
  28. package/lib/field/decimal/decimal.component.html +2 -1
  29. package/lib/field/decimal/decimal.component.ts +2 -0
  30. package/lib/field/dropdown/dropdown.component.html +4 -1
  31. package/lib/field/dropdown/dropdown.component.ts +18 -19
  32. package/lib/field/email/email.component.html +2 -1
  33. package/lib/field/email/email.component.ts +2 -2
  34. package/lib/field/embedded-data-multi/embedded-data-multi.component.html +3 -0
  35. package/lib/field/embedded-data-multi/embedded-data-multi.component.scss +0 -0
  36. package/lib/field/embedded-data-multi/embedded-data-multi.component.ts +173 -0
  37. package/lib/field/field.base.ts +27 -1
  38. package/lib/field/group/group.component.html +1 -1
  39. package/lib/field/group/group.component.ts +16 -7
  40. package/lib/field/integer/integer.component.html +2 -1
  41. package/lib/field/integer/integer.component.ts +4 -2
  42. package/lib/field/location/location.component.html +2 -1
  43. package/lib/field/location/location.component.ts +3 -1
  44. package/lib/field/multiselect/multiselect.component.html +1 -1
  45. package/lib/field/multiselect/multiselect.component.ts +23 -4
  46. package/lib/field/multiselect/utils.ts +5 -3
  47. package/lib/field/object-reference/object-reference.component.html +30 -15
  48. package/lib/field/object-reference/object-reference.component.ts +818 -94
  49. package/lib/field/percentage/percentage.component.html +2 -1
  50. package/lib/field/percentage/percentage.component.ts +10 -1
  51. package/lib/field/phone/phone.component.html +2 -1
  52. package/lib/field/phone/phone.component.ts +2 -1
  53. package/lib/field/radio-buttons/radio-buttons.component.html +2 -1
  54. package/lib/field/radio-buttons/radio-buttons.component.ts +10 -1
  55. package/lib/field/rich-text/rich-text.component.scss +1 -166
  56. package/lib/field/rich-text/rich-text.component.spec.ts +1 -1
  57. package/lib/field/rich-text/rich-text.component.ts +1 -1
  58. package/lib/field/selectable-card/selectable-card.component.html +1 -0
  59. package/lib/field/selectable-card/selectable-card.component.ts +31 -16
  60. package/lib/field/semantic-link/semantic-link.component.html +1 -1
  61. package/lib/field/semantic-link/semantic-link.component.scss +4 -0
  62. package/lib/field/semantic-link/semantic-link.component.ts +13 -7
  63. package/lib/field/text-area/text-area.component.html +2 -1
  64. package/lib/field/text-area/text-area.component.ts +2 -1
  65. package/lib/field/text-input/text-input.component.html +2 -1
  66. package/lib/field/text-input/text-input.component.ts +2 -1
  67. package/lib/field/time/time.component.html +2 -1
  68. package/lib/field/time/time.component.ts +2 -1
  69. package/lib/field/url/url.component.html +2 -1
  70. package/lib/field/url/url.component.ts +2 -1
  71. package/lib/field/user-reference/user-reference.component.html +4 -2
  72. package/lib/field/user-reference/user-reference.component.ts +11 -6
  73. package/lib/infra/Containers/flow-container/flow-container.component.html +2 -2
  74. package/lib/infra/Containers/flow-container/flow-container.component.ts +34 -42
  75. package/lib/infra/Containers/modal-view-container/data-view-action-buttons/data-view-action-buttons.component.html +12 -0
  76. package/lib/infra/Containers/modal-view-container/data-view-action-buttons/data-view-action-buttons.component.spec.ts +130 -0
  77. package/lib/infra/Containers/modal-view-container/data-view-action-buttons/data-view-action-buttons.component.ts +77 -0
  78. package/lib/infra/Containers/modal-view-container/modal-view-container.component.html +35 -8
  79. package/lib/infra/Containers/modal-view-container/modal-view-container.component.ts +185 -196
  80. package/lib/infra/Containers/view-container/view-container.component.html +1 -1
  81. package/lib/infra/Containers/view-container/view-container.component.ts +36 -43
  82. package/lib/infra/assignment/assignment.component.html +2 -1
  83. package/lib/infra/assignment/assignment.component.ts +44 -22
  84. package/lib/infra/assignment-card/assignment-card.component.html +1 -0
  85. package/lib/infra/assignment-card/assignment-card.component.ts +2 -8
  86. package/lib/infra/defer-load/defer-load.component.ts +7 -5
  87. package/lib/infra/multi-step/multi-step.component.html +25 -33
  88. package/lib/infra/multi-step/multi-step.component.scss +67 -125
  89. package/lib/infra/multi-step/multi-step.component.ts +11 -0
  90. package/lib/infra/navbar/navbar.component.ts +33 -36
  91. package/lib/infra/reference/reference.component.html +7 -1
  92. package/lib/infra/reference/reference.component.ts +63 -109
  93. package/lib/infra/region/region.component.ts +1 -3
  94. package/lib/infra/root-container/root-container.component.html +1 -0
  95. package/lib/infra/root-container/root-container.component.ts +34 -42
  96. package/lib/infra/view/view.component.ts +22 -46
  97. package/lib/template/advanced-search/advanced-search.component.ts +0 -1
  98. package/lib/template/advanced-search/search-groups/search-groups.component.ts +2 -3
  99. package/lib/template/app-shell/app-shell.component.ts +13 -13
  100. package/lib/template/banner-page/banner-page.component.ts +1 -2
  101. package/lib/template/base/details-template-base.ts +41 -14
  102. package/lib/template/base/form-template-base.ts +0 -2
  103. package/lib/template/case-summary/case-summary.component.ts +15 -7
  104. package/lib/template/case-view/case-view.component.html +14 -2
  105. package/lib/template/case-view/case-view.component.spec.ts +119 -10
  106. package/lib/template/case-view/case-view.component.ts +52 -3
  107. package/lib/template/data-reference/data-reference.component.ts +29 -22
  108. package/lib/template/data-reference/search-form/search-form.component.html +1 -1
  109. package/lib/template/data-reference/search-form/search-form.component.ts +9 -1
  110. package/lib/template/data-reference/search-form/tabsData.ts +0 -1
  111. package/lib/template/default-form/default-form.component.html +20 -4
  112. package/lib/template/default-form/default-form.component.ts +14 -5
  113. package/lib/template/default-page/default-page.component.ts +1 -2
  114. package/lib/template/details/details.component.html +23 -3
  115. package/lib/template/details/details.component.scss +9 -2
  116. package/lib/template/details/details.component.ts +3 -70
  117. package/lib/template/details-narrow-wide/details-narrow-wide.component.html +21 -2
  118. package/lib/template/details-narrow-wide/details-narrow-wide.component.scss +8 -1
  119. package/lib/template/details-narrow-wide/details-narrow-wide.component.ts +3 -39
  120. package/lib/template/details-one-column/details-one-column.component.html +23 -1
  121. package/lib/template/details-one-column/details-one-column.component.scss +14 -0
  122. package/lib/template/details-one-column/details-one-column.component.ts +3 -40
  123. package/lib/template/details-three-column/details-three-column.component.html +21 -2
  124. package/lib/template/details-three-column/details-three-column.component.scss +8 -1
  125. package/lib/template/details-three-column/details-three-column.component.ts +3 -48
  126. package/lib/template/details-two-column/details-two-column.component.html +21 -2
  127. package/lib/template/details-two-column/details-two-column.component.scss +8 -1
  128. package/lib/template/details-two-column/details-two-column.component.ts +3 -46
  129. package/lib/template/details-wide-narrow/details-wide-narrow.component.html +21 -2
  130. package/lib/template/details-wide-narrow/details-wide-narrow.component.scss +8 -1
  131. package/lib/template/details-wide-narrow/details-wide-narrow.component.ts +3 -43
  132. package/lib/template/dynamic-tabs/dynamic-tabs.component.html +1 -0
  133. package/lib/template/field-group-template/field-group-template.component.ts +19 -6
  134. package/lib/template/field-value-list/field-value-list.component.scss +17 -0
  135. package/lib/template/inline-dashboard-page/inline-dashboard-page.component.ts +2 -10
  136. package/lib/template/list-view/list-view.component.ts +47 -11
  137. package/lib/template/one-column/one-column.component.html +3 -0
  138. package/lib/template/one-column-tab/one-column-tab.component.html +1 -0
  139. package/lib/template/page/page.component.html +1 -0
  140. package/lib/template/self-service-case-view/self-service-case-view.component.html +13 -1
  141. package/lib/template/self-service-case-view/self-service-case-view.component.spec.ts +96 -11
  142. package/lib/template/self-service-case-view/self-service-case-view.component.ts +52 -3
  143. package/lib/template/simple-table/simple-table.component.ts +11 -1
  144. package/lib/template/simple-table-manual/helpers.ts +84 -16
  145. package/lib/template/simple-table-manual/simple-table-manual.component.html +30 -14
  146. package/lib/template/simple-table-manual/simple-table-manual.component.scss +8 -2
  147. package/lib/template/simple-table-manual/simple-table-manual.component.ts +142 -46
  148. package/lib/template/single-reference-readonly/single-reference-readonly.component.html +0 -0
  149. package/lib/template/single-reference-readonly/single-reference-readonly.component.scss +2 -3
  150. package/lib/template/single-reference-readonly/single-reference-readonly.component.ts +7 -8
  151. package/lib/template/wide-narrow-page/wide-narrow-page.component.ts +0 -3
  152. package/lib/template/wss-nav-bar/wss-nav-bar.component.ts +19 -21
  153. package/lib/widget/attachment/AttachmentUtils.ts +19 -11
  154. package/lib/widget/attachment/attachment.component.html +16 -6
  155. package/lib/widget/attachment/attachment.component.ts +14 -4
  156. package/lib/widget/case-history/case-history.component.ts +6 -2
  157. package/lib/widget/feed-container/feed-container.component.ts +1 -199
  158. package/lib/widget/file-utility/file-utility.component.ts +26 -30
  159. package/lib/widget/todo/todo.component.ts +7 -2
  160. package/package.json +2 -2
  161. package/lib/designSystemExtension/material-details/material-details.component.html +0 -40
  162. package/lib/designSystemExtension/material-details/material-details.component.scss +0 -116
  163. package/lib/designSystemExtension/material-details/material-details.component.spec.ts +0 -24
  164. package/lib/designSystemExtension/material-details/material-details.component.ts +0 -31
  165. package/lib/designSystemExtension/material-details-fields/material-details-fields.component.html +0 -29
  166. package/lib/designSystemExtension/material-details-fields/material-details-fields.component.scss +0 -34
  167. package/lib/designSystemExtension/material-details-fields/material-details-fields.component.spec.ts +0 -22
  168. 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 ? (key = this.options$[index].key) : event.target.value;
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="!isMultiStep">{{ containerName$ }}</h2>
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>
@@ -39,6 +39,6 @@
39
39
  </mat-card>
40
40
  </div>
41
41
  <div *ngIf="bShowBanner && bShowConfirm && confirm_pconn">
42
- <component-mapper name="View" [props]="{ formGroup$, pConn$: confirm_pconn }"></component-mapper>
42
+ <component-mapper name="reference" [props]="{ formGroup$, pConn$: confirm_pconn }"></component-mapper>
43
43
  </div>
44
44
  </div>
@@ -1,10 +1,9 @@
1
- import { Component, OnInit, Input, ChangeDetectorRef, NgZone, forwardRef, OnDestroy, Injector } from '@angular/core';
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';
5
5
  import { publicConstants } from '@pega/pcore-pconnect-typedefs/constants';
6
6
  import { ProgressSpinnerService } from '@pega/angular-sdk-components';
7
- import { ReferenceComponent } from '@pega/angular-sdk-components';
8
7
  import { Utils } from '@pega/angular-sdk-components';
9
8
  import { getToDoAssignments, hasAssignments, showBanner } from './helpers';
10
9
  import { ComponentMapperComponent } from '@pega/angular-sdk-components';
@@ -76,7 +75,6 @@ export class FlowContainerComponent extends FlowContainerBaseComponent implement
76
75
  private cdRef: ChangeDetectorRef,
77
76
  private psService: ProgressSpinnerService,
78
77
  private fb: FormBuilder,
79
- private ngZone: NgZone,
80
78
  private utils: Utils
81
79
  ) {
82
80
  super(injector);
@@ -124,6 +122,7 @@ export class FlowContainerComponent extends FlowContainerBaseComponent implement
124
122
  'clearBannerMessages',
125
123
  () => {
126
124
  this.banners = [];
125
+ this.cdRef.markForCheck();
127
126
  },
128
127
  'clearBannerMessages'
129
128
  );
@@ -189,10 +188,9 @@ export class FlowContainerComponent extends FlowContainerBaseComponent implement
189
188
  }
190
189
 
191
190
  showPageMessages(completeProps: FlowContainerProps) {
192
- this.ngZone.run(() => {
193
- const pageMessages = completeProps.pageMessages;
194
- this.banners = [{ messages: pageMessages?.map(msg => this.localizedVal(msg.message, 'Messages')), variant: 'urgent' }];
195
- });
191
+ const pageMessages = completeProps.pageMessages;
192
+ this.banners = [{ messages: pageMessages?.map(msg => this.localizedVal(msg.message, 'Messages')), variant: 'urgent' }];
193
+ this.cdRef.markForCheck();
196
194
  }
197
195
 
198
196
  getTodoVisibilty() {
@@ -385,8 +383,7 @@ export class FlowContainerComponent extends FlowContainerBaseComponent implement
385
383
  const { CASE_INFO: CASE_CONSTS } = PCore.getConstants();
386
384
 
387
385
  setTimeout(() => {
388
- this.ngZone.run(() => {
389
- /*
386
+ /*
390
387
  *** renove this commmented out code when React/WC is updated
391
388
  *** this code is replace with the call to "getToDoAssigments" function below
392
389
 
@@ -404,32 +401,32 @@ export class FlowContainerComponent extends FlowContainerBaseComponent implement
404
401
  const caseActions = localPConn.getValue(CASE_CONSTS.CASE_INFO_ACTIONS);
405
402
  */
406
403
 
407
- const todoAssignments = getToDoAssignments(this.pConn$);
404
+ const todoAssignments = getToDoAssignments(this.pConn$);
408
405
 
409
- if (todoAssignments && todoAssignments.length > 0) {
410
- this.todo_caseInfoID$ = this.pConn$.getValue(CASE_CONSTS.CASE_INFO_ID);
411
- this.todo_datasource$ = { source: todoAssignments };
412
- }
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
+ }
413
410
 
414
- /* remove this commented out code when update React/WC */
415
- // let kid = this.pConn$.getChildren()[0];
411
+ /* remove this commented out code when update React/WC */
412
+ // let kid = this.pConn$.getChildren()[0];
416
413
 
417
- // kid.getPConnect() can be a Reference component. So normalize it just in case
418
- // let todoKid = ReferenceComponent.normalizePConn(kid.getPConnect()).getChildren()[0];
414
+ // kid.getPConnect() can be a Reference component. So normalize it just in case
415
+ // let todoKid = kid.getPConnect().getChildren()[0];
419
416
 
420
- // this.todo_pConn$ = todoKid.getPConnect();
417
+ // this.todo_pConn$ = todoKid.getPConnect();
421
418
 
422
- /* code change here to note for React/WC */
423
- // todo now needs pConn to open the work item on click "go"
424
- this.todo_pConn$ = this.pConn$;
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$;
425
422
 
426
- // still needs the context of the original work item
427
- this.todo_context$ = localPConn.getContextName();
423
+ // still needs the context of the original work item
424
+ this.todo_context$ = localPConn.getContextName();
428
425
 
429
- this.todo_showTodo$ = true;
426
+ this.todo_showTodo$ = true;
430
427
 
431
- this.psService.sendMessage(false);
432
- });
428
+ this.psService.sendMessage(false);
429
+ this.cdRef.markForCheck();
433
430
  });
434
431
  }
435
432
 
@@ -528,30 +525,25 @@ export class FlowContainerComponent extends FlowContainerBaseComponent implement
528
525
  // the View if it is a Reference component. And need to pass in the getPConnect
529
526
  // to have normalize do a c11Env createComponent (that makes sure options.hasForm
530
527
  // is passed along to all the component's children)
531
- const normalizedConfigObject = ReferenceComponent.normalizePConn(configObject.getPConnect());
528
+ const normalizedConfigObject = configObject.getPConnect();
532
529
  // We want the children to be the PConnect itself, not the result of calling getPConnect(),
533
530
  // So need to get the PConnect of the normalized component we just created...
534
531
  const normalizedConfigObjectAsPConnect = normalizedConfigObject.getComponent();
535
532
 
536
533
  // makes sure Angular tracks these changes
537
- this.ngZone.run(() => {
538
- this.buildName$ = this.getBuildName();
539
- // 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
540
536
 
541
- this.arChildren$ = [];
542
- this.arChildren$.push(normalizedConfigObjectAsPConnect);
537
+ this.arChildren$ = [];
538
+ this.arChildren$.push(normalizedConfigObjectAsPConnect);
543
539
 
544
- this.psService.sendMessage(false);
540
+ this.psService.sendMessage(false);
545
541
 
546
- const oWorkItem = configObject.getPConnect();
547
- const oWorkData: any = oWorkItem.getDataObject();
542
+ const oWorkItem = configObject.getPConnect();
543
+ const oWorkData: any = oWorkItem.getDataObject();
548
544
 
549
- this.containerName$ = this.localizedVal(
550
- this.getActiveViewLabel() || oWorkData.caseInfo.assignments?.[0]?.name,
551
- undefined,
552
- this.localeReference
553
- );
554
- });
545
+ this.containerName$ = this.localizedVal(this.getActiveViewLabel() || oWorkData.caseInfo.assignments?.[0]?.name, undefined, this.localeReference);
546
+ this.cdRef.markForCheck();
555
547
  }
556
548
 
557
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 id="dialog" *ngIf="bShowModal$" class="psdk-dialog-background">
2
- <div class="psdk-modal-view-container-top" id="{{ buildName$ }}">
3
- <h3 *ngIf="title$ != ''">{{ title$ }}</h3>
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]="{ pConn$: createdViewPConn$, formGroup$, arChildren$, itemKey$, isCreateStage$: true, updateToken$, isInModal$: true, banners }"
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="isMultiRecord">
16
+ <div *ngIf="modal.isMultiRecordData">
9
17
  <component-mapper
10
18
  name="ListViewActionButtons"
11
- [props]="{ pConn$: createdViewPConn$, context$ }"
12
- [outputEvents]="{ closeActionsDialog: 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]="{ bShowAlert$: bShowCancelAlert$, pConn$: cancelPConn$ }"
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>