@pega/angular-sdk-overrides 0.25.18 → 0.25.20
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/field/currency/currency.component.html +1 -0
- package/lib/field/currency/currency.component.ts +36 -43
- package/lib/field/decimal/decimal.component.html +2 -2
- package/lib/field/decimal/decimal.component.ts +35 -59
- package/lib/field/integer/integer.component.html +13 -4
- package/lib/field/integer/integer.component.ts +46 -12
- package/lib/field/percentage/percentage.component.html +2 -2
- package/lib/field/percentage/percentage.component.ts +46 -41
- package/lib/infra/navbar/navbar.component.ts +0 -1
- package/lib/infra/reference/reference.component.ts +1 -2
- package/lib/template/advanced-search/advanced-search.component.ts +0 -1
- package/lib/template/advanced-search/search-groups/search-groups.component.ts +3 -4
- package/lib/template/app-shell/app-shell.component.ts +0 -1
- package/lib/template/data-reference/data-reference.component.ts +0 -1
- package/lib/template/data-reference/search-form/tabsData.ts +0 -1
- package/lib/template/list-view/list-view.component.ts +0 -1
- package/lib/template/simple-table-manual/helpers.ts +1 -1
- package/lib/template/utils.ts +0 -1
- package/package.json +1 -1
|
@@ -7,16 +7,27 @@ import { NgxCurrencyDirective, NgxCurrencyInputMode } from 'ngx-currency';
|
|
|
7
7
|
|
|
8
8
|
import { FieldBase } from '@pega/angular-sdk-components';
|
|
9
9
|
import { ComponentMapperComponent } from '@pega/angular-sdk-components';
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
import {
|
|
11
|
+
formatNumberFieldForDisplay,
|
|
12
|
+
getCurrencyInputFormat,
|
|
13
|
+
NumberInputFormat,
|
|
14
|
+
parseFormattedNumber,
|
|
15
|
+
saveNumberOnBlur
|
|
16
|
+
} from '@pega/angular-sdk-components';
|
|
13
17
|
import { PConnFieldProps } from '@pega/angular-sdk-components';
|
|
14
18
|
|
|
15
|
-
interface CurrrencyProps extends PConnFieldProps {
|
|
19
|
+
interface CurrrencyProps extends Omit<PConnFieldProps, 'value'> {
|
|
16
20
|
// If any, enter additional props that only exist on Currency here
|
|
21
|
+
value?: number | string;
|
|
17
22
|
currencyISOCode?: string;
|
|
23
|
+
alwaysShowISOCode?: boolean;
|
|
18
24
|
allowDecimals: boolean;
|
|
19
25
|
formatter?: string;
|
|
26
|
+
currencyDisplay?: 'symbol' | 'code' | 'name';
|
|
27
|
+
negative?: 'minus-sign' | 'parentheses';
|
|
28
|
+
notation?: 'standard' | 'compact';
|
|
29
|
+
currencyDecimalPrecision?: string;
|
|
30
|
+
decimalPrecision?: number | string;
|
|
20
31
|
}
|
|
21
32
|
|
|
22
33
|
@Component({
|
|
@@ -29,14 +40,14 @@ export class CurrencyComponent extends FieldBase {
|
|
|
29
40
|
configProps$: CurrrencyProps;
|
|
30
41
|
override fieldControl = new FormControl<number | null>(null, { updateOn: 'blur' });
|
|
31
42
|
|
|
32
|
-
currencyOptions: object = {};
|
|
33
43
|
currencySymbol: string;
|
|
44
|
+
currencySuffix: string;
|
|
34
45
|
thousandSeparator: string;
|
|
35
46
|
decimalSeparator: string;
|
|
36
47
|
decimalPrecision: number | undefined;
|
|
37
48
|
formattedValue: string;
|
|
38
|
-
formatter;
|
|
39
49
|
inputMode = NgxCurrencyInputMode.Natural;
|
|
50
|
+
private inputFormat: NumberInputFormat;
|
|
40
51
|
|
|
41
52
|
/**
|
|
42
53
|
* Updates the component when there are changes in the state.
|
|
@@ -50,56 +61,38 @@ export class CurrencyComponent extends FieldBase {
|
|
|
50
61
|
|
|
51
62
|
// Extract and normalize the value property
|
|
52
63
|
const { value } = this.configProps$;
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
this.fieldControl.setValue(this.value$);
|
|
56
|
-
}
|
|
64
|
+
this.value$ = value === undefined || value === null || value === '' ? '' : Number(value);
|
|
65
|
+
this.fieldControl.setValue(this.value$ === '' ? null : this.value$);
|
|
57
66
|
|
|
58
67
|
// update currency properties
|
|
59
68
|
this.updateCurrencyProperties(this.configProps$);
|
|
60
69
|
}
|
|
61
70
|
|
|
62
71
|
/**
|
|
63
|
-
* Updates the
|
|
64
|
-
*
|
|
65
|
-
* @param {Object} configProps - Configuration properties.
|
|
66
|
-
* @param {boolean} configProps.allowDecimals - Whether to allow decimal values.
|
|
67
|
-
* @param {string} configProps.currencyISOCode - The ISO code of the currency.
|
|
68
|
-
* @param {string} configProps.formatter - The formatter type (e.g., 'currency').
|
|
72
|
+
* Updates the input mask and read-only value, matching the Constellation DX Currency component.
|
|
69
73
|
*/
|
|
70
|
-
protected updateCurrencyProperties(configProps): void {
|
|
71
|
-
const { allowDecimals, currencyISOCode = 'USD',
|
|
74
|
+
protected updateCurrencyProperties(configProps: CurrrencyProps): void {
|
|
75
|
+
const { allowDecimals = true, currencyISOCode = 'USD', alwaysShowISOCode = false } = configProps;
|
|
72
76
|
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
77
|
+
const inputFormat = getCurrencyInputFormat(
|
|
78
|
+
currencyISOCode,
|
|
79
|
+
this.utils.getBooleanValue(alwaysShowISOCode),
|
|
80
|
+
this.utils.getBooleanValue(allowDecimals)
|
|
81
|
+
);
|
|
82
|
+
this.inputFormat = inputFormat;
|
|
83
|
+
this.currencySymbol = inputFormat.prefix;
|
|
84
|
+
this.currencySuffix = inputFormat.suffix;
|
|
85
|
+
this.thousandSeparator = inputFormat.thousandSeparator;
|
|
86
|
+
this.decimalSeparator = inputFormat.decimalSeparator;
|
|
87
|
+
this.decimalPrecision = inputFormat.precision;
|
|
78
88
|
|
|
79
89
|
if (['DISPLAY_ONLY', 'STACKED_LARGE_VAL'].includes(this.displayMode$)) {
|
|
80
|
-
this.formattedValue =
|
|
90
|
+
this.formattedValue = formatNumberFieldForDisplay('Currency', this.value$, { ...configProps, currencyISOCode });
|
|
81
91
|
}
|
|
82
92
|
}
|
|
83
93
|
|
|
84
94
|
fieldOnBlur(event: any) {
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
if (isValueChanged) {
|
|
89
|
-
const actionsApi = this.pConn$?.getActionsApi();
|
|
90
|
-
const propName = this.pConn$?.getStateProps().value;
|
|
91
|
-
let value = event?.target?.value;
|
|
92
|
-
value = value?.substring(1);
|
|
93
|
-
// replacing thousand separator with empty string as not required in api call
|
|
94
|
-
const thousandSep = this.thousandSeparator === '.' ? '\\.' : this.thousandSeparator;
|
|
95
|
-
let regExp = new RegExp(String.raw`${thousandSep}`, 'g');
|
|
96
|
-
value = value?.replace(regExp, '');
|
|
97
|
-
// replacing decimal separator with '.'
|
|
98
|
-
if (this.decimalSeparator !== '.') {
|
|
99
|
-
regExp = new RegExp(String.raw`${this.decimalSeparator}`, 'g');
|
|
100
|
-
value = value.replace(regExp, '.');
|
|
101
|
-
}
|
|
102
|
-
handleEvent(actionsApi, 'changeNblur', propName, value);
|
|
103
|
-
}
|
|
95
|
+
const parsed = parseFormattedNumber(event?.target?.value, this.inputFormat);
|
|
96
|
+
saveNumberOnBlur(this.pConn$, parsed !== '' ? Number(parsed) : '', this.configProps$?.value);
|
|
104
97
|
}
|
|
105
98
|
}
|
|
@@ -7,17 +7,27 @@ import { NgxCurrencyDirective, NgxCurrencyInputMode } from 'ngx-currency';
|
|
|
7
7
|
|
|
8
8
|
import { FieldBase } from '@pega/angular-sdk-components';
|
|
9
9
|
import { ComponentMapperComponent } from '@pega/angular-sdk-components';
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
import {
|
|
11
|
+
formatNumberFieldForDisplay,
|
|
12
|
+
getNumberInputFormat,
|
|
13
|
+
NumberInputFormat,
|
|
14
|
+
parseDecimalPrecision,
|
|
15
|
+
parseFormattedNumber,
|
|
16
|
+
saveNumberOnBlur
|
|
17
|
+
} from '@pega/angular-sdk-components';
|
|
13
18
|
import { PConnFieldProps } from '@pega/angular-sdk-components';
|
|
14
19
|
|
|
15
|
-
interface DecimalProps extends PConnFieldProps {
|
|
20
|
+
interface DecimalProps extends Omit<PConnFieldProps, 'value'> {
|
|
16
21
|
// If any, enter additional props that only exist on Decimal here
|
|
22
|
+
value?: number | string;
|
|
17
23
|
currencyISOCode?: string;
|
|
18
|
-
decimalPrecision?: number;
|
|
19
|
-
showGroupSeparators?: string;
|
|
24
|
+
decimalPrecision?: number | string;
|
|
25
|
+
showGroupSeparators?: boolean | string;
|
|
20
26
|
formatter?: string;
|
|
27
|
+
currencyDisplay?: 'symbol' | 'code' | 'name';
|
|
28
|
+
negative?: 'minus-sign' | 'parentheses';
|
|
29
|
+
notation?: 'standard' | 'compact';
|
|
30
|
+
currencyDecimalPrecision?: string;
|
|
21
31
|
}
|
|
22
32
|
|
|
23
33
|
@Component({
|
|
@@ -40,12 +50,10 @@ export class DecimalComponent extends FieldBase {
|
|
|
40
50
|
|
|
41
51
|
decimalSeparator: string;
|
|
42
52
|
thousandSeparator: string;
|
|
43
|
-
currencySymbol = '';
|
|
44
53
|
decimalPrecision: number | undefined;
|
|
45
|
-
formatter;
|
|
46
54
|
formattedValue: any;
|
|
47
55
|
inputMode: any = NgxCurrencyInputMode.Natural;
|
|
48
|
-
|
|
56
|
+
private inputFormat: NumberInputFormat;
|
|
49
57
|
|
|
50
58
|
/**
|
|
51
59
|
* Updates the component when there are changes in the state.
|
|
@@ -59,66 +67,34 @@ export class DecimalComponent extends FieldBase {
|
|
|
59
67
|
|
|
60
68
|
// Extract and normalize the value property
|
|
61
69
|
const { value } = this.configProps$;
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
this.fieldControl.setValue(this.value$);
|
|
65
|
-
}
|
|
70
|
+
this.value$ = value === undefined || value === null || value === '' ? '' : Number(value);
|
|
71
|
+
this.fieldControl.setValue(this.value$ === '' ? null : this.value$);
|
|
66
72
|
|
|
67
73
|
// updates decimal properties
|
|
68
74
|
this.updateDecimalProperties(this.configProps$);
|
|
69
75
|
}
|
|
70
76
|
|
|
71
77
|
/**
|
|
72
|
-
* Updates
|
|
73
|
-
*
|
|
74
|
-
* @param {Object} configProps - Configuration properties.
|
|
75
|
-
* @param {string} configProps.currencyISOCode - ISO code of the currency.
|
|
76
|
-
* @param {string} configProps.formatter - Formatter type (e.g., 'decimal', 'currency').
|
|
77
|
-
* @param {boolean} configProps.showGroupSeparators - Whether to show group separators.
|
|
78
|
+
* Updates the input mask and read-only value, matching the Constellation DX Decimal component.
|
|
78
79
|
*/
|
|
79
|
-
protected updateDecimalProperties(configProps): void {
|
|
80
|
-
const {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
this.
|
|
85
|
-
this.
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
this.currencySymbol = theSymbols.theCurrencySymbol;
|
|
80
|
+
protected updateDecimalProperties(configProps: DecimalProps): void {
|
|
81
|
+
const { decimalPrecision, showGroupSeparators = true } = configProps;
|
|
82
|
+
const numberOfDecimals = parseDecimalPrecision(decimalPrecision, 2);
|
|
83
|
+
const groupSeparators = this.utils.getBooleanValue(showGroupSeparators);
|
|
84
|
+
|
|
85
|
+
this.inputFormat = getNumberInputFormat();
|
|
86
|
+
this.decimalSeparator = this.inputFormat.decimalSeparator;
|
|
87
|
+
this.thousandSeparator = groupSeparators ? this.inputFormat.thousandSeparator : '';
|
|
88
|
+
// ngx-currency needs a fixed precision; Constellation allows any number of decimals when none is configured
|
|
89
|
+
this.decimalPrecision = numberOfDecimals ?? 2;
|
|
90
|
+
|
|
91
|
+
if (['DISPLAY_ONLY', 'STACKED_LARGE_VAL'].includes(this.displayMode$)) {
|
|
92
|
+
this.formattedValue = formatNumberFieldForDisplay('Decimal', this.value$, configProps);
|
|
93
93
|
}
|
|
94
|
-
|
|
95
|
-
if (this.bReadonly$ && formatter === 'Percentage') {
|
|
96
|
-
this.suffix = '%';
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
this.decimalPrecision = this.configProps$?.decimalPrecision ?? 2;
|
|
100
94
|
}
|
|
101
95
|
|
|
102
96
|
fieldOnBlur(event: any) {
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
if (isValueChanged) {
|
|
107
|
-
const actionsApi = this.pConn$?.getActionsApi();
|
|
108
|
-
const propName = this.pConn$?.getStateProps().value;
|
|
109
|
-
let value = event?.target?.value;
|
|
110
|
-
// replacing thousand separator with empty string as not required in api call
|
|
111
|
-
if (this.configProps$.showGroupSeparators) {
|
|
112
|
-
const thousandSep = this.thousandSeparator === '.' ? '\\.' : this.thousandSeparator;
|
|
113
|
-
const regExp = new RegExp(String.raw`${thousandSep}`, 'g');
|
|
114
|
-
value = value?.replace(regExp, '');
|
|
115
|
-
}
|
|
116
|
-
// replacing decimal separator with '.'
|
|
117
|
-
if (this.decimalSeparator !== '.') {
|
|
118
|
-
const regExp = new RegExp(String.raw`${this.decimalSeparator}`, 'g');
|
|
119
|
-
value = value.replace(regExp, '.');
|
|
120
|
-
}
|
|
121
|
-
handleEvent(actionsApi, 'changeNblur', propName, value);
|
|
122
|
-
}
|
|
97
|
+
const parsed = parseFormattedNumber(event?.target?.value, this.inputFormat);
|
|
98
|
+
saveNumberOnBlur(this.pConn$, parsed !== '' ? Number(parsed) : '', this.configProps$?.value);
|
|
123
99
|
}
|
|
124
100
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<div *ngIf="displayMode$; else noDisplayMode">
|
|
2
|
-
<component-mapper *ngIf="bVisible$ !== false" name="FieldValueList" [props]="{ label$, value
|
|
2
|
+
<component-mapper *ngIf="bVisible$ !== false" name="FieldValueList" [props]="{ label$, value$: formattedValue, displayMode$ }"></component-mapper>
|
|
3
3
|
</div>
|
|
4
4
|
<ng-template #noDisplayMode>
|
|
5
5
|
<div *ngIf="!bReadonly$ && bHasForm$; else noEdit">
|
|
@@ -8,10 +8,19 @@
|
|
|
8
8
|
<mat-label>{{ label$ }}</mat-label>
|
|
9
9
|
<input
|
|
10
10
|
matInput
|
|
11
|
+
type="text"
|
|
12
|
+
currencyMask
|
|
13
|
+
[options]="{
|
|
14
|
+
prefix: '',
|
|
15
|
+
suffix: '',
|
|
16
|
+
thousands: thousandSeparator,
|
|
17
|
+
decimal: decimalSeparator,
|
|
18
|
+
align: 'left',
|
|
19
|
+
nullable: true,
|
|
20
|
+
precision: 0,
|
|
21
|
+
inputMode: inputMode
|
|
22
|
+
}"
|
|
11
23
|
[placeholder]="placeholder"
|
|
12
|
-
type="number"
|
|
13
|
-
step="1"
|
|
14
|
-
[value]="value$"
|
|
15
24
|
[required]="bRequired$"
|
|
16
25
|
[formControl]="fieldControl"
|
|
17
26
|
[attr.data-test-id]="testId"
|
|
@@ -3,26 +3,48 @@ import { CommonModule } from '@angular/common';
|
|
|
3
3
|
import { FormControl, ReactiveFormsModule } from '@angular/forms';
|
|
4
4
|
import { MatInputModule } from '@angular/material/input';
|
|
5
5
|
import { MatFormFieldModule } from '@angular/material/form-field';
|
|
6
|
+
import { NgxCurrencyDirective, NgxCurrencyInputMode } from 'ngx-currency';
|
|
6
7
|
|
|
7
8
|
import { FieldBase } from '@pega/angular-sdk-components';
|
|
8
9
|
import { ComponentMapperComponent } from '@pega/angular-sdk-components';
|
|
9
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
formatNumberFieldForDisplay,
|
|
12
|
+
getNumberInputFormat,
|
|
13
|
+
NumberInputFormat,
|
|
14
|
+
parseFormattedNumber,
|
|
15
|
+
saveNumberOnBlur
|
|
16
|
+
} from '@pega/angular-sdk-components';
|
|
10
17
|
import { PConnFieldProps } from '@pega/angular-sdk-components';
|
|
11
18
|
|
|
12
|
-
interface IntegerProps extends PConnFieldProps {
|
|
19
|
+
interface IntegerProps extends Omit<PConnFieldProps, 'value'> {
|
|
13
20
|
// If any, enter additional props that only exist on Integer here
|
|
21
|
+
value?: number | string;
|
|
22
|
+
showGroupSeparators?: boolean | string;
|
|
23
|
+
formatter?: string;
|
|
24
|
+
decimalPrecision?: number | string;
|
|
25
|
+
currencyISOCode?: string;
|
|
26
|
+
currencyDisplay?: 'symbol' | 'code' | 'name';
|
|
27
|
+
negative?: 'minus-sign' | 'parentheses';
|
|
28
|
+
notation?: 'standard' | 'compact';
|
|
29
|
+
currencyDecimalPrecision?: string;
|
|
14
30
|
}
|
|
15
31
|
|
|
16
32
|
@Component({
|
|
17
33
|
selector: 'app-integer',
|
|
18
34
|
templateUrl: './integer.component.html',
|
|
19
35
|
styleUrls: ['./integer.component.scss'],
|
|
20
|
-
imports: [CommonModule, ReactiveFormsModule, MatFormFieldModule, MatInputModule, forwardRef(() => ComponentMapperComponent)]
|
|
36
|
+
imports: [CommonModule, ReactiveFormsModule, MatFormFieldModule, MatInputModule, NgxCurrencyDirective, forwardRef(() => ComponentMapperComponent)]
|
|
21
37
|
})
|
|
22
38
|
export class IntegerComponent extends FieldBase {
|
|
23
39
|
configProps$: IntegerProps;
|
|
24
40
|
override fieldControl = new FormControl<number | null>(null, null);
|
|
25
41
|
|
|
42
|
+
decimalSeparator: string;
|
|
43
|
+
thousandSeparator: string;
|
|
44
|
+
formattedValue: string;
|
|
45
|
+
inputMode: any = NgxCurrencyInputMode.Natural;
|
|
46
|
+
private inputFormat: NumberInputFormat;
|
|
47
|
+
|
|
26
48
|
/**
|
|
27
49
|
* Updates the component when there are changes in the state.
|
|
28
50
|
*/
|
|
@@ -35,8 +57,25 @@ export class IntegerComponent extends FieldBase {
|
|
|
35
57
|
|
|
36
58
|
// Extract and normalize the value property
|
|
37
59
|
const { value } = this.configProps$;
|
|
38
|
-
|
|
39
|
-
|
|
60
|
+
this.value$ = value === undefined || value === null || value === '' ? '' : Number(value);
|
|
61
|
+
this.fieldControl.setValue(this.value$ === '' ? null : this.value$);
|
|
62
|
+
|
|
63
|
+
this.updateIntegerProperties(this.configProps$);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Updates the input mask and read-only value, matching the Constellation DX Integer component.
|
|
68
|
+
*/
|
|
69
|
+
protected updateIntegerProperties(configProps: IntegerProps): void {
|
|
70
|
+
const { showGroupSeparators = true } = configProps;
|
|
71
|
+
const groupSeparators = this.utils.getBooleanValue(showGroupSeparators);
|
|
72
|
+
|
|
73
|
+
this.inputFormat = getNumberInputFormat();
|
|
74
|
+
this.decimalSeparator = this.inputFormat.decimalSeparator;
|
|
75
|
+
this.thousandSeparator = groupSeparators ? this.inputFormat.thousandSeparator : '';
|
|
76
|
+
|
|
77
|
+
if (['DISPLAY_ONLY', 'STACKED_LARGE_VAL'].includes(this.displayMode$)) {
|
|
78
|
+
this.formattedValue = formatNumberFieldForDisplay('Integer', this.value$, configProps);
|
|
40
79
|
}
|
|
41
80
|
}
|
|
42
81
|
|
|
@@ -52,12 +91,7 @@ export class IntegerComponent extends FieldBase {
|
|
|
52
91
|
}
|
|
53
92
|
|
|
54
93
|
fieldOnBlur(event: any) {
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
if (isValueChanged) {
|
|
59
|
-
const value = event?.target?.value;
|
|
60
|
-
handleEvent(this.actionsApi, 'changeNblur', this.propName, value);
|
|
61
|
-
}
|
|
94
|
+
const parsed = parseFormattedNumber(event?.target?.value, this.inputFormat);
|
|
95
|
+
saveNumberOnBlur(this.pConn$, parsed !== '' ? Number(parsed) : '', this.configProps$?.value);
|
|
62
96
|
}
|
|
63
97
|
}
|
|
@@ -7,16 +7,24 @@ import { NgxCurrencyDirective, NgxCurrencyInputMode } from 'ngx-currency';
|
|
|
7
7
|
|
|
8
8
|
import { FieldBase } from '@pega/angular-sdk-components';
|
|
9
9
|
import { ComponentMapperComponent } from '@pega/angular-sdk-components';
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
import {
|
|
11
|
+
decimalsToPercentage,
|
|
12
|
+
formatNumberFieldForDisplay,
|
|
13
|
+
getNumberInputFormat,
|
|
14
|
+
NumberInputFormat,
|
|
15
|
+
parseDecimalPrecision,
|
|
16
|
+
parseFormattedNumber,
|
|
17
|
+
percentageToDecimals,
|
|
18
|
+
saveNumberOnBlur
|
|
19
|
+
} from '@pega/angular-sdk-components';
|
|
13
20
|
import { PConnFieldProps } from '@pega/angular-sdk-components';
|
|
14
21
|
|
|
15
22
|
interface PercentageProps extends Omit<PConnFieldProps, 'value'> {
|
|
16
|
-
value?: number;
|
|
17
|
-
showGroupSeparators?: string;
|
|
18
|
-
decimalPrecision?: number;
|
|
23
|
+
value?: number | string;
|
|
24
|
+
showGroupSeparators?: boolean | string;
|
|
25
|
+
decimalPrecision?: number | string;
|
|
19
26
|
currencyISOCode?: string;
|
|
27
|
+
storePercentageAsDecimal?: boolean | string;
|
|
20
28
|
// If any, enter additional props that only exist on Percentage here
|
|
21
29
|
}
|
|
22
30
|
|
|
@@ -30,11 +38,16 @@ export class PercentageComponent extends FieldBase {
|
|
|
30
38
|
configProps$: PercentageProps;
|
|
31
39
|
override fieldControl = new FormControl<number | null>(null, null);
|
|
32
40
|
|
|
41
|
+
prefix: string;
|
|
42
|
+
suffix: string;
|
|
33
43
|
decimalSeparator: string;
|
|
34
44
|
thousandSeparator: string;
|
|
35
45
|
inputMode: any = NgxCurrencyInputMode.Natural;
|
|
36
46
|
decimalPrecision: number | undefined;
|
|
37
47
|
formattedValue: string;
|
|
48
|
+
private inputFormat: NumberInputFormat;
|
|
49
|
+
private numberOfDecimals: number | undefined;
|
|
50
|
+
private storeAsDecimal = false;
|
|
38
51
|
|
|
39
52
|
/**
|
|
40
53
|
* Updates the component when there are changes in the state.
|
|
@@ -46,34 +59,39 @@ export class PercentageComponent extends FieldBase {
|
|
|
46
59
|
// Update component common properties
|
|
47
60
|
this.updateComponentCommonProperties(this.configProps$);
|
|
48
61
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
62
|
+
const { value, decimalPrecision, storePercentageAsDecimal } = this.configProps$;
|
|
63
|
+
this.numberOfDecimals = parseDecimalPrecision(decimalPrecision, 2);
|
|
64
|
+
this.storeAsDecimal = this.utils.getBooleanValue(storePercentageAsDecimal);
|
|
65
|
+
|
|
66
|
+
// The stored value may be a fraction (0.25); the field always shows/edits the percentage (25)
|
|
67
|
+
if (value === undefined || value === null || value === '') {
|
|
68
|
+
this.value$ = '';
|
|
69
|
+
} else {
|
|
70
|
+
this.value$ = this.storeAsDecimal && Number(value) ? decimalsToPercentage(Number(value), this.numberOfDecimals) : Number(value);
|
|
54
71
|
}
|
|
72
|
+
this.fieldControl.setValue(this.value$ === '' ? null : this.value$);
|
|
55
73
|
|
|
56
74
|
// update percentage properties
|
|
57
75
|
this.updatePercentageProperties(this.configProps$);
|
|
58
76
|
}
|
|
59
77
|
|
|
60
78
|
/**
|
|
61
|
-
* Updates the
|
|
62
|
-
*
|
|
63
|
-
* @param {Object} configProps - Configuration properties.
|
|
64
|
-
* @param {boolean} configProps.showGroupSeparators - Whether to show group separators.
|
|
65
|
-
* @param {number} configProps.decimalPrecision - The number of decimal places to display.
|
|
79
|
+
* Updates the input mask and read-only value, matching the Constellation DX Percentage component.
|
|
66
80
|
*/
|
|
67
|
-
updatePercentageProperties(configProps): void {
|
|
68
|
-
const { showGroupSeparators
|
|
81
|
+
updatePercentageProperties(configProps: PercentageProps): void {
|
|
82
|
+
const { showGroupSeparators = false } = configProps;
|
|
83
|
+
const groupSeparators = this.utils.getBooleanValue(showGroupSeparators);
|
|
69
84
|
|
|
70
|
-
|
|
71
|
-
this.
|
|
72
|
-
this.
|
|
73
|
-
this.
|
|
85
|
+
this.inputFormat = getNumberInputFormat('percent');
|
|
86
|
+
this.prefix = this.inputFormat.prefix;
|
|
87
|
+
this.suffix = this.inputFormat.suffix;
|
|
88
|
+
this.decimalSeparator = this.inputFormat.decimalSeparator;
|
|
89
|
+
this.thousandSeparator = groupSeparators ? this.inputFormat.thousandSeparator : '';
|
|
90
|
+
// ngx-currency needs a fixed precision; Constellation allows any number of decimals when none is configured
|
|
91
|
+
this.decimalPrecision = this.numberOfDecimals ?? 2;
|
|
74
92
|
|
|
75
93
|
if (['DISPLAY_ONLY', 'STACKED_LARGE_VAL'].includes(this.displayMode$)) {
|
|
76
|
-
this.formattedValue =
|
|
94
|
+
this.formattedValue = formatNumberFieldForDisplay('Percentage', this.value$, configProps);
|
|
77
95
|
}
|
|
78
96
|
}
|
|
79
97
|
|
|
@@ -89,24 +107,11 @@ export class PercentageComponent extends FieldBase {
|
|
|
89
107
|
}
|
|
90
108
|
|
|
91
109
|
fieldOnBlur(event: any) {
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
let value = event?.target?.value;
|
|
97
|
-
value = value ? value.replace(/%/g, '') : '';
|
|
98
|
-
// replacing thousand separator with empty string as not required in api call
|
|
99
|
-
if (this.configProps$.showGroupSeparators) {
|
|
100
|
-
const thousandSep = this.thousandSeparator === '.' ? '\\.' : this.thousandSeparator;
|
|
101
|
-
const regExp = new RegExp(String.raw`${thousandSep}`, 'g');
|
|
102
|
-
value = value?.replace(regExp, '');
|
|
103
|
-
}
|
|
104
|
-
// replacing decimal separator with '.'
|
|
105
|
-
if (this.decimalSeparator !== '.') {
|
|
106
|
-
const regExp = new RegExp(String.raw`${this.decimalSeparator}`, 'g');
|
|
107
|
-
value = value.replace(regExp, '.');
|
|
108
|
-
}
|
|
109
|
-
handleEvent(this.actionsApi, 'changeNblur', this.propName, value);
|
|
110
|
+
const parsed = parseFormattedNumber(event?.target?.value, this.inputFormat);
|
|
111
|
+
let newValue: number | '' = parsed !== '' ? Number(parsed) : '';
|
|
112
|
+
if (this.storeAsDecimal && newValue !== '') {
|
|
113
|
+
newValue = percentageToDecimals(newValue, this.numberOfDecimals);
|
|
110
114
|
}
|
|
115
|
+
saveNumberOnBlur(this.pConn$, newValue, this.configProps$?.value);
|
|
111
116
|
}
|
|
112
117
|
}
|
|
@@ -110,7 +110,6 @@ export class NavbarComponent implements OnInit, OnDestroy {
|
|
|
110
110
|
|
|
111
111
|
// making a copy, so can add info
|
|
112
112
|
this.navPages$ = JSON.parse(JSON.stringify(this.pages$));
|
|
113
|
-
// @ts-ignore
|
|
114
113
|
const localeReference = PCore.getLocaleUtils().getPortalLocaleReference() || this.pConn$.getValue('.pyLocaleReference');
|
|
115
114
|
this.navPages$.forEach(page => {
|
|
116
115
|
const destinationObject: any = {};
|
|
@@ -88,8 +88,7 @@ export class ReferenceComponent implements OnInit, OnDestroy, OnChanges {
|
|
|
88
88
|
}
|
|
89
89
|
};
|
|
90
90
|
|
|
91
|
-
|
|
92
|
-
const viewComponent: any = pConnect.createComponent(viewObject, null, null, {
|
|
91
|
+
const viewComponent: any = pConnect.createComponent(viewObject, '', 0, {
|
|
93
92
|
pageReference: context && context.startsWith('@CLASS') ? '' : context
|
|
94
93
|
});
|
|
95
94
|
|
|
@@ -71,7 +71,6 @@ export class AdvancedSearchComponent implements OnInit, OnChanges {
|
|
|
71
71
|
const [firstChildMeta] = rawViewMetadata.children;
|
|
72
72
|
|
|
73
73
|
const localizedVal = PCore.getLocaleUtils().getLocaleValue;
|
|
74
|
-
// @ts-ignore
|
|
75
74
|
const cache = PCore.getNavigationUtils().getComponentCache(searchSelectCacheKey) ?? {};
|
|
76
75
|
|
|
77
76
|
this.editableFieldComp = firstChildPConnect().createComponent({
|
|
@@ -210,8 +210,7 @@ export class SearchGroupsComponent implements OnInit, OnDestroy, OnChanges {
|
|
|
210
210
|
isValidInput(formValues)
|
|
211
211
|
) {
|
|
212
212
|
if (this.isValidatorField) {
|
|
213
|
-
|
|
214
|
-
PCore.getMessageManager().clearContextMessages({ context: transientItemID });
|
|
213
|
+
PCore.getMessageManager().clearContextMessages({ context: this.transientItemID });
|
|
215
214
|
}
|
|
216
215
|
|
|
217
216
|
this.previousFormValues = formValues;
|
|
@@ -220,13 +219,13 @@ export class SearchGroupsComponent implements OnInit, OnDestroy, OnChanges {
|
|
|
220
219
|
PCore.getPubSubUtils().publish(PCore.getEvents().getTransientEvent().UPDATE_PROMOTED_FILTERS, {
|
|
221
220
|
payload: formValues,
|
|
222
221
|
showRecords: true,
|
|
223
|
-
viewName: this.getPConnect.getCurrentView()
|
|
222
|
+
viewName: this.getPConnect().getCurrentView()
|
|
224
223
|
});
|
|
225
224
|
}
|
|
226
225
|
|
|
227
226
|
this.state.activeGroupId = this.activeGroupId;
|
|
228
227
|
this.state.searchFields = changes;
|
|
229
|
-
this.state.selectedCategory = this.getPConnect.getCurrentView();
|
|
228
|
+
this.state.selectedCategory = this.getPConnect().getCurrentView();
|
|
230
229
|
const options = componentCachePersistUtils.getComponentStateOptions(this.getPConnect);
|
|
231
230
|
componentCachePersistUtils.setComponentCache({
|
|
232
231
|
cacheKey: this.searchSelectCacheKey,
|
|
@@ -89,7 +89,6 @@ export class AppShellComponent implements OnInit, OnDestroy {
|
|
|
89
89
|
PCore.getEnvironmentInfo().setEnvironmentInfo({ ...PCore.getEnvironmentInfo().environmentInfoObject, pyPortalTemplate: 'wss' } as any);
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
-
// @ts-ignore - Property 'pyCaseTypesAvailableToCreateDP' does not exist on type pxApplication
|
|
93
92
|
const caseTypesAvailableToCreateDP = PCore.getEnvironmentInfo().environmentInfoObject?.pxApplication?.pyCaseTypesAvailableToCreateDP;
|
|
94
93
|
if (caseTypesAvailableToCreateDP) {
|
|
95
94
|
const portalID = this.pConn$.getValue('.pyOwner');
|
|
@@ -398,7 +398,6 @@ export class DataReferenceComponent implements OnInit, OnDestroy {
|
|
|
398
398
|
if (['Dropdown', 'Checkbox', 'RadioButtons'].includes(type) && !config.deferDatasource && config.datasource) {
|
|
399
399
|
const isCardVariant = config.variant === 'card';
|
|
400
400
|
const hasParameters = this.rawViewMetadata.config?.parameters;
|
|
401
|
-
// @ts-ignore
|
|
402
401
|
const isDeferDataPageCallEnabled = isCardVariant && hasParameters && !this.firstChildPConnect()?.getSharedDataPageForReferenceList();
|
|
403
402
|
|
|
404
403
|
const useDropDownDataSource = (isCardVariant && (this.dropDownDataSource || isDeferDataPageCallEnabled)) || (!isCardVariant && hasParameters);
|
|
@@ -127,7 +127,6 @@ export function getData(deferLoadedTabs, tabCountSources, currentTabId, data) {
|
|
|
127
127
|
});
|
|
128
128
|
} else if (calculatedFieldsWithoutValue.length) {
|
|
129
129
|
PCore.getViewRuleApi()
|
|
130
|
-
// @ts-ignore
|
|
131
130
|
.getCalculatedFields(
|
|
132
131
|
pConn.getCaseInfo().getKey(),
|
|
133
132
|
pConn.getCurrentView(),
|
|
@@ -346,7 +346,6 @@ export class ListViewComponent implements OnInit, OnDestroy {
|
|
|
346
346
|
}
|
|
347
347
|
|
|
348
348
|
getFieldsMetadata(refList) {
|
|
349
|
-
// @ts-ignore - 3rd parameter "associationFilter" should be optional for getDataViewMetadata method
|
|
350
349
|
return PCore.getAnalyticsUtils().getDataViewMetadata(refList, this.showDynamicFields);
|
|
351
350
|
}
|
|
352
351
|
|
|
@@ -217,7 +217,7 @@ export const updateFieldLabels = (fields, configFields, primaryFieldsViewIndex,
|
|
|
217
217
|
let label = configFields[i].config?.label;
|
|
218
218
|
if (isFLProperty(label)) {
|
|
219
219
|
label = getFieldLabel(configFields[i].config);
|
|
220
|
-
} else if (label
|
|
220
|
+
} else if (label?.startsWith('@')) {
|
|
221
221
|
label = label.substring(3);
|
|
222
222
|
}
|
|
223
223
|
if (pConnect) {
|
package/lib/template/utils.ts
CHANGED
|
@@ -32,7 +32,6 @@ export const evaluateAllowRowAction = (allowRowDelete, rowData) => {
|
|
|
32
32
|
if (allowRowDelete === undefined || allowRowDelete === true) return true;
|
|
33
33
|
if (allowRowDelete.startsWith?.('@E ')) {
|
|
34
34
|
const expression = allowRowDelete.replace('@E ', '');
|
|
35
|
-
// @ts-ignore - Expected 3 arguments, but got 2
|
|
36
35
|
return PCore.getExpressionEngine().evaluate(expression, rowData);
|
|
37
36
|
}
|
|
38
37
|
return false;
|