@pega/dx-component-builder-sdk 0.24.1 → 0.24.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/package.json +1 -1
  2. package/src/tasks/create/templates/Constellation/field/Icon-Button-URL/demo.stories.tsx.mustache +1 -1
  3. package/src/tasks/create/templates/Constellation/field/Picklist/index.tsx.mustache +0 -1
  4. package/src/tasks/create/templates/Constellation/field/Picklist-Autocomplete/date.ts.mustache +15 -37
  5. package/src/tasks/create/templates/Constellation/template/DETAILS/HighlightRender.tsx.mustache +2 -2
  6. package/src/tasks/create/templates/Constellation/template/DETAILS-region/HighlightRender.tsx.mustache +2 -2
  7. package/src/tasks/create/templates/Constellation/template/DETAILS-region/index.tsx.mustache +1 -1
  8. package/src/tasks/create/templates/SDK-Angular/field/Boolean/boolean.component.html.mustache +19 -18
  9. package/src/tasks/create/templates/SDK-Angular/field/Boolean/boolean.component.ts.mustache +127 -44
  10. package/src/tasks/create/templates/SDK-Angular/field/Icon-Button-URL/demo.stories.tsx.mustache +36 -15
  11. package/src/tasks/create/templates/SDK-Angular/field/Icon-Button-URL/icon-button-url.component.html.mustache +40 -0
  12. package/src/tasks/create/templates/SDK-Angular/field/Icon-Button-URL/{text-url.component.scss.mustache → icon-button-url.component.scss.mustache} +4 -0
  13. package/src/tasks/create/templates/SDK-Angular/field/Icon-Button-URL/icon-button-url.component.ts.mustache +195 -0
  14. package/src/tasks/create/templates/SDK-Angular/field/Icon-Button-URL/mock.ts.mustache +32 -12
  15. package/src/tasks/create/templates/SDK-Angular/field/Text-URL/text-url.component.html.mustache +1 -0
  16. package/src/tasks/create/templates/SDK-Angular/field/Text-URL/text-url.component.ts.mustache +2 -0
  17. package/src/tasks/create/templates/SDK-Angular/field/TimeOfDay/time-of-day.component.html.mustache +1 -0
  18. package/src/tasks/create/templates/SDK-Angular/field/TimeOfDay/time-of-day.component.ts.mustache +2 -0
  19. package/src/tasks/create/templates/SDK-Angular/template/FORM-region/form.component.scss.mustache +1 -1
  20. package/src/tasks/create/templates/SDK-Angular/widget/CASE/case.component.ts.mustache +2 -2
  21. package/src/tasks/create/templates/SDK-Angular/widget/PAGE/page.component.html.mustache +1 -1
  22. package/src/tasks/create/templates/SDK-React/field/Boolean/demo.stories.tsx.mustache +1 -1
  23. package/src/tasks/create/templates/SDK-React/field/Boolean/mock.ts.mustache +8 -8
  24. package/src/tasks/create/templates/SDK-React/field/Date/index.tsx.mustache +2 -2
  25. package/src/tasks/create/templates/SDK-React/field/Date/mock.ts.mustache +7 -7
  26. package/src/tasks/create/templates/SDK-React/field/DateTime/demo.stories.tsx.mustache +1 -1
  27. package/src/tasks/create/templates/SDK-React/field/DateTime/index.tsx.mustache +2 -3
  28. package/src/tasks/create/templates/SDK-React/field/DateTime/mock.ts.mustache +6 -6
  29. package/src/tasks/create/templates/SDK-React/field/Decimal/index.tsx.mustache +51 -35
  30. package/src/tasks/create/templates/SDK-React/field/Decimal/mock.ts.mustache +1 -1
  31. package/src/tasks/create/templates/SDK-React/field/Decimal-Currency/config.json.mustache +1 -1
  32. package/src/tasks/create/templates/SDK-React/field/Decimal-Currency/demo.stories.tsx.mustache +1 -1
  33. package/src/tasks/create/templates/SDK-React/field/Decimal-Currency/index.tsx.mustache +47 -37
  34. package/src/tasks/create/templates/SDK-React/field/Decimal-Currency/mock.ts.mustache +1 -1
  35. package/src/tasks/create/templates/SDK-React/field/Decimal-Percentage/config.json.mustache +1 -1
  36. package/src/tasks/create/templates/SDK-React/field/Decimal-Percentage/index.tsx.mustache +36 -21
  37. package/src/tasks/create/templates/SDK-React/field/Decimal-Percentage/mock.ts.mustache +1 -1
  38. package/src/tasks/create/templates/SDK-React/field/Icon-Button-URL/demo.stories.tsx.mustache +58 -25
  39. package/src/tasks/create/templates/SDK-React/field/Icon-Button-URL/index.tsx.mustache +134 -53
  40. package/src/tasks/create/templates/SDK-React/field/Icon-Button-URL/mock.ts.mustache +2 -14
  41. package/src/tasks/create/templates/SDK-React/field/Integer/config.json.mustache +1 -1
  42. package/src/tasks/create/templates/SDK-React/field/Integer/index.tsx.mustache +19 -20
  43. package/src/tasks/create/templates/SDK-React/field/Integer/mock.ts.mustache +1 -1
  44. package/src/tasks/create/templates/SDK-React/field/Picklist/index.tsx.mustache +26 -26
  45. package/src/tasks/create/templates/SDK-React/field/Picklist-RadioButtons/mock.ts.mustache +0 -1
  46. package/src/tasks/create/templates/SDK-React/field/Text/config.json.mustache +1 -1
  47. package/src/tasks/create/templates/SDK-React/field/Text/index.tsx.mustache +0 -1
  48. package/src/tasks/create/templates/SDK-React/field/Text/mock.ts.mustache +1 -1
  49. package/src/tasks/create/templates/SDK-React/field/Text-Email/config.json.mustache +1 -1
  50. package/src/tasks/create/templates/SDK-React/field/Text-Email/mock.ts.mustache +1 -1
  51. package/src/tasks/create/templates/SDK-React/field/Text-Input/config.json.mustache +1 -1
  52. package/src/tasks/create/templates/SDK-React/field/Text-Input/index.tsx.mustache +0 -1
  53. package/src/tasks/create/templates/SDK-React/field/Text-Input/mock.ts.mustache +1 -1
  54. package/src/tasks/create/templates/SDK-React/field/Text-Paragraph/index.tsx.mustache +1 -3
  55. package/src/tasks/create/templates/SDK-React/field/Text-Paragraph/mock.ts.mustache +1 -1
  56. package/src/tasks/create/templates/SDK-React/field/Text-Phone/index.tsx.mustache +1 -2
  57. package/src/tasks/create/templates/SDK-React/field/Text-URL/index.tsx.mustache +1 -2
  58. package/src/tasks/create/templates/SDK-React/field/Text-URL/mock.ts.mustache +1 -1
  59. package/src/tasks/create/templates/SDK-React/field/TimeOfDay/demo.stories.tsx.mustache +4 -4
  60. package/src/tasks/create/templates/SDK-React/field/TimeOfDay/index.tsx.mustache +0 -2
  61. package/src/tasks/create/templates/SDK-React/field/TimeOfDay/mock.ts.mustache +6 -6
  62. package/src/tasks/create/templates/SDK-React/template/DETAILS/demo.stories.tsx.mustache +1 -4
  63. package/src/tasks/create/templates/SDK-React/template/DETAILS/index.tsx.mustache +3 -8
  64. package/src/tasks/create/templates/SDK-React/template/DETAILS/mock.ts.mustache +181 -165
  65. package/src/tasks/create/templates/SDK-React/template/DETAILS-region/demo.stories.tsx.mustache +1 -3
  66. package/src/tasks/create/templates/SDK-React/template/DETAILS-region/index.tsx.mustache +3 -8
  67. package/src/tasks/create/templates/SDK-React/template/DETAILS-region/mock.ts.mustache +207 -163
  68. package/src/tasks/create/templates/SDK-React/template/FORM/config.json.mustache +1 -1
  69. package/src/tasks/create/templates/SDK-React/template/FORM/demo.stories.tsx.mustache +0 -1
  70. package/src/tasks/create/templates/SDK-React/template/FORM/index.tsx.mustache +14 -16
  71. package/src/tasks/create/templates/SDK-React/template/FORM/utils.ts.mustache +1 -1
  72. package/src/tasks/create/templates/SDK-React/template/FORM-region/demo.stories.tsx.mustache +0 -2
  73. package/src/tasks/create/templates/SDK-React/template/FORM-region/mock.ts.mustache +121 -122
  74. package/src/tasks/create/templates/SDK-React/template/PAGE/OneColumn.tsx.mustache +12 -13
  75. package/src/tasks/create/templates/SDK-React/template/PAGE/demo.stories.tsx.mustache +1 -1
  76. package/src/tasks/create/templates/SDK-React/template/PAGE/index.tsx.mustache +3 -5
  77. package/src/tasks/create/templates/SDK-React/template/PAGE/mock.ts.mustache +8 -9
  78. package/src/tasks/create/templates/SDK-React/widget/CASE/config.json.mustache +2 -2
  79. package/src/tasks/create/templates/SDK-React/widget/CASE/demo.stories.tsx.mustache +0 -1
  80. package/src/tasks/create/templates/SDK-React/widget/CASE/index.tsx.mustache +3 -3
  81. package/src/tasks/create/templates/SDK-React/widget/PAGE/config.json.mustache +43 -43
  82. package/src/tasks/create/templates/SDK-React/widget/PAGE/mock.ts.mustache +1 -1
  83. package/src/tasks/create/templates/SDK-React/widget/PAGE-CASE/demo.stories.tsx.mustache +1 -2
  84. package/src/tasks/create/templates/SDK-React/widget/PAGE-CASE/index.tsx.mustache +0 -1
  85. package/src/tasks/create/templates/SDK-React/widget/PAGE-CASE/mock.ts.mustache +0 -1
  86. package/src/tasks/create/templates/SDK-Angular/field/Icon-Button-URL/text-url.component.html.mustache +0 -29
  87. package/src/tasks/create/templates/SDK-Angular/field/Icon-Button-URL/text-url.component.ts.mustache +0 -179
  88. /package/src/tasks/create/templates/SDK-Angular/field/Icon-Button-URL/{text-url.component.spec.ts.mustache → icon-button-url.component.spec.ts.mustache} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pega/dx-component-builder-sdk",
