@gnggln/ng-ui-system 1.0.0-alpha.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/esm2022/gnggln-ng-ui-system.mjs +5 -0
- package/esm2022/lib/components/accordion/accordion.component.mjs +353 -0
- package/esm2022/lib/components/accordion/accordion.types.mjs +6 -0
- package/esm2022/lib/components/accordion/index.mjs +2 -0
- package/esm2022/lib/components/base-layout/base-layout.component.mjs +218 -0
- package/esm2022/lib/components/base-layout/base-layout.types.mjs +6 -0
- package/esm2022/lib/components/base-layout/index.mjs +14 -0
- package/esm2022/lib/components/button/button-area.component.mjs +196 -0
- package/esm2022/lib/components/button/button.component.mjs +164 -0
- package/esm2022/lib/components/button/button.types.mjs +6 -0
- package/esm2022/lib/components/button/index.mjs +16 -0
- package/esm2022/lib/components/crud-table/crud-table.component.mjs +789 -0
- package/esm2022/lib/components/crud-table/crud-table.types.mjs +6 -0
- package/esm2022/lib/components/crud-table/index.mjs +16 -0
- package/esm2022/lib/components/form-builder/adapters/it-date-adapter.mjs +82 -0
- package/esm2022/lib/components/form-builder/directives/currency-input.directive.mjs +184 -0
- package/esm2022/lib/components/form-builder/form-builder.component.mjs +824 -0
- package/esm2022/lib/components/form-builder/form-wizard.component.mjs +510 -0
- package/esm2022/lib/components/form-builder/index.mjs +19 -0
- package/esm2022/lib/components/form-builder/services/form-condition.service.mjs +132 -0
- package/esm2022/lib/components/form-builder/services/form-validation.service.mjs +381 -0
- package/esm2022/lib/components/form-builder/services/location.service.mjs +140 -0
- package/esm2022/lib/components/form-builder/services/wizard-sync.service.mjs +84 -0
- package/esm2022/lib/components/form-builder/sub-components/error-summary/form-error-summary.component.mjs +161 -0
- package/esm2022/lib/components/form-builder/sub-components/file-input/file-input.component.mjs +310 -0
- package/esm2022/lib/components/form-builder/sub-components/specifica-territoriale/specifica-territoriale.component.mjs +648 -0
- package/esm2022/lib/components/form-builder/sub-components/table-territoriale/table-territoriale.component.mjs +432 -0
- package/esm2022/lib/components/form-builder/types/condition.types.mjs +6 -0
- package/esm2022/lib/components/form-builder/types/field.types.mjs +6 -0
- package/esm2022/lib/components/form-builder/types/index.mjs +2 -0
- package/esm2022/lib/components/form-builder/types/schema.types.mjs +6 -0
- package/esm2022/lib/components/form-builder/types/territoriale.types.mjs +6 -0
- package/esm2022/lib/components/form-builder/types/validation.types.mjs +6 -0
- package/esm2022/lib/components/form-builder-editor/form-builder-editor.component.mjs +730 -0
- package/esm2022/lib/components/form-builder-editor/form-builder-editor.service.mjs +56 -0
- package/esm2022/lib/components/form-builder-editor/index.mjs +21 -0
- package/esm2022/lib/components/form-builder-editor/services/editor-persistence.service.mjs +190 -0
- package/esm2022/lib/components/form-builder-editor/services/editor-state.service.mjs +324 -0
- package/esm2022/lib/components/form-builder-editor/services/field-factory.service.mjs +188 -0
- package/esm2022/lib/components/form-builder-editor/sub-components/condition-editor/condition-editor.component.mjs +667 -0
- package/esm2022/lib/components/form-builder-editor/sub-components/editor-toolbar/editor-toolbar.component.mjs +317 -0
- package/esm2022/lib/components/form-builder-editor/sub-components/field-config-panel/field-config-panel.component.mjs +611 -0
- package/esm2022/lib/components/form-builder-editor/sub-components/field-palette/field-palette.component.mjs +267 -0
- package/esm2022/lib/components/form-builder-editor/sub-components/form-values-panel/form-values-panel.component.mjs +276 -0
- package/esm2022/lib/components/form-builder-editor/sub-components/options-editor/options-editor.component.mjs +323 -0
- package/esm2022/lib/components/form-builder-editor/sub-components/preview-container/preview-container.component.mjs +238 -0
- package/esm2022/lib/components/form-builder-editor/sub-components/section-editor/section-editor.component.mjs +472 -0
- package/esm2022/lib/components/form-builder-editor/sub-components/validation-editor/validation-editor.component.mjs +473 -0
- package/esm2022/lib/components/form-builder-editor/types/editor.types.mjs +6 -0
- package/esm2022/lib/components/layout-builder/index.mjs +18 -0
- package/esm2022/lib/components/layout-builder/layout-builder.component.mjs +1730 -0
- package/esm2022/lib/components/layout-builder/layout-builder.types.mjs +9 -0
- package/esm2022/lib/components/layout-builder/layout.service.mjs +239 -0
- package/esm2022/lib/components/modal/confirm-dialog.component.mjs +151 -0
- package/esm2022/lib/components/modal/index.mjs +4 -0
- package/esm2022/lib/components/modal/modal.component.mjs +139 -0
- package/esm2022/lib/components/modal/modal.service.mjs +194 -0
- package/esm2022/lib/components/modal/modal.types.mjs +6 -0
- package/esm2022/lib/components/page-header/breadcrumb.service.mjs +242 -0
- package/esm2022/lib/components/page-header/index.mjs +20 -0
- package/esm2022/lib/components/page-header/page-header.component.mjs +243 -0
- package/esm2022/lib/components/page-header/page-header.types.mjs +21 -0
- package/esm2022/lib/components/table/index.mjs +2 -0
- package/esm2022/lib/components/table/paginated-table.component.mjs +407 -0
- package/esm2022/lib/components/table/table.types.mjs +6 -0
- package/esm2022/lib/core/types/index.mjs +6 -0
- package/esm2022/lib/core/utils/index.mjs +53 -0
- package/esm2022/lib/sources/location-data.opt.json +8942 -0
- package/esm2022/lib/sources/nazioni.opt.json +215 -0
- package/esm2022/public-api.mjs +34 -0
- package/fesm2022/gnggln-ng-ui-system.mjs +55752 -0
- package/fesm2022/gnggln-ng-ui-system.mjs.map +1 -0
- package/index.d.ts +5 -0
- package/lib/components/accordion/accordion.component.d.ts +118 -0
- package/lib/components/accordion/accordion.types.d.ts +62 -0
- package/lib/components/accordion/index.d.ts +2 -0
- package/lib/components/base-layout/base-layout.component.d.ts +83 -0
- package/lib/components/base-layout/base-layout.types.d.ts +26 -0
- package/lib/components/base-layout/index.d.ts +13 -0
- package/lib/components/button/button-area.component.d.ts +88 -0
- package/lib/components/button/button.component.d.ts +55 -0
- package/lib/components/button/button.types.d.ts +70 -0
- package/lib/components/button/index.d.ts +15 -0
- package/lib/components/crud-table/crud-table.component.d.ts +143 -0
- package/lib/components/crud-table/crud-table.types.d.ts +207 -0
- package/lib/components/crud-table/index.d.ts +15 -0
- package/lib/components/form-builder/adapters/it-date-adapter.d.ts +32 -0
- package/lib/components/form-builder/directives/currency-input.directive.d.ts +48 -0
- package/lib/components/form-builder/form-builder.component.d.ts +183 -0
- package/lib/components/form-builder/form-wizard.component.d.ts +87 -0
- package/lib/components/form-builder/index.d.ts +13 -0
- package/lib/components/form-builder/services/form-condition.service.d.ts +46 -0
- package/lib/components/form-builder/services/form-validation.service.d.ts +63 -0
- package/lib/components/form-builder/services/location.service.d.ts +83 -0
- package/lib/components/form-builder/services/wizard-sync.service.d.ts +63 -0
- package/lib/components/form-builder/sub-components/error-summary/form-error-summary.component.d.ts +28 -0
- package/lib/components/form-builder/sub-components/file-input/file-input.component.d.ts +41 -0
- package/lib/components/form-builder/sub-components/specifica-territoriale/specifica-territoriale.component.d.ts +145 -0
- package/lib/components/form-builder/sub-components/table-territoriale/table-territoriale.component.d.ts +108 -0
- package/lib/components/form-builder/types/condition.types.d.ts +51 -0
- package/lib/components/form-builder/types/field.types.d.ts +288 -0
- package/lib/components/form-builder/types/index.d.ts +5 -0
- package/lib/components/form-builder/types/schema.types.d.ts +227 -0
- package/lib/components/form-builder/types/territoriale.types.d.ts +170 -0
- package/lib/components/form-builder/types/validation.types.d.ts +174 -0
- package/lib/components/form-builder-editor/form-builder-editor.component.d.ts +117 -0
- package/lib/components/form-builder-editor/form-builder-editor.service.d.ts +38 -0
- package/lib/components/form-builder-editor/index.d.ts +15 -0
- package/lib/components/form-builder-editor/services/editor-persistence.service.d.ts +42 -0
- package/lib/components/form-builder-editor/services/editor-state.service.d.ts +66 -0
- package/lib/components/form-builder-editor/services/field-factory.service.d.ts +28 -0
- package/lib/components/form-builder-editor/sub-components/condition-editor/condition-editor.component.d.ts +139 -0
- package/lib/components/form-builder-editor/sub-components/editor-toolbar/editor-toolbar.component.d.ts +43 -0
- package/lib/components/form-builder-editor/sub-components/field-config-panel/field-config-panel.component.d.ts +83 -0
- package/lib/components/form-builder-editor/sub-components/field-palette/field-palette.component.d.ts +40 -0
- package/lib/components/form-builder-editor/sub-components/form-values-panel/form-values-panel.component.d.ts +51 -0
- package/lib/components/form-builder-editor/sub-components/options-editor/options-editor.component.d.ts +63 -0
- package/lib/components/form-builder-editor/sub-components/preview-container/preview-container.component.d.ts +68 -0
- package/lib/components/form-builder-editor/sub-components/section-editor/section-editor.component.d.ts +82 -0
- package/lib/components/form-builder-editor/sub-components/validation-editor/validation-editor.component.d.ts +112 -0
- package/lib/components/form-builder-editor/types/editor.types.d.ts +124 -0
- package/lib/components/layout-builder/index.d.ts +16 -0
- package/lib/components/layout-builder/layout-builder.component.d.ts +85 -0
- package/lib/components/layout-builder/layout-builder.types.d.ts +436 -0
- package/lib/components/layout-builder/layout.service.d.ts +100 -0
- package/lib/components/modal/confirm-dialog.component.d.ts +46 -0
- package/lib/components/modal/index.d.ts +4 -0
- package/lib/components/modal/modal.component.d.ts +44 -0
- package/lib/components/modal/modal.service.d.ts +93 -0
- package/lib/components/modal/modal.types.d.ts +110 -0
- package/lib/components/page-header/breadcrumb.service.d.ts +96 -0
- package/lib/components/page-header/index.d.ts +16 -0
- package/lib/components/page-header/page-header.component.d.ts +59 -0
- package/lib/components/page-header/page-header.types.d.ts +96 -0
- package/lib/components/table/index.d.ts +2 -0
- package/lib/components/table/paginated-table.component.d.ts +85 -0
- package/lib/components/table/table.types.d.ts +81 -0
- package/lib/core/types/index.d.ts +57 -0
- package/lib/core/utils/index.d.ts +29 -0
- package/package.json +44 -0
- package/public-api.d.ts +22 -0
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { Injectable } from '@angular/core';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
/**
|
|
4
|
+
* Servizio per la valutazione delle condizioni di visibilita,
|
|
5
|
+
* required e disable dei campi del form.
|
|
6
|
+
*
|
|
7
|
+
* Supporta 12 operatori di confronto, logica AND/OR
|
|
8
|
+
* e accesso a valori annidati tramite dot notation.
|
|
9
|
+
*
|
|
10
|
+
* @providedIn 'root'
|
|
11
|
+
*/
|
|
12
|
+
export class UiFormConditionService {
|
|
13
|
+
/**
|
|
14
|
+
* Valuta una singola condizione rispetto ai dati del form.
|
|
15
|
+
*
|
|
16
|
+
* @param condition - Condizione da valutare.
|
|
17
|
+
* @param formData - Stato corrente dei dati del form.
|
|
18
|
+
* @returns `true` se la condizione e soddisfatta.
|
|
19
|
+
*/
|
|
20
|
+
evaluateCondition(condition, formData) {
|
|
21
|
+
const fieldValue = this.getNestedValue(formData, condition.field);
|
|
22
|
+
switch (condition.operator) {
|
|
23
|
+
case 'equals':
|
|
24
|
+
return fieldValue === condition.value;
|
|
25
|
+
case 'not_equals':
|
|
26
|
+
return fieldValue !== condition.value;
|
|
27
|
+
case 'contains':
|
|
28
|
+
return this.stringContains(fieldValue, condition.value);
|
|
29
|
+
case 'not_contains':
|
|
30
|
+
return !this.stringContains(fieldValue, condition.value);
|
|
31
|
+
case 'greater_than':
|
|
32
|
+
return this.numericCompare(fieldValue, condition.value, '>');
|
|
33
|
+
case 'less_than':
|
|
34
|
+
return this.numericCompare(fieldValue, condition.value, '<');
|
|
35
|
+
case 'greater_equal':
|
|
36
|
+
return this.numericCompare(fieldValue, condition.value, '>=');
|
|
37
|
+
case 'less_equal':
|
|
38
|
+
return this.numericCompare(fieldValue, condition.value, '<=');
|
|
39
|
+
case 'is_empty':
|
|
40
|
+
return this.isEmpty(fieldValue);
|
|
41
|
+
case 'is_not_empty':
|
|
42
|
+
return !this.isEmpty(fieldValue);
|
|
43
|
+
case 'in_array':
|
|
44
|
+
return Array.isArray(condition.value) && condition.value.includes(fieldValue);
|
|
45
|
+
case 'not_in_array':
|
|
46
|
+
return Array.isArray(condition.value) && !condition.value.includes(fieldValue);
|
|
47
|
+
default:
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Valuta un array di condizioni con logica AND/OR.
|
|
53
|
+
*
|
|
54
|
+
* La prima condizione stabilisce il valore iniziale.
|
|
55
|
+
* Le condizioni successive usano la proprieta `logic` per
|
|
56
|
+
* combinare il risultato (`AND` per default).
|
|
57
|
+
*
|
|
58
|
+
* @param conditions - Array di condizioni.
|
|
59
|
+
* @param formData - Stato corrente dei dati del form.
|
|
60
|
+
* @returns `true` se le condizioni combinate sono soddisfatte.
|
|
61
|
+
*/
|
|
62
|
+
evaluateConditions(conditions, formData) {
|
|
63
|
+
if (!conditions || conditions.length === 0) {
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
let result = this.evaluateCondition(conditions[0], formData);
|
|
67
|
+
for (let i = 1; i < conditions.length; i++) {
|
|
68
|
+
const condition = conditions[i];
|
|
69
|
+
const conditionResult = this.evaluateCondition(condition, formData);
|
|
70
|
+
if (condition.logic === 'OR') {
|
|
71
|
+
result = result || conditionResult;
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
result = result && conditionResult;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return result;
|
|
78
|
+
}
|
|
79
|
+
/** Accesso a valori annidati tramite dot notation (es. `'address.city'`). */
|
|
80
|
+
getNestedValue(obj, path) {
|
|
81
|
+
return path
|
|
82
|
+
.split('.')
|
|
83
|
+
.reduce((current, key) => (current != null && current[key] !== undefined ? current[key] : undefined), obj);
|
|
84
|
+
}
|
|
85
|
+
/** Confronto stringa case-insensitive. */
|
|
86
|
+
stringContains(haystack, needle) {
|
|
87
|
+
if (haystack == null || needle == null)
|
|
88
|
+
return false;
|
|
89
|
+
return String(haystack).toLowerCase().includes(String(needle).toLowerCase());
|
|
90
|
+
}
|
|
91
|
+
/** Confronto numerico generico. */
|
|
92
|
+
numericCompare(a, b, op) {
|
|
93
|
+
const n1 = Number(a);
|
|
94
|
+
const n2 = Number(b);
|
|
95
|
+
if (isNaN(n1) || isNaN(n2))
|
|
96
|
+
return false;
|
|
97
|
+
switch (op) {
|
|
98
|
+
case '>':
|
|
99
|
+
return n1 > n2;
|
|
100
|
+
case '<':
|
|
101
|
+
return n1 < n2;
|
|
102
|
+
case '>=':
|
|
103
|
+
return n1 >= n2;
|
|
104
|
+
case '<=':
|
|
105
|
+
return n1 <= n2;
|
|
106
|
+
default:
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Verifica se un valore e vuoto in modo robusto.
|
|
112
|
+
* Gestisce null, undefined, false, stringhe vuote, array vuoti e oggetti vuoti.
|
|
113
|
+
*/
|
|
114
|
+
isEmpty(value) {
|
|
115
|
+
if (value === null || value === undefined || value === false)
|
|
116
|
+
return true;
|
|
117
|
+
if (typeof value === 'string' && value.trim().length === 0)
|
|
118
|
+
return true;
|
|
119
|
+
if (Array.isArray(value) && value.length === 0)
|
|
120
|
+
return true;
|
|
121
|
+
if (typeof value === 'object' && Object.keys(value).length === 0)
|
|
122
|
+
return true;
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: UiFormConditionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
126
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: UiFormConditionService, providedIn: 'root' }); }
|
|
127
|
+
}
|
|
128
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: UiFormConditionService, decorators: [{
|
|
129
|
+
type: Injectable,
|
|
130
|
+
args: [{ providedIn: 'root' }]
|
|
131
|
+
}] });
|
|
132
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9ybS1jb25kaXRpb24uc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL25nLXVpLXN5c3RlbS9zcmMvbGliL2NvbXBvbmVudHMvZm9ybS1idWlsZGVyL3NlcnZpY2VzL2Zvcm0tY29uZGl0aW9uLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQzs7QUFHM0M7Ozs7Ozs7O0dBUUc7QUFFSCxNQUFNLE9BQU8sc0JBQXNCO0lBQ2pDOzs7Ozs7T0FNRztJQUNILGlCQUFpQixDQUFDLFNBQTJCLEVBQUUsUUFBNkI7UUFDMUUsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxRQUFRLEVBQUUsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBRWxFLFFBQVEsU0FBUyxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQzNCLEtBQUssUUFBUTtnQkFDWCxPQUFPLFVBQVUsS0FBSyxTQUFTLENBQUMsS0FBSyxDQUFDO1lBQ3hDLEtBQUssWUFBWTtnQkFDZixPQUFPLFVBQVUsS0FBSyxTQUFTLENBQUMsS0FBSyxDQUFDO1lBQ3hDLEtBQUssVUFBVTtnQkFDYixPQUFPLElBQUksQ0FBQyxjQUFjLENBQUMsVUFBVSxFQUFFLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUMxRCxLQUFLLGNBQWM7Z0JBQ2pCLE9BQU8sQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLFVBQVUsRUFBRSxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDM0QsS0FBSyxjQUFjO2dCQUNqQixPQUFPLElBQUksQ0FBQyxjQUFjLENBQUMsVUFBVSxFQUFFLFNBQVMsQ0FBQyxLQUFLLEVBQUUsR0FBRyxDQUFDLENBQUM7WUFDL0QsS0FBSyxXQUFXO2dCQUNkLE9BQU8sSUFBSSxDQUFDLGNBQWMsQ0FBQyxVQUFVLEVBQUUsU0FBUyxDQUFDLEtB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QXNCLGNBRFQsTUFBTTs7NEZBQ25CLHNCQUFzQjtrQkFEbEMsVUFBVTttQkFBQyxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IFVpRmllbGRDb25kaXRpb24gfSBmcm9tICcuLi90eXBlcy9jb25kaXRpb24udHlwZXMnO1xyXG5cclxuLyoqXHJcbiAqIFNlcnZpemlvIHBlciBsYSB2YWx1dGF6aW9uZSBkZWxsZSBjb25kaXppb25pIGRpIHZpc2liaWxpdGEsXHJcbiAqIHJlcXVpcmVkIGUgZGlzYWJsZSBkZWkgY2FtcGkgZGVsIGZvcm0uXHJcbiAqXHJcbiAqIFN1cHBvcnRhIDEyIG9wZXJhdG9yaSBkaSBjb25mcm9udG8sIGxvZ2ljYSBBTkQvT1JcclxuICogZSBhY2Nlc3NvIGEgdmFsb3JpIGFubmlkYXRpIHRyYW1pdGUgZG90IG5vdGF0aW9uLlxyXG4gKlxyXG4gKiBAcHJvdmlkZWRJbiAncm9vdCdcclxuICovXHJcbkBJbmplY3RhYmxlKHsgcHJvdmlkZWRJbjogJ3Jvb3QnIH0pXHJcbmV4cG9ydCBjbGFzcyBVaUZvcm1Db25kaXRpb25TZXJ2aWNlIHtcclxuICAvKipcclxuICAgKiBWYWx1dGEgdW5hIHNpbmdvbGEgY29uZGl6aW9uZSByaXNwZXR0byBhaSBkYXRpIGRlbCBmb3JtLlxyXG4gICAqXHJcbiAgICogQHBhcmFtIGNvbmRpdGlvbiAtIENvbmRpemlvbmUgZGEgdmFsdXRhcmUuXHJcbiAgICogQHBhcmFtIGZvcm1EYXRhIC0gU3RhdG8gY29ycmVudGUgZGVpIGRhdGkgZGVsIGZvcm0uXHJcbiAgICogQHJldHVybnMgYHRydWVgIHNlIGxhIGNvbmRpemlvbmUgZSBzb2RkaXNmYXR0YS5cclxuICAgKi9cclxuICBldmFsdWF0ZUNvbmRpdGlvbihjb25kaXRpb246IFVpRmllbGRDb25kaXRpb24sIGZvcm1EYXRhOiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogYm9vbGVhbiB7XHJcbiAgICBjb25zdCBmaWVsZFZhbHVlID0gdGhpcy5nZXROZXN0ZWRWYWx1ZShmb3JtRGF0YSwgY29uZGl0aW9uLmZpZWxkKTtcclxuXHJcbiAgICBzd2l0Y2ggKGNvbmRpdGlvbi5vcGVyYXRvcikge1xyXG4gICAgICBjYXNlICdlcXVhbHMnOlxyXG4gICAgICAgIHJldHVybiBmaWVsZFZhbHVlID09PSBjb25kaXRpb24udmFsdWU7XHJcbiAgICAgIGNhc2UgJ25vdF9lcXVhbHMnOlxyXG4gICAgICAgIHJldHVybiBmaWVsZFZhbHVlICE9PSBjb25kaXRpb24udmFsdWU7XHJcbiAgICAgIGNhc2UgJ2NvbnRhaW5zJzpcclxuICAgICAgICByZXR1cm4gdGhpcy5zdHJpbmdDb250YWlucyhmaWVsZFZhbHVlLCBjb25kaXRpb24udmFsdWUpO1xyXG4gICAgICBjYXNlICdub3RfY29udGFpbnMnOlxyXG4gICAgICAgIHJldHVybiAhdGhpcy5zdHJpbmdDb250YWlucyhmaWVsZFZhbHVlLCBjb25kaXRpb24udmFsdWUpO1xyXG4gICAgICBjYXNlICdncmVhdGVyX3RoYW4nOlxyXG4gICAgICAgIHJldHVybiB0aGlzLm51bWVyaWNDb21wYXJlKGZpZWxkVmFsdWUsIGNvbmRpdGlvbi52YWx1ZSwgJz4nKTtcclxuICAgICAgY2FzZSAnbGVzc190aGFuJzpcclxuICAgICAgICByZXR1cm4gdGhpcy5udW1lcmljQ29tcGFyZShmaWVsZFZhbHVlLCBjb25kaXRpb24udmFsdWUsICc8Jyk7XHJcbiAgICAgIGNhc2UgJ2dyZWF0ZXJfZXF1YWwnOlxyXG4gICAgICAgIHJldHVybiB0aGlzLm51bWVyaWNDb21wYXJlKGZpZWxkVmFsdWUsIGNvbmRpdGlvbi52YWx1ZSwgJz49Jyk7XHJcbiAgICAgIGNhc2UgJ2xlc3NfZXF1YWwnOlxyXG4gICAgICAgIHJldHVybiB0aGlzLm51bWVyaWNDb21wYXJlKGZpZWxkVmFsdWUsIGNvbmRpdGlvbi52YWx1ZSwgJzw9Jyk7XHJcbiAgICAgIGNhc2UgJ2lzX2VtcHR5JzpcclxuICAgICAgICByZXR1cm4gdGhpcy5pc0VtcHR5KGZpZWxkVmFsdWUpO1xyXG4gICAgICBjYXNlICdpc19ub3RfZW1wdHknOlxyXG4gICAgICAgIHJldHVybiAhdGhpcy5pc0VtcHR5KGZpZWxkVmFsdWUpO1xyXG4gICAgICBjYXNlICdpbl9hcnJheSc6XHJcbiAgICAgICAgcmV0dXJuIEFycmF5LmlzQXJyYXkoY29uZGl0aW9uLnZhbHVlKSAmJiBjb25kaXRpb24udmFsdWUuaW5jbHVkZXMoZmllbGRWYWx1ZSk7XHJcbiAgICAgIGNhc2UgJ25vdF9pbl9hcnJheSc6XHJcbiAgICAgICAgcmV0dXJuIEFycmF5LmlzQXJyYXkoY29uZGl0aW9uLnZhbHVlKSAmJiAhY29uZGl0aW9uLnZhbHVlLmluY2x1ZGVzKGZpZWxkVmFsdWUpO1xyXG4gICAgICBkZWZhdWx0OlxyXG4gICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFZhbHV0YSB1biBhcnJheSBkaSBjb25kaXppb25pIGNvbiBsb2dpY2EgQU5EL09SLlxyXG4gICAqXHJcbiAgICogTGEgcHJpbWEgY29uZGl6aW9uZSBzdGFiaWxpc2NlIGlsIHZhbG9yZSBpbml6aWFsZS5cclxuICAgKiBMZSBjb25kaXppb25pIHN1Y2Nlc3NpdmUgdXNhbm8gbGEgcHJvcHJpZXRhIGBsb2dpY2AgcGVyXHJcbiAgICogY29tYmluYXJlIGlsIHJpc3VsdGF0byAoYEFORGAgcGVyIGRlZmF1bHQpLlxyXG4gICAqXHJcbiAgICogQHBhcmFtIGNvbmRpdGlvbnMgLSBBcnJheSBkaSBjb25kaXppb25pLlxyXG4gICAqIEBwYXJhbSBmb3JtRGF0YSAtIFN0YXRvIGNvcnJlbnRlIGRlaSBkYXRpIGRlbCBmb3JtLlxyXG4gICAqIEByZXR1cm5zIGB0cnVlYCBzZSBsZSBjb25kaXppb25pIGNvbWJpbmF0ZSBzb25vIHNvZGRpc2ZhdHRlLlxyXG4gICAqL1xyXG4gIGV2YWx1YXRlQ29uZGl0aW9ucyhjb25kaXRpb25zOiBVaUZpZWxkQ29uZGl0aW9uW10sIGZvcm1EYXRhOiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogYm9vbGVhbiB7XHJcbiAgICBpZiAoIWNvbmRpdGlvbnMgfHwgY29uZGl0aW9ucy5sZW5ndGggPT09IDApIHtcclxuICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICB9XHJcblxyXG4gICAgbGV0IHJlc3VsdCA9IHRoaXMuZXZhbHVhdGVDb25kaXRpb24oY29uZGl0aW9uc1swXSwgZm9ybURhdGEpO1xyXG5cclxuICAgIGZvciAobGV0IGkgPSAxOyBpIDwgY29uZGl0aW9ucy5sZW5ndGg7IGkrKykge1xyXG4gICAgICBjb25zdCBjb25kaXRpb24gPSBjb25kaXRpb25zW2ldO1xyXG4gICAgICBjb25zdCBjb25kaXRpb25SZXN1bHQgPSB0aGlzLmV2YWx1YXRlQ29uZGl0aW9uKGNvbmRpdGlvbiwgZm9ybURhdGEpO1xyXG5cclxuICAgICAgaWYgKGNvbmRpdGlvbi5sb2dpYyA9PT0gJ09SJykge1xyXG4gICAgICAgIHJlc3VsdCA9IHJlc3VsdCB8fCBjb25kaXRpb25SZXN1bHQ7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgcmVzdWx0ID0gcmVzdWx0ICYmIGNvbmRpdGlvblJlc3VsdDtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiByZXN1bHQ7XHJcbiAgfVxyXG5cclxuICAvKiogQWNjZXNzbyBhIHZhbG9yaSBhbm5pZGF0aSB0cmFtaXRlIGRvdCBub3RhdGlvbiAoZXMuIGAnYWRkcmVzcy5jaXR5J2ApLiAqL1xyXG4gIHByaXZhdGUgZ2V0TmVzdGVkVmFsdWUob2JqOiBhbnksIHBhdGg6IHN0cmluZyk6IGFueSB7XHJcbiAgICByZXR1cm4gcGF0aFxyXG4gICAgICAuc3BsaXQoJy4nKVxyXG4gICAgICAucmVkdWNlKChjdXJyZW50LCBrZXkpID0+IChjdXJyZW50ICE9IG51bGwgJiYgY3VycmVudFtrZXldICE9PSB1bmRlZmluZWQgPyBjdXJyZW50W2tleV0gOiB1bmRlZmluZWQpLCBvYmopO1xyXG4gIH1cclxuXHJcbiAgLyoqIENvbmZyb250byBzdHJpbmdhIGNhc2UtaW5zZW5zaXRpdmUuICovXHJcbiAgcHJpdmF0ZSBzdHJpbmdDb250YWlucyhoYXlzdGFjazogYW55LCBuZWVkbGU6IGFueSk6IGJvb2xlYW4ge1xyXG4gICAgaWYgKGhheXN0YWNrID09IG51bGwgfHwgbmVlZGxlID09IG51bGwpIHJldHVybiBmYWxzZTtcclxuICAgIHJldHVybiBTdHJpbmcoaGF5c3RhY2spLnRvTG93ZXJDYXNlKCkuaW5jbHVkZXMoU3RyaW5nKG5lZWRsZSkudG9Mb3dlckNhc2UoKSk7XHJcbiAgfVxyXG5cclxuICAvKiogQ29uZnJvbnRvIG51bWVyaWNvIGdlbmVyaWNvLiAqL1xyXG4gIHByaXZhdGUgbnVtZXJpY0NvbXBhcmUoYTogYW55LCBiOiBhbnksIG9wOiBzdHJpbmcpOiBib29sZWFuIHtcclxuICAgIGNvbnN0IG4xID0gTnVtYmVyKGEpO1xyXG4gICAgY29uc3QgbjIgPSBOdW1iZXIoYik7XHJcbiAgICBpZiAoaXNOYU4objEpIHx8IGlzTmFOKG4yKSkgcmV0dXJuIGZhbHNlO1xyXG4gICAgc3dpdGNoIChvcCkge1xyXG4gICAgICBjYXNlICc+JzpcclxuICAgICAgICByZXR1cm4gbjEgPiBuMjtcclxuICAgICAgY2FzZSAnPCc6XHJcbiAgICAgICAgcmV0dXJuIG4xIDwgbjI7XHJcbiAgICAgIGNhc2UgJz49JzpcclxuICAgICAgICByZXR1cm4gbjEgPj0gbjI7XHJcbiAgICAgIGNhc2UgJzw9JzpcclxuICAgICAgICByZXR1cm4gbjEgPD0gbjI7XHJcbiAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogVmVyaWZpY2Egc2UgdW4gdmFsb3JlIGUgdnVvdG8gaW4gbW9kbyByb2J1c3RvLlxyXG4gICAqIEdlc3Rpc2NlIG51bGwsIHVuZGVmaW5lZCwgZmFsc2UsIHN0cmluZ2hlIHZ1b3RlLCBhcnJheSB2dW90aSBlIG9nZ2V0dGkgdnVvdGkuXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBpc0VtcHR5KHZhbHVlOiBhbnkpOiBib29sZWFuIHtcclxuICAgIGlmICh2YWx1ZSA9PT0gbnVsbCB8fCB2YWx1ZSA9PT0gdW5kZWZpbmVkIHx8IHZhbHVlID09PSBmYWxzZSkgcmV0dXJuIHRydWU7XHJcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJyAmJiB2YWx1ZS50cmltKCkubGVuZ3RoID09PSAwKSByZXR1cm4gdHJ1ZTtcclxuICAgIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSAmJiB2YWx1ZS5sZW5ndGggPT09IDApIHJldHVybiB0cnVlO1xyXG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcgJiYgT2JqZWN0LmtleXModmFsdWUpLmxlbmd0aCA9PT0gMCkgcmV0dXJuIHRydWU7XHJcbiAgICByZXR1cm4gZmFsc2U7XHJcbiAgfVxyXG59XHJcbiJdfQ==
|
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
import { Injectable } from '@angular/core';
|
|
2
|
+
import { Validators } from '@angular/forms';
|
|
3
|
+
import { parse, format, startOfDay, startOfMonth, addDays, addMonths, addYears, addWeeks, isAfter, isBefore, isEqual, isValid as isDateValid, } from 'date-fns';
|
|
4
|
+
import * as i0 from "@angular/core";
|
|
5
|
+
import * as i1 from "./form-condition.service";
|
|
6
|
+
/**
|
|
7
|
+
* Servizio per la creazione e gestione dei validatori Angular
|
|
8
|
+
* basati sulle regole dichiarative dello schema del form.
|
|
9
|
+
*
|
|
10
|
+
* Supporta validazioni standard, cross-field, date con offset,
|
|
11
|
+
* file e validatori condizionali.
|
|
12
|
+
*
|
|
13
|
+
* @providedIn 'root'
|
|
14
|
+
*/
|
|
15
|
+
export class UiFormValidationService {
|
|
16
|
+
constructor(conditionService) {
|
|
17
|
+
this.conditionService = conditionService;
|
|
18
|
+
}
|
|
19
|
+
// ─── Creazione validatori ──────────────────────────────────────
|
|
20
|
+
/** Crea un array di validatori Angular dalle regole di validazione. */
|
|
21
|
+
createValidators(rules) {
|
|
22
|
+
if (!rules?.length)
|
|
23
|
+
return [];
|
|
24
|
+
return rules.map((r) => this.createValidator(r)).filter((v) => v !== null);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Crea validatori con supporto condizionale.
|
|
28
|
+
* Le regole con `conditions` vengono applicate solo se le condizioni sono soddisfatte.
|
|
29
|
+
*/
|
|
30
|
+
createConditionalValidators(rules, formData) {
|
|
31
|
+
if (!rules?.length)
|
|
32
|
+
return [];
|
|
33
|
+
const validators = [];
|
|
34
|
+
for (const rule of rules) {
|
|
35
|
+
if (rule.conditions?.length) {
|
|
36
|
+
const shouldApply = this.conditionService.evaluateConditions(rule.conditions, formData);
|
|
37
|
+
if (!shouldApply)
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
const v = this.createValidator(rule);
|
|
41
|
+
if (v)
|
|
42
|
+
validators.push(v);
|
|
43
|
+
}
|
|
44
|
+
return validators;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Aggiorna i validatori di un campo in base allo stato corrente del form.
|
|
48
|
+
* Usato per ricalcolare validazioni condizionali quando i dati cambiano.
|
|
49
|
+
*/
|
|
50
|
+
updateFieldValidators(control, rules, formData) {
|
|
51
|
+
if (!rules?.length) {
|
|
52
|
+
control.clearValidators();
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
const validators = this.createConditionalValidators(rules, formData);
|
|
56
|
+
control.setValidators(validators);
|
|
57
|
+
}
|
|
58
|
+
control.updateValueAndValidity({ emitEvent: false });
|
|
59
|
+
}
|
|
60
|
+
// ─── Utility pubbliche ─────────────────────────────────────────
|
|
61
|
+
/** Verifica se un campo dovrebbe mostrare gli errori. */
|
|
62
|
+
shouldShowFieldErrors(control) {
|
|
63
|
+
return control.invalid && (control.dirty || control.touched);
|
|
64
|
+
}
|
|
65
|
+
/** Restituisce i campi correlati da cross-field validation. */
|
|
66
|
+
getCrossFieldRelatedFields(fieldKey, allRules) {
|
|
67
|
+
const related = [];
|
|
68
|
+
for (const [key, rules] of Object.entries(allRules)) {
|
|
69
|
+
if (key === fieldKey)
|
|
70
|
+
continue;
|
|
71
|
+
for (const rule of rules) {
|
|
72
|
+
if (rule.type === 'crossField' && rule.crossField?.targetField === fieldKey) {
|
|
73
|
+
related.push(key);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return related;
|
|
78
|
+
}
|
|
79
|
+
/** Verifica se un campo ha validazioni cross-field che lo referenziano. */
|
|
80
|
+
hasCrossFieldValidations(fieldKey, allRules) {
|
|
81
|
+
return this.getCrossFieldRelatedFields(fieldKey, allRules).length > 0;
|
|
82
|
+
}
|
|
83
|
+
/** Formatta la dimensione del file in una stringa leggibile. */
|
|
84
|
+
formatFileSize(bytes) {
|
|
85
|
+
if (bytes === 0)
|
|
86
|
+
return '0 B';
|
|
87
|
+
const k = 1024;
|
|
88
|
+
const sizes = ['B', 'KB', 'MB', 'GB'];
|
|
89
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
90
|
+
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
|
91
|
+
}
|
|
92
|
+
// ─── Factory validatori ────────────────────────────────────────
|
|
93
|
+
createValidator(rule) {
|
|
94
|
+
switch (rule.type) {
|
|
95
|
+
case 'required':
|
|
96
|
+
return Validators.required;
|
|
97
|
+
case 'email':
|
|
98
|
+
return Validators.email;
|
|
99
|
+
case 'min':
|
|
100
|
+
return Validators.min(rule.value);
|
|
101
|
+
case 'max':
|
|
102
|
+
return Validators.max(rule.value);
|
|
103
|
+
case 'minLength':
|
|
104
|
+
return Validators.minLength(rule.value);
|
|
105
|
+
case 'maxLength':
|
|
106
|
+
return Validators.maxLength(rule.value);
|
|
107
|
+
case 'pattern':
|
|
108
|
+
return Validators.pattern(rule.value);
|
|
109
|
+
case 'custom':
|
|
110
|
+
return rule.validator || null;
|
|
111
|
+
case 'crossField':
|
|
112
|
+
return rule.crossField ? this.createCrossFieldValidator(rule.crossField) : null;
|
|
113
|
+
case 'date-min':
|
|
114
|
+
return this.createDateMinValidator(rule.value, rule.offset);
|
|
115
|
+
case 'date-max':
|
|
116
|
+
return this.createDateMaxValidator(rule.value, rule.offset);
|
|
117
|
+
case 'fileSize':
|
|
118
|
+
return this.createFileSizeValidator(rule.value);
|
|
119
|
+
case 'fileType':
|
|
120
|
+
return this.createFileTypeValidator(rule.value);
|
|
121
|
+
case 'fileCount':
|
|
122
|
+
return this.createFileCountValidator(rule.value);
|
|
123
|
+
default:
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
// ─── Cross-field ───────────────────────────────────────────────
|
|
128
|
+
createCrossFieldValidator(config) {
|
|
129
|
+
return (control) => {
|
|
130
|
+
if (!control.parent || !config.targetField)
|
|
131
|
+
return null;
|
|
132
|
+
const targetControl = control.parent.get(config.targetField);
|
|
133
|
+
if (!targetControl)
|
|
134
|
+
return null;
|
|
135
|
+
const sourceValue = control.value;
|
|
136
|
+
const targetValue = targetControl.value;
|
|
137
|
+
if (sourceValue == null || targetValue == null || sourceValue === '' || targetValue === '') {
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
let isValid = false;
|
|
141
|
+
if (config.dataType === 'date') {
|
|
142
|
+
isValid = this.validateDateComparison(sourceValue, targetValue, config.operator, config.isMonthYear);
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
isValid = this.validateNumberComparison(sourceValue, targetValue, config.operator);
|
|
146
|
+
}
|
|
147
|
+
return isValid
|
|
148
|
+
? null
|
|
149
|
+
: {
|
|
150
|
+
crossField: {
|
|
151
|
+
actualValue: sourceValue,
|
|
152
|
+
requiredComparison: config.operator,
|
|
153
|
+
comparedValue: targetValue,
|
|
154
|
+
targetField: config.targetField,
|
|
155
|
+
},
|
|
156
|
+
};
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
/** Confronto date con date-fns. */
|
|
160
|
+
validateDateComparison(sourceValue, targetValue, operator, isMonthYear) {
|
|
161
|
+
const normalize = isMonthYear ? startOfMonth : startOfDay;
|
|
162
|
+
const sourceDate = normalize(new Date(sourceValue));
|
|
163
|
+
const targetDate = normalize(new Date(targetValue));
|
|
164
|
+
if (!isDateValid(sourceDate) || !isDateValid(targetDate))
|
|
165
|
+
return false;
|
|
166
|
+
switch (operator) {
|
|
167
|
+
case 'greater_than':
|
|
168
|
+
return isAfter(sourceDate, targetDate);
|
|
169
|
+
case 'greater_equal':
|
|
170
|
+
return isAfter(sourceDate, targetDate) || isEqual(sourceDate, targetDate);
|
|
171
|
+
case 'less_than':
|
|
172
|
+
return isBefore(sourceDate, targetDate);
|
|
173
|
+
case 'less_equal':
|
|
174
|
+
return isBefore(sourceDate, targetDate) || isEqual(sourceDate, targetDate);
|
|
175
|
+
case 'not_equal':
|
|
176
|
+
return !isEqual(sourceDate, targetDate);
|
|
177
|
+
default:
|
|
178
|
+
return false;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
/** Confronto numerico. */
|
|
182
|
+
validateNumberComparison(sourceValue, targetValue, operator) {
|
|
183
|
+
const src = Number(sourceValue);
|
|
184
|
+
const tgt = Number(targetValue);
|
|
185
|
+
if (isNaN(src) || isNaN(tgt))
|
|
186
|
+
return false;
|
|
187
|
+
switch (operator) {
|
|
188
|
+
case 'greater_than':
|
|
189
|
+
return src > tgt;
|
|
190
|
+
case 'greater_equal':
|
|
191
|
+
return src >= tgt;
|
|
192
|
+
case 'less_than':
|
|
193
|
+
return src < tgt;
|
|
194
|
+
case 'less_equal':
|
|
195
|
+
return src <= tgt;
|
|
196
|
+
case 'not_equal':
|
|
197
|
+
return src !== tgt;
|
|
198
|
+
default:
|
|
199
|
+
return false;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
// ─── Date min/max (con keyword e offset) ───────────────────────
|
|
203
|
+
createDateMinValidator(value, offset) {
|
|
204
|
+
return (control) => {
|
|
205
|
+
if (!control.value)
|
|
206
|
+
return null;
|
|
207
|
+
const refDate = this.parseReferenceDate(value, offset);
|
|
208
|
+
if (!refDate)
|
|
209
|
+
return null;
|
|
210
|
+
const inputDate = startOfDay(new Date(control.value));
|
|
211
|
+
if (!isDateValid(inputDate)) {
|
|
212
|
+
return { 'date-min': { message: 'Data non valida', referenceDate: this.formatRefDate(refDate) } };
|
|
213
|
+
}
|
|
214
|
+
if (isBefore(inputDate, refDate)) {
|
|
215
|
+
return {
|
|
216
|
+
'date-min': {
|
|
217
|
+
message: `La data deve essere successiva o uguale a ${this.formatRefDate(refDate)}`,
|
|
218
|
+
referenceDate: this.formatRefDate(refDate),
|
|
219
|
+
inputDate: format(inputDate, 'dd/MM/yyyy'),
|
|
220
|
+
},
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
return null;
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
createDateMaxValidator(value, offset) {
|
|
227
|
+
return (control) => {
|
|
228
|
+
if (!control.value)
|
|
229
|
+
return null;
|
|
230
|
+
const refDate = this.parseReferenceDate(value, offset);
|
|
231
|
+
if (!refDate)
|
|
232
|
+
return null;
|
|
233
|
+
const inputDate = startOfDay(new Date(control.value));
|
|
234
|
+
if (!isDateValid(inputDate)) {
|
|
235
|
+
return { 'date-max': { message: 'Data non valida', referenceDate: this.formatRefDate(refDate) } };
|
|
236
|
+
}
|
|
237
|
+
if (isAfter(inputDate, refDate)) {
|
|
238
|
+
return {
|
|
239
|
+
'date-max': {
|
|
240
|
+
message: `La data deve essere precedente o uguale a ${this.formatRefDate(refDate)}`,
|
|
241
|
+
referenceDate: this.formatRefDate(refDate),
|
|
242
|
+
inputDate: format(inputDate, 'dd/MM/yyyy'),
|
|
243
|
+
},
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
return null;
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Parsa una data di riferimento da keyword o stringa DD/MM/YYYY
|
|
251
|
+
* e applica un eventuale offset temporale.
|
|
252
|
+
*/
|
|
253
|
+
parseReferenceDate(value, offset) {
|
|
254
|
+
const today = startOfDay(new Date());
|
|
255
|
+
let date;
|
|
256
|
+
switch (value?.toLowerCase().trim()) {
|
|
257
|
+
case 'today':
|
|
258
|
+
case 'oggi':
|
|
259
|
+
date = today;
|
|
260
|
+
break;
|
|
261
|
+
case 'tomorrow':
|
|
262
|
+
case 'domani':
|
|
263
|
+
date = addDays(today, 1);
|
|
264
|
+
break;
|
|
265
|
+
case 'yesterday':
|
|
266
|
+
case 'ieri':
|
|
267
|
+
date = addDays(today, -1);
|
|
268
|
+
break;
|
|
269
|
+
default: {
|
|
270
|
+
// Prova DD/MM/YYYY
|
|
271
|
+
const parsed = parse(value, 'dd/MM/yyyy', new Date());
|
|
272
|
+
if (isDateValid(parsed)) {
|
|
273
|
+
date = startOfDay(parsed);
|
|
274
|
+
}
|
|
275
|
+
else {
|
|
276
|
+
// Prova YYYY-MM-DD (ISO)
|
|
277
|
+
const isoDate = new Date(value);
|
|
278
|
+
if (isDateValid(isoDate)) {
|
|
279
|
+
date = startOfDay(isoDate);
|
|
280
|
+
}
|
|
281
|
+
else {
|
|
282
|
+
return null;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
return offset ? this.applyDateOffset(date, offset) : date;
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Applica un offset temporale a una data.
|
|
291
|
+
*
|
|
292
|
+
* Formato: `numero + unita`
|
|
293
|
+
* - `y`/`a` = anni, `m` = mesi, `g`/`d` = giorni, `s`/`w` = settimane
|
|
294
|
+
*/
|
|
295
|
+
applyDateOffset(date, offset) {
|
|
296
|
+
const match = offset.match(/^(-?\d+)([yYaAmMgGdDsSwW])$/);
|
|
297
|
+
if (!match)
|
|
298
|
+
return date;
|
|
299
|
+
const amount = parseInt(match[1], 10);
|
|
300
|
+
switch (match[2].toLowerCase()) {
|
|
301
|
+
case 'y':
|
|
302
|
+
case 'a':
|
|
303
|
+
return addYears(date, amount);
|
|
304
|
+
case 'm':
|
|
305
|
+
return addMonths(date, amount);
|
|
306
|
+
case 'g':
|
|
307
|
+
case 'd':
|
|
308
|
+
return addDays(date, amount);
|
|
309
|
+
case 's':
|
|
310
|
+
case 'w':
|
|
311
|
+
return addWeeks(date, amount);
|
|
312
|
+
default:
|
|
313
|
+
return date;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
formatRefDate(date) {
|
|
317
|
+
return format(date, 'dd/MM/yyyy');
|
|
318
|
+
}
|
|
319
|
+
// ─── File validators ───────────────────────────────────────────
|
|
320
|
+
createFileSizeValidator(maxSize) {
|
|
321
|
+
return (control) => {
|
|
322
|
+
const files = control.value;
|
|
323
|
+
if (!Array.isArray(files) || files.length === 0)
|
|
324
|
+
return null;
|
|
325
|
+
const oversized = files.filter((f) => f.size > maxSize);
|
|
326
|
+
if (oversized.length > 0) {
|
|
327
|
+
return {
|
|
328
|
+
fileSize: {
|
|
329
|
+
maxSize,
|
|
330
|
+
maxSizeFormatted: this.formatFileSize(maxSize),
|
|
331
|
+
files: oversized.map((f) => f.filename),
|
|
332
|
+
},
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
return null;
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
createFileTypeValidator(allowedTypes) {
|
|
339
|
+
return (control) => {
|
|
340
|
+
const files = control.value;
|
|
341
|
+
if (!Array.isArray(files) || files.length === 0)
|
|
342
|
+
return null;
|
|
343
|
+
const invalid = files.filter((f) => {
|
|
344
|
+
return !allowedTypes.some((type) => {
|
|
345
|
+
if (type.endsWith('/*')) {
|
|
346
|
+
const category = type.split('/')[0];
|
|
347
|
+
return f.mimeType.startsWith(category + '/');
|
|
348
|
+
}
|
|
349
|
+
return f.mimeType === type;
|
|
350
|
+
});
|
|
351
|
+
});
|
|
352
|
+
if (invalid.length > 0) {
|
|
353
|
+
return {
|
|
354
|
+
fileType: {
|
|
355
|
+
allowedTypes,
|
|
356
|
+
files: invalid.map((f) => f.filename),
|
|
357
|
+
},
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
return null;
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
createFileCountValidator(maxCount) {
|
|
364
|
+
return (control) => {
|
|
365
|
+
const files = control.value;
|
|
366
|
+
if (!Array.isArray(files))
|
|
367
|
+
return null;
|
|
368
|
+
if (files.length > maxCount) {
|
|
369
|
+
return { fileCount: { maxCount, actualCount: files.length } };
|
|
370
|
+
}
|
|
371
|
+
return null;
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: UiFormValidationService, deps: [{ token: i1.UiFormConditionService }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
375
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: UiFormValidationService, providedIn: 'root' }); }
|
|
376
|
+
}
|
|
377
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: UiFormValidationService, decorators: [{
|
|
378
|
+
type: Injectable,
|
|
379
|
+
args: [{ providedIn: 'root' }]
|
|
380
|
+
}], ctorParameters: () => [{ type: i1.UiFormConditionService }] });
|
|
381
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9ybS12YWxpZGF0aW9uLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9uZy11aS1zeXN0ZW0vc3JjL2xpYi9jb21wb25lbnRzL2Zvcm0tYnVpbGRlci9zZXJ2aWNlcy9mb3JtLXZhbGlkYXRpb24uc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzNDLE9BQU8sRUFBZ0MsVUFBVSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDMUUsT0FBTyxFQUNMLEtBQUssRUFDTCxNQUFNLEVBQ04sVUFBVSxFQUNWLFlBQVksRUFDWixPQUFPLEVBQ1AsU0FBUyxFQUNULFFBQVEsRUFDUixRQUFRLEVBQ1IsT0FBTyxFQUNQLFFBQVEsRUFDUixPQUFPLEVBQ1AsT0FBTyxJQUFJLFdBQVcsR0FDdkIsTUFBTSxVQUFVLENBQUM7OztBQU1sQjs7Ozs7Ozs7R0FRRztBQUVILE1BQU0sT0FBTyx1QkFBdUI7SUFDbEMsWUFBb0IsZ0JBQXdDO1FBQXhDLHFCQUFnQixHQUFoQixnQkFBZ0IsQ0FBd0I7SUFBRyxDQUFDO0lBRWhFLGtFQUFrRTtJQUVsRSx1RUFBdUU7SUFDdkUsZ0JBQWdCLENBQUMsS0FBeUI7UUFDeEMsSUFBSSxDQUFDLEtBQUssRUFBRSxNQUFNO1lBQUUsT0FBTyxFQUFFLENBQUM7UUFDOUIsT0FBTyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFvQixFQUFFLENBQUMsQ0FBQyxLQUFLLElBQUksQ0FBQyxDQUFDO0lBQy9GLENBQUM7SUFFRDs7O09BR0c7SUFDSCwyQkFBMkIsQ0FBQyxLQUF5QixFQUFFLFFBQTZCO1FBQ2xGLElBQUksQ0FBQyxLQUFLLEVB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QUMsQ0FBQztZQUNMLENBQUMsQ0FBQyxDQUFDO1lBRUgsSUFBSSxPQUFPLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO2dCQUN2QixPQUFPO29CQUNMLFFBQVEsRUFBRTt3QkFDUixZQUFZO3dCQUNaLEtBQUssRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDO3FCQUN0QztpQkFDRixDQUFDO1lBQ0osQ0FBQztZQUNELE9BQU8sSUFBSSxDQUFDO1FBQ2QsQ0FBQyxDQUFDO0lBQ0osQ0FBQztJQUVPLHdCQUF3QixDQUFDLFFBQWdCO1FBQy9DLE9BQU8sQ0FBQyxPQUF3QixFQUFFLEVBQUU7WUFDbEMsTUFBTSxLQUFLLEdBQWlCLE9BQU8sQ0FBQyxLQUFLLENBQUM7WUFDMUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDO2dCQUFFLE9BQU8sSUFBSSxDQUFDO1lBRXZDLElBQUksS0FBSyxDQUFDLE1BQU0sR0FBRyxRQUFRLEVBQUUsQ0FBQztnQkFDNUIsT0FBTyxFQUFFLFNBQVMsRUFBRSxFQUFFLFFBQVEsRUFBRSxXQUFXLEVBQUUsS0FBSyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUM7WUFDaEUsQ0FBQztZQUNELE9BQU8sSUFBSSxDQUFDO1FBQ2QsQ0FBQyxDQUFDO0lBQ0osQ0FBQzsrR0F2WVUsdUJBQXVCO21IQUF2Qix1QkFBdUIsY0FEVixNQUFNOzs0RkFDbkIsdUJBQXVCO2tCQURuQyxVQUFVO21CQUFDLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgQWJzdHJhY3RDb250cm9sLCBWYWxpZGF0b3JGbiwgVmFsaWRhdG9ycyB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcclxuaW1wb3J0IHtcclxuICBwYXJzZSxcclxuICBmb3JtYXQsXHJcbiAgc3RhcnRPZkRheSxcclxuICBzdGFydE9mTW9udGgsXHJcbiAgYWRkRGF5cyxcclxuICBhZGRNb250aHMsXHJcbiAgYWRkWWVhcnMsXHJcbiAgYWRkV2Vla3MsXHJcbiAgaXNBZnRlcixcclxuICBpc0JlZm9yZSxcclxuICBpc0VxdWFsLFxyXG4gIGlzVmFsaWQgYXMgaXNEYXRlVmFsaWQsXHJcbn0gZnJvbSAnZGF0ZS1mbnMnO1xyXG5pbXBvcnQgeyBVaVZhbGlkYXRpb25SdWxlIH0gZnJvbSAnLi4vdHlwZXMvdmFsaWRhdGlvbi50eXBlcyc7XHJcbmltcG9ydCB7IFVpQ3Jvc3NGaWVsZENvbmZpZywgVWlDcm9zc0ZpZWxkT3BlcmF0b3IgfSBmcm9tICcuLi90eXBlcy92YWxpZGF0aW9uLnR5cGVzJztcclxuaW1wb3J0IHsgVWlGaWxlRGF0YSB9IGZyb20gJy4uL3R5cGVzL2ZpZWxkLnR5cGVzJztcclxuaW1wb3J0IHsgVWlGb3JtQ29uZGl0aW9uU2VydmljZSB9IGZyb20gJy4vZm9ybS1jb25kaXRpb24uc2VydmljZSc7XHJcblxyXG4vKipcclxuICogU2Vydml6aW8gcGVyIGxhIGNyZWF6aW9uZSBlIGdlc3Rpb25lIGRlaSB2YWxpZGF0b3JpIEFuZ3VsYXJcclxuICogYmFzYXRpIHN1bGxlIHJlZ29sZSBkaWNoaWFyYXRpdmUgZGVsbG8gc2NoZW1hIGRlbCBmb3JtLlxyXG4gKlxyXG4gKiBTdXBwb3J0YSB2YWxpZGF6aW9uaSBzdGFuZGFyZCwgY3Jvc3MtZmllbGQsIGRhdGUgY29uIG9mZnNldCxcclxuICogZmlsZSBlIHZhbGlkYXRvcmkgY29uZGl6aW9uYWxpLlxyXG4gKlxyXG4gKiBAcHJvdmlkZWRJbiAncm9vdCdcclxuICovXHJcbkBJbmplY3RhYmxlKHsgcHJvdmlkZWRJbjogJ3Jvb3QnIH0pXHJcbmV4cG9ydCBjbGFzcyBVaUZvcm1WYWxpZGF0aW9uU2VydmljZSB7XHJcbiAgY29uc3RydWN0b3IocHJpdmF0ZSBjb25kaXRpb25TZXJ2aWNlOiBVaUZvcm1Db25kaXRpb25TZXJ2aWNlKSB7fVxyXG5cclxuICAvLyDilIDilIDilIAgQ3JlYXppb25lIHZhbGlkYXRvcmkg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXHJcblxyXG4gIC8qKiBDcmVhIHVuIGFycmF5IGRpIHZhbGlkYXRvcmkgQW5ndWxhciBkYWxsZSByZWdvbGUgZGkgdmFsaWRhemlvbmUuICovXHJcbiAgY3JlYXRlVmFsaWRhdG9ycyhydWxlczogVWlWYWxpZGF0aW9uUnVsZVtdKTogVmFsaWRhdG9yRm5bXSB7XHJcbiAgICBpZiAoIXJ1bGVzPy5sZW5ndGgpIHJldHVybiBbXTtcclxuICAgIHJldHVybiBydWxlcy5tYXAoKHIpID0+IHRoaXMuY3JlYXRlVmFsaWRhdG9yKHIpKS5maWx0ZXIoKHYpOiB2IGlzIFZhbGlkYXRvckZuID0+IHYgIT09IG51bGwpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQ3JlYSB2YWxpZGF0b3JpIGNvbiBzdXBwb3J0byBjb25kaXppb25hbGUuXHJcbiAgICogTGUgcmVnb2xlIGNvbiBgY29uZGl0aW9uc2AgdmVuZ29ubyBhcHBsaWNhdGUgc29sbyBzZSBsZSBjb25kaXppb25pIHNvbm8gc29kZGlzZmF0dGUuXHJcbiAgICovXHJcbiAgY3JlYXRlQ29uZGl0aW9uYWxWYWxpZGF0b3JzKHJ1bGVzOiBVaVZhbGlkYXRpb25SdWxlW10sIGZvcm1EYXRhOiBSZWNvcmQ8c3RyaW5nLCBhbnk+KTogVmFsaWRhdG9yRm5bXSB7XHJcbiAgICBpZiAoIXJ1bGVzPy5sZW5ndGgpIHJldHVybiBbXTtcclxuICAgIGNvbnN0IHZhbGlkYXRvcnM6IFZhbGlkYXRvckZuW10gPSBbXTtcclxuXHJcbiAgICBmb3IgKGNvbnN0IHJ1bGUgb2YgcnVsZXMpIHtcclxuICAgICAgaWYgKHJ1bGUuY29uZGl0aW9ucz8ubGVuZ3RoKSB7XHJcbiAgICAgICAgY29uc3Qgc2hvdWxkQXBwbHkgPSB0aGlzLmNvbmRpdGlvblNlcnZpY2UuZXZhbHVhdGVDb25kaXRpb25zKHJ1bGUuY29uZGl0aW9ucywgZm9ybURhdGEpO1xyXG4gICAgICAgIGlmICghc2hvdWxkQXBwbHkpIGNvbnRpbnVlO1xyXG4gICAgICB9XHJcbiAgICAgIGNvbnN0IHYgPSB0aGlzLmNyZWF0ZVZhbGlkYXRvcihydWxlKTtcclxuICAgICAgaWYgKHYpIHZhbGlkYXRvcnMucHVzaCh2KTtcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gdmFsaWRhdG9ycztcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEFnZ2lvcm5hIGkgdmFsaWRhdG9yaSBkaSB1biBjYW1wbyBpbiBiYXNlIGFsbG8gc3RhdG8gY29ycmVudGUgZGVsIGZvcm0uXHJcbiAgICogVXNhdG8gcGVyIHJpY2FsY29sYXJlIHZhbGlkYXppb25pIGNvbmRpemlvbmFsaSBxdWFuZG8gaSBkYXRpIGNhbWJpYW5vLlxyXG4gICAqL1xyXG4gIHVwZGF0ZUZpZWxkVmFsaWRhdG9ycyhcclxuICAgIGNvbnRyb2w6IEFic3RyYWN0Q29udHJvbCxcclxuICAgIHJ1bGVzOiBVaVZhbGlkYXRpb25SdWxlW10gfCB1bmRlZmluZWQsXHJcbiAgICBmb3JtRGF0YTogUmVjb3JkPHN0cmluZywgYW55PixcclxuICApOiB2b2lkIHtcclxuICAgIGlmICghcnVsZXM/Lmxlbmd0aCkge1xyXG4gICAgICBjb250cm9sLmNsZWFyVmFsaWRhdG9ycygpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgY29uc3QgdmFsaWRhdG9ycyA9IHRoaXMuY3JlYXRlQ29uZGl0aW9uYWxWYWxpZGF0b3JzKHJ1bGVzLCBmb3JtRGF0YSk7XHJcbiAgICAgIGNvbnRyb2wuc2V0VmFsaWRhdG9ycyh2YWxpZGF0b3JzKTtcclxuICAgIH1cclxuICAgIGNvbnRyb2wudXBkYXRlVmFsdWVBbmRWYWxpZGl0eSh7IGVtaXRFdmVudDogZmFsc2UgfSk7XHJcbiAgfVxyXG5cclxuICAvLyDilIDilIDilIAgVXRpbGl0eSBwdWJibGljaGUg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXHJcblxyXG4gIC8qKiBWZXJpZmljYSBzZSB1biBjYW1wbyBkb3ZyZWJiZSBtb3N0cmFyZSBnbGkgZXJyb3JpLiAqL1xyXG4gIHNob3VsZFNob3dGaWVsZEVycm9ycyhjb250cm9sOiBBYnN0cmFjdENvbnRyb2wpOiBib29sZWFuIHtcclxuICAgIHJldHVybiBjb250cm9sLmludmFsaWQgJiYgKGNvbnRyb2wuZGlydHkgfHwgY29udHJvbC50b3VjaGVkKTtcclxuICB9XHJcblxyXG4gIC8qKiBSZXN0aXR1aXNjZSBpIGNhbXBpIGNvcnJlbGF0aSBkYSBjcm9zcy1maWVsZCB2YWxpZGF0aW9uLiAqL1xyXG4gIGdldENyb3NzRmllbGRSZWxhdGVkRmllbGRzKGZpZWxkS2V5OiBzdHJpbmcsIGFsbFJ1bGVzOiBSZWNvcmQ8c3RyaW5nLCBVaVZhbGlkYXRpb25SdWxlW10+KTogc3RyaW5nW10ge1xyXG4gICAgY29uc3QgcmVsYXRlZDogc3RyaW5nW10gPSBbXTtcclxuICAgIGZvciAoY29uc3QgW2tleSwgcnVsZXNdIG9mIE9iamVjdC5lbnRyaWVzKGFsbFJ1bGVzKSkge1xyXG4gICAgICBpZiAoa2V5ID09PSBmaWVsZEtleSkgY29udGludWU7XHJcbiAgICAgIGZvciAoY29uc3QgcnVsZSBvZiBydWxlcykge1xyXG4gICAgICAgIGlmIChydWxlLnR5cGUgPT09ICdjcm9zc0ZpZWxkJyAmJiBydWxlLmNyb3NzRmllbGQ/LnRhcmdldEZpZWxkID09PSBmaWVsZEtleSkge1xyXG4gICAgICAgICAgcmVsYXRlZC5wdXNoKGtleSk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4gcmVsYXRlZDtcclxuICB9XHJcblxyXG4gIC8qKiBWZXJpZmljYSBzZSB1biBjYW1wbyBoYSB2YWxpZGF6aW9uaSBjcm9zcy1maWVsZCBjaGUgbG8gcmVmZXJlbnppYW5vLiAqL1xyXG4gIGhhc0Nyb3NzRmllbGRWYWxpZGF0aW9ucyhmaWVsZEtleTogc3RyaW5nLCBhbGxSdWxlczogUmVjb3JkPHN0cmluZywgVWlWYWxpZGF0aW9uUnVsZVtdPik6IGJvb2xlYW4ge1xyXG4gICAgcmV0dXJuIHRoaXMuZ2V0Q3Jvc3NGaWVsZFJlbGF0ZWRGaWVsZHMoZmllbGRLZXksIGFsbFJ1bGVzKS5sZW5ndGggPiAwO1xyXG4gIH1cclxuXHJcbiAgLyoqIEZvcm1hdHRhIGxhIGRpbWVuc2lvbmUgZGVsIGZpbGUgaW4gdW5hIHN0cmluZ2EgbGVnZ2liaWxlLiAqL1xyXG4gIGZvcm1hdEZpbGVTaXplKGJ5dGVzOiBudW1iZXIpOiBzdHJpbmcge1xyXG4gICAgaWYgKGJ5dGVzID09PSAwKSByZXR1cm4gJzAgQic7XHJcbiAgICBjb25zdCBrID0gMTAyNDtcclxuICAgIGNvbnN0IHNpemVzID0gWydCJywgJ0tCJywgJ01CJywgJ0dCJ107XHJcbiAgICBjb25zdCBpID0gTWF0aC5mbG9vcihNYXRoLmxvZyhieXRlcykgLyBNYXRoLmxvZyhrKSk7XHJcbiAgICByZXR1cm4gcGFyc2VGbG9hdCgoYnl0ZXMgLyBNYXRoLnBvdyhrLCBpKSkudG9GaXhlZCgyKSkgKyAnICcgKyBzaXplc1tpXTtcclxuICB9XHJcblxyXG4gIC8vIOKUgOKUgOKUgCBGYWN0b3J5IHZhbGlkYXRvcmkg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXHJcblxyXG4gIHByaXZhdGUgY3JlYXRlVmFsaWRhdG9yKHJ1bGU6IFVpVmFsaWRhdGlvblJ1bGUpOiBWYWxpZGF0b3JGbiB8IG51bGwge1xyXG4gICAgc3dpdGNoIChydWxlLnR5cGUpIHtcclxuICAgICAgY2FzZSAncmVxdWlyZWQnOlxyXG4gICAgICAgIHJldHVybiBWYWxpZGF0b3JzLnJlcXVpcmVkO1xyXG4gICAgICBjYXNlICdlbWFpbCc6XHJcbiAgICAgICAgcmV0dXJuIFZhbGlkYXRvcnMuZW1haWw7XHJcbiAgICAgIGNhc2UgJ21pbic6XHJcbiAgICAgICAgcmV0dXJuIFZhbGlkYXRvcnMubWluKHJ1bGUudmFsdWUpO1xyXG4gICAgICBjYXNlICdtYXgnOlxyXG4gICAgICAgIHJldHVybiBWYWxpZGF0b3JzLm1heChydWxlLnZhbHVlKTtcclxuICAgICAgY2FzZSAnbWluTGVuZ3RoJzpcclxuICAgICAgICByZXR1cm4gVmFsaWRhdG9ycy5taW5MZW5ndGgocnVsZS52YWx1ZSk7XHJcbiAgICAgIGNhc2UgJ21heExlbmd0aCc6XHJcbiAgICAgICAgcmV0dXJuIFZhbGlkYXRvcnMubWF4TGVuZ3RoKHJ1bGUudmFsdWUpO1xyXG4gICAgICBjYXNlICdwYXR0ZXJuJzpcclxuICAgICAgICByZXR1cm4gVmFsaWRhdG9ycy5wYXR0ZXJuKHJ1bGUudmFsdWUpO1xyXG4gICAgICBjYXNlICdjdXN0b20nOlxyXG4gICAgICAgIHJldHVybiBydWxlLnZhbGlkYXRvciB8fCBudWxsO1xyXG4gICAgICBjYXNlICdjcm9zc0ZpZWxkJzpcclxuICAgICAgICByZXR1cm4gcnVsZS5jcm9zc0ZpZWxkID8gdGhpcy5jcmVhdGVDcm9zc0ZpZWxkVmFsaWRhdG9yKHJ1bGUuY3Jvc3NGaWVsZCkgOiBudWxsO1xyXG4gICAgICBjYXNlICdkYXRlLW1pbic6XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuY3JlYXRlRGF0ZU1pblZhbGlkYXRvcihydWxlLnZhbHVlLCBydWxlLm9mZnNldCk7XHJcbiAgICAgIGNhc2UgJ2RhdGUtbWF4JzpcclxuICAgICAgICByZXR1cm4gdGhpcy5jcmVhdGVEYXRlTWF4VmFsaWRhdG9yKHJ1bGUudmFsdWUsIHJ1bGUub2Zmc2V0KTtcclxuICAgICAgY2FzZSAnZmlsZVNpemUnOlxyXG4gICAgICAgIHJldHVybiB0aGlzLmNyZWF0ZUZpbGVTaXplVmFsaWRhdG9yKHJ1bGUudmFsdWUpO1xyXG4gICAgICBjYXNlICdmaWxlVHlwZSc6XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuY3JlYXRlRmlsZVR5cGVWYWxpZGF0b3IocnVsZS52YWx1ZSk7XHJcbiAgICAgIGNhc2UgJ2ZpbGVDb3VudCc6XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuY3JlYXRlRmlsZUNvdW50VmFsaWRhdG9yKHJ1bGUudmFsdWUpO1xyXG4gICAgICBkZWZhdWx0OlxyXG4gICAgICAgIHJldHVybiBudWxsO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLy8g4pSA4pSA4pSAIENyb3NzLWZpZWxkIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxyXG5cclxuICBwcml2YXRlIGNyZWF0ZUNyb3NzRmllbGRWYWxpZGF0b3IoY29uZmlnOiBVaUNyb3NzRmllbGRDb25maWcpOiBWYWxpZGF0b3JGbiB7XHJcbiAgICByZXR1cm4gKGNvbnRyb2w6IEFic3RyYWN0Q29udHJvbCkgPT4ge1xyXG4gICAgICBpZiAoIWNvbnRyb2wucGFyZW50IHx8ICFjb25maWcudGFyZ2V0RmllbGQpIHJldHVybiBudWxsO1xyXG5cclxuICAgICAgY29uc3QgdGFyZ2V0Q29udHJvbCA9IGNvbnRyb2wucGFyZW50LmdldChjb25maWcudGFyZ2V0RmllbGQpO1xyXG4gICAgICBpZiAoIXRhcmdldENvbnRyb2wpIHJldHVybiBudWxsO1xyXG5cclxuICAgICAgY29uc3Qgc291cmNlVmFsdWUgPSBjb250cm9sLnZhbHVlO1xyXG4gICAgICBjb25zdCB0YXJnZXRWYWx1ZSA9IHRhcmdldENvbnRyb2wudmFsdWU7XHJcblxyXG4gICAgICBpZiAoc291cmNlVmFsdWUgPT0gbnVsbCB8fCB0YXJnZXRWYWx1ZSA9PSBudWxsIHx8IHNvdXJjZVZhbHVlID09PSAnJyB8fCB0YXJnZXRWYWx1ZSA9PT0gJycpIHtcclxuICAgICAgICByZXR1cm4gbnVsbDtcclxuICAgICAgfVxyXG5cclxuICAgICAgbGV0IGlzVmFsaWQgPSBmYWxzZTtcclxuICAgICAgaWYgKGNvbmZpZy5kYXRhVHlwZSA9PT0gJ2RhdGUnKSB7XHJcbiAgICAgICAgaXNWYWxpZCA9IHRoaXMudmFsaWRhdGVEYXRlQ29tcGFyaXNvbihzb3VyY2VWYWx1ZSwgdGFyZ2V0VmFsdWUsIGNvbmZpZy5vcGVyYXRvciwgY29uZmlnLmlzTW9udGhZZWFyKTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICBpc1ZhbGlkID0gdGhpcy52YWxpZGF0ZU51bWJlckNvbXBhcmlzb24oc291cmNlVmFsdWUsIHRhcmdldFZhbHVlLCBjb25maWcub3BlcmF0b3IpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICByZXR1cm4gaXNWYWxpZFxyXG4gICAgICAgID8gbnVsbFxyXG4gICAgICAgIDoge1xyXG4gICAgICAgICAgICBjcm9zc0ZpZWxkOiB7XHJcbiAgICAgICAgICAgICAgYWN0dWFsVmFsdWU6IHNvdXJjZVZhbHVlLFxyXG4gICAgICAgICAgICAgIHJlcXVpcmVkQ29tcGFyaXNvbjogY29uZmlnLm9wZXJhdG9yLFxyXG4gICAgICAgICAgICAgIGNvbXBhcmVkVmFsdWU6IHRhcmdldFZhbHVlLFxyXG4gICAgICAgICAgICAgIHRhcmdldEZpZWxkOiBjb25maWcudGFyZ2V0RmllbGQsXHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICB9O1xyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIC8qKiBDb25mcm9udG8gZGF0ZSBjb24gZGF0ZS1mbnMuICovXHJcbiAgcHJpdmF0ZSB2YWxpZGF0ZURhdGVDb21wYXJpc29uKFxyXG4gICAgc291cmNlVmFsdWU6IGFueSxcclxuICAgIHRhcmdldFZhbHVlOiBhbnksXHJcbiAgICBvcGVyYXRvcjogVWlDcm9zc0ZpZWxkT3BlcmF0b3IsXHJcbiAgICBpc01vbnRoWWVhcj86IGJvb2xlYW4sXHJcbiAgKTogYm9vbGVhbiB7XHJcbiAgICBjb25zdCBub3JtYWxpemUgPSBpc01vbnRoWWVhciA/IHN0YXJ0T2ZNb250aCA6IHN0YXJ0T2ZEYXk7XHJcbiAgICBjb25zdCBzb3VyY2VEYXRlID0gbm9ybWFsaXplKG5ldyBEYXRlKHNvdXJjZVZhbHVlKSk7XHJcbiAgICBjb25zdCB0YXJnZXREYXRlID0gbm9ybWFsaXplKG5ldyBEYXRlKHRhcmdldFZhbHVlKSk7XHJcblxyXG4gICAgaWYgKCFpc0RhdGVWYWxpZChzb3VyY2VEYXRlKSB8fCAhaXNEYXRlVmFsaWQodGFyZ2V0RGF0ZSkpIHJldHVybiBmYWxzZTtcclxuXHJcbiAgICBzd2l0Y2ggKG9wZXJhdG9yKSB7XHJcbiAgICAgIGNhc2UgJ2dyZWF0ZXJfdGhhbic6XHJcbiAgICAgICAgcmV0dXJuIGlzQWZ0ZXIoc291cmNlRGF0ZSwgdGFyZ2V0RGF0ZSk7XHJcbiAgICAgIGNhc2UgJ2dyZWF0ZXJfZXF1YWwnOlxyXG4gICAgICAgIHJldHVybiBpc0FmdGVyKHNvdXJjZURhdGUsIHRhcmdldERhdGUpIHx8IGlzRXF1YWwoc291cmNlRGF0ZSwgdGFyZ2V0RGF0ZSk7XHJcbiAgICAgIGNhc2UgJ2xlc3NfdGhhbic6XHJcbiAgICAgICAgcmV0dXJuIGlzQmVmb3JlKHNvdXJjZURhdGUsIHRhcmdldERhdGUpO1xyXG4gICAgICBjYXNlICdsZXNzX2VxdWFsJzpcclxuICAgICAgICByZXR1cm4gaXNCZWZvcmUoc291cmNlRGF0ZSwgdGFyZ2V0RGF0ZSkgfHwgaXNFcXVhbChzb3VyY2VEYXRlLCB0YXJnZXREYXRlKTtcclxuICAgICAgY2FzZSAnbm90X2VxdWFsJzpcclxuICAgICAgICByZXR1cm4gIWlzRXF1YWwoc291cmNlRGF0ZSwgdGFyZ2V0RGF0ZSk7XHJcbiAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqIENvbmZyb250byBudW1lcmljby4gKi9cclxuICBwcml2YXRlIHZhbGlkYXRlTnVtYmVyQ29tcGFyaXNvbihzb3VyY2VWYWx1ZTogYW55LCB0YXJnZXRWYWx1ZTogYW55LCBvcGVyYXRvcjogVWlDcm9zc0ZpZWxkT3BlcmF0b3IpOiBib29sZWFuIHtcclxuICAgIGNvbnN0IHNyYyA9IE51bWJlcihzb3VyY2VWYWx1ZSk7XHJcbiAgICBjb25zdCB0Z3QgPSBOdW1iZXIodGFyZ2V0VmFsdWUpO1xyXG4gICAgaWYgKGlzTmFOKHNyYykgfHwgaXNOYU4odGd0KSkgcmV0dXJuIGZhbHNlO1xyXG5cclxuICAgIHN3aXRjaCAob3BlcmF0b3IpIHtcclxuICAgICAgY2FzZSAnZ3JlYXRlcl90aGFuJzpcclxuICAgICAgICByZXR1cm4gc3JjID4gdGd0O1xyXG4gICAgICBjYXNlICdncmVhdGVyX2VxdWFsJzpcclxuICAgICAgICByZXR1cm4gc3JjID49IHRndDtcclxuICAgICAgY2FzZSAnbGVzc190aGFuJzpcclxuICAgICAgICByZXR1cm4gc3JjIDwgdGd0O1xyXG4gICAgICBjYXNlICdsZXNzX2VxdWFsJzpcclxuICAgICAgICByZXR1cm4gc3JjIDw9IHRndDtcclxuICAgICAgY2FzZSAnbm90X2VxdWFsJzpcclxuICAgICAgICByZXR1cm4gc3JjICE9PSB0Z3Q7XHJcbiAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLy8g4pSA4pSA4pSAIERhdGUgbWluL21heCAoY29uIGtleXdvcmQgZSBvZmZzZXQpIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxyXG5cclxuICBwcml2YXRlIGNyZWF0ZURhdGVNaW5WYWxpZGF0b3IodmFsdWU6IHN0cmluZywgb2Zmc2V0Pzogc3RyaW5nKTogVmFsaWRhdG9yRm4ge1xyXG4gICAgcmV0dXJuIChjb250cm9sOiBBYnN0cmFjdENvbnRyb2wpID0+IHtcclxuICAgICAgaWYgKCFjb250cm9sLnZhbHVlKSByZXR1cm4gbnVsbDtcclxuXHJcbiAgICAgIGNvbnN0IHJlZkRhdGUgPSB0aGlzLnBhcnNlUmVmZXJlbmNlRGF0ZSh2YWx1ZSwgb2Zmc2V0KTtcclxuICAgICAgaWYgKCFyZWZEYXRlKSByZXR1cm4gbnVsbDtcclxuXHJcbiAgICAgIGNvbnN0IGlucHV0RGF0ZSA9IHN0YXJ0T2ZEYXkobmV3IERhdGUoY29udHJvbC52YWx1ZSkpO1xyXG4gICAgICBpZiAoIWlzRGF0ZVZhbGlkKGlucHV0RGF0ZSkpIHtcclxuICAgICAgICByZXR1cm4geyAnZGF0ZS1taW4nOiB7IG1lc3NhZ2U6ICdEYXRhIG5vbiB2YWxpZGEnLCByZWZlcmVuY2VEYXRlOiB0aGlzLmZvcm1hdFJlZkRhdGUocmVmRGF0ZSkgfSB9O1xyXG4gICAgICB9XHJcblxyXG4gICAgICBpZiAoaXNCZWZvcmUoaW5wdXREYXRlLCByZWZEYXRlKSkge1xyXG4gICAgICAgIHJldHVybiB7XHJcbiAgICAgICAgICAnZGF0ZS1taW4nOiB7XHJcbiAgICAgICAgICAgIG1lc3NhZ2U6IGBMYSBkYXRhIGRldmUgZXNzZXJlIHN1Y2Nlc3NpdmEgbyB1Z3VhbGUgYSAke3RoaXMuZm9ybWF0UmVmRGF0ZShyZWZEYXRlKX1gLFxyXG4gICAgICAgICAgICByZWZlcmVuY2VEYXRlOiB0aGlzLmZvcm1hdFJlZkRhdGUocmVmRGF0ZSksXHJcbiAgICAgICAgICAgIGlucHV0RGF0ZTogZm9ybWF0KGlucHV0RGF0ZSwgJ2RkL01NL3l5eXknKSxcclxuICAgICAgICAgIH0sXHJcbiAgICAgICAgfTtcclxuICAgICAgfVxyXG4gICAgICByZXR1cm4gbnVsbDtcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGNyZWF0ZURhdGVNYXhWYWxpZGF0b3IodmFsdWU6IHN0cmluZywgb2Zmc2V0Pzogc3RyaW5nKTogVmFsaWRhdG9yRm4ge1xyXG4gICAgcmV0dXJuIChjb250cm9sOiBBYnN0cmFjdENvbnRyb2wpID0+IHtcclxuICAgICAgaWYgKCFjb250cm9sLnZhbHVlKSByZXR1cm4gbnVsbDtcclxuXHJcbiAgICAgIGNvbnN0IHJlZkRhdGUgPSB0aGlzLnBhcnNlUmVmZXJlbmNlRGF0ZSh2YWx1ZSwgb2Zmc2V0KTtcclxuICAgICAgaWYgKCFyZWZEYXRlKSByZXR1cm4gbnVsbDtcclxuXHJcbiAgICAgIGNvbnN0IGlucHV0RGF0ZSA9IHN0YXJ0T2ZEYXkobmV3IERhdGUoY29udHJvbC52YWx1ZSkpO1xyXG4gICAgICBpZiAoIWlzRGF0ZVZhbGlkKGlucHV0RGF0ZSkpIHtcclxuICAgICAgICByZXR1cm4geyAnZGF0ZS1tYXgnOiB7IG1lc3NhZ2U6ICdEYXRhIG5vbiB2YWxpZGEnLCByZWZlcmVuY2VEYXRlOiB0aGlzLmZvcm1hdFJlZkRhdGUocmVmRGF0ZSkgfSB9O1xyXG4gICAgICB9XHJcblxyXG4gICAgICBpZiAoaXNBZnRlcihpbnB1dERhdGUsIHJlZkRhdGUpKSB7XHJcbiAgICAgICAgcmV0dXJuIHtcclxuICAgICAgICAgICdkYXRlLW1heCc6IHtcclxuICAgICAgICAgICAgbWVzc2FnZTogYExhIGRhdGEgZGV2ZSBlc3NlcmUgcHJlY2VkZW50ZSBvIHVndWFsZSBhICR7dGhpcy5mb3JtYXRSZWZEYXRlKHJlZkRhdGUpfWAsXHJcbiAgICAgICAgICAgIHJlZmVyZW5jZURhdGU6IHRoaXMuZm9ybWF0UmVmRGF0ZShyZWZEYXRlKSxcclxuICAgICAgICAgICAgaW5wdXREYXRlOiBmb3JtYXQoaW5wdXREYXRlLCAnZGQvTU0veXl5eScpLFxyXG4gICAgICAgICAgfSxcclxuICAgICAgICB9O1xyXG4gICAgICB9XHJcbiAgICAgIHJldHVybiBudWxsO1xyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFBhcnNhIHVuYSBkYXRhIGRpIHJpZmVyaW1lbnRvIGRhIGtleXdvcmQgbyBzdHJpbmdhIEREL01NL1lZWVlcclxuICAgKiBlIGFwcGxpY2EgdW4gZXZlbnR1YWxlIG9mZnNldCB0ZW1wb3JhbGUuXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBwYXJzZVJlZmVyZW5jZURhdGUodmFsdWU6IHN0cmluZywgb2Zmc2V0Pzogc3RyaW5nKTogRGF0ZSB8IG51bGwge1xyXG4gICAgY29uc3QgdG9kYXkgPSBzdGFydE9mRGF5KG5ldyBEYXRlKCkpO1xyXG4gICAgbGV0IGRhdGU6IERhdGU7XHJcblxyXG4gICAgc3dpdGNoICh2YWx1ZT8udG9Mb3dlckNhc2UoKS50cmltKCkpIHtcclxuICAgICAgY2FzZSAndG9kYXknOlxyXG4gICAgICBjYXNlICdvZ2dpJzpcclxuICAgICAgICBkYXRlID0gdG9kYXk7XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICAgIGNhc2UgJ3RvbW9ycm93JzpcclxuICAgICAgY2FzZSAnZG9tYW5pJzpcclxuICAgICAgICBkYXRlID0gYWRkRGF5cyh0b2RheSwgMSk7XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICAgIGNhc2UgJ3llc3RlcmRheSc6XHJcbiAgICAgIGNhc2UgJ2llcmknOlxyXG4gICAgICAgIGRhdGUgPSBhZGREYXlzKHRvZGF5LCAtMSk7XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICAgIGRlZmF1bHQ6IHtcclxuICAgICAgICAvLyBQcm92YSBERC9NTS9ZWVlZXHJcbiAgICAgICAgY29uc3QgcGFyc2VkID0gcGFyc2UodmFsdWUsICdkZC9NTS95eXl5JywgbmV3IERhdGUoKSk7XHJcbiAgICAgICAgaWYgKGlzRGF0ZVZhbGlkKHBhcnNlZCkpIHtcclxuICAgICAgICAgIGRhdGUgPSBzdGFydE9mRGF5KHBhcnNlZCk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIC8vIFByb3ZhIFlZWVktTU0tREQgKElTTylcclxuICAgICAgICAgIGNvbnN0IGlzb0RhdGUgPSBuZXcgRGF0ZSh2YWx1ZSk7XHJcbiAgICAgICAgICBpZiAoaXNEYXRlVmFsaWQoaXNvRGF0ZSkpIHtcclxuICAgICAgICAgICAgZGF0ZSA9IHN0YXJ0T2ZEYXkoaXNvRGF0ZSk7XHJcbiAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gb2Zmc2V0ID8gdGhpcy5hcHBseURhdGVPZmZzZXQoZGF0ZSwgb2Zmc2V0KSA6IGRhdGU7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBBcHBsaWNhIHVuIG9mZnNldCB0ZW1wb3JhbGUgYSB1bmEgZGF0YS5cclxuICAgKlxyXG4gICAqIEZvcm1hdG86IGBudW1lcm8gKyB1bml0YWBcclxuICAgKiAtIGB5YC9gYWAgPSBhbm5pLCBgbWAgPSBtZXNpLCBgZ2AvYGRgID0gZ2lvcm5pLCBgc2AvYHdgID0gc2V0dGltYW5lXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBhcHBseURhdGVPZmZzZXQoZGF0ZTogRGF0ZSwgb2Zmc2V0OiBzdHJpbmcpOiBEYXRlIHtcclxuICAgIGNvbnN0IG1hdGNoID0gb2Zmc2V0Lm1hdGNoKC9eKC0/XFxkKykoW3lZYUFtTWdHZERzU3dXXSkkLyk7XHJcbiAgICBpZiAoIW1hdGNoKSByZXR1cm4gZGF0ZTtcclxuXHJcbiAgICBjb25zdCBhbW91bnQgPSBwYXJzZUludChtYXRjaFsxXSwgMTApO1xyXG4gICAgc3dpdGNoIChtYXRjaFsyXS50b0xvd2VyQ2FzZSgpKSB7XHJcbiAgICAgIGNhc2UgJ3knOlxyXG4gICAgICBjYXNlICdhJzpcclxuICAgICAgICByZXR1cm4gYWRkWWVhcnMoZGF0ZSwgYW1vdW50KTtcclxuICAgICAgY2FzZSAnbSc6XHJcbiAgICAgICAgcmV0dXJuIGFkZE1vbnRocyhkYXRlLCBhbW91bnQpO1xyXG4gICAgICBjYXNlICdnJzpcclxuICAgICAgY2FzZSAnZCc6XHJcbiAgICAgICAgcmV0dXJuIGFkZERheXMoZGF0ZSwgYW1vdW50KTtcclxuICAgICAgY2FzZSAncyc6XHJcbiAgICAgIGNhc2UgJ3cnOlxyXG4gICAgICAgIHJldHVybiBhZGRXZWVrcyhkYXRlLCBhbW91bnQpO1xyXG4gICAgICBkZWZhdWx0OlxyXG4gICAgICAgIHJldHVybiBkYXRlO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBmb3JtYXRSZWZEYXRlKGRhdGU6IERhdGUpOiBzdHJpbmcge1xyXG4gICAgcmV0dXJuIGZvcm1hdChkYXRlLCAnZGQvTU0veXl5eScpO1xyXG4gIH1cclxuXHJcbiAgLy8g4pSA4pSA4pSAIEZpbGUgdmFsaWRhdG9ycyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcclxuXHJcbiAgcHJpdmF0ZSBjcmVhdGVGaWxlU2l6ZVZhbGlkYXRvcihtYXhTaXplOiBudW1iZXIpOiBWYWxpZGF0b3JGbiB7XHJcbiAgICByZXR1cm4gKGNvbnRyb2w6IEFic3RyYWN0Q29udHJvbCkgPT4ge1xyXG4gICAgICBjb25zdCBmaWxlczogVWlGaWxlRGF0YVtdID0gY29udHJvbC52YWx1ZTtcclxuICAgICAgaWYgKCFBcnJheS5pc0FycmF5KGZpbGVzKSB8fCBmaWxlcy5sZW5ndGggPT09IDApIHJldHVybiBudWxsO1xyXG5cclxuICAgICAgY29uc3Qgb3ZlcnNpemVkID0gZmlsZXMuZmlsdGVyKChmKSA9PiBmLnNpemUgPiBtYXhTaXplKTtcclxuICAgICAgaWYgKG92ZXJzaXplZC5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgcmV0dXJuIHtcclxuICAgICAgICAgIGZpbGVTaXplOiB7XHJcbiAgICAgICAgICAgIG1heFNpemUsXHJcbiAgICAgICAgICAgIG1heFNpemVGb3JtYXR0ZWQ6IHRoaXMuZm9ybWF0RmlsZVNpemUobWF4U2l6ZSksXHJcbiAgICAgICAgICAgIGZpbGVzOiBvdmVyc2l6ZWQubWFwKChmKSA9PiBmLmZpbGVuYW1lKSxcclxuICAgICAgICAgIH0sXHJcbiAgICAgICAgfTtcclxuICAgICAgfVxyXG4gICAgICByZXR1cm4gbnVsbDtcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGNyZWF0ZUZpbGVUeXBlVmFsaWRhdG9yKGFsbG93ZWRUeXBlczogc3RyaW5nW10pOiBWYWxpZGF0b3JGbiB7XHJcbiAgICByZXR1cm4gKGNvbnRyb2w6IEFic3RyYWN0Q29udHJvbCkgPT4ge1xyXG4gICAgICBjb25zdCBmaWxlczogVWlGaWxlRGF0YVtdID0gY29udHJvbC52YWx1ZTtcclxuICAgICAgaWYgKCFBcnJheS5pc0FycmF5KGZpbGVzKSB8fCBmaWxlcy5sZW5ndGggPT09IDApIHJldHVybiBudWxsO1xyXG5cclxuICAgICAgY29uc3QgaW52YWxpZCA9IGZpbGVzLmZpbHRlcigoZikgPT4ge1xyXG4gICAgICAgIHJldHVybiAhYWxsb3dlZFR5cGVzLnNvbWUoKHR5cGUpID0+IHtcclxuICAgICAgICAgIGlmICh0eXBlLmVuZHNXaXRoKCcvKicpKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IGNhdGVnb3J5ID0gdHlwZS5zcGxpdCgnLycpWzBdO1xyXG4gICAgICAgICAgICByZXR1cm4gZi5taW1lVHlwZS5zdGFydHNXaXRoKGNhdGVnb3J5ICsgJy8nKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIHJldHVybiBmLm1pbWVUeXBlID09PSB0eXBlO1xyXG4gICAgICAgIH0pO1xyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIGlmIChpbnZhbGlkLmxlbmd0aCA+IDApIHtcclxuICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgZmlsZVR5cGU6IHtcclxuICAgICAgICAgICAgYWxsb3dlZFR5cGVzLFxyXG4gICAgICAgICAgICBmaWxlczogaW52YWxpZC5tYXAoKGYpID0+IGYuZmlsZW5hbWUpLFxyXG4gICAgICAgICAgfSxcclxuICAgICAgICB9O1xyXG4gICAgICB9XHJcbiAgICAgIHJldHVybiBudWxsO1xyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgY3JlYXRlRmlsZUNvdW50VmFsaWRhdG9yKG1heENvdW50OiBudW1iZXIpOiBWYWxpZGF0b3JGbiB7XHJcbiAgICByZXR1cm4gKGNvbnRyb2w6IEFic3RyYWN0Q29udHJvbCkgPT4ge1xyXG4gICAgICBjb25zdCBmaWxlczogVWlGaWxlRGF0YVtdID0gY29udHJvbC52YWx1ZTtcclxuICAgICAgaWYgKCFBcnJheS5pc0FycmF5KGZpbGVzKSkgcmV0dXJuIG51bGw7XHJcblxyXG4gICAgICBpZiAoZmlsZXMubGVuZ3RoID4gbWF4Q291bnQpIHtcclxuICAgICAgICByZXR1cm4geyBmaWxlQ291bnQ6IHsgbWF4Q291bnQsIGFjdHVhbENvdW50OiBmaWxlcy5sZW5ndGggfSB9O1xyXG4gICAgICB9XHJcbiAgICAgIHJldHVybiBudWxsO1xyXG4gICAgfTtcclxuICB9XHJcbn1cclxuIl19
|