@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,730 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module ng-ui-system/form-builder-editor
|
|
3
|
+
* Componente principale dell'editor visuale del form builder.
|
|
4
|
+
*
|
|
5
|
+
* Layout a tre pannelli:
|
|
6
|
+
* - Sinistra: palette dei tipi di campo (drag source)
|
|
7
|
+
* - Centro: sezioni con campi (drop target + editor inline)
|
|
8
|
+
* - Destra: pannello di configurazione del campo selezionato
|
|
9
|
+
*
|
|
10
|
+
* Funzionalita principali:
|
|
11
|
+
* - Drag & drop dei campi dalla palette alle sezioni
|
|
12
|
+
* - Riordino campi all'interno e tra sezioni
|
|
13
|
+
* - Configurazione campi in tempo reale
|
|
14
|
+
* - Preview live del form
|
|
15
|
+
* - Import/export JSON
|
|
16
|
+
* - Auto-save su localStorage
|
|
17
|
+
*/
|
|
18
|
+
import { Component, ChangeDetectionStrategy, ChangeDetectorRef, inject, Optional, Inject, } from '@angular/core';
|
|
19
|
+
import { DragDropModule } from '@angular/cdk/drag-drop';
|
|
20
|
+
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
|
|
21
|
+
import { MatSnackBar, MatSnackBarModule } from '@angular/material/snack-bar';
|
|
22
|
+
import { MatTabsModule } from '@angular/material/tabs';
|
|
23
|
+
import { LucideAngularModule } from 'lucide-angular';
|
|
24
|
+
import { Subject, interval } from 'rxjs';
|
|
25
|
+
import { takeUntil } from 'rxjs/operators';
|
|
26
|
+
import { UiEditorStateService } from './services/editor-state.service';
|
|
27
|
+
import { UiEditorPersistenceService } from './services/editor-persistence.service';
|
|
28
|
+
import { UiEditorFieldFactoryService } from './services/field-factory.service';
|
|
29
|
+
// Sotto-componenti
|
|
30
|
+
import { UiEditorToolbarComponent } from './sub-components/editor-toolbar/editor-toolbar.component';
|
|
31
|
+
import { UiFieldPaletteComponent } from './sub-components/field-palette/field-palette.component';
|
|
32
|
+
import { UiSectionEditorComponent } from './sub-components/section-editor/section-editor.component';
|
|
33
|
+
import { UiEditorFieldConfigPanelComponent } from './sub-components/field-config-panel/field-config-panel.component';
|
|
34
|
+
import { UiEditorPreviewContainerComponent } from './sub-components/preview-container/preview-container.component';
|
|
35
|
+
import { UiButtonComponent } from '../button/index';
|
|
36
|
+
import * as i0 from "@angular/core";
|
|
37
|
+
import * as i1 from "@angular/material/dialog";
|
|
38
|
+
import * as i2 from "@angular/cdk/drag-drop";
|
|
39
|
+
import * as i3 from "@angular/material/tabs";
|
|
40
|
+
import * as i4 from "lucide-angular";
|
|
41
|
+
export class UiFormBuilderEditorComponent {
|
|
42
|
+
constructor(dialogRef, dialogData) {
|
|
43
|
+
this.dialogRef = dialogRef;
|
|
44
|
+
this.dialogData = dialogData;
|
|
45
|
+
/** @internal Servizio per lo stato dell'editor. */
|
|
46
|
+
this.stateService = inject(UiEditorStateService);
|
|
47
|
+
/** @internal Servizio per la persistenza. */
|
|
48
|
+
this.persistenceService = inject(UiEditorPersistenceService);
|
|
49
|
+
/** @internal Factory per i campi. */
|
|
50
|
+
this.fieldFactory = inject(UiEditorFieldFactoryService);
|
|
51
|
+
/** @internal Snack bar per i messaggi. */
|
|
52
|
+
this.snackBar = inject(MatSnackBar);
|
|
53
|
+
/** @internal Change detector. */
|
|
54
|
+
this.cdr = inject(ChangeDetectorRef);
|
|
55
|
+
/** @internal Subject per la distruzione. */
|
|
56
|
+
this.destroy$ = new Subject();
|
|
57
|
+
/** Indice del tab selezionato (0=Editor, 1=Preview). */
|
|
58
|
+
this.selectedTabIndex = 0;
|
|
59
|
+
/** Breadcrumb di navigazione. */
|
|
60
|
+
this.breadcrumb = [];
|
|
61
|
+
/** Se il componente e aperto in modalita dialog. */
|
|
62
|
+
this.isDialogMode = false;
|
|
63
|
+
/** Chiave per forzare il re-render del preview. */
|
|
64
|
+
this.previewKey = 0;
|
|
65
|
+
/** Campi disponibili per le condizioni (cache). */
|
|
66
|
+
this.availableFields = [];
|
|
67
|
+
/** Larghezza della sidebar sinistra (px). */
|
|
68
|
+
this.leftSidebarWidth = 280;
|
|
69
|
+
/** Larghezza della sidebar destra (px). */
|
|
70
|
+
this.rightSidebarWidth = 460;
|
|
71
|
+
/** Se e in corso il resize della sidebar destra. */
|
|
72
|
+
this.isResizing = false;
|
|
73
|
+
/** Se e in corso il resize della sidebar sinistra. */
|
|
74
|
+
this.isResizingLeft = false;
|
|
75
|
+
/** @internal Limiti di resize sidebar destra. */
|
|
76
|
+
this.MIN_SIDEBAR_WIDTH = 400;
|
|
77
|
+
this.MAX_SIDEBAR_WIDTH = 1200;
|
|
78
|
+
/** @internal Limiti di resize sidebar sinistra. */
|
|
79
|
+
this.MIN_LEFT_SIDEBAR_WIDTH = 200;
|
|
80
|
+
this.MAX_LEFT_SIDEBAR_WIDTH = 500;
|
|
81
|
+
this.resizeStartX = 0;
|
|
82
|
+
this.resizeStartWidth = 0;
|
|
83
|
+
this.SIDEBAR_WIDTH_KEY = 'ui-editor-right-sidebar-width';
|
|
84
|
+
this.LEFT_SIDEBAR_WIDTH_KEY = 'ui-editor-left-sidebar-width';
|
|
85
|
+
this.onResizeMove = (event) => {
|
|
86
|
+
if (!this.isResizing)
|
|
87
|
+
return;
|
|
88
|
+
const delta = this.resizeStartX - event.clientX;
|
|
89
|
+
this.rightSidebarWidth = Math.max(this.MIN_SIDEBAR_WIDTH, Math.min(this.MAX_SIDEBAR_WIDTH, this.resizeStartWidth + delta));
|
|
90
|
+
this.cdr.markForCheck();
|
|
91
|
+
};
|
|
92
|
+
this.onResizeEnd = () => {
|
|
93
|
+
if (!this.isResizing)
|
|
94
|
+
return;
|
|
95
|
+
this.isResizing = false;
|
|
96
|
+
document.removeEventListener('mousemove', this.onResizeMove);
|
|
97
|
+
document.removeEventListener('mouseup', this.onResizeEnd);
|
|
98
|
+
document.body.style.cursor = '';
|
|
99
|
+
document.body.style.userSelect = '';
|
|
100
|
+
this.saveSidebarWidth();
|
|
101
|
+
};
|
|
102
|
+
this.onLeftResizeMove = (event) => {
|
|
103
|
+
if (!this.isResizingLeft)
|
|
104
|
+
return;
|
|
105
|
+
const delta = event.clientX - this.resizeStartX;
|
|
106
|
+
this.leftSidebarWidth = Math.max(this.MIN_LEFT_SIDEBAR_WIDTH, Math.min(this.MAX_LEFT_SIDEBAR_WIDTH, this.resizeStartWidth + delta));
|
|
107
|
+
this.cdr.markForCheck();
|
|
108
|
+
};
|
|
109
|
+
this.onLeftResizeEnd = () => {
|
|
110
|
+
if (!this.isResizingLeft)
|
|
111
|
+
return;
|
|
112
|
+
this.isResizingLeft = false;
|
|
113
|
+
document.removeEventListener('mousemove', this.onLeftResizeMove);
|
|
114
|
+
document.removeEventListener('mouseup', this.onLeftResizeEnd);
|
|
115
|
+
document.body.style.cursor = '';
|
|
116
|
+
document.body.style.userSelect = '';
|
|
117
|
+
this.saveLeftSidebarWidth();
|
|
118
|
+
};
|
|
119
|
+
this.state = this.stateService.getCurrentState();
|
|
120
|
+
this.isDialogMode = !!this.dialogRef;
|
|
121
|
+
// Carica schema iniziale se fornito via dialog data
|
|
122
|
+
if (this.dialogData?.initialSchema) {
|
|
123
|
+
this.stateService.setSchema(this.dialogData.initialSchema);
|
|
124
|
+
}
|
|
125
|
+
this.loadSidebarWidth();
|
|
126
|
+
}
|
|
127
|
+
ngOnInit() {
|
|
128
|
+
// Sottoscrizione allo stato
|
|
129
|
+
this.stateService.state$.pipe(takeUntil(this.destroy$)).subscribe((state) => {
|
|
130
|
+
this.state = state;
|
|
131
|
+
this.updateBreadcrumb();
|
|
132
|
+
this.updateAvailableFields();
|
|
133
|
+
this.cdr.markForCheck();
|
|
134
|
+
});
|
|
135
|
+
// Controlla salvataggi precedenti da recuperare
|
|
136
|
+
this.checkForRecovery();
|
|
137
|
+
// Auto-save ogni 30 secondi
|
|
138
|
+
interval(30000)
|
|
139
|
+
.pipe(takeUntil(this.destroy$))
|
|
140
|
+
.subscribe(() => {
|
|
141
|
+
if (this.state.isDirty) {
|
|
142
|
+
this.autoSave();
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
ngOnDestroy() {
|
|
147
|
+
this.destroy$.next();
|
|
148
|
+
this.destroy$.complete();
|
|
149
|
+
}
|
|
150
|
+
// ─── Toolbar actions ─────────────────────────────────────────
|
|
151
|
+
/** Aggiunge una nuova sezione. */
|
|
152
|
+
onAddSection() {
|
|
153
|
+
this.stateService.addSection();
|
|
154
|
+
this.showMessage('Sezione aggiunta');
|
|
155
|
+
}
|
|
156
|
+
/** Salva nel localStorage. */
|
|
157
|
+
onSave() {
|
|
158
|
+
try {
|
|
159
|
+
this.persistenceService.saveToLocalStorage(this.state.schema);
|
|
160
|
+
this.stateService.markAsSaved();
|
|
161
|
+
this.showMessage('Salvato con successo');
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
this.showMessage(error.message || 'Errore durante il salvataggio', true);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
/** Crea un nuovo form. */
|
|
168
|
+
onNewForm() {
|
|
169
|
+
if (this.state.isDirty && !confirm('Ci sono modifiche non salvate. Continuare?')) {
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
this.stateService.reset();
|
|
173
|
+
this.showMessage('Nuovo form creato');
|
|
174
|
+
}
|
|
175
|
+
/** Importa da file JSON. */
|
|
176
|
+
onImportJson() {
|
|
177
|
+
const input = document.createElement('input');
|
|
178
|
+
input.type = 'file';
|
|
179
|
+
input.accept = '.json';
|
|
180
|
+
input.onchange = async (e) => {
|
|
181
|
+
const file = e.target.files[0];
|
|
182
|
+
if (!file)
|
|
183
|
+
return;
|
|
184
|
+
try {
|
|
185
|
+
const schema = await this.persistenceService.importFromJSON(file);
|
|
186
|
+
if (this.state.isDirty && !confirm('Ci sono modifiche non salvate. Sovrascrivere?')) {
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
this.stateService.setSchema(schema);
|
|
190
|
+
this.showMessage('Schema importato con successo');
|
|
191
|
+
}
|
|
192
|
+
catch (error) {
|
|
193
|
+
this.showMessage(error.message || "Errore durante l'import", true);
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
input.click();
|
|
197
|
+
}
|
|
198
|
+
/** Esporta come file JSON. */
|
|
199
|
+
onExportJson() {
|
|
200
|
+
try {
|
|
201
|
+
const validation = this.stateService.validateSchema();
|
|
202
|
+
if (!validation.valid) {
|
|
203
|
+
const message = `Schema con errori:\n${validation.errors.map((e) => e.message).join('\n')}`;
|
|
204
|
+
if (!confirm(`${message}\n\nEsportare comunque?`))
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
this.persistenceService.exportToJSON(this.state.schema);
|
|
208
|
+
this.showMessage('Schema esportato con successo');
|
|
209
|
+
}
|
|
210
|
+
catch (error) {
|
|
211
|
+
this.showMessage(error.message || "Errore durante l'export", true);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
/** Pulisce tutto lo schema. */
|
|
215
|
+
onClear() {
|
|
216
|
+
if (!confirm('Vuoi davvero eliminare tutto? Questa azione non puo essere annullata.'))
|
|
217
|
+
return;
|
|
218
|
+
this.persistenceService.createBackup(this.state.schema);
|
|
219
|
+
this.stateService.clearSchema();
|
|
220
|
+
this.showMessage('Schema pulito');
|
|
221
|
+
}
|
|
222
|
+
// ─── Sezioni ─────────────────────────────────────────────────
|
|
223
|
+
onSectionDuplicate(sectionId) {
|
|
224
|
+
this.stateService.duplicateSection(sectionId);
|
|
225
|
+
this.showMessage('Sezione duplicata');
|
|
226
|
+
}
|
|
227
|
+
onSectionDelete(sectionId) {
|
|
228
|
+
if (!confirm('Vuoi davvero eliminare questa sezione?'))
|
|
229
|
+
return;
|
|
230
|
+
this.stateService.removeSection(sectionId);
|
|
231
|
+
this.showMessage('Sezione eliminata');
|
|
232
|
+
}
|
|
233
|
+
// ─── Campi ───────────────────────────────────────────────────
|
|
234
|
+
onFieldSelect(sectionId, fieldKey) {
|
|
235
|
+
this.stateService.selectField(sectionId, fieldKey);
|
|
236
|
+
}
|
|
237
|
+
onFieldDuplicate(sectionId, fieldKey) {
|
|
238
|
+
this.stateService.duplicateField(sectionId, fieldKey);
|
|
239
|
+
this.showMessage('Campo duplicato');
|
|
240
|
+
}
|
|
241
|
+
onFieldDelete(sectionId, fieldKey) {
|
|
242
|
+
if (!confirm('Vuoi davvero eliminare questo campo?'))
|
|
243
|
+
return;
|
|
244
|
+
this.stateService.removeField(sectionId, fieldKey);
|
|
245
|
+
this.showMessage('Campo eliminato');
|
|
246
|
+
}
|
|
247
|
+
onFieldUpdate(sectionId, fieldKey, updates) {
|
|
248
|
+
this.stateService.updateField(sectionId, fieldKey, updates);
|
|
249
|
+
}
|
|
250
|
+
/** Gestisce il drop di un campo (dalla palette o tra sezioni). */
|
|
251
|
+
onFieldDrop(event) {
|
|
252
|
+
const prevId = event.previousContainer.id;
|
|
253
|
+
if (prevId.startsWith('palette-')) {
|
|
254
|
+
// Drop dalla palette
|
|
255
|
+
const paletteItem = event.item.data;
|
|
256
|
+
const section = event.container.data;
|
|
257
|
+
const newField = this.fieldFactory.createDefaultField(paletteItem.type);
|
|
258
|
+
this.stateService.addFieldAtIndex(section.id, newField, event.currentIndex);
|
|
259
|
+
this.showMessage(`Campo ${paletteItem.label} aggiunto`);
|
|
260
|
+
}
|
|
261
|
+
else if (event.previousContainer !== event.container) {
|
|
262
|
+
// Spostamento tra sezioni
|
|
263
|
+
const field = event.item.data;
|
|
264
|
+
const fromSection = event.previousContainer.data;
|
|
265
|
+
const toSection = event.container.data;
|
|
266
|
+
this.stateService.moveFieldBetweenSections(fromSection.id, toSection.id, field.key, event.currentIndex);
|
|
267
|
+
this.showMessage('Campo spostato');
|
|
268
|
+
}
|
|
269
|
+
else {
|
|
270
|
+
// Riordino nella stessa sezione
|
|
271
|
+
const section = event.container.data;
|
|
272
|
+
this.stateService.moveFieldInSection(section.id, event.previousIndex, event.currentIndex);
|
|
273
|
+
}
|
|
274
|
+
this.cdr.markForCheck();
|
|
275
|
+
}
|
|
276
|
+
// ─── Computed properties ─────────────────────────────────────
|
|
277
|
+
/** Campo attualmente selezionato. */
|
|
278
|
+
get selectedField() {
|
|
279
|
+
if (!this.state.selectedFieldKey)
|
|
280
|
+
return null;
|
|
281
|
+
return this.stateService.findFieldByKey(this.state.selectedFieldKey);
|
|
282
|
+
}
|
|
283
|
+
/** ID della sezione del campo selezionato. */
|
|
284
|
+
get selectedFieldSectionId() {
|
|
285
|
+
if (!this.state.selectedFieldKey)
|
|
286
|
+
return null;
|
|
287
|
+
return this.stateService.findSectionByFieldKey(this.state.selectedFieldKey)?.id || null;
|
|
288
|
+
}
|
|
289
|
+
// ─── Tab / Preview ───────────────────────────────────────────
|
|
290
|
+
onTabChange(index) {
|
|
291
|
+
this.selectedTabIndex = index;
|
|
292
|
+
if (index === 1)
|
|
293
|
+
this.refreshPreview();
|
|
294
|
+
}
|
|
295
|
+
refreshPreview() {
|
|
296
|
+
this.previewKey++;
|
|
297
|
+
this.cdr.markForCheck();
|
|
298
|
+
}
|
|
299
|
+
// ─── Dialog ──────────────────────────────────────────────────
|
|
300
|
+
/** Chiude la modale restituendo lo schema corrente. */
|
|
301
|
+
closeDialog() {
|
|
302
|
+
this.dialogRef?.close(this.state.schema);
|
|
303
|
+
}
|
|
304
|
+
// ─── Resize sidebar ──────────────────────────────────────────
|
|
305
|
+
onResizeStart(event) {
|
|
306
|
+
event.preventDefault();
|
|
307
|
+
this.isResizing = true;
|
|
308
|
+
this.resizeStartX = event.clientX;
|
|
309
|
+
this.resizeStartWidth = this.rightSidebarWidth;
|
|
310
|
+
document.addEventListener('mousemove', this.onResizeMove);
|
|
311
|
+
document.addEventListener('mouseup', this.onResizeEnd);
|
|
312
|
+
document.body.style.cursor = 'ew-resize';
|
|
313
|
+
document.body.style.userSelect = 'none';
|
|
314
|
+
}
|
|
315
|
+
// ─── Resize sidebar sinistra ─────────────────────────────────
|
|
316
|
+
onLeftResizeStart(event) {
|
|
317
|
+
event.preventDefault();
|
|
318
|
+
this.isResizingLeft = true;
|
|
319
|
+
this.resizeStartX = event.clientX;
|
|
320
|
+
this.resizeStartWidth = this.leftSidebarWidth;
|
|
321
|
+
document.addEventListener('mousemove', this.onLeftResizeMove);
|
|
322
|
+
document.addEventListener('mouseup', this.onLeftResizeEnd);
|
|
323
|
+
document.body.style.cursor = 'ew-resize';
|
|
324
|
+
document.body.style.userSelect = 'none';
|
|
325
|
+
}
|
|
326
|
+
// ─── Private ─────────────────────────────────────────────────
|
|
327
|
+
checkForRecovery() {
|
|
328
|
+
if (this.persistenceService.hasLocalStorageData()) {
|
|
329
|
+
const age = this.persistenceService.getLocalStorageAge();
|
|
330
|
+
const message = age
|
|
331
|
+
? `Trovato salvataggio del ${age.toLocaleString('it-IT')}. Vuoi recuperarlo?`
|
|
332
|
+
: 'Trovato salvataggio precedente. Vuoi recuperarlo?';
|
|
333
|
+
const ref = this.snackBar.open(message, 'Recupera', { duration: 10000 });
|
|
334
|
+
ref.onAction().subscribe(() => {
|
|
335
|
+
const schema = this.persistenceService.loadFromLocalStorage();
|
|
336
|
+
if (schema) {
|
|
337
|
+
this.stateService.setSchema(schema);
|
|
338
|
+
this.showMessage('Schema recuperato');
|
|
339
|
+
}
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
autoSave() {
|
|
344
|
+
try {
|
|
345
|
+
this.persistenceService.saveToLocalStorage(this.state.schema);
|
|
346
|
+
this.stateService.markAsSaved();
|
|
347
|
+
}
|
|
348
|
+
catch {
|
|
349
|
+
// Silenzioso per auto-save
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
updateBreadcrumb() {
|
|
353
|
+
this.breadcrumb = [
|
|
354
|
+
{
|
|
355
|
+
label: this.state.schema.title || 'Form',
|
|
356
|
+
id: this.state.schema.id,
|
|
357
|
+
type: 'form',
|
|
358
|
+
active: !this.state.selectedSectionId && !this.state.selectedFieldKey,
|
|
359
|
+
},
|
|
360
|
+
];
|
|
361
|
+
if (this.state.selectedSectionId) {
|
|
362
|
+
const section = this.state.schema.sections.find((s) => s.id === this.state.selectedSectionId);
|
|
363
|
+
if (section) {
|
|
364
|
+
this.breadcrumb.push({
|
|
365
|
+
label: section.title || 'Sezione',
|
|
366
|
+
id: section.id,
|
|
367
|
+
type: 'section',
|
|
368
|
+
active: !this.state.selectedFieldKey,
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
if (this.state.selectedFieldKey) {
|
|
373
|
+
const field = this.stateService.findFieldByKey(this.state.selectedFieldKey);
|
|
374
|
+
if (field) {
|
|
375
|
+
this.breadcrumb.push({
|
|
376
|
+
label: field.label,
|
|
377
|
+
id: field.key,
|
|
378
|
+
type: 'field',
|
|
379
|
+
active: true,
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
updateAvailableFields() {
|
|
385
|
+
const fields = [];
|
|
386
|
+
this.state.schema.sections.forEach((section) => {
|
|
387
|
+
section.fields.forEach((field) => {
|
|
388
|
+
const af = {
|
|
389
|
+
key: field.key,
|
|
390
|
+
label: field.label,
|
|
391
|
+
type: field.type,
|
|
392
|
+
};
|
|
393
|
+
if (field.options && Array.isArray(field.options) && field.options.length > 0) {
|
|
394
|
+
af.options = field.options.map((opt) => ({
|
|
395
|
+
value: opt.value,
|
|
396
|
+
label: opt.label,
|
|
397
|
+
}));
|
|
398
|
+
}
|
|
399
|
+
fields.push(af);
|
|
400
|
+
});
|
|
401
|
+
});
|
|
402
|
+
this.availableFields = fields;
|
|
403
|
+
}
|
|
404
|
+
showMessage(message, isError = false) {
|
|
405
|
+
this.snackBar.open(message, 'Chiudi', {
|
|
406
|
+
duration: 3000,
|
|
407
|
+
panelClass: isError ? ['ui-snackbar-error'] : [],
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
loadSidebarWidth() {
|
|
411
|
+
try {
|
|
412
|
+
const savedRight = localStorage.getItem(this.SIDEBAR_WIDTH_KEY);
|
|
413
|
+
if (savedRight) {
|
|
414
|
+
const w = parseInt(savedRight, 10);
|
|
415
|
+
if (!isNaN(w) && w >= this.MIN_SIDEBAR_WIDTH && w <= this.MAX_SIDEBAR_WIDTH) {
|
|
416
|
+
this.rightSidebarWidth = w;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
const savedLeft = localStorage.getItem(this.LEFT_SIDEBAR_WIDTH_KEY);
|
|
420
|
+
if (savedLeft) {
|
|
421
|
+
const w = parseInt(savedLeft, 10);
|
|
422
|
+
if (!isNaN(w) && w >= this.MIN_LEFT_SIDEBAR_WIDTH && w <= this.MAX_LEFT_SIDEBAR_WIDTH) {
|
|
423
|
+
this.leftSidebarWidth = w;
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
catch {
|
|
428
|
+
// Silenzioso
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
saveSidebarWidth() {
|
|
432
|
+
try {
|
|
433
|
+
localStorage.setItem(this.SIDEBAR_WIDTH_KEY, this.rightSidebarWidth.toString());
|
|
434
|
+
}
|
|
435
|
+
catch {
|
|
436
|
+
// Silenzioso
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
saveLeftSidebarWidth() {
|
|
440
|
+
try {
|
|
441
|
+
localStorage.setItem(this.LEFT_SIDEBAR_WIDTH_KEY, this.leftSidebarWidth.toString());
|
|
442
|
+
}
|
|
443
|
+
catch {
|
|
444
|
+
// Silenzioso
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: UiFormBuilderEditorComponent, deps: [{ token: i1.MatDialogRef, optional: true }, { token: MAT_DIALOG_DATA, optional: true }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
448
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: UiFormBuilderEditorComponent, isStandalone: true, selector: "ui-form-builder-editor", providers: [UiEditorStateService, UiEditorPersistenceService, UiEditorFieldFactoryService], ngImport: i0, template: `
|
|
449
|
+
<div class="editor-root" [class.dialog-mode]="isDialogMode">
|
|
450
|
+
<!-- Header con chiusura (solo in modale) -->
|
|
451
|
+
@if (isDialogMode) {
|
|
452
|
+
<div class="editor-dialog-header">
|
|
453
|
+
<h2>Form Builder - Editor Visuale</h2>
|
|
454
|
+
<ui-button
|
|
455
|
+
icon="x"
|
|
456
|
+
variant="ghost"
|
|
457
|
+
size="md"
|
|
458
|
+
ariaLabel="Chiudi editor"
|
|
459
|
+
tooltip="Chiudi editor"
|
|
460
|
+
(click)="closeDialog()"
|
|
461
|
+
/>
|
|
462
|
+
</div>
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
<!-- Toolbar -->
|
|
466
|
+
<ui-editor-toolbar
|
|
467
|
+
[breadcrumb]="breadcrumb"
|
|
468
|
+
[isDirty]="state.isDirty"
|
|
469
|
+
[lastSaved]="state.lastSaved"
|
|
470
|
+
(newForm)="onNewForm()"
|
|
471
|
+
(importJson)="onImportJson()"
|
|
472
|
+
(exportJson)="onExportJson()"
|
|
473
|
+
(save)="onSave()"
|
|
474
|
+
(clear)="onClear()"
|
|
475
|
+
(addSection)="onAddSection()"
|
|
476
|
+
/>
|
|
477
|
+
|
|
478
|
+
<!-- Tabs: Editor / Preview -->
|
|
479
|
+
<mat-tab-group
|
|
480
|
+
[selectedIndex]="selectedTabIndex"
|
|
481
|
+
(selectedIndexChange)="onTabChange($event)"
|
|
482
|
+
class="editor-tabs"
|
|
483
|
+
>
|
|
484
|
+
<!-- Tab Editor -->
|
|
485
|
+
<mat-tab label="Editor">
|
|
486
|
+
<div class="editor-layout" cdkDropListGroup>
|
|
487
|
+
<!-- Palette (sidebar sinistra) -->
|
|
488
|
+
<div
|
|
489
|
+
class="editor-sidebar left"
|
|
490
|
+
[style.width.px]="leftSidebarWidth"
|
|
491
|
+
>
|
|
492
|
+
<ui-field-palette />
|
|
493
|
+
<div
|
|
494
|
+
class="resize-handle resize-handle--right"
|
|
495
|
+
[class.resizing]="isResizingLeft"
|
|
496
|
+
(mousedown)="onLeftResizeStart($event)"
|
|
497
|
+
></div>
|
|
498
|
+
</div>
|
|
499
|
+
|
|
500
|
+
<!-- Area centrale con sezioni -->
|
|
501
|
+
<div class="editor-main">
|
|
502
|
+
<div class="sections-container">
|
|
503
|
+
@for (section of state.schema.sections; track section.id) {
|
|
504
|
+
<ui-section-editor
|
|
505
|
+
[section]="section"
|
|
506
|
+
[isSelected]="state.selectedSectionId === section.id"
|
|
507
|
+
[selectedFieldKey]="state.selectedFieldKey"
|
|
508
|
+
(sectionUpdate)="
|
|
509
|
+
stateService.updateSection(section.id, $event)
|
|
510
|
+
"
|
|
511
|
+
(sectionDelete)="onSectionDelete(section.id)"
|
|
512
|
+
(sectionDuplicate)="onSectionDuplicate(section.id)"
|
|
513
|
+
(fieldSelect)="onFieldSelect(section.id, $event)"
|
|
514
|
+
(fieldDuplicate)="onFieldDuplicate(section.id, $event)"
|
|
515
|
+
(fieldDelete)="onFieldDelete(section.id, $event)"
|
|
516
|
+
(fieldDrop)="onFieldDrop($event)"
|
|
517
|
+
/>
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
@if (state.schema.sections.length === 0) {
|
|
521
|
+
<div class="empty-state">
|
|
522
|
+
<lucide-icon
|
|
523
|
+
name="layout-template"
|
|
524
|
+
[size]="64"
|
|
525
|
+
></lucide-icon>
|
|
526
|
+
<h3>Nessuna sezione presente</h3>
|
|
527
|
+
<p>
|
|
528
|
+
Clicca su "Sezione" nella toolbar per aggiungere la prima
|
|
529
|
+
sezione
|
|
530
|
+
</p>
|
|
531
|
+
<ui-button
|
|
532
|
+
label="Aggiungi Prima Sezione"
|
|
533
|
+
variant="primary"
|
|
534
|
+
icon="plus"
|
|
535
|
+
(click)="onAddSection()"
|
|
536
|
+
/>
|
|
537
|
+
</div>
|
|
538
|
+
}
|
|
539
|
+
</div>
|
|
540
|
+
</div>
|
|
541
|
+
|
|
542
|
+
<!-- Config panel (sidebar destra) -->
|
|
543
|
+
<div
|
|
544
|
+
class="editor-sidebar right"
|
|
545
|
+
[style.width.px]="rightSidebarWidth"
|
|
546
|
+
>
|
|
547
|
+
<div
|
|
548
|
+
class="resize-handle"
|
|
549
|
+
[class.resizing]="isResizing"
|
|
550
|
+
(mousedown)="onResizeStart($event)"
|
|
551
|
+
></div>
|
|
552
|
+
<ui-editor-field-config-panel
|
|
553
|
+
[field]="selectedField"
|
|
554
|
+
[availableFields]="availableFields"
|
|
555
|
+
(fieldUpdate)="
|
|
556
|
+
onFieldUpdate(
|
|
557
|
+
selectedFieldSectionId!,
|
|
558
|
+
state.selectedFieldKey!,
|
|
559
|
+
$event
|
|
560
|
+
)
|
|
561
|
+
"
|
|
562
|
+
/>
|
|
563
|
+
</div>
|
|
564
|
+
</div>
|
|
565
|
+
</mat-tab>
|
|
566
|
+
|
|
567
|
+
<!-- Tab Preview -->
|
|
568
|
+
<mat-tab label="Anteprima">
|
|
569
|
+
<ui-editor-preview-container
|
|
570
|
+
[schema]="state.schema"
|
|
571
|
+
[key]="previewKey"
|
|
572
|
+
(refresh)="refreshPreview()"
|
|
573
|
+
/>
|
|
574
|
+
</mat-tab>
|
|
575
|
+
</mat-tab-group>
|
|
576
|
+
</div>
|
|
577
|
+
`, isInline: true, styles: ["@use \"../../../core/tokens/mixins\" as ui;.editor-root{display:flex;flex-direction:column;height:100vh;background:var(--ui-color-bg-subtle);&.dialog-mode{height:100%}}.editor-dialog-header{display:flex;align-items:center;justify-content:space-between;padding:var(--ui-spacing-3) var(--ui-spacing-4);background:var(--ui-color-surface);border-bottom:1px solid var(--ui-color-border);box-shadow:var(--ui-shadow-sm);h2{margin:0;font-size:var(--ui-font-size-lg);font-weight:500;color:var(--ui-color-text)}}.editor-tabs{flex:1;display:flex;flex-direction:column;overflow:hidden;::ng-deep .mat-mdc-tab-header{background:var(--ui-color-surface);border-bottom:1px solid var(--ui-color-border)}::ng-deep .mat-mdc-tab .mdc-tab__text-label{color:var(--ui-color-text-secondary);font-weight:500;font-size:var(--ui-font-size-sm);letter-spacing:.02em}::ng-deep .mat-mdc-tab.mdc-tab--active .mdc-tab__text-label{color:var(--ui-color-primary);font-weight:600}::ng-deep .mat-mdc-tab-header .mdc-tab-indicator__content--underline{border-color:var(--ui-color-primary);border-width:3px}::ng-deep .mat-mdc-tab-body-wrapper{flex:1;overflow:hidden}::ng-deep .mat-mdc-tab-body{height:100%}::ng-deep .mat-mdc-tab-body-content{height:100%;overflow:hidden}}.editor-layout{display:flex;height:100%;overflow:hidden}.editor-sidebar{height:100%;overflow-y:auto;background:var(--ui-color-surface);flex-shrink:0;&.left{position:relative;border-right:1px solid var(--ui-color-border);min-width:200px;max-width:500px}&.right{position:relative;border-left:1px solid var(--ui-color-border);min-width:400px;max-width:1200px}}.editor-main{flex:1;min-width:0;height:100%;overflow-y:auto;padding:var(--ui-spacing-4);background:var(--ui-color-bg-subtle)}.sections-container{max-width:1200px;margin:0 auto;display:flex;flex-direction:column;gap:var(--ui-spacing-4)}.resize-handle{position:absolute;top:0;bottom:0;width:6px;cursor:ew-resize;z-index:10;transition:background-color var(--ui-transition-fast);left:0;&:before{content:\"\";position:absolute;left:-3px;top:0;bottom:0;width:12px}&:hover,&.resizing{background-color:color-mix(in srgb,var(--ui-color-primary) 30%,transparent)}&.resizing{background-color:color-mix(in srgb,var(--ui-color-primary) 50%,transparent)}}.resize-handle--right{left:auto;right:0;&:before{left:auto;right:-3px}}.empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:var(--ui-spacing-12) var(--ui-spacing-8);text-align:center;color:var(--ui-color-text-muted);lucide-icon{opacity:.4}h3{margin:0 0 var(--ui-spacing-2) 0;font-size:var(--ui-font-size-xl);font-weight:400;color:var(--ui-color-text-secondary)}p{margin:0 0 var(--ui-spacing-6) 0;font-size:var(--ui-font-size-md);color:var(--ui-color-text-muted)}}@media (max-width: 1280px){.editor-sidebar.left{width:250px}}@media (max-width: 960px){.editor-layout{flex-direction:column}.editor-sidebar{&.left{display:none}&.right{position:fixed;right:0;top:64px;width:100%!important;max-width:350px;height:calc(100vh - 64px);z-index:1000;box-shadow:var(--ui-shadow-lg);transform:translate(100%);transition:transform var(--ui-transition-normal);.resize-handle{display:none}}}}\n"], dependencies: [{ kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i2.CdkDropListGroup, selector: "[cdkDropListGroup]", inputs: ["cdkDropListGroupDisabled"], exportAs: ["cdkDropListGroup"] }, { kind: "ngmodule", type: MatSnackBarModule }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i3.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass"], exportAs: ["matTab"] }, { kind: "component", type: i3.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "ngmodule", type: LucideAngularModule }, { kind: "component", type: i4.LucideAngularComponent, selector: "lucide-angular, lucide-icon, i-lucide, span-lucide", inputs: ["class", "name", "img", "color", "absoluteStrokeWidth", "size", "strokeWidth"] }, { kind: "component", type: UiEditorToolbarComponent, selector: "ui-editor-toolbar", inputs: ["breadcrumb", "isDirty", "lastSaved"], outputs: ["newForm", "importJson", "exportJson", "save", "clear", "addSection"] }, { kind: "component", type: UiFieldPaletteComponent, selector: "ui-field-palette" }, { kind: "component", type: UiSectionEditorComponent, selector: "ui-section-editor", inputs: ["section", "isSelected", "selectedFieldKey"], outputs: ["sectionUpdate", "sectionDelete", "sectionDuplicate", "fieldSelect", "fieldDuplicate", "fieldDelete", "fieldDrop"] }, { kind: "component", type: UiEditorFieldConfigPanelComponent, selector: "ui-editor-field-config-panel", inputs: ["field", "availableFields"], outputs: ["fieldUpdate"] }, { kind: "component", type: UiEditorPreviewContainerComponent, selector: "ui-editor-preview-container", inputs: ["schema", "key"], outputs: ["refresh"] }, { kind: "component", type: UiButtonComponent, selector: "ui-button", inputs: ["label", "tooltip", "variant", "size", "icon", "iconPosition", "loading", "disabled", "fullWidth", "type", "ariaLabel", "customClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
578
|
+
}
|
|
579
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: UiFormBuilderEditorComponent, decorators: [{
|
|
580
|
+
type: Component,
|
|
581
|
+
args: [{ selector: 'ui-form-builder-editor', standalone: true, imports: [
|
|
582
|
+
DragDropModule,
|
|
583
|
+
MatSnackBarModule,
|
|
584
|
+
MatTabsModule,
|
|
585
|
+
LucideAngularModule,
|
|
586
|
+
UiEditorToolbarComponent,
|
|
587
|
+
UiFieldPaletteComponent,
|
|
588
|
+
UiSectionEditorComponent,
|
|
589
|
+
UiEditorFieldConfigPanelComponent,
|
|
590
|
+
UiEditorPreviewContainerComponent,
|
|
591
|
+
UiButtonComponent,
|
|
592
|
+
], providers: [UiEditorStateService, UiEditorPersistenceService, UiEditorFieldFactoryService], changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
593
|
+
<div class="editor-root" [class.dialog-mode]="isDialogMode">
|
|
594
|
+
<!-- Header con chiusura (solo in modale) -->
|
|
595
|
+
@if (isDialogMode) {
|
|
596
|
+
<div class="editor-dialog-header">
|
|
597
|
+
<h2>Form Builder - Editor Visuale</h2>
|
|
598
|
+
<ui-button
|
|
599
|
+
icon="x"
|
|
600
|
+
variant="ghost"
|
|
601
|
+
size="md"
|
|
602
|
+
ariaLabel="Chiudi editor"
|
|
603
|
+
tooltip="Chiudi editor"
|
|
604
|
+
(click)="closeDialog()"
|
|
605
|
+
/>
|
|
606
|
+
</div>
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
<!-- Toolbar -->
|
|
610
|
+
<ui-editor-toolbar
|
|
611
|
+
[breadcrumb]="breadcrumb"
|
|
612
|
+
[isDirty]="state.isDirty"
|
|
613
|
+
[lastSaved]="state.lastSaved"
|
|
614
|
+
(newForm)="onNewForm()"
|
|
615
|
+
(importJson)="onImportJson()"
|
|
616
|
+
(exportJson)="onExportJson()"
|
|
617
|
+
(save)="onSave()"
|
|
618
|
+
(clear)="onClear()"
|
|
619
|
+
(addSection)="onAddSection()"
|
|
620
|
+
/>
|
|
621
|
+
|
|
622
|
+
<!-- Tabs: Editor / Preview -->
|
|
623
|
+
<mat-tab-group
|
|
624
|
+
[selectedIndex]="selectedTabIndex"
|
|
625
|
+
(selectedIndexChange)="onTabChange($event)"
|
|
626
|
+
class="editor-tabs"
|
|
627
|
+
>
|
|
628
|
+
<!-- Tab Editor -->
|
|
629
|
+
<mat-tab label="Editor">
|
|
630
|
+
<div class="editor-layout" cdkDropListGroup>
|
|
631
|
+
<!-- Palette (sidebar sinistra) -->
|
|
632
|
+
<div
|
|
633
|
+
class="editor-sidebar left"
|
|
634
|
+
[style.width.px]="leftSidebarWidth"
|
|
635
|
+
>
|
|
636
|
+
<ui-field-palette />
|
|
637
|
+
<div
|
|
638
|
+
class="resize-handle resize-handle--right"
|
|
639
|
+
[class.resizing]="isResizingLeft"
|
|
640
|
+
(mousedown)="onLeftResizeStart($event)"
|
|
641
|
+
></div>
|
|
642
|
+
</div>
|
|
643
|
+
|
|
644
|
+
<!-- Area centrale con sezioni -->
|
|
645
|
+
<div class="editor-main">
|
|
646
|
+
<div class="sections-container">
|
|
647
|
+
@for (section of state.schema.sections; track section.id) {
|
|
648
|
+
<ui-section-editor
|
|
649
|
+
[section]="section"
|
|
650
|
+
[isSelected]="state.selectedSectionId === section.id"
|
|
651
|
+
[selectedFieldKey]="state.selectedFieldKey"
|
|
652
|
+
(sectionUpdate)="
|
|
653
|
+
stateService.updateSection(section.id, $event)
|
|
654
|
+
"
|
|
655
|
+
(sectionDelete)="onSectionDelete(section.id)"
|
|
656
|
+
(sectionDuplicate)="onSectionDuplicate(section.id)"
|
|
657
|
+
(fieldSelect)="onFieldSelect(section.id, $event)"
|
|
658
|
+
(fieldDuplicate)="onFieldDuplicate(section.id, $event)"
|
|
659
|
+
(fieldDelete)="onFieldDelete(section.id, $event)"
|
|
660
|
+
(fieldDrop)="onFieldDrop($event)"
|
|
661
|
+
/>
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
@if (state.schema.sections.length === 0) {
|
|
665
|
+
<div class="empty-state">
|
|
666
|
+
<lucide-icon
|
|
667
|
+
name="layout-template"
|
|
668
|
+
[size]="64"
|
|
669
|
+
></lucide-icon>
|
|
670
|
+
<h3>Nessuna sezione presente</h3>
|
|
671
|
+
<p>
|
|
672
|
+
Clicca su "Sezione" nella toolbar per aggiungere la prima
|
|
673
|
+
sezione
|
|
674
|
+
</p>
|
|
675
|
+
<ui-button
|
|
676
|
+
label="Aggiungi Prima Sezione"
|
|
677
|
+
variant="primary"
|
|
678
|
+
icon="plus"
|
|
679
|
+
(click)="onAddSection()"
|
|
680
|
+
/>
|
|
681
|
+
</div>
|
|
682
|
+
}
|
|
683
|
+
</div>
|
|
684
|
+
</div>
|
|
685
|
+
|
|
686
|
+
<!-- Config panel (sidebar destra) -->
|
|
687
|
+
<div
|
|
688
|
+
class="editor-sidebar right"
|
|
689
|
+
[style.width.px]="rightSidebarWidth"
|
|
690
|
+
>
|
|
691
|
+
<div
|
|
692
|
+
class="resize-handle"
|
|
693
|
+
[class.resizing]="isResizing"
|
|
694
|
+
(mousedown)="onResizeStart($event)"
|
|
695
|
+
></div>
|
|
696
|
+
<ui-editor-field-config-panel
|
|
697
|
+
[field]="selectedField"
|
|
698
|
+
[availableFields]="availableFields"
|
|
699
|
+
(fieldUpdate)="
|
|
700
|
+
onFieldUpdate(
|
|
701
|
+
selectedFieldSectionId!,
|
|
702
|
+
state.selectedFieldKey!,
|
|
703
|
+
$event
|
|
704
|
+
)
|
|
705
|
+
"
|
|
706
|
+
/>
|
|
707
|
+
</div>
|
|
708
|
+
</div>
|
|
709
|
+
</mat-tab>
|
|
710
|
+
|
|
711
|
+
<!-- Tab Preview -->
|
|
712
|
+
<mat-tab label="Anteprima">
|
|
713
|
+
<ui-editor-preview-container
|
|
714
|
+
[schema]="state.schema"
|
|
715
|
+
[key]="previewKey"
|
|
716
|
+
(refresh)="refreshPreview()"
|
|
717
|
+
/>
|
|
718
|
+
</mat-tab>
|
|
719
|
+
</mat-tab-group>
|
|
720
|
+
</div>
|
|
721
|
+
`, styles: ["@use \"../../../core/tokens/mixins\" as ui;.editor-root{display:flex;flex-direction:column;height:100vh;background:var(--ui-color-bg-subtle);&.dialog-mode{height:100%}}.editor-dialog-header{display:flex;align-items:center;justify-content:space-between;padding:var(--ui-spacing-3) var(--ui-spacing-4);background:var(--ui-color-surface);border-bottom:1px solid var(--ui-color-border);box-shadow:var(--ui-shadow-sm);h2{margin:0;font-size:var(--ui-font-size-lg);font-weight:500;color:var(--ui-color-text)}}.editor-tabs{flex:1;display:flex;flex-direction:column;overflow:hidden;::ng-deep .mat-mdc-tab-header{background:var(--ui-color-surface);border-bottom:1px solid var(--ui-color-border)}::ng-deep .mat-mdc-tab .mdc-tab__text-label{color:var(--ui-color-text-secondary);font-weight:500;font-size:var(--ui-font-size-sm);letter-spacing:.02em}::ng-deep .mat-mdc-tab.mdc-tab--active .mdc-tab__text-label{color:var(--ui-color-primary);font-weight:600}::ng-deep .mat-mdc-tab-header .mdc-tab-indicator__content--underline{border-color:var(--ui-color-primary);border-width:3px}::ng-deep .mat-mdc-tab-body-wrapper{flex:1;overflow:hidden}::ng-deep .mat-mdc-tab-body{height:100%}::ng-deep .mat-mdc-tab-body-content{height:100%;overflow:hidden}}.editor-layout{display:flex;height:100%;overflow:hidden}.editor-sidebar{height:100%;overflow-y:auto;background:var(--ui-color-surface);flex-shrink:0;&.left{position:relative;border-right:1px solid var(--ui-color-border);min-width:200px;max-width:500px}&.right{position:relative;border-left:1px solid var(--ui-color-border);min-width:400px;max-width:1200px}}.editor-main{flex:1;min-width:0;height:100%;overflow-y:auto;padding:var(--ui-spacing-4);background:var(--ui-color-bg-subtle)}.sections-container{max-width:1200px;margin:0 auto;display:flex;flex-direction:column;gap:var(--ui-spacing-4)}.resize-handle{position:absolute;top:0;bottom:0;width:6px;cursor:ew-resize;z-index:10;transition:background-color var(--ui-transition-fast);left:0;&:before{content:\"\";position:absolute;left:-3px;top:0;bottom:0;width:12px}&:hover,&.resizing{background-color:color-mix(in srgb,var(--ui-color-primary) 30%,transparent)}&.resizing{background-color:color-mix(in srgb,var(--ui-color-primary) 50%,transparent)}}.resize-handle--right{left:auto;right:0;&:before{left:auto;right:-3px}}.empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:var(--ui-spacing-12) var(--ui-spacing-8);text-align:center;color:var(--ui-color-text-muted);lucide-icon{opacity:.4}h3{margin:0 0 var(--ui-spacing-2) 0;font-size:var(--ui-font-size-xl);font-weight:400;color:var(--ui-color-text-secondary)}p{margin:0 0 var(--ui-spacing-6) 0;font-size:var(--ui-font-size-md);color:var(--ui-color-text-muted)}}@media (max-width: 1280px){.editor-sidebar.left{width:250px}}@media (max-width: 960px){.editor-layout{flex-direction:column}.editor-sidebar{&.left{display:none}&.right{position:fixed;right:0;top:64px;width:100%!important;max-width:350px;height:calc(100vh - 64px);z-index:1000;box-shadow:var(--ui-shadow-lg);transform:translate(100%);transition:transform var(--ui-transition-normal);.resize-handle{display:none}}}}\n"] }]
|
|
722
|
+
}], ctorParameters: () => [{ type: i1.MatDialogRef, decorators: [{
|
|
723
|
+
type: Optional
|
|
724
|
+
}] }, { type: undefined, decorators: [{
|
|
725
|
+
type: Optional
|
|
726
|
+
}, {
|
|
727
|
+
type: Inject,
|
|
728
|
+
args: [MAT_DIALOG_DATA]
|
|
729
|
+
}] }] });
|
|
730
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9ybS1idWlsZGVyLWVkaXRvci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9uZy11aS1zeXN0ZW0vc3JjL2xpYi9jb21wb25lbnRzL2Zvcm0tYnVpbGRlci1lZGl0b3IvZm9ybS1idWlsZGVyLWVkaXRvci5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7R0FnQkc7QUFFSCxPQUFPLEVBQ0wsU0FBUyxFQUNULHVCQUF1QixFQUN2QixpQkFBaUIsRUFHakIsTUFBTSxFQUNOLFFBQVEsRUFDUixNQUFNLEdBQ1AsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFlLGNBQWMsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ3JFLE9BQU8sRUFBZ0IsZUFBZSxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDekUsT0FBTyxFQUFFLFdBQVcsRUFBRSxpQkFBaUIsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBQzdFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUN2RCxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUNyRCxPQUFPLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUN6QyxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFZM0MsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDdkUsT0FBTyxFQUFFLDBCQUEwQixFQUFFLE1BQU0sdUNBQXVDLENBQUM7QUFDbkYsT0FBTyxFQUFFLDJCQUEyQixFQUFFLE1BQU0sa0NBQWtDLENBQUM7QUFFL0UsbUJBQW1CO0FBQ25CLE9BQU8sRUFBRSx3QkFBd0IsRUFBRSxNQUFNLDBEQUEwRCxDQUFDO0FBQ3BHLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxNQUFNLHdEQUF3RCxD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UUFBUTs7MEJBQUksTUFBTTsyQkFBQyxlQUFlIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXHJcbiAqIEBtb2R1bGUgbmctdWktc3lzdGVtL2Zvcm0tYnVpbGRlci1lZGl0b3JcclxuICogQ29tcG9uZW50ZSBwcmluY2lwYWxlIGRlbGwnZWRpdG9yIHZpc3VhbGUgZGVsIGZvcm0gYnVpbGRlci5cclxuICpcclxuICogTGF5b3V0IGEgdHJlIHBhbm5lbGxpOlxyXG4gKiAtIFNpbmlzdHJhOiBwYWxldHRlIGRlaSB0aXBpIGRpIGNhbXBvIChkcmFnIHNvdXJjZSlcclxuICogLSBDZW50cm86IHNlemlvbmkgY29uIGNhbXBpIChkcm9wIHRhcmdldCArIGVkaXRvciBpbmxpbmUpXHJcbiAqIC0gRGVzdHJhOiBwYW5uZWxsbyBkaSBjb25maWd1cmF6aW9uZSBkZWwgY2FtcG8gc2VsZXppb25hdG9cclxuICpcclxuICogRnVuemlvbmFsaXRhIHByaW5jaXBhbGk6XHJcbiAqIC0gRHJhZyAmIGRyb3AgZGVpIGNhbXBpIGRhbGxhIHBhbGV0dGUgYWxsZSBzZXppb25pXHJcbiAqIC0gUmlvcmRpbm8gY2FtcGkgYWxsJ2ludGVybm8gZSB0cmEgc2V6aW9uaVxyXG4gKiAtIENvbmZpZ3VyYXppb25lIGNhbXBpIGluIHRlbXBvIHJlYWxlXHJcbiAqIC0gUHJldmlldyBsaXZlIGRlbCBmb3JtXHJcbiAqIC0gSW1wb3J0L2V4cG9ydCBKU09OXHJcbiAqIC0gQXV0by1zYXZlIHN1IGxvY2FsU3RvcmFnZVxyXG4gKi9cclxuXHJcbmltcG9ydCB7XHJcbiAgQ29tcG9uZW50LFxyXG4gIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxyXG4gIENoYW5nZURldGVjdG9yUmVmLFxyXG4gIE9uSW5pdCxcclxuICBPbkRlc3Ryb3ksXHJcbiAgaW5qZWN0LFxyXG4gIE9wdGlvbmFsLFxyXG4gIEluamVjdCxcclxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgQ2RrRHJhZ0Ryb3AsIERyYWdEcm9wTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY2RrL2RyYWctZHJvcCc7XHJcbmltcG9ydCB7IE1hdERpYWxvZ1JlZiwgTUFUX0RJQUxPR19EQVRBIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvZGlhbG9nJztcclxuaW1wb3J0IHsgTWF0U25hY2tCYXIsIE1hdFNuYWNrQmFyTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvc25hY2stYmFyJztcclxuaW1wb3J0IHsgTWF0VGFic01vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL3RhYnMnO1xyXG5pbXBvcnQgeyBMdWNpZGVBbmd1bGFyTW9kdWxlIH0gZnJvbSAnbHVjaWRlLWFuZ3VsYXInO1xyXG5pbXBvcnQgeyBTdWJqZWN0LCBpbnRlcnZhbCB9IGZyb20gJ3J4anMnO1xyXG5pbXBvcnQgeyB0YWtlVW50aWwgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XHJcblxyXG5pbXBvcnQgeyBVaUZvcm1TY2hlbWEsIFVpRm9ybVNlY3Rpb24sIFVpRm9ybUZpZWxkRGVzY3JpcHRvciB9IGZyb20gJy4uL2Zvcm0tYnVpbGRlci90eXBlcy9pbmRleCc7XHJcblxyXG5pbXBvcnQge1xyXG4gIFVpRWRpdG9yU3RhdGUsXHJcbiAgVWlFZGl0b3JCcmVhZGNydW1iSXRlbSxcclxuICBVaUVkaXRvckZpZWxkUGFsZXR0ZUl0ZW0sXHJcbiAgVWlFZGl0b3JBdmFpbGFibGVGaWVsZCxcclxuICBVaUVkaXRvckRpYWxvZ0RhdGEsXHJcbn0gZnJvbSAnLi90eXBlcy9lZGl0b3IudHlwZXMnO1xyXG5cclxuaW1wb3J0IHsgVWlFZGl0b3JTdGF0ZVNlcnZpY2UgfSBmcm9tICcuL3NlcnZpY2VzL2VkaXRvci1zdGF0ZS5zZXJ2aWNlJztcclxuaW1wb3J0IHsgVWlFZGl0b3JQZXJzaXN0ZW5jZVNlcnZpY2UgfSBmcm9tICcuL3NlcnZpY2VzL2VkaXRvci1wZXJzaXN0ZW5jZS5zZXJ2aWNlJztcclxuaW1wb3J0IHsgVWlFZGl0b3JGaWVsZEZhY3RvcnlTZXJ2aWNlIH0gZnJvbSAnLi9zZXJ2aWNlcy9maWVsZC1mYWN0b3J5LnNlcnZpY2UnO1xyXG5cclxuLy8gU290dG8tY29tcG9uZW50aVxyXG5pbXBvcnQgeyBVaUVkaXRvclRvb2xiYXJDb21wb25lbnQgfSBmcm9tICcuL3N1Yi1jb21wb25lbnRzL2VkaXRvci10b29sYmFyL2VkaXRvci10b29sYmFyLmNvbXBvbmVudCc7XHJcbmltcG9ydCB7IFVpRmllbGRQYWxldHRlQ29tcG9uZW50IH0gZnJvbSAnLi9zdWItY29tcG9uZW50cy9maWVsZC1wYWxldHRlL2ZpZWxkLXBhbGV0dGUuY29tcG9uZW50JztcclxuaW1wb3J0IHsgVWlTZWN0aW9uRWRpdG9yQ29tcG9uZW50IH0gZnJvbSAnLi9zdWItY29tcG9uZW50cy9zZWN0aW9uLWVkaXRvci9zZWN0aW9uLWVkaXRvci5jb21wb25lbnQnO1xyXG5pbXBvcnQgeyBVaUVkaXRvckZpZWxkQ29uZmlnUGFuZWxDb21wb25lbnQgfSBmcm9tICcuL3N1Yi1jb21wb25lbnRzL2ZpZWxkLWNvbmZpZy1wYW5lbC9maWVsZC1jb25maWctcGFuZWwuY29tcG9uZW50JztcclxuaW1wb3J0IHsgVWlFZGl0b3JQcmV2aWV3Q29udGFpbmVyQ29tcG9uZW50IH0gZnJvbSAnLi9zdWItY29tcG9uZW50cy9wcmV2aWV3LWNvbnRhaW5lci9wcmV2aWV3LWNvbnRhaW5lci5jb21wb25lbnQnO1xyXG5pbXBvcnQgeyBVaUJ1dHRvbkNvbXBvbmVudCB9IGZyb20gJy4uL2J1dHRvbi9pbmRleCc7XHJcblxyXG5AQ29tcG9uZW50KHtcclxuICBzZWxlY3RvcjogJ3VpLWZvcm0tYnVpbGRlci1lZGl0b3InLFxyXG4gIHN0YW5kYWxvbmU6IHRydWUsXHJcbiAgaW1wb3J0czogW1xyXG4gICAgRHJhZ0Ryb3BNb2R1bGUsXHJcbiAgICBNYXRTbmFja0Jhck1vZHVsZSxcclxuICAgIE1hdFRhYnNNb2R1bGUsXHJcbiAgICBMdWNpZGVBbmd1bGFyTW9kdWxlLFxyXG4gICAgVWlFZGl0b3JUb29sYmFyQ29tcG9uZW50LFxyXG4gICAgVWlGaWVsZFBhbGV0dGVDb21wb25lbnQsXHJcbiAgICBVaVNlY3Rpb25FZGl0b3JDb21wb25lbnQsXHJcbiAgICBVaUVkaXRvckZpZWxkQ29uZmlnUGFuZWxDb21wb25lbnQsXHJcbiAgICBVaUVkaXRvclByZXZpZXdDb250YWluZXJDb21wb25lbnQsXHJcbiAgICBVaUJ1dHRvbkNvbXBvbmVudCxcclxuICBdLFxyXG4gIHByb3ZpZGVyczogW1VpRWRpdG9yU3RhdGVTZXJ2aWNlLCBVaUVkaXRvclBlcnNpc3RlbmNlU2VydmljZSwgVWlFZGl0b3JGaWVsZEZhY3RvcnlTZXJ2aWNlXSxcclxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcclxuICB0ZW1wbGF0ZTogYFxyXG4gICAgPGRpdiBjbGFzcz1cImVkaXRvci1yb290XCIgW2NsYXNzLmRpYWxvZy1tb2RlXT1cImlzRGlhbG9nTW9kZVwiPlxyXG4gICAgICA8IS0tIEhlYWRlciBjb24gY2hpdXN1cmEgKHNvbG8gaW4gbW9kYWxlKSAtLT5cclxuICAgICAgQGlmIChpc0RpYWxvZ01vZGUpIHtcclxuICAgICAgICA8ZGl2IGNsYXNzPVwiZWRpdG9yLWRpYWxvZy1oZWFkZXJcIj5cclxuICAgICAgICAgIDxoMj5Gb3JtIEJ1aWxkZXIgLSBFZGl0b3IgVmlzdWFsZTwvaDI+XHJcbiAgICAgICAgICA8dWktYnV0dG9uXHJcbiAgICAgICAgICAgIGljb249XCJ4XCJcclxuICAgICAgICAgICAgdmFyaWFudD1cImdob3N0XCJcclxuICAgICAgICAgICAgc2l6ZT1cIm1kXCJcclxuICAgICAgICAgICAgYXJpYUxhYmVsPVwiQ2hpdWRpIGVkaXRvclwiXHJcbiAgICAgICAgICAgIHRvb2x0aXA9XCJDaGl1ZGkgZWRpdG9yXCJcclxuICAgICAgICAgICAgKGNsaWNrKT1cImNsb3NlRGlhbG9nKClcIlxyXG4gICAgICAgICAgLz5cclxuICAgICAgICA8L2Rpdj5cclxuICAgICAgfVxyXG5cclxuICAgICAgPCEtLSBUb29sYmFyIC0tPlxyXG4gICAgICA8dWktZWRpdG9yLXRvb2xiYXJcclxuICAgICAgICBbYnJlYWRjcnVtYl09XCJicmVhZGNydW1iXCJcclxuICAgICAgICBbaXNEaXJ0eV09XCJzdGF0ZS5pc0RpcnR5XCJcclxuICAgICAgICBbbGFzdFNhdmVkXT1cInN0YXRlLmxhc3RTYXZlZFwiXHJcbiAgICAgICAgKG5ld0Zvcm0pPVwib25OZXdGb3JtKClcIlxyXG4gICAgICAgIChpbXBvcnRKc29uKT1cIm9uSW1wb3J0SnNvbigpXCJcclxuICAgICAgICAoZXhwb3J0SnNvbik9XCJvbkV4cG9ydEpzb24oKVwiXHJcbiAgICAgICAgKHNhdmUpPVwib25TYXZlKClcIlxyXG4gICAgICAgIChjbGVhcik9XCJvbkNsZWFyKClcIlxyXG4gICAgICAgIChhZGRTZWN0aW9uKT1cIm9uQWRkU2VjdGlvbigpXCJcclxuICAgICAgLz5cclxuXHJcbiAgICAgIDwhLS0gVGFiczogRWRpdG9yIC8gUHJldmlldyAtLT5cclxuICAgICAgPG1hdC10YWItZ3JvdXBcclxuICAgICAgICBbc2VsZWN0ZWRJbmRleF09XCJzZWxlY3RlZFRhYkluZGV4XCJcclxuICAgICAgICAoc2VsZWN0ZWRJbmRleENoYW5nZSk9XCJvblRhYkNoYW5nZSgkZXZlbnQpXCJcclxuICAgICAgICBjbGFzcz1cImVkaXRvci10YWJzXCJcclxuICAgICAgPlxyXG4gICAgICAgIDwhLS0gVGFiIEVkaXRvciAtLT5cclxuICAgICAgICA8bWF0LXRhYiBsYWJlbD1cIkVkaXRvclwiPlxyXG4gICAgICAgICAgPGRpdiBjbGFzcz1cImVkaXRvci1sYXlvdXRcIiBjZGtEcm9wTGlzdEdyb3VwPlxyXG4gICAgICAgICAgICA8IS0tIFBhbGV0dGUgKHNpZGViYXIgc2luaXN0cmEpIC0tPlxyXG4gICAgICAgICAgICA8ZGl2XHJcbiAgICAgICAgICAgICAgY2xhc3M9XCJlZGl0b3Itc2lkZWJhciBsZWZ0XCJcclxuICAgICAgICAgICAgICBbc3R5bGUud2lkdGgucHhdPVwibGVmdFNpZGViYXJXaWR0aFwiXHJcbiAgICAgICAgICAgID5cclxuICAgICAgICAgICAgICA8dWktZmllbGQtcGFsZXR0ZSAvPlxyXG4gICAgICAgICAgICAgIDxkaXZcclxuICAgICAgICAgICAgICAgIGNsYXNzPVwicmVzaXplLWhhbmRsZSByZXNpemUtaGFuZGxlLS1yaWdodFwiXHJcbiAgICAgICAgICAgICAgICBbY2xhc3MucmVzaXppbmddPVwiaXNSZXNpemluZ0xlZnRcIlxyXG4gICAgICAgICAgICAgICAgKG1vdXNlZG93bik9XCJvbkxlZnRSZXNpemVTdGFydCgkZXZlbnQpXCJcclxuICAgICAgICAgICAgICA+PC9kaXY+XHJcbiAgICAgICAgICAgIDwvZGl2PlxyXG5cclxuICAgICAgICAgICAgPCEtLSBBcmVhIGNlbnRyYWxlIGNvbiBzZXppb25pIC0tPlxyXG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZWRpdG9yLW1haW5cIj5cclxuICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwic2VjdGlvbnMtY29udGFpbmVyXCI+XHJcbiAgICAgICAgICAgICAgICBAZm9yIChzZWN0aW9uIG9mIHN0YXRlLnNjaGVtYS5zZWN0aW9uczsgdHJhY2sgc2VjdGlvbi5pZCkge1xyXG4gICAgICAgICAgICAgICAgICA8dWktc2VjdGlvbi1lZGl0b3JcclxuICAgICAgICAgICAgICAgICAgICBbc2VjdGlvbl09XCJzZWN0aW9uXCJcclxuICAgICAgICAgICAgICAgICAgICBbaXNTZWxlY3RlZF09XCJzdGF0ZS5zZWxlY3RlZFNlY3Rpb25JZCA9PT0gc2VjdGlvbi5pZFwiXHJcbiAgICAgICAgICAgICAgICAgICAgW3NlbGVjdGVkRmllbGRLZXldPVwic3RhdGUuc2VsZWN0ZWRGaWVsZEtleVwiXHJcbiAgICAgICAgICAgICAgICAgICAgKHNlY3Rpb25VcGRhdGUpPVwiXHJcbiAgICAgICAgICAgICAgICAgICAgICBzdGF0ZVNlcnZpY2UudXBkYXRlU2VjdGlvbihzZWN0aW9uLmlkLCAkZXZlbnQpXHJcbiAgICAgICAgICAgICAgICAgICAgXCJcclxuICAgICAgICAgICAgICAgICAgICAoc2VjdGlvbkRlbGV0ZSk9XCJvblNlY3Rpb25EZWxldGUoc2VjdGlvbi5pZClcIlxyXG4gICAgICAgICAgICAgICAgICAgIChzZWN0aW9uRHVwbGljYXRlKT1cIm9uU2VjdGlvbkR1cGxpY2F0ZShzZWN0aW9uLmlkKVwiXHJcbiAgICAgICAgICAgICAgICAgICAgKGZpZWxkU2VsZWN0KT1cIm9uRmllbGRTZWxlY3Qoc2VjdGlvbi5pZCwgJGV2ZW50KVwiXHJcbiAgICAgICAgICAgICAgICAgICAgKGZpZWxkRHVwbGljYXRlKT1cIm9uRmllbGREdXBsaWNhdGUoc2VjdGlvbi5pZCwgJGV2ZW50KVwiXHJcbiAgICAgICAgICAgICAgICAgICAgKGZpZWxkRGVsZXRlKT1cIm9uRmllbGREZWxldGUoc2VjdGlvbi5pZCwgJGV2ZW50KVwiXHJcbiAgICAgICAgICAgICAgICAgICAgKGZpZWxkRHJvcCk9XCJvbkZpZWxkRHJvcCgkZXZlbnQpXCJcclxuICAgICAgICAgICAgICAgICAgLz5cclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICBAaWYgKHN0YXRlLnNjaGVtYS5zZWN0aW9ucy5sZW5ndGggPT09IDApIHtcclxuICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImVtcHR5LXN0YXRlXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgPGx1Y2lkZS1pY29uXHJcbiAgICAgICAgICAgICAgICAgICAgICBuYW1lPVwibGF5b3V0LXRlbXBsYXRlXCJcclxuICAgICAgICAgICAgICAgICAgICAgIFtzaXplXT1cIjY0XCJcclxuICAgICAgICAgICAgICAgICAgICA+PC9sdWNpZGUtaWNvbj5cclxuICAgICAgICAgICAgICAgICAgICA8aDM+TmVzc3VuYSBzZXppb25lIHByZXNlbnRlPC9oMz5cclxuICAgICAgICAgICAgICAgICAgICA8cD5cclxuICAgICAgICAgICAgICAgICAgICAgIENsaWNjYSBzdSBcIlNlemlvbmVcIiBuZWxsYSB0b29sYmFyIHBlciBhZ2dpdW5nZXJlIGxhIHByaW1hXHJcbiAgICAgICAgICAgICAgICAgICAgICBzZXppb25lXHJcbiAgICAgICAgICAgICAgICAgICAgPC9wPlxyXG4gICAgICAgICAgICAgICAgICAgIDx1aS1idXR0b25cclxuICAgICAgICAgICAgICAgICAgICAgIGxhYmVsPVwiQWdnaXVuZ2kgUHJpbWEgU2V6aW9uZVwiXHJcbiAgICAgICAgICAgICAgICAgICAgICB2YXJpYW50PVwicHJpbWFyeVwiXHJcbiAgICAgICAgICAgICAgICAgICAgICBpY29uPVwicGx1c1wiXHJcbiAgICAgICAgICAgICAgICAgICAgICAoY2xpY2spPVwib25BZGRTZWN0aW9uKClcIlxyXG4gICAgICAgICAgICAgICAgICAgIC8+XHJcbiAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICA8L2Rpdj5cclxuXHJcbiAgICAgICAgICAgIDwhLS0gQ29uZmlnIHBhbmVsIChzaWRlYmFyIGRlc3RyYSkgLS0+XHJcbiAgICAgICAgICAgIDxkaXZcclxuICAgICAgICAgICAgICBjbGFzcz1cImVkaXRvci1zaWRlYmFyIHJpZ2h0XCJcclxuICAgICAgICAgICAgICBbc3R5bGUud2lkdGgucHhdPVwicmlnaHRTaWRlYmFyV2lkdGhcIlxyXG4gICAgICAgICAgICA+XHJcbiAgICAgICAgICAgICAgPGRpdlxyXG4gICAgICAgICAgICAgICAgY2xhc3M9XCJyZXNpemUtaGFuZGxlXCJcclxuICAgICAgICAgICAgICAgIFtjbGFzcy5yZXNpemluZ109XCJpc1Jlc2l6aW5nXCJcclxuICAgICAgICAgICAgICAgIChtb3VzZWRvd24pPVwib25SZXNpemVTdGFydCgkZXZlbnQpXCJcclxuICAgICAgICAgICAgICA+PC9kaXY+XHJcbiAgICAgICAgICAgICAgPHVpLWVkaXRvci1maWVsZC1jb25maWctcGFuZWxcclxuICAgICAgICAgICAgICAgIFtmaWVsZF09XCJzZWxlY3RlZEZpZWxkXCJcclxuICAgICAgICAgICAgICAgIFthdmFpbGFibGVGaWVsZHNdPVwiYXZhaWxhYmxlRmllbGRzXCJcclxuICAgICAgICAgICAgICAgIChmaWVsZFVwZGF0ZSk9XCJcclxuICAgICAgICAgICAgICAgICAgb25GaWVsZFVwZGF0ZShcclxuICAgICAgICAgICAgICAgICAgICBzZWxlY3RlZEZpZWxkU2VjdGlvbklkISxcclxuICAgICAgICAgICAgICAgICAgICBzdGF0ZS5zZWxlY3RlZEZpZWxkS2V5ISxcclxuICAgICAgICAgICAgICAgICAgICAkZXZlbnRcclxuICAgICAgICAgICAgICAgICAgKVxyXG4gICAgICAgICAgICAgICAgXCJcclxuICAgICAgICAgICAgICAvPlxyXG4gICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgIDwvbWF0LXRhYj5cclxuXHJcbiAgICAgICAgPCEtLSBUYWIgUHJldmlldyAtLT5cclxuICAgICAgICA8bWF0LXRhYiBsYWJlbD1cIkFudGVwcmltYVwiPlxyXG4gICAgICAgICAgPHVpLWVkaXRvci1wcmV2aWV3LWNvbnRhaW5lclxyXG4gICAgICAgICAgICBbc2NoZW1hXT1cInN0YXRlLnNjaGVtYVwiXHJcbiAgICAgICAgICAgIFtrZXldPVwicHJldmlld0tleVwiXHJcbiAgICAgICAgICAgIChyZWZyZXNoKT1cInJlZnJlc2hQcmV2aWV3KClcIlxyXG4gICAgICAgICAgLz5cclxuICAgICAgICA8L21hdC10YWI+XHJcbiAgICAgIDwvbWF0LXRhYi1ncm91cD5cclxuICAgIDwvZGl2PlxyXG4gIGAsXHJcbiAgc3R5bGVzOiBbXHJcbiAgICBgXHJcbiAgICAgIEB1c2UgJy4uLy4uLy4uL2NvcmUvdG9rZW5zL21peGlucycgYXMgdWk7XHJcblxyXG4gICAgICAuZWRpdG9yLXJvb3Qge1xyXG4gICAgICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICAgICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcclxuICAgICAgICBoZWlnaHQ6IDEwMHZoO1xyXG4gICAgICAgIGJhY2tncm91bmQ6IHZhcigtLXVpLWNvbG9yLWJnLXN1YnRsZSk7XHJcblxyXG4gICAgICAgICYuZGlhbG9nLW1vZGUge1xyXG4gICAgICAgICAgaGVpZ2h0OiAxMDAlO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgICAgLmVkaXRvci1kaWFsb2ctaGVhZGVyIHtcclxuICAgICAgICBkaXNwbGF5OiBmbGV4O1xyXG4gICAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgICAgICAganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuO1xyXG4gICAgICAgIHBhZGRpbmc6IHZhcigtLXVpLXNwYWNpbmctMykgdmFyKC0tdWktc3BhY2luZy00KTtcclxuICAgICAgICBiYWNrZ3JvdW5kOiB2YXIoLS11aS1jb2xvci1zdXJmYWNlKTtcclxuICAgICAgICBib3JkZXItYm90dG9tOiAxcHggc29saWQgdmFyKC0tdWktY29sb3ItYm9yZGVyKTtcclxuICAgICAgICBib3gtc2hhZG93OiB2YXIoLS11aS1zaGFkb3ctc20pO1xyXG5cclxuICAgICAgICBoMiB7XHJcbiAgICAgICAgICBtYXJnaW46IDA7XHJcbiAgICAgICAgICBmb250LXNpemU6IHZhcigtLXVpLWZvbnQtc2l6ZS1sZyk7XHJcbiAgICAgICAgICBmb250LXdlaWdodDogNTAwO1xyXG4gICAgICAgICAgY29sb3I6IHZhcigtLXVpLWNvbG9yLXRleHQpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLyogU3RpbGUgcGVyIGlsIHB1bHNhbnRlIGRpIGNoaXVzdXJhIChnZXN0aXRvIGRhIFVpQnV0dG9uKSAqL1xyXG4gICAgICB9XHJcblxyXG4gICAgICAuZWRpdG9yLXRhYnMge1xyXG4gICAgICAgIGZsZXg6IDE7XHJcbiAgICAgICAgZGlzcGxheTogZmxleDtcclxuICAgICAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xyXG4gICAgICAgIG92ZXJmbG93OiBoaWRkZW47XHJcblxyXG4gICAgICAgIC8qIFN0aWxlIGludGVzdGF6aW9uZSB0YWIgKi9cclxuICAgICAgICA6Om5nLWRlZXAgLm1hdC1tZGMtdGFiLWhlYWRlciB7XHJcbiAgICAgICAgICBiYWNrZ3JvdW5kOiB2YXIoLS11aS1jb2xvci1zdXJmYWNlKTtcclxuICAgICAgICAgIGJvcmRlci1ib3R0b206IDFweCBzb2xpZCB2YXIoLS11aS1jb2xvci1ib3JkZXIpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLyogU3RpbGUgZXRpY2hldHRhIHRhYiAqL1xyXG4gICAgICAgIDo6bmctZGVlcCAubWF0LW1kYy10YWIgLm1kYy10YWJfX3RleHQtbGFiZWwge1xyXG4gICAgICAgICAgY29sb3I6IHZhcigtLXVpLWNvbG9yLXRleHQtc2Vjb25kYXJ5KTtcclxuICAgICAgICAgIGZvbnQtd2VpZ2h0OiA1MDA7XHJcbiAgICAgICAgICBmb250LXNpemU6IHZhcigtLXVpLWZvbnQtc2l6ZS1zbSk7XHJcbiAgICAgICAgICBsZXR0ZXItc3BhY2luZzogMC4wMmVtO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLyogVGFiIGF0dGl2bzogdGVzdG8gZXZpZGVuemlhdG8gKi9cclxuICAgICAgICA6Om5nLWRlZXAgLm1hdC1tZGMtdGFiLm1kYy10YWItLWFjdGl2ZSAubWRjLXRhYl9fdGV4dC1sYWJlbCB7XHJcbiAgICAgICAgICBjb2xvcjogdmFyKC0tdWktY29sb3ItcHJpbWFyeSk7XHJcbiAgICAgICAgICBmb250LXdlaWdodDogNjAwO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLyogSW5kaWNhdG9yZSB0YWIgYXR0aXZvIChpbmsgYmFyKSAqL1xyXG4gICAgICAgIDo6bmctZGVlcCAubWF0LW1kYy10YWItaGVhZGVyIC5tZGMtdGFiLWluZGljYXRvcl9fY29udGVudC0tdW5kZXJsaW5lIHtcclxuICAgICAgICAgIGJvcmRlci1jb2xvcjogdmFyKC0tdWktY29sb3ItcHJpbWFyeSk7XHJcbiAgICAgICAgICBib3JkZXItd2lkdGg6IDNweDtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIDo6bmctZGVlcCAubWF0LW1kYy10YWItYm9keS13cmFwcGVyIHtcclxuICAgICAgICAgIGZsZXg6IDE7XHJcbiAgICAgICAgICBvdmVyZmxvdzogaGlkZGVuO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgOjpuZy1kZWVwIC5tYXQtbWRjLXRhYi1ib2R5IHtcclxuICAgICAgICAgIGhlaWdodDogMTAwJTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIDo6bmctZGVlcCAubWF0LW1kYy10YWItYm9keS1jb250ZW50IHtcclxuICAgICAgICAgIGhlaWdodDogMTAwJTtcclxuICAgICAgICAgIG92ZXJmbG93OiBoaWRkZW47XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcblxyXG4gICAgICAuZWRpdG9yLWxheW91dCB7XHJcbiAgICAgICAgZGlzcGxheTogZmxleDtcclxuICAgICAgICBoZWlnaHQ6IDEwMCU7XHJcbiAgICAgICAgb3ZlcmZsb3c6IGhpZGRlbjtcclxuICAgICAgfVxyXG5cclxuICAgICAgLmVkaXRvci1zaWRlYmFyIHtcclxuICAgICAgICBoZWlnaHQ6IDEwMCU7XHJcbiAgICAgICAgb3ZlcmZsb3cteTogYXV0bztcclxuICAgICAgICBiYWNrZ3JvdW5kOiB2YXIoLS11aS1jb2xvci1zdXJmYWNlKTtcclxuICAgICAgICBmbGV4LXNocmluazogMDtcclxuXHJcbiAgICAgICAgJi5sZWZ0IHtcclxuICAgICAgICAgIHBvc2l0aW9uOiByZWxhdGl2ZTtcclxuICAgICAgICAgIGJvcmRlci1yaWdodDogMXB4IHNvbGlkIHZhcigtLXVpLWNvbG9yLWJvcmRlcik7XHJcbiAgICAgICAgICBtaW4td2lkdGg6IDIwMHB4O1xyXG4gICAgICAgICAgbWF4LXdpZHRoOiA1MDBweDtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICYucmlnaHQge1xyXG4gICAgICAgICAgcG9zaXRpb246IHJlbGF0aXZlO1xyXG4gICAgICAgICAgYm9yZGVyLWxlZnQ6IDFweCBzb2xpZCB2YXIoLS11aS1jb2xvci1ib3JkZXIpO1xyXG4gICAgICAgICAgbWluLXdpZHRoOiA0MDBweDtcclxuICAgICAgICAgIG1heC13aWR0aDogMTIwMHB4O1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgICAgLmVkaXRvci1tYWluIHtcclxuICAgICAgICBmbGV4OiAxO1xyXG4gICAgICAgIG1pbi13aWR0aDogMDtcclxuICAgICAgICBoZWlnaHQ6IDEwMCU7XHJcbiAgICAgICAgb3ZlcmZsb3cteTogYXV0bztcclxuICAgICAgICBwYWRkaW5nOiB2YXIoLS11aS1zcGFjaW5nLTQpO1xyXG4gICAgICAgIGJhY2tncm91bmQ6IHZhcigtLXVpLWNvbG9yLWJnLXN1YnRsZSk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC5zZWN0aW9ucy1jb250YWluZXIge1xyXG4gICAgICAgIG1heC13aWR0aDogMTIwMHB4O1xyXG4gICAgICAgIG1hcmdpbjogMCBhdXRvO1xyXG4gICAgICAgIGRpc3BsYXk6IGZsZXg7XHJcbiAgICAgICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcclxuICAgICAgICBnYXA6IHZhcigtLXVpLXNwYWNpbmctNCk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC5yZXNpemUtaGFuZGxlIHtcclxuICAgICAgICBwb3NpdGlvbjogYWJzb2x1dGU7XHJcbiAgICAgICAgdG9wOiAwO1xyXG4gICAgICAgIGJvdHRvbTogMDtcclxuICAgICAgICB3aWR0aDogNnB4O1xyXG4gICAgICAgIGN1cnNvcjogZXctcmVzaXplO1xyXG4gICAgICAgIHotaW5kZXg6IDEwO1xyXG4gICAgICAgIHRyYW5zaXRpb246IGJhY2tncm91bmQtY29sb3IgdmFyKC0tdWktdHJhbnNpdGlvbi1mYXN0KTtcclxuXHJcbiAgICAgICAgLyogSGFuZGxlIHNpbmlzdHJvIChwZXIgc2lkZWJhciBkZXN0cmEpICovXHJcbiAgICAgICAgbGVmdDogMDtcclxuXHJcbiAgICAgICAgJjo6YmVmb3JlIHtcclxuICAgICAgICAgIGNvbnRlbnQ6ICcnO1xyXG4gICAgICAgICAgcG9zaXRpb246IGFic29sdXRlO1xyXG4gICAgICAgICAgbGVmdDogLTNweDtcclxuICAgICAgICAgIHRvcDogMDtcclxuICAgICAgICAgIGJvdHRvbTogMDtcclxuICAgICAgICAgIHdpZHRoOiAxMnB4O1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgJjpob3ZlcixcclxuICAgICAgICAmLnJlc2l6aW5nIHtcclxuICAgICAgICAgIGJhY2tncm91bmQtY29sb3I6IGNvbG9yLW1peChcclxuICAgICAgICAgICAgaW4gc3JnYixcclxuICAgICAgICAgICAgdmFyKC0tdWktY29sb3ItcHJpbWFyeSkgMzAlLFxyXG4gICAgICAgICAgICB0cmFuc3BhcmVudFxyXG4gICAgICAgICAgKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgICYucmVzaXppbmcge1xyXG4gICAgICAgICAgYmFja2dyb3VuZC1jb2xvcjogY29sb3ItbWl4KFxyXG4gICAgICAgICAgICBpbiBzcmdiLFxyXG4gICAgICAgICAgICB2YXIoLS11aS1jb2xvci1wcmltYXJ5KSA1MCUsXHJcbiAgICAgICAgICAgIHRyYW5zcGFyZW50XHJcbiAgICAgICAgICApO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgICAgLyogSGFuZGxlIGRlc3RybyAocGVyIHNpZGViYXIgc2luaXN0cmEpICovXHJcbiAgICAgIC5yZXNpemUtaGFuZGxlLS1yaWdodCB7XHJcbiAgICAgICAgbGVmdDogYXV0bztcclxuICAgICAgICByaWdodDogMDtcclxuXHJcbiAgICAgICAgJjo6YmVmb3JlIHtcclxuICAgICAgICAgIGxlZnQ6IGF1dG87XHJcbiAgICAgICAgICByaWdodDogLTNweDtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC5lbXB0eS1zdGF0ZSB7XHJcbiAgICAgICAgZGlzcGxheTogZmxleDtcclxuICAgICAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xyXG4gICAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XHJcbiAgICAgICAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XHJcbiAgICAgICAgcGFkZGluZzogdmFyKC0tdWktc3BhY2luZy0xMikgdmFyKC0tdWktc3BhY2luZy04KTtcclxuICAgICAgICB0ZXh0LWFsaWduOiBjZW50ZXI7XHJcbiAgICAgICAgY29sb3I6IHZhcigtLXVpLWNvbG9yLXRleHQtbXV0ZWQpO1xyXG5cclxuICAgICAgICBsdWNpZGUtaWNvbiB7XHJcbiAgICAgICAgICBvcGFjaXR5OiAwLjQ7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBoMyB7XHJcbiAgICAgICAgICBtYXJnaW46IDAgMCB2YXIoLS11aS1zcGFjaW5nLTIpIDA7XHJcbiAgICAgICAgICBmb250LXNpemU6IHZhcigtLXVpLWZvbnQtc2l6ZS14bCk7XHJcbiAgICAgICAgICBmb250LXdlaWdodDogNDAwO1xyXG4gICAgICAgICAgY29sb3I6IHZhcigtLXVpLWNvbG9yLXRleHQtc2Vjb25kYXJ5KTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHAge1xyXG4gICAgICAgICAgbWFyZ2luOiAwIDAgdmFyKC0tdWktc3BhY2luZy02KSAwO1xyXG4gICAgICAgICAgZm9udC1zaXplOiB2YXIoLS11aS1mb250LXNpemUtbWQpO1xyXG4gICAgICAgICAgY29sb3I6IHZhcigtLXVpLWNvbG9yLXRleHQtbXV0ZWQpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgICAgLyogUmVzcG9uc2l2ZSAqL1xyXG4gICAgICBAbWVkaWEgKG1heC13aWR0aDogMTI4MHB4KSB7XHJcbiAgICAgICAgLmVkaXRvci1zaWRlYmFyLmxlZnQge1xyXG4gICAgICAgICAgd2lkdGg6IDI1MHB4O1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgICAgQG1lZGlhIChtYXgtd2lkdGg6IDk2MHB4KSB7XHJcbiAgICAgICAgLmVkaXRvci1sYXlvdXQge1xyXG4gICAgICAgICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC5lZGl0b3Itc2lkZWJhciB7XHJcbiAgICAgICAgICAmLmxlZnQge1xyXG4gICAgICAgICAgICBkaXNwbGF5OiBub25lO1xyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICYucmlnaHQge1xyXG4gICAgICAgICAgICBwb3NpdGlvbjogZml4ZWQ7XHJcbiAgICAgICAgICAgIHJpZ2h0OiAwO1xyXG4gICAgICAgICAgICB0b3A6IDY0cHg7XHJcbiAgICAgICAgICAgIHdpZHRoOiAxMDAlICFpbXBvcnRhbnQ7XHJcbiAgICAgICAgICAgIG1heC13aWR0aDogMzUwcHg7XHJcbiAgICAgICAgICAgIGhlaWdodDogY2FsYygxMDB2aCAtIDY0cHgpO1xyXG4gICAgICAgICAgICB6LWluZGV4OiAxMDAwO1xyXG4gICAgICAgICAgICBib3gtc2hhZG93OiB2YXIoLS11aS1zaGFkb3ctbGcpO1xyXG4gICAgICAgICAgICB0cmFuc2Zvcm06IHRyYW5zbGF0ZVgoMTAwJSk7XHJcbiAgICAgICAgICAgIHRyYW5zaXRpb246IHRyYW5zZm9ybSB2YXIoLS11aS10cmFuc2l0aW9uLW5vcm1hbCk7XHJcblxyXG4gICAgICAgICAgICAucmVzaXplLWhhbmRsZSB7XHJcbiAgICAgICAgICAgICAgZGlzcGxheTogbm9uZTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgYCxcclxuICBdLFxyXG59KVxyXG5leHBvcnQgY2xhc3MgVWlGb3JtQnVpbGRlckVkaXRvckNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25EZXN0cm95IHtcclxuICAvKiogQGludGVybmFsIFNlcnZpemlvIHBlciBsbyBzdGF0byBkZWxsJ2VkaXRvci4gKi9cclxuICByZWFkb25seSBzdGF0ZVNlcnZpY2UgPSBpbmplY3QoVWlFZGl0b3JTdGF0ZVNlcnZpY2UpO1xyXG5cclxuICAvKiogQGludGVybmFsIFNlcnZpemlvIHBlciBsYSBwZXJzaXN0ZW56YS4gKi9cclxuICBwcml2YXRlIHJlYWRvbmx5IHBlcnNpc3RlbmNlU2VydmljZSA9IGluamVjdChVaUVkaXRvclBlcnNpc3RlbmNlU2VydmljZSk7XHJcblxyXG4gIC8qKiBAaW50ZXJuYWwgRmFjdG9yeSBwZXIgaSBjYW1waS4gKi9cclxuICBwcml2YXRlIHJlYWRvbmx5IGZpZWxkRmFjdG9yeSA9IGluamVjdChVaUVkaXRvckZpZWxkRmFjdG9yeVNlcnZpY2UpO1xyXG5cclxuICAvKiogQGludGVybmFsIFNuYWNrIGJhciBwZXIgaSBtZXNzYWdnaS4gKi9cclxuICBwcml2YXRlIHJlYWRvbmx5IHNuYWNrQmFyID0gaW5qZWN0KE1hdFNuYWNrQmFyKTtcclxuXHJcbiAgLyoqIEBpbnRlcm5hbCBDaGFuZ2UgZGV0ZWN0b3IuICovXHJcbiAgcHJpdmF0ZSByZWFkb25seSBjZHIgPSBpbmplY3QoQ2hhbmdlRGV0ZWN0b3JSZWYpO1xyXG5cclxuICAvKiogQGludGVybmFsIFN1YmplY3QgcGVyIGxhIGRpc3RydXppb25lLiAqL1xyXG4gIHByaXZhdGUgcmVhZG9ubHkgZGVzdHJveSQgPSBuZXcgU3ViamVjdDx2b2lkPigpO1xyXG5cclxuICAvKiogU3RhdG8gY29ycmVudGUgZGVsbCdlZGl0b3IuICovXHJcbiAgc3RhdGU6IFVpRWRpdG9yU3RhdGU7XHJcblxyXG4gIC8qKiBJbmRpY2UgZGVsIHRhYiBzZWxlemlvbmF0byAoMD1FZGl0b3IsIDE9UHJldmlldykuICovXHJcbiAgc2VsZWN0ZWRUYWJJbmRleCA9IDA7XHJcblxyXG4gIC8qKiBCcmVhZGNydW1iIGRpIG5hdmlnYXppb25lLiAqL1xyXG4gIGJyZWFkY3J1bWI6IFVpRWRpdG9yQnJlYWRjcnVtYkl0ZW1bXSA9IFtdO1xyXG5cclxuICAvKiogU2UgaWwgY29tcG9uZW50ZSBlIGFwZXJ0byBpbiBtb2RhbGl0YSBkaWFsb2cuICovXHJcbiAgaXNEaWFsb2dNb2RlID0gZmFsc2U7XHJcblxyXG4gIC8qKiBDaGlhdmUgcGVyIGZvcnphcmUgaWwgcmUtcmVuZGVyIGRlbCBwcmV2aWV3LiAqL1xyXG4gIHByZXZpZXdLZXkgPSAwO1xyXG5cclxuICAvKiogQ2FtcGkgZGlzcG9uaWJpbGkgcGVyIGxlIGNvbmRpemlvbmkgKGNhY2hlKS4gKi9cclxuICBhdmFpbGFibGVGaWVsZHM6IFVpRWRpdG9yQXZhaWxhYmxlRmllbGRbXSA9IFtdO1xyXG5cclxuICAvKiogTGFyZ2hlenphIGRlbGxhIHNpZGViYXIgc2luaXN0cmEgKHB4KS4gKi9cclxuICBsZWZ0U2lkZWJhcldpZHRoID0gMjgwO1xyXG5cclxuICAvKiogTGFyZ2hlenphIGRlbGxhIHNpZGViYXIgZGVzdHJhIChweCkuICovXHJcbiAgcmlnaHRTaWRlYmFyV2lkdGggPSA0NjA7XHJcblxyXG4gIC8qKiBTZSBlIGluIGNvcnNvIGlsIHJlc2l6ZSBkZWxsYSBzaWRlYmFyIGRlc3RyYS4gKi9cclxuICBpc1Jlc2l6aW5nID0gZmFsc2U7XHJcblxyXG4gIC8qKiBTZSBlIGluIGNvcnNvIGlsIHJlc2l6ZSBkZWxsYSBzaWRlYmFyIHNpbmlzdHJhLiAqL1xyXG4gIGlzUmVzaXppbmdMZWZ0ID0gZmFsc2U7XHJcblxyXG4gIC8qKiBAaW50ZXJuYWwgTGltaXRpIGRpIHJlc2l6ZSBzaWRlYmFyIGRlc3RyYS4gKi9cclxuICBwcml2YXRlIHJlYWRvbmx5IE1JTl9TSURFQkFSX1dJRFRIID0gNDAwO1xyXG4gIHByaXZhdGUgcmVhZG9ubHkgTUFYX1NJREVCQVJfV0lEVEggPSAxMjAwO1xyXG5cclxuICAvKiogQGludGVybmFsIExpbWl0aSBkaSByZXNpemUgc2lkZWJhciBzaW5pc3RyYS4gKi9cclxuICBwcml2YXRlIHJlYWRvbmx5IE1JTl9MRUZUX1NJREVCQVJfV0lEVEggPSAyMDA7XHJcbiAgcHJpdmF0ZSByZWFkb25seSBNQVhfTEVGVF9TSURFQkFSX1dJRFRIID0gNTAwO1xyXG5cclxuICBwcml2YXRlIHJlc2l6ZVN0YXJ0WCA9IDA7XHJcbiAgcHJpdmF0ZSByZXNpemVTdGFydFdpZHRoID0gMDtcclxuICBwcml2YXRlIHJlYWRvbmx5IFNJREVCQVJfV0lEVEhfS0VZID0gJ3VpLWVkaXRvci1yaWdodC1zaWRlYmFyLXdpZHRoJztcclxuICBwcml2YXRlIHJlYWRvbmx5IExFRlRfU0lERUJBUl9XSURUSF9LRVkgPSAndWktZWRpdG9yLWxlZnQtc2lkZWJhci13aWR0aCc7XHJcblxyXG4gIGNvbnN0cnVjdG9yKFxyXG4gICAgQE9wdGlvbmFsKCkgcHVibGljIGRpYWxvZ1JlZjogTWF0RGlhbG9nUmVmPFVpRm9ybUJ1aWxkZXJFZGl0b3JDb21wb25lbnQ+LFxyXG4gICAgQE9wdGlvbmFsKCkgQEluamVjdChNQVRfRElBTE9HX0RBVEEpIHB1YmxpYyBkaWFsb2dEYXRhOiBVaUVkaXRvckRpYWxvZ0RhdGEsXHJcbiAgKSB7XHJcbiAgICB0aGlzLnN0YXRlID0gdGhpcy5zdGF0ZVNlcnZpY2UuZ2V0Q3VycmVudFN0YXRlKCk7XHJcbiAgICB0aGlzLmlzRGlhbG9nTW9kZSA9ICEhdGhpcy5kaWFsb2dSZWY7XHJcblxyXG4gICAgLy8gQ2FyaWNhIHNjaGVtYSBpbml6aWFsZSBzZSBmb3JuaXRvIHZpYSBkaWFsb2cgZGF0YVxyXG4gICAgaWYgKHRoaXMuZGlhbG9nRGF0YT8uaW5pdGlhbFNjaGVtYSkge1xyXG4gICAgICB0aGlzLnN0YXRlU2VydmljZS5zZXRTY2hlbWEodGhpcy5kaWFsb2dEYXRhLmluaXRpYWxTY2hlbWEpO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMubG9hZFNpZGViYXJXaWR0aCgpO1xyXG4gIH1cclxuXHJcbiAgbmdPbkluaXQoKTogdm9pZCB7XHJcbiAgICAvLyBTb3R0b3Njcml6aW9uZSBhbGxvIHN0YXRvXHJcbiAgICB0aGlzLnN0YXRlU2VydmljZS5zdGF0ZSQucGlwZSh0YWtlVW50aWwodGhpcy5kZXN0cm95JCkpLnN1YnNjcmliZSgoc3RhdGUpID0+IHtcclxuICAgICAgdGhpcy5zdGF0ZSA9IHN0YXRlO1xyXG4gICAgICB0aGlzLnVwZGF0ZUJyZWFkY3J1bWIoKTtcclxuICAgICAgdGhpcy51cGRhdGVBdmFpbGFibGVGaWVsZHMoKTtcclxuICAgICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XHJcbiAgICB9KTtcclxuXHJcbiAgICAvLyBDb250cm9sbGEgc2FsdmF0YWdnaSBwcmVjZWRlbnRpIGRhIHJlY3VwZXJhcmVcclxuICAgIHRoaXMuY2hlY2tGb3JSZWNvdmVyeSgpO1xyXG5cclxuICAgIC8vIEF1dG8tc2F2ZSBvZ25pIDMwIHNlY29uZGlcclxuICAgIGludGVydmFsKDMwMDAwKVxyXG4gICAgICAucGlwZSh0YWtlVW50aWwodGhpcy5kZXN0cm95JCkpXHJcbiAgICAgIC5zdWJzY3JpYmUoKCkgPT4ge1xyXG4gICAgICAgIGlmICh0aGlzLnN0YXRlLmlzRGlydHkpIHtcclxuICAgICAgICAgIHRoaXMuYXV0b1NhdmUoKTtcclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XHJcbiAgICB0aGlzLmRlc3Ryb3kkLm5leHQoKTtcclxuICAgIHRoaXMuZGVzdHJveSQuY29tcGxldGUoKTtcclxuICB9XHJcblxyXG4gIC8vIOKUgOKUgOKUgCBUb29sYmFyIGFjdGlvbnMg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXHJcblxyXG4gIC8qKiBBZ2dpdW5nZSB1bmEgbnVvdmEgc2V6aW9uZS4gKi9cclxuICBvbkFkZFNlY3Rpb24oKTogdm9pZCB7XHJcbiAgICB0aGlzLnN0YXRlU2VydmljZS5hZGRTZWN0aW9uKCk7XHJcbiAgICB0aGlzLnNob3dNZXNzYWdlKCdTZXppb25lIGFnZ2l1bnRhJyk7XHJcbiAgfVxyXG5cclxuICAvKiogU2FsdmEgbmVsIGxvY2FsU3RvcmFnZS4gKi9cclxuICBvblNhdmUoKTogdm9pZCB7XHJcbiAgICB0cnkge1xyXG4gICAgICB0aGlzLnBlcnNpc3RlbmNlU2VydmljZS5zYXZlVG9Mb2NhbFN0b3JhZ2UodGhpcy5zdGF0ZS5zY2hlbWEpO1xyXG4gICAgICB0aGlzLnN0YXRlU2VydmljZS5tYXJrQXNTYXZlZCgpO1xyXG4gICAgICB0aGlzLnNob3dNZXNzYWdlKCdTYWx2YXRvIGNvbiBzdWNjZXNzbycpO1xyXG4gICAgfSBjYXRjaCAoZXJyb3I6IGFueSkge1xyXG4gICAgICB0aGlzLnNob3dNZXNzYWdlKGVycm9yLm1lc3NhZ2UgfHwgJ0Vycm9yZSBkdXJhbnRlIGlsIHNhbHZhdGFnZ2lvJywgdHJ1ZSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKiogQ3JlYSB1biBudW92byBmb3JtLiAqL1xyXG4gIG9uTmV3Rm9ybSgpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLnN0YXRlLmlzRGlydHkgJiYgIWNvbmZpcm0oJ0NpIHNvbm8gbW9kaWZpY2hlIG5vbiBzYWx2YXRlLiBDb250aW51YXJlPycpKSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuICAgIHRoaXMuc3RhdGVTZXJ2aWNlLnJlc2V0KCk7XHJcbiAgICB0aGlzLnNob3dNZXNzYWdlKCdOdW92byBmb3JtIGNyZWF0bycpO1xyXG4gIH1cclxuXHJcbiAgLyoqIEltcG9ydGEgZGEgZmlsZSBKU09OLiAqL1xyXG4gIG9uSW1wb3J0SnNvbigpOiB2b2lkIHtcclxuICAgIGNvbnN0IGlucHV0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnaW5wdXQnKTtcclxuICAgIGlucHV0LnR5cGUgPSAnZmlsZSc7XHJcbiAgICBpbnB1dC5hY2NlcHQgPSAnLmpzb24nO1xyXG5cclxuICAgIGlucHV0Lm9uY2hhbmdlID0gYXN5bmMgKGU6IGFueSkgPT4ge1xyXG4gICAgICBjb25zdCBmaWxlID0gZS50YXJnZXQuZmlsZXNbMF07XHJcbiAgICAgIGlmICghZmlsZSkgcmV0dXJuO1xyXG5cclxuICAgICAgdHJ5IHtcclxuICAgICAgICBjb25zdCBzY2hlbWEgPSBhd2FpdCB0aGlzLnBlcnNpc3RlbmNlU2VydmljZS5pbXBvcnRGcm9tSlNPTihmaWxlKTtcclxuICAgICAgICBpZiAodGhpcy5zdGF0ZS5pc0RpcnR5ICYmICFjb25maXJtKCdDaSBzb25vIG1vZGlmaWNoZSBub24gc2FsdmF0ZS4gU292cmFzY3JpdmVyZT8nKSkge1xyXG4gICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLnN0YXRlU2VydmljZS5zZXRTY2hlbWEoc2NoZW1hKTtcclxuICAgICAgICB0aGlzLnNob3dNZXNzYWdlKCdTY2hlbWEgaW1wb3J0YXRvIGNvbiBzdWNjZXNzbycpO1xyXG4gICAgICB9IGNhdGNoIChlcnJvcjogYW55KSB7XHJcbiAgICAgICAgdGhpcy5zaG93TWVzc2FnZShlcnJvci5tZXNzYWdlIHx8IFwiRXJyb3JlIGR1cmFudGUgbCdpbXBvcnRcIiwgdHJ1ZSk7XHJcbiAgICAgIH1cclxuICAgIH07XHJcblxyXG4gICAgaW5wdXQuY2xpY2soKTtcclxuICB9XHJcblxyXG4gIC8qKiBFc3BvcnRhIGNvbWUgZmlsZSBKU09OLiAqL1xyXG4gIG9uRXhwb3J0SnNvbigpOiB2b2lkIHtcclxuICAgIHRyeSB7XHJcbiAgICAgIGNvbnN0IHZhbGlkYXRpb24gPSB0aGlzLnN0YXRlU2VydmljZS52YWxpZGF0ZVNjaGVtYSgpO1xyXG4gICAgICBpZiAoIXZhbGlkYXRpb24udmFsaWQpIHtcclxuICAgICAgICBjb25zdCBtZXNzYWdlID0gYFNjaGVtYSBjb24gZXJyb3JpOlxcbiR7dmFsaWRhdGlvbi5lcnJvcnMubWFwKChlKSA9PiBlLm1lc3NhZ2UpLmpvaW4oJ1xcbicpfWA7XHJcbiAgICAgICAgaWYgKCFjb25maXJtKGAke21lc3NhZ2V9XFxuXFxuRXNwb3J0YXJlIGNvbXVucXVlP2ApKSByZXR1cm47XHJcbiAgICAgIH1cclxuICAgICAgdGhpcy5wZXJzaXN0ZW5jZVNlcnZpY2UuZXhwb3J0VG9KU09OKHRoaXMuc3RhdGUuc2NoZW1hKTtcclxuICAgICAgdGhpcy5zaG93TWVzc2FnZSgnU2NoZW1hIGVzcG9ydGF0byBjb24gc3VjY2Vzc28nKTtcclxuICAgIH0gY2F0Y2ggKGVycm9yOiBhbnkpIHtcclxuICAgICAgdGhpcy5zaG93TWVzc2FnZShlcnJvci5tZXNzYWdlIHx8IFwiRXJyb3JlIGR1cmFudGUgbCdleHBvcnRcIiwgdHJ1ZSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKiogUHVsaXNjZSB0dXR0byBsbyBzY2hlbWEuICovXHJcbiAgb25DbGVhcigpOiB2b2lkIHtcclxuICAgIGlmICghY29uZmlybSgnVnVvaSBkYXZ2ZXJvIGVsaW1pbmFyZSB0dXR0bz8gUXVlc3RhIGF6aW9uZSBub24gcHVvIGVzc2VyZSBhbm51bGxhdGEuJykpIHJldHVybjtcclxuICAgIHRoaXMucGVyc2lzdGVuY2VTZXJ2aWNlLmNyZWF0ZUJhY2t1cCh0aGlzLnN0YXRlLnNjaGVtYSk7XHJcbiAgICB0aGlzLnN0YXRlU2VydmljZS5jbGVhclNjaGVtYSgpO1xyXG4gICAgdGhpcy5zaG93TWVzc2FnZSgnU2NoZW1hIHB1bGl0bycpO1xyXG4gIH1cclxuXHJcbiAgLy8g4pSA4pSA4pSAIFNlemlvbmkg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXHJcblxyXG4gIG9uU2VjdGlvbkR1cGxpY2F0ZShzZWN0aW9uSWQ6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgdGhpcy5zdGF0ZVNlcnZpY2UuZHVwbGljYXRlU2VjdGlvbihzZWN0aW9uSWQpO1xyXG4gICAgdGhpcy5zaG93TWVzc2FnZSgnU2V6aW9uZSBkdXBsaWNhdGEnKTtcclxuICB9XHJcblxyXG4gIG9uU2VjdGlvbkRlbGV0ZShzZWN0aW9uSWQ6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgaWYgKCFjb25maXJtKCdWdW9pIGRhdnZlcm8gZWxpbWluYXJlIHF1ZXN0YSBzZXppb25lPycpKSByZXR1cm47XHJcbiAgICB0aGlzLnN0YXRlU2VydmljZS5yZW1vdmVTZWN0aW9uKHNlY3Rpb25JZCk7XHJcbiAgICB0aGlzLnNob3dNZXNzYWdlKCdTZXppb25lIGVsaW1pbmF0YScpO1xyXG4gIH1cclxuXHJcbiAgLy8g4pSA4pSA4pSAIENhbXBpIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxyXG5cclxuICBvbkZpZWxkU2VsZWN0KHNlY3Rpb25JZDogc3RyaW5nLCBmaWVsZEtleTogc3RyaW5nKTogdm9pZCB7XHJcbiAgICB0aGlzLnN0YXRlU2VydmljZS5zZWxlY3RGaWVsZChzZWN0aW9uSWQsIGZpZWxkS2V5KTtcclxuICB9XHJcblxyXG4gIG9uRmllbGREdXBsaWNhdGUoc2VjdGlvbklkOiBzdHJpbmcsIGZpZWxkS2V5OiBzdHJpbmcpOiB2b2lkIHtcclxuICAgIHRoaXMuc3RhdGVTZXJ2aWNlLmR1cGxpY2F0ZUZpZWxkKHNlY3Rpb25JZCwgZmllbGRLZXkpO1xyXG4gICAgdGhpcy5zaG93TWVzc2FnZSgnQ2FtcG8gZHVwbGljYXRvJyk7XHJcbiAgfVxyXG5cclxuICBvbkZpZWxkRGVsZXRlKHNlY3Rpb25JZDogc3RyaW5nLCBmaWVsZEtleTogc3RyaW5nKTogdm9pZCB7XHJcbiAgICBpZiAoIWNvbmZpcm0oJ1Z1b2kgZGF2dmVybyBlbGltaW5hcmUgcXVlc3RvIGNhbXBvPycpKSByZXR1cm47XHJcbiAgICB0aGlzLnN0YXRlU2VydmljZS5yZW1vdmVGaWVsZChzZWN0aW9uSWQsIGZpZWxkS2V5KTtcclxuICAgIHRoaXMuc2hvd01lc3NhZ2UoJ0NhbXBvIGVsaW1pbmF0bycpO1xyXG4gIH1cclxuXHJcbiAgb25GaWVsZFVwZGF0ZShzZWN0aW9uSWQ6IHN0cmluZywgZmllbGRLZXk6IHN0cmluZywgdXBkYXRlczogUGFydGlhbDxVaUZvcm1GaWVsZERlc2NyaXB0b3I+KTogdm9pZCB7XHJcbiAgICB0aGlzLnN0YXRlU2VydmljZS51cGRhdGVGaWVsZChzZWN0aW9uSWQsIGZpZWxkS2V5LCB1cGRhdGVzKTtcclxuICB9XHJcblxyXG4gIC8qKiBHZXN0aXNjZSBpbCBkcm9wIGRpIHVuIGNhbXBvIChkYWxsYSBwYWxldHRlIG8gdHJhIHNlemlvbmkpLiAqL1xyXG4gIG9uRmllbGREcm9wKGV2ZW50OiBDZGtEcmFnRHJvcDxhbnk+KTogdm9pZCB7XHJcbiAgICBjb25zdCBwcmV2SWQgPSBldmVudC5wcmV2aW91c0NvbnRhaW5lci5pZDtcclxuXHJcbiAgICBpZiAocHJldklkLnN0YXJ0c1dpdGgoJ3BhbGV0dGUtJykpIHtcclxuICAgICAgLy8gRHJvcCBkYWxsYSBwYWxldHRlXHJcbiAgICAgIGNvbnN0IHBhbGV0dGVJdGVtOiBVaUVkaXRvckZpZWxkUGFsZXR0ZUl0ZW0gPSBldmVudC5pdGVtLmRhdGE7XHJcbiAgICAgIGNvbnN0IHNlY3Rpb246IFVpRm9ybVNlY3Rpb24gPSBldmVudC5jb250YWluZXIuZGF0YTtcclxuICAgICAgY29uc3QgbmV3RmllbGQgPSB0aGlzLmZpZWxkRmFjdG9yeS5jcmVhdGVEZWZhdWx0RmllbGQocGFsZXR0ZUl0ZW0udHlwZSk7XHJcbiAgICAgIHRoaXMuc3RhdGVTZXJ2aWNlLmFkZEZpZWxkQXRJbmRleChzZWN0aW9uLmlkLCBuZXdGaWVsZCwgZXZlbnQuY3VycmVudEluZGV4KTtcclxuICAgICAgdGhpcy5zaG93TWVzc2FnZShgQ2FtcG8gJHtwYWxldHRlSXRlbS5sYWJlbH0gYWdnaXVudG9gKTtcclxuICAgIH0gZWxzZSBpZiAoZXZlbnQucHJldmlvdXNDb250YWluZXIgIT09IGV2ZW50LmNvbnRhaW5lcikge1xyXG4gICAgICAvLyBTcG9zdGFtZW50byB0cmEgc2V6aW9uaVxyXG4gICAgICBjb25zdCBmaWVsZDogVWlGb3JtRmllbGREZXNjcmlwdG9yID0gZXZlbnQuaXRlbS5kYXRhO1xyXG4gICAgICBjb25zdCBmcm9tU2VjdGlvbjogVWlGb3JtU2VjdGlvbiA9IGV2ZW50LnByZXZpb3VzQ29udGFpbmVyLmRhdGE7XHJcbiAgICAgIGNvbnN0IHRvU2VjdGlvbjogVWlGb3JtU2VjdGlvbiA9IGV2ZW50LmNvbnRhaW5lci5kYXRhO1xyXG4gICAgICB0aGlzLnN0YXRlU2VydmljZS5tb3ZlRmllbGRCZXR3ZWVuU2VjdGlvbnMoZnJvbVNlY3Rpb24uaWQsIHRvU2VjdGlvbi5pZCwgZmllbGQua2V5LCBldmVudC5jdXJyZW50SW5kZXgpO1xyXG4gICAgICB0aGlzLnNob3dNZXNzYWdlKCdDYW1wbyBzcG9zdGF0bycpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgLy8gUmlvcmRpbm8gbmVsbGEgc3Rlc3NhIHNlemlvbmVcclxuICAgICAgY29uc3Qgc2VjdGlvbjogVWlGb3JtU2VjdGlvbiA9IGV2ZW50LmNvbnRhaW5lci5kYXRhO1xyXG4gICAgICB0aGlzLnN0YXRlU2VydmljZS5tb3ZlRmllbGRJblNlY3Rpb24oc2VjdGlvbi5pZCwgZXZlbnQucHJldmlvdXNJbmRleCwgZXZlbnQuY3VycmVudEluZGV4KTtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcclxuICB9XHJcblxyXG4gIC8vIOKUgOKUgOKUgCBDb21wdXRlZCBwcm9wZXJ0aWVzIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxyXG5cclxuICAvKiogQ2FtcG8gYXR0dWFsbWVudGUgc2VsZXppb25hdG8uICovXHJcbiAgZ2V0IHNlbGVjdGVkRmllbGQoKTogVWlGb3JtRmllbGREZXNjcmlwdG9yIHwgbnVsbCB7XHJcbiAgICBpZiAoIXRoaXMuc3RhdGUuc2VsZWN0ZWRGaWVsZEtleSkgcmV0dXJuIG51bGw7XHJcbiAgICByZXR1cm4gdGhpcy5zdGF0ZVNlcnZpY2UuZmluZEZpZWxkQnlLZXkodGhpcy5zdGF0ZS5zZWxlY3RlZEZpZWxkS2V5KTtcclxuICB9XHJcblxyXG4gIC8qKiBJRCBkZWxsYSBzZXppb25lIGRlbCBjYW1wbyBzZWxlemlvbmF0by4gKi9cclxuICBnZXQgc2VsZWN0ZWRGaWVsZFNlY3Rpb25JZCgpOiBzdHJpbmcgfCBudWxsIHtcclxuICAgIGlmICghdGhpcy5zdGF0ZS5zZWxlY3RlZEZpZWxkS2V5KSByZXR1cm4gbnVsbDtcclxuICAgIHJldHVybiB0aGlzLnN0YXRlU2VydmljZS5maW5kU2VjdGlvbkJ5RmllbGRLZXkodGhpcy5zdGF0ZS5zZWxlY3RlZEZpZWxkS2V5KT8uaWQgfHwgbnVsbDtcclxuICB9XHJcblxyXG4gIC8vIOKUgOKUgOKUgCBUYWIgLyBQcmV2aWV3IOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxyXG5cclxuICBvblRhYkNoYW5nZShpbmRleDogbnVtYmVyKTogdm9pZCB7XHJcbiAgICB0aGlzLnNlbGVjdGVkVGFiSW5kZXggPSBpbmRleDtcclxuICAgIGlmIChpbmRleCA9PT0gMSkgdGhpcy5yZWZyZXNoUHJldmlldygpO1xyXG4gIH1cclxuXHJcbiAgcmVmcmVzaFByZXZpZXcoKTogdm9pZCB7XHJcbiAgICB0aGlzLnByZXZpZXdLZXkrKztcclxuICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xyXG4gIH1cclxuXHJcbiAgLy8g4pSA4pSA4pSAIERpYWxvZyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcclxuXHJcbiAgLyoqIENoaXVkZSBsYSBtb2RhbGUgcmVzdGl0dWVuZG8gbG8gc2NoZW1hIGNvcnJlbnRlLiAqL1xyXG4gIGNsb3NlRGlhbG9nKCk6IHZvaWQge1xyXG4gICAgdGhpcy5kaWFsb2dSZWY/LmNsb3NlKHRoaXMuc3RhdGUuc2NoZW1hKTtcclxuICB9XHJcblxyXG4gIC8vIOKUgOKUgOKUgCBSZXNpemUgc2lkZWJhciDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcclxuXHJcbiAgb25SZXNpemVTdGFydChldmVudDogTW91c2VFdmVudCk6IHZvaWQge1xyXG4gICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcclxuICAgIHRoaXMuaXNSZXNpemluZyA9IHRydWU7XHJcbiAgICB0aGlzLnJlc2l6ZVN0YXJ0WCA9IGV2ZW50LmNsaWVudFg7XHJcbiAgICB0aGlzLnJlc2l6ZVN0YXJ0V2lkdGggPSB0aGlzLnJpZ2h0U2lkZWJhcldpZHRoO1xyXG5cclxuICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIHRoaXMub25SZXNpemVNb3ZlKTtcclxuICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCB0aGlzLm9uUmVzaXplRW5kKTtcclxuICAgIGRvY3VtZW50LmJvZHkuc3R5bGUuY3Vyc29yID0gJ2V3LXJlc2l6ZSc7XHJcbiAgICBkb2N1bWVudC5ib2R5LnN0eWxlLnVzZXJTZWxlY3QgPSAnbm9uZSc7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIG9uUmVzaXplTW92ZSA9IChldmVudDogTW91c2VFdmVudCk6IHZvaWQgPT4ge1xyXG4gICAgaWYgKCF0aGlzLmlzUmVzaXppbmcpIHJldHVybjtcclxuICAgIGNvbnN0IGRlbHRhID0gdGhpcy5yZXNpemVTdGFydFggLSBldmVudC5jbGllbnRYO1xyXG4gICAgdGhpcy5yaWdodFNpZGViYXJXaWR0aCA9IE1hdGgubWF4KFxyXG4gICAgICB0aGlzLk1JTl9TSURFQkFSX1dJRFRILFxyXG4gICAgICBNYXRoLm1pbih0aGlzLk1BWF9TSURFQkFSX1dJRFRILCB0aGlzLnJlc2l6ZVN0YXJ0V2lkdGggKyBkZWx0YSksXHJcbiAgICApO1xyXG4gICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XHJcbiAgfTtcclxuXHJcbiAgcHJpdmF0ZSBvblJlc2l6ZUVuZCA9ICgpOiB2b2lkID0+IHtcclxuICAgIGlmICghdGhpcy5pc1Jlc2l6aW5nKSByZXR1cm47XHJcbiAgICB0aGlzLmlzUmVzaXppbmcgPSBmYWxzZTtcclxuICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIHRoaXMub25SZXNpemVNb3ZlKTtcclxuICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCB0aGlzLm9uUmVzaXplRW5kKTtcclxuICAgIGRvY3VtZW50LmJvZHkuc3R5bGUuY3Vyc29yID0gJyc7XHJcbiAgICBkb2N1bWVudC5ib2R5LnN0eWxlLnVzZXJTZWxlY3QgPSAnJztcclxuICAgIHRoaXMuc2F2ZVNpZGViYXJXaWR0aCgpO1xyXG4gIH07XHJcblxyXG4gIC8vIOKUgOKUgOKUgCBSZXNpemUgc2lkZWJhciBzaW5pc3RyYSDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcclxuXHJcbiAgb25MZWZ0UmVzaXplU3RhcnQoZXZlbnQ6IE1vdXNlRXZlbnQpOiB2b2lkIHtcclxuICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICB0aGlzLmlzUmVzaXppbmdMZWZ0ID0gdHJ1ZTtcclxuICAgIHRoaXMucmVzaXplU3RhcnRYID0gZXZlbnQuY2xpZW50WDtcclxuICAgIHRoaXMucmVzaXplU3RhcnRXaWR0aCA9IHRoaXMubGVmdFNpZGViYXJXaWR0aDtcclxuXHJcbiAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLCB0aGlzLm9uTGVmdFJlc2l6ZU1vdmUpO1xyXG4gICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignbW91c2V1cCcsIHRoaXMub25MZWZ0UmVzaXplRW5kKTtcclxuICAgIGRvY3VtZW50LmJvZHkuc3R5bGUuY3Vyc29yID0gJ2V3LXJlc2l6ZSc7XHJcbiAgICBkb2N1bWVudC5ib2R5LnN0eWxlLnVzZXJTZWxlY3QgPSAnbm9uZSc7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIG9uTGVmdFJlc2l6ZU1vdmUgPSAoZXZlbnQ6IE1vdXNlRXZlbnQpOiB2b2lkID0+IHtcclxuICAgIGlmICghdGhpcy5pc1Jlc2l6aW5nTGVmdCkgcmV0dXJuO1xyXG4gICAgY29uc3QgZGVsdGEgPSBldmVudC5jbGllbnRYIC0gdGhpcy5yZXNpemVTdGFydFg7XHJcbiAgICB0aGlzLmxlZnRTaWRlYmFyV2lkdGggPSBNYXRoLm1heChcclxuICAgICAgdGhpcy5NSU5fTEVGVF9TSURFQkFSX1dJRFRILFxyXG4gICAgICBNYXRoLm1pbih0aGlzLk1BWF9MRUZUX1NJREVCQVJfV0lEVEgsIHRoaXMucmVzaXplU3RhcnRXaWR0aCArIGRlbHRhKSxcclxuICAgICk7XHJcbiAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcclxuICB9O1xyXG5cclxuICBwcml2YXRlIG9uTGVmdFJlc2l6ZUVuZCA9ICgpOiB2b2lkID0+IHtcclxuICAgIGlmICghdGhpcy5pc1Jlc2l6aW5nTGVmdCkgcmV0dXJuO1xyXG4gICAgdGhpcy5pc1Jlc2l6aW5nTGVmdCA9IGZhbHNlO1xyXG4gICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgdGhpcy5vbkxlZnRSZXNpemVNb3ZlKTtcclxuICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCB0aGlzLm9uTGVmdFJlc2l6ZUVuZCk7XHJcbiAgICBkb2N1bWVudC5ib2R5LnN0eWxlLmN1cnNvciA9ICcnO1xyXG4gICAgZG9jdW1lbnQuYm9keS5zdHlsZS51c2VyU2VsZWN0ID0gJyc7XHJcbiAgICB0aGlzLnNhdmVMZWZ0U2lkZWJhcldpZHRoKCk7XHJcbiAgfTtcclxuXHJcbiAgLy8g4pSA4pSA4pSAIFByaXZhdGUg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXHJcblxyXG4gIHByaXZhdGUgY2hlY2tGb3JSZWNvdmVyeSgpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLnBlcnNpc3RlbmNlU2VydmljZS5oYXNMb2NhbFN0b3JhZ2VEYXRhKCkpIHtcclxuICAgICAgY29uc3QgYWdlID0gdGhpcy5wZXJzaXN0ZW5jZVNlcnZpY2UuZ2V0TG9jYWxTdG9yYWdlQWdlKCk7XHJcbiAgICAgIGNvbnN0IG1lc3NhZ2UgPSBhZ2VcclxuICAgICAgICA/IGBUcm92YXRvIHNhbHZhdGFnZ2lvIGRlbCAke2FnZS50b0xvY2FsZVN0cmluZygnaXQtSVQnKX0uIFZ1b2kgcmVjdXBlcmFybG8/YFxyXG4gICAgICAgIDogJ1Ryb3ZhdG8gc2FsdmF0YWdnaW8gcHJlY2VkZW50ZS4gVnVvaSByZWN1cGVyYXJsbz8nO1xyXG5cclxuICAgICAgY29uc3QgcmVmID0gdGhpcy5zbmFja0Jhci5vcGVuKG1lc3NhZ2UsICdSZWN1cGVyYScsIHsgZHVyYXRpb246IDEwMDAwIH0pO1xyXG4gICAgICByZWYub25BY3Rpb24oKS5zdWJzY3JpYmUoKCkgPT4ge1xyXG4gICAgICAgIGNvbnN0IHNjaGVtYSA9IHRoaXMucGVyc2lzdGVuY2VTZXJ2aWNlLmxvYWRGcm9tTG9jYWxTdG9yYWdlKCk7XHJcbiAgICAgICAgaWYgKHNjaGVtYSkge1xyXG4gICAgICAgICAgdGhpcy5zdGF0ZVNlcnZpY2Uuc2V0U2NoZW1hKHNjaGVtYSk7XHJcbiAgICAgICAgICB0aGlzLnNob3dNZXNzYWdlKCdTY2hlbWEgcmVjdXBlcmF0bycpO1xyXG4gICAgICAgIH1cclxuICAgICAgfSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGF1dG9TYXZlKCk6IHZvaWQge1xyXG4gICAgdHJ5IHtcclxuICAgICAgdGhpcy5wZXJzaXN0ZW5jZVNlcnZpY2Uuc2F2ZVRvTG9jYWxTdG9yYWdlKHRoaXMuc3RhdGUuc2NoZW1hKTtcclxuICAgICAgdGhpcy5zdGF0ZVNlcnZpY2UubWFya0FzU2F2ZWQoKTtcclxuICAgIH0gY2F0Y2gge1xyXG4gICAgICAvLyBTaWxlbnppb3NvIHBlciBhdXRvLXNhdmVcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgdXBkYXRlQnJlYWRjcnVtYigpOiB2b2lkIHtcclxuICAgIHRoaXMuYnJlYWRjcnVtYiA9IFtcclxuICAgICAge1xyXG4gICAgICAgIGxhYmVsOiB0aGlzLnN0YXRlLnNjaGVtYS50aXRsZSB8fCAnRm9ybScsXHJcbiAgICAgICAgaWQ6IHRoaXMuc3RhdGUuc2NoZW1hLmlkLFxyXG4gICAgICAgIHR5cGU6ICdmb3JtJyxcclxuICAgICAgICBhY3RpdmU6ICF0aGlzLnN0YXRlLnNlbGVjdGVkU2VjdGlvbklkICYmICF0aGlzLnN0YXRlLnNlbGVjdGVkRmllbGRLZXksXHJcbiAgICAgIH0sXHJcbiAgICBdO1xyXG5cclxuICAgIGlmICh0aGlzLnN0YXRlLnNlbGVjdGVkU2VjdGlvbklkKSB7XHJcbiAgICAgIGNvbnN0IHNlY3Rpb24gPSB0aGlzLnN0YXRlLnNjaGVtYS5zZWN0aW9ucy5maW5kKChzKSA9PiBzLmlkID09PSB0aGlzLnN0YXRlLnNlbGVjdGVkU2VjdGlvbklkKTtcclxuICAgICAgaWYgKHNlY3Rpb24pIHtcclxuICAgICAgICB0aGlzLmJyZWFkY3J1bWIucHVzaCh7XHJcbiAgICAgICAgICBsYWJlbDogc2VjdGlvbi50aXRsZSB8fCAnU2V6aW9uZScsXHJcbiAgICAgICAgICBpZDogc2VjdGlvbi5pZCxcclxuICAgICAgICAgIHR5cGU6ICdzZWN0aW9uJyxcclxuICAgICAgICAgIGFjdGl2ZTogIXRoaXMuc3RhdGUuc2VsZWN0ZWRGaWVsZEtleSxcclxuICAgICAgICB9KTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGlmICh0aGlzLnN0YXRlLnNlbGVjdGVkRmllbGRLZXkpIHtcclxuICAgICAgY29uc3QgZmllbGQgPSB0aGlzLnN0YXRlU2VydmljZS5maW5kRmllbGRCeUtleSh0aGlzLnN0YXRlLnNlbGVjdGVkRmllbGRLZXkpO1xyXG4gICAgICBpZiAoZmllbGQpIHtcclxuICAgICAgICB0aGlzLmJyZWFkY3J1bWIucHVzaCh7XHJcbiAgICAgICAgICBsYWJlbDogZmllbGQubGFiZWwsXHJcbiAgICAgICAgICBpZDogZmllbGQua2V5LFxyXG4gICAgICAgICAgdHlwZTogJ2ZpZWxkJyxcclxuICAgICAgICAgIGFjdGl2ZTogdHJ1ZSxcclxuICAgICAgICB9KTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSB1cGRhdGVBdmFpbGFibGVGaWVsZHMoKTogdm9pZCB7XHJcbiAgICBjb25zdCBmaWVsZHM6IFVpRWRpdG9yQXZhaWxhYmxlRmllbGRbXSA9IFtdO1xyXG4gICAgdGhpcy5zdGF0ZS5zY2hlbWEuc2VjdGlvbnMuZm9yRWFjaCgoc2VjdGlvbikgPT4ge1xyXG4gICAgICBzZWN0aW9uLmZpZWxkcy5mb3JFYWNoKChmaWVsZCkgPT4ge1xyXG4gICAgICAgIGNvbnN0IGFmOiBVaUVkaXRvckF2YWlsYWJsZUZpZWxkID0ge1xyXG4gICAgICAgICAga2V5OiBmaWVsZC5rZXksXHJcbiAgICAgICAgICBsYWJlbDogZmllbGQubGFiZWwsXHJcbiAgICAgICAgICB0eXBlOiBmaWVsZC50eXBlLFxyXG4gICAgICAgIH07XHJcbiAgICAgICAgaWYgKGZpZWxkLm9wdGlvbnMgJiYgQXJyYXkuaXNBcnJheShmaWVsZC5vcHRpb25zKSAmJiBmaWVsZC5vcHRpb25zLmxlbmd0aCA+IDApIHtcclxuICAgICAgICAgIGFmLm9wdGlvbnMgPSBmaWVsZC5vcHRpb25zLm1hcCgob3B0KSA9PiAoe1xyXG4gICAgICAgICAgICB2YWx1ZTogb3B0LnZhbHVlLFxyXG4gICAgICAgICAgICBsYWJlbDogb3B0LmxhYmVsLFxyXG4gICAgICAgICAgfSkpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBmaWVsZHMucHVzaChhZik7XHJcbiAgICAgIH0pO1xyXG4gICAgfSk7XHJcbiAgICB0aGlzLmF2YWlsYWJsZUZpZWxkcyA9IGZpZWxkcztcclxuICB9XHJcblxyXG4gIHByaXZhdGUgc2hvd01lc3NhZ2UobWVzc2FnZTogc3RyaW5nLCBpc0Vycm9yID0gZmFsc2UpOiB2b2lkIHtcclxuICAgIHRoaXMuc25hY2tCYXIub3BlbihtZXNzYWdlLCAnQ2hpdWRpJywge1xyXG4gICAgICBkdXJhdGlvbjogMzAwMCxcclxuICAgICAgcGFuZWxDbGFzczogaXNFcnJvciA/IFsndWktc25hY2tiYXItZXJyb3InXSA6IFtdLFxyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGxvYWRTaWRlYmFyV2lkdGgoKTogdm9pZCB7XHJcbiAgICB0cnkge1xyXG4gICAgICBjb25zdCBzYXZlZFJpZ2h0ID0gbG9jYWxTdG9yYWdlLmdldEl0ZW0odGhpcy5TSURFQkFSX1dJRFRIX0tFWSk7XHJcbiAgICAgIGlmIChzYXZlZFJpZ2h0KSB7XHJcbiAgICAgICAgY29uc3QgdyA9IHBhcnNlSW50KHNhdmVkUmlnaHQsIDEwKTtcclxuICAgICAgICBpZiAoIWlzTmFOKHcpICYmIHcgPj0gdGhpcy5NSU5fU0lERUJBUl9XSURUSCAmJiB3IDw9IHRoaXMuTUFYX1NJREVCQVJfV0lEVEgpIHtcclxuICAgICAgICAgIHRoaXMucmlnaHRTaWRlYmFyV2lkdGggPSB3O1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgICBjb25zdCBzYXZlZExlZnQgPSBsb2NhbFN0b3JhZ2UuZ2V0SXRlbSh0aGlzLkxFRlRfU0lERUJBUl9XSURUSF9LRVkpO1xyXG4gICAgICBpZiAoc2F2ZWRMZWZ0KSB7XHJcbiAgICAgICAgY29uc3QgdyA9IHBhcnNlSW50KHNhdmVkTGVmdCwgMTApO1xyXG4gICAgICAgIGlmICghaXNOYU4odykgJiYgdyA+PSB0aGlzLk1JTl9MRUZUX1NJREVCQVJfV0lEVEggJiYgdyA8PSB0aGlzLk1BWF9MRUZUX1NJREVCQVJfV0lEVEgpIHtcclxuICAgICAgICAgIHRoaXMubGVmdFNpZGViYXJXaWR0aCA9IHc7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9IGNhdGNoIHtcclxuICAgICAgLy8gU2lsZW56aW9zb1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBzYXZlU2lkZWJhcldpZHRoKCk6IHZvaWQge1xyXG4gICAgdHJ5IHtcclxuICAgICAgbG9jYWxTdG9yYWdlLnNldEl0ZW0odGhpcy5TSURFQkFSX1dJRFRIX0tFWSwgdGhpcy5yaWdodFNpZGViYXJXaWR0aC50b1N0cmluZygpKTtcclxuICAgIH0gY2F0Y2gge1xyXG4gICAgICAvLyBTaWxlbnppb3NvXHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHNhdmVMZWZ0U2lkZWJhcldpZHRoKCk6IHZvaWQge1xyXG4gICAgdHJ5IHtcclxuICAgICAgbG9jYWxTdG9yYWdlLnNldEl0ZW0odGhpcy5MRUZUX1NJREVCQVJfV0lEVEhfS0VZLCB0aGlzLmxlZnRTaWRlYmFyV2lkdGgudG9TdHJpbmcoKSk7XHJcbiAgICB9IGNhdGNoIHtcclxuICAgICAgLy8gU2lsZW56aW9zb1xyXG4gICAgfVxyXG4gIH1cclxufVxyXG4iXX0=
|