@ogidor/dashboard 1.0.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.
@@ -0,0 +1,703 @@
1
+ import { Component, Input } from '@angular/core';
2
+ import { Subscription } from 'rxjs';
3
+ import * as i0 from "@angular/core";
4
+ import * as i1 from "./dashboard-state.service";
5
+ import * as i2 from "@angular/common";
6
+ import * as i3 from "@angular/forms";
7
+ import * as i4 from "angular-gridster2";
8
+ import * as i5 from "./widget-renderer.component";
9
+ const DEFAULT_THEME = {
10
+ backgroundColor: '#000000',
11
+ panelColor: '#1c1c1e',
12
+ widgetCardColor: '#2c2c2e',
13
+ chartForeColor: '#8e8e93',
14
+ accentColor: '#0a84ff',
15
+ dangerColor: '#ff453a',
16
+ chartColors: ['#0a84ff', '#30d158', '#ff9f0a', '#bf5af2', '#ff453a'],
17
+ fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif',
18
+ };
19
+ export class DashboardComponent {
20
+ constructor(stateService) {
21
+ this.stateService = stateService;
22
+ this.resolvedTheme = { ...DEFAULT_THEME };
23
+ this.wrapperStyles = {};
24
+ this.pages = [];
25
+ this.activePageId = '';
26
+ // ── Dialog state ──
27
+ this.dialogOpen = false;
28
+ this.dialogType = 'LINE';
29
+ this.dialogTitle = '';
30
+ this.dialogCategories = '';
31
+ this.dialogSeries = [{ name: 'Series 1', dataRaw: '' }];
32
+ this.dialogSlices = [
33
+ { label: 'Slice A', value: null },
34
+ { label: 'Slice B', value: null },
35
+ { label: 'Slice C', value: null },
36
+ ];
37
+ this.widgetTypes = [
38
+ { value: 'LINE', label: 'Line', icon: 'la-chart-area' },
39
+ { value: 'BAR', label: 'Bar', icon: 'la-chart-bar' },
40
+ { value: 'DONUT', label: 'Donut', icon: 'la-chart-pie' },
41
+ ];
42
+ this.subs = new Subscription();
43
+ // ── Edit dialog state ──
44
+ this.editDialogOpen = false;
45
+ this.editWidgetType = 'LINE';
46
+ this.editTitle = '';
47
+ this.editCardColor = '';
48
+ this.editColors = [];
49
+ this.editSeries = [];
50
+ this.editCategories = '';
51
+ this.editSlices = [];
52
+ this.DEFAULT_COLORS = ['#0a84ff', '#30d158', '#ff9f0a', '#bf5af2', '#ff453a'];
53
+ this.removeWidgetHandler = (id) => { this.stateService.removeWidget(id); };
54
+ }
55
+ ngOnChanges(changes) {
56
+ if (changes['theme'] || changes['initialLayout'])
57
+ this.applyTheme();
58
+ }
59
+ ngOnInit() {
60
+ this.applyTheme();
61
+ if (this.initialLayout) {
62
+ try {
63
+ this.stateService.loadLayout(JSON.parse(this.initialLayout));
64
+ }
65
+ catch (e) {
66
+ console.error('[Dashboard] Failed to parse initialLayout', e);
67
+ }
68
+ }
69
+ this.options = {
70
+ gridType: 'fit',
71
+ displayGrid: 'none',
72
+ pushItems: true,
73
+ draggable: { enabled: true },
74
+ resizable: { enabled: true },
75
+ minCols: 12, maxCols: 12,
76
+ minRows: 12, maxRows: 50,
77
+ margin: 20, outerMargin: true,
78
+ itemChangeCallback: (item) => {
79
+ this.stateService.updateWidgetPosition(this.activePageId, item.id, item.x, item.y, item.cols, item.rows);
80
+ }
81
+ };
82
+ this.subs.add(this.stateService.pages$.subscribe(pages => {
83
+ this.pages = pages;
84
+ this.updateActivePage();
85
+ }));
86
+ this.subs.add(this.stateService.activePageId$.subscribe(id => {
87
+ this.activePageId = id;
88
+ this.updateActivePage();
89
+ }));
90
+ }
91
+ ngOnDestroy() { this.subs.unsubscribe(); }
92
+ applyTheme() {
93
+ this.resolvedTheme = { ...DEFAULT_THEME, ...(this.theme ?? {}) };
94
+ this.wrapperStyles = {
95
+ '--dash-bg': this.resolvedTheme.backgroundColor,
96
+ '--dash-panel-bg': this.resolvedTheme.panelColor,
97
+ '--dash-card-bg': this.resolvedTheme.widgetCardColor,
98
+ '--dash-fore-color': this.resolvedTheme.chartForeColor,
99
+ '--dash-accent-color': this.resolvedTheme.accentColor,
100
+ '--dash-danger-color': this.resolvedTheme.dangerColor,
101
+ '--dash-font-family': this.resolvedTheme.fontFamily,
102
+ };
103
+ }
104
+ updateActivePage() {
105
+ this.activePage = this.pages.find(p => p.id === this.activePageId);
106
+ }
107
+ // ── Page actions ──
108
+ onSelectPage(id) { this.stateService.setActivePage(id); }
109
+ onAddPage() {
110
+ const name = prompt('Enter workspace name:', `Workspace ${this.pages.length + 1}`);
111
+ if (name)
112
+ this.stateService.addPage(name);
113
+ }
114
+ onRemovePage(event, id) {
115
+ event.stopPropagation();
116
+ if (confirm('Remove this workspace?'))
117
+ this.stateService.removePage(id);
118
+ }
119
+ // ── Dialog ──
120
+ openDialog() {
121
+ this.dialogType = 'LINE';
122
+ this.dialogTitle = '';
123
+ this.dialogCategories = '';
124
+ this.dialogSeries = [{ name: 'Series 1', dataRaw: '' }];
125
+ this.dialogSlices = [
126
+ { label: 'Slice A', value: null },
127
+ { label: 'Slice B', value: null },
128
+ { label: 'Slice C', value: null },
129
+ ];
130
+ this.dialogOpen = true;
131
+ }
132
+ closeDialog() { this.dialogOpen = false; }
133
+ addSeries() { this.dialogSeries.push({ name: `Series ${this.dialogSeries.length + 1}`, dataRaw: '' }); }
134
+ removeSeries(i) { this.dialogSeries.splice(i, 1); }
135
+ addSlice() { this.dialogSlices.push({ label: `Slice ${this.dialogSlices.length + 1}`, value: null }); }
136
+ removeSlice(i) { this.dialogSlices.splice(i, 1); }
137
+ confirmAddWidget() {
138
+ const title = this.dialogTitle.trim();
139
+ if (!title)
140
+ return;
141
+ let data;
142
+ if (this.dialogType === 'DONUT') {
143
+ const validSlices = this.dialogSlices.filter(s => s.value !== null && s.label.trim());
144
+ data = {
145
+ series: validSlices.length
146
+ ? validSlices.map(s => Number(s.value))
147
+ : [30, 20, 50],
148
+ labels: validSlices.length
149
+ ? validSlices.map(s => s.label)
150
+ : ['A', 'B', 'C'],
151
+ };
152
+ }
153
+ else {
154
+ const parseNums = (raw) => raw.split(',').map(v => parseFloat(v.trim())).filter(n => !isNaN(n));
155
+ data = {
156
+ series: this.dialogSeries.map(s => ({
157
+ name: s.name || 'Series',
158
+ data: s.dataRaw.trim()
159
+ ? parseNums(s.dataRaw)
160
+ : Array.from({ length: 8 }, () => Math.floor(Math.random() * 100)),
161
+ })),
162
+ categories: this.dialogCategories.trim()
163
+ ? this.dialogCategories.split(',').map(c => c.trim())
164
+ : undefined,
165
+ };
166
+ }
167
+ this.stateService.addWidgetWithData(this.dialogType, title, data);
168
+ this.closeDialog();
169
+ }
170
+ openEditDialog(widget) {
171
+ this.editingWidget = widget;
172
+ this.editWidgetType = widget.type;
173
+ this.editTitle = widget.title;
174
+ this.editCardColor = widget.cardColor ?? this.resolvedTheme.widgetCardColor;
175
+ this.editColors = widget.colors?.length
176
+ ? [...widget.colors]
177
+ : [...this.resolvedTheme.chartColors];
178
+ if (widget.type === 'DONUT') {
179
+ const d = widget.data;
180
+ this.editSlices = d.series.map((v, i) => ({
181
+ label: d.labels?.[i] ?? `Slice ${i + 1}`,
182
+ value: v,
183
+ }));
184
+ this.editColors = this.editColors.slice(0, this.editSlices.length);
185
+ while (this.editColors.length < this.editSlices.length) {
186
+ this.editColors.push(this.DEFAULT_COLORS[this.editColors.length % this.DEFAULT_COLORS.length]);
187
+ }
188
+ }
189
+ else {
190
+ const d = widget.data;
191
+ this.editSeries = d.series.map((s) => ({ name: s.name, dataRaw: s.data.join(',') }));
192
+ this.editCategories = d.categories?.join(',') ?? '';
193
+ this.editColors = this.editColors.slice(0, this.editSeries.length);
194
+ while (this.editColors.length < this.editSeries.length) {
195
+ this.editColors.push(this.DEFAULT_COLORS[this.editColors.length % this.DEFAULT_COLORS.length]);
196
+ }
197
+ }
198
+ this.editDialogOpen = true;
199
+ }
200
+ closeEditDialog() { this.editDialogOpen = false; this.editingWidget = undefined; }
201
+ getEditSeriesLabel(i) {
202
+ if (this.editWidgetType === 'DONUT')
203
+ return this.editSlices[i]?.label || `Slice ${i + 1}`;
204
+ return this.editSeries[i]?.name || `Series ${i + 1}`;
205
+ }
206
+ addEditSeries() {
207
+ this.editSeries.push({ name: `Series ${this.editSeries.length + 1}`, dataRaw: '' });
208
+ this.editColors.push(this.DEFAULT_COLORS[this.editColors.length % this.DEFAULT_COLORS.length]);
209
+ }
210
+ removeEditSeries(i) { this.editSeries.splice(i, 1); this.editColors.splice(i, 1); }
211
+ addEditSlice() {
212
+ this.editSlices.push({ label: `Slice ${this.editSlices.length + 1}`, value: null });
213
+ this.editColors.push(this.DEFAULT_COLORS[this.editColors.length % this.DEFAULT_COLORS.length]);
214
+ }
215
+ removeEditSlice(i) { this.editSlices.splice(i, 1); this.editColors.splice(i, 1); }
216
+ confirmEditWidget() {
217
+ if (!this.editingWidget)
218
+ return;
219
+ const parseNums = (raw) => raw.split(',').map(v => parseFloat(v.trim())).filter(n => !isNaN(n));
220
+ let data;
221
+ if (this.editWidgetType === 'DONUT') {
222
+ data = {
223
+ series: this.editSlices.map(s => Number(s.value) || 0),
224
+ labels: this.editSlices.map(s => s.label),
225
+ };
226
+ }
227
+ else {
228
+ data = {
229
+ series: this.editSeries.map(s => ({
230
+ name: s.name || 'Series',
231
+ data: s.dataRaw.trim() ? parseNums(s.dataRaw) : [],
232
+ })),
233
+ categories: this.editCategories.trim()
234
+ ? this.editCategories.split(',').map(c => c.trim())
235
+ : undefined,
236
+ };
237
+ }
238
+ this.stateService.updateWidgetMeta(this.editingWidget.id, {
239
+ title: this.editTitle.trim() || this.editingWidget.title,
240
+ colors: [...this.editColors],
241
+ cardColor: this.editCardColor,
242
+ data,
243
+ });
244
+ this.closeEditDialog();
245
+ }
246
+ // ── Widget actions ──
247
+ onAddWidget(type) { this.stateService.addWidget(type); }
248
+ updateWidgetData(widgetId, data) {
249
+ this.stateService.updateWidgetData(widgetId, data);
250
+ }
251
+ serializeLayout() { return this.stateService.serializeLayout(); }
252
+ }
253
+ DashboardComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: DashboardComponent, deps: [{ token: i1.DashboardStateService }], target: i0.ɵɵFactoryTarget.Component });
254
+ DashboardComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: DashboardComponent, selector: "app-dashboard", inputs: { initialLayout: "initialLayout", theme: "theme" }, usesOnChanges: true, ngImport: i0, template: `
255
+ <div class="dashboard-wrapper" [ngStyle]="wrapperStyles">
256
+ <main class="main-content">
257
+
258
+ <!-- ── Header ── -->
259
+ <header class="dashboard-header">
260
+ <!-- Tabs -->
261
+ <div class="tabs-container">
262
+ <div
263
+ *ngFor="let page of pages"
264
+ class="tab"
265
+ [class.active]="page.id === activePageId"
266
+ (click)="onSelectPage(page.id)"
267
+ >
268
+ <span class="tab-name">{{ page.name }}</span>
269
+ <button class="tab-close" *ngIf="pages.length > 1" (click)="onRemovePage($event, page.id)">
270
+ <i class="la la-times"></i>
271
+ </button>
272
+ </div>
273
+ <button class="btn-add-page" (click)="onAddPage()" title="New workspace">
274
+ <i class="la la-plus"></i>
275
+ </button>
276
+ </div>
277
+
278
+ <!-- Add Widget button -->
279
+ <button class="btn-add-widget" (click)="openDialog()" title="Add widget">
280
+ <i class="la la-plus"></i>
281
+ <span>Add Widget</span>
282
+ </button>
283
+ </header>
284
+
285
+ <!-- ── Grid ── -->
286
+ <div class="grid-container">
287
+ <gridster [options]="options">
288
+ <gridster-item [item]="widget" *ngFor="let widget of activePage?.widgets">
289
+ <app-widget-renderer
290
+ [widget]="widget"
291
+ [onRemoveWidget]="removeWidgetHandler"
292
+ [theme]="resolvedTheme"
293
+ (editRequested)="openEditDialog($event)"
294
+ ></app-widget-renderer>
295
+ </gridster-item>
296
+ </gridster>
297
+ </div>
298
+ </main>
299
+ </div>
300
+
301
+ <!-- ── Add Widget Dialog ── -->
302
+ <div class="dialog-backdrop" *ngIf="dialogOpen" (click)="closeDialog()"></div>
303
+ <div class="dialog" *ngIf="dialogOpen">
304
+ <div class="dialog-header">
305
+ <span class="dialog-title">Add Widget</span>
306
+ <button class="dialog-close" (click)="closeDialog()"><i class="la la-times"></i></button>
307
+ </div>
308
+
309
+ <div class="dialog-body">
310
+
311
+ <!-- Chart type picker -->
312
+ <div class="field-group">
313
+ <label class="field-label">Chart type</label>
314
+ <div class="type-picker">
315
+ <button
316
+ *ngFor="let t of widgetTypes"
317
+ class="type-btn"
318
+ [class.selected]="dialogType === t.value"
319
+ (click)="dialogType = t.value"
320
+ >
321
+ <i [class]="'la ' + t.icon"></i>
322
+ <span>{{ t.label }}</span>
323
+ </button>
324
+ </div>
325
+ </div>
326
+
327
+ <!-- Title -->
328
+ <div class="field-group">
329
+ <label class="field-label">Title</label>
330
+ <input class="field-input" [(ngModel)]="dialogTitle" placeholder="My Chart" />
331
+ </div>
332
+
333
+ <!-- Series (LINE / BAR) -->
334
+ <ng-container *ngIf="dialogType !== 'DONUT'">
335
+ <div class="field-group">
336
+ <div class="field-row-header">
337
+ <label class="field-label">Series</label>
338
+ <button class="btn-link" (click)="addSeries()"><i class="la la-plus"></i> Add series</button>
339
+ </div>
340
+ <div class="series-list">
341
+ <div class="series-row" *ngFor="let s of dialogSeries; let i = index">
342
+ <input class="field-input series-name" [(ngModel)]="s.name" placeholder="Series name" />
343
+ <input class="field-input series-data" [(ngModel)]="s.dataRaw"
344
+ placeholder="Comma-separated values, e.g. 10,25,40" />
345
+ <button class="btn-remove-series" *ngIf="dialogSeries.length > 1" (click)="removeSeries(i)">
346
+ <i class="la la-times"></i>
347
+ </button>
348
+ </div>
349
+ </div>
350
+ </div>
351
+
352
+ <div class="field-group">
353
+ <label class="field-label">X-axis labels <span class="field-hint">(optional, comma-separated)</span></label>
354
+ <input class="field-input" [(ngModel)]="dialogCategories" placeholder="Jan,Feb,Mar,Apr" />
355
+ </div>
356
+ </ng-container>
357
+
358
+ <!-- Slices (DONUT) -->
359
+ <ng-container *ngIf="dialogType === 'DONUT'">
360
+ <div class="field-group">
361
+ <div class="field-row-header">
362
+ <label class="field-label">Slices</label>
363
+ <button class="btn-link" (click)="addSlice()"><i class="la la-plus"></i> Add slice</button>
364
+ </div>
365
+ <div class="series-list">
366
+ <div class="series-row" *ngFor="let sl of dialogSlices; let i = index">
367
+ <input class="field-input series-name" [(ngModel)]="sl.label" placeholder="Label" />
368
+ <input class="field-input series-data" [(ngModel)]="sl.value" type="number" placeholder="Value" />
369
+ <button class="btn-remove-series" *ngIf="dialogSlices.length > 1" (click)="removeSlice(i)">
370
+ <i class="la la-times"></i>
371
+ </button>
372
+ </div>
373
+ </div>
374
+ </div>
375
+ </ng-container>
376
+
377
+ </div>
378
+
379
+ <div class="dialog-footer">
380
+ <button class="btn-cancel" (click)="closeDialog()">Cancel</button>
381
+ <button class="btn-confirm" (click)="confirmAddWidget()" [disabled]="!dialogTitle.trim()">
382
+ <i class="la la-check"></i> Add Widget
383
+ </button>
384
+ </div>
385
+ </div>
386
+ <!-- ── Edit Widget Dialog ── -->
387
+ <div class="dialog-backdrop" *ngIf="editDialogOpen" (click)="closeEditDialog()"></div>
388
+ <div class="dialog" *ngIf="editDialogOpen">
389
+ <div class="dialog-header">
390
+ <span class="dialog-title">Edit Widget</span>
391
+ <button class="dialog-close" (click)="closeEditDialog()"><i class="la la-times"></i></button>
392
+ </div>
393
+
394
+ <div class="dialog-body">
395
+
396
+ <!-- Title -->
397
+ <div class="field-group">
398
+ <label class="field-label">Title</label>
399
+ <input class="field-input" [(ngModel)]="editTitle" placeholder="Chart title" />
400
+ </div>
401
+
402
+ <!-- Card background -->
403
+ <div class="field-group">
404
+ <label class="field-label">Card color</label>
405
+ <div class="color-row">
406
+ <input type="color" class="color-swatch" [(ngModel)]="editCardColor" />
407
+ <input class="field-input" [(ngModel)]="editCardColor" placeholder="#2c2c2e" />
408
+ </div>
409
+ </div>
410
+
411
+ <!-- Series colors -->
412
+ <div class="field-group">
413
+ <label class="field-label">Series colors</label>
414
+ <div class="color-list">
415
+ <div class="color-item" *ngFor="let c of editColors; let i = index">
416
+ <input type="color" class="color-swatch" [(ngModel)]="editColors[i]" />
417
+ <input class="field-input color-hex" [(ngModel)]="editColors[i]" placeholder="#0a84ff" />
418
+ <span class="color-label">{{ getEditSeriesLabel(i) }}</span>
419
+ </div>
420
+ </div>
421
+ </div>
422
+
423
+ <!-- Data: LINE / BAR -->
424
+ <ng-container *ngIf="editWidgetType !== 'DONUT'">
425
+ <div class="field-group">
426
+ <div class="field-row-header">
427
+ <label class="field-label">Series data</label>
428
+ <button class="btn-link" (click)="addEditSeries()"><i class="la la-plus"></i> Add</button>
429
+ </div>
430
+ <div class="series-list">
431
+ <div class="series-row" *ngFor="let s of editSeries; let i = index">
432
+ <input class="field-input series-name" [(ngModel)]="s.name" placeholder="Name" />
433
+ <input class="field-input series-data" [(ngModel)]="s.dataRaw" placeholder="10,20,30" />
434
+ <button class="btn-remove-series" *ngIf="editSeries.length > 1" (click)="removeEditSeries(i)">
435
+ <i class="la la-times"></i>
436
+ </button>
437
+ </div>
438
+ </div>
439
+ </div>
440
+ <div class="field-group">
441
+ <label class="field-label">X-axis labels <span class="field-hint">(optional, comma-separated)</span></label>
442
+ <input class="field-input" [(ngModel)]="editCategories" placeholder="Jan,Feb,Mar" />
443
+ </div>
444
+ </ng-container>
445
+
446
+ <!-- Data: DONUT -->
447
+ <ng-container *ngIf="editWidgetType === 'DONUT'">
448
+ <div class="field-group">
449
+ <div class="field-row-header">
450
+ <label class="field-label">Slices</label>
451
+ <button class="btn-link" (click)="addEditSlice()"><i class="la la-plus"></i> Add</button>
452
+ </div>
453
+ <div class="series-list">
454
+ <div class="series-row" *ngFor="let sl of editSlices; let i = index">
455
+ <input class="field-input series-name" [(ngModel)]="sl.label" placeholder="Label" />
456
+ <input class="field-input series-data" [(ngModel)]="sl.value" type="number" placeholder="Value" />
457
+ <button class="btn-remove-series" *ngIf="editSlices.length > 1" (click)="removeEditSlice(i)">
458
+ <i class="la la-times"></i>
459
+ </button>
460
+ </div>
461
+ </div>
462
+ </div>
463
+ </ng-container>
464
+
465
+ </div>
466
+
467
+ <div class="dialog-footer">
468
+ <button class="btn-cancel" (click)="closeEditDialog()">Cancel</button>
469
+ <button class="btn-confirm" (click)="confirmEditWidget()">
470
+ <i class="la la-check"></i> Save
471
+ </button>
472
+ </div>
473
+ </div>
474
+ `, isInline: true, styles: [":host{--dash-bg: #000000;--dash-panel-bg: #1c1c1e;--dash-card-bg: #2c2c2e;--dash-fore-color: #8e8e93;--dash-accent-color: #0a84ff;--dash-danger-color: #ff453a;--dash-font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif}.dashboard-wrapper{display:flex;height:100vh;width:100vw;overflow:hidden;padding:16px;box-sizing:border-box;background:var(--dash-bg);color:var(--dash-fore-color);font-family:var(--dash-font-family)}.main-content{flex:1;display:flex;flex-direction:column;overflow:hidden;border-radius:40px;padding:20px;background:var(--dash-panel-bg);box-shadow:0 10px 30px #00000080;border:1px solid rgba(255,255,255,.05)}.dashboard-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:20px;gap:12px}.tabs-container{display:flex;align-items:center;gap:8px;background:rgba(44,44,46,.6);backdrop-filter:blur(10px);border-radius:25px;padding:6px}.tab{display:flex;align-items:center;padding:8px 20px;border-radius:20px;cursor:pointer;font-size:14px;font-weight:500;color:var(--dash-fore-color);transition:all .3s cubic-bezier(.25,.8,.25,1)}.tab.active{background:#3a3a3c;color:#fff;box-shadow:0 2px 10px #0003}.tab:hover:not(.active){color:#e5e5ea;background:rgba(255,255,255,.05)}.tab-name{margin-right:8px}.tab-close{background:transparent;border:none;color:var(--dash-fore-color);padding:2px;font-size:12px;cursor:pointer;opacity:0;border-radius:50%;display:flex;align-items:center;justify-content:center;transition:all .2s}.tab-close:hover{color:var(--dash-danger-color);background:rgba(255,69,58,.2)}.tab:hover .tab-close{opacity:1}.btn-add-page{background:transparent;border:none;color:var(--dash-fore-color);padding:8px 16px;cursor:pointer;border-radius:20px;transition:all .2s}.btn-add-page:hover{color:var(--dash-accent-color);background:rgba(10,132,255,.1)}.btn-add-widget{display:flex;align-items:center;gap:6px;background:var(--dash-accent-color);border:none;color:#fff;font-size:14px;font-weight:600;padding:10px 20px;border-radius:22px;cursor:pointer;white-space:nowrap;transition:opacity .2s,transform .15s;box-shadow:0 4px 14px #0a84ff66}.btn-add-widget:hover{opacity:.9;transform:translateY(-1px)}.btn-add-widget:active{transform:translateY(0)}.grid-container{flex:1;overflow:auto;border-radius:24px;min-height:0}gridster{background:transparent;height:100%!important}.dialog-backdrop{position:fixed;inset:0;background:rgba(0,0,0,.6);backdrop-filter:blur(6px);z-index:900}.dialog{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);z-index:901;width:min(520px,calc(100vw - 32px));max-height:calc(100vh - 64px);display:flex;flex-direction:column;background:var(--dash-panel-bg);border-radius:28px;border:1px solid rgba(255,255,255,.1);box-shadow:0 24px 60px #000000b3;overflow:hidden}.dialog-header{display:flex;align-items:center;justify-content:space-between;padding:22px 24px 16px;border-bottom:1px solid rgba(255,255,255,.07)}.dialog-title{font-size:17px;font-weight:700;color:#fff}.dialog-close{background:rgba(255,255,255,.08);border:none;color:var(--dash-fore-color);width:30px;height:30px;border-radius:50%;display:flex;align-items:center;justify-content:center;cursor:pointer;font-size:14px;transition:all .2s}.dialog-close:hover{background:rgba(255,69,58,.25);color:var(--dash-danger-color)}.dialog-body{flex:1;overflow-y:auto;padding:20px 24px;display:flex;flex-direction:column;gap:20px}.field-group{display:flex;flex-direction:column;gap:8px}.field-label{font-size:13px;font-weight:600;color:var(--dash-fore-color);text-transform:uppercase;letter-spacing:.5px}.field-input{background:var(--dash-card-bg);border:1px solid rgba(255,255,255,.08);border-radius:12px;padding:10px 14px;color:#fff;font-size:14px;outline:none;width:100%;box-sizing:border-box}.field-input:focus{border-color:var(--dash-accent-color)}.type-picker{display:flex;gap:10px}.type-btn{flex:1;display:flex;flex-direction:column;align-items:center;gap:6px;padding:14px 10px;background:var(--dash-card-bg);border:2px solid transparent;border-radius:16px;color:var(--dash-fore-color);font-size:12px;font-weight:600;cursor:pointer;transition:all .2s}.type-btn.selected{border-color:var(--dash-accent-color);color:var(--dash-accent-color);background:rgba(10,132,255,.12)}.btn-link{background:transparent;border:none;color:var(--dash-accent-color);font-size:13px;font-weight:600;cursor:pointer}.dialog-footer{display:flex;align-items:center;justify-content:flex-end;gap:10px;padding:16px 24px 22px;border-top:1px solid rgba(255,255,255,.07)}.btn-cancel{background:transparent;border:1px solid rgba(255,255,255,.12);color:var(--dash-fore-color);padding:10px 20px;border-radius:20px;cursor:pointer}.btn-confirm{background:var(--dash-accent-color);border:none;color:#fff;padding:10px 22px;border-radius:20px;font-weight:600;cursor:pointer}.btn-confirm:disabled{opacity:.4;cursor:not-allowed}\n"], dependencies: [{ kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i4.GridsterComponent, selector: "gridster", inputs: ["options"] }, { kind: "component", type: i4.GridsterItemComponent, selector: "gridster-item", inputs: ["item"], outputs: ["itemInit", "itemChange", "itemResize"] }, { kind: "component", type: i5.WidgetRendererComponent, selector: "app-widget-renderer", inputs: ["widget", "onRemoveWidget", "theme"], outputs: ["editRequested"] }] });
475
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: DashboardComponent, decorators: [{
476
+ type: Component,
477
+ args: [{ selector: 'app-dashboard', template: `
478
+ <div class="dashboard-wrapper" [ngStyle]="wrapperStyles">
479
+ <main class="main-content">
480
+
481
+ <!-- ── Header ── -->
482
+ <header class="dashboard-header">
483
+ <!-- Tabs -->
484
+ <div class="tabs-container">
485
+ <div
486
+ *ngFor="let page of pages"
487
+ class="tab"
488
+ [class.active]="page.id === activePageId"
489
+ (click)="onSelectPage(page.id)"
490
+ >
491
+ <span class="tab-name">{{ page.name }}</span>
492
+ <button class="tab-close" *ngIf="pages.length > 1" (click)="onRemovePage($event, page.id)">
493
+ <i class="la la-times"></i>
494
+ </button>
495
+ </div>
496
+ <button class="btn-add-page" (click)="onAddPage()" title="New workspace">
497
+ <i class="la la-plus"></i>
498
+ </button>
499
+ </div>
500
+
501
+ <!-- Add Widget button -->
502
+ <button class="btn-add-widget" (click)="openDialog()" title="Add widget">
503
+ <i class="la la-plus"></i>
504
+ <span>Add Widget</span>
505
+ </button>
506
+ </header>
507
+
508
+ <!-- ── Grid ── -->
509
+ <div class="grid-container">
510
+ <gridster [options]="options">
511
+ <gridster-item [item]="widget" *ngFor="let widget of activePage?.widgets">
512
+ <app-widget-renderer
513
+ [widget]="widget"
514
+ [onRemoveWidget]="removeWidgetHandler"
515
+ [theme]="resolvedTheme"
516
+ (editRequested)="openEditDialog($event)"
517
+ ></app-widget-renderer>
518
+ </gridster-item>
519
+ </gridster>
520
+ </div>
521
+ </main>
522
+ </div>
523
+
524
+ <!-- ── Add Widget Dialog ── -->
525
+ <div class="dialog-backdrop" *ngIf="dialogOpen" (click)="closeDialog()"></div>
526
+ <div class="dialog" *ngIf="dialogOpen">
527
+ <div class="dialog-header">
528
+ <span class="dialog-title">Add Widget</span>
529
+ <button class="dialog-close" (click)="closeDialog()"><i class="la la-times"></i></button>
530
+ </div>
531
+
532
+ <div class="dialog-body">
533
+
534
+ <!-- Chart type picker -->
535
+ <div class="field-group">
536
+ <label class="field-label">Chart type</label>
537
+ <div class="type-picker">
538
+ <button
539
+ *ngFor="let t of widgetTypes"
540
+ class="type-btn"
541
+ [class.selected]="dialogType === t.value"
542
+ (click)="dialogType = t.value"
543
+ >
544
+ <i [class]="'la ' + t.icon"></i>
545
+ <span>{{ t.label }}</span>
546
+ </button>
547
+ </div>
548
+ </div>
549
+
550
+ <!-- Title -->
551
+ <div class="field-group">
552
+ <label class="field-label">Title</label>
553
+ <input class="field-input" [(ngModel)]="dialogTitle" placeholder="My Chart" />
554
+ </div>
555
+
556
+ <!-- Series (LINE / BAR) -->
557
+ <ng-container *ngIf="dialogType !== 'DONUT'">
558
+ <div class="field-group">
559
+ <div class="field-row-header">
560
+ <label class="field-label">Series</label>
561
+ <button class="btn-link" (click)="addSeries()"><i class="la la-plus"></i> Add series</button>
562
+ </div>
563
+ <div class="series-list">
564
+ <div class="series-row" *ngFor="let s of dialogSeries; let i = index">
565
+ <input class="field-input series-name" [(ngModel)]="s.name" placeholder="Series name" />
566
+ <input class="field-input series-data" [(ngModel)]="s.dataRaw"
567
+ placeholder="Comma-separated values, e.g. 10,25,40" />
568
+ <button class="btn-remove-series" *ngIf="dialogSeries.length > 1" (click)="removeSeries(i)">
569
+ <i class="la la-times"></i>
570
+ </button>
571
+ </div>
572
+ </div>
573
+ </div>
574
+
575
+ <div class="field-group">
576
+ <label class="field-label">X-axis labels <span class="field-hint">(optional, comma-separated)</span></label>
577
+ <input class="field-input" [(ngModel)]="dialogCategories" placeholder="Jan,Feb,Mar,Apr" />
578
+ </div>
579
+ </ng-container>
580
+
581
+ <!-- Slices (DONUT) -->
582
+ <ng-container *ngIf="dialogType === 'DONUT'">
583
+ <div class="field-group">
584
+ <div class="field-row-header">
585
+ <label class="field-label">Slices</label>
586
+ <button class="btn-link" (click)="addSlice()"><i class="la la-plus"></i> Add slice</button>
587
+ </div>
588
+ <div class="series-list">
589
+ <div class="series-row" *ngFor="let sl of dialogSlices; let i = index">
590
+ <input class="field-input series-name" [(ngModel)]="sl.label" placeholder="Label" />
591
+ <input class="field-input series-data" [(ngModel)]="sl.value" type="number" placeholder="Value" />
592
+ <button class="btn-remove-series" *ngIf="dialogSlices.length > 1" (click)="removeSlice(i)">
593
+ <i class="la la-times"></i>
594
+ </button>
595
+ </div>
596
+ </div>
597
+ </div>
598
+ </ng-container>
599
+
600
+ </div>
601
+
602
+ <div class="dialog-footer">
603
+ <button class="btn-cancel" (click)="closeDialog()">Cancel</button>
604
+ <button class="btn-confirm" (click)="confirmAddWidget()" [disabled]="!dialogTitle.trim()">
605
+ <i class="la la-check"></i> Add Widget
606
+ </button>
607
+ </div>
608
+ </div>
609
+ <!-- ── Edit Widget Dialog ── -->
610
+ <div class="dialog-backdrop" *ngIf="editDialogOpen" (click)="closeEditDialog()"></div>
611
+ <div class="dialog" *ngIf="editDialogOpen">
612
+ <div class="dialog-header">
613
+ <span class="dialog-title">Edit Widget</span>
614
+ <button class="dialog-close" (click)="closeEditDialog()"><i class="la la-times"></i></button>
615
+ </div>
616
+
617
+ <div class="dialog-body">
618
+
619
+ <!-- Title -->
620
+ <div class="field-group">
621
+ <label class="field-label">Title</label>
622
+ <input class="field-input" [(ngModel)]="editTitle" placeholder="Chart title" />
623
+ </div>
624
+
625
+ <!-- Card background -->
626
+ <div class="field-group">
627
+ <label class="field-label">Card color</label>
628
+ <div class="color-row">
629
+ <input type="color" class="color-swatch" [(ngModel)]="editCardColor" />
630
+ <input class="field-input" [(ngModel)]="editCardColor" placeholder="#2c2c2e" />
631
+ </div>
632
+ </div>
633
+
634
+ <!-- Series colors -->
635
+ <div class="field-group">
636
+ <label class="field-label">Series colors</label>
637
+ <div class="color-list">
638
+ <div class="color-item" *ngFor="let c of editColors; let i = index">
639
+ <input type="color" class="color-swatch" [(ngModel)]="editColors[i]" />
640
+ <input class="field-input color-hex" [(ngModel)]="editColors[i]" placeholder="#0a84ff" />
641
+ <span class="color-label">{{ getEditSeriesLabel(i) }}</span>
642
+ </div>
643
+ </div>
644
+ </div>
645
+
646
+ <!-- Data: LINE / BAR -->
647
+ <ng-container *ngIf="editWidgetType !== 'DONUT'">
648
+ <div class="field-group">
649
+ <div class="field-row-header">
650
+ <label class="field-label">Series data</label>
651
+ <button class="btn-link" (click)="addEditSeries()"><i class="la la-plus"></i> Add</button>
652
+ </div>
653
+ <div class="series-list">
654
+ <div class="series-row" *ngFor="let s of editSeries; let i = index">
655
+ <input class="field-input series-name" [(ngModel)]="s.name" placeholder="Name" />
656
+ <input class="field-input series-data" [(ngModel)]="s.dataRaw" placeholder="10,20,30" />
657
+ <button class="btn-remove-series" *ngIf="editSeries.length > 1" (click)="removeEditSeries(i)">
658
+ <i class="la la-times"></i>
659
+ </button>
660
+ </div>
661
+ </div>
662
+ </div>
663
+ <div class="field-group">
664
+ <label class="field-label">X-axis labels <span class="field-hint">(optional, comma-separated)</span></label>
665
+ <input class="field-input" [(ngModel)]="editCategories" placeholder="Jan,Feb,Mar" />
666
+ </div>
667
+ </ng-container>
668
+
669
+ <!-- Data: DONUT -->
670
+ <ng-container *ngIf="editWidgetType === 'DONUT'">
671
+ <div class="field-group">
672
+ <div class="field-row-header">
673
+ <label class="field-label">Slices</label>
674
+ <button class="btn-link" (click)="addEditSlice()"><i class="la la-plus"></i> Add</button>
675
+ </div>
676
+ <div class="series-list">
677
+ <div class="series-row" *ngFor="let sl of editSlices; let i = index">
678
+ <input class="field-input series-name" [(ngModel)]="sl.label" placeholder="Label" />
679
+ <input class="field-input series-data" [(ngModel)]="sl.value" type="number" placeholder="Value" />
680
+ <button class="btn-remove-series" *ngIf="editSlices.length > 1" (click)="removeEditSlice(i)">
681
+ <i class="la la-times"></i>
682
+ </button>
683
+ </div>
684
+ </div>
685
+ </div>
686
+ </ng-container>
687
+
688
+ </div>
689
+
690
+ <div class="dialog-footer">
691
+ <button class="btn-cancel" (click)="closeEditDialog()">Cancel</button>
692
+ <button class="btn-confirm" (click)="confirmEditWidget()">
693
+ <i class="la la-check"></i> Save
694
+ </button>
695
+ </div>
696
+ </div>
697
+ `, styles: [":host{--dash-bg: #000000;--dash-panel-bg: #1c1c1e;--dash-card-bg: #2c2c2e;--dash-fore-color: #8e8e93;--dash-accent-color: #0a84ff;--dash-danger-color: #ff453a;--dash-font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif}.dashboard-wrapper{display:flex;height:100vh;width:100vw;overflow:hidden;padding:16px;box-sizing:border-box;background:var(--dash-bg);color:var(--dash-fore-color);font-family:var(--dash-font-family)}.main-content{flex:1;display:flex;flex-direction:column;overflow:hidden;border-radius:40px;padding:20px;background:var(--dash-panel-bg);box-shadow:0 10px 30px #00000080;border:1px solid rgba(255,255,255,.05)}.dashboard-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:20px;gap:12px}.tabs-container{display:flex;align-items:center;gap:8px;background:rgba(44,44,46,.6);backdrop-filter:blur(10px);border-radius:25px;padding:6px}.tab{display:flex;align-items:center;padding:8px 20px;border-radius:20px;cursor:pointer;font-size:14px;font-weight:500;color:var(--dash-fore-color);transition:all .3s cubic-bezier(.25,.8,.25,1)}.tab.active{background:#3a3a3c;color:#fff;box-shadow:0 2px 10px #0003}.tab:hover:not(.active){color:#e5e5ea;background:rgba(255,255,255,.05)}.tab-name{margin-right:8px}.tab-close{background:transparent;border:none;color:var(--dash-fore-color);padding:2px;font-size:12px;cursor:pointer;opacity:0;border-radius:50%;display:flex;align-items:center;justify-content:center;transition:all .2s}.tab-close:hover{color:var(--dash-danger-color);background:rgba(255,69,58,.2)}.tab:hover .tab-close{opacity:1}.btn-add-page{background:transparent;border:none;color:var(--dash-fore-color);padding:8px 16px;cursor:pointer;border-radius:20px;transition:all .2s}.btn-add-page:hover{color:var(--dash-accent-color);background:rgba(10,132,255,.1)}.btn-add-widget{display:flex;align-items:center;gap:6px;background:var(--dash-accent-color);border:none;color:#fff;font-size:14px;font-weight:600;padding:10px 20px;border-radius:22px;cursor:pointer;white-space:nowrap;transition:opacity .2s,transform .15s;box-shadow:0 4px 14px #0a84ff66}.btn-add-widget:hover{opacity:.9;transform:translateY(-1px)}.btn-add-widget:active{transform:translateY(0)}.grid-container{flex:1;overflow:auto;border-radius:24px;min-height:0}gridster{background:transparent;height:100%!important}.dialog-backdrop{position:fixed;inset:0;background:rgba(0,0,0,.6);backdrop-filter:blur(6px);z-index:900}.dialog{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);z-index:901;width:min(520px,calc(100vw - 32px));max-height:calc(100vh - 64px);display:flex;flex-direction:column;background:var(--dash-panel-bg);border-radius:28px;border:1px solid rgba(255,255,255,.1);box-shadow:0 24px 60px #000000b3;overflow:hidden}.dialog-header{display:flex;align-items:center;justify-content:space-between;padding:22px 24px 16px;border-bottom:1px solid rgba(255,255,255,.07)}.dialog-title{font-size:17px;font-weight:700;color:#fff}.dialog-close{background:rgba(255,255,255,.08);border:none;color:var(--dash-fore-color);width:30px;height:30px;border-radius:50%;display:flex;align-items:center;justify-content:center;cursor:pointer;font-size:14px;transition:all .2s}.dialog-close:hover{background:rgba(255,69,58,.25);color:var(--dash-danger-color)}.dialog-body{flex:1;overflow-y:auto;padding:20px 24px;display:flex;flex-direction:column;gap:20px}.field-group{display:flex;flex-direction:column;gap:8px}.field-label{font-size:13px;font-weight:600;color:var(--dash-fore-color);text-transform:uppercase;letter-spacing:.5px}.field-input{background:var(--dash-card-bg);border:1px solid rgba(255,255,255,.08);border-radius:12px;padding:10px 14px;color:#fff;font-size:14px;outline:none;width:100%;box-sizing:border-box}.field-input:focus{border-color:var(--dash-accent-color)}.type-picker{display:flex;gap:10px}.type-btn{flex:1;display:flex;flex-direction:column;align-items:center;gap:6px;padding:14px 10px;background:var(--dash-card-bg);border:2px solid transparent;border-radius:16px;color:var(--dash-fore-color);font-size:12px;font-weight:600;cursor:pointer;transition:all .2s}.type-btn.selected{border-color:var(--dash-accent-color);color:var(--dash-accent-color);background:rgba(10,132,255,.12)}.btn-link{background:transparent;border:none;color:var(--dash-accent-color);font-size:13px;font-weight:600;cursor:pointer}.dialog-footer{display:flex;align-items:center;justify-content:flex-end;gap:10px;padding:16px 24px 22px;border-top:1px solid rgba(255,255,255,.07)}.btn-cancel{background:transparent;border:1px solid rgba(255,255,255,.12);color:var(--dash-fore-color);padding:10px 20px;border-radius:20px;cursor:pointer}.btn-confirm{background:var(--dash-accent-color);border:none;color:#fff;padding:10px 22px;border-radius:20px;font-weight:600;cursor:pointer}.btn-confirm:disabled{opacity:.4;cursor:not-allowed}\n"] }]
698
+ }], ctorParameters: function () { return [{ type: i1.DashboardStateService }]; }, propDecorators: { initialLayout: [{
699
+ type: Input
700
+ }], theme: [{
701
+ type: Input
702
+ }] } });
703
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGFzaGJvYXJkLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9hcHAvZGFzaGJvYXJkLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFxQixLQUFLLEVBQTRCLE1BQU0sZUFBZSxDQUFDO0FBSTlGLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxNQUFNLENBQUM7Ozs7Ozs7QUFFcEMsTUFBTSxhQUFhLEdBQTZCO0lBQzlDLGVBQWUsRUFBRSxTQUFTO0lBQzFCLFVBQVUsRUFBRSxTQUFTO0lBQ3JCLGVBQWUsRUFBRSxTQUFTO0lBQzFCLGNBQWMsRUFBRSxTQUFTO0lBQ3pCLFdBQVcsRUFBRSxTQUFTO0lBQ3RCLFdBQVcsRUFBRSxTQUFTO0lBQ3RCLFdBQVcsRUFBRSxDQUFDLFNBQVMsRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBRSxTQUFTLENBQUM7SUFDcEUsVUFBVSxFQUFFLHFGQUFxRjtDQUNsRyxDQUFDO0FBbVpGLE1BQU0sT0FBTyxrQkFBa0I7SUFnQzdCLFlBQW9CLFlBQW1DO1FBQW5DLGlCQUFZLEdBQVosWUFBWSxDQUF1QjtRQTVCdkQsa0JBQWEsR0FBNkIsRUFBRSxHQUFHLGFBQWEsRUFBRSxDQUFDO1FBQy9ELGtCQUFhLEdBQTJCLEVBQUUsQ0FBQztRQUczQyxVQUFLLEdBQVcsRUFBRSxDQUFDO1FBQ25CLGlCQUFZLEdBQVcsRUFBRSxDQUFDO1FBRzFCLHFCQUFxQjtRQUNyQixlQUFVLEdBQUcsS0FBSyxDQUFDO1FBQ25CLGVBQVUsR0FBZSxNQUFNLENBQUM7UUFDaEMsZ0JBQVcsR0FBRyxFQUFFLENBQUM7UUFDakIscUJBQWdCLEdBQUcsRUFBRSxDQUFDO1FBQ3RCLGlCQUFZLEdBQXdDLENBQUMsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLE9BQU8sRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQ3hGLGlCQUFZLEdBQThD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LGFBQWE7c0JBQXJCLEtBQUs7Z0JBQ0csS0FBSztzQkFBYixLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBPbkluaXQsIE9uRGVzdHJveSwgSW5wdXQsIE9uQ2hhbmdlcywgU2ltcGxlQ2hhbmdlcyB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgR3JpZHN0ZXJDb25maWcgfSBmcm9tICdhbmd1bGFyLWdyaWRzdGVyMic7XG5pbXBvcnQgeyBEYXNoYm9hcmRTdGF0ZVNlcnZpY2UgfSBmcm9tICcuL2Rhc2hib2FyZC1zdGF0ZS5zZXJ2aWNlJztcbmltcG9ydCB7IFBhZ2UsIFdpZGdldCwgV2lkZ2V0VHlwZSwgRGFzaGJvYXJkVGhlbWUsIExpbmVCYXJEYXRhLCBEb251dERhdGEgfSBmcm9tICcuL21vZGVscyc7XG5pbXBvcnQgeyBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcblxuY29uc3QgREVGQVVMVF9USEVNRTogUmVxdWlyZWQ8RGFzaGJvYXJkVGhlbWU+ID0ge1xuICBiYWNrZ3JvdW5kQ29sb3I6ICcjMDAwMDAwJyxcbiAgcGFuZWxDb2xvcjogJyMxYzFjMWUnLFxuICB3aWRnZXRDYXJkQ29sb3I6ICcjMmMyYzJlJyxcbiAgY2hhcnRGb3JlQ29sb3I6ICcjOGU4ZTkzJyxcbiAgYWNjZW50Q29sb3I6ICcjMGE4NGZmJyxcbiAgZGFuZ2VyQ29sb3I6ICcjZmY0NTNhJyxcbiAgY2hhcnRDb2xvcnM6IFsnIzBhODRmZicsICcjMzBkMTU4JywgJyNmZjlmMGEnLCAnI2JmNWFmMicsICcjZmY0NTNhJ10sXG4gIGZvbnRGYW1pbHk6ICctYXBwbGUtc3lzdGVtLCBCbGlua01hY1N5c3RlbUZvbnQsIFwiU2Vnb2UgVUlcIiwgUm9ib3RvLCBIZWx2ZXRpY2EsIEFyaWFsLCBzYW5zLXNlcmlmJyxcbn07XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2FwcC1kYXNoYm9hcmQnLFxuICB0ZW1wbGF0ZTogYFxuICAgIDxkaXYgY2xhc3M9XCJkYXNoYm9hcmQtd3JhcHBlclwiIFtuZ1N0eWxlXT1cIndyYXBwZXJTdHlsZXNcIj5cbiAgICAgIDxtYWluIGNsYXNzPVwibWFpbi1jb250ZW50XCI+XG5cbiAgICAgICAgPCEtLSDilIDilIAgSGVhZGVyIOKUgOKUgCAtLT5cbiAgICAgICAgPGhlYWRlciBjbGFzcz1cImRhc2hib2FyZC1oZWFkZXJcIj5cbiAgICAgICAgICA8IS0tIFRhYnMgLS0+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cInRhYnMtY29udGFpbmVyXCI+XG4gICAgICAgICAgICA8ZGl2XG4gICAgICAgICAgICAgICpuZ0Zvcj1cImxldCBwYWdlIG9mIHBhZ2VzXCJcbiAgICAgICAgICAgICAgY2xhc3M9XCJ0YWJcIlxuICAgICAgICAgICAgICBbY2xhc3MuYWN0aXZlXT1cInBhZ2UuaWQgPT09IGFjdGl2ZVBhZ2VJZFwiXG4gICAgICAgICAgICAgIChjbGljayk9XCJvblNlbGVjdFBhZ2UocGFnZS5pZClcIlxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cInRhYi1uYW1lXCI+e3sgcGFnZS5uYW1lIH19PC9zcGFuPlxuICAgICAgICAgICAgICA8YnV0dG9uIGNsYXNzPVwidGFiLWNsb3NlXCIgKm5nSWY9XCJwYWdlcy5sZW5ndGggPiAxXCIgKGNsaWNrKT1cIm9uUmVtb3ZlUGFnZSgkZXZlbnQsIHBhZ2UuaWQpXCI+XG4gICAgICAgICAgICAgICAgPGkgY2xhc3M9XCJsYSBsYS10aW1lc1wiPjwvaT5cbiAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDxidXR0b24gY2xhc3M9XCJidG4tYWRkLXBhZ2VcIiAoY2xpY2spPVwib25BZGRQYWdlKClcIiB0aXRsZT1cIk5ldyB3b3Jrc3BhY2VcIj5cbiAgICAgICAgICAgICAgPGkgY2xhc3M9XCJsYSBsYS1wbHVzXCI+PC9pPlxuICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICA8IS0tIEFkZCBXaWRnZXQgYnV0dG9uIC0tPlxuICAgICAgICAgIDxidXR0b24gY2xhc3M9XCJidG4tYWRkLXdpZGdldFwiIChjbGljayk9XCJvcGVuRGlhbG9nKClcIiB0aXRsZT1cIkFkZCB3aWRnZXRcIj5cbiAgICAgICAgICAgIDxpIGNsYXNzPVwibGEgbGEtcGx1c1wiPjwvaT5cbiAgICAgICAgICAgIDxzcGFuPkFkZCBXaWRnZXQ8L3NwYW4+XG4gICAgICAgICAgPC9idXR0b24+XG4gICAgICAgIDwvaGVhZGVyPlxuXG4gICAgICAgIDwhLS0g4pSA4pSAIEdyaWQg4pSA4pSAIC0tPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiZ3JpZC1jb250YWluZXJcIj5cbiAgICAgICAgICA8Z3JpZHN0ZXIgW29wdGlvbnNdPVwib3B0aW9uc1wiPlxuICAgICAgICAgICAgPGdyaWRzdGVyLWl0ZW0gW2l0ZW1dPVwid2lkZ2V0XCIgKm5nRm9yPVwibGV0IHdpZGdldCBvZiBhY3RpdmVQYWdlPy53aWRnZXRzXCI+XG4gICAgICAgICAgICAgIDxhcHAtd2lkZ2V0LXJlbmRlcmVyXG4gICAgICAgICAgICAgICAgW3dpZGdldF09XCJ3aWRnZXRcIlxuICAgICAgICAgICAgICAgIFtvblJlbW92ZVdpZGdldF09XCJyZW1vdmVXaWRnZXRIYW5kbGVyXCJcbiAgICAgICAgICAgICAgICBbdGhlbWVdPVwicmVzb2x2ZWRUaGVtZVwiXG4gICAgICAgICAgICAgICAgKGVkaXRSZXF1ZXN0ZWQpPVwib3BlbkVkaXREaWFsb2coJGV2ZW50KVwiXG4gICAgICAgICAgICAgID48L2FwcC13aWRnZXQtcmVuZGVyZXI+XG4gICAgICAgICAgICA8L2dyaWRzdGVyLWl0ZW0+XG4gICAgICAgICAgPC9ncmlkc3Rlcj5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L21haW4+XG4gICAgPC9kaXY+XG5cbiAgICA8IS0tIOKUgOKUgCBBZGQgV2lkZ2V0IERpYWxvZyDilIDilIAgLS0+XG4gICAgPGRpdiBjbGFzcz1cImRpYWxvZy1iYWNrZHJvcFwiICpuZ0lmPVwiZGlhbG9nT3BlblwiIChjbGljayk9XCJjbG9zZURpYWxvZygpXCI+PC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cImRpYWxvZ1wiICpuZ0lmPVwiZGlhbG9nT3BlblwiPlxuICAgICAgPGRpdiBjbGFzcz1cImRpYWxvZy1oZWFkZXJcIj5cbiAgICAgICAgPHNwYW4gY2xhc3M9XCJkaWFsb2ctdGl0bGVcIj5BZGQgV2lkZ2V0PC9zcGFuPlxuICAgICAgICA8YnV0dG9uIGNsYXNzPVwiZGlhbG9nLWNsb3NlXCIgKGNsaWNrKT1cImNsb3NlRGlhbG9nKClcIj48aSBjbGFzcz1cImxhIGxhLXRpbWVzXCI+PC9pPjwvYnV0dG9uPlxuICAgICAgPC9kaXY+XG5cbiAgICAgIDxkaXYgY2xhc3M9XCJkaWFsb2ctYm9keVwiPlxuXG4gICAgICAgIDwhLS0gQ2hhcnQgdHlwZSBwaWNrZXIgLS0+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJmaWVsZC1ncm91cFwiPlxuICAgICAgICAgIDxsYWJlbCBjbGFzcz1cImZpZWxkLWxhYmVsXCI+Q2hhcnQgdHlwZTwvbGFiZWw+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cInR5cGUtcGlja2VyXCI+XG4gICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgICpuZ0Zvcj1cImxldCB0IG9mIHdpZGdldFR5cGVzXCJcbiAgICAgICAgICAgICAgY2xhc3M9XCJ0eXBlLWJ0blwiXG4gICAgICAgICAgICAgIFtjbGFzcy5zZWxlY3RlZF09XCJkaWFsb2dUeXBlID09PSB0LnZhbHVlXCJcbiAgICAgICAgICAgICAgKGNsaWNrKT1cImRpYWxvZ1R5cGUgPSB0LnZhbHVlXCJcbiAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgPGkgW2NsYXNzXT1cIidsYSAnICsgdC5pY29uXCI+PC9pPlxuICAgICAgICAgICAgICA8c3Bhbj57eyB0LmxhYmVsIH19PC9zcGFuPlxuICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuXG4gICAgICAgIDwhLS0gVGl0bGUgLS0+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJmaWVsZC1ncm91cFwiPlxuICAgICAgICAgIDxsYWJlbCBjbGFzcz1cImZpZWxkLWxhYmVsXCI+VGl0bGU8L2xhYmVsPlxuICAgICAgICAgIDxpbnB1dCBjbGFzcz1cImZpZWxkLWlucHV0XCIgWyhuZ01vZGVsKV09XCJkaWFsb2dUaXRsZVwiIHBsYWNlaG9sZGVyPVwiTXkgQ2hhcnRcIiAvPlxuICAgICAgICA8L2Rpdj5cblxuICAgICAgICA8IS0tIFNlcmllcyAoTElORSAvIEJBUikgLS0+XG4gICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJkaWFsb2dUeXBlICE9PSAnRE9OVVQnXCI+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImZpZWxkLWdyb3VwXCI+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZmllbGQtcm93LWhlYWRlclwiPlxuICAgICAgICAgICAgICA8bGFiZWwgY2xhc3M9XCJmaWVsZC1sYWJlbFwiPlNlcmllczwvbGFiZWw+XG4gICAgICAgICAgICAgIDxidXR0b24gY2xhc3M9XCJidG4tbGlua1wiIChjbGljayk9XCJhZGRTZXJpZXMoKVwiPjxpIGNsYXNzPVwibGEgbGEtcGx1c1wiPjwvaT4gQWRkIHNlcmllczwvYnV0dG9uPlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwic2VyaWVzLWxpc3RcIj5cbiAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInNlcmllcy1yb3dcIiAqbmdGb3I9XCJsZXQgcyBvZiBkaWFsb2dTZXJpZXM7IGxldCBpID0gaW5kZXhcIj5cbiAgICAgICAgICAgICAgICA8aW5wdXQgY2xhc3M9XCJmaWVsZC1pbnB1dCBzZXJpZXMtbmFtZVwiIFsobmdNb2RlbCldPVwicy5uYW1lXCIgcGxhY2Vob2xkZXI9XCJTZXJpZXMgbmFtZVwiIC8+XG4gICAgICAgICAgICAgICAgPGlucHV0IGNsYXNzPVwiZmllbGQtaW5wdXQgc2VyaWVzLWRhdGFcIiBbKG5nTW9kZWwpXT1cInMuZGF0YVJhd1wiXG4gICAgICAgICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyPVwiQ29tbWEtc2VwYXJhdGVkIHZhbHVlcywgZS5nLiAxMCwyNSw0MFwiIC8+XG4gICAgICAgICAgICAgICAgPGJ1dHRvbiBjbGFzcz1cImJ0bi1yZW1vdmUtc2VyaWVzXCIgKm5nSWY9XCJkaWFsb2dTZXJpZXMubGVuZ3RoID4gMVwiIChjbGljayk9XCJyZW1vdmVTZXJpZXMoaSlcIj5cbiAgICAgICAgICAgICAgICAgIDxpIGNsYXNzPVwibGEgbGEtdGltZXNcIj48L2k+XG4gICAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiZmllbGQtZ3JvdXBcIj5cbiAgICAgICAgICAgIDxsYWJlbCBjbGFzcz1cImZpZWxkLWxhYmVsXCI+WC1heGlzIGxhYmVscyA8c3BhbiBjbGFzcz1cImZpZWxkLWhpbnRcIj4ob3B0aW9uYWwsIGNvbW1hLXNlcGFyYXRlZCk8L3NwYW4+PC9sYWJlbD5cbiAgICAgICAgICAgIDxpbnB1dCBjbGFzcz1cImZpZWxkLWlucHV0XCIgWyhuZ01vZGVsKV09XCJkaWFsb2dDYXRlZ29yaWVzXCIgcGxhY2Vob2xkZXI9XCJKYW4sRmViLE1hcixBcHJcIiAvPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L25nLWNvbnRhaW5lcj5cblxuICAgICAgICA8IS0tIFNsaWNlcyAoRE9OVVQpIC0tPlxuICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiZGlhbG9nVHlwZSA9PT0gJ0RPTlVUJ1wiPlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJmaWVsZC1ncm91cFwiPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZpZWxkLXJvdy1oZWFkZXJcIj5cbiAgICAgICAgICAgICAgPGxhYmVsIGNsYXNzPVwiZmllbGQtbGFiZWxcIj5TbGljZXM8L2xhYmVsPlxuICAgICAgICAgICAgICA8YnV0dG9uIGNsYXNzPVwiYnRuLWxpbmtcIiAoY2xpY2spPVwiYWRkU2xpY2UoKVwiPjxpIGNsYXNzPVwibGEgbGEtcGx1c1wiPjwvaT4gQWRkIHNsaWNlPC9idXR0b24+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzZXJpZXMtbGlzdFwiPlxuICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwic2VyaWVzLXJvd1wiICpuZ0Zvcj1cImxldCBzbCBvZiBkaWFsb2dTbGljZXM7IGxldCBpID0gaW5kZXhcIj5cbiAgICAgICAgICAgICAgICA8aW5wdXQgY2xhc3M9XCJmaWVsZC1pbnB1dCBzZXJpZXMtbmFtZVwiIFsobmdNb2RlbCldPVwic2wubGFiZWxcIiBwbGFjZWhvbGRlcj1cIkxhYmVsXCIgLz5cbiAgICAgICAgICAgICAgICA8aW5wdXQgY2xhc3M9XCJmaWVsZC1pbnB1dCBzZXJpZXMtZGF0YVwiIFsobmdNb2RlbCldPVwic2wudmFsdWVcIiB0eXBlPVwibnVtYmVyXCIgcGxhY2Vob2xkZXI9XCJWYWx1ZVwiIC8+XG4gICAgICAgICAgICAgICAgPGJ1dHRvbiBjbGFzcz1cImJ0bi1yZW1vdmUtc2VyaWVzXCIgKm5nSWY9XCJkaWFsb2dTbGljZXMubGVuZ3RoID4gMVwiIChjbGljayk9XCJyZW1vdmVTbGljZShpKVwiPlxuICAgICAgICAgICAgICAgICAgPGkgY2xhc3M9XCJsYSBsYS10aW1lc1wiPjwvaT5cbiAgICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9uZy1jb250YWluZXI+XG5cbiAgICAgIDwvZGl2PlxuXG4gICAgICA8ZGl2IGNsYXNzPVwiZGlhbG9nLWZvb3RlclwiPlxuICAgICAgICA8YnV0dG9uIGNsYXNzPVwiYnRuLWNhbmNlbFwiIChjbGljayk9XCJjbG9zZURpYWxvZygpXCI+Q2FuY2VsPC9idXR0b24+XG4gICAgICAgIDxidXR0b24gY2xhc3M9XCJidG4tY29uZmlybVwiIChjbGljayk9XCJjb25maXJtQWRkV2lkZ2V0KClcIiBbZGlzYWJsZWRdPVwiIWRpYWxvZ1RpdGxlLnRyaW0oKVwiPlxuICAgICAgICAgIDxpIGNsYXNzPVwibGEgbGEtY2hlY2tcIj48L2k+IEFkZCBXaWRnZXRcbiAgICAgICAgPC9idXR0b24+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgICA8IS0tIOKUgOKUgCBFZGl0IFdpZGdldCBEaWFsb2cg4pSA4pSAIC0tPlxuICAgIDxkaXYgY2xhc3M9XCJkaWFsb2ctYmFja2Ryb3BcIiAqbmdJZj1cImVkaXREaWFsb2dPcGVuXCIgKGNsaWNrKT1cImNsb3NlRWRpdERpYWxvZygpXCI+PC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cImRpYWxvZ1wiICpuZ0lmPVwiZWRpdERpYWxvZ09wZW5cIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJkaWFsb2ctaGVhZGVyXCI+XG4gICAgICAgIDxzcGFuIGNsYXNzPVwiZGlhbG9nLXRpdGxlXCI+RWRpdCBXaWRnZXQ8L3NwYW4+XG4gICAgICAgIDxidXR0b24gY2xhc3M9XCJkaWFsb2ctY2xvc2VcIiAoY2xpY2spPVwiY2xvc2VFZGl0RGlhbG9nKClcIj48aSBjbGFzcz1cImxhIGxhLXRpbWVzXCI+PC9pPjwvYnV0dG9uPlxuICAgICAgPC9kaXY+XG5cbiAgICAgIDxkaXYgY2xhc3M9XCJkaWFsb2ctYm9keVwiPlxuXG4gICAgICAgIDwhLS0gVGl0bGUgLS0+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJmaWVsZC1ncm91cFwiPlxuICAgICAgICAgIDxsYWJlbCBjbGFzcz1cImZpZWxkLWxhYmVsXCI+VGl0bGU8L2xhYmVsPlxuICAgICAgICAgIDxpbnB1dCBjbGFzcz1cImZpZWxkLWlucHV0XCIgWyhuZ01vZGVsKV09XCJlZGl0VGl0bGVcIiBwbGFjZWhvbGRlcj1cIkNoYXJ0IHRpdGxlXCIgLz5cbiAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgPCEtLSBDYXJkIGJhY2tncm91bmQgLS0+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJmaWVsZC1ncm91cFwiPlxuICAgICAgICAgIDxsYWJlbCBjbGFzcz1cImZpZWxkLWxhYmVsXCI+Q2FyZCBjb2xvcjwvbGFiZWw+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImNvbG9yLXJvd1wiPlxuICAgICAgICAgICAgPGlucHV0IHR5cGU9XCJjb2xvclwiIGNsYXNzPVwiY29sb3Itc3dhdGNoXCIgWyhuZ01vZGVsKV09XCJlZGl0Q2FyZENvbG9yXCIgLz5cbiAgICAgICAgICAgIDxpbnB1dCBjbGFzcz1cImZpZWxkLWlucHV0XCIgWyhuZ01vZGVsKV09XCJlZGl0Q2FyZENvbG9yXCIgcGxhY2Vob2xkZXI9XCIjMmMyYzJlXCIgLz5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgPCEtLSBTZXJpZXMgY29sb3JzIC0tPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiZmllbGQtZ3JvdXBcIj5cbiAgICAgICAgICA8bGFiZWwgY2xhc3M9XCJmaWVsZC1sYWJlbFwiPlNlcmllcyBjb2xvcnM8L2xhYmVsPlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJjb2xvci1saXN0XCI+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiY29sb3ItaXRlbVwiICpuZ0Zvcj1cImxldCBjIG9mIGVkaXRDb2xvcnM7IGxldCBpID0gaW5kZXhcIj5cbiAgICAgICAgICAgICAgPGlucHV0IHR5cGU9XCJjb2xvclwiIGNsYXNzPVwiY29sb3Itc3dhdGNoXCIgWyhuZ01vZGVsKV09XCJlZGl0Q29sb3JzW2ldXCIgLz5cbiAgICAgICAgICAgICAgPGlucHV0IGNsYXNzPVwiZmllbGQtaW5wdXQgY29sb3ItaGV4XCIgWyhuZ01vZGVsKV09XCJlZGl0Q29sb3JzW2ldXCIgcGxhY2Vob2xkZXI9XCIjMGE4NGZmXCIgLz5cbiAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJjb2xvci1sYWJlbFwiPnt7IGdldEVkaXRTZXJpZXNMYWJlbChpKSB9fTwvc3Bhbj5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cblxuICAgICAgICA8IS0tIERhdGE6IExJTkUgLyBCQVIgLS0+XG4gICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJlZGl0V2lkZ2V0VHlwZSAhPT0gJ0RPTlVUJ1wiPlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJmaWVsZC1ncm91cFwiPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZpZWxkLXJvdy1oZWFkZXJcIj5cbiAgICAgICAgICAgICAgPGxhYmVsIGNsYXNzPVwiZmllbGQtbGFiZWxcIj5TZXJpZXMgZGF0YTwvbGFiZWw+XG4gICAgICAgICAgICAgIDxidXR0b24gY2xhc3M9XCJidG4tbGlua1wiIChjbGljayk9XCJhZGRFZGl0U2VyaWVzKClcIj48aSBjbGFzcz1cImxhIGxhLXBsdXNcIj48L2k+IEFkZDwvYnV0dG9uPlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwic2VyaWVzLWxpc3RcIj5cbiAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInNlcmllcy1yb3dcIiAqbmdGb3I9XCJsZXQgcyBvZiBlZGl0U2VyaWVzOyBsZXQgaSA9IGluZGV4XCI+XG4gICAgICAgICAgICAgICAgPGlucHV0IGNsYXNzPVwiZmllbGQtaW5wdXQgc2VyaWVzLW5hbWVcIiBbKG5nTW9kZWwpXT1cInMubmFtZVwiIHBsYWNlaG9sZGVyPVwiTmFtZVwiIC8+XG4gICAgICAgICAgICAgICAgPGlucHV0IGNsYXNzPVwiZmllbGQtaW5wdXQgc2VyaWVzLWRhdGFcIiBbKG5nTW9kZWwpXT1cInMuZGF0YVJhd1wiIHBsYWNlaG9sZGVyPVwiMTAsMjAsMzBcIiAvPlxuICAgICAgICAgICAgICAgIDxidXR0b24gY2xhc3M9XCJidG4tcmVtb3ZlLXNlcmllc1wiICpuZ0lmPVwiZWRpdFNlcmllcy5sZW5ndGggPiAxXCIgKGNsaWNrKT1cInJlbW92ZUVkaXRTZXJpZXMoaSlcIj5cbiAgICAgICAgICAgICAgICAgIDxpIGNsYXNzPVwibGEgbGEtdGltZXNcIj48L2k+XG4gICAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImZpZWxkLWdyb3VwXCI+XG4gICAgICAgICAgICA8bGFiZWwgY2xhc3M9XCJmaWVsZC1sYWJlbFwiPlgtYXhpcyBsYWJlbHMgPHNwYW4gY2xhc3M9XCJmaWVsZC1oaW50XCI+KG9wdGlvbmFsLCBjb21tYS1zZXBhcmF0ZWQpPC9zcGFuPjwvbGFiZWw+XG4gICAgICAgICAgICA8aW5wdXQgY2xhc3M9XCJmaWVsZC1pbnB1dFwiIFsobmdNb2RlbCldPVwiZWRpdENhdGVnb3JpZXNcIiBwbGFjZWhvbGRlcj1cIkphbixGZWIsTWFyXCIgLz5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9uZy1jb250YWluZXI+XG5cbiAgICAgICAgPCEtLSBEYXRhOiBET05VVCAtLT5cbiAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cImVkaXRXaWRnZXRUeXBlID09PSAnRE9OVVQnXCI+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImZpZWxkLWdyb3VwXCI+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZmllbGQtcm93LWhlYWRlclwiPlxuICAgICAgICAgICAgICA8bGFiZWwgY2xhc3M9XCJmaWVsZC1sYWJlbFwiPlNsaWNlczwvbGFiZWw+XG4gICAgICAgICAgICAgIDxidXR0b24gY2xhc3M9XCJidG4tbGlua1wiIChjbGljayk9XCJhZGRFZGl0U2xpY2UoKVwiPjxpIGNsYXNzPVwibGEgbGEtcGx1c1wiPjwvaT4gQWRkPC9idXR0b24+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzZXJpZXMtbGlzdFwiPlxuICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwic2VyaWVzLXJvd1wiICpuZ0Zvcj1cImxldCBzbCBvZiBlZGl0U2xpY2VzOyBsZXQgaSA9IGluZGV4XCI+XG4gICAgICAgICAgICAgICAgPGlucHV0IGNsYXNzPVwiZmllbGQtaW5wdXQgc2VyaWVzLW5hbWVcIiBbKG5nTW9kZWwpXT1cInNsLmxhYmVsXCIgcGxhY2Vob2xkZXI9XCJMYWJlbFwiIC8+XG4gICAgICAgICAgICAgICAgPGlucHV0IGNsYXNzPVwiZmllbGQtaW5wdXQgc2VyaWVzLWRhdGFcIiBbKG5nTW9kZWwpXT1cInNsLnZhbHVlXCIgdHlwZT1cIm51bWJlclwiIHBsYWNlaG9sZGVyPVwiVmFsdWVcIiAvPlxuICAgICAgICAgICAgICAgIDxidXR0b24gY2xhc3M9XCJidG4tcmVtb3ZlLXNlcmllc1wiICpuZ0lmPVwiZWRpdFNsaWNlcy5sZW5ndGggPiAxXCIgKGNsaWNrKT1cInJlbW92ZUVkaXRTbGljZShpKVwiPlxuICAgICAgICAgICAgICAgICAgPGkgY2xhc3M9XCJsYSBsYS10aW1lc1wiPjwvaT5cbiAgICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9uZy1jb250YWluZXI+XG5cbiAgICAgIDwvZGl2PlxuXG4gICAgICA8ZGl2IGNsYXNzPVwiZGlhbG9nLWZvb3RlclwiPlxuICAgICAgICA8YnV0dG9uIGNsYXNzPVwiYnRuLWNhbmNlbFwiIChjbGljayk9XCJjbG9zZUVkaXREaWFsb2coKVwiPkNhbmNlbDwvYnV0dG9uPlxuICAgICAgICA8YnV0dG9uIGNsYXNzPVwiYnRuLWNvbmZpcm1cIiAoY2xpY2spPVwiY29uZmlybUVkaXRXaWRnZXQoKVwiPlxuICAgICAgICAgIDxpIGNsYXNzPVwibGEgbGEtY2hlY2tcIj48L2k+IFNhdmVcbiAgICAgICAgPC9idXR0b24+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgYCxcbiAgc3R5bGVzOiBbYFxuICAgIDpob3N0IHtcbiAgICAgIC0tZGFzaC1iZzogIzAwMDAwMDtcbiAgICAgIC0tZGFzaC1wYW5lbC1iZzogIzFjMWMxZTtcbiAgICAgIC0tZGFzaC1jYXJkLWJnOiAjMmMyYzJlO1xuICAgICAgLS1kYXNoLWZvcmUtY29sb3I6ICM4ZThlOTM7XG4gICAgICAtLWRhc2gtYWNjZW50LWNvbG9yOiAjMGE4NGZmO1xuICAgICAgLS1kYXNoLWRhbmdlci1jb2xvcjogI2ZmNDUzYTtcbiAgICAgIC0tZGFzaC1mb250LWZhbWlseTogLWFwcGxlLXN5c3RlbSwgQmxpbmtNYWNTeXN0ZW1Gb250LCBcIlNlZ29lIFVJXCIsIFJvYm90bywgSGVsdmV0aWNhLCBBcmlhbCwgc2Fucy1zZXJpZjtcbiAgICB9XG5cbiAgICAvKiDilIDilIAgTGF5b3V0IOKUgOKUgCAqL1xuICAgIC5kYXNoYm9hcmQtd3JhcHBlciB7XG4gICAgICBkaXNwbGF5OiBmbGV4O1xuICAgICAgaGVpZ2h0OiAxMDB2aDtcbiAgICAgIHdpZHRoOiAxMDB2dztcbiAgICAgIG92ZXJmbG93OiBoaWRkZW47XG4gICAgICBwYWRkaW5nOiAxNnB4O1xuICAgICAgYm94LXNpemluZzogYm9yZGVyLWJveDtcbiAgICAgIGJhY2tncm91bmQ6IHZhcigtLWRhc2gtYmcpO1xuICAgICAgY29sb3I6IHZhcigtLWRhc2gtZm9yZS1jb2xvcik7XG4gICAgICBmb250LWZhbWlseTogdmFyKC0tZGFzaC1mb250LWZhbWlseSk7XG4gICAgfVxuICAgIC5tYWluLWNvbnRlbnQge1xuICAgICAgZmxleDogMTtcbiAgICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xuICAgICAgb3ZlcmZsb3c6IGhpZGRlbjtcbiAgICAgIGJvcmRlci1yYWRpdXM6IDQwcHg7XG4gICAgICBwYWRkaW5nOiAyMHB4O1xuICAgICAgYmFja2dyb3VuZDogdmFyKC0tZGFzaC1wYW5lbC1iZyk7XG4gICAgICBib3gtc2hhZG93OiAwIDEwcHggMzBweCByZ2JhKDAsMCwwLDAuNSk7XG4gICAgICBib3JkZXI6IDFweCBzb2xpZCByZ2JhKDI1NSwyNTUsMjU1LDAuMDUpO1xuICAgIH1cblxuICAgIC8qIOKUgOKUgCBIZWFkZXIg4pSA4pSAICovXG4gICAgLmRhc2hib2FyZC1oZWFkZXIge1xuICAgICAgZGlzcGxheTogZmxleDtcbiAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gICAgICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47XG4gICAgICBtYXJnaW4tYm90dG9tOiAyMHB4O1xuICAgICAgZ2FwOiAxMnB4O1xuICAgIH1cbiAgICAudGFicy1jb250YWluZXIge1xuICAgICAgZGlzcGxheTogZmxleDtcbiAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gICAgICBnYXA6IDhweDtcbiAgICAgIGJhY2tncm91bmQ6IHJnYmEoNDQsNDQsNDYsMC42KTtcbiAgICAgIGJhY2tkcm9wLWZpbHRlcjogYmx1cigxMHB4KTtcbiAgICAgIGJvcmRlci1yYWRpdXM6IDI1cHg7XG4gICAgICBwYWRkaW5nOiA2cHg7XG4gICAgfVxuICAgIC50YWIge1xuICAgICAgZGlzcGxheTogZmxleDtcbiAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gICAgICBwYWRkaW5nOiA4cHggMjBweDtcbiAgICAgIGJvcmRlci1yYWRpdXM6IDIwcHg7XG4gICAgICBjdXJzb3I6IHBvaW50ZXI7XG4gICAgICBmb250LXNpemU6IDE0cHg7XG4gICAgICBmb250LXdlaWdodDogNTAwO1xuICAgICAgY29sb3I6IHZhcigtLWRhc2gtZm9yZS1jb2xvcik7XG4gICAgICB0cmFuc2l0aW9uOiBhbGwgMC4zcyBjdWJpYy1iZXppZXIoMC4yNSwwLjgsMC4yNSwxKTtcbiAgICB9XG4gICAgLnRhYi5hY3RpdmUge1xuICAgICAgYmFja2dyb3VuZDogIzNhM2EzYztcbiAgICAgIGNvbG9yOiAjZmZmZmZmO1xuICAgICAgYm94LXNoYWRvdzogMCAycHggMTBweCByZ2JhKDAsMCwwLDAuMik7XG4gICAgfVxuICAgIC50YWI6aG92ZXI6bm90KC5hY3RpdmUpIHtcbiAgICAgIGNvbG9yOiAjZTVlNWVhO1xuICAgICAgYmFja2dyb3VuZDogcmdiYSgyNTUsMjU1LDI1NSwwLjA1KTtcbiAgICB9XG4gICAgLnRhYi1uYW1lIHsgbWFyZ2luLXJpZ2h0OiA4cHg7IH1cbiAgICAudGFiLWNsb3NlIHtcbiAgICAgIGJhY2tncm91bmQ6IHRyYW5zcGFyZW50OyBib3JkZXI6IG5vbmU7IGNvbG9yOiB2YXIoLS1kYXNoLWZvcmUtY29sb3IpOyBwYWRkaW5nOiAycHg7XG4gICAgICBmb250LXNpemU6IDEycHg7IGN1cnNvcjogcG9pbnRlcjsgb3BhY2l0eTogMDsgYm9yZGVyLXJhZGl1czogNTAlO1xuICAgICAgZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IGNlbnRlcjsganVzdGlmeS1jb250ZW50OiBjZW50ZXI7IHRyYW5zaXRpb246IGFsbCAwLjJzO1xuICAgIH1cbiAgICAudGFiLWNsb3NlOmhvdmVyIHsgY29sb3I6IHZhcigtLWRhc2gtZGFuZ2VyLWNvbG9yKTsgYmFja2dyb3VuZDogcmdiYSgyNTUsIDY5LCA1OCwgMC4yKTsgfVxuICAgIC50YWI6aG92ZXIgLnRhYi1jbG9zZSB7IG9wYWNpdHk6IDE7IH1cbiAgICAuYnRuLWFkZC1wYWdlIHtcbiAgICAgIGJhY2tncm91bmQ6IHRyYW5zcGFyZW50OyBib3JkZXI6IG5vbmU7IGNvbG9yOiB2YXIoLS1kYXNoLWZvcmUtY29sb3IpO1xuICAgICAgcGFkZGluZzogOHB4IDE2cHg7IGN1cnNvcjogcG9pbnRlcjsgYm9yZGVyLXJhZGl1czogMjBweDsgdHJhbnNpdGlvbjogYWxsIDAuMnM7XG4gICAgfVxuICAgIC5idG4tYWRkLXBhZ2U6aG92ZXIgeyBjb2xvcjogdmFyKC0tZGFzaC1hY2NlbnQtY29sb3IpOyBiYWNrZ3JvdW5kOiByZ2JhKDEwLCAxMzIsIDI1NSwgMC4xKTsgfVxuXG4gICAgLyogQWRkIFdpZGdldCBidXR0b24gKi9cbiAgICAuYnRuLWFkZC13aWRnZXQge1xuICAgICAgZGlzcGxheTogZmxleDtcbiAgICAgIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG4gICAgICBnYXA6IDZweDtcbiAgICAgIGJhY2tncm91bmQ6IHZhcigtLWRhc2gtYWNjZW50LWNvbG9yKTtcbiAgICAgIGJvcmRlcjogbm9uZTtcbiAgICAgIGNvbG9yOiAjZmZmZmZmO1xuICAgICAgZm9udC1zaXplOiAxNHB4O1xuICAgICAgZm9udC13ZWlnaHQ6IDYwMDtcbiAgICAgIHBhZGRpbmc6IDEwcHggMjBweDtcbiAgICAgIGJvcmRlci1yYWRpdXM6IDIycHg7XG4gICAgICBjdXJzb3I6IHBvaW50ZXI7XG4gICAgICB3aGl0ZS1zcGFjZTogbm93cmFwO1xuICAgICAgdHJhbnNpdGlvbjogb3BhY2l0eSAwLjJzLCB0cmFuc2Zvcm0gMC4xNXM7XG4gICAgICBib3gtc2hhZG93OiAwIDRweCAxNHB4IHJnYmEoMTAsMTMyLDI1NSwwLjQpO1xuICAgIH1cbiAgICAuYnRuLWFkZC13aWRnZXQ6aG92ZXIgeyBvcGFjaXR5OiAwLjk7IHRyYW5zZm9ybTogdHJhbnNsYXRlWSgtMXB4KTsgfVxuICAgIC5idG4tYWRkLXdpZGdldDphY3RpdmUgeyB0cmFuc2Zvcm06IHRyYW5zbGF0ZVkoMCk7IH1cblxuICAgIC8qIOKUgOKUgCBHcmlkIOKUgOKUgCAqL1xuICAgIC5ncmlkLWNvbnRhaW5lciB7IGZsZXg6IDE7IG92ZXJmbG93OiBhdXRvOyBib3JkZXItcmFkaXVzOiAyNHB4OyBtaW4taGVpZ2h0OiAwOyB9XG4gICAgZ3JpZHN0ZXIgeyBiYWNrZ3JvdW5kOiB0cmFuc3BhcmVudDsgaGVpZ2h0OiAxMDAlICFpbXBvcnRhbnQ7IH1cblxuICAgIC8qIOKUgOKUgCBEaWFsb2cg4pSA4pSAICovXG4gICAgLmRpYWxvZy1iYWNrZHJvcCB7XG4gICAgICBwb3NpdGlvbjogZml4ZWQ7XG4gICAgICBpbnNldDogMDtcbiAgICAgIGJhY2tncm91bmQ6IHJnYmEoMCwwLDAsMC42KTtcbiAgICAgIGJhY2tkcm9wLWZpbHRlcjogYmx1cig2cHgpO1xuICAgICAgei1pbmRleDogOTAwO1xuICAgIH1cbiAgICAuZGlhbG9nIHtcbiAgICAgIHBvc2l0aW9uOiBmaXhlZDtcbiAgICAgIHRvcDogNTAlO1xuICAgICAgbGVmdDogNTAlO1xuICAgICAgdHJhbnNmb3JtOiB0cmFuc2xhdGUoLTUwJSwgLTUwJSk7XG4gICAgICB6LWluZGV4OiA5MDE7XG4gICAgICB3aWR0aDogbWluKDUyMHB4LCBjYWxjKDEwMHZ3IC0gMzJweCkpO1xuICAgICAgbWF4LWhlaWdodDogY2FsYygxMDB2aCAtIDY0cHgpO1xuICAgICAgZGlzcGxheTogZmxleDtcbiAgICAgIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XG4gICAgICBiYWNrZ3JvdW5kOiB2YXIoLS1kYXNoLXBhbmVsLWJnKTtcbiAgICAgIGJvcmRlci1yYWRpdXM6IDI4cHg7XG4gICAgICBib3JkZXI6IDFweCBzb2xpZCByZ2JhKDI1NSwyNTUsMjU1LDAuMSk7XG4gICAgICBib3gtc2hhZG93OiAwIDI0cHggNjBweCByZ2JhKDAsMCwwLDAuNyk7XG4gICAgICBvdmVyZmxvdzogaGlkZGVuO1xuICAgIH1cbiAgICAuZGlhbG9nLWhlYWRlciB7XG4gICAgICBkaXNwbGF5OiBmbGV4O1xuICAgICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgICAgIGp1c3RpZnktY29udGVudDogc3BhY2UtYmV0d2VlbjtcbiAgICAgIHBhZGRpbmc6IDIycHggMjRweCAxNnB4O1xuICAgICAgYm9yZGVyLWJvdHRvbTogMXB4IHNvbGlkIHJnYmEoMjU1LDI1NSwyNTUsMC4wNyk7XG4gICAgfVxuICAgIC5kaWFsb2ctdGl0bGUgeyBmb250LXNpemU6IDE3cHg7IGZvbnQtd2VpZ2h0OiA3MDA7IGNvbG9yOiAjZmZmZmZmOyB9XG4gICAgLmRpYWxvZy1jbG9zZSB7XG4gICAgICBiYWNrZ3JvdW5kOiByZ2JhKDI1NSwyNTUsMjU1LDAuMDgpOyBib3JkZXI6IG5vbmU7IGNvbG9yOiB2YXIoLS1kYXNoLWZvcmUtY29sb3IpO1xuICAgICAgd2lkdGg6IDMwcHg7IGhlaWdodDogMzBweDsgYm9yZGVyLXJhZGl1czogNTAlO1xuICAgICAgZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IGNlbnRlcjsganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XG4gICAgICBjdXJzb3I6IHBvaW50ZXI7IGZvbnQtc2l6ZTogMTRweDsgdHJhbnNpdGlvbjogYWxsIDAuMnM7XG4gICAgfVxuICAgIC5kaWFsb2ctY2xvc2U6aG92ZXIgeyBiYWNrZ3JvdW5kOiByZ2JhKDI1NSw2OSw1OCwwLjI1KTsgY29sb3I6IHZhcigtLWRhc2gtZGFuZ2VyLWNvbG9yKTsgfVxuICAgIC5kaWFsb2ctYm9keSB7IGZsZXg6IDE7IG92ZXJmbG93LXk6IGF1dG87IHBhZGRpbmc6IDIwcHggMjRweDsgZGlzcGxheTogZmxleDsgZmxleC1kaXJlY3Rpb246IGNvbHVtbjsgZ2FwOiAyMHB4OyB9XG4gICAgLmZpZWxkLWdyb3VwIHsgZGlzcGxheTogZmxleDsgZmxleC1kaXJlY3Rpb246IGNvbHVtbjsgZ2FwOiA4cHg7IH1cbiAgICAuZmllbGQtbGFiZWwgeyBmb250LXNpemU6IDEzcHg7IGZvbnQtd2VpZ2h0OiA2MDA7IGNvbG9yOiB2YXIoLS1kYXNoLWZvcmUtY29sb3IpOyB0ZXh0LXRyYW5zZm9ybTogdXBwZXJjYXNlOyBsZXR0ZXItc3BhY2luZzogMC41cHg7IH1cbiAgICAuZmllbGQtaW5wdXQge1xuICAgICAgYmFja2dyb3VuZDogdmFyKC0tZGFzaC1jYXJkLWJnKTtcbiAgICAgIGJvcmRlcjogMXB4IHNvbGlkIHJnYmEoMjU1LDI1NSwyNTUsMC4wOCk7XG4gICAgICBib3JkZXItcmFkaXVzOiAxMnB4O1xuICAgICAgcGFkZGluZzogMTBweCAxNHB4O1xuICAgICAgY29sb3I6ICNmZmZmZmY7XG4gICAgICBmb250LXNpemU6IDE0cHg7XG4gICAgICBvdXRsaW5lOiBub25lO1xuICAgICAgd2lkdGg6IDEwMCU7XG4gICAgICBib3gtc2l6aW5nOiBib3JkZXItYm94O1xuICAgIH1cbiAgICAuZmllbGQtaW5wdXQ6Zm9jdXMgeyBib3JkZXItY29sb3I6IHZhcigtLWRhc2gtYWNjZW50LWNvbG9yKTsgfVxuICAgIC50eXBlLXBpY2tlciB7IGRpc3BsYXk6IGZsZXg7IGdhcDogMTBweDsgfVxuICAgIC50eXBlLWJ0biB7XG4gICAgICBmbGV4OiAxOyBkaXNwbGF5OiBmbGV4OyBmbGV4LWRpcmVjdGlvbjogY29sdW1uOyBhbGlnbi1pdGVtczogY2VudGVyOyBnYXA6IDZweDsgcGFkZGluZzogMTRweCAxMHB4O1xuICAgICAgYmFja2dyb3VuZDogdmFyKC0tZGFzaC1jYXJkLWJnKTsgYm9yZGVyOiAycHggc29saWQgdHJhbnNwYXJlbnQ7IGJvcmRlci1yYWRpdXM6IDE2cHg7XG4gICAgICBjb2xvcjogdmFyKC0tZGFzaC1mb3JlLWNvbG9yKTsgZm9udC1zaXplOiAxMnB4OyBmb250LXdlaWdodDogNjAwOyBjdXJzb3I6IHBvaW50ZXI7IHRyYW5zaXRpb246IGFsbCAwLjJzO1xuICAgIH1cbiAgICAudHlwZS1idG4uc2VsZWN0ZWQgeyBib3JkZXItY29sb3I6IHZhcigtLWRhc2gtYWNjZW50LWNvbG9yKTsgY29sb3I6IHZhcigtLWRhc2gtYWNjZW50LWNvbG9yKTsgYmFja2dyb3VuZDogcmdiYSgxMCwxMzIsMjU1LDAuMTIpOyB9XG4gICAgLmJ0bi1saW5rIHsgYmFja2dyb3VuZDogdHJhbnNwYXJlbnQ7IGJvcmRlcjogbm9uZTsgY29sb3I6IHZhcigtLWRhc2gtYWNjZW50LWNvbG9yKTsgZm9udC1zaXplOiAxM3B4OyBmb250LXdlaWdodDogNjAwOyBjdXJzb3I6IHBvaW50ZXI7IH1cbiAgICAuZGlhbG9nLWZvb3RlciB7IGRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiBjZW50ZXI7IGp1c3RpZnktY29udGVudDogZmxleC1lbmQ7IGdhcDogMTBweDsgcGFkZGluZzogMTZweCAyNHB4IDIycHg7IGJvcmRlci10b3A6IDFweCBzb2xpZCByZ2JhKDI1NSwyNTUsMjU1LDAuMDcpOyB9XG4gICAgLmJ0bi1jYW5jZWwgeyBiYWNrZ3JvdW5kOiB0cmFuc3BhcmVudDsgYm9yZGVyOiAxcHggc29saWQgcmdiYSgyNTUsMjU1LDI1NSwwLjEyKTsgY29sb3I6IHZhcigtLWRhc2gtZm9yZS1jb2xvcik7IHBhZGRpbmc6IDEwcHggMjBweDsgYm9yZGVyLXJhZGl1czogMjBweDsgY3Vyc29yOiBwb2ludGVyOyB9XG4gICAgLmJ0bi1jb25maXJtIHsgYmFja2dyb3VuZDogdmFyKC0tZGFzaC1hY2NlbnQtY29sb3IpOyBib3JkZXI6IG5vbmU7IGNvbG9yOiAjZmZmZmZmOyBwYWRkaW5nOiAxMHB4IDIycHg7IGJvcmRlci1yYWRpdXM6IDIwcHg7IGZvbnQtd2VpZ2h0OiA2MDA7IGN1cnNvcjogcG9pbnRlcjsgfVxuICAgIC5idG4tY29uZmlybTpkaXNhYmxlZCB7IG9wYWNpdHk6IDAuNDsgY3Vyc29yOiBub3QtYWxsb3dlZDsgfVxuICBgXVxufSlcbmV4cG9ydCBjbGFzcyBEYXNoYm9hcmRDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIE9uRGVzdHJveSwgT25DaGFuZ2VzIHtcbiAgQElucHV0KCkgaW5pdGlhbExheW91dD86IHN0cmluZztcbiAgQElucHV0KCkgdGhlbWU/OiBEYXNoYm9hcmRUaGVtZTtcblxuICByZXNvbHZlZFRoZW1lOiBSZXF1aXJlZDxEYXNoYm9hcmRUaGVtZT4gPSB7IC4uLkRFRkFVTFRfVEhFTUUgfTtcbiAgd3JhcHBlclN0eWxlczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9O1xuXG4gIG9wdGlvbnMhOiBHcmlkc3RlckNvbmZpZztcbiAgcGFnZXM6IFBhZ2VbXSA9IFtdO1xuICBhY3RpdmVQYWdlSWQ6IHN0cmluZyA9ICcnO1xuICBhY3RpdmVQYWdlPzogUGFnZTtcblxuICAvLyDilIDilIAgRGlhbG9nIHN0YXRlIOKUgOKUgFxuICBkaWFsb2dPcGVuID0gZmFsc2U7XG4gIGRpYWxvZ1R5cGU6IFdpZGdldFR5cGUgPSAnTElORSc7XG4gIGRpYWxvZ1RpdGxlID0gJyc7XG4gIGRpYWxvZ0NhdGVnb3JpZXMgPSAnJztcbiAgZGlhbG9nU2VyaWVzOiB7IG5hbWU6IHN0cmluZzsgZGF0YVJhdzogc3RyaW5nIH1bXSA9IFt7IG5hbWU6ICdTZXJpZXMgMScsIGRhdGFSYXc6ICcnIH1dO1xuICBkaWFsb2dTbGljZXM6IHsgbGFiZWw6IHN0cmluZzsgdmFsdWU6IG51bWJlciB8IG51bGwgfVtdID0gW1xuICAgIHsgbGFiZWw6ICdTbGljZSBBJywgdmFsdWU6IG51bGwgfSxcbiAgICB7IGxhYmVsOiAnU2xpY2UgQicsIHZhbHVlOiBudWxsIH0sXG4gICAgeyBsYWJlbDogJ1NsaWNlIEMnLCB2YWx1ZTogbnVsbCB9LFxuICBdO1xuXG4gIHJlYWRvbmx5IHdpZGdldFR5cGVzOiB7IHZhbHVlOiBXaWRnZXRUeXBlOyBsYWJlbDogc3RyaW5nOyBpY29uOiBzdHJpbmcgfVtdID0gW1xuICAgIHsgdmFsdWU6ICdMSU5FJywgbGFiZWw6ICdMaW5lJywgIGljb246ICdsYS1jaGFydC1hcmVhJyB9LFxuICAgIHsgdmFsdWU6ICdCQVInLCAgbGFiZWw6ICdCYXInLCAgIGljb246ICdsYS1jaGFydC1iYXInICB9LFxuICAgIHsgdmFsdWU6ICdET05VVCcsbGFiZWw6ICdEb251dCcsIGljb246ICdsYS1jaGFydC1waWUnICB9LFxuICBdO1xuXG4gIHByaXZhdGUgc3VicyA9IG5ldyBTdWJzY3JpcHRpb24oKTtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHN0YXRlU2VydmljZTogRGFzaGJvYXJkU3RhdGVTZXJ2aWNlKSB7fVxuXG4gIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpIHtcbiAgICBpZiAoY2hhbmdlc1sndGhlbWUnXSB8fCBjaGFuZ2VzWydpbml0aWFsTGF5b3V0J10pIHRoaXMuYXBwbHlUaGVtZSgpO1xuICB9XG5cbiAgbmdPbkluaXQoKSB7XG4gICAgdGhpcy5hcHBseVRoZW1lKCk7XG5cbiAgICBpZiAodGhpcy5pbml0aWFsTGF5b3V0KSB7XG4gICAgICB0cnkgeyB0aGlzLnN0YXRlU2VydmljZS5sb2FkTGF5b3V0KEpTT04ucGFyc2UodGhpcy5pbml0aWFsTGF5b3V0KSk7IH1cbiAgICAgIGNhdGNoIChlKSB7IGNvbnNvbGUuZXJyb3IoJ1tEYXNoYm9hcmRdIEZhaWxlZCB0byBwYXJzZSBpbml0aWFsTGF5b3V0JywgZSk7IH1cbiAgICB9XG5cbiAgICB0aGlzLm9wdGlvbnMgPSB7XG4gICAgICBncmlkVHlwZTogJ2ZpdCcsXG4gICAgICBkaXNwbGF5R3JpZDogJ25vbmUnLFxuICAgICAgcHVzaEl0ZW1zOiB0cnVlLFxuICAgICAgZHJhZ2dhYmxlOiB7IGVuYWJsZWQ6IHRydWUgfSxcbiAgICAgIHJlc2l6YWJsZTogeyBlbmFibGVkOiB0cnVlIH0sXG4gICAgICBtaW5Db2xzOiAxMiwgbWF4Q29sczogMTIsXG4gICAgICBtaW5Sb3dzOiAxMiwgbWF4Um93czogNTAsXG4gICAgICBtYXJnaW46IDIwLCBvdXRlck1hcmdpbjogdHJ1ZSxcbiAgICAgIGl0ZW1DaGFuZ2VDYWxsYmFjazogKGl0ZW06IGFueSkgPT4ge1xuICAgICAgICB0aGlzLnN0YXRlU2VydmljZS51cGRhdGVXaWRnZXRQb3NpdGlvbihcbiAgICAgICAgICB0aGlzLmFjdGl2ZVBhZ2VJZCwgaXRlbS5pZCwgaXRlbS54LCBpdGVtLnksIGl0ZW0uY29scywgaXRlbS5yb3dzXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIHRoaXMuc3Vicy5hZGQodGhpcy5zdGF0ZVNlcnZpY2UucGFnZXMkLnN1YnNjcmliZShwYWdlcyA9PiB7XG4gICAgICB0aGlzLnBhZ2VzID0gcGFnZXM7XG4gICAgICB0aGlzLnVwZGF0ZUFjdGl2ZVBhZ2UoKTtcbiAgICB9KSk7XG4gICAgdGhpcy5zdWJzLmFkZCh0aGlzLnN0YXRlU2VydmljZS5hY3RpdmVQYWdlSWQkLnN1YnNjcmliZShpZCA9PiB7XG4gICAgICB0aGlzLmFjdGl2ZVBhZ2VJZCA9IGlkO1xuICAgICAgdGhpcy51cGRhdGVBY3RpdmVQYWdlKCk7XG4gICAgfSkpO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKSB7IHRoaXMuc3Vicy51bnN1YnNjcmliZSgpOyB9XG5cbiAgcHJpdmF0ZSBhcHBseVRoZW1lKCkge1xuICAgIHRoaXMucmVzb2x2ZWRUaGVtZSA9IHsgLi4uREVGQVVMVF9USEVNRSwgLi4uKHRoaXMudGhlbWUgPz8ge30pIH07XG4gICAgdGhpcy53cmFwcGVyU3R5bGVzID0ge1xuICAgICAgJy0tZGFzaC1iZyc6IHRoaXMucmVzb2x2ZWRUaGVtZS5iYWNrZ3JvdW5kQ29sb3IsXG4gICAgICAnLS1kYXNoLXBhbmVsLWJnJzogdGhpcy5yZXNvbHZlZFRoZW1lLnBhbmVsQ29sb3IsXG4gICAgICAnLS1kYXNoLWNhcmQtYmcnOiB0aGlzLnJlc29sdmVkVGhlbWUud2lkZ2V0Q2FyZENvbG9yLFxuICAgICAgJy0tZGFzaC1mb3JlLWNvbG9yJzogdGhpcy5yZXNvbHZlZFRoZW1lLmNoYXJ0Rm9yZUNvbG9yLFxuICAgICAgJy0tZGFzaC1hY2NlbnQtY29sb3InOiB0aGlzLnJlc29sdmVkVGhlbWUuYWNjZW50Q29sb3IsXG4gICAgICAnLS1kYXNoLWRhbmdlci1jb2xvcic6IHRoaXMucmVzb2x2ZWRUaGVtZS5kYW5nZXJDb2xvcixcbiAgICAgICctLWRhc2gtZm9udC1mYW1pbHknOiB0aGlzLnJlc29sdmVkVGhlbWUuZm9udEZhbWlseSxcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSB1cGRhdGVBY3RpdmVQYWdlKCkge1xuICAgIHRoaXMuYWN0aXZlUGFnZSA9IHRoaXMucGFnZXMuZmluZChwID0+IHAuaWQgPT09IHRoaXMuYWN0aXZlUGFnZUlkKTtcbiAgfVxuXG5cbiAgLy8g4pSA4pSAIFBhZ2UgYWN0aW9ucyDilIDilIBcbiAgb25TZWxlY3RQYWdlKGlkOiBzdHJpbmcpIHsgdGhpcy5zdGF0ZVNlcnZpY2Uuc2V0QWN0aXZlUGFnZShpZCk7IH1cblxuICBvbkFkZFBhZ2UoKSB7XG4gICAgY29uc3QgbmFtZSA9IHByb21wdCgnRW50ZXIgd29ya3NwYWNlIG5hbWU6JywgYFdvcmtzcGFjZSAke3RoaXMucGFnZXMubGVuZ3RoICsgMX1gKTtcbiAgICBpZiAobmFtZSkgdGhpcy5zdGF0ZVNlcnZpY2UuYWRkUGFnZShuYW1lKTtcbiAgfVxuXG4gIG9uUmVtb3ZlUGFnZShldmVudDogRXZlbnQsIGlkOiBzdHJpbmcpIHtcbiAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICBpZiAoY29uZmlybSgnUmVtb3ZlIHRoaXMgd29ya3NwYWNlPycpKSB0aGlzLnN0YXRlU2VydmljZS5yZW1vdmVQYWdlKGlkKTtcbiAgfVxuXG4gIC8vIOKUgOKUgCBEaWFsb2cg4pSA4pSAXG4gIG9wZW5EaWFsb2coKSB7XG4gICAgdGhpcy5kaWFsb2dUeXBlID0gJ0xJTkUnO1xuICAgIHRoaXMuZGlhbG9nVGl0bGUgPSAnJztcbiAgICB0aGlzLmRpYWxvZ0NhdGVnb3JpZXMgPSAnJztcbiAgICB0aGlzLmRpYWxvZ1NlcmllcyA9IFt7IG5hbWU6ICdTZXJpZXMgMScsIGRhdGFSYXc6ICcnIH1dO1xuICAgIHRoaXMuZGlhbG9nU2xpY2VzID0gW1xuICAgICAgeyBsYWJlbDogJ1NsaWNlIEEnLCB2YWx1ZTogbnVsbCB9LFxuICAgICAgeyBsYWJlbDogJ1NsaWNlIEInLCB2YWx1ZTogbnVsbCB9LFxuICAgICAgeyBsYWJlbDogJ1NsaWNlIEMnLCB2YWx1ZTogbnVsbCB9LFxuICAgIF07XG4gICAgdGhpcy5kaWFsb2dPcGVuID0gdHJ1ZTtcbiAgfVxuXG4gIGNsb3NlRGlhbG9nKCkgeyB0aGlzLmRpYWxvZ09wZW4gPSBmYWxzZTsgfVxuXG4gIGFkZFNlcmllcygpIHsgdGhpcy5kaWFsb2dTZXJpZXMucHVzaCh7IG5hbWU6IGBTZXJpZXMgJHt0aGlzLmRpYWxvZ1Nlcmllcy5sZW5ndGggKyAxfWAsIGRhdGFSYXc6ICcnIH0pOyB9XG4gIHJlbW92ZVNlcmllcyhpOiBudW1iZXIpIHsgdGhpcy5kaWFsb2dTZXJpZXMuc3BsaWNlKGksIDEpOyB9XG5cbiAgYWRkU2xpY2UoKSB7IHRoaXMuZGlhbG9nU2xpY2VzLnB1c2goeyBsYWJlbDogYFNsaWNlICR7dGhpcy5kaWFsb2dTbGljZXMubGVuZ3RoICsgMX1gLCB2YWx1ZTogbnVsbCB9KTsgfVxuICByZW1vdmVTbGljZShpOiBudW1iZXIpIHsgdGhpcy5kaWFsb2dTbGljZXMuc3BsaWNlKGksIDEpOyB9XG5cbiAgY29uZmlybUFkZFdpZGdldCgpIHtcbiAgICBjb25zdCB0aXRsZSA9IHRoaXMuZGlhbG9nVGl0bGUudHJpbSgpO1xuICAgIGlmICghdGl0bGUpIHJldHVybjtcblxuICAgIGxldCBkYXRhOiBMaW5lQmFyRGF0YSB8IERvbnV0RGF0YTtcblxuICAgIGlmICh0aGlzLmRpYWxvZ1R5cGUgPT09ICdET05VVCcpIHtcbiAgICAgIGNvbnN0IHZhbGlkU2xpY2VzID0gdGhpcy5kaWFsb2dTbGljZXMuZmlsdGVyKHMgPT4gcy52YWx1ZSAhPT0gbnVsbCAmJiBzLmxhYmVsLnRyaW0oKSk7XG4gICAgICBkYXRhID0ge1xuICAgICAgICBzZXJpZXM6IHZhbGlkU2xpY2VzLmxlbmd0aFxuICAgICAgICAgID8gdmFsaWRTbGljZXMubWFwKHMgPT4gTnVtYmVyKHMudmFsdWUpKVxuICAgICAgICAgIDogWzMwLCAyMCwgNTBdLFxuICAgICAgICBsYWJlbHM6IHZhbGlkU2xpY2VzLmxlbmd0aFxuICAgICAgICAgID8gdmFsaWRTbGljZXMubWFwKHMgPT4gcy5sYWJlbClcbiAgICAgICAgICA6IFsnQScsICdCJywgJ0MnXSxcbiAgICAgIH0gYXMgRG9udXREYXRhO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBwYXJzZU51bXMgPSAocmF3OiBzdHJpbmcpID0+XG4gICAgICAgIHJhdy5zcGxpdCgnLCcpLm1hcCh2ID0+IHBhcnNlRmxvYXQodi50cmltKCkpKS5maWx0ZXIobiA9PiAhaXNOYU4obikpO1xuXG4gICAgICBkYXRhID0ge1xuICAgICAgICBzZXJpZXM6IHRoaXMuZGlhbG9nU2VyaWVzLm1hcChzID0+ICh7XG4gICAgICAgICAgbmFtZTogcy5uYW1lIHx8ICdTZXJpZXMnLFxuICAgICAgICAgIGRhdGE6IHMuZGF0YVJhdy50cmltKClcbiAgICAgICAgICAgID8gcGFyc2VOdW1zKHMuZGF0YVJhdylcbiAgICAgICAgICAgIDogQXJyYXkuZnJvbSh7IGxlbmd0aDogOCB9LCAoKSA9PiBNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiAxMDApKSxcbiAgICAgICAgfSkpLFxuICAgICAgICBjYXRlZ29yaWVzOiB0aGlzLmRpYWxvZ0NhdGVnb3JpZXMudHJpbSgpXG4gICAgICAgICAgPyB0aGlzLmRpYWxvZ0NhdGVnb3JpZXMuc3BsaXQoJywnKS5tYXAoYyA9PiBjLnRyaW0oKSlcbiAgICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICAgIH0gYXMgTGluZUJhckRhdGE7XG4gICAgfVxuXG4gICAgdGhpcy5zdGF0ZVNlcnZpY2UuYWRkV2lkZ2V0V2l0aERhdGEodGhpcy5kaWFsb2dUeXBlLCB0aXRsZSwgZGF0YSk7XG4gICAgdGhpcy5jbG9zZURpYWxvZygpO1xuICB9XG5cbiAgLy8g4pSA4pSAIEVkaXQgZGlhbG9nIHN0YXRlIOKUgOKUgFxuICBlZGl0RGlhbG9nT3BlbiA9IGZhbHNlO1xuICBlZGl0aW5nV2lkZ2V0PzogV2lkZ2V0O1xuICBlZGl0V2lkZ2V0VHlwZTogV2lkZ2V0VHlwZSA9ICdMSU5FJztcbiAgZWRpdFRpdGxlID0gJyc7XG4gIGVkaXRDYXJkQ29sb3IgPSAnJztcbiAgZWRpdENvbG9yczogc3RyaW5nW10gPSBbXTtcbiAgZWRpdFNlcmllczogeyBuYW1lOiBzdHJpbmc7IGRhdGFSYXc6IHN0cmluZyB9W10gPSBbXTtcbiAgZWRpdENhdGVnb3JpZXMgPSAnJztcbiAgZWRpdFNsaWNlczogeyBsYWJlbDogc3RyaW5nOyB2YWx1ZTogbnVtYmVyIHwgbnVsbCB9W10gPSBbXTtcblxuICBwcml2YXRlIHJlYWRvbmx5IERFRkFVTFRfQ09MT1JTID0gWycjMGE4NGZmJywgJyMzMGQxNTgnLCAnI2ZmOWYwYScsICcjYmY1YWYyJywgJyNmZjQ1M2EnXTtcblxuICBvcGVuRWRpdERpYWxvZyh3aWRnZXQ6IFdpZGdldCkge1xuICAgIHRoaXMuZWRpdGluZ1dpZGdldCAgPSB3aWRnZXQ7XG4gICAgdGhpcy5lZGl0V2lkZ2V0VHlwZSA9IHdpZGdldC50eXBlO1xuICAgIHRoaXMuZWRpdFRpdGxlICAgICAgPSB3aWRnZXQudGl0bGU7XG4gICAgdGhpcy5lZGl0Q2FyZENvbG9yICA9IHdpZGdldC5jYXJkQ29sb3IgPz8gdGhpcy5yZXNvbHZlZFRoZW1lLndpZGdldENhcmRDb2xvcjtcbiAgICB0aGlzLmVkaXRDb2xvcnMgICAgID0gd2lkZ2V0LmNvbG9ycz8ubGVuZ3RoXG4gICAgICA/IFsuLi53aWRnZXQuY29sb3JzXVxuICAgICAgOiBbLi4udGhpcy5yZXNvbHZlZFRoZW1lLmNoYXJ0Q29sb3JzXTtcblxuICAgIGlmICh3aWRnZXQudHlwZSA9PT0gJ0RPTlVUJykge1xuICAgICAgY29uc3QgZCA9IHdpZGdldC5kYXRhIGFzIGFueTtcbiAgICAgIHRoaXMuZWRpdFNsaWNlcyA9IChkLnNlcmllcyBhcyBudW1iZXJbXSkubWFwKCh2OiBudW1iZXIsIGk6IG51bWJlcikgPT4gKHtcbiAgICAgICAgbGFiZWw6IGQubGFiZWxzPy5baV0gPz8gYFNsaWNlICR7aSArIDF9YCxcbiAgICAgICAgdmFsdWU6IHYsXG4gICAgICB9KSk7XG4gICAgICB0aGlzLmVkaXRDb2xvcnMgPSB0aGlzLmVkaXRDb2xvcnMuc2xpY2UoMCwgdGhpcy5lZGl0U2xpY2VzLmxlbmd0aCk7XG4gICAgICB3aGlsZSAodGhpcy5lZGl0Q29sb3JzLmxlbmd0aCA8IHRoaXMuZWRpdFNsaWNlcy5sZW5ndGgpIHtcbiAgICAgICAgdGhpcy5lZGl0Q29sb3JzLnB1c2godGhpcy5ERUZBVUxUX0NPTE9SU1t0aGlzLmVkaXRDb2xvcnMubGVuZ3RoICUgdGhpcy5ERUZBVUxUX0NPTE9SUy5sZW5ndGhdKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgZCA9IHdpZGdldC5kYXRhIGFzIGFueTtcbiAgICAgIHRoaXMuZWRpdFNlcmllcyAgICAgPSAoZC5zZXJpZXMgYXMgYW55W10pLm1hcCgoczogYW55KSA9PiAoeyBuYW1lOiBzLm5hbWUsIGRhdGFSYXc6IHMuZGF0YS5qb2luKCcsJykgfSkpO1xuICAgICAgdGhpcy5lZGl0Q2F0ZWdvcmllcyA9IGQuY2F0ZWdvcmllcz8uam9pbignLCcpID8/ICcnO1xuICAgICAgdGhpcy5lZGl0Q29sb3JzICAgICA9IHRoaXMuZWRpdENvbG9ycy5zbGljZSgwLCB0aGlzLmVkaXRTZXJpZXMubGVuZ3RoKTtcbiAgICAgIHdoaWxlICh0aGlzLmVkaXRDb2xvcnMubGVuZ3RoIDwgdGhpcy5lZGl0U2VyaWVzLmxlbmd0aCkge1xuICAgICAgICB0aGlzLmVkaXRDb2xvcnMucHVzaCh0aGlzLkRFRkFVTFRfQ09MT1JTW3RoaXMuZWRpdENvbG9ycy5sZW5ndGggJSB0aGlzLkRFRkFVTFRfQ09MT1JTLmxlbmd0aF0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMuZWRpdERpYWxvZ09wZW4gPSB0cnVlO1xuICB9XG5cbiAgY2xvc2VFZGl0RGlhbG9nKCkgeyB0aGlzLmVkaXREaWFsb2dPcGVuID0gZmFsc2U7IHRoaXMuZWRpdGluZ1dpZGdldCA9IHVuZGVmaW5lZDsgfVxuXG4gIGdldEVkaXRTZXJpZXNMYWJlbChpOiBudW1iZXIpOiBzdHJpbmcge1xuICAgIGlmICh0aGlzLmVkaXRXaWRnZXRUeXBlID09PSAnRE9OVVQnKSByZXR1cm4gdGhpcy5lZGl0U2xpY2VzW2ldPy5sYWJlbCB8fCBgU2xpY2UgJHtpICsgMX1gO1xuICAgIHJldHVybiB0aGlzLmVkaXRTZXJpZXNbaV0/Lm5hbWUgfHwgYFNlcmllcyAke2kgKyAxfWA7XG4gIH1cblxuICBhZGRFZGl0U2VyaWVzKCkge1xuICAgIHRoaXMuZWRpdFNlcmllcy5wdXNoKHsgbmFtZTogYFNlcmllcyAke3RoaXMuZWRpdFNlcmllcy5sZW5ndGggKyAxfWAsIGRhdGFSYXc6ICcnIH0pO1xuICAgIHRoaXMuZWRpdENvbG9ycy5wdXNoKHRoaXMuREVGQVVMVF9DT0xPUlNbdGhpcy5lZGl0Q29sb3JzLmxlbmd0aCAlIHRoaXMuREVGQVVMVF9DT0xPUlMubGVuZ3RoXSk7XG4gIH1cbiAgcmVtb3ZlRWRpdFNlcmllcyhpOiBudW1iZXIpIHsgdGhpcy5lZGl0U2VyaWVzLnNwbGljZShpLCAxKTsgdGhpcy5lZGl0Q29sb3JzLnNwbGljZShpLCAxKTsgfVxuXG4gIGFkZEVkaXRTbGljZSgpIHtcbiAgICB0aGlzLmVkaXRTbGljZXMucHVzaCh7IGxhYmVsOiBgU2xpY2UgJHt0aGlzLmVkaXRTbGljZXMubGVuZ3RoICsgMX1gLCB2YWx1ZTogbnVsbCB9KTtcbiAgICB0aGlzLmVkaXRDb2xvcnMucHVzaCh0aGlzLkRFRkFVTFRfQ09MT1JTW3RoaXMuZWRpdENvbG9ycy5sZW5ndGggJSB0aGlzLkRFRkFVTFRfQ09MT1JTLmxlbmd0aF0pO1xuICB9XG4gIHJlbW92ZUVkaXRTbGljZShpOiBudW1iZXIpIHsgdGhpcy5lZGl0U2xpY2VzLnNwbGljZShpLCAxKTsgdGhpcy5lZGl0Q29sb3JzLnNwbGljZShpLCAxKTsgfVxuXG4gIGNvbmZpcm1FZGl0V2lkZ2V0KCkge1xuICAgIGlmICghdGhpcy5lZGl0aW5nV2lkZ2V0KSByZXR1cm47XG4gICAgY29uc3QgcGFyc2VOdW1zID0gKHJhdzogc3RyaW5nKSA9PlxuICAgICAgcmF3LnNwbGl0KCcsJykubWFwKHYgPT4gcGFyc2VGbG9hdCh2LnRyaW0oKSkpLmZpbHRlcihuID0+ICFpc05hTihuKSk7XG5cbiAgICBsZXQgZGF0YTogTGluZUJhckRhdGEgfCBEb251dERhdGE7XG4gICAgaWYgKHRoaXMuZWRpdFdpZGdldFR5cGUgPT09ICdET05VVCcpIHtcbiAgICAgIGRhdGEgPSB7XG4gICAgICAgIHNlcmllczogdGhpcy5lZGl0U2xpY2VzLm1hcChzID0+IE51bWJlcihzLnZhbHVlKSB8fCAwKSxcbiAgICAgICAgbGFiZWxzOiB0aGlzLmVkaXRTbGljZXMubWFwKHMgPT4gcy5sYWJlbCksXG4gICAgICB9IGFzIERvbnV0RGF0YTtcbiAgICB9IGVsc2Uge1xuICAgICAgZGF0YSA9IHtcbiAgICAgICAgc2VyaWVzOiB0aGlzLmVkaXRTZXJpZXMubWFwKHMgPT4gKHtcbiAgICAgICAgICBuYW1lOiBzLm5hbWUgfHwgJ1NlcmllcycsXG4gICAgICAgICAgZGF0YTogcy5kYXRhUmF3LnRyaW0oKSA/IHBhcnNlTnVtcyhzLmRhdGFSYXcpIDogW10sXG4gICAgICAgIH0pKSxcbiAgICAgICAgY2F0ZWdvcmllczogdGhpcy5lZGl0Q2F0ZWdvcmllcy50cmltKClcbiAgICAgICAgICA/IHRoaXMuZWRpdENhdGVnb3JpZXMuc3BsaXQoJywnKS5tYXAoYyA9PiBjLnRyaW0oKSlcbiAgICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICAgIH0gYXMgTGluZUJhckRhdGE7XG4gICAgfVxuXG4gICAgdGhpcy5zdGF0ZVNlcnZpY2UudXBkYXRlV2lkZ2V0TWV0YSh0aGlzLmVkaXRpbmdXaWRnZXQuaWQsIHtcbiAgICAgIHRpdGxlOiAgICAgdGhpcy5lZGl0VGl0bGUudHJpbSgpIHx8IHRoaXMuZWRpdGluZ1dpZGdldC50aXRsZSxcbiAgICAgIGNvbG9yczogICAgWy4uLnRoaXMuZWRpdENvbG9yc10sXG4gICAgICBjYXJkQ29sb3I6IHRoaXMuZWRpdENhcmRDb2xvcixcbiAgICAgIGRhdGEsXG4gICAgfSk7XG4gICAgdGhpcy5jbG9zZUVkaXREaWFsb2coKTtcbiAgfVxuXG4gIC8vIOKUgOKUgCBXaWRnZXQgYWN0aW9ucyDilIDilIBcbiAgb25BZGRXaWRnZXQodHlwZTogV2lkZ2V0VHlwZSkgeyB0aGlzLnN0YXRlU2VydmljZS5hZGRXaWRnZXQodHlwZSk7IH1cblxuICB1cGRhdGVXaWRnZXREYXRhKHdpZGdldElkOiBzdHJpbmcsIGRhdGE6IExpbmVCYXJEYXRhIHwgRG9udXREYXRhKSB7XG4gICAgdGhpcy5zdGF0ZVNlcnZpY2UudXBkYXRlV2lkZ2V0RGF0YSh3aWRnZXRJZCwgZGF0YSk7XG4gIH1cblxuICByZW1vdmVXaWRnZXRIYW5kbGVyID0gKGlkOiBzdHJpbmcpID0+IHsgdGhpcy5zdGF0ZVNlcnZpY2UucmVtb3ZlV2lkZ2V0KGlkKTsgfTtcblxuICBzZXJpYWxpemVMYXlvdXQoKTogc3RyaW5nIHsgcmV0dXJuIHRoaXMuc3RhdGVTZXJ2aWNlLnNlcmlhbGl6ZUxheW91dCgpOyB9XG59XG4iXX0=