3
- "version": "0.24.1",
3
+ "version": "0.24.2",
4
4
  "description": "Utility for building custom UI components",
5
5
  "bin": "./bin/index.js",
6
6
  "scripts": {
@@ -4,7 +4,7 @@
4
4
  import type { Meta, StoryObj } from '@storybook/react';
5
5
 
6
6
  import {{COMPONENT_CLASS_NAME}} from './index';
7
- import { stateProps, configProps } from './mock';
7
+ import { configProps } from './mock';
8
8
 
9
9
  const meta: Meta<typeof {{COMPONENT_CLASS_NAME}}> = {
10
10
  title: '{{COMPONENT_CLASS_NAME}}',
@@ -39,7 +39,6 @@ interface StateProps {
39
39
  hasSuggestions: boolean;
40
40
  }
41
41
 
42
-
43
42
  export const formatExists = (formatterVal: string) => {
44
43
  const formatterValues = [
45
44
  "TextInput",
@@ -1,4 +1,3 @@
1
- // @ts-nocheck
2
1
  import dayjs from 'dayjs';
3
2
  import relativeTime from 'dayjs/plugin/relativeTime.js';
4
3
  import localizedFormat from 'dayjs/plugin/localizedFormat.js';
@@ -35,18 +34,9 @@ const constellationToCosmosFormatterMap = new Map([
35
34
  [
36
35
  DATE_TYPES.DATE,
37
36
  new Map([
38
- [
39
- formatConstants.DateTimeLong,
40
- { format: COSMOS_FORMAT_CONSTANTS.LONG, variant: COSMOS_VARIANT_CONSTANTS.DATE_TIME }
41
- ],
42
- [
43
- formatConstants.DateTimeShort,
44
- { format: COSMOS_FORMAT_CONSTANTS.SHORT, variant: COSMOS_VARIANT_CONSTANTS.DATE }
45
- ],
46
- [
47
- formatConstants.DateTimeSince,
48
- { format: COSMOS_FORMAT_CONSTANTS.SHORT, variant: COSMOS_VARIANT_CONSTANTS.RELATIVE }
49
- ],
37
+ [formatConstants.DateTimeLong, { format: COSMOS_FORMAT_CONSTANTS.LONG, variant: COSMOS_VARIANT_CONSTANTS.DATE_TIME }],
38
+ [formatConstants.DateTimeShort, { format: COSMOS_FORMAT_CONSTANTS.SHORT, variant: COSMOS_VARIANT_CONSTANTS.DATE }],
39
+ [formatConstants.DateTimeSince, { format: COSMOS_FORMAT_CONSTANTS.SHORT, variant: COSMOS_VARIANT_CONSTANTS.RELATIVE }],
50
40
  [formatConstants.DateDefault, { format: COSMOS_FORMAT_CONSTANTS.LONG, variant: COSMOS_VARIANT_CONSTANTS.DATE }]
51
41
  ])
52
42
  ],
@@ -60,22 +50,10 @@ const constellationToCosmosFormatterMap = new Map([
60
50
  [
61
51
  DATE_TYPES.DATE_TIME,
62
52
  new Map([
63
- [
64
- formatConstants.DateTimeDefault,
65
- { format: COSMOS_FORMAT_CONSTANTS.SHORT, variant: COSMOS_VARIANT_CONSTANTS.DATE_TIME }
66
- ],
67
- [
68
- formatConstants.DateTimeShort,
69
- { format: COSMOS_FORMAT_CONSTANTS.SHORT, variant: COSMOS_VARIANT_CONSTANTS.DATE }
70
- ],
71
- [
72
- formatConstants.DateTimeSince,
73
- { format: COSMOS_FORMAT_CONSTANTS.SHORT, variant: COSMOS_VARIANT_CONSTANTS.RELATIVE }
74
- ],
75
- [
76
- formatConstants.DateTimeLong,
77
- { format: COSMOS_FORMAT_CONSTANTS.LONG, variant: COSMOS_VARIANT_CONSTANTS.DATE_TIME }
78
- ],
53
+ [formatConstants.DateTimeDefault, { format: COSMOS_FORMAT_CONSTANTS.SHORT, variant: COSMOS_VARIANT_CONSTANTS.DATE_TIME }],
54
+ [formatConstants.DateTimeShort, { format: COSMOS_FORMAT_CONSTANTS.SHORT, variant: COSMOS_VARIANT_CONSTANTS.DATE }],
55
+ [formatConstants.DateTimeSince, { format: COSMOS_FORMAT_CONSTANTS.SHORT, variant: COSMOS_VARIANT_CONSTANTS.RELATIVE }],
56
+ [formatConstants.DateTimeLong, { format: COSMOS_FORMAT_CONSTANTS.LONG, variant: COSMOS_VARIANT_CONSTANTS.DATE_TIME }],
79
57
  [formatConstants.TimeOnly, { format: COSMOS_FORMAT_CONSTANTS.SHORT, variant: COSMOS_VARIANT_CONSTANTS.TIME }]
80
58
  ])
81
59
  ]
@@ -85,13 +63,14 @@ const types = ['fromNow', 'customFormat'];
85
63
  // value should be in ISO 8601 format.
86
64
  function DateFormatter(
87
65
  value,
88
- // eslint-disable-next-line no-shadow, @typescript-eslint/no-shadow
89
- { type = types[1], format = 'DD/MM/YYYY', timezone, fieldType } = {}) {
66
+ // @ts-ignore
67
+ // eslint-disable-next-line @typescript-eslint/no-shadow
68
+ { type = types[1], format = 'DD/MM/YYYY', timezone, fieldType } = {}
69
+ ) {
90
70
  if (!value) return value;
91
71
  switch (type) {
92
72
  case types[1]:
93
- if (timezone && !(fieldType === 'Date' || fieldType === 'Date only'))
94
- return dayjs(value).tz(timezone).format(format); // Date only value should be formatted without timezone
73
+ if (timezone && !(fieldType === 'Date' || fieldType === 'Date only')) return dayjs(value).tz(timezone).format(format); // Date only value should be formatted without timezone
95
74
  return dayjs(value).format(format);
96
75
  case types[0]:
97
76
  return dayjs(value).from(dayjs());
@@ -129,8 +108,8 @@ function DateFormatter(
129
108
  export function format(value, options) {
130
109
  if (!value) return null;
131
110
  const { type, locale, timezone, formatter, translate } = options;
132
- // eslint-disable-next-line no-shadow, @typescript-eslint/no-shadow
133
- const { format, variant } = constellationToCosmosFormatterMap.get(type).get(formatter);
111
+ // eslint-disable-next-line @typescript-eslint/no-shadow
112
+ const { format, variant } = (constellationToCosmosFormatterMap.get(type) as any).get(formatter);
134
113
  return formatDateTime(parseToDate(value), {
135
114
  t: translate,
136
115
  locale,
@@ -154,8 +133,7 @@ export default {
154
133
  })
155
134
  : value;
156
135
  },
157
- convertFromTimezone: (value, timezone) =>
158
- value && timezone ? dayjs.tz(value, timezone).utc().format('YYYY-MM-DDTHH:mm:ss[Z]') : value,
136
+ convertFromTimezone: (value, timezone) => (value && timezone ? dayjs.tz(value, timezone).utc().format('YYYY-MM-DDTHH:mm:ss[Z]') : value),
159
137
  Date: (value, options) => DateFormatter(value, { type: 'customFormat', ...options }),
160
138
  'Date-Default': (value, options) => format(value, { ...options, formatter: 'Date-Default' }),
161
139
  'Date-Time-Default': (value, options) => format(value, { ...options, formatter: 'Date-Time-Default' }),
@@ -10,7 +10,7 @@ interface HighlightRenderProps extends PConnProps {
10
10
  const HighlightRender = (props: HighlightRenderProps) => {
11
11
  const { getPConnect, field } = props;
12
12
 
13
- field.config['displayMode'] = 'DISPLAY_ONLY';
13
+ field.config.displayMode = 'DISPLAY_ONLY';
14
14
 
15
15
  // Mark as status display when using pyStatusWork
16
16
  if (field.config?.value === '@P .pyStatusWork') {
@@ -18,7 +18,7 @@ const HighlightRender = (props: HighlightRenderProps) => {
18
18
  field.config.displayAsStatus = true;
19
19
  }
20
20
 
21
- const configProps = getPConnect().resolveConfigProps(field.config);
21
+ const configProps: any = getPConnect().resolveConfigProps(field.config);
22
22
 
23
23
  // @ts-ignore
24
24
  const reactField = getPConnect().createComponent(field);
@@ -10,7 +10,7 @@ interface HighlightRenderProps extends PConnProps {
10
10
  const HighlightRender = (props: HighlightRenderProps) => {
11
11
  const { getPConnect, field } = props;
12
12
 
13
- field.config['displayMode'] = 'DISPLAY_ONLY';
13
+ field.config.displayMode = 'DISPLAY_ONLY';
14
14
 
15
15
  // Mark as status display when using pyStatusWork
16
16
  if (field.config?.value === '@P .pyStatusWork') {
@@ -18,7 +18,7 @@ const HighlightRender = (props: HighlightRenderProps) => {
18
18
  field.config.displayAsStatus = true;
19
19
  }
20
20
 
21
- const configProps = getPConnect().resolveConfigProps(field.config);
21
+ const configProps: any = getPConnect().resolveConfigProps(field.config);
22
22
 
23
23
  // @ts-ignore
24
24
  const reactField = getPConnect().createComponent(field);
@@ -33,7 +33,7 @@ function {{COMPONENT_CLASS_NAME}}(props: {{COMPONENT_CLASS_NAME}}Props) {
33
33
  });
34
34
 
35
35
  const numRegions = getAllFields(getPConnect)?.length;
36
- const gridRepeat = "repeat(".concat(numRegions).concat(", 1fr)");
36
+ const gridRepeat = "repeat(".concat(numRegions.toString()).concat(", 1fr)");
37
37
 
38
38
  const gridContainer: GridContainerProps = { colGap: 6 };
39
39
  gridContainer.cols = gridRepeat;
@@ -5,44 +5,45 @@
5
5
  [props]="{ label$: caption$, value$: value$ ? trueLabel$ : falseLabel$, displayMode$ }"
6
6
  ></component-mapper>
7
7
  </div>
8
+ {{! pick new delimiters for mustache }}
9
+ {{=<% %>=}}
8
10
  <ng-template #noDisplayMode>
9
- <div *ngIf="!bReadonly$ && bHasForm$; else noEdit">
11
+ <div *ngIf="bHasForm$; else noEdit">
10
12
  <div [formGroup]="formGroup$" *ngIf="bVisible$">
11
13
  <div class="mat-form-field-infix" *ngIf="showLabel$">
12
14
  <span>
13
15
  <label class="mat-form-field-label psdk-label-readonly">{{ label$ }}</label>
14
16
  </span>
15
- {{! pick new delimiters for mustache }}
16
- {{=<% %>=}}
17
- <mat-checkbox
18
- [labelPosition]="'after'"
19
- [checked]="isChecked$"
20
- [disabled]="bDisabled$"
21
- [attr.data-test-id]="testId"
22
- [formControl]="fieldControl"
23
- (change)="fieldOnChange($event)"
24
- (blur)="fieldOnBlur($event)"
25
- >{{ caption$ }}</mat-checkbox
26
- >
27
17
  </div>
28
- <div class="mat-form-field-infix" *ngIf="!bReadonly$ && !showLabel$">
18
+ <div *ngIf="selectionMode === 'multi'; else single">
19
+ <mat-option *ngFor="let item of listOfCheckboxes" (click)="handleChangeMultiMode($event, item)">
20
+ <mat-checkbox
21
+ [labelPosition]="'after'"
22
+ [checked]="item.selected"
23
+ [attr.data-test-id]="testId + ':' + item.value"
24
+ (change)="handleChangeMultiMode($event, item)"
25
+ (blur)="fieldOnBlur($event)"
26
+ >{{ item.text ?? item.value }}
27
+ </mat-checkbox>
28
+ </mat-option>
29
+ </div>
30
+ <ng-template #single>
29
31
  <mat-checkbox
30
32
  [labelPosition]="'after'"
31
33
  [checked]="isChecked$"
32
- [disabled]="bDisabled$"
33
34
  [attr.data-test-id]="testId"
34
35
  [formControl]="fieldControl"
35
36
  (change)="fieldOnChange($event)"
36
37
  (blur)="fieldOnBlur($event)"
37
38
  >{{ caption$ }}</mat-checkbox
38
39
  >
39
- <%={{ }}=%> {{! revert delimiters for mustache }}
40
- </div>
41
- <mat-hint *ngIf="helperText">{{ helperText }}</mat-hint>
40
+ <p *ngIf="helperText">{{ helperText }}</p>
41
+ </ng-template>
42
42
  <mat-error *ngIf="fieldControl.invalid">{{ getErrorMessage() }}</mat-error>
43
43
  </div>
44
44
  </div>
45
45
  </ng-template>
46
+ <%={{ }}=%> {{! revert delimiters for mustache }}
46
47
  <ng-template #noEdit>
47
48
  <component-mapper *ngIf="bVisible$ !== false" name="Text" [props]="{ pConn$, formatAs$: 'text' }"></component-mapper>
48
49
  </ng-template>
@@ -3,10 +3,14 @@ import { CommonModule } from '@angular/common';
3
3
  import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
4
4
  import { MatCheckboxModule } from '@angular/material/checkbox';
5
5
  import { MatFormFieldModule } from '@angular/material/form-field';
6
+ import { MatOptionModule } from '@angular/material/core';
7
+ import { interval } from 'rxjs';
6
8
  import { AngularPConnectData, AngularPConnectService } from '@pega/angular-sdk-components';
7
9
  import { Utils } from '@pega/angular-sdk-components';
8
10
  import { ComponentMapperComponent } from '@pega/angular-sdk-components';
9
11
  import { PConnFieldProps } from '@pega/angular-sdk-components';
12
+ import { deleteInstruction, insertInstruction, updateNewInstructions } from '@pega/angular-sdk-components';
13
+ import { handleEvent } from '@pega/angular-sdk-components';
10
14
 
11
15
  interface {{COMPONENT_CLASS_NAME}}Props extends Omit<PConnFieldProps, 'value'> {
12
16
  // If any, enter additional props that only exist on Checkbox here
@@ -15,6 +19,13 @@ interface {{COMPONENT_CLASS_NAME}}Props extends Omit<PConnFieldProps, 'value'> {
15
19
  caption?: string;
16
20
  trueLabel?: string;
17
21
  falseLabel?: string;
22
+ selectionMode?: string;
23
+ datasource?: any;
24
+ selectionKey?: string;
25
+ selectionList?: any;
26
+ primaryField: string;
27
+ readonlyContextList: any;
28
+ referenceList: string;
18
29
  }
19
30
 
20
31
  @Component({
@@ -22,7 +33,7 @@ interface {{COMPONENT_CLASS_NAME}}Props extends Omit<PConnFieldProps, 'value'> {
22
33
  templateUrl: './{{COMPONENT_CLASS_NAME_KEBAB}}.component.html',
23
34
  styleUrls: ['./{{COMPONENT_CLASS_NAME_KEBAB}}.component.scss'],
24
35
  standalone: true,
25
- imports: [CommonModule, ReactiveFormsModule, MatCheckboxModule, MatFormFieldModule, forwardRef(() => ComponentMapperComponent)]
36
+ imports: [CommonModule, ReactiveFormsModule, MatCheckboxModule, MatFormFieldModule,MatOptionModule, forwardRef(() => ComponentMapperComponent)]
26
37
  })
27
38
  export class {{COMPONENT_CLASS_NAME}}Component implements OnInit, OnDestroy {
28
39
  @Input() pConn$: typeof PConnect;
@@ -50,6 +61,17 @@ export class {{COMPONENT_CLASS_NAME}}Component implements OnInit, OnDestroy {
50
61
  trueLabel$?: string;
51
62
  falseLabel$?: string;
52
63
 
64
+ selectionMode?: string;
65
+ datasource?: any;
66
+ selectionKey?: string;
67
+ selectionList?: any;
68
+ primaryField: string;
69
+ selectedvalues: any;
70
+ referenceList: string;
71
+ listOfCheckboxes: any[] = [];
72
+ actionsApi: any;
73
+ propName: any;
74
+
53
75
  fieldControl = new FormControl('', null);
54
76
 
55
77
  constructor(
@@ -69,6 +91,11 @@ export class {{COMPONENT_CLASS_NAME}}Component implements OnInit, OnDestroy {
69
91
  // this.updateSelf();
70
92
  this.checkAndUpdate();
71
93
 
94
+ if (this.selectionMode === 'multi' && this.referenceList?.length > 0) {
95
+ this.pConn$.setReferenceList(this.selectionList);
96
+ updateNewInstructions(this.pConn$, this.selectionList);
97
+ }
98
+
72
99
  if (this.formGroup$) {
73
100
  // add control to formGroup
74
101
  this.formGroup$.addControl(this.controlName$, this.fieldControl);
@@ -111,68 +138,124 @@ export class {{COMPONENT_CLASS_NAME}}Component implements OnInit, OnDestroy {
111
138
  // moved this from ngOnInit() and call this from there instead...
112
139
  this.configProps$ = this.pConn$.resolveConfigProps(this.pConn$.getConfigProps()) as {{COMPONENT_CLASS_NAME}}Props;
113
140
 
114
- if (this.configProps$.value != undefined) {
115
- this.value$ = this.configProps$.value;
116
- }
117
141
  this.testId = this.configProps$.testId;
118
- this.label$ = this.configProps$.label;
119
142
  this.displayMode$ = this.configProps$.displayMode;
143
+ this.label$ = this.configProps$.label;
144
+ if (this.label$ != '') {
145
+ this.showLabel$ = true;
146
+ }
120
147
 
121
- this.caption$ = this.configProps$.caption;
122
- this.helperText = this.configProps$.helperText;
123
- this.trueLabel$ = this.configProps$.trueLabel;
124
- this.falseLabel$ = this.configProps$.falseLabel;
125
-
126
- // timeout and detectChanges to avoid ExpressionChangedAfterItHasBeenCheckedError
127
- setTimeout(() => {
128
- if (this.configProps$.required != null) {
129
- this.bRequired$ = this.utils.getBooleanValue(this.configProps$.required);
148
+ this.actionsApi = this.pConn$.getActionsApi();
149
+ this.propName = (this.pConn$.getStateProps() as any).value;
150
+
151
+ // multi case
152
+ this.selectionMode = this.configProps$.selectionMode;
153
+ if (this.selectionMode === 'multi') {
154
+ this.referenceList = this.configProps$.referenceList;
155
+ this.selectionList = this.configProps$.selectionList;
156
+ this.selectedvalues = this.configProps$.readonlyContextList;
157
+ this.primaryField = this.configProps$.primaryField;
158
+
159
+ this.datasource = this.configProps$.datasource;
160
+ this.selectionKey = this.configProps$.selectionKey;
161
+ const listSourceItems = this.datasource?.source ?? [];
162
+ const dataField: any = this.selectionKey?.split?.('.')[1];
163
+ const listToDisplay: any[] = [];
164
+ listSourceItems.forEach(element => {
165
+ element.selected = this.selectedvalues?.some?.(data => data[dataField] === element.key);
166
+ listToDisplay.push(element);
167
+ });
168
+ this.listOfCheckboxes = listToDisplay;
169
+ } else {
170
+ if (this.configProps$.value != undefined) {
171
+ this.value$ = this.configProps$.value;
130
172
  }
131
- this.cdRef.detectChanges();
132
- });
133
-
134
- if (this.configProps$.visibility != null) {
135
- this.bVisible$ = this.utils.getBooleanValue(this.configProps$.visibility);
136
- }
137
173
 
138
- // disabled
139
- if (this.configProps$.disabled != undefined) {
140
- this.bDisabled$ = this.utils.getBooleanValue(this.configProps$.disabled);
141
- }
174
+ this.caption$ = this.configProps$.caption;
175
+ this.helperText = this.configProps$.helperText;
176
+ this.trueLabel$ = this.configProps$.trueLabel;
177
+ this.falseLabel$ = this.configProps$.falseLabel;
178
+
179
+ // timeout and detectChanges to avoid ExpressionChangedAfterItHasBeenCheckedError
180
+ setTimeout(() => {
181
+ if (this.configProps$.required != null) {
182
+ this.bRequired$ = this.utils.getBooleanValue(this.configProps$.required);
183
+ }
184
+ this.cdRef.detectChanges();
185
+ });
186
+
187
+ if (this.configProps$.visibility != null) {
188
+ this.bVisible$ = this.utils.getBooleanValue(this.configProps$.visibility);
189
+ }
142
190
 
143
- if (this.bDisabled$) {
144
- this.fieldControl.disable();
145
- } else {
146
- this.fieldControl.enable();
147
- }
191
+ // disabled
192
+ if (this.configProps$.disabled != undefined) {
193
+ this.bDisabled$ = this.utils.getBooleanValue(this.configProps$.disabled);
194
+ }
148
195
 
149
- if (this.configProps$.readOnly != null) {
150
- this.bReadonly$ = this.utils.getBooleanValue(this.configProps$.readOnly);
151
- }
196
+ if (this.bDisabled$) {
197
+ this.fieldControl.disable();
198
+ } else {
199
+ this.fieldControl.enable();
200
+ }
152
201
 
153
- this.componentReference = (this.pConn$.getStateProps() as any).value;
202
+ if (this.configProps$.readOnly != null) {
203
+ this.bReadonly$ = this.utils.getBooleanValue(this.configProps$.readOnly);
204
+ this.fieldControl.disable();
205
+ }
154
206
 
155
- if (this.label$ != '') {
156
- this.showLabel$ = true;
157
- }
207
+ this.componentReference = (this.pConn$.getStateProps() as any).value;
158
208
 
159
- // eslint-disable-next-line sonarjs/no-redundant-boolean
160
- if (this.value$ === 'true' || this.value$ == true) {
161
- this.isChecked$ = true;
162
- } else {
163
- this.isChecked$ = false;
209
+ // eslint-disable-next-line sonarjs/no-redundant-boolean
210
+ if (this.value$ === 'true' || this.value$ == true) {
211
+ this.isChecked$ = true;
212
+ } else {
213
+ this.isChecked$ = false;
214
+ }
215
+ // trigger display of error message with field control
216
+ if (this.angularPConnectData.validateMessage != null && this.angularPConnectData.validateMessage != '') {
217
+ const timer = interval(100).subscribe(() => {
218
+ this.fieldControl.setErrors({ message: true });
219
+ this.fieldControl.markAsTouched();
220
+
221
+ timer.unsubscribe();
222
+ });
223
+ }
164
224
  }
165
225
  }
166
226
 
167
227
  fieldOnChange(event: any) {
168
228
  event.value = event.checked;
169
229
 
170
- this.angularPConnectData.actions?.onChange(this, event);
230
+ handleEvent(this.actionsApi, 'changeNblur', this.propName, event.checked);
171
231
  }
172
232
 
173
233
  fieldOnBlur(event: any) {
174
- event.value = event.checked;
175
- this.angularPConnectData.actions?.onBlur(this, event);
234
+ if (this.selectionMode === 'multi') {
235
+ this.pConn$.getValidationApi().validate(this.selectedvalues, this.selectionList);
236
+ } else {
237
+ event.value = event.checked;
238
+ this.angularPConnectData.actions?.onBlur(this, event);
239
+ }
240
+ }
241
+
242
+ handleChangeMultiMode(event, element) {
243
+ if (!element.selected) {
244
+ insertInstruction(this.pConn$, this.selectionList, this.selectionKey, this.primaryField, {
245
+ id: element.key,
246
+ primary: element.text ?? element.value
247
+ });
248
+ } else {
249
+ deleteInstruction(this.pConn$, this.selectionList, this.selectionKey, {
250
+ id: element.key,
251
+ primary: element.text ?? element.value
252
+ });
253
+ }
254
+ this.pConn$.clearErrorMessages({
255
+ property: this.selectionList,
256
+ category: '',
257
+ context: ''
258
+ });
176
259
  }
177
260
 
178
261
  getErrorMessage() {
@@ -1,10 +1,28 @@
1
1
  import type { Meta, StoryObj } from '@storybook/angular';
2
2
  import { FormBuilder } from '@angular/forms';
3
3
 
4
- import { configProps, stateProps } from './mock';
4
+ import { configProps, stateListData, stateProps } from './mock';
5
5
 
6
6
  import {{! pick new delimiters for mustache }}{{=<% %>=}}{<%={{ }}=%> {{COMPONENT_CLASS_NAME}}Component {{=<% %>=}}}<%={{ }}=%>{{! revert delimiters for mustache }} from './{{COMPONENT_CLASS_NAME_KEBAB}}.component';
7
7
 
8
+ window.PCore = {
9
+ ...window.PCore,
10
+ getConstants: () => {
11
+ return {
12
+ CASE_INFO: {
13
+ CASE_INFO_ID: 'caseInfo.ID'
14
+ }
15
+ } as any;
16
+ },
17
+ getDataApiUtils: () => {
18
+ return {
19
+ getData: () => {
20
+ return Promise.resolve(stateListData);
21
+ }
22
+ } as any;
23
+ }
24
+ };
25
+
8
26
  const meta: Meta<{{COMPONENT_CLASS_NAME}}Component> = {
9
27
  title: '{{COMPONENT_CLASS_NAME}}',
10
28
  component: {{COMPONENT_CLASS_NAME}}Component,
@@ -13,13 +31,22 @@ const meta: Meta<{{COMPONENT_CLASS_NAME}}Component> = {
13
31
  props: {
14
32
  ...args,
15
33
  pConn$: {
16
- resolveConfigProps: (props) => props,
17
- getConfigProps: () => {
18
- return configProps;
19
- },
20
- getStateProps: () => {
21
- return stateProps;
22
- }
34
+ resolveConfigProps: props => props,
35
+ getConfigProps: () => {
36
+ return configProps;
37
+ },
38
+ getValue: value => {
39
+ return value;
40
+ },
41
+ getContextName: () => {
42
+ return 'app/primary_1';
43
+ },
44
+ getStateProps: () => {
45
+ return stateProps;
46
+ },
47
+ getLocalizedValue: value => {
48
+ return value;
49
+ }
23
50
  } as any,
24
51
  formGroup$: new FormBuilder().group({})
25
52
  }
@@ -31,12 +58,6 @@ type Story = StoryObj<{{COMPONENT_CLASS_NAME}}Component>;
31
58
 
32
59
  export const {{COMPONENT_CLASS_NAME}}: Story = {
33
60
  args: {
34
- label$: configProps.label,
35
- helperText: configProps.helperText,
36
- placeholder: configProps.placeholder,
37
- bReadonly$: configProps.readOnly,
38
- bDisabled$: configProps.disabled,
39
- bRequired$: configProps.required,
40
- displayMode$: configProps.displayMode
61
+ countryCode: 'USA'
41
62
  }
42
63
  };
@@ -0,0 +1,40 @@
1
+ <div *ngIf="displayMode$; else noDisplayMode">
2
+ <component-mapper name="FieldValueList" [props]="{ label$, value$, displayMode$ }"></component-mapper>
3
+ </div>
4
+ {{! pick new delimiters for mustache }}
5
+ {{=<% %>=}}
6
+ <ng-template #noDisplayMode>
7
+ <div *ngIf="bHasForm$; else noEdit">
8
+ <div [formGroup]="formGroup$">
9
+ <mat-icon aria-hidden="false" aria-label="arrow right" fontIcon="arrow_forward"></mat-icon>
10
+ <mat-label style="vertical-align: super">{{ label$ }}</mat-label>
11
+ <button mat-icon-button aria-label="tooltip$" (click)="buttonClick()">
12
+ <mat-icon aria-hidden="false" [ariaLabel]="tooltip$" fontIcon="format_list_numbered"></mat-icon>
13
+ </button>
14
+ <a [href]="value$"><mat-icon aria-hidden="false" aria-label="tooltip$" fontIcon="language"></mat-icon></a>
15
+ </div>
16
+ <div *ngIf="showTable$">
17
+ <h2 class="psdk-state-list-title">{{ tableLabel$ }}</h2>
18
+ <table mat-table [dataSource]="repeatList$">
19
+ <!-- State name-->
20
+ <ng-container [matColumnDef]="displayedColumns$[0]">
21
+ <th mat-header-cell *matHeaderCellDef>{{ stateCodeLabel$ }}</th>
22
+ <td mat-cell *matCellDef="let element">{{ element.stateCode }}</td>
23
+ </ng-container>
24
+
25
+ <!-- State code-->
26
+ <ng-container [matColumnDef]="displayedColumns$[1]">
27
+ <th mat-header-cell *matHeaderCellDef>{{ stateNameLabel$ }}</th>
28
+ <td mat-cell *matCellDef="let element">{{ element.stateName }}</td>
29
+ </ng-container>
30
+
31
+ <tr mat-header-row *matHeaderRowDef="displayedColumns$"></tr>
32
+ <tr mat-row *matRowDef="let row; columns: displayedColumns$"></tr>
33
+ </table>
34
+ </div>
35
+ </div>
36
+ </ng-template>
37
+ <%={{ }}=%> {{! revert delimiters for mustache }}
38
+ <ng-template #noEdit>
39
+ <component-mapper name="Text" [props]="{ pConn$, formatAs$: 'url' }"></component-mapper>
40
+ </ng-template>
@@ -18,3 +18,7 @@
18
18
  ::ng-deep .mat-mdc-form-field-infix {
19
19
  width: auto;
20
20
  }
21
+
22
+ .psdk-state-list-title {
23
+ margin-left: 0.5rem;
24
+ }