@ogidor/dashboard 1.0.3 → 1.0.5

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.
Files changed (39) hide show
  1. package/README.md +283 -48
  2. package/app/app.module.d.ts +20 -0
  3. package/app/custom-grid.component.d.ts +93 -0
  4. package/app/dashboard-state.service.d.ts +70 -0
  5. package/app/dashboard.component.d.ts +48 -0
  6. package/app/models.d.ts +53 -0
  7. package/app/widget-renderer.component.d.ts +13 -0
  8. package/esm2020/app/app.module.mjs +57 -0
  9. package/esm2020/app/custom-grid.component.mjs +509 -0
  10. package/esm2020/app/dashboard-state.service.mjs +288 -0
  11. package/esm2020/app/dashboard.component.mjs +299 -0
  12. package/esm2020/app/models.mjs +2 -0
  13. package/esm2020/app/widget-renderer.component.mjs +83 -0
  14. package/esm2020/public-api.mjs +10 -0
  15. package/fesm2015/ogidor-dashboard.mjs +1233 -0
  16. package/fesm2015/ogidor-dashboard.mjs.map +1 -0
  17. package/fesm2020/ogidor-dashboard.mjs +1229 -0
  18. package/fesm2020/ogidor-dashboard.mjs.map +1 -0
  19. package/package.json +30 -44
  20. package/{dist-lib/public-api.d.ts → public-api.d.ts} +3 -2
  21. package/dist-lib/README.md +0 -103
  22. package/dist-lib/app/app.module.d.ts +0 -22
  23. package/dist-lib/app/dashboard-state.service.d.ts +0 -49
  24. package/dist-lib/app/dashboard.component.d.ts +0 -80
  25. package/dist-lib/app/models.d.ts +0 -73
  26. package/dist-lib/app/widget-renderer.component.d.ts +0 -40
  27. package/dist-lib/esm2020/app/app.module.mjs +0 -65
  28. package/dist-lib/esm2020/app/dashboard-state.service.mjs +0 -218
  29. package/dist-lib/esm2020/app/dashboard.component.mjs +0 -703
  30. package/dist-lib/esm2020/app/models.mjs +0 -2
  31. package/dist-lib/esm2020/app/widget-renderer.component.mjs +0 -163
  32. package/dist-lib/esm2020/public-api.mjs +0 -9
  33. package/dist-lib/fesm2015/ogidor-dashboard.mjs +0 -1154
  34. package/dist-lib/fesm2015/ogidor-dashboard.mjs.map +0 -1
  35. package/dist-lib/fesm2020/ogidor-dashboard.mjs +0 -1145
  36. package/dist-lib/fesm2020/ogidor-dashboard.mjs.map +0 -1
  37. package/dist-lib/package.json +0 -51
  38. /package/{dist-lib/esm2020 → esm2020}/ogidor-dashboard.mjs +0 -0
  39. /package/{dist-lib/index.d.ts → index.d.ts} +0 -0
@@ -1,703 +0,0 @@
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=