ngx-dynamic-entity 0.0.1 → 1.1.0
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/README.md +129 -0
- package/esm2022/lib/field-types/array-field.component.mjs +160 -0
- package/esm2022/lib/field-types/boolean-field.component.mjs +100 -0
- package/esm2022/lib/field-types/checkbox-field.component.mjs +25 -17
- package/esm2022/lib/field-types/currency-field.component.mjs +101 -0
- package/esm2022/lib/field-types/date-field.component.mjs +21 -13
- package/esm2022/lib/field-types/dropdown-field.component.mjs +120 -29
- package/esm2022/lib/field-types/email-field.component.mjs +101 -0
- package/esm2022/lib/field-types/entity-ref-field.component.mjs +96 -32
- package/esm2022/lib/field-types/file-field.component.mjs +156 -0
- package/esm2022/lib/field-types/group-field.component.mjs +89 -0
- package/esm2022/lib/field-types/image-field.component.mjs +168 -0
- package/esm2022/lib/field-types/month-year-field.component.mjs +151 -0
- package/esm2022/lib/field-types/multi-select-field.component.mjs +79 -25
- package/esm2022/lib/field-types/number-field.component.mjs +60 -17
- package/esm2022/lib/field-types/password-field.component.mjs +109 -0
- package/esm2022/lib/field-types/radio-field.component.mjs +152 -0
- package/esm2022/lib/field-types/text-field.component.mjs +58 -18
- package/esm2022/lib/field-types/textarea-field.component.mjs +26 -15
- package/esm2022/lib/form/dynamic-field/dynamic-field.component.mjs +44 -26
- package/esm2022/lib/form/dynamic-form.component.mjs +676 -69
- package/esm2022/lib/form/dynamic-record-form.component.mjs +494 -0
- package/esm2022/lib/providers/provide-field-types.mjs +72 -0
- package/esm2022/lib/providers/provide-ngx-dynamic-entity.mjs +4 -5
- package/esm2022/lib/services/cascade-data.service.mjs +129 -0
- package/esm2022/lib/services/config-source.service.mjs +67 -0
- package/esm2022/lib/services/entity-ref-cache.mjs +20 -0
- package/esm2022/lib/services/entity-ref-registry.service.mjs +3 -3
- package/esm2022/lib/services/entity-ref-selection.service.mjs +27 -0
- package/esm2022/lib/services/entity-reference.service.mjs +168 -0
- package/esm2022/lib/services/field-registry.service.mjs +35 -30
- package/esm2022/lib/services/file-upload.service.mjs +89 -0
- package/esm2022/lib/services/lookup-registry.service.mjs +246 -0
- package/esm2022/lib/services/rbac.service.mjs +5 -11
- package/esm2022/lib/services/rules-evaluation.service.mjs +27 -0
- package/esm2022/lib/services/validator-registry.service.mjs +35 -7
- package/esm2022/lib/tokens/injection-tokens.mjs +104 -7
- package/esm2022/public-api.mjs +31 -6
- package/fesm2022/ngx-dynamic-entity.mjs +4094 -759
- package/fesm2022/ngx-dynamic-entity.mjs.map +1 -1
- package/lib/field-types/array-field.component.d.ts +22 -0
- package/lib/field-types/boolean-field.component.d.ts +18 -0
- package/lib/field-types/checkbox-field.component.d.ts +3 -2
- package/lib/field-types/currency-field.component.d.ts +17 -0
- package/lib/field-types/date-field.component.d.ts +3 -2
- package/lib/field-types/dropdown-field.component.d.ts +24 -4
- package/lib/field-types/email-field.component.d.ts +15 -0
- package/lib/field-types/entity-ref-field.component.d.ts +24 -11
- package/lib/field-types/file-field.component.d.ts +25 -0
- package/lib/field-types/group-field.component.d.ts +17 -0
- package/lib/field-types/image-field.component.d.ts +30 -0
- package/lib/field-types/month-year-field.component.d.ts +28 -0
- package/lib/field-types/multi-select-field.component.d.ts +18 -4
- package/lib/field-types/number-field.component.d.ts +5 -2
- package/lib/field-types/password-field.component.d.ts +17 -0
- package/lib/field-types/radio-field.component.d.ts +33 -0
- package/lib/field-types/text-field.component.d.ts +5 -3
- package/lib/field-types/textarea-field.component.d.ts +4 -2
- package/lib/form/dynamic-field/dynamic-field.component.d.ts +20 -7
- package/lib/form/dynamic-form.component.d.ts +203 -24
- package/lib/form/dynamic-record-form.component.d.ts +180 -0
- package/lib/providers/provide-field-types.d.ts +24 -0
- package/lib/providers/provide-ngx-dynamic-entity.d.ts +19 -8
- package/lib/services/cascade-data.service.d.ts +45 -0
- package/lib/services/config-source.service.d.ts +14 -0
- package/lib/services/entity-ref-cache.d.ts +27 -0
- package/lib/services/entity-ref-registry.service.d.ts +4 -3
- package/lib/services/entity-ref-selection.service.d.ts +24 -0
- package/lib/services/entity-reference.service.d.ts +49 -0
- package/lib/services/field-registry.service.d.ts +17 -7
- package/lib/services/file-upload.service.d.ts +27 -0
- package/lib/services/lookup-registry.service.d.ts +94 -0
- package/lib/services/rbac.service.d.ts +4 -9
- package/lib/services/rules-evaluation.service.d.ts +17 -0
- package/lib/services/validator-registry.service.d.ts +5 -4
- package/lib/tokens/injection-tokens.d.ts +113 -8
- package/package.json +18 -8
- package/public-api.d.ts +21 -4
- package/esm2022/lib/services/config.service.mjs +0 -58
- package/esm2022/lib/services/version.service.mjs +0 -40
- package/esm2022/lib/table/dynamic-table.component.mjs +0 -160
- package/lib/services/config.service.d.ts +0 -25
- package/lib/services/version.service.d.ts +0 -26
- package/lib/table/dynamic-table.component.d.ts +0 -56
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Component, Input } from '@angular/core';
|
|
2
2
|
import { ReactiveFormsModule } from '@angular/forms';
|
|
3
|
+
import { resolveLabel } from '@dynamic-entity/core';
|
|
3
4
|
import * as i0 from "@angular/core";
|
|
4
5
|
import * as i1 from "@angular/forms";
|
|
5
6
|
export class DateFieldComponent {
|
|
@@ -8,6 +9,9 @@ export class DateFieldComponent {
|
|
|
8
9
|
language = 'en';
|
|
9
10
|
readonly = false;
|
|
10
11
|
masked = false;
|
|
12
|
+
get label() {
|
|
13
|
+
return resolveLabel(this.field?.label, this.language);
|
|
14
|
+
}
|
|
11
15
|
/** ISO 8601 date → locale display string (ONEHERMES convention: always UTC, display in user locale) */
|
|
12
16
|
formatDate(value) {
|
|
13
17
|
if (!value)
|
|
@@ -21,21 +25,23 @@ export class DateFieldComponent {
|
|
|
21
25
|
}
|
|
22
26
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: DateFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
23
27
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: DateFieldComponent, isStandalone: true, selector: "ngx-date-field", inputs: { field: "field", control: "control", language: "language", readonly: "readonly", masked: "masked" }, ngImport: i0, template: `
|
|
24
|
-
<div class="ngx-field ngx-field--date"
|
|
25
|
-
|
|
28
|
+
<div class="ngx-field ngx-field--date"
|
|
29
|
+
[attr.data-testid]="'field-' + field.id" [attr.data-field-type]="field.type" [class.ngx-field--readonly]="readonly" [class.ngx-field--masked]="masked">
|
|
30
|
+
<label class="ngx-field__label" [attr.for]="field.id">{{ label }}</label>
|
|
26
31
|
@if (masked) {
|
|
27
|
-
<span class="ngx-field__value ngx-field__value--masked">XXXXXXXXX</span>
|
|
32
|
+
<span class="ngx-field__value ngx-field__value--masked" [attr.data-testid]="'field-' + field.id + '-masked'">XXXXXXXXX</span>
|
|
28
33
|
} @else if (readonly) {
|
|
29
|
-
<span class="ngx-field__value">{{ formatDate(control.value) }}</span>
|
|
34
|
+
<span class="ngx-field__value" [attr.data-testid]="'field-' + field.id + '-value'">{{ formatDate(control.value) }}</span>
|
|
30
35
|
} @else {
|
|
31
36
|
<input
|
|
32
|
-
|
|
37
|
+
[id]="field.id"
|
|
38
|
+
class="ngx-field__input" [attr.data-testid]="'field-' + field.id + '-input'"
|
|
33
39
|
type="date"
|
|
34
40
|
[formControl]="$any(control)"
|
|
35
41
|
[attr.disabled]="field.disabled ? true : null"
|
|
36
42
|
/>
|
|
37
43
|
@if (control.invalid && control.touched) {
|
|
38
|
-
<span class="ngx-field__error">This field has an error</span>
|
|
44
|
+
<span class="ngx-field__error" [attr.data-testid]="'field-' + field.id + '-error'">This field has an error</span>
|
|
39
45
|
}
|
|
40
46
|
}
|
|
41
47
|
</div>
|
|
@@ -48,21 +54,23 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
|
|
|
48
54
|
standalone: true,
|
|
49
55
|
imports: [ReactiveFormsModule],
|
|
50
56
|
template: `
|
|
51
|
-
<div class="ngx-field ngx-field--date"
|
|
52
|
-
|
|
57
|
+
<div class="ngx-field ngx-field--date"
|
|
58
|
+
[attr.data-testid]="'field-' + field.id" [attr.data-field-type]="field.type" [class.ngx-field--readonly]="readonly" [class.ngx-field--masked]="masked">
|
|
59
|
+
<label class="ngx-field__label" [attr.for]="field.id">{{ label }}</label>
|
|
53
60
|
@if (masked) {
|
|
54
|
-
<span class="ngx-field__value ngx-field__value--masked">XXXXXXXXX</span>
|
|
61
|
+
<span class="ngx-field__value ngx-field__value--masked" [attr.data-testid]="'field-' + field.id + '-masked'">XXXXXXXXX</span>
|
|
55
62
|
} @else if (readonly) {
|
|
56
|
-
<span class="ngx-field__value">{{ formatDate(control.value) }}</span>
|
|
63
|
+
<span class="ngx-field__value" [attr.data-testid]="'field-' + field.id + '-value'">{{ formatDate(control.value) }}</span>
|
|
57
64
|
} @else {
|
|
58
65
|
<input
|
|
59
|
-
|
|
66
|
+
[id]="field.id"
|
|
67
|
+
class="ngx-field__input" [attr.data-testid]="'field-' + field.id + '-input'"
|
|
60
68
|
type="date"
|
|
61
69
|
[formControl]="$any(control)"
|
|
62
70
|
[attr.disabled]="field.disabled ? true : null"
|
|
63
71
|
/>
|
|
64
72
|
@if (control.invalid && control.touched) {
|
|
65
|
-
<span class="ngx-field__error">This field has an error</span>
|
|
73
|
+
<span class="ngx-field__error" [attr.data-testid]="'field-' + field.id + '-error'">This field has an error</span>
|
|
66
74
|
}
|
|
67
75
|
}
|
|
68
76
|
</div>
|
|
@@ -79,4 +87,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
|
|
|
79
87
|
}], masked: [{
|
|
80
88
|
type: Input
|
|
81
89
|
}] } });
|
|
82
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
90
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0ZS1maWVsZC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL2ZpZWxkLXR5cGVzL2RhdGUtZmllbGQuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ2pELE9BQU8sRUFBbUIsbUJBQW1CLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUV0RSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7OztBQTZCcEQsTUFBTSxPQUFPLGtCQUFrQjtJQUNwQixLQUFLLENBQXFCO0lBQzFCLE9BQU8sQ0FBbUI7SUFDMUIsUUFBUSxHQUFXLElBQUksQ0FBQztJQUN4QixRQUFRLEdBQVksS0FBSyxDQUFDO0lBQzFCLE1BQU0sR0FBWSxLQUFLLENBQUM7SUFFakMsSUFBSSxLQUFLO1FBQ1AsT0FBTyxZQUFZLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxLQUFLLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ3hELENBQUM7SUFFRCx1R0FBdUc7SUFDdkcsVUFBVSxDQUFDLEtBQW9CO1FBQzdCLElBQUksQ0FBQyxLQUFLO1lBQUUsT0FBTyxHQUFHLENBQUM7UUFDdkIsSUFBSSxDQUFDO1lBQ0gsT0FBTyxJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO1FBQzlDLENBQUM7UUFBQyxNQUFNLENBQUM7WUFDUCxPQUFPLEtBQUssQ0FBQztRQUNmLENBQUM7SUFDSCxDQUFDO3dHQW5CVSxrQkFBa0I7NEZBQWxCLGtCQUFrQix3TEF2Qm5COzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FxQlQsMkRBdEJTLG1CQUFtQjs7NEZBd0JsQixrQkFBa0I7a0JBM0I5QixTQUFTO21CQUFDO29CQUNULFFBQVEsRUFBRSxnQkFBZ0I7b0JBQzFCLFVBQVUsRUFBRSxJQUFJO29CQUNoQixPQUFPLEVBQUUsQ0FBQyxtQkFBbUIsQ0FBQztvQkFDOUIsUUFBUSxFQUFFOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FxQlQ7aUJBQ0Y7OEJBRVUsS0FBSztzQkFBYixLQUFLO2dCQUNHLE9BQU87c0JBQWYsS0FBSztnQkFDRyxRQUFRO3NCQUFoQixLQUFLO2dCQUNHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBQ0csTUFBTTtzQkFBZCxLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBJbnB1dCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQWJzdHJhY3RDb250cm9sLCBSZWFjdGl2ZUZvcm1zTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHR5cGUgeyBOZXN0ZWRGaWVsZENvbmZpZyB9IGZyb20gJ0BkeW5hbWljLWVudGl0eS9jb3JlJztcbmltcG9ydCB7IHJlc29sdmVMYWJlbCB9IGZyb20gJ0BkeW5hbWljLWVudGl0eS9jb3JlJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnbmd4LWRhdGUtZmllbGQnLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbUmVhY3RpdmVGb3Jtc01vZHVsZV0sXG4gIHRlbXBsYXRlOiBgXG4gICAgPGRpdiBjbGFzcz1cIm5neC1maWVsZCBuZ3gtZmllbGQtLWRhdGVcIlxuICAgICAgW2F0dHIuZGF0YS10ZXN0aWRdPVwiJ2ZpZWxkLScgKyBmaWVsZC5pZFwiIFthdHRyLmRhdGEtZmllbGQtdHlwZV09XCJmaWVsZC50eXBlXCIgW2NsYXNzLm5neC1maWVsZC0tcmVhZG9ubHldPVwicmVhZG9ubHlcIiBbY2xhc3Mubmd4LWZpZWxkLS1tYXNrZWRdPVwibWFza2VkXCI+XG4gICAgICA8bGFiZWwgY2xhc3M9XCJuZ3gtZmllbGRfX2xhYmVsXCIgW2F0dHIuZm9yXT1cImZpZWxkLmlkXCI+e3sgbGFiZWwgfX08L2xhYmVsPlxuICAgICAgQGlmIChtYXNrZWQpIHtcbiAgICAgICAgPHNwYW4gY2xhc3M9XCJuZ3gtZmllbGRfX3ZhbHVlIG5neC1maWVsZF9fdmFsdWUtLW1hc2tlZFwiIFthdHRyLmRhdGEtdGVzdGlkXT1cIidmaWVsZC0nICsgZmllbGQuaWQgKyAnLW1hc2tlZCdcIj5YWFhYWFhYWFg8L3NwYW4+XG4gICAgICB9IEBlbHNlIGlmIChyZWFkb25seSkge1xuICAgICAgICA8c3BhbiBjbGFzcz1cIm5neC1maWVsZF9fdmFsdWVcIiBbYXR0ci5kYXRhLXRlc3RpZF09XCInZmllbGQtJyArIGZpZWxkLmlkICsgJy12YWx1ZSdcIj57eyBmb3JtYXREYXRlKGNvbnRyb2wudmFsdWUpIH19PC9zcGFuPlxuICAgICAgfSBAZWxzZSB7XG4gICAgICAgIDxpbnB1dFxuICAgICAgICAgIFtpZF09XCJmaWVsZC5pZFwiXG4gICAgICAgICAgY2xhc3M9XCJuZ3gtZmllbGRfX2lucHV0XCIgW2F0dHIuZGF0YS10ZXN0aWRdPVwiJ2ZpZWxkLScgKyBmaWVsZC5pZCArICctaW5wdXQnXCJcbiAgICAgICAgICB0eXBlPVwiZGF0ZVwiXG4gICAgICAgICAgW2Zvcm1Db250cm9sXT1cIiRhbnkoY29udHJvbClcIlxuICAgICAgICAgIFthdHRyLmRpc2FibGVkXT1cImZpZWxkLmRpc2FibGVkID8gdHJ1ZSA6IG51bGxcIlxuICAgICAgICAvPlxuICAgICAgICBAaWYgKGNvbnRyb2wuaW52YWxpZCAmJiBjb250cm9sLnRvdWNoZWQpIHtcbiAgICAgICAgICA8c3BhbiBjbGFzcz1cIm5neC1maWVsZF9fZXJyb3JcIiBbYXR0ci5kYXRhLXRlc3RpZF09XCInZmllbGQtJyArIGZpZWxkLmlkICsgJy1lcnJvcidcIj5UaGlzIGZpZWxkIGhhcyBhbiBlcnJvcjwvc3Bhbj5cbiAgICAgICAgfVxuICAgICAgfVxuICAgIDwvZGl2PlxuICBgLFxufSlcbmV4cG9ydCBjbGFzcyBEYXRlRmllbGRDb21wb25lbnQge1xuICBASW5wdXQoKSBmaWVsZCE6IE5lc3RlZEZpZWxkQ29uZmlnO1xuICBASW5wdXQoKSBjb250cm9sITogQWJzdHJhY3RDb250cm9sO1xuICBASW5wdXQoKSBsYW5ndWFnZTogc3RyaW5nID0gJ2VuJztcbiAgQElucHV0KCkgcmVhZG9ubHk6IGJvb2xlYW4gPSBmYWxzZTtcbiAgQElucHV0KCkgbWFza2VkOiBib29sZWFuID0gZmFsc2U7XG5cbiAgZ2V0IGxhYmVsKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHJlc29sdmVMYWJlbCh0aGlzLmZpZWxkPy5sYWJlbCwgdGhpcy5sYW5ndWFnZSk7XG4gIH1cblxuICAvKiogSVNPIDg2MDEgZGF0ZSDihpIgbG9jYWxlIGRpc3BsYXkgc3RyaW5nIChPTkVIRVJNRVMgY29udmVudGlvbjogYWx3YXlzIFVUQywgZGlzcGxheSBpbiB1c2VyIGxvY2FsZSkgKi9cbiAgZm9ybWF0RGF0ZSh2YWx1ZTogc3RyaW5nIHwgbnVsbCk6IHN0cmluZyB7XG4gICAgaWYgKCF2YWx1ZSkgcmV0dXJuICfigJQnO1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gbmV3IERhdGUodmFsdWUpLnRvTG9jYWxlRGF0ZVN0cmluZygpO1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cbiAgfVxufVxuIl19
|
|
@@ -1,38 +1,112 @@
|
|
|
1
|
-
import { Component, Input } from '@angular/core';
|
|
1
|
+
import { Component, Input, inject, signal } from '@angular/core';
|
|
2
2
|
import { ReactiveFormsModule } from '@angular/forms';
|
|
3
|
+
import { getOptionStoredValue, resolveLabel, resolveOptionLabel, valuesMatch, } from '@dynamic-entity/core';
|
|
4
|
+
import { LookupRegistryService, refreshChoiceOptions } from '../services/lookup-registry.service';
|
|
3
5
|
import * as i0 from "@angular/core";
|
|
4
6
|
import * as i1 from "@angular/forms";
|
|
5
7
|
export class DropdownFieldComponent {
|
|
6
|
-
|
|
8
|
+
lookups = inject(LookupRegistryService);
|
|
9
|
+
_field;
|
|
10
|
+
_language = 'en';
|
|
11
|
+
/** Setter-based so options resolve however the input is set — see `refreshChoiceOptions`. */
|
|
12
|
+
set field(value) {
|
|
13
|
+
this._field = value;
|
|
14
|
+
refreshChoiceOptions(this, this.lookups);
|
|
15
|
+
}
|
|
16
|
+
get field() {
|
|
17
|
+
return this._field;
|
|
18
|
+
}
|
|
19
|
+
set language(value) {
|
|
20
|
+
this._language = value || 'en';
|
|
21
|
+
refreshChoiceOptions(this, this.lookups);
|
|
22
|
+
}
|
|
23
|
+
get language() {
|
|
24
|
+
return this._language;
|
|
25
|
+
}
|
|
7
26
|
control;
|
|
8
|
-
language = 'en';
|
|
9
27
|
readonly = false;
|
|
10
28
|
masked = false;
|
|
29
|
+
/** Inline `options`, or the field's named list resolved through the registry (§6.3). */
|
|
30
|
+
options = signal([]);
|
|
31
|
+
compareFn = (o1, o2) => valuesMatch(o1, o2, this.language);
|
|
32
|
+
isObjectVal(option) {
|
|
33
|
+
const val = getOptionStoredValue(option);
|
|
34
|
+
return typeof val === 'object' && val !== null;
|
|
35
|
+
}
|
|
36
|
+
get label() {
|
|
37
|
+
return resolveLabel(this.field?.label, this.language);
|
|
38
|
+
}
|
|
39
|
+
get placeholder() {
|
|
40
|
+
return resolveLabel(this.field?.placeholder, this.language);
|
|
41
|
+
}
|
|
42
|
+
getOptStoredVal(option) {
|
|
43
|
+
return getOptionStoredValue(option);
|
|
44
|
+
}
|
|
45
|
+
getOptLabel(option) {
|
|
46
|
+
return resolveOptionLabel(option, this.language);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Read-only display. Never awaits (§6.2): a warm list resolves the label, a cold one falls
|
|
50
|
+
* back to the stored text — which under the §2 contract *is* the display value, so it is
|
|
51
|
+
* never wrong, only unlocalised.
|
|
52
|
+
*/
|
|
11
53
|
getLabel(value) {
|
|
12
|
-
|
|
13
|
-
|
|
54
|
+
if (value == null || value === '')
|
|
55
|
+
return '—';
|
|
56
|
+
const option = this.options().find(o => valuesMatch(getOptionStoredValue(o), value, this.language));
|
|
57
|
+
if (option)
|
|
58
|
+
return this.getOptLabel(option);
|
|
59
|
+
const cached = this.lookups.labelFor(this.field?.listName, value, this.language);
|
|
60
|
+
if (cached)
|
|
61
|
+
return cached;
|
|
62
|
+
return typeof value === 'object' ? resolveLabel(value, this.language) : (value ?? '—');
|
|
63
|
+
}
|
|
64
|
+
get errorMessage() {
|
|
65
|
+
if (!this.control || !this.control.errors || !this.control.touched)
|
|
66
|
+
return '';
|
|
67
|
+
const errs = this.control.errors;
|
|
68
|
+
if (errs['required'])
|
|
69
|
+
return 'Please select an option.';
|
|
70
|
+
return 'Invalid selection.';
|
|
14
71
|
}
|
|
15
72
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: DropdownFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
16
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: DropdownFieldComponent, isStandalone: true, selector: "ngx-dropdown-field", inputs: { field: "field",
|
|
17
|
-
<div
|
|
18
|
-
|
|
73
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: DropdownFieldComponent, isStandalone: true, selector: "ngx-dropdown-field", inputs: { field: "field", language: "language", control: "control", readonly: "readonly", masked: "masked" }, ngImport: i0, template: `
|
|
74
|
+
<div
|
|
75
|
+
class="ngx-field ngx-field--dropdown"
|
|
76
|
+
[attr.data-testid]="'field-' + field.id" [attr.data-field-type]="field.type"
|
|
77
|
+
[class.ngx-field--readonly]="readonly"
|
|
78
|
+
[class.ngx-field--masked]="masked"
|
|
79
|
+
[class.ngx-field--invalid]="control && control.invalid && control.touched"
|
|
80
|
+
>
|
|
81
|
+
<label class="ngx-field__label" [attr.for]="field.id">
|
|
82
|
+
{{ label }}
|
|
83
|
+
@if (field.validators?.required) { <span class="ngx-field__req">*</span> }
|
|
84
|
+
</label>
|
|
19
85
|
@if (masked) {
|
|
20
|
-
<span class="ngx-field__value ngx-field__value--masked">XXXXXXXXX</span>
|
|
86
|
+
<span class="ngx-field__value ngx-field__value--masked" [attr.data-testid]="'field-' + field.id + '-masked'">XXXXXXXXX</span>
|
|
21
87
|
} @else if (readonly) {
|
|
22
|
-
<span class="ngx-field__value">{{ getLabel(control.value) }}</span>
|
|
88
|
+
<span class="ngx-field__value" [attr.data-testid]="'field-' + field.id + '-value'">{{ getLabel(control.value) }}</span>
|
|
23
89
|
} @else {
|
|
24
90
|
<select
|
|
25
|
-
|
|
91
|
+
[id]="field.id"
|
|
92
|
+
class="ngx-field__input" [attr.data-testid]="'field-' + field.id + '-input'"
|
|
26
93
|
[formControl]="$any(control)"
|
|
94
|
+
[compareWith]="compareFn"
|
|
27
95
|
[attr.disabled]="field.disabled ? true : null"
|
|
96
|
+
[attr.aria-invalid]="control.invalid && control.touched"
|
|
97
|
+
[attr.aria-describedby]="errorMessage ? field.id + '-error' : null"
|
|
28
98
|
>
|
|
29
|
-
<option value="">{{
|
|
30
|
-
@for (option of
|
|
31
|
-
|
|
99
|
+
<option [value]="''">{{ placeholder || 'Select...' }}</option>
|
|
100
|
+
@for (option of options(); track getOptLabel(option)) {
|
|
101
|
+
@if (isObjectVal(option)) {
|
|
102
|
+
<option [ngValue]="getOptStoredVal(option)">{{ getOptLabel(option) }}</option>
|
|
103
|
+
} @else {
|
|
104
|
+
<option [value]="getOptStoredVal(option)">{{ getOptLabel(option) }}</option>
|
|
105
|
+
}
|
|
32
106
|
}
|
|
33
107
|
</select>
|
|
34
|
-
@if (
|
|
35
|
-
<span class="ngx-field__error"
|
|
108
|
+
@if (errorMessage) {
|
|
109
|
+
<span class="ngx-field__error" [attr.data-testid]="'field-' + field.id + '-error'" [id]="field.id + '-error'" role="alert">{{ errorMessage }}</span>
|
|
36
110
|
}
|
|
37
111
|
}
|
|
38
112
|
</div>
|
|
@@ -45,25 +119,42 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
|
|
|
45
119
|
standalone: true,
|
|
46
120
|
imports: [ReactiveFormsModule],
|
|
47
121
|
template: `
|
|
48
|
-
<div
|
|
49
|
-
|
|
122
|
+
<div
|
|
123
|
+
class="ngx-field ngx-field--dropdown"
|
|
124
|
+
[attr.data-testid]="'field-' + field.id" [attr.data-field-type]="field.type"
|
|
125
|
+
[class.ngx-field--readonly]="readonly"
|
|
126
|
+
[class.ngx-field--masked]="masked"
|
|
127
|
+
[class.ngx-field--invalid]="control && control.invalid && control.touched"
|
|
128
|
+
>
|
|
129
|
+
<label class="ngx-field__label" [attr.for]="field.id">
|
|
130
|
+
{{ label }}
|
|
131
|
+
@if (field.validators?.required) { <span class="ngx-field__req">*</span> }
|
|
132
|
+
</label>
|
|
50
133
|
@if (masked) {
|
|
51
|
-
<span class="ngx-field__value ngx-field__value--masked">XXXXXXXXX</span>
|
|
134
|
+
<span class="ngx-field__value ngx-field__value--masked" [attr.data-testid]="'field-' + field.id + '-masked'">XXXXXXXXX</span>
|
|
52
135
|
} @else if (readonly) {
|
|
53
|
-
<span class="ngx-field__value">{{ getLabel(control.value) }}</span>
|
|
136
|
+
<span class="ngx-field__value" [attr.data-testid]="'field-' + field.id + '-value'">{{ getLabel(control.value) }}</span>
|
|
54
137
|
} @else {
|
|
55
138
|
<select
|
|
56
|
-
|
|
139
|
+
[id]="field.id"
|
|
140
|
+
class="ngx-field__input" [attr.data-testid]="'field-' + field.id + '-input'"
|
|
57
141
|
[formControl]="$any(control)"
|
|
142
|
+
[compareWith]="compareFn"
|
|
58
143
|
[attr.disabled]="field.disabled ? true : null"
|
|
144
|
+
[attr.aria-invalid]="control.invalid && control.touched"
|
|
145
|
+
[attr.aria-describedby]="errorMessage ? field.id + '-error' : null"
|
|
59
146
|
>
|
|
60
|
-
<option value="">{{
|
|
61
|
-
@for (option of
|
|
62
|
-
|
|
147
|
+
<option [value]="''">{{ placeholder || 'Select...' }}</option>
|
|
148
|
+
@for (option of options(); track getOptLabel(option)) {
|
|
149
|
+
@if (isObjectVal(option)) {
|
|
150
|
+
<option [ngValue]="getOptStoredVal(option)">{{ getOptLabel(option) }}</option>
|
|
151
|
+
} @else {
|
|
152
|
+
<option [value]="getOptStoredVal(option)">{{ getOptLabel(option) }}</option>
|
|
153
|
+
}
|
|
63
154
|
}
|
|
64
155
|
</select>
|
|
65
|
-
@if (
|
|
66
|
-
<span class="ngx-field__error"
|
|
156
|
+
@if (errorMessage) {
|
|
157
|
+
<span class="ngx-field__error" [attr.data-testid]="'field-' + field.id + '-error'" [id]="field.id + '-error'" role="alert">{{ errorMessage }}</span>
|
|
67
158
|
}
|
|
68
159
|
}
|
|
69
160
|
</div>
|
|
@@ -71,13 +162,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
|
|
|
71
162
|
}]
|
|
72
163
|
}], propDecorators: { field: [{
|
|
73
164
|
type: Input
|
|
74
|
-
}], control: [{
|
|
75
|
-
type: Input
|
|
76
165
|
}], language: [{
|
|
77
166
|
type: Input
|
|
167
|
+
}], control: [{
|
|
168
|
+
type: Input
|
|
78
169
|
}], readonly: [{
|
|
79
170
|
type: Input
|
|
80
171
|
}], masked: [{
|
|
81
172
|
type: Input
|
|
82
173
|
}] } });
|
|
83
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHJvcGRvd24tZmllbGQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xpYi9maWVsZC10eXBlcy9kcm9wZG93bi1maWVsZC5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQWtCLE1BQU0sZUFBZSxDQUFDO0FBQ2pFLE9BQU8sRUFBbUIsbUJBQW1CLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQzs7O0FBZ0N0RSxNQUFNLE9BQU8sc0JBQXNCO0lBQ3hCLEtBQUssQ0FBZTtJQUNwQixPQUFPLENBQW1CO0lBQzFCLFFBQVEsR0FBVyxJQUFJLENBQUM7SUFDeEIsUUFBUSxHQUFZLEtBQUssQ0FBQztJQUMxQixNQUFNLEdBQVksS0FBSyxDQUFDO0lBRWpDLFFBQVEsQ0FBQyxLQUFVO1FBQ2pCLE1BQU0sTUFBTSxHQUFHLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLElBQUksRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEtBQUssS0FBSyxLQUFLLENBQUMsQ0FBQztRQUN2RSxPQUFPLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssSUFBSSxHQUFHLENBQUMsQ0FBQztJQUN4RyxDQUFDO3dHQVZVLHNCQUFzQjs0RkFBdEIsc0JBQXNCLDRMQXpCdkI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBdUJULDJEQXhCUyxtQkFBbUI7OzRGQTBCbEIsc0JBQXNCO2tCQTdCbEMsU0FBUzttQkFBQztvQkFDVCxRQUFRLEVBQUUsb0JBQW9CO29CQUM5QixVQUFVLEVBQUUsSUFBSTtvQkFDaEIsT0FBTyxFQUFFLENBQUMsbUJBQW1CLENBQUM7b0JBQzlCLFFBQVEsRUFBRTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0F1QlQ7aUJBQ0Y7OEJBRVUsS0FBSztzQkFBYixLQUFLO2dCQUNHLE9BQU87c0JBQWYsS0FBSztnQkFDRyxRQUFRO3NCQUFoQixLQUFLO2dCQUNHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBQ0csTUFBTTtzQkFBZCxLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBJbnB1dCwgT25Jbml0LCBzaWduYWwgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEFic3RyYWN0Q29udHJvbCwgUmVhY3RpdmVGb3Jtc01vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB0eXBlIHsgRmllbGRDb25maWcsIERyb3Bkb3duT3B0aW9uIH0gZnJvbSAnQGR5bmFtaWMtZW50aXR5L2NvcmUnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICduZ3gtZHJvcGRvd24tZmllbGQnLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbUmVhY3RpdmVGb3Jtc01vZHVsZV0sXG4gIHRlbXBsYXRlOiBgXG4gICAgPGRpdiBjbGFzcz1cIm5neC1maWVsZCBuZ3gtZmllbGQtLWRyb3Bkb3duXCIgW2NsYXNzLm5neC1maWVsZC0tcmVhZG9ubHldPVwicmVhZG9ubHlcIiBbY2xhc3Mubmd4LWZpZWxkLS1tYXNrZWRdPVwibWFza2VkXCI+XG4gICAgICA8bGFiZWwgY2xhc3M9XCJuZ3gtZmllbGRfX2xhYmVsXCI+e3sgZmllbGQubGFiZWxbbGFuZ3VhZ2VdIHx8IGZpZWxkLmxhYmVsWydlbiddIH19PC9sYWJlbD5cbiAgICAgIEBpZiAobWFza2VkKSB7XG4gICAgICAgIDxzcGFuIGNsYXNzPVwibmd4LWZpZWxkX192YWx1ZSBuZ3gtZmllbGRfX3ZhbHVlLS1tYXNrZWRcIj5YWFhYWFhYWFg8L3NwYW4+XG4gICAgICB9IEBlbHNlIGlmIChyZWFkb25seSkge1xuICAgICAgICA8c3BhbiBjbGFzcz1cIm5neC1maWVsZF9fdmFsdWVcIj57eyBnZXRMYWJlbChjb250cm9sLnZhbHVlKSB9fTwvc3Bhbj5cbiAgICAgIH0gQGVsc2Uge1xuICAgICAgICA8c2VsZWN0XG4gICAgICAgICAgY2xhc3M9XCJuZ3gtZmllbGRfX2lucHV0XCJcbiAgICAgICAgICBbZm9ybUNvbnRyb2xdPVwiJGFueShjb250cm9sKVwiXG4gICAgICAgICAgW2F0dHIuZGlzYWJsZWRdPVwiZmllbGQuZGlzYWJsZWQgPyB0cnVlIDogbnVsbFwiXG4gICAgICAgID5cbiAgICAgICAgICA8b3B0aW9uIHZhbHVlPVwiXCI+e3sgZmllbGQucGxhY2Vob2xkZXI/LltsYW5ndWFnZV0gfHwgZmllbGQucGxhY2Vob2xkZXI/LlsnZW4nXSB8fCAnU2VsZWN0Li4uJyB9fTwvb3B0aW9uPlxuICAgICAgICAgIEBmb3IgKG9wdGlvbiBvZiBmaWVsZC5vcHRpb25zIHx8IFtdOyB0cmFjayBvcHRpb24udmFsdWUpIHtcbiAgICAgICAgICAgIDxvcHRpb24gW3ZhbHVlXT1cIm9wdGlvbi52YWx1ZVwiPnt7IG9wdGlvbi5sYWJlbFtsYW5ndWFnZV0gfHwgb3B0aW9uLmxhYmVsWydlbiddIH19PC9vcHRpb24+XG4gICAgICAgICAgfVxuICAgICAgICA8L3NlbGVjdD5cbiAgICAgICAgQGlmIChjb250cm9sLmludmFsaWQgJiYgY29udHJvbC50b3VjaGVkKSB7XG4gICAgICAgICAgPHNwYW4gY2xhc3M9XCJuZ3gtZmllbGRfX2Vycm9yXCI+VGhpcyBmaWVsZCBoYXMgYW4gZXJyb3I8L3NwYW4+XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICA8L2Rpdj5cbiAgYCxcbn0pXG5leHBvcnQgY2xhc3MgRHJvcGRvd25GaWVsZENvbXBvbmVudCB7XG4gIEBJbnB1dCgpIGZpZWxkITogRmllbGRDb25maWc7XG4gIEBJbnB1dCgpIGNvbnRyb2whOiBBYnN0cmFjdENvbnRyb2w7XG4gIEBJbnB1dCgpIGxhbmd1YWdlOiBzdHJpbmcgPSAnZW4nO1xuICBASW5wdXQoKSByZWFkb25seTogYm9vbGVhbiA9IGZhbHNlO1xuICBASW5wdXQoKSBtYXNrZWQ6IGJvb2xlYW4gPSBmYWxzZTtcblxuICBnZXRMYWJlbCh2YWx1ZTogYW55KTogc3RyaW5nIHtcbiAgICBjb25zdCBvcHRpb24gPSAodGhpcy5maWVsZC5vcHRpb25zIHx8IFtdKS5maW5kKG8gPT4gby52YWx1ZSA9PT0gdmFsdWUpO1xuICAgIHJldHVybiBvcHRpb24gPyAob3B0aW9uLmxhYmVsW3RoaXMubGFuZ3VhZ2VdIHx8IG9wdGlvbi5sYWJlbFsnZW4nXSB8fCBTdHJpbmcodmFsdWUpKSA6ICh2YWx1ZSA/PyAn4oCUJyk7XG4gIH1cbn1cbiJdfQ==
|
|
174
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHJvcGRvd24tZmllbGQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xpYi9maWVsZC10eXBlcy9kcm9wZG93bi1maWVsZC5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNqRSxPQUFPLEVBQW1CLG1CQUFtQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFdEUsT0FBTyxFQUNMLG9CQUFvQixFQUNwQixZQUFZLEVBQ1osa0JBQWtCLEVBQ2xCLFdBQVcsR0FDWixNQUFNLHNCQUFzQixDQUFDO0FBQzlCLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxvQkFBb0IsRUFBRSxNQUFNLHFDQUFxQyxDQUFDOzs7QUFnRGxHLE1BQU0sT0FBTyxzQkFBc0I7SUFDaEIsT0FBTyxHQUFHLE1BQU0sQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO0lBRWpELE1BQU0sQ0FBcUI7SUFDM0IsU0FBUyxHQUFHLElBQUksQ0FBQztJQUV6Qiw2RkFBNkY7SUFDN0YsSUFBYSxLQUFLLENBQUMsS0FBd0I7UUFDekMsSUFBSSxDQUFDLE1BQU0sR0FBRyxLQUFLLENBQUM7UUFDcEIsb0JBQW9CLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUMzQyxDQUFDO0lBQ0QsSUFBSSxLQUFLO1FBQ1AsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDO0lBQ3JCLENBQUM7SUFFRCxJQUFhLFFBQVEsQ0FBQyxLQUFhO1FBQ2pDLElBQUksQ0FBQyxTQUFTLEdBQUcsS0FBSyxJQUFJLElBQUksQ0FBQztRQUMvQixvQkFBb0IsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQzNDLENBQUM7SUFDRCxJQUFJLFFBQVE7UUFDVixPQUFPLElBQUksQ0FBQyxTQUFTLENB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LE9BQU8sRUFBRSxDQUFDLG1CQUFtQixDQUFDO29CQUM5QixRQUFRLEVBQUU7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0F3Q1Q7aUJBQ0Y7OEJBUWMsS0FBSztzQkFBakIsS0FBSztnQkFRTyxRQUFRO3NCQUFwQixLQUFLO2dCQVFHLE9BQU87c0JBQWYsS0FBSztnQkFDRyxRQUFRO3NCQUFoQixLQUFLO2dCQUNHLE1BQU07c0JBQWQsS0FBSyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgSW5wdXQsIGluamVjdCwgc2lnbmFsIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBBYnN0cmFjdENvbnRyb2wsIFJlYWN0aXZlRm9ybXNNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgdHlwZSB7IERyb3Bkb3duT3B0aW9uLCBOZXN0ZWRGaWVsZENvbmZpZyB9IGZyb20gJ0BkeW5hbWljLWVudGl0eS9jb3JlJztcbmltcG9ydCB7XG4gIGdldE9wdGlvblN0b3JlZFZhbHVlLFxuICByZXNvbHZlTGFiZWwsXG4gIHJlc29sdmVPcHRpb25MYWJlbCxcbiAgdmFsdWVzTWF0Y2gsXG59IGZyb20gJ0BkeW5hbWljLWVudGl0eS9jb3JlJztcbmltcG9ydCB7IExvb2t1cFJlZ2lzdHJ5U2VydmljZSwgcmVmcmVzaENob2ljZU9wdGlvbnMgfSBmcm9tICcuLi9zZXJ2aWNlcy9sb29rdXAtcmVnaXN0cnkuc2VydmljZSc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ25neC1kcm9wZG93bi1maWVsZCcsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtSZWFjdGl2ZUZvcm1zTW9kdWxlXSxcbiAgdGVtcGxhdGU6IGBcbiAgICA8ZGl2XG4gICAgICBjbGFzcz1cIm5neC1maWVsZCBuZ3gtZmllbGQtLWRyb3Bkb3duXCJcbiAgICAgIFthdHRyLmRhdGEtdGVzdGlkXT1cIidmaWVsZC0nICsgZmllbGQuaWRcIiBbYXR0ci5kYXRhLWZpZWxkLXR5cGVdPVwiZmllbGQudHlwZVwiXG4gICAgICBbY2xhc3Mubmd4LWZpZWxkLS1yZWFkb25seV09XCJyZWFkb25seVwiXG4gICAgICBbY2xhc3Mubmd4LWZpZWxkLS1tYXNrZWRdPVwibWFza2VkXCJcbiAgICAgIFtjbGFzcy5uZ3gtZmllbGQtLWludmFsaWRdPVwiY29udHJvbCAmJiBjb250cm9sLmludmFsaWQgJiYgY29udHJvbC50b3VjaGVkXCJcbiAgICA+XG4gICAgICA8bGFiZWwgY2xhc3M9XCJuZ3gtZmllbGRfX2xhYmVsXCIgW2F0dHIuZm9yXT1cImZpZWxkLmlkXCI+XG4gICAgICAgIHt7IGxhYmVsIH19XG4gICAgICAgIEBpZiAoZmllbGQudmFsaWRhdG9ycz8ucmVxdWlyZWQpIHsgPHNwYW4gY2xhc3M9XCJuZ3gtZmllbGRfX3JlcVwiPio8L3NwYW4+IH1cbiAgICAgIDwvbGFiZWw+XG4gICAgICBAaWYgKG1hc2tlZCkge1xuICAgICAgICA8c3BhbiBjbGFzcz1cIm5neC1maWVsZF9fdmFsdWUgbmd4LWZpZWxkX192YWx1ZS0tbWFza2VkXCIgW2F0dHIuZGF0YS10ZXN0aWRdPVwiJ2ZpZWxkLScgKyBmaWVsZC5pZCArICctbWFza2VkJ1wiPlhYWFhYWFhYWDwvc3Bhbj5cbiAgICAgIH0gQGVsc2UgaWYgKHJlYWRvbmx5KSB7XG4gICAgICAgIDxzcGFuIGNsYXNzPVwibmd4LWZpZWxkX192YWx1ZVwiIFthdHRyLmRhdGEtdGVzdGlkXT1cIidmaWVsZC0nICsgZmllbGQuaWQgKyAnLXZhbHVlJ1wiPnt7IGdldExhYmVsKGNvbnRyb2wudmFsdWUpIH19PC9zcGFuPlxuICAgICAgfSBAZWxzZSB7XG4gICAgICAgIDxzZWxlY3RcbiAgICAgICAgICBbaWRdPVwiZmllbGQuaWRcIlxuICAgICAgICAgIGNsYXNzPVwibmd4LWZpZWxkX19pbnB1dFwiIFthdHRyLmRhdGEtdGVzdGlkXT1cIidmaWVsZC0nICsgZmllbGQuaWQgKyAnLWlucHV0J1wiXG4gICAgICAgICAgW2Zvcm1Db250cm9sXT1cIiRhbnkoY29udHJvbClcIlxuICAgICAgICAgIFtjb21wYXJlV2l0aF09XCJjb21wYXJlRm5cIlxuICAgICAgICAgIFthdHRyLmRpc2FibGVkXT1cImZpZWxkLmRpc2FibGVkID8gdHJ1ZSA6IG51bGxcIlxuICAgICAgICAgIFthdHRyLmFyaWEtaW52YWxpZF09XCJjb250cm9sLmludmFsaWQgJiYgY29udHJvbC50b3VjaGVkXCJcbiAgICAgICAgICBbYXR0ci5hcmlhLWRlc2NyaWJlZGJ5XT1cImVycm9yTWVzc2FnZSA/IGZpZWxkLmlkICsgJy1lcnJvcicgOiBudWxsXCJcbiAgICAgICAgPlxuICAgICAgICAgIDxvcHRpb24gW3ZhbHVlXT1cIicnXCI+e3sgcGxhY2Vob2xkZXIgfHwgJ1NlbGVjdC4uLicgfX08L29wdGlvbj5cbiAgICAgICAgICBAZm9yIChvcHRpb24gb2Ygb3B0aW9ucygpOyB0cmFjayBnZXRPcHRMYWJlbChvcHRpb24pKSB7XG4gICAgICAgICAgICBAaWYgKGlzT2JqZWN0VmFsKG9wdGlvbikpIHtcbiAgICAgICAgICAgICAgPG9wdGlvbiBbbmdWYWx1ZV09XCJnZXRPcHRTdG9yZWRWYWwob3B0aW9uKVwiPnt7IGdldE9wdExhYmVsKG9wdGlvbikgfX08L29wdGlvbj5cbiAgICAgICAgICAgIH0gQGVsc2Uge1xuICAgICAgICAgICAgICA8b3B0aW9uIFt2YWx1ZV09XCJnZXRPcHRTdG9yZWRWYWwob3B0aW9uKVwiPnt7IGdldE9wdExhYmVsKG9wdGlvbikgfX08L29wdGlvbj5cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIDwvc2VsZWN0PlxuICAgICAgICBAaWYgKGVycm9yTWVzc2FnZSkge1xuICAgICAgICAgIDxzcGFuIGNsYXNzPVwibmd4LWZpZWxkX19lcnJvclwiIFthdHRyLmRhdGEtdGVzdGlkXT1cIidmaWVsZC0nICsgZmllbGQuaWQgKyAnLWVycm9yJ1wiIFtpZF09XCJmaWVsZC5pZCArICctZXJyb3InXCIgcm9sZT1cImFsZXJ0XCI+e3sgZXJyb3JNZXNzYWdlIH19PC9zcGFuPlxuICAgICAgICB9XG4gICAgICB9XG4gICAgPC9kaXY+XG4gIGAsXG59KVxuZXhwb3J0IGNsYXNzIERyb3Bkb3duRmllbGRDb21wb25lbnQge1xuICBwcml2YXRlIHJlYWRvbmx5IGxvb2t1cHMgPSBpbmplY3QoTG9va3VwUmVnaXN0cnlTZXJ2aWNlKTtcblxuICBwcml2YXRlIF9maWVsZCE6IE5lc3RlZEZpZWxkQ29uZmlnO1xuICBwcml2YXRlIF9sYW5ndWFnZSA9ICdlbic7XG5cbiAgLyoqIFNldHRlci1iYXNlZCBzbyBvcHRpb25zIHJlc29sdmUgaG93ZXZlciB0aGUgaW5wdXQgaXMgc2V0IOKAlCBzZWUgYHJlZnJlc2hDaG9pY2VPcHRpb25zYC4gKi9cbiAgQElucHV0KCkgc2V0IGZpZWxkKHZhbHVlOiBOZXN0ZWRGaWVsZENvbmZpZykge1xuICAgIHRoaXMuX2ZpZWxkID0gdmFsdWU7XG4gICAgcmVmcmVzaENob2ljZU9wdGlvbnModGhpcywgdGhpcy5sb29rdXBzKTtcbiAgfVxuICBnZXQgZmllbGQoKTogTmVzdGVkRmllbGRDb25maWcge1xuICAgIHJldHVybiB0aGlzLl9maWVsZDtcbiAgfVxuXG4gIEBJbnB1dCgpIHNldCBsYW5ndWFnZSh2YWx1ZTogc3RyaW5nKSB7XG4gICAgdGhpcy5fbGFuZ3VhZ2UgPSB2YWx1ZSB8fCAnZW4nO1xuICAgIHJlZnJlc2hDaG9pY2VPcHRpb25zKHRoaXMsIHRoaXMubG9va3Vwcyk7XG4gIH1cbiAgZ2V0IGxhbmd1YWdlKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuX2xhbmd1YWdlO1xuICB9XG5cbiAgQElucHV0KCkgY29udHJvbCE6IEFic3RyYWN0Q29udHJvbDtcbiAgQElucHV0KCkgcmVhZG9ubHk6IGJvb2xlYW4gPSBmYWxzZTtcbiAgQElucHV0KCkgbWFza2VkOiBib29sZWFuID0gZmFsc2U7XG5cbiAgLyoqIElubGluZSBgb3B0aW9uc2AsIG9yIHRoZSBmaWVsZCdzIG5hbWVkIGxpc3QgcmVzb2x2ZWQgdGhyb3VnaCB0aGUgcmVnaXN0cnkgKMKnNi4zKS4gKi9cbiAgcmVhZG9ubHkgb3B0aW9ucyA9IHNpZ25hbDxEcm9wZG93bk9wdGlvbltdPihbXSk7XG5cbiAgcmVhZG9ubHkgY29tcGFyZUZuID0gKG8xOiBhbnksIG8yOiBhbnkpOiBib29sZWFuID0+IHZhbHVlc01hdGNoKG8xLCBvMiwgdGhpcy5sYW5ndWFnZSk7XG5cbiAgaXNPYmplY3RWYWwob3B0aW9uOiBhbnkpOiBib29sZWFuIHtcbiAgICBjb25zdCB2YWwgPSBnZXRPcHRpb25TdG9yZWRWYWx1ZShvcHRpb24pO1xuICAgIHJldHVybiB0eXBlb2YgdmFsID09PSAnb2JqZWN0JyAmJiB2YWwgIT09IG51bGw7XG4gIH1cblxuICBnZXQgbGFiZWwoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gcmVzb2x2ZUxhYmVsKHRoaXMuZmllbGQ/LmxhYmVsLCB0aGlzLmxhbmd1YWdlKTtcbiAgfVxuXG4gIGdldCBwbGFjZWhvbGRlcigpOiBzdHJpbmcge1xuICAgIHJldHVybiByZXNvbHZlTGFiZWwodGhpcy5maWVsZD8ucGxhY2Vob2xkZXIsIHRoaXMubGFuZ3VhZ2UpO1xuICB9XG5cbiAgZ2V0T3B0U3RvcmVkVmFsKG9wdGlvbjogYW55KTogYW55IHtcbiAgICByZXR1cm4gZ2V0T3B0aW9uU3RvcmVkVmFsdWUob3B0aW9uKTtcbiAgfVxuXG4gIGdldE9wdExhYmVsKG9wdGlvbjogYW55KTogc3RyaW5nIHtcbiAgICByZXR1cm4gcmVzb2x2ZU9wdGlvbkxhYmVsKG9wdGlvbiwgdGhpcy5sYW5ndWFnZSk7XG4gIH1cblxuICAvKipcbiAgICogUmVhZC1vbmx5IGRpc3BsYXkuIE5ldmVyIGF3YWl0cyAowqc2LjIpOiBhIHdhcm0gbGlzdCByZXNvbHZlcyB0aGUgbGFiZWwsIGEgY29sZCBvbmUgZmFsbHNcbiAgICogYmFjayB0byB0aGUgc3RvcmVkIHRleHQg4oCUIHdoaWNoIHVuZGVyIHRoZSDCpzIgY29udHJhY3QgKmlzKiB0aGUgZGlzcGxheSB2YWx1ZSwgc28gaXQgaXNcbiAgICogbmV2ZXIgd3JvbmcsIG9ubHkgdW5sb2NhbGlzZWQuXG4gICAqL1xuICBnZXRMYWJlbCh2YWx1ZTogYW55KTogc3RyaW5nIHtcbiAgICBpZiAodmFsdWUgPT0gbnVsbCB8fCB2YWx1ZSA9PT0gJycpIHJldHVybiAn4oCUJztcbiAgICBjb25zdCBvcHRpb24gPSB0aGlzLm9wdGlvbnMoKS5maW5kKG8gPT4gdmFsdWVzTWF0Y2goZ2V0T3B0aW9uU3RvcmVkVmFsdWUobyksIHZhbHVlLCB0aGlzLmxhbmd1YWdlKSk7XG4gICAgaWYgKG9wdGlvbikgcmV0dXJuIHRoaXMuZ2V0T3B0TGFiZWwob3B0aW9uKTtcbiAgICBjb25zdCBjYWNoZWQgPSB0aGlzLmxvb2t1cHMubGFiZWxGb3IodGhpcy5maWVsZD8ubGlzdE5hbWUsIHZhbHVlLCB0aGlzLmxhbmd1YWdlKTtcbiAgICBpZiAoY2FjaGVkKSByZXR1cm4gY2FjaGVkO1xuICAgIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnID8gcmVzb2x2ZUxhYmVsKHZhbHVlLCB0aGlzLmxhbmd1YWdlKSA6ICh2YWx1ZSA/PyAn4oCUJyk7XG4gIH1cblxuICBnZXQgZXJyb3JNZXNzYWdlKCk6IHN0cmluZyB7XG4gICAgaWYgKCF0aGlzLmNvbnRyb2wgfHwgIXRoaXMuY29udHJvbC5lcnJvcnMgfHwgIXRoaXMuY29udHJvbC50b3VjaGVkKSByZXR1cm4gJyc7XG4gICAgY29uc3QgZXJycyA9IHRoaXMuY29udHJvbC5lcnJvcnM7XG4gICAgaWYgKGVycnNbJ3JlcXVpcmVkJ10pIHJldHVybiAnUGxlYXNlIHNlbGVjdCBhbiBvcHRpb24uJztcbiAgICByZXR1cm4gJ0ludmFsaWQgc2VsZWN0aW9uLic7XG4gIH1cbn1cbiJdfQ==
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { Component, Input } from '@angular/core';
|
|
2
|
+
import { ReactiveFormsModule } from '@angular/forms';
|
|
3
|
+
import { resolveLabel } from '@dynamic-entity/core';
|
|
4
|
+
import * as i0 from "@angular/core";
|
|
5
|
+
import * as i1 from "@angular/forms";
|
|
6
|
+
/** Email field: type="email" input with inline validation hint. */
|
|
7
|
+
export class EmailFieldComponent {
|
|
8
|
+
field;
|
|
9
|
+
control;
|
|
10
|
+
language = 'en';
|
|
11
|
+
readonly = false;
|
|
12
|
+
masked = false;
|
|
13
|
+
get label() {
|
|
14
|
+
return resolveLabel(this.field?.label, this.language);
|
|
15
|
+
}
|
|
16
|
+
get placeholder() {
|
|
17
|
+
return resolveLabel(this.field?.placeholder, this.language);
|
|
18
|
+
}
|
|
19
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: EmailFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
20
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: EmailFieldComponent, isStandalone: true, selector: "ngx-email-field", inputs: { field: "field", control: "control", language: "language", readonly: "readonly", masked: "masked" }, ngImport: i0, template: `
|
|
21
|
+
<div class="ngx-field ngx-field--email"
|
|
22
|
+
[attr.data-testid]="'field-' + field.id" [attr.data-field-type]="field.type" [class.ngx-field--readonly]="readonly" [class.ngx-field--masked]="masked">
|
|
23
|
+
<label class="ngx-field__label">{{ label }}</label>
|
|
24
|
+
@if (masked) {
|
|
25
|
+
<span class="ngx-field__value ngx-field__value--masked" [attr.data-testid]="'field-' + field.id + '-masked'">XXXXXXXXX</span>
|
|
26
|
+
} @else if (readonly) {
|
|
27
|
+
<span class="ngx-field__value" [attr.data-testid]="'field-' + field.id + '-value'">
|
|
28
|
+
<a [href]="'mailto:' + control.value" class="ngx-field__email-link">{{ control.value || '—' }}</a>
|
|
29
|
+
</span>
|
|
30
|
+
} @else {
|
|
31
|
+
<input
|
|
32
|
+
class="ngx-field__input" [attr.data-testid]="'field-' + field.id + '-input'"
|
|
33
|
+
type="email"
|
|
34
|
+
autocomplete="email"
|
|
35
|
+
[formControl]="$any(control)"
|
|
36
|
+
[placeholder]="placeholder || 'you@example.com'"
|
|
37
|
+
[attr.disabled]="field.disabled ? true : null"
|
|
38
|
+
/>
|
|
39
|
+
@if (control.invalid && control.touched) {
|
|
40
|
+
@if (control.errors?.['required']) {
|
|
41
|
+
<span class="ngx-field__error" [attr.data-testid]="'field-' + field.id + '-error'">Email is required</span>
|
|
42
|
+
} @else if (control.errors?.['email']) {
|
|
43
|
+
<span class="ngx-field__error" [attr.data-testid]="'field-' + field.id + '-error'">Enter a valid email address</span>
|
|
44
|
+
} @else {
|
|
45
|
+
<span class="ngx-field__error" [attr.data-testid]="'field-' + field.id + '-error'">This field has an error</span>
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
</div>
|
|
50
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }] });
|
|
51
|
+
}
|
|
52
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: EmailFieldComponent, decorators: [{
|
|
53
|
+
type: Component,
|
|
54
|
+
args: [{
|
|
55
|
+
selector: 'ngx-email-field',
|
|
56
|
+
standalone: true,
|
|
57
|
+
imports: [ReactiveFormsModule],
|
|
58
|
+
template: `
|
|
59
|
+
<div class="ngx-field ngx-field--email"
|
|
60
|
+
[attr.data-testid]="'field-' + field.id" [attr.data-field-type]="field.type" [class.ngx-field--readonly]="readonly" [class.ngx-field--masked]="masked">
|
|
61
|
+
<label class="ngx-field__label">{{ label }}</label>
|
|
62
|
+
@if (masked) {
|
|
63
|
+
<span class="ngx-field__value ngx-field__value--masked" [attr.data-testid]="'field-' + field.id + '-masked'">XXXXXXXXX</span>
|
|
64
|
+
} @else if (readonly) {
|
|
65
|
+
<span class="ngx-field__value" [attr.data-testid]="'field-' + field.id + '-value'">
|
|
66
|
+
<a [href]="'mailto:' + control.value" class="ngx-field__email-link">{{ control.value || '—' }}</a>
|
|
67
|
+
</span>
|
|
68
|
+
} @else {
|
|
69
|
+
<input
|
|
70
|
+
class="ngx-field__input" [attr.data-testid]="'field-' + field.id + '-input'"
|
|
71
|
+
type="email"
|
|
72
|
+
autocomplete="email"
|
|
73
|
+
[formControl]="$any(control)"
|
|
74
|
+
[placeholder]="placeholder || 'you@example.com'"
|
|
75
|
+
[attr.disabled]="field.disabled ? true : null"
|
|
76
|
+
/>
|
|
77
|
+
@if (control.invalid && control.touched) {
|
|
78
|
+
@if (control.errors?.['required']) {
|
|
79
|
+
<span class="ngx-field__error" [attr.data-testid]="'field-' + field.id + '-error'">Email is required</span>
|
|
80
|
+
} @else if (control.errors?.['email']) {
|
|
81
|
+
<span class="ngx-field__error" [attr.data-testid]="'field-' + field.id + '-error'">Enter a valid email address</span>
|
|
82
|
+
} @else {
|
|
83
|
+
<span class="ngx-field__error" [attr.data-testid]="'field-' + field.id + '-error'">This field has an error</span>
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
</div>
|
|
88
|
+
`,
|
|
89
|
+
}]
|
|
90
|
+
}], propDecorators: { field: [{
|
|
91
|
+
type: Input
|
|
92
|
+
}], control: [{
|
|
93
|
+
type: Input
|
|
94
|
+
}], language: [{
|
|
95
|
+
type: Input
|
|
96
|
+
}], readonly: [{
|
|
97
|
+
type: Input
|
|
98
|
+
}], masked: [{
|
|
99
|
+
type: Input
|
|
100
|
+
}] } });
|
|
101
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW1haWwtZmllbGQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xpYi9maWVsZC10eXBlcy9lbWFpbC1maWVsZC5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDakQsT0FBTyxFQUFtQixtQkFBbUIsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRXRFLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQzs7O0FBRXBELG1FQUFtRTtBQXFDbkUsTUFBTSxPQUFPLG1CQUFtQjtJQUNyQixLQUFLLENBQXFCO0lBQzFCLE9BQU8sQ0FBbUI7SUFDMUIsUUFBUSxHQUFXLElBQUksQ0FBQztJQUN4QixRQUFRLEdBQVksS0FBSyxDQUFDO0lBQzFCLE1BQU0sR0FBWSxLQUFLLENBQUM7SUFFakMsSUFBSSxLQUFLO1FBQ1AsT0FBTyxZQUFZLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxLQUFLLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ3hELENBQUM7SUFFRCxJQUFJLFdBQVc7UUFDYixPQUFPLFlBQVksQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLFdBQVcsRUFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDOUQsQ0FBQzt3R0FiVSxtQkFBbUI7NEZBQW5CLG1CQUFtQix5TEFoQ3BCOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0E4QlQsMkRBL0JTLG1CQUFtQjs7NEZBaUNsQixtQkFBbUI7a0JBcEMvQixTQUFTO21CQUFDO29CQUNULFFBQVEsRUFBRSxpQkFBaUI7b0JBQzNCLFVBQVUsRUFBRSxJQUFJO29CQUNoQixPQUFPLEVBQUUsQ0FBQyxtQkFBbUIsQ0FBQztvQkFDOUIsUUFBUSxFQUFFOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0E4QlQ7aUJBQ0Y7OEJBRVUsS0FBSztzQkFBYixLQUFLO2dCQUNHLE9BQU87c0JBQWYsS0FBSztnQkFDRyxRQUFRO3NCQUFoQixLQUFLO2dCQUNHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBQ0csTUFBTTtzQkFBZCxLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBJbnB1dCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQWJzdHJhY3RDb250cm9sLCBSZWFjdGl2ZUZvcm1zTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHR5cGUgeyBOZXN0ZWRGaWVsZENvbmZpZyB9IGZyb20gJ0BkeW5hbWljLWVudGl0eS9jb3JlJztcbmltcG9ydCB7IHJlc29sdmVMYWJlbCB9IGZyb20gJ0BkeW5hbWljLWVudGl0eS9jb3JlJztcblxuLyoqIEVtYWlsIGZpZWxkOiB0eXBlPVwiZW1haWxcIiBpbnB1dCB3aXRoIGlubGluZSB2YWxpZGF0aW9uIGhpbnQuICovXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICduZ3gtZW1haWwtZmllbGQnLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbUmVhY3RpdmVGb3Jtc01vZHVsZV0sXG4gIHRlbXBsYXRlOiBgXG4gICAgPGRpdiBjbGFzcz1cIm5neC1maWVsZCBuZ3gtZmllbGQtLWVtYWlsXCJcbiAgICAgIFthdHRyLmRhdGEtdGVzdGlkXT1cIidmaWVsZC0nICsgZmllbGQuaWRcIiBbYXR0ci5kYXRhLWZpZWxkLXR5cGVdPVwiZmllbGQudHlwZVwiIFtjbGFzcy5uZ3gtZmllbGQtLXJlYWRvbmx5XT1cInJlYWRvbmx5XCIgW2NsYXNzLm5neC1maWVsZC0tbWFza2VkXT1cIm1hc2tlZFwiPlxuICAgICAgPGxhYmVsIGNsYXNzPVwibmd4LWZpZWxkX19sYWJlbFwiPnt7IGxhYmVsIH19PC9sYWJlbD5cbiAgICAgIEBpZiAobWFza2VkKSB7XG4gICAgICAgIDxzcGFuIGNsYXNzPVwibmd4LWZpZWxkX192YWx1ZSBuZ3gtZmllbGRfX3ZhbHVlLS1tYXNrZWRcIiBbYXR0ci5kYXRhLXRlc3RpZF09XCInZmllbGQtJyArIGZpZWxkLmlkICsgJy1tYXNrZWQnXCI+WFhYWFhYWFhYPC9zcGFuPlxuICAgICAgfSBAZWxzZSBpZiAocmVhZG9ubHkpIHtcbiAgICAgICAgPHNwYW4gY2xhc3M9XCJuZ3gtZmllbGRfX3ZhbHVlXCIgW2F0dHIuZGF0YS10ZXN0aWRdPVwiJ2ZpZWxkLScgKyBmaWVsZC5pZCArICctdmFsdWUnXCI+XG4gICAgICAgICAgPGEgW2hyZWZdPVwiJ21haWx0bzonICsgY29udHJvbC52YWx1ZVwiIGNsYXNzPVwibmd4LWZpZWxkX19lbWFpbC1saW5rXCI+e3sgY29udHJvbC52YWx1ZSB8fCAn4oCUJyB9fTwvYT5cbiAgICAgICAgPC9zcGFuPlxuICAgICAgfSBAZWxzZSB7XG4gICAgICAgIDxpbnB1dFxuICAgICAgICAgIGNsYXNzPVwibmd4LWZpZWxkX19pbnB1dFwiIFthdHRyLmRhdGEtdGVzdGlkXT1cIidmaWVsZC0nICsgZmllbGQuaWQgKyAnLWlucHV0J1wiXG4gICAgICAgICAgdHlwZT1cImVtYWlsXCJcbiAgICAgICAgICBhdXRvY29tcGxldGU9XCJlbWFpbFwiXG4gICAgICAgICAgW2Zvcm1Db250cm9sXT1cIiRhbnkoY29udHJvbClcIlxuICAgICAgICAgIFtwbGFjZWhvbGRlcl09XCJwbGFjZWhvbGRlciB8fCAneW91QGV4YW1wbGUuY29tJ1wiXG4gICAgICAgICAgW2F0dHIuZGlzYWJsZWRdPVwiZmllbGQuZGlzYWJsZWQgPyB0cnVlIDogbnVsbFwiXG4gICAgICAgIC8+XG4gICAgICAgIEBpZiAoY29udHJvbC5pbnZhbGlkICYmIGNvbnRyb2wudG91Y2hlZCkge1xuICAgICAgICAgIEBpZiAoY29udHJvbC5lcnJvcnM/LlsncmVxdWlyZWQnXSkge1xuICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJuZ3gtZmllbGRfX2Vycm9yXCIgW2F0dHIuZGF0YS10ZXN0aWRdPVwiJ2ZpZWxkLScgKyBmaWVsZC5pZCArICctZXJyb3InXCI+RW1haWwgaXMgcmVxdWlyZWQ8L3NwYW4+XG4gICAgICAgICAgfSBAZWxzZSBpZiAoY29udHJvbC5lcnJvcnM/LlsnZW1haWwnXSkge1xuICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJuZ3gtZmllbGRfX2Vycm9yXCIgW2F0dHIuZGF0YS10ZXN0aWRdPVwiJ2ZpZWxkLScgKyBmaWVsZC5pZCArICctZXJyb3InXCI+RW50ZXIgYSB2YWxpZCBlbWFpbCBhZGRyZXNzPC9zcGFuPlxuICAgICAgICAgIH0gQGVsc2Uge1xuICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJuZ3gtZmllbGRfX2Vycm9yXCIgW2F0dHIuZGF0YS10ZXN0aWRdPVwiJ2ZpZWxkLScgKyBmaWVsZC5pZCArICctZXJyb3InXCI+VGhpcyBmaWVsZCBoYXMgYW4gZXJyb3I8L3NwYW4+XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgPC9kaXY+XG4gIGAsXG59KVxuZXhwb3J0IGNsYXNzIEVtYWlsRmllbGRDb21wb25lbnQge1xuICBASW5wdXQoKSBmaWVsZCE6IE5lc3RlZEZpZWxkQ29uZmlnO1xuICBASW5wdXQoKSBjb250cm9sITogQWJzdHJhY3RDb250cm9sO1xuICBASW5wdXQoKSBsYW5ndWFnZTogc3RyaW5nID0gJ2VuJztcbiAgQElucHV0KCkgcmVhZG9ubHk6IGJvb2xlYW4gPSBmYWxzZTtcbiAgQElucHV0KCkgbWFza2VkOiBib29sZWFuID0gZmFsc2U7XG5cbiAgZ2V0IGxhYmVsKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHJlc29sdmVMYWJlbCh0aGlzLmZpZWxkPy5sYWJlbCwgdGhpcy5sYW5ndWFnZSk7XG4gIH1cblxuICBnZXQgcGxhY2Vob2xkZXIoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gcmVzb2x2ZUxhYmVsKHRoaXMuZmllbGQ/LnBsYWNlaG9sZGVyLCB0aGlzLmxhbmd1YWdlKTtcbiAgfVxufVxuIl19
|