ng-kinintel 0.0.397 → 20.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/ng-kinintel.mjs +11874 -0
- package/fesm2022/ng-kinintel.mjs.map +1 -0
- package/index.d.ts +2818 -5
- package/package.json +6 -14
- package/esm2020/lib/components/alert-groups/alert-groups.component.mjs +0 -76
- package/esm2020/lib/components/alert-groups/edit-alert-group/edit-alert-group.component.mjs +0 -83
- package/esm2020/lib/components/dashboard-editor/configure-item/configure-item.component.mjs +0 -853
- package/esm2020/lib/components/dashboard-editor/configure-item/edit-dashboard-alert/edit-dashboard-alert.component.mjs +0 -56
- package/esm2020/lib/components/dashboard-editor/configure-item/html-documentation/html-documentation.component.mjs +0 -114
- package/esm2020/lib/components/dashboard-editor/configure-item/table-cell-formatter/table-cell-formatter.component.mjs +0 -163
- package/esm2020/lib/components/dashboard-editor/configure-item/vis-network-options.json +0 -135
- package/esm2020/lib/components/dashboard-editor/dashboard-editor.component.mjs +0 -580
- package/esm2020/lib/components/dashboard-editor/dashboard-parameter/dashboard-parameter.component.mjs +0 -15
- package/esm2020/lib/components/dashboard-editor/dashboard-settings/dashboard-settings.component.mjs +0 -50
- package/esm2020/lib/components/dashboard-editor/item-component/item-component.component.mjs +0 -1226
- package/esm2020/lib/components/dashboard-editor/source-selector-dialog/source-selector-dialog.component.mjs +0 -111
- package/esm2020/lib/components/dashboards/dashboards.component.mjs +0 -163
- package/esm2020/lib/components/dashboards/view-dashboard/view-dashboard.component.mjs +0 -429
- package/esm2020/lib/components/data-explorer/change-source-warning/change-source-warning.component.mjs +0 -20
- package/esm2020/lib/components/data-explorer/data-explorer.component.mjs +0 -243
- package/esm2020/lib/components/data-explorer/export-data/export-data.component.mjs +0 -62
- package/esm2020/lib/components/data-explorer/snapshot-api-access/snapshot-api-access.component.mjs +0 -70
- package/esm2020/lib/components/data-explorer/snapshot-profile-dialog/snapshot-profile-dialog.component.mjs +0 -190
- package/esm2020/lib/components/data-picker/data-picker.component.mjs +0 -79
- package/esm2020/lib/components/data-search/data-search.component.mjs +0 -11
- package/esm2020/lib/components/data-sharing-invite/data-sharing-invite.component.mjs +0 -52
- package/esm2020/lib/components/dataset/create-dataset/create-dataset.component.mjs +0 -47
- package/esm2020/lib/components/dataset/dataset-editor/available-columns/available-columns.component.mjs +0 -28
- package/esm2020/lib/components/dataset/dataset-editor/dataset-add-join/dataset-add-join.component.mjs +0 -344
- package/esm2020/lib/components/dataset/dataset-editor/dataset-column-settings/dataset-column-editor/dataset-column-editor.component.mjs +0 -80
- package/esm2020/lib/components/dataset/dataset-editor/dataset-column-settings/dataset-column-settings.component.mjs +0 -54
- package/esm2020/lib/components/dataset/dataset-editor/dataset-create-formula/dataset-create-formula.component.mjs +0 -67
- package/esm2020/lib/components/dataset/dataset-editor/dataset-editor.component.mjs +0 -1134
- package/esm2020/lib/components/dataset/dataset-editor/dataset-filters/dataset-filter/dataset-filter.component.mjs +0 -201
- package/esm2020/lib/components/dataset/dataset-editor/dataset-filters/dataset-filter-inclusion/dataset-filter-inclusion.component.mjs +0 -25
- package/esm2020/lib/components/dataset/dataset-editor/dataset-filters/dataset-filter-junction/dataset-filter-junction.component.mjs +0 -72
- package/esm2020/lib/components/dataset/dataset-editor/dataset-filters/dataset-filters.component.mjs +0 -62
- package/esm2020/lib/components/dataset/dataset-editor/dataset-name-dialog/dataset-name-dialog.component.mjs +0 -41
- package/esm2020/lib/components/dataset/dataset-editor/dataset-parameter-values/dataset-add-parameter/dataset-add-parameter.component.mjs +0 -78
- package/esm2020/lib/components/dataset/dataset-editor/dataset-parameter-values/dataset-parameter-type/dataset-parameter-type.component.mjs +0 -39
- package/esm2020/lib/components/dataset/dataset-editor/dataset-parameter-values/dataset-parameter-values.component.mjs +0 -75
- package/esm2020/lib/components/dataset/dataset-editor/dataset-summarise/dataset-summarise.component.mjs +0 -107
- package/esm2020/lib/components/dataset/dataset-editor/move-transformation-confirmation/move-transformation-confirmation.component.mjs +0 -20
- package/esm2020/lib/components/dataset/dataset-editor/remove-transformation-warning/remove-transformation-warning.component.mjs +0 -20
- package/esm2020/lib/components/dataset/dataset-editor/save-as-query/save-as-query.component.mjs +0 -58
- package/esm2020/lib/components/dataset/dataset-editor/share-query/share-query.component.mjs +0 -110
- package/esm2020/lib/components/dataset/dataset-editor/upstream-changes-confirmation/upstream-changes-confirmation.component.mjs +0 -20
- package/esm2020/lib/components/dataset/dataset.component.mjs +0 -294
- package/esm2020/lib/components/datasource/create-datasource/advanced-settings/advanced-settings.component.mjs +0 -130
- package/esm2020/lib/components/datasource/create-datasource/api-access/api-access.component.mjs +0 -132
- package/esm2020/lib/components/datasource/create-datasource/create-datasource.component.mjs +0 -729
- package/esm2020/lib/components/datasource/create-datasource/import-data/import-data.component.mjs +0 -146
- package/esm2020/lib/components/datasource/create-datasource/import-data/import-wizard/import-wizard.component.mjs +0 -165
- package/esm2020/lib/components/datasource/create-datasource/tabular-datasource/tabular-datasource.component.mjs +0 -145
- package/esm2020/lib/components/datasource/datasource.component.mjs +0 -162
- package/esm2020/lib/components/datasource/document-datasource/document-datasource.component.mjs +0 -297
- package/esm2020/lib/components/export-project/export-project.component.mjs +0 -29
- package/esm2020/lib/components/feeds/feed/feed.component.mjs +0 -92
- package/esm2020/lib/components/feeds/feeds.component.mjs +0 -145
- package/esm2020/lib/components/job-tasks/job-tasks.component.mjs +0 -25
- package/esm2020/lib/components/marketplace/marketplace.component.mjs +0 -65
- package/esm2020/lib/components/metadata/metadata.component.mjs +0 -65
- package/esm2020/lib/components/notification-groups/edit-notification-group/edit-notification-group.component.mjs +0 -113
- package/esm2020/lib/components/notification-groups/notification-groups.component.mjs +0 -86
- package/esm2020/lib/components/project-picker/project-picker.component.mjs +0 -118
- package/esm2020/lib/components/project-settings/project-link-selection/project-link-selection.component.mjs +0 -104
- package/esm2020/lib/components/project-settings/project-settings.component.mjs +0 -155
- package/esm2020/lib/components/query-caching/edit-query-cache/edit-query-cache.component.mjs +0 -51
- package/esm2020/lib/components/query-caching/query-cache-view/query-cache-view.component.mjs +0 -121
- package/esm2020/lib/components/query-caching/query-caching.component.mjs +0 -162
- package/esm2020/lib/components/shared-with-me/feed-api-modal/feed-api-modal.component.mjs +0 -45
- package/esm2020/lib/components/shared-with-me/shared-with-me.component.mjs +0 -174
- package/esm2020/lib/components/snapshots/snapshots.component.mjs +0 -244
- package/esm2020/lib/components/tag-picker/tag-picker.component.mjs +0 -74
- package/esm2020/lib/components/task-time-periods/task-time-periods.component.mjs +0 -55
- package/esm2020/lib/components/whitelisted-sql-functions/whitelisted-sql-functions.component.mjs +0 -40
- package/esm2020/lib/guards/dashboard-changes.guard.mjs +0 -22
- package/esm2020/lib/kinintel-config.mjs +0 -3
- package/esm2020/lib/ng-kinintel.module.mjs +0 -437
- package/esm2020/lib/objects/action-event.mjs +0 -16
- package/esm2020/lib/services/alert.service.mjs +0 -52
- package/esm2020/lib/services/dashboard.service.mjs +0 -75
- package/esm2020/lib/services/data-processor.service.mjs +0 -56
- package/esm2020/lib/services/data-search.service.mjs +0 -36
- package/esm2020/lib/services/dataset.service.mjs +0 -187
- package/esm2020/lib/services/datasource.service.mjs +0 -93
- package/esm2020/lib/services/external.service.mjs +0 -33
- package/esm2020/lib/services/feed.service.mjs +0 -50
- package/esm2020/lib/services/notification.service.mjs +0 -41
- package/esm2020/lib/services/project.service.mjs +0 -130
- package/esm2020/lib/services/tag.service.mjs +0 -63
- package/esm2020/ng-kinintel.mjs +0 -5
- package/esm2020/public-api.mjs +0 -43
- package/fesm2015/ng-kinintel.mjs +0 -12182
- package/fesm2015/ng-kinintel.mjs.map +0 -1
- package/fesm2020/ng-kinintel.mjs +0 -11872
- package/fesm2020/ng-kinintel.mjs.map +0 -1
- package/lib/components/alert-groups/alert-groups.component.d.ts +0 -30
- package/lib/components/alert-groups/edit-alert-group/edit-alert-group.component.d.ts +0 -28
- package/lib/components/dashboard-editor/configure-item/configure-item.component.d.ts +0 -256
- package/lib/components/dashboard-editor/configure-item/edit-dashboard-alert/edit-dashboard-alert.component.d.ts +0 -16
- package/lib/components/dashboard-editor/configure-item/html-documentation/html-documentation.component.d.ts +0 -59
- package/lib/components/dashboard-editor/configure-item/table-cell-formatter/table-cell-formatter.component.d.ts +0 -26
- package/lib/components/dashboard-editor/dashboard-editor.component.d.ts +0 -85
- package/lib/components/dashboard-editor/dashboard-parameter/dashboard-parameter.component.d.ts +0 -8
- package/lib/components/dashboard-editor/dashboard-settings/dashboard-settings.component.d.ts +0 -22
- package/lib/components/dashboard-editor/item-component/item-component.component.d.ts +0 -264
- package/lib/components/dashboard-editor/source-selector-dialog/source-selector-dialog.component.d.ts +0 -30
- package/lib/components/dashboards/dashboards.component.d.ts +0 -56
- package/lib/components/dashboards/view-dashboard/view-dashboard.component.d.ts +0 -81
- package/lib/components/data-explorer/change-source-warning/change-source-warning.component.d.ts +0 -11
- package/lib/components/data-explorer/data-explorer.component.d.ts +0 -61
- package/lib/components/data-explorer/export-data/export-data.component.d.ts +0 -17
- package/lib/components/data-explorer/snapshot-api-access/snapshot-api-access.component.d.ts +0 -25
- package/lib/components/data-explorer/snapshot-profile-dialog/snapshot-profile-dialog.component.d.ts +0 -44
- package/lib/components/data-picker/data-picker.component.d.ts +0 -32
- package/lib/components/data-search/data-search.component.d.ts +0 -5
- package/lib/components/data-sharing-invite/data-sharing-invite.component.d.ts +0 -21
- package/lib/components/dataset/create-dataset/create-dataset.component.d.ts +0 -17
- package/lib/components/dataset/dataset-editor/available-columns/available-columns.component.d.ts +0 -12
- package/lib/components/dataset/dataset-editor/dataset-add-join/dataset-add-join.component.d.ts +0 -61
- package/lib/components/dataset/dataset-editor/dataset-column-settings/dataset-column-editor/dataset-column-editor.component.d.ts +0 -21
- package/lib/components/dataset/dataset-editor/dataset-column-settings/dataset-column-settings.component.d.ts +0 -20
- package/lib/components/dataset/dataset-editor/dataset-create-formula/dataset-create-formula.component.d.ts +0 -19
- package/lib/components/dataset/dataset-editor/dataset-editor.component.d.ts +0 -131
- package/lib/components/dataset/dataset-editor/dataset-filters/dataset-filter/dataset-filter.component.d.ts +0 -63
- package/lib/components/dataset/dataset-editor/dataset-filters/dataset-filter-inclusion/dataset-filter-inclusion.component.d.ts +0 -11
- package/lib/components/dataset/dataset-editor/dataset-filters/dataset-filter-junction/dataset-filter-junction.component.d.ts +0 -20
- package/lib/components/dataset/dataset-editor/dataset-filters/dataset-filters.component.d.ts +0 -16
- package/lib/components/dataset/dataset-editor/dataset-name-dialog/dataset-name-dialog.component.d.ts +0 -18
- package/lib/components/dataset/dataset-editor/dataset-parameter-values/dataset-add-parameter/dataset-add-parameter.component.d.ts +0 -23
- package/lib/components/dataset/dataset-editor/dataset-parameter-values/dataset-parameter-type/dataset-parameter-type.component.d.ts +0 -13
- package/lib/components/dataset/dataset-editor/dataset-parameter-values/dataset-parameter-values.component.d.ts +0 -22
- package/lib/components/dataset/dataset-editor/dataset-summarise/dataset-summarise.component.d.ts +0 -27
- package/lib/components/dataset/dataset-editor/move-transformation-confirmation/move-transformation-confirmation.component.d.ts +0 -11
- package/lib/components/dataset/dataset-editor/remove-transformation-warning/remove-transformation-warning.component.d.ts +0 -11
- package/lib/components/dataset/dataset-editor/save-as-query/save-as-query.component.d.ts +0 -25
- package/lib/components/dataset/dataset-editor/share-query/share-query.component.d.ts +0 -41
- package/lib/components/dataset/dataset-editor/upstream-changes-confirmation/upstream-changes-confirmation.component.d.ts +0 -11
- package/lib/components/dataset/dataset.component.d.ts +0 -74
- package/lib/components/datasource/create-datasource/advanced-settings/advanced-settings.component.d.ts +0 -26
- package/lib/components/datasource/create-datasource/api-access/api-access.component.d.ts +0 -31
- package/lib/components/datasource/create-datasource/create-datasource.component.d.ts +0 -112
- package/lib/components/datasource/create-datasource/import-data/import-data.component.d.ts +0 -28
- package/lib/components/datasource/create-datasource/import-data/import-wizard/import-wizard.component.d.ts +0 -40
- package/lib/components/datasource/create-datasource/tabular-datasource/tabular-datasource.component.d.ts +0 -34
- package/lib/components/datasource/datasource.component.d.ts +0 -46
- package/lib/components/datasource/document-datasource/document-datasource.component.d.ts +0 -64
- package/lib/components/export-project/export-project.component.d.ts +0 -9
- package/lib/components/feeds/feed/feed.component.d.ts +0 -30
- package/lib/components/feeds/feeds.component.d.ts +0 -47
- package/lib/components/job-tasks/job-tasks.component.d.ts +0 -11
- package/lib/components/marketplace/marketplace.component.d.ts +0 -42
- package/lib/components/metadata/metadata.component.d.ts +0 -24
- package/lib/components/notification-groups/edit-notification-group/edit-notification-group.component.d.ts +0 -37
- package/lib/components/notification-groups/notification-groups.component.d.ts +0 -28
- package/lib/components/project-picker/project-picker.component.d.ts +0 -37
- package/lib/components/project-settings/project-link-selection/project-link-selection.component.d.ts +0 -32
- package/lib/components/project-settings/project-settings.component.d.ts +0 -40
- package/lib/components/query-caching/edit-query-cache/edit-query-cache.component.d.ts +0 -17
- package/lib/components/query-caching/query-cache-view/query-cache-view.component.d.ts +0 -35
- package/lib/components/query-caching/query-caching.component.d.ts +0 -38
- package/lib/components/shared-with-me/feed-api-modal/feed-api-modal.component.d.ts +0 -21
- package/lib/components/shared-with-me/shared-with-me.component.d.ts +0 -43
- package/lib/components/snapshots/snapshots.component.d.ts +0 -52
- package/lib/components/tag-picker/tag-picker.component.d.ts +0 -27
- package/lib/components/task-time-periods/task-time-periods.component.d.ts +0 -20
- package/lib/components/whitelisted-sql-functions/whitelisted-sql-functions.component.d.ts +0 -17
- package/lib/guards/dashboard-changes.guard.d.ts +0 -11
- package/lib/kinintel-config.d.ts +0 -10
- package/lib/ng-kinintel.module.d.ts +0 -116
- package/lib/objects/action-event.d.ts +0 -12
- package/lib/services/alert.service.d.ts +0 -17
- package/lib/services/dashboard.service.d.ts +0 -25
- package/lib/services/data-processor.service.d.ts +0 -18
- package/lib/services/data-search.service.d.ts +0 -14
- package/lib/services/dataset.service.d.ts +0 -56
- package/lib/services/datasource.service.d.ts +0 -34
- package/lib/services/external.service.d.ts +0 -12
- package/lib/services/feed.service.d.ts +0 -19
- package/lib/services/notification.service.d.ts +0 -16
- package/lib/services/project.service.d.ts +0 -27
- package/lib/services/tag.service.d.ts +0 -19
- package/public-api.d.ts +0 -38
|
@@ -1,1134 +0,0 @@
|
|
|
1
|
-
import { Component, Inject, Input, Output, EventEmitter } from '@angular/core';
|
|
2
|
-
import * as lodash from 'lodash';
|
|
3
|
-
import { MAT_LEGACY_DIALOG_DATA as MAT_DIALOG_DATA } from '@angular/material/legacy-dialog';
|
|
4
|
-
import { DatasetSummariseComponent } from './dataset-summarise/dataset-summarise.component';
|
|
5
|
-
import { DatasetAddJoinComponent } from './dataset-add-join/dataset-add-join.component';
|
|
6
|
-
import { DatasetCreateFormulaComponent } from './dataset-create-formula/dataset-create-formula.component';
|
|
7
|
-
import { DatasetColumnSettingsComponent } from './dataset-column-settings/dataset-column-settings.component';
|
|
8
|
-
import { DatasetFilterComponent } from './dataset-filters/dataset-filter/dataset-filter.component';
|
|
9
|
-
import { DatasetAddParameterComponent } from './dataset-parameter-values/dataset-add-parameter/dataset-add-parameter.component';
|
|
10
|
-
import { BehaviorSubject } from 'rxjs';
|
|
11
|
-
import moment from 'moment';
|
|
12
|
-
import { UpstreamChangesConfirmationComponent } from '../dataset-editor/upstream-changes-confirmation/upstream-changes-confirmation.component';
|
|
13
|
-
import { DatasetNameDialogComponent } from '../dataset-editor/dataset-name-dialog/dataset-name-dialog.component';
|
|
14
|
-
import { moveItemInArray } from '@angular/cdk/drag-drop';
|
|
15
|
-
import { MoveTransformationConfirmationComponent } from '../dataset-editor/move-transformation-confirmation/move-transformation-confirmation.component';
|
|
16
|
-
import { SaveAsQueryComponent } from '../dataset-editor/save-as-query/save-as-query.component';
|
|
17
|
-
import { ShareQueryComponent } from '../dataset-editor/share-query/share-query.component';
|
|
18
|
-
import { RemoveTransformationWarningComponent } from '../dataset-editor/remove-transformation-warning/remove-transformation-warning.component';
|
|
19
|
-
import { COMMA, ENTER } from "@angular/cdk/keycodes";
|
|
20
|
-
import * as i0 from "@angular/core";
|
|
21
|
-
import * as i1 from "@angular/material/legacy-dialog";
|
|
22
|
-
import * as i2 from "../../../services/dataset.service";
|
|
23
|
-
import * as i3 from "@angular/material/legacy-snack-bar";
|
|
24
|
-
import * as i4 from "@angular/common";
|
|
25
|
-
import * as i5 from "@angular/material/legacy-button";
|
|
26
|
-
import * as i6 from "@angular/material/icon";
|
|
27
|
-
import * as i7 from "@angular/material/legacy-menu";
|
|
28
|
-
import * as i8 from "@angular/material/legacy-input";
|
|
29
|
-
import * as i9 from "@angular/material/chips";
|
|
30
|
-
import * as i10 from "@angular/material/legacy-table";
|
|
31
|
-
import * as i11 from "@angular/material/sort";
|
|
32
|
-
import * as i12 from "@angular/cdk/drag-drop";
|
|
33
|
-
import * as i13 from "@angular/forms";
|
|
34
|
-
import * as i14 from "@angular/material/legacy-slide-toggle";
|
|
35
|
-
import * as i15 from "@angular/material/legacy-progress-spinner";
|
|
36
|
-
import * as i16 from "@angular/material/legacy-tooltip";
|
|
37
|
-
import * as i17 from "@angular/cdk/overlay";
|
|
38
|
-
import * as i18 from "./dataset-filters/dataset-filters.component";
|
|
39
|
-
import * as i19 from "../../whitelisted-sql-functions/whitelisted-sql-functions.component";
|
|
40
|
-
const _ = lodash.default;
|
|
41
|
-
export class DatasetEditorComponent {
|
|
42
|
-
constructor(dialogRef, data, dialog, datasetService, snackBar) {
|
|
43
|
-
this.dialogRef = dialogRef;
|
|
44
|
-
this.data = data;
|
|
45
|
-
this.dialog = dialog;
|
|
46
|
-
this.datasetService = datasetService;
|
|
47
|
-
this.snackBar = snackBar;
|
|
48
|
-
this.environment = {};
|
|
49
|
-
this.datasetEditorReadonly = false;
|
|
50
|
-
this.datasetEditorSimpleMode = false;
|
|
51
|
-
this.datasetEditorNoTools = false;
|
|
52
|
-
this.dataLoaded = new EventEmitter();
|
|
53
|
-
this.datasetInstanceSummaryChange = new EventEmitter();
|
|
54
|
-
this.tableData = [];
|
|
55
|
-
this.showFilters = false;
|
|
56
|
-
this.showParameters = false;
|
|
57
|
-
this.displayedColumns = [];
|
|
58
|
-
this._ = _;
|
|
59
|
-
this.Array = Array;
|
|
60
|
-
this.Object = Object;
|
|
61
|
-
this.filterFields = [];
|
|
62
|
-
this.filterJunction = {
|
|
63
|
-
logic: 'AND',
|
|
64
|
-
filters: [{
|
|
65
|
-
lhsExpression: '',
|
|
66
|
-
rhsExpression: [],
|
|
67
|
-
filterType: ''
|
|
68
|
-
}],
|
|
69
|
-
filterJunctions: []
|
|
70
|
-
};
|
|
71
|
-
this.page = 1;
|
|
72
|
-
this.endOfResults = false;
|
|
73
|
-
this.parameterValues = [];
|
|
74
|
-
this.focusParams = false;
|
|
75
|
-
this.terminatingTransformations = [];
|
|
76
|
-
this.String = String;
|
|
77
|
-
this.longRunning = false;
|
|
78
|
-
this.sideOpen = false;
|
|
79
|
-
this.openSide = new BehaviorSubject(false);
|
|
80
|
-
this.limit = 25;
|
|
81
|
-
this.offset = 0;
|
|
82
|
-
this.decodeURIComponent = decodeURIComponent;
|
|
83
|
-
this.decodeURI = decodeURI;
|
|
84
|
-
this.ENTER = ENTER;
|
|
85
|
-
this.COMMA = COMMA;
|
|
86
|
-
}
|
|
87
|
-
async ngOnInit() {
|
|
88
|
-
let limit = null;
|
|
89
|
-
limit = localStorage.getItem('datasetInstanceLimit' + this.datasetInstanceSummary.id);
|
|
90
|
-
this.limit = limit ? Number(limit) : 25;
|
|
91
|
-
if (this.datasetInstanceSummary.transformationInstances.length) {
|
|
92
|
-
const filters = _.filter(this.datasetInstanceSummary.transformationInstances, { type: 'filter' });
|
|
93
|
-
if (filters.length) {
|
|
94
|
-
filters.forEach(filter => {
|
|
95
|
-
filter.hide = true;
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
if (Array.isArray(this.datasetInstanceSummary.parameterValues)) {
|
|
100
|
-
this.datasetInstanceSummary.parameterValues = {};
|
|
101
|
-
}
|
|
102
|
-
if (!this.datasetInstanceSummary.id) {
|
|
103
|
-
this.datasetTitle = this.datasetInstanceSummary.title;
|
|
104
|
-
}
|
|
105
|
-
this.evaluateDataset();
|
|
106
|
-
this.openSide.subscribe((open) => {
|
|
107
|
-
if (open) {
|
|
108
|
-
document.getElementById('sidebarWrapper')?.classList.add('z-20');
|
|
109
|
-
document.getElementById('sidebarWrapper')?.classList.remove('-z-10');
|
|
110
|
-
}
|
|
111
|
-
else {
|
|
112
|
-
setTimeout(() => {
|
|
113
|
-
document.getElementById('sidebarWrapper')?.classList.add('-z-10');
|
|
114
|
-
document.getElementById('sidebarWrapper')?.classList.remove('z-20');
|
|
115
|
-
}, 700);
|
|
116
|
-
}
|
|
117
|
-
this.sideOpen = open;
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
ngOnDestroy() {
|
|
121
|
-
if (this.evaluateSub) {
|
|
122
|
-
this.evaluateSub.unsubscribe();
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
async shareQuery() {
|
|
126
|
-
this.dialog.open(ShareQueryComponent, {
|
|
127
|
-
width: '800px',
|
|
128
|
-
height: '950px',
|
|
129
|
-
data: {
|
|
130
|
-
datasetInstance: this.datasetInstanceSummary
|
|
131
|
-
}
|
|
132
|
-
}).afterClosed().subscribe(res => {
|
|
133
|
-
});
|
|
134
|
-
}
|
|
135
|
-
async saveAsQuery() {
|
|
136
|
-
const newDatasetInstance = {
|
|
137
|
-
title: this.datasetInstanceSummary.title || 'Stored Query' + ' COPY',
|
|
138
|
-
summary: '',
|
|
139
|
-
description: '',
|
|
140
|
-
categories: this.datasetInstanceSummary.categories,
|
|
141
|
-
datasourceInstanceKey: this.datasetInstanceSummary.datasourceInstanceKey,
|
|
142
|
-
datasetInstanceId: this.datasetInstanceSummary.datasetInstanceId,
|
|
143
|
-
tags: this.datasetInstanceSummary.tags,
|
|
144
|
-
parameterValue: this.datasetInstanceSummary.parameterValues,
|
|
145
|
-
parameters: this.datasetInstanceSummary.parameters
|
|
146
|
-
};
|
|
147
|
-
this.dialog.open(SaveAsQueryComponent, {
|
|
148
|
-
width: '700px',
|
|
149
|
-
height: '800px',
|
|
150
|
-
data: {
|
|
151
|
-
datasetInstanceSummary: newDatasetInstance,
|
|
152
|
-
transformations: this.datasetInstanceSummary.transformationInstances
|
|
153
|
-
}
|
|
154
|
-
}).afterClosed().subscribe(async (transformationInstances) => {
|
|
155
|
-
if (transformationInstances) {
|
|
156
|
-
newDatasetInstance.transformationInstances = transformationInstances;
|
|
157
|
-
await this.datasetService.saveDataset(newDatasetInstance, this.accountId);
|
|
158
|
-
this.snackBar.open('Dataset successfully copied.', 'Close', {
|
|
159
|
-
verticalPosition: 'top',
|
|
160
|
-
duration: 3000
|
|
161
|
-
});
|
|
162
|
-
}
|
|
163
|
-
});
|
|
164
|
-
}
|
|
165
|
-
drop(event) {
|
|
166
|
-
this.dialog.open(MoveTransformationConfirmationComponent, {
|
|
167
|
-
width: '700px',
|
|
168
|
-
height: '275px'
|
|
169
|
-
}).afterClosed().subscribe(res => {
|
|
170
|
-
if (res === 'proceed') {
|
|
171
|
-
moveItemInArray(this.datasetInstanceSummary.transformationInstances, event.previousContainer.data.index, event.container.data.index);
|
|
172
|
-
this.evaluateDataset();
|
|
173
|
-
}
|
|
174
|
-
});
|
|
175
|
-
}
|
|
176
|
-
async insertTransformation(index, transformationType, nextTransformation) {
|
|
177
|
-
await this.excludeUpstreamTransformations(nextTransformation);
|
|
178
|
-
switch (transformationType) {
|
|
179
|
-
case 'columns':
|
|
180
|
-
this.editColumnSettings(null, null, index);
|
|
181
|
-
break;
|
|
182
|
-
case 'formula':
|
|
183
|
-
this.createFormula(null, null, index);
|
|
184
|
-
break;
|
|
185
|
-
case 'join':
|
|
186
|
-
this.joinData(null, null, index);
|
|
187
|
-
break;
|
|
188
|
-
case 'summarise':
|
|
189
|
-
this.summariseData(null, null, index);
|
|
190
|
-
break;
|
|
191
|
-
case 'filter':
|
|
192
|
-
this.addFilter(index);
|
|
193
|
-
break;
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
addFilter(insertIndex) {
|
|
197
|
-
_.forEach(this.datasetInstanceSummary.transformationInstances || [], transformation => {
|
|
198
|
-
transformation.hide = true;
|
|
199
|
-
});
|
|
200
|
-
const filterTransformation = {
|
|
201
|
-
type: 'filter',
|
|
202
|
-
config: {
|
|
203
|
-
logic: 'AND',
|
|
204
|
-
filters: [{
|
|
205
|
-
lhsExpression: '',
|
|
206
|
-
rhsExpression: [],
|
|
207
|
-
filterType: ''
|
|
208
|
-
}],
|
|
209
|
-
filterJunctions: []
|
|
210
|
-
},
|
|
211
|
-
hide: false
|
|
212
|
-
};
|
|
213
|
-
if (!_.isNil(insertIndex) && insertIndex >= 0) {
|
|
214
|
-
this.datasetInstanceSummary.transformationInstances.splice(insertIndex, 0, filterTransformation);
|
|
215
|
-
}
|
|
216
|
-
else {
|
|
217
|
-
this.datasetInstanceSummary.transformationInstances.push(filterTransformation);
|
|
218
|
-
}
|
|
219
|
-
this.showFilters = true;
|
|
220
|
-
this.setTerminatingTransformations();
|
|
221
|
-
setTimeout(() => {
|
|
222
|
-
const filters = document.getElementById('datasetFilters');
|
|
223
|
-
if (filters) {
|
|
224
|
-
filters.scrollTo({ top: filters.scrollHeight, behavior: 'smooth' });
|
|
225
|
-
}
|
|
226
|
-
}, 0);
|
|
227
|
-
}
|
|
228
|
-
getFilterString(config) {
|
|
229
|
-
const filter = config.filters[0];
|
|
230
|
-
if (config.filters.length) {
|
|
231
|
-
if (_.every(filter)) {
|
|
232
|
-
const type = DatasetFilterComponent.getFilterType(filter.filterType);
|
|
233
|
-
if (type) {
|
|
234
|
-
const lhsExpression = filter.lhsExpression.replace('[[', '').replace(']]', '');
|
|
235
|
-
return `${_.startCase(lhsExpression)} ${type.string} ${filter.rhsExpression}`;
|
|
236
|
-
}
|
|
237
|
-
return '';
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
return '';
|
|
241
|
-
}
|
|
242
|
-
removeFilter(index) {
|
|
243
|
-
const existingMultiSort = _.find(this.datasetInstanceSummary.transformationInstances, { type: 'multisort' });
|
|
244
|
-
existingMultiSort.config.sorts.splice(index, 1);
|
|
245
|
-
if (!existingMultiSort.config.sorts.length) {
|
|
246
|
-
_.remove(this.datasetInstanceSummary.transformationInstances, { type: 'multisort' });
|
|
247
|
-
}
|
|
248
|
-
this.evaluateDataset();
|
|
249
|
-
}
|
|
250
|
-
removeTransformation(transformation, confirm = false, index, active) {
|
|
251
|
-
if (index === undefined) {
|
|
252
|
-
index = _.findIndex(this.datasetInstanceSummary.transformationInstances, {
|
|
253
|
-
type: transformation.type,
|
|
254
|
-
config: transformation.config
|
|
255
|
-
});
|
|
256
|
-
}
|
|
257
|
-
if (!active) {
|
|
258
|
-
const dialogRef = this.dialog.open(RemoveTransformationWarningComponent, {
|
|
259
|
-
width: '700px',
|
|
260
|
-
height: '275px'
|
|
261
|
-
});
|
|
262
|
-
dialogRef.afterClosed().subscribe(proceed => {
|
|
263
|
-
if (proceed) {
|
|
264
|
-
this._removeTransformation(transformation, index);
|
|
265
|
-
}
|
|
266
|
-
});
|
|
267
|
-
}
|
|
268
|
-
else {
|
|
269
|
-
if (confirm) {
|
|
270
|
-
const message = 'Are you sure you would like to remove this transformation?';
|
|
271
|
-
if (window.confirm(message)) {
|
|
272
|
-
this._removeTransformation(transformation, index);
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
else {
|
|
276
|
-
this._removeTransformation(transformation, index);
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
enableAllTransformation() {
|
|
281
|
-
this.datasetInstanceSummary.transformationInstances.forEach((transformation) => {
|
|
282
|
-
transformation.exclude = false;
|
|
283
|
-
});
|
|
284
|
-
this.evaluateDataset();
|
|
285
|
-
}
|
|
286
|
-
disableTransformation(transformation, index) {
|
|
287
|
-
transformation.exclude = !transformation.exclude;
|
|
288
|
-
this.evaluateDataset();
|
|
289
|
-
}
|
|
290
|
-
showTransformationDetail(transformation) {
|
|
291
|
-
const clone = _.clone(transformation);
|
|
292
|
-
this.terminatingTransformations.forEach(item => {
|
|
293
|
-
item._showDetail = false;
|
|
294
|
-
});
|
|
295
|
-
if (!clone._showDetail) {
|
|
296
|
-
transformation._showDetail = true;
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
async editTerminatingTransformation(transformation) {
|
|
300
|
-
const [clonedTransformation, existingIndex] = await this.excludeUpstreamTransformations(transformation);
|
|
301
|
-
if (transformation.type === 'filter') {
|
|
302
|
-
const hiddenValue = !transformation.hide;
|
|
303
|
-
const filters = _.filter(this.datasetInstanceSummary.transformationInstances, { type: 'filter' });
|
|
304
|
-
filters.forEach(filter => {
|
|
305
|
-
filter.hide = true;
|
|
306
|
-
});
|
|
307
|
-
transformation.hide = hiddenValue;
|
|
308
|
-
this.showFilters = !hiddenValue;
|
|
309
|
-
}
|
|
310
|
-
else {
|
|
311
|
-
if (transformation.type === 'summarise') {
|
|
312
|
-
this.summariseData(clonedTransformation.config, existingIndex);
|
|
313
|
-
}
|
|
314
|
-
if (transformation.type === 'join') {
|
|
315
|
-
this.joinData(clonedTransformation, existingIndex);
|
|
316
|
-
}
|
|
317
|
-
if (transformation.type === 'formula') {
|
|
318
|
-
this.createFormula(clonedTransformation, existingIndex);
|
|
319
|
-
}
|
|
320
|
-
if (transformation.type === 'columns') {
|
|
321
|
-
this.editColumnSettings(clonedTransformation, existingIndex);
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
exportData() {
|
|
326
|
-
}
|
|
327
|
-
async editColumnSettings(existingTransformation, existingIndex, insertIndex) {
|
|
328
|
-
const clonedColumns = existingTransformation ? _.clone(existingTransformation.config.columns) : null;
|
|
329
|
-
const resetColumnNames = existingTransformation ? existingTransformation.config.resetColumnNames : true;
|
|
330
|
-
const namingConvention = existingTransformation ? existingTransformation.config.namingConvention : "CAMEL";
|
|
331
|
-
const columnSettings = [];
|
|
332
|
-
if (clonedColumns) {
|
|
333
|
-
clonedColumns.forEach(column => {
|
|
334
|
-
column.selected = true;
|
|
335
|
-
columnSettings.push(column);
|
|
336
|
-
});
|
|
337
|
-
}
|
|
338
|
-
this.filterFields.forEach(field => {
|
|
339
|
-
if (!_.find(columnSettings, { name: field.name })) {
|
|
340
|
-
columnSettings.push(field);
|
|
341
|
-
}
|
|
342
|
-
});
|
|
343
|
-
const dialogRef = this.dialog.open(DatasetColumnSettingsComponent, {
|
|
344
|
-
width: '1000px',
|
|
345
|
-
height: '800px',
|
|
346
|
-
disableClose: true,
|
|
347
|
-
data: {
|
|
348
|
-
columns: columnSettings,
|
|
349
|
-
reset: !!_.find(this.datasetInstanceSummary.transformationInstances, { type: 'columns' }),
|
|
350
|
-
resetFields: _.clone(this.filterFields),
|
|
351
|
-
resetColumnNames,
|
|
352
|
-
namingConvention
|
|
353
|
-
}
|
|
354
|
-
});
|
|
355
|
-
dialogRef.afterClosed().subscribe(result => {
|
|
356
|
-
const columns = result.columns;
|
|
357
|
-
if (columns) {
|
|
358
|
-
const fields = _.map(columns, column => {
|
|
359
|
-
return { title: column.title, name: column.name };
|
|
360
|
-
});
|
|
361
|
-
const columnTransformation = {
|
|
362
|
-
type: 'columns',
|
|
363
|
-
config: {
|
|
364
|
-
columns: fields,
|
|
365
|
-
resetColumnNames: result.resetColumnNames,
|
|
366
|
-
namingConvention: result.namingConvention
|
|
367
|
-
}
|
|
368
|
-
};
|
|
369
|
-
if (!_.isNil(existingIndex) && existingIndex > -1) {
|
|
370
|
-
this.datasetInstanceSummary.transformationInstances[existingIndex] = columnTransformation;
|
|
371
|
-
}
|
|
372
|
-
else if (!_.isNil(insertIndex) && insertIndex >= 0) {
|
|
373
|
-
this.datasetInstanceSummary.transformationInstances.splice(insertIndex, 0, columnTransformation);
|
|
374
|
-
}
|
|
375
|
-
else {
|
|
376
|
-
this.datasetInstanceSummary.transformationInstances.push(columnTransformation);
|
|
377
|
-
}
|
|
378
|
-
this.evaluateDataset();
|
|
379
|
-
}
|
|
380
|
-
else {
|
|
381
|
-
if (clonedColumns) {
|
|
382
|
-
this.datasetInstanceSummary.transformationInstances[existingIndex] = {
|
|
383
|
-
type: 'columns',
|
|
384
|
-
config: {
|
|
385
|
-
columns: clonedColumns
|
|
386
|
-
}
|
|
387
|
-
};
|
|
388
|
-
this.datasetInstanceSummary.transformationInstances.forEach((instance, index) => {
|
|
389
|
-
instance.exclude = false;
|
|
390
|
-
});
|
|
391
|
-
this.evaluateDataset();
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
});
|
|
395
|
-
}
|
|
396
|
-
createFormula(existingTransformation, existingIndex, insertIndex) {
|
|
397
|
-
const clonedExpressions = existingTransformation ? _.clone(existingTransformation.config.expressions) : null;
|
|
398
|
-
const dialogRef = this.dialog.open(DatasetCreateFormulaComponent, {
|
|
399
|
-
width: '900px',
|
|
400
|
-
height: '800px',
|
|
401
|
-
disableClose: true,
|
|
402
|
-
data: {
|
|
403
|
-
allColumns: this.filterFields,
|
|
404
|
-
formulas: existingTransformation ? existingTransformation.config.expressions : [{}]
|
|
405
|
-
}
|
|
406
|
-
});
|
|
407
|
-
dialogRef.afterClosed().subscribe(formula => {
|
|
408
|
-
if (formula) {
|
|
409
|
-
const formulaTransformation = {
|
|
410
|
-
type: 'formula',
|
|
411
|
-
config: {
|
|
412
|
-
expressions: formula
|
|
413
|
-
}
|
|
414
|
-
};
|
|
415
|
-
if (!_.isNil(existingIndex) && existingIndex >= 0) {
|
|
416
|
-
this.datasetInstanceSummary.transformationInstances[existingIndex] = formulaTransformation;
|
|
417
|
-
}
|
|
418
|
-
else if (!_.isNil(insertIndex) && insertIndex >= 0) {
|
|
419
|
-
this.datasetInstanceSummary.transformationInstances.splice(insertIndex, 0, formulaTransformation);
|
|
420
|
-
}
|
|
421
|
-
else {
|
|
422
|
-
this.datasetInstanceSummary.transformationInstances.push(formulaTransformation);
|
|
423
|
-
}
|
|
424
|
-
this.evaluateDataset();
|
|
425
|
-
}
|
|
426
|
-
else {
|
|
427
|
-
// Formula was cancelled, restore if we have one
|
|
428
|
-
if (clonedExpressions) {
|
|
429
|
-
this.datasetInstanceSummary.transformationInstances[existingIndex] = {
|
|
430
|
-
type: 'formula',
|
|
431
|
-
config: {
|
|
432
|
-
expressions: clonedExpressions
|
|
433
|
-
}
|
|
434
|
-
};
|
|
435
|
-
this.datasetInstanceSummary.transformationInstances.forEach((instance, index) => {
|
|
436
|
-
instance.exclude = false;
|
|
437
|
-
});
|
|
438
|
-
this.evaluateDataset();
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
});
|
|
442
|
-
}
|
|
443
|
-
joinData(transformation, existingIndex, insertIndex) {
|
|
444
|
-
const clonedTransformation = transformation ? _.clone(transformation) : null;
|
|
445
|
-
const data = {
|
|
446
|
-
admin: this.admin,
|
|
447
|
-
environment: this.environment,
|
|
448
|
-
filterFields: this.filterFields,
|
|
449
|
-
parameterValues: _.map(this.parameterValues, param => {
|
|
450
|
-
return {
|
|
451
|
-
title: param.title,
|
|
452
|
-
name: param.name,
|
|
453
|
-
currentValue: this.datasetInstanceSummary.parameterValues[param.name]
|
|
454
|
-
};
|
|
455
|
-
}),
|
|
456
|
-
datasetEditor: this,
|
|
457
|
-
};
|
|
458
|
-
if (transformation) {
|
|
459
|
-
data.joinTransformation = {
|
|
460
|
-
type: 'join',
|
|
461
|
-
config: transformation.config
|
|
462
|
-
};
|
|
463
|
-
}
|
|
464
|
-
const dialogRef = this.dialog.open(DatasetAddJoinComponent, {
|
|
465
|
-
width: '1200px',
|
|
466
|
-
height: '800px',
|
|
467
|
-
disableClose: true,
|
|
468
|
-
data,
|
|
469
|
-
});
|
|
470
|
-
dialogRef.afterClosed().subscribe(joinTransformation => {
|
|
471
|
-
if (joinTransformation) {
|
|
472
|
-
if (!_.isNil(existingIndex) && existingIndex >= 0) {
|
|
473
|
-
this.datasetInstanceSummary.transformationInstances[existingIndex] = joinTransformation;
|
|
474
|
-
}
|
|
475
|
-
else if (!_.isNil(insertIndex) && insertIndex >= 0) {
|
|
476
|
-
this.datasetInstanceSummary.transformationInstances.splice(insertIndex, 0, joinTransformation);
|
|
477
|
-
}
|
|
478
|
-
else {
|
|
479
|
-
this.datasetInstanceSummary.transformationInstances.push(joinTransformation);
|
|
480
|
-
}
|
|
481
|
-
this.evaluateDataset(true);
|
|
482
|
-
}
|
|
483
|
-
else {
|
|
484
|
-
if (clonedTransformation) {
|
|
485
|
-
this.datasetInstanceSummary.transformationInstances[existingIndex] = clonedTransformation;
|
|
486
|
-
this.datasetInstanceSummary.transformationInstances.forEach((instance, index) => {
|
|
487
|
-
instance.exclude = false;
|
|
488
|
-
});
|
|
489
|
-
this.evaluateDataset();
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
|
-
});
|
|
493
|
-
}
|
|
494
|
-
applyFilters() {
|
|
495
|
-
const filterTransformations = _.filter(this.datasetInstanceSummary.transformationInstances, { type: 'filter' });
|
|
496
|
-
filterTransformations.forEach(transformation => {
|
|
497
|
-
this.validateFilterJunction(transformation.config);
|
|
498
|
-
});
|
|
499
|
-
this.evaluateDataset(true);
|
|
500
|
-
}
|
|
501
|
-
increaseOffset() {
|
|
502
|
-
this.page = this.page + 1;
|
|
503
|
-
this.offset = (this.limit * this.page) - this.limit;
|
|
504
|
-
this.evaluateDataset();
|
|
505
|
-
}
|
|
506
|
-
decreaseOffset() {
|
|
507
|
-
this.page = this.page <= 1 ? 1 : this.page - 1;
|
|
508
|
-
this.offset = (this.limit * this.page) - this.limit;
|
|
509
|
-
this.evaluateDataset();
|
|
510
|
-
}
|
|
511
|
-
pageSizeChange(value) {
|
|
512
|
-
this.limit = value;
|
|
513
|
-
localStorage.setItem('datasetInstanceLimit' + this.datasetInstanceSummary.id, this.limit.toString());
|
|
514
|
-
this.evaluateDataset(true);
|
|
515
|
-
}
|
|
516
|
-
addPagingMarker() {
|
|
517
|
-
this.datasetInstanceSummary.transformationInstances.push({ type: 'pagingmarker' });
|
|
518
|
-
this.evaluateDataset();
|
|
519
|
-
}
|
|
520
|
-
sort(event) {
|
|
521
|
-
const column = event.active;
|
|
522
|
-
const direction = event.direction;
|
|
523
|
-
const existingMultiSort = _.find(this.datasetInstanceSummary.transformationInstances, { type: 'multisort' });
|
|
524
|
-
if (existingMultiSort) {
|
|
525
|
-
const existingIndex = _.findIndex(existingMultiSort.config.sorts, { fieldName: column });
|
|
526
|
-
if (direction) {
|
|
527
|
-
if (existingIndex > -1) {
|
|
528
|
-
existingMultiSort.config.sorts[existingIndex] = { fieldName: column, direction };
|
|
529
|
-
}
|
|
530
|
-
else {
|
|
531
|
-
existingMultiSort.config.sorts.push({ fieldName: column, direction });
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
|
-
else {
|
|
535
|
-
existingMultiSort.config.sorts.splice(existingIndex, 1);
|
|
536
|
-
if (!existingMultiSort.config.sorts.length) {
|
|
537
|
-
_.remove(this.datasetInstanceSummary.transformationInstances, { type: 'multisort' });
|
|
538
|
-
}
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
else {
|
|
542
|
-
if (direction) {
|
|
543
|
-
this.datasetInstanceSummary.transformationInstances.push({
|
|
544
|
-
type: 'multisort',
|
|
545
|
-
config: {
|
|
546
|
-
sorts: [{ fieldName: column, direction }]
|
|
547
|
-
}
|
|
548
|
-
});
|
|
549
|
-
}
|
|
550
|
-
}
|
|
551
|
-
this.evaluateDataset(true);
|
|
552
|
-
}
|
|
553
|
-
summariseData(config, existingIndex, insertIndex) {
|
|
554
|
-
const clonedConfig = config ? _.clone(config) : null;
|
|
555
|
-
const summariseDialog = this.dialog.open(DatasetSummariseComponent, {
|
|
556
|
-
width: '1100px',
|
|
557
|
-
height: '900px',
|
|
558
|
-
disableClose: true,
|
|
559
|
-
data: {
|
|
560
|
-
availableColumns: this.filterFields,
|
|
561
|
-
config: config ? config : null,
|
|
562
|
-
originDataItemTitle: this.datasetInstanceSummary.originDataItemTitle
|
|
563
|
-
}
|
|
564
|
-
});
|
|
565
|
-
summariseDialog.afterClosed().subscribe(summariseTransformation => {
|
|
566
|
-
if (summariseTransformation) {
|
|
567
|
-
// this.datasetInstanceSummary.transformationInstances.forEach((instance, index) => {
|
|
568
|
-
// instance.exclude = false;
|
|
569
|
-
// });
|
|
570
|
-
if (!_.isNil(existingIndex) && existingIndex >= 0) {
|
|
571
|
-
// Check if anything has changed
|
|
572
|
-
if (!_.isEqual(clonedConfig, summariseTransformation) && (existingIndex + 1) < this.datasetInstanceSummary.transformationInstances.length) {
|
|
573
|
-
// Things have changed, ask user to confirm
|
|
574
|
-
this.dialog.open(UpstreamChangesConfirmationComponent, {
|
|
575
|
-
width: '700px',
|
|
576
|
-
height: '275px'
|
|
577
|
-
}).afterClosed().subscribe(res => {
|
|
578
|
-
if (res) {
|
|
579
|
-
if (res === 'remove') {
|
|
580
|
-
for (let i = existingIndex; i < this.datasetInstanceSummary.transformationInstances.length; i++) {
|
|
581
|
-
this.datasetInstanceSummary.transformationInstances.splice(i, 1);
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
|
-
this.datasetInstanceSummary.transformationInstances[existingIndex] = {
|
|
585
|
-
type: 'summarise',
|
|
586
|
-
config: summariseTransformation
|
|
587
|
-
};
|
|
588
|
-
this.evaluateDataset(true);
|
|
589
|
-
}
|
|
590
|
-
});
|
|
591
|
-
}
|
|
592
|
-
else {
|
|
593
|
-
this.datasetInstanceSummary.transformationInstances[existingIndex] = {
|
|
594
|
-
type: 'summarise',
|
|
595
|
-
config: summariseTransformation
|
|
596
|
-
};
|
|
597
|
-
this.evaluateDataset(true);
|
|
598
|
-
}
|
|
599
|
-
}
|
|
600
|
-
else if (!_.isNil(insertIndex) && insertIndex >= 0) {
|
|
601
|
-
this.datasetInstanceSummary.transformationInstances.splice(insertIndex, 0, {
|
|
602
|
-
type: 'summarise',
|
|
603
|
-
config: summariseTransformation
|
|
604
|
-
});
|
|
605
|
-
this.evaluateDataset(true);
|
|
606
|
-
}
|
|
607
|
-
else {
|
|
608
|
-
this.datasetInstanceSummary.transformationInstances.push({
|
|
609
|
-
type: 'summarise',
|
|
610
|
-
config: summariseTransformation
|
|
611
|
-
});
|
|
612
|
-
this.evaluateDataset(true);
|
|
613
|
-
}
|
|
614
|
-
}
|
|
615
|
-
else {
|
|
616
|
-
// If we get here then the summarise transformation was cancelled - restore if we have one
|
|
617
|
-
if (clonedConfig) {
|
|
618
|
-
this.datasetInstanceSummary.transformationInstances[existingIndex] = {
|
|
619
|
-
type: 'summarise',
|
|
620
|
-
config: clonedConfig
|
|
621
|
-
};
|
|
622
|
-
this.datasetInstanceSummary.transformationInstances.forEach((instance, index) => {
|
|
623
|
-
instance.exclude = false;
|
|
624
|
-
});
|
|
625
|
-
this.evaluateDataset();
|
|
626
|
-
}
|
|
627
|
-
}
|
|
628
|
-
});
|
|
629
|
-
}
|
|
630
|
-
removeParameter(parameter) {
|
|
631
|
-
const message = 'Are you sure you would like to remove this parameter. This may cause some dashboard items ' +
|
|
632
|
-
'to fail.';
|
|
633
|
-
if (window.confirm(message)) {
|
|
634
|
-
_.remove(this.parameterValues, { name: parameter.name });
|
|
635
|
-
_.remove(this.datasetInstanceSummary.parameters, { name: parameter.name });
|
|
636
|
-
this.evaluateDataset();
|
|
637
|
-
}
|
|
638
|
-
}
|
|
639
|
-
addParameter(existingParameter, parameterValueIndex) {
|
|
640
|
-
let clonedParameter = null;
|
|
641
|
-
if (existingParameter) {
|
|
642
|
-
clonedParameter = _.clone(existingParameter);
|
|
643
|
-
}
|
|
644
|
-
if (!this.showParameters) {
|
|
645
|
-
this.showParameters = true;
|
|
646
|
-
}
|
|
647
|
-
const dialogRef = this.dialog.open(DatasetAddParameterComponent, {
|
|
648
|
-
width: '750px',
|
|
649
|
-
height: '850px',
|
|
650
|
-
disableClose: true,
|
|
651
|
-
data: {
|
|
652
|
-
parameter: clonedParameter
|
|
653
|
-
}
|
|
654
|
-
});
|
|
655
|
-
dialogRef.afterClosed().subscribe(parameter => {
|
|
656
|
-
if (parameter) {
|
|
657
|
-
if (!clonedParameter) {
|
|
658
|
-
if (parameter.defaultValue) {
|
|
659
|
-
parameter.value = parameter.defaultValue;
|
|
660
|
-
}
|
|
661
|
-
this.parameterValues.push(parameter);
|
|
662
|
-
this.datasetInstanceSummary.parameters.push(parameter);
|
|
663
|
-
}
|
|
664
|
-
else {
|
|
665
|
-
if (!clonedParameter.value) {
|
|
666
|
-
parameter.value = parameter.defaultValue || '';
|
|
667
|
-
}
|
|
668
|
-
this.parameterValues[parameterValueIndex] = parameter;
|
|
669
|
-
this.datasetInstanceSummary.parameters[parameterValueIndex] = parameter;
|
|
670
|
-
}
|
|
671
|
-
if (parameter.type === 'list') {
|
|
672
|
-
this.loadListParameters(parameter);
|
|
673
|
-
}
|
|
674
|
-
this.setAvailableFilterParameters();
|
|
675
|
-
}
|
|
676
|
-
});
|
|
677
|
-
}
|
|
678
|
-
async loadListParameters(parameter) {
|
|
679
|
-
if (parameter.settings && parameter.settings.datasetInstance) {
|
|
680
|
-
return this.datasetService.evaluateDataset(parameter.settings.datasetInstance, '0', '100000')
|
|
681
|
-
.then((data) => {
|
|
682
|
-
const list = _.map(data.allData, item => {
|
|
683
|
-
return {
|
|
684
|
-
label: item[parameter.settings.labelColumn],
|
|
685
|
-
value: item[parameter.settings.valueColumn]
|
|
686
|
-
};
|
|
687
|
-
});
|
|
688
|
-
parameter.list = _.uniqWith(list, _.isEqual);
|
|
689
|
-
});
|
|
690
|
-
}
|
|
691
|
-
}
|
|
692
|
-
getOrdinal(n) {
|
|
693
|
-
const s = ['th', 'st', 'nd', 'rd'];
|
|
694
|
-
const v = n % 100;
|
|
695
|
-
return n + (s[(v - 20) % 10] || s[v] || s[0]);
|
|
696
|
-
}
|
|
697
|
-
viewFullItemData(data, columnName) {
|
|
698
|
-
this.dialog.open(DatasetEditorPopupComponent, {
|
|
699
|
-
width: '800px',
|
|
700
|
-
height: '400px',
|
|
701
|
-
data: {
|
|
702
|
-
fullData: data,
|
|
703
|
-
columnName
|
|
704
|
-
}
|
|
705
|
-
});
|
|
706
|
-
}
|
|
707
|
-
booleanUpdate(event, parameter) {
|
|
708
|
-
parameter.value = event.checked;
|
|
709
|
-
}
|
|
710
|
-
changeDateType(event, parameter, value) {
|
|
711
|
-
event.stopPropagation();
|
|
712
|
-
event.preventDefault();
|
|
713
|
-
parameter._dateType = value;
|
|
714
|
-
}
|
|
715
|
-
updatePeriodValue(value, period, parameter) {
|
|
716
|
-
parameter.value = `${value}_${period}_AGO`;
|
|
717
|
-
}
|
|
718
|
-
cancelEvaluate() {
|
|
719
|
-
if (this.resultsSub) {
|
|
720
|
-
this.resultsSub.unsubscribe();
|
|
721
|
-
}
|
|
722
|
-
this.longRunning = false;
|
|
723
|
-
}
|
|
724
|
-
setDashboardParameter(parameter, parameterName) {
|
|
725
|
-
parameter.value = '{{' + parameterName + '}}';
|
|
726
|
-
this.evaluateDataset(true);
|
|
727
|
-
}
|
|
728
|
-
save() {
|
|
729
|
-
if (!this.datasetInstanceSummary.id && (this.datasetInstanceSummary.title === this.datasetTitle)) {
|
|
730
|
-
const dialogRef = this.dialog.open(DatasetNameDialogComponent, {
|
|
731
|
-
width: '700px',
|
|
732
|
-
height: '800px',
|
|
733
|
-
disableClose: true,
|
|
734
|
-
data: {
|
|
735
|
-
datasetInstanceSummary: this.datasetInstanceSummary
|
|
736
|
-
}
|
|
737
|
-
});
|
|
738
|
-
dialogRef.afterClosed().subscribe(datasetInstanceSummary => {
|
|
739
|
-
if (datasetInstanceSummary) {
|
|
740
|
-
this.datasetInstanceSummary = datasetInstanceSummary;
|
|
741
|
-
this.saveDataset();
|
|
742
|
-
}
|
|
743
|
-
});
|
|
744
|
-
}
|
|
745
|
-
else {
|
|
746
|
-
this.saveDataset();
|
|
747
|
-
}
|
|
748
|
-
}
|
|
749
|
-
async saveDataset() {
|
|
750
|
-
await this.datasetService.saveDataset(this.datasetInstanceSummary, this.accountId);
|
|
751
|
-
this.snackBar.open('Dataset successfully saved.', 'Close', {
|
|
752
|
-
verticalPosition: 'top',
|
|
753
|
-
duration: 3000
|
|
754
|
-
});
|
|
755
|
-
}
|
|
756
|
-
async excludeUpstreamTransformations(transformation, resetPager = false) {
|
|
757
|
-
const clonedTransformation = _.clone(transformation);
|
|
758
|
-
// Grab the index of the current transformation - so we know which upstream transformations to exclude
|
|
759
|
-
const existingIndex = _.findIndex(this.datasetInstanceSummary.transformationInstances, {
|
|
760
|
-
type: transformation.type,
|
|
761
|
-
config: transformation.config
|
|
762
|
-
});
|
|
763
|
-
// Exclude all upstream transformations from the evaluate
|
|
764
|
-
this.datasetInstanceSummary.transformationInstances.forEach((instance, index) => {
|
|
765
|
-
if ((index >= existingIndex) && instance.type !== 'multisort') {
|
|
766
|
-
instance.exclude = true;
|
|
767
|
-
}
|
|
768
|
-
});
|
|
769
|
-
await this.evaluateDataset(resetPager);
|
|
770
|
-
return [clonedTransformation, existingIndex];
|
|
771
|
-
}
|
|
772
|
-
validateFilterJunction(filterConfig) {
|
|
773
|
-
const check = (filterJunction) => {
|
|
774
|
-
// tslint:disable-next-line:prefer-for-of
|
|
775
|
-
for (let i = 0; i < filterJunction.filterJunctions.length; i++) {
|
|
776
|
-
const junction = filterJunction.filterJunctions[i];
|
|
777
|
-
if (!junction.filters.length && !junction.filterJunctions.length) {
|
|
778
|
-
filterJunction.filterJunctions.splice(i, 1);
|
|
779
|
-
}
|
|
780
|
-
else {
|
|
781
|
-
check(junction);
|
|
782
|
-
}
|
|
783
|
-
}
|
|
784
|
-
};
|
|
785
|
-
check(filterConfig);
|
|
786
|
-
}
|
|
787
|
-
loadData() {
|
|
788
|
-
this.tableData = this.dataset.allData;
|
|
789
|
-
if (!this.tableData.length) {
|
|
790
|
-
const data = {};
|
|
791
|
-
data[this.dataset.columns[0].name] = 'No Results';
|
|
792
|
-
this.tableData = [data];
|
|
793
|
-
}
|
|
794
|
-
this.endOfResults = this.dataset.allData.length < this.limit;
|
|
795
|
-
this.displayedColumns = _.map(this.dataset.columns, 'name');
|
|
796
|
-
this.filterFields = _.map(this.dataset.columns, column => {
|
|
797
|
-
return {
|
|
798
|
-
title: column.title,
|
|
799
|
-
name: column.name
|
|
800
|
-
};
|
|
801
|
-
});
|
|
802
|
-
this.dataLoaded.emit(this.dataset);
|
|
803
|
-
this.datasetInstanceSummaryChange.emit(this.datasetInstanceSummary);
|
|
804
|
-
this.setTerminatingTransformations();
|
|
805
|
-
return true;
|
|
806
|
-
}
|
|
807
|
-
setParameterValues(values) {
|
|
808
|
-
}
|
|
809
|
-
setTerminatingTransformations() {
|
|
810
|
-
let summarise = 0;
|
|
811
|
-
let join = 0;
|
|
812
|
-
const summariseTotal = _.filter(this.datasetInstanceSummary.transformationInstances, { type: 'summarise' }).length;
|
|
813
|
-
const joinTotal = _.filter(this.datasetInstanceSummary.transformationInstances, { type: 'join' }).length;
|
|
814
|
-
this.terminatingTransformations = _.filter(this.datasetInstanceSummary.transformationInstances, (transformation, index) => {
|
|
815
|
-
if (transformation.type === 'summarise') {
|
|
816
|
-
summarise++;
|
|
817
|
-
transformation._label = this.getOrdinal(summarise) + ' Summarise';
|
|
818
|
-
transformation._disable = summarise < summariseTotal;
|
|
819
|
-
transformation._active = summarise === summariseTotal;
|
|
820
|
-
return true;
|
|
821
|
-
}
|
|
822
|
-
if (transformation.type === 'join') {
|
|
823
|
-
join++;
|
|
824
|
-
transformation._label = transformation.config.joinedDataItemTitle || this.getOrdinal(join) + ' Join';
|
|
825
|
-
transformation._disable = join < joinTotal;
|
|
826
|
-
transformation._active = join === joinTotal;
|
|
827
|
-
return true;
|
|
828
|
-
}
|
|
829
|
-
if (transformation.type === 'pagingmarker') {
|
|
830
|
-
transformation._label = 'Paging Marker';
|
|
831
|
-
transformation._disable = false;
|
|
832
|
-
transformation._active = true;
|
|
833
|
-
return true;
|
|
834
|
-
}
|
|
835
|
-
if (transformation.type === 'formula') {
|
|
836
|
-
transformation._label = transformation.config.expressions[0].fieldTitle;
|
|
837
|
-
transformation._disable = false;
|
|
838
|
-
transformation._active = true;
|
|
839
|
-
return true;
|
|
840
|
-
}
|
|
841
|
-
if (transformation.type === 'columns') {
|
|
842
|
-
transformation._label = 'Columns Update';
|
|
843
|
-
transformation._disable = false;
|
|
844
|
-
transformation._active = true;
|
|
845
|
-
return true;
|
|
846
|
-
}
|
|
847
|
-
if (transformation.type === 'filter') {
|
|
848
|
-
transformation._label = 'Filter';
|
|
849
|
-
transformation._disable = false;
|
|
850
|
-
transformation._active = true;
|
|
851
|
-
return true;
|
|
852
|
-
}
|
|
853
|
-
return false;
|
|
854
|
-
});
|
|
855
|
-
}
|
|
856
|
-
/**
|
|
857
|
-
* Add an in value
|
|
858
|
-
*/
|
|
859
|
-
addParameterValue(parameter, event) {
|
|
860
|
-
const value = (event.value || event.target?.value || '').trim();
|
|
861
|
-
if (!_.isArray(parameter.value)) {
|
|
862
|
-
parameter.value = [];
|
|
863
|
-
}
|
|
864
|
-
if (value && value !== 'null' && parameter.value.indexOf(value) === -1) {
|
|
865
|
-
parameter.value.push(value);
|
|
866
|
-
}
|
|
867
|
-
// Clear the input value
|
|
868
|
-
if (event.chipInput) {
|
|
869
|
-
event.chipInput.clear();
|
|
870
|
-
}
|
|
871
|
-
}
|
|
872
|
-
/**
|
|
873
|
-
* Remove an in value
|
|
874
|
-
*
|
|
875
|
-
*/
|
|
876
|
-
removeParameterValue(parameter, value) {
|
|
877
|
-
const index = parameter.value.indexOf(value);
|
|
878
|
-
if (index >= 0) {
|
|
879
|
-
parameter.value.splice(index, 1);
|
|
880
|
-
}
|
|
881
|
-
}
|
|
882
|
-
async evaluateDataset(resetPager) {
|
|
883
|
-
return new Promise(async (resolve, reject) => {
|
|
884
|
-
if (resetPager) {
|
|
885
|
-
this.resetPager();
|
|
886
|
-
}
|
|
887
|
-
const clonedDatasetInstance = await this.prepareDatasetInstanceForEvaluation();
|
|
888
|
-
this.setAvailableFilterParameters();
|
|
889
|
-
const trackingKey = Date.now() + (Math.random() + 1).toString(36).substr(2, 5);
|
|
890
|
-
let finished = false;
|
|
891
|
-
if (this.dashboardLayoutSettings) {
|
|
892
|
-
this.dashboardLayoutSettings.limit = this.limit;
|
|
893
|
-
this.dashboardLayoutSettings.offset = this.offset;
|
|
894
|
-
}
|
|
895
|
-
this.evaluateSub = this.datasetService.evaluateDatasetWithTracking(clonedDatasetInstance, String(this.offset), String(this.limit), trackingKey).subscribe(async (dataset) => {
|
|
896
|
-
finished = true;
|
|
897
|
-
this.dataset = dataset;
|
|
898
|
-
this.loadData();
|
|
899
|
-
resolve(true);
|
|
900
|
-
}, err => {
|
|
901
|
-
finished = true;
|
|
902
|
-
if (err.error && err.error.message) {
|
|
903
|
-
let message = err.error.message.toLowerCase();
|
|
904
|
-
if (message.includes('sql')) {
|
|
905
|
-
message = 'An error occurred processing your query. Please check any SQL syntax and try again.';
|
|
906
|
-
}
|
|
907
|
-
if (!message.includes('parameter') && !message.includes('required')) {
|
|
908
|
-
this.snackBar.open(err.error.message, 'Close', {
|
|
909
|
-
verticalPosition: 'top',
|
|
910
|
-
duration: 5000
|
|
911
|
-
});
|
|
912
|
-
}
|
|
913
|
-
}
|
|
914
|
-
// If the evaluate fails we still want to publish the instance and set the terminating transformations
|
|
915
|
-
this.datasetInstanceSummaryChange.emit(this.datasetInstanceSummary);
|
|
916
|
-
this.setTerminatingTransformations();
|
|
917
|
-
return reject(false);
|
|
918
|
-
});
|
|
919
|
-
setTimeout(() => {
|
|
920
|
-
if (!finished) {
|
|
921
|
-
// If we have any pre-existing long-running tasks cancel these before setting off another evaluate.
|
|
922
|
-
this.cancelEvaluate();
|
|
923
|
-
this.longRunning = true;
|
|
924
|
-
this.evaluateSub.unsubscribe();
|
|
925
|
-
this.resultsSub = this.datasetService.getDataTrackingResults(trackingKey)
|
|
926
|
-
.subscribe((results) => {
|
|
927
|
-
if (results.status === 'COMPLETED') {
|
|
928
|
-
this.resultsSub.unsubscribe();
|
|
929
|
-
this.dataset = results.result;
|
|
930
|
-
this.longRunning = false;
|
|
931
|
-
this.loadData();
|
|
932
|
-
resolve(true);
|
|
933
|
-
}
|
|
934
|
-
else if (results.status === 'FAILED') {
|
|
935
|
-
this.resultsSub.unsubscribe();
|
|
936
|
-
this.longRunning = false;
|
|
937
|
-
const errorMessage = results.result;
|
|
938
|
-
if (errorMessage) {
|
|
939
|
-
const message = errorMessage.toLowerCase();
|
|
940
|
-
if (!message.includes('parameter') && !message.includes('required')) {
|
|
941
|
-
this.snackBar.open(errorMessage, 'Close', {
|
|
942
|
-
verticalPosition: 'top',
|
|
943
|
-
duration: 5000
|
|
944
|
-
});
|
|
945
|
-
}
|
|
946
|
-
}
|
|
947
|
-
// If the evaluate fails we still want to publish the instance and set the terminating transformations
|
|
948
|
-
this.datasetInstanceSummaryChange.emit(this.datasetInstanceSummary);
|
|
949
|
-
this.setTerminatingTransformations();
|
|
950
|
-
resolve(false);
|
|
951
|
-
}
|
|
952
|
-
});
|
|
953
|
-
}
|
|
954
|
-
}, 3000);
|
|
955
|
-
});
|
|
956
|
-
}
|
|
957
|
-
setAvailableFilterParameters() {
|
|
958
|
-
const filterParameterValues = _.map(_.concat(_.values(this.dashboardParameters), _.values(this.parameterValues)), param => {
|
|
959
|
-
return { name: param.name, title: param.title };
|
|
960
|
-
});
|
|
961
|
-
this.filterParameterValues = _.uniqBy(filterParameterValues, 'name');
|
|
962
|
-
}
|
|
963
|
-
_removeTransformation(transformation, index) {
|
|
964
|
-
if (!_.isNil(index) && index >= 0) {
|
|
965
|
-
// If a current index has been supplied, reset all the pre transformation hidden fields prior to eval.
|
|
966
|
-
for (let i = 0; i < index; i++) {
|
|
967
|
-
if (this.datasetInstanceSummary.transformationInstances[i].type !== 'filter') {
|
|
968
|
-
this.datasetInstanceSummary.transformationInstances[i].hide = false;
|
|
969
|
-
}
|
|
970
|
-
}
|
|
971
|
-
this.datasetInstanceSummary.transformationInstances.splice(index, 1);
|
|
972
|
-
}
|
|
973
|
-
else {
|
|
974
|
-
_.remove(this.datasetInstanceSummary.transformationInstances, _.omitBy({
|
|
975
|
-
type: transformation.type,
|
|
976
|
-
config: transformation.type !== 'pagingmarker' ? transformation.config : null
|
|
977
|
-
}, _.isNil));
|
|
978
|
-
}
|
|
979
|
-
this.evaluateDataset(true);
|
|
980
|
-
}
|
|
981
|
-
resetPager() {
|
|
982
|
-
this.offset = 0;
|
|
983
|
-
this.page = 1;
|
|
984
|
-
}
|
|
985
|
-
async prepareDatasetInstanceForEvaluation() {
|
|
986
|
-
const values = await this.datasetService.getEvaluatedParameters(this.datasetInstanceSummary);
|
|
987
|
-
const paramValues = values.map(value => {
|
|
988
|
-
value._locked = !_.find(this.datasetInstanceSummary.parameters, { name: value.name });
|
|
989
|
-
return value;
|
|
990
|
-
});
|
|
991
|
-
this.focusParams = false;
|
|
992
|
-
const parameterValues = {};
|
|
993
|
-
paramValues.forEach(paramValue => {
|
|
994
|
-
const existParam = _.find(this.parameterValues, { name: paramValue.name });
|
|
995
|
-
if (!existParam) {
|
|
996
|
-
const existingValue = this.datasetInstanceSummary.parameterValues[paramValue.name];
|
|
997
|
-
paramValue.value = _.isNil(existingValue) ? paramValue.defaultValue : existingValue;
|
|
998
|
-
parameterValues[paramValue.name] = paramValue;
|
|
999
|
-
this.focusParams = !existingValue;
|
|
1000
|
-
}
|
|
1001
|
-
else {
|
|
1002
|
-
parameterValues[existParam.name] = existParam;
|
|
1003
|
-
}
|
|
1004
|
-
});
|
|
1005
|
-
this.parameterValues = _.values(parameterValues);
|
|
1006
|
-
if (this.datasetInstanceSummary && this.datasetInstanceSummary.id) {
|
|
1007
|
-
localStorage.setItem('datasetInstanceLimit' + this.datasetInstanceSummary.id, (this.limit).toString());
|
|
1008
|
-
}
|
|
1009
|
-
else if (this.datasetInstanceSummary.instanceKey) {
|
|
1010
|
-
localStorage.setItem('datasetInstanceLimit' + this.datasetInstanceSummary.instanceKey, (this.limit).toString());
|
|
1011
|
-
}
|
|
1012
|
-
const sort = _.find(this.datasetInstanceSummary.transformationInstances, { type: 'multisort' });
|
|
1013
|
-
if (sort) {
|
|
1014
|
-
const clone = _.clone(sort);
|
|
1015
|
-
_.remove(this.datasetInstanceSummary.transformationInstances, sort);
|
|
1016
|
-
this.datasetInstanceSummary.transformationInstances.push(clone);
|
|
1017
|
-
}
|
|
1018
|
-
// Clone the current instance object, so we can remove any excluded transformations, without affecting
|
|
1019
|
-
// the original object which the gui uses to draw transformation items.
|
|
1020
|
-
const clonedDatasetInstance = _.merge({}, this.datasetInstanceSummary);
|
|
1021
|
-
_.remove(clonedDatasetInstance.transformationInstances, { exclude: true });
|
|
1022
|
-
const excludedTransformations = _.find(this.datasetInstanceSummary.transformationInstances, { exclude: true });
|
|
1023
|
-
if (excludedTransformations) {
|
|
1024
|
-
_.remove(clonedDatasetInstance.transformationInstances, { type: 'multisort' });
|
|
1025
|
-
}
|
|
1026
|
-
this.parameterValues.forEach(param => {
|
|
1027
|
-
if (param.type === 'date' || param.type === 'datetime') {
|
|
1028
|
-
if (!param._dateType && param.value) {
|
|
1029
|
-
const isPeriod = param.value.includes('AGO');
|
|
1030
|
-
param._dateType = isPeriod ? 'period' : 'picker';
|
|
1031
|
-
if (isPeriod) {
|
|
1032
|
-
const periodValues = param.value.split('_');
|
|
1033
|
-
param._periodValue = periodValues[0];
|
|
1034
|
-
param._period = periodValues[1];
|
|
1035
|
-
}
|
|
1036
|
-
}
|
|
1037
|
-
}
|
|
1038
|
-
if (param.type === 'list' && !param.list?.length) {
|
|
1039
|
-
this.loadListParameters(param);
|
|
1040
|
-
}
|
|
1041
|
-
if (this.dashboardParameters && Object.keys(this.dashboardParameters).length) {
|
|
1042
|
-
if (_.isString(param.value) && param.value.includes('{{')) {
|
|
1043
|
-
const paramKey = param.value.replace('{{', '').replace('}}', '');
|
|
1044
|
-
if (this.dashboardParameters[paramKey]) {
|
|
1045
|
-
clonedDatasetInstance.parameterValues[param.name] = this.dashboardParameters[paramKey].value;
|
|
1046
|
-
}
|
|
1047
|
-
}
|
|
1048
|
-
else if (!clonedDatasetInstance.parameterValues[param.name] && this.dashboardParameters[param.name]) {
|
|
1049
|
-
// If no value has been set default to the dashboard param value
|
|
1050
|
-
clonedDatasetInstance.parameterValues[param.name] = this.dashboardParameters[param.name].value;
|
|
1051
|
-
}
|
|
1052
|
-
else if (!clonedDatasetInstance.parameterValues[param.name]) {
|
|
1053
|
-
// Unless there isn't a dashboard param that matches
|
|
1054
|
-
clonedDatasetInstance.parameterValues[param.name] = param.value;
|
|
1055
|
-
}
|
|
1056
|
-
}
|
|
1057
|
-
else {
|
|
1058
|
-
clonedDatasetInstance.parameterValues[param.name] = param.value;
|
|
1059
|
-
}
|
|
1060
|
-
this.datasetInstanceSummary.parameterValues[param.name] = param.value;
|
|
1061
|
-
});
|
|
1062
|
-
// Merge in global dashboard params
|
|
1063
|
-
if (this.dashboardParameters && Object.keys(this.dashboardParameters).length) {
|
|
1064
|
-
_.forEach(this.dashboardParameters, (param, name) => {
|
|
1065
|
-
if (!clonedDatasetInstance.parameterValues[name]) {
|
|
1066
|
-
clonedDatasetInstance.parameterValues[name] = param.value;
|
|
1067
|
-
}
|
|
1068
|
-
});
|
|
1069
|
-
}
|
|
1070
|
-
// Ensure we send back any dates in correct format
|
|
1071
|
-
const datetimeParams = _.filter(clonedDatasetInstance.parameters, param => {
|
|
1072
|
-
return param.type === 'date' || param.type === 'datetime';
|
|
1073
|
-
});
|
|
1074
|
-
datetimeParams.forEach(param => {
|
|
1075
|
-
const value = clonedDatasetInstance.parameterValues[param.name];
|
|
1076
|
-
if (value && !value.includes('AGO')) {
|
|
1077
|
-
clonedDatasetInstance.parameterValues[param.name] = moment(value).format('YYYY-MM-DD HH:mm:ss');
|
|
1078
|
-
}
|
|
1079
|
-
});
|
|
1080
|
-
return clonedDatasetInstance;
|
|
1081
|
-
}
|
|
1082
|
-
}
|
|
1083
|
-
DatasetEditorComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: DatasetEditorComponent, deps: [{ token: i1.MatLegacyDialogRef }, { token: MAT_DIALOG_DATA }, { token: i1.MatLegacyDialog }, { token: i2.DatasetService }, { token: i3.MatLegacySnackBar }], target: i0.ɵɵFactoryTarget.Component });
|
|
1084
|
-
DatasetEditorComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: DatasetEditorComponent, selector: "ki-dataset-editor", inputs: { datasetInstanceSummary: "datasetInstanceSummary", environment: "environment", admin: "admin", dashboardParameters: "dashboardParameters", dashboardLayoutSettings: "dashboardLayoutSettings", accountId: "accountId", newTitle: "newTitle", newDescription: "newDescription", datasetEditorReadonly: "datasetEditorReadonly", datasetEditorSimpleMode: "datasetEditorSimpleMode", datasetEditorNoTools: "datasetEditorNoTools" }, outputs: { dataLoaded: "dataLoaded", datasetInstanceSummaryChange: "datasetInstanceSummaryChange" }, ngImport: i0, template: "<div *ngIf=\"longRunning\" class=\"long-running flex-col\">\n\n <div class=\"loading-box\">\n <mat-spinner [diameter]=\"150\"></mat-spinner>\n <div>Loading</div>\n </div>\n\n <p class=\"text-center\">Please wait while we process this query.</p>\n <p class=\"text-center\">The results will be shown here once it has finished running.</p>\n <div>\n <a class=\"text-primary hover:underline\" (click)=\"cancelEvaluate()\">Cancel query and return to editor.</a>\n </div>\n</div>\n<div class=\"pointer-events-none fixed inset-y-0 right-0 flex max-w-full pl-10 -z-10\" id=\"sidebarWrapper\">\n <div [ngClass]=\"{'translate-x-0': sideOpen, 'translate-x-full': !sideOpen}\"\n (click)=\"$event.stopPropagation()\"\n class=\"pointer-events-auto w-screen max-w-md transform transition ease-in-out duration-500 sm:duration-700\"\n id=\"docSidebar\">\n <div class=\"flex h-full flex-col overflow-y-scroll bg-white py-6 shadow-xl\">\n <div class=\"px-4 sm:px-6\">\n <div class=\"flex items-start justify-between\">\n <div></div>\n\n <div class=\"ml-3 flex h-7 items-center\">\n <button type=\"button\" (click)=\"openSide.next(false)\"\n class=\"rounded-md bg-white text-gray-400 hover:text-gray-500 focus:outline-none\">\n <span class=\"sr-only\">Close panel</span>\n <!-- Heroicon name: outline/x -->\n <svg class=\"h-6 w-6\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\"\n stroke=\"currentColor\" aria-hidden=\"true\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"\n d=\"M6 18L18 6M6 6l12 12\"/>\n </svg>\n </button>\n </div>\n </div>\n </div>\n <div class=\"relative flex-1 px-4 sm:px-6\">\n <ki-whitelisted-sql-functions [fields]=\"filterFields\"></ki-whitelisted-sql-functions>\n </div>\n </div>\n </div>\n</div>\n\n<div *ngIf=\"!datasetEditorNoTools\" class=\"border-b cell-header end\">\n <div class=\"leading-5 px-4 text-xs uppercase tracking-wider font-medium border-r-2 text-gray-600\">\n Operations\n </div>\n <div class=\"dataset-data-actions\">\n <button (click)=\"addFilter()\"\n title=\"Filter the set using column based restrictions\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">filter_alt</span>\n filter\n </button>\n <button (click)=\"summariseData()\"\n title=\"Summarise this data to produce aggregated totals, sums and other derivations\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">pivot_table_chart</span>\n summarise\n </button>\n <button *ngIf=\"!datasetEditorSimpleMode\" (click)=\"joinData()\"\n title=\"Join another data set to the current dataset\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">merge_type</span>\n join\n </button>\n <div class=\"divider\"></div>\n <button (click)=\"createFormula()\"\n title=\"Create a formula column using an expression based on other columns\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">functions</span>\n formula\n </button>\n <button (click)=\"editColumnSettings()\"\n title=\"Switch on and off columns for display\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">table_chart</span>\n columns\n </button>\n <div *ngIf=\"!datasetEditorSimpleMode\" class=\"divider\"></div>\n <button *ngIf=\"!datasetEditorSimpleMode\" (click)=\"addParameter()\"\n title=\"Add a parameter to use in filters, expressions etc.\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">text_fields</span>\n parameters\n </button>\n <button *ngIf=\"!datasetEditorSimpleMode\" (click)=\"addPagingMarker()\"\n title=\"Insert paging marker to limit results at this stage in the query flow\"\n class=\"w-24 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">skip_next</span>\n paging marker\n </button>\n <div class=\"divider\"></div>\n <button (click)=\"evaluateDataset()\"\n title=\"Reload this query based upon changes you may have made\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">sync</span>\n reload\n </button>\n <ng-template [ngIf]=\"!datasetEditorReadonly\">\n <button [disabled]=\"!datasetInstanceSummary || !datasetInstanceSummary.id\" (click)=\"shareQuery()\"\n title=\"Share this query with other account holders\"\n class=\"disabled:opacity-50 w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">share</span>\n share\n </button>\n <button (click)=\"saveAsQuery()\"\n title=\"Make a copy of this query\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">file_copy</span>\n copy query\n </button>\n <button *ngIf=\"!dashboardLayoutSettings && datasetInstanceSummary.id\" (click)=\"save()\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">save</span>\n save\n </button>\n </ng-template>\n </div>\n</div>\n\n<div class=\"cell-header\">\n <div class=\"transformation-listing parameter-listing\" *ngIf=\"showParameters || parameterValues.length\">\n <div class=\"list-title\">\n Parameters\n </div>\n <div class=\"flex items-center flex-wrap\">\n <ng-template ngFor let-parameter [ngForOf]=\"parameterValues\" let-i=index>\n\n <label class=\"pl-4\">\n {{ parameter.title }}\n\n <div *ngIf=\"(parameter.value || '').toString().includes('}}')\">\n <mat-chip class=\"bg-gray-50 ml-2\" title=\"Using parameter value from {{parameter.value}}\">\n <div class=\"flex items-center\">\n <span class=\"material-symbols-outlined text-xl mr-1 text-gray-500\">layers</span>\n <span *ngIf=\"dashboardParameters[parameter.value.replace('{{', '').replace('}}', '')]\"\n [innerHTML]=\"dashboardParameters[parameter.value.replace('{{', '').replace('}}', '')].value\"></span>\n <span *ngIf=\"!dashboardParameters[parameter.value.replace('{{', '').replace('}}', '')]\"\n class=\"font-medium text-orange-600\">\n Parameter Not Found !\n </span>\n </div>\n\n <button matChipRemove (click)=\"parameter.value = ''\" title=\"\">\n <mat-icon>cancel</mat-icon>\n </button>\n </mat-chip>\n </div>\n\n\n <div *ngIf=\"!(parameter.value || '').toString().includes('}}')\" class=\"parameter-input\">\n\n <ng-template [ngIf]=\"!parameter.multiple\">\n\n <ng-template [ngIf]=\"parameter.type === 'text'\">\n <input class=\"pr-8\" type=\"text\" placeholder=\"Enter {{parameter.title}}\"\n [(ngModel)]=\"parameter.value\"\n (keyup.enter)=\"evaluateDataset(true)\" required autofocus>\n </ng-template>\n <ng-template [ngIf]=\"parameter.type === 'numeric'\">\n <input class=\"pr-8\" type=\"number\" placeholder=\"Enter {{parameter.title}}\"\n [(ngModel)]=\"parameter.value\"\n (keyup.enter)=\"evaluateDataset(true)\" required autofocus>\n </ng-template>\n <ng-template [ngIf]=\"parameter.type === 'list'\">\n <select class=\"pr-8 py-1.5 pl-1 self-center\" [(ngModel)]=\"parameter.value\"\n (change)=\"evaluateDataset(true)\" required autofocus>\n <option [value]=\"null\">-- Select Value --</option>\n <option *ngFor=\"let item of parameter.list\" [value]=\"item.value\">{{ item.label }}\n </option>\n </select>\n </ng-template>\n <ng-template [ngIf]=\"parameter.type === 'date' || parameter.type === 'datetime'\">\n <ng-template [ngIf]=\"!parameter._dateType\">\n <div class=\"flex items-center mr-8\">\n <button (click)=\"changeDateType($event, parameter, 'picker')\"\n class=\"hover:bg-gray-50 text-gray-800 border border-gray-300 py-0.5 pr-2 rounded mr-2 bg-white flex items-center\">\n <mat-icon class=\"text-base\">calendar_month</mat-icon>\n Date Picker\n </button>\n <button (click)=\"changeDateType($event, parameter, 'period')\"\n class=\"hover:bg-gray-50 text-gray-800 border border-gray-300 py-0.5 pr-2 rounded mr-2 bg-white flex items-center\">\n <mat-icon class=\"text-base\">restore</mat-icon>\n Time Period\n </button>\n </div>\n </ng-template>\n <ng-template [ngIf]=\"parameter._dateType === 'picker'\">\n <input [type]=\"parameter.type === 'date' ? 'date' : 'datetime-local'\"\n placeholder=\"Enter {{parameter.title}}\" [(ngModel)]=\"parameter.value\"\n (keyup.enter)=\"evaluateDataset(true)\" required autofocus>\n\n <a (click)=\"changeDateType($event, parameter, 'period')\"\n matTooltip=\"Time Period\"\n class=\"mr-10 text-center ml-2 hover:bg-gray-50 text-gray-800 border border-gray-300 py-0.5 pr-0.5 rounded mr-2 bg-white flex items-center\">\n <mat-icon class=\"text-base\">restore</mat-icon>\n </a>\n </ng-template>\n <ng-template [ngIf]=\"parameter._dateType === 'period'\">\n <div class=\"flex items-center\">\n <input #periodValue type=\"number\" placeholder=\"No.\" required autofocus\n class=\"w-16 mr-2\" min=\"0\" [value]=\"parameter._periodValue\"\n (change)=\"updatePeriodValue(periodValue.value, period.value, parameter)\">\n\n <select class=\"param-period-picker mr-2\" [value]=\"parameter._period || 'DAYS'\"\n #period\n (change)=\"updatePeriodValue(periodValue.value, period.value, parameter)\">\n <option value=\"DAYS\">Days</option>\n <option value=\"HOURS\">Hours</option>\n </select>\n\n <div>Ago</div>\n </div>\n\n <a (click)=\"changeDateType($event, parameter, 'picker')\"\n matTooltip=\"Date Picker\"\n class=\"mr-10 text-center ml-2 hover:bg-gray-50 text-gray-800 border border-gray-300 py-0.5 pr-0.5 rounded mr-2 bg-white flex items-center\">\n <mat-icon class=\"text-base\">calendar_month</mat-icon>\n </a>\n </ng-template>\n\n </ng-template>\n <ng-template [ngIf]=\"parameter.type === 'boolean'\">\n <mat-slide-toggle class=\"pr-8\" color=\"primary\"\n [checked]=\"parameter.value\" (change)=\"booleanUpdate($event, parameter)\"\n required></mat-slide-toggle>\n </ng-template>\n </ng-template>\n\n <ng-template [ngIf]=\"parameter.multiple\">\n\n\n <mat-chip-grid class=\"pl-2\" #chipGrid aria-label=\"Enter values\">\n <mat-chip-row *ngFor=\"let paramValue of parameter.value\"\n class=\"bg-white mr-2\"\n (removed)=\"removeParameterValue(parameter, paramValue)\">\n {{paramValue}}\n <button matChipRemove [attr.aria-label]=\"'remove ' + paramValue\">\n <mat-icon>cancel</mat-icon>\n </button>\n </mat-chip-row>\n\n <ng-template [ngIf]=\"parameter.type === 'text'\">\n <input class=\"pr-8 py-1 self-center\" type=\"text\" placeholder=\"Enter {{parameter.title}}\"\n required autofocus\n [matChipInputFor]=\"chipGrid\"\n [matChipInputSeparatorKeyCodes]=\"[ENTER, COMMA]\"\n [matChipInputAddOnBlur]=\"true\"\n (matChipInputTokenEnd)=\"addParameterValue(parameter, $event)\">\n </ng-template>\n <ng-template [ngIf]=\"parameter.type === 'numeric'\">\n <input class=\"pr-8\" type=\"number\" placeholder=\"Enter {{parameter.title}}\"\n required autofocus\n [matChipInputFor]=\"chipGrid\"\n [matChipInputSeparatorKeyCodes]=\"[ENTER, COMMA]\"\n [matChipInputAddOnBlur]=\"true\"\n (matChipInputTokenEnd)=\"addParameterValue(parameter, $event)\">\n </ng-template>\n <ng-template [ngIf]=\"parameter.type === 'list'\">\n <select class=\"pr-8 py-1.5 pl-1 self-center\" matNativeControl\n (change)=\"addParameterValue(parameter, $event)\" required autofocus>\n <option [value]=\"null\">-- Select Value --</option>\n <option *ngFor=\"let item of parameter.list\" [value]=\"item.value\">{{ item.label }}\n </option>\n </select>\n </ng-template>\n\n </mat-chip-grid>\n\n\n </ng-template>\n\n\n\n <ng-template [ngIf]=\"!parameter._locked\">\n <button mat-icon-button [matMenuTriggerFor]=\"paramMenu\">\n <mat-icon>settings</mat-icon>\n </button>\n <mat-menu #paramMenu=\"matMenu\">\n <button mat-menu-item (click)=\"addParameter(parameter, i)\">Edit Parameter</button>\n <button mat-menu-item (click)=\"removeParameter(parameter)\">Remove Parameter</button>\n </mat-menu>\n </ng-template>\n <ng-template [ngIf]=\"Object.keys(dashboardParameters || {}).length\">\n <button mat-icon-button [matMenuTriggerFor]=\"dashParamMenu\"\n title=\"Bind this parameter value to another\">\n <mat-icon>text_fields</mat-icon>\n </button>\n <mat-menu #dashParamMenu=\"matMenu\">\n <button mat-menu-item *ngFor=\"let dashParamKey of Object.keys(dashboardParameters)\"\n (click)=\"setDashboardParameter(parameter, dashboardParameters[dashParamKey].name)\">{{ dashboardParameters[dashParamKey].title }}\n </button>\n </mat-menu>\n </ng-template>\n </div>\n\n </label>\n\n <div class=\"divider ml-2\" *ngIf=\"parameterValues.length\"></div>\n\n </ng-template>\n <button mat-icon-button color=\"primary\" class=\"mx-2\" (click)=\"addParameter()\">\n <mat-icon>add_circle</mat-icon>\n </button>\n <button type=\"button\" (click)=\"evaluateDataset(true)\" *ngIf=\"parameterValues.length\"\n class=\"mr-2 flex items-center whitespace-nowrap justify-center px-4 py-1 border border-transparent text-sm rounded-md shadow-sm text-white bg-primary focus:outline-none\">\n Apply Parameters\n </button>\n </div>\n </div>\n</div>\n\n<div class=\"cell-header\">\n <div class=\"transformation-listing py-2\" *ngIf=\"terminatingTransformations.length\">\n <div class=\"list-title\">\n Transformations\n </div>\n <div class=\"example-list flex flex-wrap\" cdkDropListGroup>\n <ng-template ngFor let-transformation [ngForOf]=\"terminatingTransformations\" let-i=\"index\">\n <div cdkDropList (cdkDropListDropped)=\"drop($event)\" cdkDropListOrientation=\"horizontal\"\n [cdkDropListData]=\"{item:transformation,index:i}\" *ngIf=\"!transformation.hidden\">\n <div class=\"flex items-center\">\n <div class=\"new-transformation flex items-center justify-center w-6 h-6\">\n <a [matMenuTriggerFor]=\"addTransformation\"\n class=\"items-center add-transformation text-primary\">\n <mat-icon class=\"flex items-center w-5 h-5 text-xl\">add_circle</mat-icon>\n </a>\n <mat-menu #addTransformation=\"matMenu\">\n <button mat-menu-item (click)=\"insertTransformation(i, 'columns', transformation)\">\n Insert Column Transformation\n </button>\n <button mat-menu-item (click)=\"insertTransformation(i, 'formula', transformation)\">\n Insert Formula Transformation\n </button>\n <button mat-menu-item (click)=\"insertTransformation(i, 'join', transformation)\">\n Insert Join Transformation\n </button>\n <button mat-menu-item (click)=\"insertTransformation(i, 'summarise', transformation)\">\n Insert Summarise Transformation\n </button>\n <button mat-menu-item (click)=\"insertTransformation(i, 'filter', transformation)\">\n Insert Filter Transformation\n </button>\n </mat-menu>\n </div>\n\n <div cdkDrag class=\"pl-0 example-box badge-item w-auto m-0\" cdkOverlayOrigin\n #trigger=\"cdkOverlayOrigin\"\n [ngClass]=\"{active: transformation._active, 'exclude bg-orange-50 border-orange-200': !!transformation.exclude, 'bg-indigo-50 border-indigo-200': (transformation.type === 'filter' && transformation.hide === false)}\">\n\n <button class=\"-mt-0.5\" title=\"Show transformation details\" mat-icon-button\n (click)=\"showTransformationDetail(transformation)\">\n <span class=\"material-symbols-outlined ml-1 text-xl\"\n *ngIf=\"transformation.type === 'columns'\">table_chart</span>\n <span class=\"material-symbols-outlined text-xl\"\n *ngIf=\"transformation.type === 'formula'\">functions</span>\n <span class=\"material-symbols-outlined text-xl\" *ngIf=\"transformation.type === 'join'\">merge_type</span>\n <span class=\"material-symbols-outlined ml-1 text-xl\"\n *ngIf=\"transformation.type === 'summarise'\">pivot_table_chart</span>\n <span class=\"material-symbols-outlined text-xl\"\n *ngIf=\"transformation.type === 'filter'\">filter_alt</span>\n </button>\n\n <span class=\"whitespace-nowrap cursor-pointer\"\n (click)=\"editTerminatingTransformation(transformation)\">{{ transformation._label }}</span>\n\n <ng-template [ngIf]=\"transformation.exclude\">\n <button class=\"-ml-1\" [title]=\"'Re-enable this transformation'\"\n mat-icon-button (click)=\"disableTransformation(transformation, i)\">\n <mat-icon class=\"text-orange-400\">replay</mat-icon>\n </button>\n </ng-template>\n <ng-template\n [ngIf]=\"!transformation.exclude && i + 1 === terminatingTransformations.length\">\n <button class=\"-ml-1\" [title]=\"'Disable transformation'\"\n mat-icon-button (click)=\"disableTransformation(transformation, i)\">\n <mat-icon>block</mat-icon>\n </button>\n </ng-template>\n <ng-template\n [ngIf]=\"!transformation.exclude && i + 1 !== terminatingTransformations.length\">\n <button class=\"-ml-1\" [matMenuTriggerFor]=\"disableMenu\"\n [title]=\"'Disable transformation'\"\n mat-icon-button>\n <mat-icon>block</mat-icon>\n </button>\n <mat-menu #disableMenu=\"matMenu\">\n <button mat-menu-item (click)=\"disableTransformation(transformation, i)\">\n Disable this transformation\n </button>\n <button mat-menu-item (click)=\"excludeUpstreamTransformations(transformation)\">\n Disable subsequent transformation(s)\n </button>\n </mat-menu>\n </ng-template>\n\n <button class=\"-ml-1\" title=\"Remove this transformation\" mat-icon-button color=\"primary\"\n (click)=\"removeTransformation(transformation, true, null, transformation._active)\">\n <mat-icon>cancel</mat-icon>\n </button>\n </div>\n <ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"trigger\"\n [cdkConnectedOverlayOpen]=\"transformation._showDetail\">\n <div class=\"p-4 w-96 bg-white shadow rounded\">\n <ng-template [ngIf]=\"transformation.type === 'summarise'\">\n <p class=\"text-sm text-gray-700 mb-0\">\n <b>SELECT </b><span\n *ngFor=\"let expression of transformation.config.expressions; let i = index\"><span\n *ngIf=\"i > 0\">, </span>{{ expression.customExpression || expression.expressionType + '(' + (expression.fieldName || '') + ')' }}</span>\n <ng-template [ngIf]=\"transformation.config.summariseFieldNames.length\"><br><b>GROUP\n BY </b> {{ transformation.config.summariseFieldNames.join(', ') }}\n </ng-template>\n </p>\n </ng-template>\n <ng-template [ngIf]=\"transformation.type === 'formula'\">\n <div class=\"text-sm text-gray-700 mb-0\">\n <b>EXPRESSION</b> {{ decodeURIComponent(transformation.config.expressions[0].expression) }}\n </div>\n </ng-template>\n <ng-template [ngIf]=\"transformation.type === 'columns'\">\n <div class=\"text-sm text-gray-700 mb-0\">\n <b>COLUMNS</b> {{ _.map(transformation.config.columns, 'title').join(', ') }}\n </div>\n </ng-template>\n <ng-template [ngIf]=\"transformation.type === 'join'\">\n <div class=\"text-sm text-gray-700 mb-0\">\n <b>JOIN\n COLUMNS</b> {{ _.map(transformation.config.joinColumns, 'title').join(', ') }}\n </div>\n </ng-template>\n <ng-template [ngIf]=\"transformation.type === 'filter'\">\n <div *ngFor=\"let filter of transformation.config.filters\"\n class=\"text-sm text-gray-700 mb-0\">\n <b>FILTER</b> {{ filter.lhsExpression }} <b>{{ filter.filterType }}</b> {{ filter.rhsExpression }}\n </div>\n </ng-template>\n </div>\n </ng-template>\n </div>\n\n </div>\n <button\n *ngIf=\"_.some(terminatingTransformations, {exclude: true}) && i === terminatingTransformations.length - 1\"\n class=\"ml-4 flex items-center border-none bg-primary text-sm rounded-md text-white pr-2 pl-1 py-0.5\"\n (click)=\"enableAllTransformation()\">\n <mat-icon class=\"mr-1 text-base\">replay</mat-icon>\n Enable All\n </button>\n </ng-template>\n\n </div>\n\n </div>\n</div>\n\n<div class=\"cell-header\">\n <div class=\"transformation-listing py-2 filters-list\"\n *ngIf=\"_.filter(datasetInstanceSummary.transformationInstances, {type: 'filter', hide: false}).length\">\n <a class=\"list-title flex items-center\" (click)=\"showFilters = !showFilters\">\n Filters \n <mat-icon *ngIf=\"!showFilters\">expand_more</mat-icon>\n <mat-icon *ngIf=\"showFilters\">expand_less</mat-icon>\n </a>\n <ng-template ngFor let-filterTransformation\n [ngForOf]=\"_.filter(datasetInstanceSummary.transformationInstances, {type: 'filter', hide: false})\">\n\n <div class=\"badge-item pl-2 mr-1\" *ngIf=\"_.every(filterTransformation.config.filters[0])\"\n (click)=\"showFilters = !showFilters\">\n <span class=\"cursor-pointer\" [innerHtml]=\"getFilterString(filterTransformation.config)\"></span>\n </div>\n\n </ng-template>\n </div>\n</div>\n\n<div class=\"dataset-filters\" id=\"datasetFilters\"\n *ngIf=\"_.filter(datasetInstanceSummary.transformationInstances, {type: 'filter', hide: false}).length\n && showFilters\">\n\n <ng-template ngFor let-transformation [ngForOf]=\"datasetInstanceSummary.transformationInstances\" let-i=index>\n <ng-template [ngIf]=\"transformation.type === 'filter' && transformation.hide === false\">\n <div class=\"dataset-filter border-b border-gray-200\">\n\n <button mat-stroked-button class=\"mr-2 bg-white remove-filter\" color=\"warn\"\n (click)=\"removeTransformation(transformation, true, i)\">\n Remove Filter\n </button>\n\n <ki-dataset-filters *ngIf=\"filterFields.length\" [filterFields]=\"filterFields\"\n [openSide]=\"openSide\" [parameterValues]=\"filterParameterValues\"\n [filterJunction]=\"transformation.config\"></ki-dataset-filters>\n <button\n *ngIf=\"_.filter(datasetInstanceSummary.transformationInstances, {type: 'filter', hide: false}).length\"\n mat-flat-button class=\"apply-filter mr-2\" color=\"primary\"\n (click)=\"applyFilters()\" [disabled]=\"!filterJunction.filters.length\">\n Apply Filters\n </button>\n\n </div>\n </ng-template>\n </ng-template>\n\n</div>\n\n<div class=\"cell-header\">\n <div class=\"transformation-listing sort\"\n *ngIf=\"_.find(datasetInstanceSummary.transformationInstances, {type: 'multisort'})\">\n <div class=\"list-title\">\n Sort\n </div>\n <div class=\"flex flex-wrap\">\n <div class=\"badge-item outline\"\n [ngClass]=\"{'exclude bg-orange-50 border-orange-200': _.find(datasetInstanceSummary.transformationInstances, {exclude: true})}\"\n *ngFor=\"let sort of _.find(datasetInstanceSummary.transformationInstances, {type: 'multisort'}).config.sorts; let i = index\">\n <span>{{ _.startCase(sort.fieldName) }} <span class=\"uppercase\">{{ sort.direction }}</span></span>\n <button mat-icon-button (click)=\"removeFilter(i)\">\n <mat-icon>cancel</mat-icon>\n </button>\n </div>\n </div>\n\n </div>\n</div>\n\n<div class=\"h-full table-overflow overflow-scroll\">\n <table mat-table [dataSource]=\"tableData\" *ngIf=\"displayedColumns.length\" matSort (matSortChange)=\"sort($event)\"\n class=\"block sticky\">\n\n <ng-template ngFor let-column [ngForOf]=\"filterFields\">\n <ng-container [matColumnDef]=\"column.name\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header\n class=\"text-xs font-semibold text-gray-900 py-3.5 px-4\"> {{ column.title }}\n </th>\n <td mat-cell *matCellDef=\"let element\" class=\"py-3 px-4\">\n <ng-template\n [ngIf]=\"!Array.isArray(element[column.name]) && !_.isPlainObject(element[column.name])\">\n <ng-template [ngIf]=\"element[column.name] && String(element[column.name]).length <= 100\">\n <div [innerHTML]=\"element[column.name]\"></div>\n </ng-template>\n <ng-template [ngIf]=\"element[column.name] && String(element[column.name]).length > 100\">\n <div>{{ element[column.name].substring(0, 100) + '...' }}</div>\n <a (click)=\"viewFullItemData(element[column.name], column.name)\"\n class=\"flex items-center text-sm text-cta\">\n view more\n <svg xmlns=\"http://www.w3.org/2000/svg\" class=\"ml-1 h-4 w-4\" fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"\n d=\"M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14\"/>\n </svg>\n </a>\n </ng-template>\n <ng-template [ngIf]=\"!element[column.name]\">\n <span *ngIf=\"element[column.name] === null\" class=\"font-mono text-gray-400\">null</span>\n <span *ngIf=\"element[column.name] !== null\">{{ element[column.name] }}</span>\n </ng-template>\n </ng-template>\n <ng-template [ngIf]=\"Array.isArray(element[column.name])\">\n Contains {{ element[column.name].length }} items\n </ng-template>\n <ng-template [ngIf]=\"_.isPlainObject(element[column.name])\">\n Object has {{ Object.keys(element[column.name]).length }} keys\n </ng-template>\n </td>\n </ng-container>\n </ng-template>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\" class=\"h-auto\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns;\"></tr>\n\n </table>\n</div>\n\n\n<div class=\"border-b border-t bg-gray-50 px-4 py-1 flex align-center justify-end\">\n\n <div class=\"flex items-center\">\n <div class=\"text-sm text-gray-500 mr-10\">\n <ng-template [ngIf]=\"dataset\">\n Showing {{ offset + 1 }} - {{ (page * limit) - (limit - tableData.length) }}\n </ng-template>\n </div>\n <select [value]=\"limit\" (change)=\"pageSizeChange($event.target.value)\"\n class=\"mr-8 p-1.5\">\n <option [value]=\"1\">1</option>\n <option [value]=\"5\">5</option>\n <option [value]=\"10\">10</option>\n <option [value]=\"25\">25</option>\n <option [value]=\"50\">50</option>\n <option [value]=\"100\">100</option>\n <option [value]=\"250\">250</option>\n <option [value]=\"1000\">1000</option>\n </select>\n <button mat-icon-button class=\"mr-4\" (click)=\"decreaseOffset()\" [disabled]=\"page <= 1\">\n <mat-icon>chevron_left</mat-icon>\n </button>\n <button mat-icon-button (click)=\"increaseOffset()\" [disabled]=\"endOfResults\">\n <mat-icon>chevron_right</mat-icon>\n </button>\n </div>\n</div>\n", styles: [":host{display:flex;flex-direction:column;position:relative;height:100%}:host>div{flex:0 1 auto}.divider{width:1px;height:17px;background-color:#cecece}.new-transformation .add-transformation{display:none}.new-transformation:hover .add-transformation{display:flex}.long-running{position:fixed;inset:0;background-color:#ffffffb3;z-index:99999;display:flex;align-items:center;justify-content:center;-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px)}.long-running .loading-box{position:relative;margin-bottom:2rem}.long-running .loading-box div{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);font-size:1.2rem;font-weight:500}.long-running p{font-size:1.1rem}.cell-header{width:100%;display:flex;align-items:center;justify-content:space-between}.cell-header.end{justify-content:flex-end}.cell-header.sorting{min-height:43px}.dataset-data-actions{display:flex;align-items:center;flex-wrap:wrap;width:100%;justify-content:flex-end;background-color:#fff;margin-top:-1px}.dataset-data-actions button{min-width:50px;padding:0 13px;color:#505050}.dataset-data-actions .divider{margin:0 .5rem;width:1px;height:36px;background-color:#ddd}.parameter-listing label{flex-direction:row;align-items:center}.parameter-listing label .parameter-input{border-radius:4px;padding-left:.5rem;height:36px;display:flex;align-items:center}.parameter-listing label .parameter-input .param-period-picker{padding:5px}.parameter-listing label .parameter-input button{color:#8e8e8e}.parameter-listing label .parameter-input button.edit-parameter{visibility:hidden}.parameter-listing label .parameter-input button.mat-icon-button{width:30px;height:30px;line-height:30px;align-self:center}.parameter-listing label .parameter-input button.mat-icon-button mat-icon{font-size:20px;width:20px;height:20px;line-height:20px}.parameter-listing label .parameter-input input{font-size:.9rem;padding:.25rem .45rem;width:175px}.parameter-listing label .parameter-input:hover .edit-parameter{visibility:visible}.transformation-listing{display:flex;align-items:center;width:100%;background-color:#00000012;border-bottom:1px solid #ddd;min-height:47px}.transformation-listing .list-title{text-transform:uppercase;font-size:.75rem;padding:0 1rem;border-right:2px solid #ddd;color:#4c4c4c;font-weight:500;letter-spacing:1px}.transformation-listing .badge-item{display:flex;align-items:center;margin-left:1rem;padding-left:1rem;border-radius:20px;background-color:#fff;border:1px solid #ddd;height:30px}.transformation-listing .badge-item.exclude{opacity:.8}.transformation-listing .badge-item:hover{background-color:#fcfcfc}.transformation-listing .badge-item span{margin-right:.5rem;color:#0000008a}.transformation-listing .badge-item button.mat-icon-button{width:33px;height:33px;line-height:33px}.transformation-listing .badge-item button.mat-icon-button mat-icon{font-size:20px;height:20px;width:20px;line-height:20px;color:#0000008a}.dataset-filters{position:relative;overflow-y:scroll;flex:none!important;max-height:400px}.dataset-filters .dataset-filter{position:relative}.dataset-filters .dataset-filter .apply-filter{position:absolute;bottom:.5rem;right:0;z-index:10}.dataset-filters .dataset-filter .remove-filter{position:absolute;top:.5rem;right:0;z-index:10}.badge-holder{display:flex;align-items:center;margin:.25rem 0}.badge-holder .badge-item{display:flex;align-items:center;padding-left:1rem;border-radius:20px}.badge-holder .badge-item.outline{background-color:#fff;border:1px solid #efefef}.badge-holder .badge-item span{margin-right:.5rem;color:#0000008a}.badge-holder .badge-item button.mat-icon-button{width:33px;height:33px;line-height:33px}.badge-holder .badge-item button.mat-icon-button mat-icon{font-size:20px;height:20px;width:20px;line-height:20px;color:#0000008a}table{position:relative;border-collapse:collapse}table.sticky th{position:sticky;top:0;background-color:#f5f5f5;border-top:none!important;border-bottom:none!important;box-shadow:inset 0 -1px #ddd}table th.settings{padding:0}table td{max-width:400px;word-wrap:break-word;padding-top:.5rem;padding-bottom:.5rem;padding-right:1rem;min-width:150px;width:1%}table td.settings{max-width:25px;min-width:25px}table::-webkit-scrollbar{width:.75em;background:transparent}table::-webkit-scrollbar-thumb{background:#d2d2d2}table tbody:nth-of-type(1) tr:nth-of-type(1) td{border-top:none!important}table thead th{border-top:none!important;border-bottom:none!important;box-shadow:inset 0 2px #000,inset 0 -2px #000;padding:2px 0}table thead th{background-clip:padding-box}.table-overflow::-webkit-scrollbar{width:.75em;background:transparent}.table-overflow::-webkit-scrollbar-thumb{background:#d2d2d2}.paging-toolbar{position:sticky;bottom:-20px;left:0;background-color:#fff;right:0;padding:1rem}table{text-align:left;position:relative;border-collapse:collapse}th,td{padding:.25rem}\n"], dependencies: [{ kind: "directive", type: i4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i5.MatLegacyButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "component", type: i6.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i7.MatLegacyMenu, selector: "mat-menu", exportAs: ["matMenu"] }, { kind: "component", type: i7.MatLegacyMenuItem, selector: "[mat-menu-item]", inputs: ["disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i7.MatLegacyMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", exportAs: ["matMenuTrigger"] }, { kind: "directive", type: i8.MatLegacyInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", exportAs: ["matInput"] }, { kind: "component", type: i9.MatChip, selector: "mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]", inputs: ["color", "disabled", "disableRipple", "tabIndex", "role", "id", "aria-label", "aria-description", "value", "removable", "highlighted"], outputs: ["removed", "destroyed"], exportAs: ["matChip"] }, { kind: "component", type: i9.MatChipGrid, selector: "mat-chip-grid", inputs: ["tabIndex", "disabled", "placeholder", "required", "value", "errorStateMatcher"], outputs: ["change", "valueChange"] }, { kind: "directive", type: i9.MatChipInput, selector: "input[matChipInputFor]", inputs: ["matChipInputFor", "matChipInputAddOnBlur", "matChipInputSeparatorKeyCodes", "placeholder", "id", "disabled"], outputs: ["matChipInputTokenEnd"], exportAs: ["matChipInput", "matChipInputFor"] }, { kind: "directive", type: i9.MatChipRemove, selector: "[matChipRemove]" }, { kind: "component", type: i9.MatChipRow, selector: "mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]", inputs: ["color", "disabled", "disableRipple", "tabIndex", "editable"], outputs: ["edited"] }, { kind: "component", type: i10.MatLegacyTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i10.MatLegacyHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i10.MatLegacyHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i10.MatLegacyColumnDef, selector: "[matColumnDef]", inputs: ["sticky", "matColumnDef"] }, { kind: "directive", type: i10.MatLegacyCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i10.MatLegacyRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i10.MatLegacyHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i10.MatLegacyCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i10.MatLegacyHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i10.MatLegacyRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "directive", type: i11.MatSort, selector: "[matSort]", inputs: ["matSortDisabled", "matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i11.MatSortHeader, selector: "[mat-sort-header]", inputs: ["disabled", "mat-sort-header", "arrowPosition", "start", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "directive", type: i12.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i12.CdkDropListGroup, selector: "[cdkDropListGroup]", inputs: ["cdkDropListGroupDisabled"], exportAs: ["cdkDropListGroup"] }, { kind: "directive", type: i12.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i13.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i13.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i13.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: i13.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i13.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i13.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i13.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i13.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i14.MatLegacySlideToggle, selector: "mat-slide-toggle", inputs: ["disabled", "disableRipple", "color", "tabIndex"], exportAs: ["matSlideToggle"] }, { kind: "component", type: i15.MatLegacyProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "diameter", "strokeWidth", "mode", "value"], exportAs: ["matProgressSpinner"] }, { kind: "directive", type: i16.MatLegacyTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }, { kind: "directive", type: i17.CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "directive", type: i17.CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "component", type: i18.DatasetFiltersComponent, selector: "ki-dataset-filters", inputs: ["filterJunction", "filterFields", "joinFilterFields", "joinFieldsName", "openSide", "parameterValues"] }, { kind: "component", type: i19.WhitelistedSqlFunctionsComponent, selector: "ki-whitelisted-sql-functions", inputs: ["search", "fields"] }] });
|
|
1085
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: DatasetEditorComponent, decorators: [{
|
|
1086
|
-
type: Component,
|
|
1087
|
-
args: [{ selector: 'ki-dataset-editor', template: "<div *ngIf=\"longRunning\" class=\"long-running flex-col\">\n\n <div class=\"loading-box\">\n <mat-spinner [diameter]=\"150\"></mat-spinner>\n <div>Loading</div>\n </div>\n\n <p class=\"text-center\">Please wait while we process this query.</p>\n <p class=\"text-center\">The results will be shown here once it has finished running.</p>\n <div>\n <a class=\"text-primary hover:underline\" (click)=\"cancelEvaluate()\">Cancel query and return to editor.</a>\n </div>\n</div>\n<div class=\"pointer-events-none fixed inset-y-0 right-0 flex max-w-full pl-10 -z-10\" id=\"sidebarWrapper\">\n <div [ngClass]=\"{'translate-x-0': sideOpen, 'translate-x-full': !sideOpen}\"\n (click)=\"$event.stopPropagation()\"\n class=\"pointer-events-auto w-screen max-w-md transform transition ease-in-out duration-500 sm:duration-700\"\n id=\"docSidebar\">\n <div class=\"flex h-full flex-col overflow-y-scroll bg-white py-6 shadow-xl\">\n <div class=\"px-4 sm:px-6\">\n <div class=\"flex items-start justify-between\">\n <div></div>\n\n <div class=\"ml-3 flex h-7 items-center\">\n <button type=\"button\" (click)=\"openSide.next(false)\"\n class=\"rounded-md bg-white text-gray-400 hover:text-gray-500 focus:outline-none\">\n <span class=\"sr-only\">Close panel</span>\n <!-- Heroicon name: outline/x -->\n <svg class=\"h-6 w-6\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\"\n stroke=\"currentColor\" aria-hidden=\"true\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"\n d=\"M6 18L18 6M6 6l12 12\"/>\n </svg>\n </button>\n </div>\n </div>\n </div>\n <div class=\"relative flex-1 px-4 sm:px-6\">\n <ki-whitelisted-sql-functions [fields]=\"filterFields\"></ki-whitelisted-sql-functions>\n </div>\n </div>\n </div>\n</div>\n\n<div *ngIf=\"!datasetEditorNoTools\" class=\"border-b cell-header end\">\n <div class=\"leading-5 px-4 text-xs uppercase tracking-wider font-medium border-r-2 text-gray-600\">\n Operations\n </div>\n <div class=\"dataset-data-actions\">\n <button (click)=\"addFilter()\"\n title=\"Filter the set using column based restrictions\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">filter_alt</span>\n filter\n </button>\n <button (click)=\"summariseData()\"\n title=\"Summarise this data to produce aggregated totals, sums and other derivations\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">pivot_table_chart</span>\n summarise\n </button>\n <button *ngIf=\"!datasetEditorSimpleMode\" (click)=\"joinData()\"\n title=\"Join another data set to the current dataset\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">merge_type</span>\n join\n </button>\n <div class=\"divider\"></div>\n <button (click)=\"createFormula()\"\n title=\"Create a formula column using an expression based on other columns\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">functions</span>\n formula\n </button>\n <button (click)=\"editColumnSettings()\"\n title=\"Switch on and off columns for display\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">table_chart</span>\n columns\n </button>\n <div *ngIf=\"!datasetEditorSimpleMode\" class=\"divider\"></div>\n <button *ngIf=\"!datasetEditorSimpleMode\" (click)=\"addParameter()\"\n title=\"Add a parameter to use in filters, expressions etc.\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">text_fields</span>\n parameters\n </button>\n <button *ngIf=\"!datasetEditorSimpleMode\" (click)=\"addPagingMarker()\"\n title=\"Insert paging marker to limit results at this stage in the query flow\"\n class=\"w-24 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">skip_next</span>\n paging marker\n </button>\n <div class=\"divider\"></div>\n <button (click)=\"evaluateDataset()\"\n title=\"Reload this query based upon changes you may have made\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">sync</span>\n reload\n </button>\n <ng-template [ngIf]=\"!datasetEditorReadonly\">\n <button [disabled]=\"!datasetInstanceSummary || !datasetInstanceSummary.id\" (click)=\"shareQuery()\"\n title=\"Share this query with other account holders\"\n class=\"disabled:opacity-50 w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">share</span>\n share\n </button>\n <button (click)=\"saveAsQuery()\"\n title=\"Make a copy of this query\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">file_copy</span>\n copy query\n </button>\n <button *ngIf=\"!dashboardLayoutSettings && datasetInstanceSummary.id\" (click)=\"save()\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">save</span>\n save\n </button>\n </ng-template>\n </div>\n</div>\n\n<div class=\"cell-header\">\n <div class=\"transformation-listing parameter-listing\" *ngIf=\"showParameters || parameterValues.length\">\n <div class=\"list-title\">\n Parameters\n </div>\n <div class=\"flex items-center flex-wrap\">\n <ng-template ngFor let-parameter [ngForOf]=\"parameterValues\" let-i=index>\n\n <label class=\"pl-4\">\n {{ parameter.title }}\n\n <div *ngIf=\"(parameter.value || '').toString().includes('}}')\">\n <mat-chip class=\"bg-gray-50 ml-2\" title=\"Using parameter value from {{parameter.value}}\">\n <div class=\"flex items-center\">\n <span class=\"material-symbols-outlined text-xl mr-1 text-gray-500\">layers</span>\n <span *ngIf=\"dashboardParameters[parameter.value.replace('{{', '').replace('}}', '')]\"\n [innerHTML]=\"dashboardParameters[parameter.value.replace('{{', '').replace('}}', '')].value\"></span>\n <span *ngIf=\"!dashboardParameters[parameter.value.replace('{{', '').replace('}}', '')]\"\n class=\"font-medium text-orange-600\">\n Parameter Not Found !\n </span>\n </div>\n\n <button matChipRemove (click)=\"parameter.value = ''\" title=\"\">\n <mat-icon>cancel</mat-icon>\n </button>\n </mat-chip>\n </div>\n\n\n <div *ngIf=\"!(parameter.value || '').toString().includes('}}')\" class=\"parameter-input\">\n\n <ng-template [ngIf]=\"!parameter.multiple\">\n\n <ng-template [ngIf]=\"parameter.type === 'text'\">\n <input class=\"pr-8\" type=\"text\" placeholder=\"Enter {{parameter.title}}\"\n [(ngModel)]=\"parameter.value\"\n (keyup.enter)=\"evaluateDataset(true)\" required autofocus>\n </ng-template>\n <ng-template [ngIf]=\"parameter.type === 'numeric'\">\n <input class=\"pr-8\" type=\"number\" placeholder=\"Enter {{parameter.title}}\"\n [(ngModel)]=\"parameter.value\"\n (keyup.enter)=\"evaluateDataset(true)\" required autofocus>\n </ng-template>\n <ng-template [ngIf]=\"parameter.type === 'list'\">\n <select class=\"pr-8 py-1.5 pl-1 self-center\" [(ngModel)]=\"parameter.value\"\n (change)=\"evaluateDataset(true)\" required autofocus>\n <option [value]=\"null\">-- Select Value --</option>\n <option *ngFor=\"let item of parameter.list\" [value]=\"item.value\">{{ item.label }}\n </option>\n </select>\n </ng-template>\n <ng-template [ngIf]=\"parameter.type === 'date' || parameter.type === 'datetime'\">\n <ng-template [ngIf]=\"!parameter._dateType\">\n <div class=\"flex items-center mr-8\">\n <button (click)=\"changeDateType($event, parameter, 'picker')\"\n class=\"hover:bg-gray-50 text-gray-800 border border-gray-300 py-0.5 pr-2 rounded mr-2 bg-white flex items-center\">\n <mat-icon class=\"text-base\">calendar_month</mat-icon>\n Date Picker\n </button>\n <button (click)=\"changeDateType($event, parameter, 'period')\"\n class=\"hover:bg-gray-50 text-gray-800 border border-gray-300 py-0.5 pr-2 rounded mr-2 bg-white flex items-center\">\n <mat-icon class=\"text-base\">restore</mat-icon>\n Time Period\n </button>\n </div>\n </ng-template>\n <ng-template [ngIf]=\"parameter._dateType === 'picker'\">\n <input [type]=\"parameter.type === 'date' ? 'date' : 'datetime-local'\"\n placeholder=\"Enter {{parameter.title}}\" [(ngModel)]=\"parameter.value\"\n (keyup.enter)=\"evaluateDataset(true)\" required autofocus>\n\n <a (click)=\"changeDateType($event, parameter, 'period')\"\n matTooltip=\"Time Period\"\n class=\"mr-10 text-center ml-2 hover:bg-gray-50 text-gray-800 border border-gray-300 py-0.5 pr-0.5 rounded mr-2 bg-white flex items-center\">\n <mat-icon class=\"text-base\">restore</mat-icon>\n </a>\n </ng-template>\n <ng-template [ngIf]=\"parameter._dateType === 'period'\">\n <div class=\"flex items-center\">\n <input #periodValue type=\"number\" placeholder=\"No.\" required autofocus\n class=\"w-16 mr-2\" min=\"0\" [value]=\"parameter._periodValue\"\n (change)=\"updatePeriodValue(periodValue.value, period.value, parameter)\">\n\n <select class=\"param-period-picker mr-2\" [value]=\"parameter._period || 'DAYS'\"\n #period\n (change)=\"updatePeriodValue(periodValue.value, period.value, parameter)\">\n <option value=\"DAYS\">Days</option>\n <option value=\"HOURS\">Hours</option>\n </select>\n\n <div>Ago</div>\n </div>\n\n <a (click)=\"changeDateType($event, parameter, 'picker')\"\n matTooltip=\"Date Picker\"\n class=\"mr-10 text-center ml-2 hover:bg-gray-50 text-gray-800 border border-gray-300 py-0.5 pr-0.5 rounded mr-2 bg-white flex items-center\">\n <mat-icon class=\"text-base\">calendar_month</mat-icon>\n </a>\n </ng-template>\n\n </ng-template>\n <ng-template [ngIf]=\"parameter.type === 'boolean'\">\n <mat-slide-toggle class=\"pr-8\" color=\"primary\"\n [checked]=\"parameter.value\" (change)=\"booleanUpdate($event, parameter)\"\n required></mat-slide-toggle>\n </ng-template>\n </ng-template>\n\n <ng-template [ngIf]=\"parameter.multiple\">\n\n\n <mat-chip-grid class=\"pl-2\" #chipGrid aria-label=\"Enter values\">\n <mat-chip-row *ngFor=\"let paramValue of parameter.value\"\n class=\"bg-white mr-2\"\n (removed)=\"removeParameterValue(parameter, paramValue)\">\n {{paramValue}}\n <button matChipRemove [attr.aria-label]=\"'remove ' + paramValue\">\n <mat-icon>cancel</mat-icon>\n </button>\n </mat-chip-row>\n\n <ng-template [ngIf]=\"parameter.type === 'text'\">\n <input class=\"pr-8 py-1 self-center\" type=\"text\" placeholder=\"Enter {{parameter.title}}\"\n required autofocus\n [matChipInputFor]=\"chipGrid\"\n [matChipInputSeparatorKeyCodes]=\"[ENTER, COMMA]\"\n [matChipInputAddOnBlur]=\"true\"\n (matChipInputTokenEnd)=\"addParameterValue(parameter, $event)\">\n </ng-template>\n <ng-template [ngIf]=\"parameter.type === 'numeric'\">\n <input class=\"pr-8\" type=\"number\" placeholder=\"Enter {{parameter.title}}\"\n required autofocus\n [matChipInputFor]=\"chipGrid\"\n [matChipInputSeparatorKeyCodes]=\"[ENTER, COMMA]\"\n [matChipInputAddOnBlur]=\"true\"\n (matChipInputTokenEnd)=\"addParameterValue(parameter, $event)\">\n </ng-template>\n <ng-template [ngIf]=\"parameter.type === 'list'\">\n <select class=\"pr-8 py-1.5 pl-1 self-center\" matNativeControl\n (change)=\"addParameterValue(parameter, $event)\" required autofocus>\n <option [value]=\"null\">-- Select Value --</option>\n <option *ngFor=\"let item of parameter.list\" [value]=\"item.value\">{{ item.label }}\n </option>\n </select>\n </ng-template>\n\n </mat-chip-grid>\n\n\n </ng-template>\n\n\n\n <ng-template [ngIf]=\"!parameter._locked\">\n <button mat-icon-button [matMenuTriggerFor]=\"paramMenu\">\n <mat-icon>settings</mat-icon>\n </button>\n <mat-menu #paramMenu=\"matMenu\">\n <button mat-menu-item (click)=\"addParameter(parameter, i)\">Edit Parameter</button>\n <button mat-menu-item (click)=\"removeParameter(parameter)\">Remove Parameter</button>\n </mat-menu>\n </ng-template>\n <ng-template [ngIf]=\"Object.keys(dashboardParameters || {}).length\">\n <button mat-icon-button [matMenuTriggerFor]=\"dashParamMenu\"\n title=\"Bind this parameter value to another\">\n <mat-icon>text_fields</mat-icon>\n </button>\n <mat-menu #dashParamMenu=\"matMenu\">\n <button mat-menu-item *ngFor=\"let dashParamKey of Object.keys(dashboardParameters)\"\n (click)=\"setDashboardParameter(parameter, dashboardParameters[dashParamKey].name)\">{{ dashboardParameters[dashParamKey].title }}\n </button>\n </mat-menu>\n </ng-template>\n </div>\n\n </label>\n\n <div class=\"divider ml-2\" *ngIf=\"parameterValues.length\"></div>\n\n </ng-template>\n <button mat-icon-button color=\"primary\" class=\"mx-2\" (click)=\"addParameter()\">\n <mat-icon>add_circle</mat-icon>\n </button>\n <button type=\"button\" (click)=\"evaluateDataset(true)\" *ngIf=\"parameterValues.length\"\n class=\"mr-2 flex items-center whitespace-nowrap justify-center px-4 py-1 border border-transparent text-sm rounded-md shadow-sm text-white bg-primary focus:outline-none\">\n Apply Parameters\n </button>\n </div>\n </div>\n</div>\n\n<div class=\"cell-header\">\n <div class=\"transformation-listing py-2\" *ngIf=\"terminatingTransformations.length\">\n <div class=\"list-title\">\n Transformations\n </div>\n <div class=\"example-list flex flex-wrap\" cdkDropListGroup>\n <ng-template ngFor let-transformation [ngForOf]=\"terminatingTransformations\" let-i=\"index\">\n <div cdkDropList (cdkDropListDropped)=\"drop($event)\" cdkDropListOrientation=\"horizontal\"\n [cdkDropListData]=\"{item:transformation,index:i}\" *ngIf=\"!transformation.hidden\">\n <div class=\"flex items-center\">\n <div class=\"new-transformation flex items-center justify-center w-6 h-6\">\n <a [matMenuTriggerFor]=\"addTransformation\"\n class=\"items-center add-transformation text-primary\">\n <mat-icon class=\"flex items-center w-5 h-5 text-xl\">add_circle</mat-icon>\n </a>\n <mat-menu #addTransformation=\"matMenu\">\n <button mat-menu-item (click)=\"insertTransformation(i, 'columns', transformation)\">\n Insert Column Transformation\n </button>\n <button mat-menu-item (click)=\"insertTransformation(i, 'formula', transformation)\">\n Insert Formula Transformation\n </button>\n <button mat-menu-item (click)=\"insertTransformation(i, 'join', transformation)\">\n Insert Join Transformation\n </button>\n <button mat-menu-item (click)=\"insertTransformation(i, 'summarise', transformation)\">\n Insert Summarise Transformation\n </button>\n <button mat-menu-item (click)=\"insertTransformation(i, 'filter', transformation)\">\n Insert Filter Transformation\n </button>\n </mat-menu>\n </div>\n\n <div cdkDrag class=\"pl-0 example-box badge-item w-auto m-0\" cdkOverlayOrigin\n #trigger=\"cdkOverlayOrigin\"\n [ngClass]=\"{active: transformation._active, 'exclude bg-orange-50 border-orange-200': !!transformation.exclude, 'bg-indigo-50 border-indigo-200': (transformation.type === 'filter' && transformation.hide === false)}\">\n\n <button class=\"-mt-0.5\" title=\"Show transformation details\" mat-icon-button\n (click)=\"showTransformationDetail(transformation)\">\n <span class=\"material-symbols-outlined ml-1 text-xl\"\n *ngIf=\"transformation.type === 'columns'\">table_chart</span>\n <span class=\"material-symbols-outlined text-xl\"\n *ngIf=\"transformation.type === 'formula'\">functions</span>\n <span class=\"material-symbols-outlined text-xl\" *ngIf=\"transformation.type === 'join'\">merge_type</span>\n <span class=\"material-symbols-outlined ml-1 text-xl\"\n *ngIf=\"transformation.type === 'summarise'\">pivot_table_chart</span>\n <span class=\"material-symbols-outlined text-xl\"\n *ngIf=\"transformation.type === 'filter'\">filter_alt</span>\n </button>\n\n <span class=\"whitespace-nowrap cursor-pointer\"\n (click)=\"editTerminatingTransformation(transformation)\">{{ transformation._label }}</span>\n\n <ng-template [ngIf]=\"transformation.exclude\">\n <button class=\"-ml-1\" [title]=\"'Re-enable this transformation'\"\n mat-icon-button (click)=\"disableTransformation(transformation, i)\">\n <mat-icon class=\"text-orange-400\">replay</mat-icon>\n </button>\n </ng-template>\n <ng-template\n [ngIf]=\"!transformation.exclude && i + 1 === terminatingTransformations.length\">\n <button class=\"-ml-1\" [title]=\"'Disable transformation'\"\n mat-icon-button (click)=\"disableTransformation(transformation, i)\">\n <mat-icon>block</mat-icon>\n </button>\n </ng-template>\n <ng-template\n [ngIf]=\"!transformation.exclude && i + 1 !== terminatingTransformations.length\">\n <button class=\"-ml-1\" [matMenuTriggerFor]=\"disableMenu\"\n [title]=\"'Disable transformation'\"\n mat-icon-button>\n <mat-icon>block</mat-icon>\n </button>\n <mat-menu #disableMenu=\"matMenu\">\n <button mat-menu-item (click)=\"disableTransformation(transformation, i)\">\n Disable this transformation\n </button>\n <button mat-menu-item (click)=\"excludeUpstreamTransformations(transformation)\">\n Disable subsequent transformation(s)\n </button>\n </mat-menu>\n </ng-template>\n\n <button class=\"-ml-1\" title=\"Remove this transformation\" mat-icon-button color=\"primary\"\n (click)=\"removeTransformation(transformation, true, null, transformation._active)\">\n <mat-icon>cancel</mat-icon>\n </button>\n </div>\n <ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"trigger\"\n [cdkConnectedOverlayOpen]=\"transformation._showDetail\">\n <div class=\"p-4 w-96 bg-white shadow rounded\">\n <ng-template [ngIf]=\"transformation.type === 'summarise'\">\n <p class=\"text-sm text-gray-700 mb-0\">\n <b>SELECT </b><span\n *ngFor=\"let expression of transformation.config.expressions; let i = index\"><span\n *ngIf=\"i > 0\">, </span>{{ expression.customExpression || expression.expressionType + '(' + (expression.fieldName || '') + ')' }}</span>\n <ng-template [ngIf]=\"transformation.config.summariseFieldNames.length\"><br><b>GROUP\n BY </b> {{ transformation.config.summariseFieldNames.join(', ') }}\n </ng-template>\n </p>\n </ng-template>\n <ng-template [ngIf]=\"transformation.type === 'formula'\">\n <div class=\"text-sm text-gray-700 mb-0\">\n <b>EXPRESSION</b> {{ decodeURIComponent(transformation.config.expressions[0].expression) }}\n </div>\n </ng-template>\n <ng-template [ngIf]=\"transformation.type === 'columns'\">\n <div class=\"text-sm text-gray-700 mb-0\">\n <b>COLUMNS</b> {{ _.map(transformation.config.columns, 'title').join(', ') }}\n </div>\n </ng-template>\n <ng-template [ngIf]=\"transformation.type === 'join'\">\n <div class=\"text-sm text-gray-700 mb-0\">\n <b>JOIN\n COLUMNS</b> {{ _.map(transformation.config.joinColumns, 'title').join(', ') }}\n </div>\n </ng-template>\n <ng-template [ngIf]=\"transformation.type === 'filter'\">\n <div *ngFor=\"let filter of transformation.config.filters\"\n class=\"text-sm text-gray-700 mb-0\">\n <b>FILTER</b> {{ filter.lhsExpression }} <b>{{ filter.filterType }}</b> {{ filter.rhsExpression }}\n </div>\n </ng-template>\n </div>\n </ng-template>\n </div>\n\n </div>\n <button\n *ngIf=\"_.some(terminatingTransformations, {exclude: true}) && i === terminatingTransformations.length - 1\"\n class=\"ml-4 flex items-center border-none bg-primary text-sm rounded-md text-white pr-2 pl-1 py-0.5\"\n (click)=\"enableAllTransformation()\">\n <mat-icon class=\"mr-1 text-base\">replay</mat-icon>\n Enable All\n </button>\n </ng-template>\n\n </div>\n\n </div>\n</div>\n\n<div class=\"cell-header\">\n <div class=\"transformation-listing py-2 filters-list\"\n *ngIf=\"_.filter(datasetInstanceSummary.transformationInstances, {type: 'filter', hide: false}).length\">\n <a class=\"list-title flex items-center\" (click)=\"showFilters = !showFilters\">\n Filters \n <mat-icon *ngIf=\"!showFilters\">expand_more</mat-icon>\n <mat-icon *ngIf=\"showFilters\">expand_less</mat-icon>\n </a>\n <ng-template ngFor let-filterTransformation\n [ngForOf]=\"_.filter(datasetInstanceSummary.transformationInstances, {type: 'filter', hide: false})\">\n\n <div class=\"badge-item pl-2 mr-1\" *ngIf=\"_.every(filterTransformation.config.filters[0])\"\n (click)=\"showFilters = !showFilters\">\n <span class=\"cursor-pointer\" [innerHtml]=\"getFilterString(filterTransformation.config)\"></span>\n </div>\n\n </ng-template>\n </div>\n</div>\n\n<div class=\"dataset-filters\" id=\"datasetFilters\"\n *ngIf=\"_.filter(datasetInstanceSummary.transformationInstances, {type: 'filter', hide: false}).length\n && showFilters\">\n\n <ng-template ngFor let-transformation [ngForOf]=\"datasetInstanceSummary.transformationInstances\" let-i=index>\n <ng-template [ngIf]=\"transformation.type === 'filter' && transformation.hide === false\">\n <div class=\"dataset-filter border-b border-gray-200\">\n\n <button mat-stroked-button class=\"mr-2 bg-white remove-filter\" color=\"warn\"\n (click)=\"removeTransformation(transformation, true, i)\">\n Remove Filter\n </button>\n\n <ki-dataset-filters *ngIf=\"filterFields.length\" [filterFields]=\"filterFields\"\n [openSide]=\"openSide\" [parameterValues]=\"filterParameterValues\"\n [filterJunction]=\"transformation.config\"></ki-dataset-filters>\n <button\n *ngIf=\"_.filter(datasetInstanceSummary.transformationInstances, {type: 'filter', hide: false}).length\"\n mat-flat-button class=\"apply-filter mr-2\" color=\"primary\"\n (click)=\"applyFilters()\" [disabled]=\"!filterJunction.filters.length\">\n Apply Filters\n </button>\n\n </div>\n </ng-template>\n </ng-template>\n\n</div>\n\n<div class=\"cell-header\">\n <div class=\"transformation-listing sort\"\n *ngIf=\"_.find(datasetInstanceSummary.transformationInstances, {type: 'multisort'})\">\n <div class=\"list-title\">\n Sort\n </div>\n <div class=\"flex flex-wrap\">\n <div class=\"badge-item outline\"\n [ngClass]=\"{'exclude bg-orange-50 border-orange-200': _.find(datasetInstanceSummary.transformationInstances, {exclude: true})}\"\n *ngFor=\"let sort of _.find(datasetInstanceSummary.transformationInstances, {type: 'multisort'}).config.sorts; let i = index\">\n <span>{{ _.startCase(sort.fieldName) }} <span class=\"uppercase\">{{ sort.direction }}</span></span>\n <button mat-icon-button (click)=\"removeFilter(i)\">\n <mat-icon>cancel</mat-icon>\n </button>\n </div>\n </div>\n\n </div>\n</div>\n\n<div class=\"h-full table-overflow overflow-scroll\">\n <table mat-table [dataSource]=\"tableData\" *ngIf=\"displayedColumns.length\" matSort (matSortChange)=\"sort($event)\"\n class=\"block sticky\">\n\n <ng-template ngFor let-column [ngForOf]=\"filterFields\">\n <ng-container [matColumnDef]=\"column.name\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header\n class=\"text-xs font-semibold text-gray-900 py-3.5 px-4\"> {{ column.title }}\n </th>\n <td mat-cell *matCellDef=\"let element\" class=\"py-3 px-4\">\n <ng-template\n [ngIf]=\"!Array.isArray(element[column.name]) && !_.isPlainObject(element[column.name])\">\n <ng-template [ngIf]=\"element[column.name] && String(element[column.name]).length <= 100\">\n <div [innerHTML]=\"element[column.name]\"></div>\n </ng-template>\n <ng-template [ngIf]=\"element[column.name] && String(element[column.name]).length > 100\">\n <div>{{ element[column.name].substring(0, 100) + '...' }}</div>\n <a (click)=\"viewFullItemData(element[column.name], column.name)\"\n class=\"flex items-center text-sm text-cta\">\n view more\n <svg xmlns=\"http://www.w3.org/2000/svg\" class=\"ml-1 h-4 w-4\" fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"\n d=\"M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14\"/>\n </svg>\n </a>\n </ng-template>\n <ng-template [ngIf]=\"!element[column.name]\">\n <span *ngIf=\"element[column.name] === null\" class=\"font-mono text-gray-400\">null</span>\n <span *ngIf=\"element[column.name] !== null\">{{ element[column.name] }}</span>\n </ng-template>\n </ng-template>\n <ng-template [ngIf]=\"Array.isArray(element[column.name])\">\n Contains {{ element[column.name].length }} items\n </ng-template>\n <ng-template [ngIf]=\"_.isPlainObject(element[column.name])\">\n Object has {{ Object.keys(element[column.name]).length }} keys\n </ng-template>\n </td>\n </ng-container>\n </ng-template>\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\" class=\"h-auto\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns;\"></tr>\n\n </table>\n</div>\n\n\n<div class=\"border-b border-t bg-gray-50 px-4 py-1 flex align-center justify-end\">\n\n <div class=\"flex items-center\">\n <div class=\"text-sm text-gray-500 mr-10\">\n <ng-template [ngIf]=\"dataset\">\n Showing {{ offset + 1 }} - {{ (page * limit) - (limit - tableData.length) }}\n </ng-template>\n </div>\n <select [value]=\"limit\" (change)=\"pageSizeChange($event.target.value)\"\n class=\"mr-8 p-1.5\">\n <option [value]=\"1\">1</option>\n <option [value]=\"5\">5</option>\n <option [value]=\"10\">10</option>\n <option [value]=\"25\">25</option>\n <option [value]=\"50\">50</option>\n <option [value]=\"100\">100</option>\n <option [value]=\"250\">250</option>\n <option [value]=\"1000\">1000</option>\n </select>\n <button mat-icon-button class=\"mr-4\" (click)=\"decreaseOffset()\" [disabled]=\"page <= 1\">\n <mat-icon>chevron_left</mat-icon>\n </button>\n <button mat-icon-button (click)=\"increaseOffset()\" [disabled]=\"endOfResults\">\n <mat-icon>chevron_right</mat-icon>\n </button>\n </div>\n</div>\n", styles: [":host{display:flex;flex-direction:column;position:relative;height:100%}:host>div{flex:0 1 auto}.divider{width:1px;height:17px;background-color:#cecece}.new-transformation .add-transformation{display:none}.new-transformation:hover .add-transformation{display:flex}.long-running{position:fixed;inset:0;background-color:#ffffffb3;z-index:99999;display:flex;align-items:center;justify-content:center;-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px)}.long-running .loading-box{position:relative;margin-bottom:2rem}.long-running .loading-box div{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);font-size:1.2rem;font-weight:500}.long-running p{font-size:1.1rem}.cell-header{width:100%;display:flex;align-items:center;justify-content:space-between}.cell-header.end{justify-content:flex-end}.cell-header.sorting{min-height:43px}.dataset-data-actions{display:flex;align-items:center;flex-wrap:wrap;width:100%;justify-content:flex-end;background-color:#fff;margin-top:-1px}.dataset-data-actions button{min-width:50px;padding:0 13px;color:#505050}.dataset-data-actions .divider{margin:0 .5rem;width:1px;height:36px;background-color:#ddd}.parameter-listing label{flex-direction:row;align-items:center}.parameter-listing label .parameter-input{border-radius:4px;padding-left:.5rem;height:36px;display:flex;align-items:center}.parameter-listing label .parameter-input .param-period-picker{padding:5px}.parameter-listing label .parameter-input button{color:#8e8e8e}.parameter-listing label .parameter-input button.edit-parameter{visibility:hidden}.parameter-listing label .parameter-input button.mat-icon-button{width:30px;height:30px;line-height:30px;align-self:center}.parameter-listing label .parameter-input button.mat-icon-button mat-icon{font-size:20px;width:20px;height:20px;line-height:20px}.parameter-listing label .parameter-input input{font-size:.9rem;padding:.25rem .45rem;width:175px}.parameter-listing label .parameter-input:hover .edit-parameter{visibility:visible}.transformation-listing{display:flex;align-items:center;width:100%;background-color:#00000012;border-bottom:1px solid #ddd;min-height:47px}.transformation-listing .list-title{text-transform:uppercase;font-size:.75rem;padding:0 1rem;border-right:2px solid #ddd;color:#4c4c4c;font-weight:500;letter-spacing:1px}.transformation-listing .badge-item{display:flex;align-items:center;margin-left:1rem;padding-left:1rem;border-radius:20px;background-color:#fff;border:1px solid #ddd;height:30px}.transformation-listing .badge-item.exclude{opacity:.8}.transformation-listing .badge-item:hover{background-color:#fcfcfc}.transformation-listing .badge-item span{margin-right:.5rem;color:#0000008a}.transformation-listing .badge-item button.mat-icon-button{width:33px;height:33px;line-height:33px}.transformation-listing .badge-item button.mat-icon-button mat-icon{font-size:20px;height:20px;width:20px;line-height:20px;color:#0000008a}.dataset-filters{position:relative;overflow-y:scroll;flex:none!important;max-height:400px}.dataset-filters .dataset-filter{position:relative}.dataset-filters .dataset-filter .apply-filter{position:absolute;bottom:.5rem;right:0;z-index:10}.dataset-filters .dataset-filter .remove-filter{position:absolute;top:.5rem;right:0;z-index:10}.badge-holder{display:flex;align-items:center;margin:.25rem 0}.badge-holder .badge-item{display:flex;align-items:center;padding-left:1rem;border-radius:20px}.badge-holder .badge-item.outline{background-color:#fff;border:1px solid #efefef}.badge-holder .badge-item span{margin-right:.5rem;color:#0000008a}.badge-holder .badge-item button.mat-icon-button{width:33px;height:33px;line-height:33px}.badge-holder .badge-item button.mat-icon-button mat-icon{font-size:20px;height:20px;width:20px;line-height:20px;color:#0000008a}table{position:relative;border-collapse:collapse}table.sticky th{position:sticky;top:0;background-color:#f5f5f5;border-top:none!important;border-bottom:none!important;box-shadow:inset 0 -1px #ddd}table th.settings{padding:0}table td{max-width:400px;word-wrap:break-word;padding-top:.5rem;padding-bottom:.5rem;padding-right:1rem;min-width:150px;width:1%}table td.settings{max-width:25px;min-width:25px}table::-webkit-scrollbar{width:.75em;background:transparent}table::-webkit-scrollbar-thumb{background:#d2d2d2}table tbody:nth-of-type(1) tr:nth-of-type(1) td{border-top:none!important}table thead th{border-top:none!important;border-bottom:none!important;box-shadow:inset 0 2px #000,inset 0 -2px #000;padding:2px 0}table thead th{background-clip:padding-box}.table-overflow::-webkit-scrollbar{width:.75em;background:transparent}.table-overflow::-webkit-scrollbar-thumb{background:#d2d2d2}.paging-toolbar{position:sticky;bottom:-20px;left:0;background-color:#fff;right:0;padding:1rem}table{text-align:left;position:relative;border-collapse:collapse}th,td{padding:.25rem}\n"] }]
|
|
1088
|
-
}], ctorParameters: function () { return [{ type: i1.MatLegacyDialogRef }, { type: undefined, decorators: [{
|
|
1089
|
-
type: Inject,
|
|
1090
|
-
args: [MAT_DIALOG_DATA]
|
|
1091
|
-
}] }, { type: i1.MatLegacyDialog }, { type: i2.DatasetService }, { type: i3.MatLegacySnackBar }]; }, propDecorators: { datasetInstanceSummary: [{
|
|
1092
|
-
type: Input
|
|
1093
|
-
}], environment: [{
|
|
1094
|
-
type: Input
|
|
1095
|
-
}], admin: [{
|
|
1096
|
-
type: Input
|
|
1097
|
-
}], dashboardParameters: [{
|
|
1098
|
-
type: Input
|
|
1099
|
-
}], dashboardLayoutSettings: [{
|
|
1100
|
-
type: Input
|
|
1101
|
-
}], accountId: [{
|
|
1102
|
-
type: Input
|
|
1103
|
-
}], newTitle: [{
|
|
1104
|
-
type: Input
|
|
1105
|
-
}], newDescription: [{
|
|
1106
|
-
type: Input
|
|
1107
|
-
}], datasetEditorReadonly: [{
|
|
1108
|
-
type: Input
|
|
1109
|
-
}], datasetEditorSimpleMode: [{
|
|
1110
|
-
type: Input
|
|
1111
|
-
}], datasetEditorNoTools: [{
|
|
1112
|
-
type: Input
|
|
1113
|
-
}], dataLoaded: [{
|
|
1114
|
-
type: Output
|
|
1115
|
-
}], datasetInstanceSummaryChange: [{
|
|
1116
|
-
type: Output
|
|
1117
|
-
}] } });
|
|
1118
|
-
export class DatasetEditorPopupComponent {
|
|
1119
|
-
constructor(data) {
|
|
1120
|
-
this.data = data;
|
|
1121
|
-
this.fullData = this.data.fullData;
|
|
1122
|
-
this.columnName = _.startCase(this.data.columnName);
|
|
1123
|
-
}
|
|
1124
|
-
}
|
|
1125
|
-
DatasetEditorPopupComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: DatasetEditorPopupComponent, deps: [{ token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component });
|
|
1126
|
-
DatasetEditorPopupComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: DatasetEditorPopupComponent, selector: "ki-dataset-editor-popup", host: { classAttribute: "dialog-wrapper" }, ngImport: i0, template: "<div class=\"dialog\" cdkDrag cdkDragRootElement=\".cdk-overlay-pane\">\n\n <div class=\"dialog-title\" cdkDragHandle>\n <h2 mat-dialog-title>{{columnName}}</h2>\n\n <button mat-icon-button mat-dialog-close>\n <mat-icon>clear</mat-icon>\n </button>\n </div>\n\n <div class=\"dialog-content\">\n\n <div [innerHTML]=\"fullData\"></div>\n\n </div>\n\n</div>\n\n\n", dependencies: [{ kind: "component", type: i5.MatLegacyButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "component", type: i6.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i1.MatLegacyDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i1.MatLegacyDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i12.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i12.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }] });
|
|
1127
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: DatasetEditorPopupComponent, decorators: [{
|
|
1128
|
-
type: Component,
|
|
1129
|
-
args: [{ selector: 'ki-dataset-editor-popup', host: { class: 'dialog-wrapper' }, template: "<div class=\"dialog\" cdkDrag cdkDragRootElement=\".cdk-overlay-pane\">\n\n <div class=\"dialog-title\" cdkDragHandle>\n <h2 mat-dialog-title>{{columnName}}</h2>\n\n <button mat-icon-button mat-dialog-close>\n <mat-icon>clear</mat-icon>\n </button>\n </div>\n\n <div class=\"dialog-content\">\n\n <div [innerHTML]=\"fullData\"></div>\n\n </div>\n\n</div>\n\n\n" }]
|
|
1130
|
-
}], ctorParameters: function () { return [{ type: DatasetEditorPopupComponent, decorators: [{
|
|
1131
|
-
type: Inject,
|
|
1132
|
-
args: [MAT_DIALOG_DATA]
|
|
1133
|
-
}] }]; } });
|
|
1134
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0YXNldC1lZGl0b3IuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmcta2luaW50ZWwvc3JjL2xpYi9jb21wb25lbnRzL2RhdGFzZXQvZGF0YXNldC1lZGl0b3IvZGF0YXNldC1lZGl0b3IuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmcta2luaW50ZWwvc3JjL2xpYi9jb21wb25lbnRzL2RhdGFzZXQvZGF0YXNldC1lZGl0b3IvZGF0YXNldC1lZGl0b3IuY29tcG9uZW50Lmh0bWwiLCIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZy1raW5pbnRlbC9zcmMvbGliL2NvbXBvbmVudHMvZGF0YXNldC9kYXRhc2V0LWVkaXRvci9kYXRhc2V0LWVkaXRvci1wb3B1cC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBQyxTQUFTLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBVSxNQUFNLEVBQUUsWUFBWSxFQUFZLE1BQU0sZUFBZSxDQUFDO0FBQ2hHLE9BQU8sS0FBSyxNQUFNLE1BQU0sUUFBUSxDQUFDO0FBR2pDLE9BQU8sRUFDSCxzQkFBc0IsSUFBSSxlQUFlLEVBRzVDLE1BQU0saUNBQWlDLENBQUM7QUFDekMsT0FBTyxFQUFDLHlCQUF5QixFQUFDLE1BQU0saURBQWlELENBQUM7QUFDMUYsT0FBTyxFQUFDLHVCQUF1QixFQUFDLE1BQU0sK0NBQStDLENBQUM7QUFDdEYsT0FBTyxFQUFDLDZCQUE2QixFQUFDLE1BQU0sMkRBQTJELENBQUM7QUFDeEcsT0FBTyxFQUFDLDhCQUE4QixFQUFDLE1BQU0sNkRBQTZELENBQUM7QUFHM0csT0FBTyxFQUFDLHNCQUFzQixFQUFDLE1BQU0sMkRBQTJELENBQUM7QUFDakcsT0FBTyxFQUNILDRCQUE0QixFQUMvQixNQUFNLGtGQUFrRixDQUFDO0FBQzFGLE9BQU8sRUFB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QkFBdUI7c0JBQS9CLEtBQUs7Z0JBQ0csU0FBUztzQkFBakIsS0FBSztnQkFDRyxRQUFRO3NCQUFoQixLQUFLO2dCQUNHLGNBQWM7c0JBQXRCLEtBQUs7Z0JBQ0cscUJBQXFCO3NCQUE3QixLQUFLO2dCQUNHLHVCQUF1QjtzQkFBL0IsS0FBSztnQkFDRyxvQkFBb0I7c0JBQTVCLEtBQUs7Z0JBRUksVUFBVTtzQkFBbkIsTUFBTTtnQkFDRyw0QkFBNEI7c0JBQXJDLE1BQU07O0FBbW9DWCxNQUFNLE9BQU8sMkJBQTJCO0lBS3BDLFlBQTRDLElBQWlDO1FBQWpDLFNBQUksR0FBSixJQUFJLENBQTZCO1FBRXpFLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUM7UUFDbkMsSUFBSSxDQUFDLFVBQVUsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDeEQsQ0FBQzs7eUhBVFEsMkJBQTJCLGtCQUtoQixlQUFlOzZHQUwxQiwyQkFBMkIsMkdFbHNDeEMsNlpBbUJBOzRGRitxQ2EsMkJBQTJCO2tCQUx2QyxTQUFTOytCQUNJLHlCQUF5QixRQUU3QixFQUFDLEtBQUssRUFBRSxnQkFBZ0IsRUFBQzs7MEJBT2xCLE1BQU07MkJBQUMsZUFBZSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7Q29tcG9uZW50LCBJbmplY3QsIElucHV0LCBPbkluaXQsIE91dHB1dCwgRXZlbnRFbWl0dGVyLCBPbkRlc3Ryb3l9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0ICogYXMgbG9kYXNoIGZyb20gJ2xvZGFzaCc7XG5cbmNvbnN0IF8gPSBsb2Rhc2guZGVmYXVsdDtcbmltcG9ydCB7XG4gICAgTUFUX0xFR0FDWV9ESUFMT0dfREFUQSBhcyBNQVRfRElBTE9HX0RBVEEsXG4gICAgTWF0TGVnYWN5RGlhbG9nIGFzIE1hdERpYWxvZyxcbiAgICBNYXRMZWdhY3lEaWFsb2dSZWYgYXMgTWF0RGlhbG9nUmVmXG59IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2xlZ2FjeS1kaWFsb2cnO1xuaW1wb3J0IHtEYXRhc2V0U3VtbWFyaXNlQ29tcG9uZW50fSBmcm9tICcuL2RhdGFzZXQtc3VtbWFyaXNlL2RhdGFzZXQtc3VtbWFyaXNlLmNvbXBvbmVudCc7XG5pbXBvcnQge0RhdGFzZXRBZGRKb2luQ29tcG9uZW50fSBmcm9tICcuL2RhdGFzZXQtYWRkLWpvaW4vZGF0YXNldC1hZGQtam9pbi5jb21wb25lbnQnO1xuaW1wb3J0IHtEYXRhc2V0Q3JlYXRlRm9ybXVsYUNvbXBvbmVudH0gZnJvbSAnLi9kYXRhc2V0LWNyZWF0ZS1mb3JtdWxhL2RhdGFzZXQtY3JlYXRlLWZvcm11bGEuY29tcG9uZW50JztcbmltcG9ydCB7RGF0YXNldENvbHVtblNldHRpbmdzQ29tcG9uZW50fSBmcm9tICcuL2RhdGFzZXQtY29sdW1uLXNldHRpbmdzL2RhdGFzZXQtY29sdW1uLXNldHRpbmdzLmNvbXBvbmVudCc7XG5pbXBvcnQge0RhdGFzZXRTZXJ2aWNlfSBmcm9tICcuLi8uLi8uLi9zZXJ2aWNlcy9kYXRhc2V0LnNlcnZpY2UnO1xuaW1wb3J0IHtNYXRMZWdhY3lTbmFja0JhciBhcyBNYXRTbmFja0Jhcn0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvbGVnYWN5LXNuYWNrLWJhcic7XG5pbXBvcnQge0RhdGFzZXRGaWx0ZXJDb21wb25lbnR9IGZyb20gJy4vZGF0YXNldC1maWx0ZXJzL2RhdGFzZXQtZmlsdGVyL2RhdGFzZXQtZmlsdGVyLmNvbXBvbmVudCc7XG5pbXBvcnQge1xuICAgIERhdGFzZXRBZGRQYXJhbWV0ZXJDb21wb25lbnRcbn0gZnJvbSAnLi9kYXRhc2V0LXBhcmFtZXRlci12YWx1ZXMvZGF0YXNldC1hZGQtcGFyYW1ldGVyL2RhdGFzZXQtYWRkLXBhcmFtZXRlci5jb21wb25lbnQnO1xuaW1wb3J0IHtCZWhhdmlvclN1YmplY3QsIFN1YmplY3QsIFN1YnNjcmlwdGlvbn0gZnJvbSAncnhqcyc7XG5pbXBvcnQgbW9tZW50IGZyb20gJ21vbWVudCc7XG5pbXBvcnQge1xuICAgIFVwc3RyZWFtQ2hhbmdlc0NvbmZpcm1hdGlvbkNvbXBvbmVudFxufSBmcm9tICcuLi9kYXRhc2V0LWVkaXRvci91cHN0cmVhbS1jaGFuZ2VzLWNvbmZpcm1hdGlvbi91cHN0cmVhbS1jaGFuZ2VzLWNvbmZpcm1hdGlvbi5jb21wb25lbnQnO1xuaW1wb3J0IHtcbiAgICBEYXRhc2V0TmFtZURpYWxvZ0NvbXBvbmVudFxufSBmcm9tICcuLi9kYXRhc2V0LWVkaXRvci9kYXRhc2V0LW5hbWUtZGlhbG9nL2RhdGFzZXQtbmFtZS1kaWFsb2cuY29tcG9uZW50JztcbmltcG9ydCB7Q2RrRHJhZ0Ryb3AsIG1vdmVJdGVtSW5BcnJheX0gZnJvbSAnQGFuZ3VsYXIvY2RrL2RyYWctZHJvcCc7XG5pbXBvcnQge1xuICAgIE1vdmVUcmFuc2Zvcm1hdGlvbkNvbmZpcm1hdGlvbkNvbXBvbmVudFxufSBmcm9tICcuLi9kYXRhc2V0LWVkaXRvci9tb3ZlLXRyYW5zZm9ybWF0aW9uLWNvbmZpcm1hdGlvbi9tb3ZlLXRyYW5zZm9ybWF0aW9uLWNvbmZpcm1hdGlvbi5jb21wb25lbnQnO1xuaW1wb3J0IHtcbiAgICBTYXZlQXNRdWVyeUNvbXBvbmVudFxufSBmcm9tICcuLi9kYXRhc2V0LWVkaXRvci9zYXZlLWFzLXF1ZXJ5L3NhdmUtYXMtcXVlcnkuY29tcG9uZW50JztcbmltcG9ydCB7XG4gICAgU2hhcmVRdWVyeUNvbXBvbmVudFxufSBmcm9tICcuLi9kYXRhc2V0LWVkaXRvci9zaGFyZS1xdWVyeS9zaGFyZS1xdWVyeS5jb21wb25lbnQnO1xuaW1wb3J0IHtcbiAgICBSZW1vdmVUcmFuc2Zvcm1hdGlvbldhcm5pbmdDb21wb25lbnRcbn0gZnJvbSAnLi4vZGF0YXNldC1lZGl0b3IvcmVtb3ZlLXRyYW5zZm9ybWF0aW9uLXdhcm5pbmcvcmVtb3ZlLXRyYW5zZm9ybWF0aW9uLXdhcm5pbmcuY29tcG9uZW50JztcbmltcG9ydCB7Q09NTUEsIEVOVEVSfSBmcm9tIFwiQGFuZ3VsYXIvY2RrL2tleWNvZGVzXCI7XG5pbXBvcnQge01hdENoaXBJbnB1dEV2ZW50fSBmcm9tIFwiQGFuZ3VsYXIvbWF0ZXJpYWwvY2hpcHNcIjtcblxuQENvbXBvbmVudCh7XG4gICAgc2VsZWN0b3I6ICdraS1kYXRhc2V0LWVkaXRvcicsXG4gICAgdGVtcGxhdGVVcmw6ICcuL2RhdGFzZXQtZWRpdG9yLmNvbXBvbmVudC5odG1sJyxcbiAgICBzdHlsZVVybHM6IFsnLi9kYXRhc2V0LWVkaXRvci5jb21wb25lbnQuc2FzcyddXG59KVxuZXhwb3J0IGNsYXNzIERhdGFzZXRFZGl0b3JDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIE9uRGVzdHJveSB7XG5cbiAgICBASW5wdXQoKSBkYXRhc2V0SW5zdGFuY2VTdW1tYXJ5OiBhbnk7XG4gICAgQElucHV0KCkgZW52aXJvbm1lbnQ6IGFueSA9IHt9O1xuICAgIEBJbnB1dCgpIGFkbWluOiBib29sZWFuO1xuICAgIEBJbnB1dCgpIGRhc2hib2FyZFBhcmFtZXRlcnM6IGFueTtcbiAgICBASW5wdXQoKSBkYXNoYm9hcmRMYXlvdXRTZXR0aW5nczogYW55O1xuICAgIEBJbnB1dCgpIGFjY291bnRJZDtcbiAgICBASW5wdXQoKSBuZXdUaXRsZTtcbiAgICBASW5wdXQoKSBuZXdEZXNjcmlwdGlvbjtcbiAgICBASW5wdXQoKSBkYXRhc2V0RWRpdG9yUmVhZG9ubHkgPSBmYWxzZTtcbiAgICBASW5wdXQoKSBkYXRhc2V0RWRpdG9yU2ltcGxlTW9kZTogYm9vbGVhbiA9IGZhbHNlO1xuICAgIEBJbnB1dCgpIGRhdGFzZXRFZGl0b3JOb1Rvb2xzOiBib29sZWFuID0gZmFsc2U7XG5cbiAgICBAT3V0cHV0KCkgZGF0YUxvYWRlZCA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpO1xuICAgIEBPdXRwdXQoKSBkYXRhc2V0SW5zdGFuY2VTdW1tYXJ5Q2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gICAgcHVibGljIGRhdGFzZXQ6IGFueTtcbiAgICBwdWJsaWMgdGFibGVEYXRhID0gW107XG4gICAgcHVibGljIHNob3dGaWx0ZXJzID0gZmFsc2U7XG4gICAgcHVibGljIHNob3dQYXJhbWV0ZXJzID0gZmFsc2U7XG4gICAgcHVibGljIGRpc3BsYXllZENvbHVtbnMgPSBbXTtcbiAgICBwdWJsaWMgXyA9IF87XG4gICAgcHVibGljIEFycmF5ID0gQXJyYXk7XG4gICAgcHVibGljIE9iamVjdCA9IE9iamVjdDtcbiAgICBwdWJsaWMgZmlsdGVyRmllbGRzID0gW107XG4gICAgcHVibGljIGZpbHRlckp1bmN0aW9uID0ge1xuICAgICAgICBsb2dpYzogJ0FORCcsXG4gICAgICAgIGZpbHRlcnM6IFt7XG4gICAgICAgICAgICBsaHNFeHByZXNzaW9uOiAnJyxcbiAgICAgICAgICAgIHJoc0V4cHJlc3Npb246IFtdLFxuICAgICAgICAgICAgZmlsdGVyVHlwZTogJydcbiAgICAgICAgfV0sXG4gICAgICAgIGZpbHRlckp1bmN0aW9uczogW11cbiAgICB9O1xuICAgIHB1YmxpYyBwYWdlID0gMTtcbiAgICBwdWJsaWMgZW5kT2ZSZXN1bHRzID0gZmFsc2U7XG4gICAgcHVibGljIHBhcmFtZXRlclZhbHVlczogYW55ID0gW107XG4gICAgcHVibGljIGZvY3VzUGFyYW1zID0gZmFsc2U7XG4gICAgcHVibGljIHRlcm1pbmF0aW5nVHJhbnNmb3JtYXRpb25zID0gW107XG4gICAgcHVibGljIFN0cmluZyA9IFN0cmluZztcbiAgICBwdWJsaWMgbG9uZ1J1bm5pbmcgPSBmYWxzZTtcbiAgICBwdWJsaWMgc2lkZU9wZW4gPSBmYWxzZTtcbiAgICBwdWJsaWMgb3BlblNpZGUgPSBuZXcgQmVoYXZpb3JTdWJqZWN0KGZhbHNlKTtcbiAgICBwdWJsaWMgbGltaXQgPSAyNTtcbiAgICBwdWJsaWMgb2Zmc2V0ID0gMDtcbiAgICBwdWJsaWMgZmlsdGVyUGFyYW1ldGVyVmFsdWVzOiBhbnk7XG5cbiAgICBwdWJsaWMgcmVhZG9ubHkgZGVjb2RlVVJJQ29tcG9uZW50ID0gZGVjb2RlVVJJQ29tcG9uZW50O1xuXG4gICAgcHJpdmF0ZSBldmFsdWF0ZVN1YjogU3Vic2NyaXB0aW9uO1xuICAgIHByaXZhdGUgcmVzdWx0c1N1YjogU3Vic2NyaXB0aW9uO1xuICAgIHByaXZhdGUgZGF0YXNldFRpdGxlOiBzdHJpbmc7XG5cbiAgICBjb25zdHJ1Y3RvcihwdWJsaWMgZGlhbG9nUmVmOiBNYXREaWFsb2dSZWY8RGF0YXNldEVkaXRvckNvbXBvbmVudD4sXG4gICAgICAgICAgICAgICAgQEluamVjdChNQVRfRElBTE9HX0RBVEEpIHB1YmxpYyBkYXRhOiBhbnksXG4gICAgICAgICAgICAgICAgcHJpdmF0ZSBkaWFsb2c6IE1hdERpYWxvZyxcbiAgICAgICAgICAgICAgICBwcml2YXRlIGRhdGFzZXRTZXJ2aWNlOiBEYXRhc2V0U2VydmljZSxcbiAgICAgICAgICAgICAgICBwcml2YXRlIHNuYWNrQmFyOiBNYXRTbmFja0Jhcikge1xuICAgIH1cblxuICAgIGFzeW5jIG5nT25Jbml0KCkge1xuICAgICAgICBsZXQgbGltaXQgPSBudWxsO1xuICAgICAgICBsaW1pdCA9IGxvY2FsU3RvcmFnZS5nZXRJdGVtKCdkYXRhc2V0SW5zdGFuY2VMaW1pdCcgKyB0aGlzLmRhdGFzZXRJbnN0YW5jZVN1bW1hcnkuaWQpO1xuXG4gICAgICAgIHRoaXMubGltaXQgPSBsaW1pdCA/IE51bWJlcihsaW1pdCkgOiAyNTtcblxuICAgICAgICBpZiAodGhpcy5kYXRhc2V0SW5zdGFuY2VTdW1tYXJ5LnRyYW5zZm9ybWF0aW9uSW5zdGFuY2VzLmxlbmd0aCkge1xuICAgICAgICAgICAgY29uc3QgZmlsdGVycyA9IF8uZmlsdGVyKHRoaXMuZGF0YXNldEluc3RhbmNlU3VtbWFyeS50cmFuc2Zvcm1hdGlvbkluc3RhbmNlcywge3R5cGU6ICdmaWx0ZXInfSk7XG4gICAgICAgICAgICBpZiAoZmlsdGVycy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBmaWx0ZXJzLmZvckVhY2goZmlsdGVyID0+IHtcbiAgICAgICAgICAgICAgICAgICAgZmlsdGVyLmhpZGUgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkodGhpcy5kYXRhc2V0SW5zdGFuY2VTdW1tYXJ5LnBhcmFtZXRlclZhbHVlcykpIHtcbiAgICAgICAgICAgIHRoaXMuZGF0YXNldEluc3RhbmNlU3VtbWFyeS5wYXJhbWV0ZXJWYWx1ZXMgPSB7fTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghdGhpcy5kYXRhc2V0SW5zdGFuY2VTdW1tYXJ5LmlkKSB7XG4gICAgICAgICAgICB0aGlzLmRhdGFzZXRUaXRsZSA9IHRoaXMuZGF0YXNldEluc3RhbmNlU3VtbWFyeS50aXRsZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuZXZhbHVhdGVEYXRhc2V0KCk7XG5cbiAgICAgICAgdGhpcy5vcGVuU2lkZS5zdWJzY3JpYmUoKG9wZW46IGJvb2xlYW4pID0+IHtcbiAgICAgICAgICAgIGlmIChvcGVuKSB7XG4gICAgICAgICAgICAgICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3NpZGViYXJXcmFwcGVyJyk/LmNsYXNzTGlzdC5hZGQoJ3otMjAnKTtcbiAgICAgICAgICAgICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnc2lkZWJhcldyYXBwZXInKT8uY2xhc3NMaXN0LnJlbW92ZSgnLXotMTAnKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdzaWRlYmFyV3JhcHBlcicpPy5jbGFzc0xpc3QuYWRkKCctei0xMCcpO1xuICAgICAgICAgICAgICAgICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnc2lkZWJhcldyYXBwZXInKT8uY2xhc3NMaXN0LnJlbW92ZSgnei0yMCcpO1xuICAgICAgICAgICAgICAgIH0sIDcwMCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnNpZGVPcGVuID0gb3BlbjtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgbmdPbkRlc3Ryb3koKSB7XG4gICAgICAgIGlmICh0aGlzLmV2YWx1YXRlU3ViKSB7XG4gICAgICAgICAgICB0aGlzLmV2YWx1YXRlU3ViLnVuc3Vic2NyaWJlKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgc2hhcmVRdWVyeSgpIHtcbiAgICAgICAgdGhpcy5kaWFsb2cub3BlbihTaGFyZVF1ZXJ5Q29tcG9uZW50LCB7XG4gICAgICAgICAgICB3aWR0aDogJzgwMHB4JyxcbiAgICAgICAgICAgIGhlaWdodDogJzk1MHB4JyxcbiAgICAgICAgICAgIGRhdGE6IHtcbiAgICAgICAgICAgICAgICBkYXRhc2V0SW5zdGFuY2U6IHRoaXMuZGF0YXNldEluc3RhbmNlU3VtbWFyeVxuICAgICAgICAgICAgfVxuICAgICAgICB9KS5hZnRlckNsb3NlZCgpLnN1YnNjcmliZShyZXMgPT4ge1xuXG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBzYXZlQXNRdWVyeSgpIHtcbiAgICAgICAgY29uc3QgbmV3RGF0YXNldEluc3RhbmNlOiBhbnkgPSB7XG4gICAgICAgICAgICB0aXRsZTogdGhpcy5kYXRhc2V0SW5zdGFuY2VTdW1tYXJ5LnRpdGxlIHx8ICdTdG9yZWQgUXVlcnknICsgJyBDT1BZJyxcbiAgICAgICAgICAgIHN1bW1hcnk6ICcnLFxuICAgICAgICAgICAgZGVzY3JpcHRpb246ICcnLFxuICAgICAgICAgICAgY2F0ZWdvcmllczogdGhpcy5kYXRhc2V0SW5zdGFuY2VTdW1tYXJ5LmNhdGVnb3JpZXMsXG4gICAgICAgICAgICBkYXRhc291cmNlSW5zdGFuY2VLZXk6IHRoaXMuZGF0YXNldEluc3RhbmNlU3VtbWFyeS5kYXRhc291cmNlSW5zdGFuY2VLZXksXG4gICAgICAgICAgICBkYXRhc2V0SW5zdGFuY2VJZDogdGhpcy5kYXRhc2V0SW5zdGFuY2VTdW1tYXJ5LmRhdGFzZXRJbnN0YW5jZUlkLFxuICAgICAgICAgICAgdGFnczogdGhpcy5kYXRhc2V0SW5zdGFuY2VTdW1tYXJ5LnRhZ3MsXG4gICAgICAgICAgICBwYXJhbWV0ZXJWYWx1ZTogdGhpcy5kYXRhc2V0SW5zdGFuY2VTdW1tYXJ5LnBhcmFtZXRlclZhbHVlcyxcbiAgICAgICAgICAgIHBhcmFtZXRlcnM6IHRoaXMuZGF0YXNldEluc3RhbmNlU3VtbWFyeS5wYXJhbWV0ZXJzXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuZGlhbG9nLm9wZW4oU2F2ZUFzUXVlcnlDb21wb25lbnQsIHtcbiAgICAgICAgICAgIHdpZHRoOiAnNzAwcHgnLFxuICAgICAgICAgICAgaGVpZ2h0OiAnODAwcHgnLFxuICAgICAgICAgICAgZGF0YToge1xuICAgICAgICAgICAgICAgIGRhdGFzZXRJbnN0YW5jZVN1bW1hcnk6IG5ld0RhdGFzZXRJbnN0YW5jZSxcbiAgICAgICAgICAgICAgICB0cmFuc2Zvcm1hdGlvbnM6IHRoaXMuZGF0YXNldEluc3RhbmNlU3VtbWFyeS50cmFuc2Zvcm1hdGlvbkluc3RhbmNlc1xuICAgICAgICAgICAgfVxuICAgICAgICB9KS5hZnRlckNsb3NlZCgpLnN1YnNjcmliZShhc3luYyB0cmFuc2Zvcm1hdGlvbkluc3RhbmNlcyA9PiB7XG4gICAgICAgICAgICBpZiAodHJhbnNmb3JtYXRpb25JbnN0YW5jZXMpIHtcbiAgICAgICAgICAgICAgICBuZXdEYXRhc2V0SW5zdGFuY2UudHJhbnNmb3JtYXRpb25JbnN0YW5jZXMgPSB0cmFuc2Zvcm1hdGlvbkluc3RhbmNlcztcbiAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLmRhdGFzZXRTZXJ2aWNlLnNhdmVEYXRhc2V0KG5ld0RhdGFzZXRJbnN0YW5jZSwgdGhpcy5hY2NvdW50SWQpO1xuICAgICAgICAgICAgICAgIHRoaXMuc25hY2tCYXIub3BlbignRGF0YXNldCBzdWNjZXNzZnVsbHkgY29waWVkLicsICdDbG9zZScsIHtcbiAgICAgICAgICAgICAgICAgICAgdmVydGljYWxQb3NpdGlvbjogJ3RvcCcsXG4gICAgICAgICAgICAgICAgICAgIGR1cmF0aW9uOiAzMDAwXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHB1YmxpYyBkcm9wKGV2ZW50OiBDZGtEcmFnRHJvcDxhbnk+KSB7XG4gICAgICAgIHRoaXMuZGlhbG9nLm9wZW4oTW92ZVRyYW5zZm9ybWF0aW9uQ29uZmlybWF0aW9uQ29tcG9uZW50LCB7XG4gICAgICAgICAgICB3aWR0aDogJzcwMHB4JyxcbiAgICAgICAgICAgIGhlaWdodDogJzI3NXB4J1xuICAgICAgICB9KS5hZnRlckNsb3NlZCgpLnN1YnNjcmliZShyZXMgPT4ge1xuICAgICAgICAgICAgaWYgKHJlcyA9PT0gJ3Byb2NlZWQnKSB7XG4gICAgICAgICAgICAgICAgbW92ZUl0ZW1JbkFycmF5KHRoaXMuZGF0YXNldEluc3RhbmNlU3VtbWFyeS50cmFuc2Zvcm1hdGlvbkluc3RhbmNlcywgZXZlbnQucHJldmlvdXNDb250YWluZXIuZGF0YS5pbmRleCwgZXZlbnQuY29udGFpbmVyLmRhdGEuaW5kZXgpO1xuICAgICAgICAgICAgICAgIHRoaXMuZXZhbHVhdGVEYXRhc2V0KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBpbnNlcnRUcmFuc2Zvcm1hdGlvbihpbmRleDogbnVtYmVyLCB0cmFuc2Zvcm1hdGlvblR5cGU6IHN0cmluZywgbmV4dFRyYW5zZm9ybWF0aW9uOiBhbnkpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5leGNsdWRlVXBzdHJlYW1UcmFuc2Zvcm1hdGlvbnMobmV4dFRyYW5zZm9ybWF0aW9uKTtcblxuICAgICAgICBzd2l0Y2ggKHRyYW5zZm9ybWF0aW9uVHlwZSkge1xuICAgICAgICAgICAgY2FzZSAnY29sdW1ucyc6XG4gICAgICAgICAgICAgICAgdGhpcy5lZGl0Q29sdW1uU2V0dGluZ3MobnVsbCwgbnVsbCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnZm9ybXVsYSc6XG4gICAgICAgICAgICAgICAgdGhpcy5jcmVhdGVGb3JtdWxhKG51bGwsIG51bGwsIGluZGV4KTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ2pvaW4nOlxuICAgICAgICAgICAgICAgIHRoaXMuam9pbkRhdGEobnVsbCwgbnVsbCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnc3VtbWFyaXNlJzpcbiAgICAgICAgICAgICAgICB0aGlzLnN1bW1hcmlzZURhdGEobnVsbCwgbnVsbCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnZmlsdGVyJzpcbiAgICAgICAgICAgICAgICB0aGlzLmFkZEZpbHRlcihpbmRleCk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgYWRkRmlsdGVyKGluc2VydEluZGV4PzogbnVtYmVyKSB7XG4gICAgICAgIF8uZm9yRWFjaCh0aGlzLmRhdGFzZXRJbnN0YW5jZVN1bW1hcnkudHJhbnNmb3JtYXRpb25JbnN0YW5jZXMgfHwgW10sIHRyYW5zZm9ybWF0aW9uID0+IHtcbiAgICAgICAgICAgIHRyYW5zZm9ybWF0aW9uLmhpZGUgPSB0cnVlO1xuICAgICAgICB9KTtcblxuICAgICAgICBjb25zdCBmaWx0ZXJUcmFuc2Zvcm1hdGlvbiA9IHtcbiAgICAgICAgICAgIHR5cGU6ICdmaWx0ZXInLFxuICAgICAgICAgICAgY29uZmlnOiB7XG4gICAgICAgICAgICAgICAgbG9naWM6ICdBTkQnLFxuICAgICAgICAgICAgICAgIGZpbHRlcnM6IFt7XG4gICAgICAgICAgICAgICAgICAgIGxoc0V4cHJlc3Npb246ICcnLFxuICAgICAgICAgICAgICAgICAgICByaHNFeHByZXNzaW9uOiBbXSxcbiAgICAgICAgICAgICAgICAgICAgZmlsdGVyVHlwZTogJydcbiAgICAgICAgICAgICAgICB9XSxcbiAgICAgICAgICAgICAgICBmaWx0ZXJKdW5jdGlvbnM6IFtdXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgaGlkZTogZmFsc2VcbiAgICAgICAgfTtcblxuICAgICAgICBpZiAoIV8uaXNOaWwoaW5zZXJ0SW5kZXgpICYmIGluc2VydEluZGV4ID49IDApIHtcbiAgICAgICAgICAgIHRoaXMuZGF0YXNldEluc3RhbmNlU3VtbWFyeS50cmFuc2Zvcm1hdGlvbkluc3RhbmNlcy5zcGxpY2UoaW5zZXJ0SW5kZXgsIDAsIGZpbHRlclRyYW5zZm9ybWF0aW9uKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuZGF0YXNldEluc3RhbmNlU3VtbWFyeS50cmFuc2Zvcm1hdGlvbkluc3RhbmNlcy5wdXNoKGZpbHRlclRyYW5zZm9ybWF0aW9uKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuc2hvd0ZpbHRlcnMgPSB0cnVlO1xuICAgICAgICB0aGlzLnNldFRlcm1pbmF0aW5nVHJhbnNmb3JtYXRpb25zKCk7XG5cbiAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBmaWx0ZXJzID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2RhdGFzZXRGaWx0ZXJzJyk7XG4gICAgICAgICAgICBpZiAoZmlsdGVycykge1xuICAgICAgICAgICAgICAgIGZpbHRlcnMuc2Nyb2xsVG8oe3RvcDogZmlsdGVycy5zY3JvbGxIZWlnaHQsIGJlaGF2aW9yOiAnc21vb3RoJ30pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCAwKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0RmlsdGVyU3RyaW5nKGNvbmZpZykge1xuICAgICAgICBjb25zdCBmaWx0ZXIgPSBjb25maWcuZmlsdGVyc1swXTtcbiAgICAgICAgaWYgKGNvbmZpZy5maWx0ZXJzLmxlbmd0aCkge1xuICAgICAgICAgICAgaWYgKF8uZXZlcnkoZmlsdGVyKSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHR5cGUgPSBEYXRhc2V0RmlsdGVyQ29tcG9uZW50LmdldEZpbHRlclR5cGUoZmlsdGVyLmZpbHRlclR5cGUpO1xuICAgICAgICAgICAgICAgIGlmICh0eXBlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGxoc0V4cHJlc3Npb24gPSBmaWx0ZXIubGhzRXhwcmVzc2lvbi5yZXBsYWNlKCdbWycsICcnKS5yZXBsYWNlKCddXScsICcnKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGAke18uc3RhcnRDYXNlKGxoc0V4cHJlc3Npb24pfSAke3R5cGUuc3RyaW5nfSAke2ZpbHRlci5yaHNFeHByZXNzaW9ufWA7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiAnJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gJyc7XG4gICAgfVxuXG4gICAgcHVibGljIHJlbW92ZUZpbHRlcihpbmRleCkge1xuICAgICAgICBjb25zdCBleGlzdGluZ011bHRpU29ydCA9IF8uZmluZCh0aGlzLmRhdGFzZXRJbnN0YW5jZVN1bW1hcnkudHJhbnNmb3JtYXRpb25JbnN0YW5jZXMsIHt0eXBlOiAnbXVsdGlzb3J0J30pO1xuICAgICAgICBleGlzdGluZ011bHRpU29ydC5jb25maWcuc29ydHMuc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgICAgaWYgKCFleGlzdGluZ011bHRpU29ydC5jb25maWcuc29ydHMubGVuZ3RoKSB7XG4gICAgICAgICAgICBfLnJlbW92ZSh0aGlzLmRhdGFzZXRJbnN0YW5jZVN1bW1hcnkudHJhbnNmb3JtYXRpb25JbnN0YW5jZXMsIHt0eXBlOiAnbXVsdGlzb3J0J30pO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZXZhbHVhdGVEYXRhc2V0KCk7XG4gICAgfVxuXG4gICAgcHVibGljIHJlbW92ZVRyYW5zZm9ybWF0aW9uKHRyYW5zZm9ybWF0aW9uOiBhbnksIGNvbmZpcm0gPSBmYWxzZSwgaW5kZXg/OiBudW1iZXIsIGFjdGl2ZT86IGJvb2xlYW4pIHtcbiAgICAgICAgaWYgKGluZGV4ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGluZGV4ID0gXy5maW5kSW5kZXgodGhpcy5kYXRhc2V0SW5zdGFuY2VTdW1tYXJ5LnRyYW5zZm9ybWF0aW9uSW5zdGFuY2VzLCB7XG4gICAgICAgICAgICAgICAgdHlwZTogdHJhbnNmb3JtYXRpb24udHlwZSxcbiAgICAgICAgICAgICAgICBjb25maWc6IHRyYW5zZm9ybWF0aW9uLmNvbmZpZ1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuXG4gICAgICAgIGlmICghYWN0aXZlKSB7XG4gICAgICAgICAgICBjb25zdCBkaWFsb2dSZWYgPSB0aGlzLmRpYWxvZy5vcGVuKFJlbW92ZVRyYW5zZm9ybWF0aW9uV2FybmluZ0NvbXBvbmVudCwge1xuICAgICAgICAgICAgICAgIHdpZHRoOiAnNzAwcHgnLFxuICAgICAgICAgICAgICAgIGhlaWdodDogJzI3NXB4J1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBkaWFsb2dSZWYuYWZ0ZXJDbG9zZWQoKS5zdWJzY3JpYmUocHJvY2VlZCA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKHByb2NlZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fcmVtb3ZlVHJhbnNmb3JtYXRpb24odHJhbnNmb3JtYXRpb24sIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmIChjb25maXJtKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgbWVzc2FnZSA9ICdBcmUgeW91IHN1cmUgeW91IHdvdWxkIGxpa2UgdG8gcmVtb3ZlIHRoaXMgdHJhbnNmb3JtYXRpb24/JztcbiAgICAgICAgICAgICAgICBpZiAod2luZG93LmNvbmZpcm0obWVzc2FnZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fcmVtb3ZlVHJhbnNmb3JtYXRpb24odHJhbnNmb3JtYXRpb24sIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuX3JlbW92ZVRyYW5zZm9ybWF0aW9uKHRyYW5zZm9ybWF0aW9uLCBpbmRleCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgIH1cblxuICAgIHB1YmxpYyBlbmFibGVBbGxUcmFuc2Zvcm1hdGlvbigpIHtcbiAgICAgICAgdGhpcy5kYXRhc2V0SW5zdGFuY2VTdW1tYXJ5LnRyYW5zZm9ybWF0aW9uSW5zdGFuY2VzLmZvckVhY2goKHRyYW5zZm9ybWF0aW9uOiBhbnkpID0+IHtcbiAgICAgICAgICAgIHRyYW5zZm9ybWF0aW9uLmV4Y2x1ZGUgPSBmYWxzZTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuZXZhbHVhdGVEYXRhc2V0KCk7XG4gICAgfVxuXG4gICAgcHVibGljIGRpc2FibGVUcmFuc2Zvcm1hdGlvbih0cmFuc2Zvcm1hdGlvbiwgaW5kZXgpIHtcbiAgICAgICAgdHJhbnNmb3JtYXRpb24uZXhjbHVkZSA9ICF0cmFuc2Zvcm1hdGlvbi5leGNsdWRlO1xuICAgICAgICB0aGlzLmV2YWx1YXRlRGF0YXNldCgpO1xuICAgIH1cblxuICAgIHB1YmxpYyBzaG93VHJhbnNmb3JtYXRpb25EZXRhaWwodHJhbnNmb3JtYXRpb24pIHtcbiAgICAgICAgY29uc3QgY2xvbmUgPSBfLmNsb25lKHRyYW5zZm9ybWF0aW9uKTtcbiAgICAgICAgdGhpcy50ZXJtaW5hdGluZ1RyYW5zZm9ybWF0aW9ucy5mb3JFYWNoKGl0ZW0gPT4ge1xuICAgICAgICAgICAgaXRlbS5fc2hvd0RldGFpbCA9IGZhbHNlO1xuICAgICAgICB9KTtcbiAgICAgICAgaWYgKCFjbG9uZS5fc2hvd0RldGFpbCkge1xuICAgICAgICAgICAgdHJhbnNmb3JtYXRpb24uX3Nob3dEZXRhaWwgPSB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIGVkaXRUZXJtaW5hdGluZ1RyYW5zZm9ybWF0aW9uKHRyYW5zZm9ybWF0aW9uKSB7XG4gICAgICAgIGNvbnN0IFtjbG9uZWRUcmFuc2Zvcm1hdGlvbiwgZXhpc3RpbmdJbmRleF0gPSBhd2FpdCB0aGlzLmV4Y2x1ZGVVcHN0cmVhbVRyYW5zZm9ybWF0aW9ucyh0cmFuc2Zvcm1hdGlvbik7XG4gICAgICAgIGlmICh0cmFuc2Zvcm1hdGlvbi50eXBlID09PSAnZmlsdGVyJykge1xuICAgICAgICAgICAgY29uc3QgaGlkZGVuVmFsdWUgPSAhdHJhbnNmb3JtYXRpb24uaGlkZTtcbiAgICAgICAgICAgIGNvbnN0IGZpbHRlcnMgPSBfLmZpbHRlcih0aGlzLmRhdGFzZXRJbnN0YW5jZVN1bW1hcnkudHJhbnNmb3JtYXRpb25JbnN0YW5jZXMsIHt0eXBlOiAnZmlsdGVyJ30pO1xuICAgICAgICAgICAgZmlsdGVycy5mb3JFYWNoKGZpbHRlciA9PiB7XG4gICAgICAgICAgICAgICAgZmlsdGVyLmhpZGUgPSB0cnVlO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0cmFuc2Zvcm1hdGlvbi5oaWRlID0gaGlkZGVuVmFsdWU7XG4gICAgICAgICAgICB0aGlzLnNob3dGaWx0ZXJzID0gIWhpZGRlblZhbHVlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKHRyYW5zZm9ybWF0aW9uLnR5cGUgPT09ICdzdW1tYXJpc2UnKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zdW1tYXJpc2VEYXRhKGNsb25lZFRyYW5zZm9ybWF0aW9uLmNvbmZpZywgZXhpc3RpbmdJbmRleCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodHJhbnNmb3JtYXRpb24udHlwZSA9PT0gJ2pvaW4nKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5qb2luRGF0YShjbG9uZWRUcmFuc2Zvcm1hdGlvbiwgZXhpc3RpbmdJbmRleCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodHJhbnNmb3JtYXRpb24udHlwZSA9PT0gJ2Zvcm11bGEnKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jcmVhdGVGb3JtdWxhKGNsb25lZFRyYW5zZm9ybWF0aW9uLCBleGlzdGluZ0luZGV4KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0cmFuc2Zvcm1hdGlvbi50eXBlID09PSAnY29sdW1ucycpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmVkaXRDb2x1bW5TZXR0aW5ncyhjbG9uZWRUcmFuc2Zvcm1hdGlvbiwgZXhpc3RpbmdJbmRleCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgZXhwb3J0RGF0YSgpIHtcblxuICAgIH1cblxuICAgIHB1YmxpYyBhc3luYyBlZGl0Q29sdW1uU2V0dGluZ3MoZXhpc3RpbmdUcmFuc2Zvcm1hdGlvbj86IGFueSwgZXhpc3RpbmdJbmRleD86IG51bWJlciwgaW5zZXJ0SW5kZXg/OiBudW1iZXIpIHtcbiAgICAgICAgY29uc3QgY2xvbmVkQ29sdW1ucyA9IGV4aXN0aW5nVHJhbnNmb3JtYXRpb24gPyBfLmNsb25lKGV4aXN0aW5nVHJhbnNmb3JtYXRpb24uY29uZmlnLmNvbHVtbnMpIDogbnVsbDtcbiAgICAgICAgY29uc3QgcmVzZXRDb2x1bW5OYW1lcyA9IGV4aXN0aW5nVHJhbnNmb3JtYXRpb24gPyBleGlzdGluZ1RyYW5zZm9ybWF0aW9uLmNvbmZpZy5yZXNldENvbHVtbk5hbWVzIDogdHJ1ZTtcbiAgICAgICAgY29uc3QgbmFtaW5nQ29udmVudGlvbiA9IGV4aXN0aW5nVHJhbnNmb3JtYXRpb24gPyBleGlzdGluZ1RyYW5zZm9ybWF0aW9uLmNvbmZpZy5uYW1pbmdDb252ZW50aW9uIDogXCJDQU1FTFwiO1xuXG5cbiAgICAgICAgY29uc3QgY29sdW1uU2V0dGluZ3MgPSBbXTtcblxuICAgICAgICBpZiAoY2xvbmVkQ29sdW1ucykge1xuICAgICAgICAgICAgY2xvbmVkQ29sdW1ucy5mb3JFYWNoKGNvbHVtbiA9PiB7XG4gICAgICAgICAgICAgICAgY29sdW1uLnNlbGVjdGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBjb2x1bW5TZXR0aW5ncy5wdXNoKGNvbHVtbik7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuZmlsdGVyRmllbGRzLmZvckVhY2goZmllbGQgPT4ge1xuICAgICAgICAgICAgaWYgKCFfLmZpbmQoY29sdW1uU2V0dGluZ3MsIHtuYW1lOiBmaWVsZC5uYW1lfSkpIHtcbiAgICAgICAgICAgICAgICBjb2x1bW5TZXR0aW5ncy5wdXNoKGZpZWxkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgY29uc3QgZGlhbG9nUmVmID0gdGhpcy5kaWFsb2cub3BlbihEYXRhc2V0Q29sdW1uU2V0dGluZ3NDb21wb25lbnQsIHtcbiAgICAgICAgICAgIHdpZHRoOiAnMTAwMHB4JyxcbiAgICAgICAgICAgIGhlaWdodDogJzgwMHB4JyxcbiAgICAgICAgICAgIGRpc2FibGVDbG9zZTogdHJ1ZSxcbiAgICAgICAgICAgIGRhdGE6IHtcbiAgICAgICAgICAgICAgICBjb2x1bW5zOiBjb2x1bW5TZXR0aW5ncyxcbiAgICAgICAgICAgICAgICByZXNldDogISFfLmZpbmQodGhpcy5kYXRhc2V0SW5zdGFuY2VTdW1tYXJ5LnRyYW5zZm9ybWF0aW9uSW5zdGFuY2VzLCB7dHlwZTogJ2NvbHVtbnMnfSksXG4gICAgICAgICAgICAgICAgcmVzZXRGaWVsZHM6IF8uY2xvbmUodGhpcy5maWx0ZXJGaWVsZHMpLFxuICAgICAgICAgICAgICAgIHJlc2V0Q29sdW1uTmFtZXMsXG4gICAgICAgICAgICAgICAgbmFtaW5nQ29udmVudGlvblxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICBkaWFsb2dSZWYuYWZ0ZXJDbG9zZWQoKS5zdWJzY3JpYmUocmVzdWx0ID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGNvbHVtbnMgPSByZXN1bHQuY29sdW1ucztcbiAgICAgICAgICAgIGlmIChjb2x1bW5zKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZmllbGRzID0gXy5tYXAoY29sdW1ucywgY29sdW1uID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHt0aXRsZTogY29sdW1uLnRpdGxlLCBuYW1lOiBjb2x1bW4ubmFtZX07XG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICBjb25zdCBjb2x1bW5UcmFuc2Zvcm1hdGlvbiA9IHtcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogJ2NvbHVtbnMnLFxuICAgICAgICAgICAgICAgICAgICBjb25maWc6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbHVtbnM6IGZpZWxkcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc2V0Q29sdW1uTmFtZXM6IHJlc3VsdC5yZXNldENvbHVtbk5hbWVzLFxuICAgICAgICAgICAgICAgICAgICAgICAgbmFtaW5nQ29udmVudGlvbjogcmVzdWx0Lm5hbWluZ0NvbnZlbnRpb25cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICBpZiAoIV8uaXNOaWwoZXhpc3RpbmdJbmRleCkgJiYgZXhpc3RpbmdJbmRleCA+IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0YXNldEluc3RhbmNlU3VtbWFyeS50cmFuc2Zvcm1hdGlvbkluc3RhbmNlc1tleGlzdGluZ0luZGV4XSA9IGNvbHVtblRyYW5zZm9ybWF0aW9uO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIV8uaXNOaWwoaW5zZXJ0SW5kZXgpICYmIGluc2VydEluZGV4ID49IDApIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRhc2V0SW5zdGFuY2VTdW1tYXJ5LnRyYW5zZm9ybWF0aW9uSW5zdGFuY2VzLnNwbGljZShpbnNlcnRJbmRleCwgMCwgY29sdW1uVHJhbnNmb3JtYXRpb24pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0YXNldEluc3RhbmNlU3VtbWFyeS50cmFuc2Zvcm1hdGlvbkluc3RhbmNlcy5wdXNoKGNvbHVtblRyYW5zZm9ybWF0aW9uKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLmV2YWx1YXRlRGF0YXNldCgpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAoY2xvbmVkQ29sdW1ucykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGFzZXRJbnN0YW5jZVN1bW1hcnkudHJhbnNmb3JtYXRpb25JbnN0YW5jZXNbZXhpc3RpbmdJbmRleF0gPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAnY29sdW1ucycsXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25maWc6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2x1bW5zOiBjbG9uZWRDb2x1bW5zXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0YXNldEluc3RhbmNlU3VtbWFyeS50cmFuc2Zvcm1hdGlvbkluc3RhbmNlcy5mb3JFYWNoKChpbnN0YW5jZSwgaW5kZXgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluc3RhbmNlLmV4Y2x1ZGUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZXZhbHVhdGVEYXRhc2V0KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgY3JlYXRlRm9ybXVsYShleGlzdGluZ1RyYW5zZm9ybWF0aW9uPzogYW55LCBleGlzdGluZ0luZGV4PzogbnVtYmVyLCBpbnNlcnRJbmRleD86IG51bWJlcikge1xuICAgICAgICBjb25zdCBjbG9uZWRFeHByZXNzaW9ucyA9IGV4aXN0aW5nVHJhbnNmb3JtYXRpb24gPyBfLmNsb25lKGV4aXN0aW5nVHJhbnNmb3JtYXRpb24uY29uZmlnLmV4cHJlc3Npb25zKSA6IG51bGw7XG4gICAgICAgIGNvbnN0IGRpYWxvZ1JlZiA9IHRoaXMuZGlhbG9nLm9wZW4oRGF0YXNldENyZWF0ZUZvcm11bGFDb21wb25lbnQsIHtcbiAgICAgICAgICAgIHdpZHRoOiAnOTAwcHgnLFxuICAgICAgICAgICAgaGVpZ2h0OiAnODAwcHgnLFxuICAgICAgICAgICAgZGlzYWJsZUNsb3NlOiB0cnVlLFxuICAgICAgICAgICAgZGF0YToge1xuICAgICAgICAgICAgICAgIGFsbENvbHVtbnM6IHRoaXMuZmlsdGVyRmllbGRzLFxuICAgICAgICAgICAgICAgIGZvcm11bGFzOiBleGlzdGluZ1RyYW5zZm9ybWF0aW9uID8gZXhpc3RpbmdUcmFuc2Zvcm1hdGlvbi5jb25maWcuZXhwcmVzc2lvbnMgOiBbe31dXG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGRpYWxvZ1JlZi5hZnRlckNsb3NlZCgpLnN1YnNjcmliZShmb3JtdWxhID0+IHtcbiAgICAgICAgICAgIGlmIChmb3JtdWxhKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZm9ybXVsYVRyYW5zZm9ybWF0aW9uID0ge1xuICAgICAgICAgICAgICAgICAgICB0eXBlOiAnZm9ybXVsYScsXG4gICAgICAgICAgICAgICAgICAgIGNvbmZpZzoge1xuICAgICAgICAgICAgICAgICAgICAgICAgZXhwcmVzc2lvbnM6IGZvcm11bGFcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICBpZiAoIV8uaXNOaWwoZXhpc3RpbmdJbmRleCkgJiYgZXhpc3RpbmdJbmRleCA+PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0YXNldEluc3RhbmNlU3VtbWFyeS50cmFuc2Zvcm1hdGlvbkluc3RhbmNlc1tleGlzdGluZ0luZGV4XSA9IGZvcm11bGFUcmFuc2Zvcm1hdGlvbjtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFfLmlzTmlsKGluc2VydEluZGV4KSAmJiBpbnNlcnRJbmRleCA+PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0YXNldEluc3RhbmNlU3VtbWFyeS50cmFuc2Zvcm1hdGlvbkluc3RhbmNlcy5zcGxpY2UoaW5zZXJ0SW5kZXgsIDAsIGZvcm11bGFUcmFuc2Zvcm1hdGlvbik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRhc2V0SW5zdGFuY2VTdW1tYXJ5LnRyYW5zZm9ybWF0aW9uSW5zdGFuY2VzLnB1c2goZm9ybXVsYVRyYW5zZm9ybWF0aW9uKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLmV2YWx1YXRlRGF0YXNldCgpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBGb3JtdWxhIHdhcyBjYW5jZWxsZWQsIHJlc3RvcmUgaWYgd2UgaGF2ZSBvbmVcbiAgICAgICAgICAgICAgICBpZiAoY2xvbmVkRXhwcmVzc2lvbnMpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRhc2V0SW5zdGFuY2VTdW1tYXJ5LnRyYW5zZm9ybWF0aW9uSW5zdGFuY2VzW2V4aXN0aW5nSW5kZXhdID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ2Zvcm11bGEnLFxuICAgICAgICAgICAgICAgICAgICAgICAgY29uZmlnOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhwcmVzc2lvbnM6IGNsb25lZEV4cHJlc3Npb25zXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0YXNldEluc3RhbmNlU3VtbWFyeS50cmFuc2Zvcm1hdGlvbkluc3RhbmNlcy5mb3JFYWNoKChpbnN0YW5jZSwgaW5kZXgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluc3RhbmNlLmV4Y2x1ZGUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZXZhbHVhdGVEYXRhc2V0KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgam9pbkRhdGEodHJhbnNmb3JtYXRpb24/OiBhbnksIGV4aXN0aW5nSW5kZXg/OiBudW1iZXIsIGluc2VydEluZGV4PzogbnVtYmVyKSB7XG4gICAgICAgIGNvbnN0IGNsb25lZFRyYW5zZm9ybWF0aW9uID0gdHJhbnNmb3JtYXRpb24gPyBfLmNsb25lKHRyYW5zZm9ybWF0aW9uKSA6IG51bGw7XG4gICAgICAgIGNvbnN0IGRhdGE6IGFueSA9IHtcbiAgICAgICAgICAgIGFkbWluOiB0aGlzLmFkbWluLFxuICAgICAgICAgICAgZW52aXJvbm1lbnQ6IHRoaXMuZW52aXJvbm1lbnQsXG4gICAgICAgICAgICBmaWx0ZXJGaWVsZHM6IHRoaXMuZmlsdGVyRmllbGRzLFxuICAgICAgICAgICAgcGFyYW1ldGVyVmFsdWVzOiBfLm1hcCh0aGlzLnBhcmFtZXRlclZhbHVlcywgcGFyYW0gPT4ge1xuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIHRpdGxlOiBwYXJhbS50aXRsZSxcbiAgICAgICAgICAgICAgICAgICAgbmFtZTogcGFyYW0ubmFtZSxcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudFZhbHVlOiB0aGlzLmRhdGFzZXRJbnN0YW5jZVN1bW1hcnkucGFyYW1ldGVyVmFsdWVzW3BhcmFtLm5hbWVdXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgZGF0YXNldEVkaXRvcjogdGhpcyxcbiAgICAgICAgfTtcbiAgICAgICAgaWYgKHRyYW5zZm9ybWF0aW9uKSB7XG4gICAgICAgICAgICBkYXRhLmpvaW5UcmFuc2Zvcm1hdGlvbiA9IHtcbiAgICAgICAgICAgICAgICB0eXBlOiAnam9pbicsXG4gICAgICAgICAgICAgICAgY29uZmlnOiB0cmFuc2Zvcm1hdGlvbi5jb25maWdcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBkaWFsb2dSZWYgPSB0aGlzLmRpYWxvZy5vcGVuKERhdGFzZXRBZGRKb2luQ29tcG9uZW50LCB7XG4gICAgICAgICAgICB3aWR0aDogJzEyMDBweCcsXG4gICAgICAgICAgICBoZWlnaHQ6ICc4MDBweCcsXG4gICAgICAgICAgICBkaXNhYmxlQ2xvc2U6IHRydWUsXG4gICAgICAgICAgICBkYXRhLFxuICAgICAgICB9KTtcblxuICAgICAgICBkaWFsb2dSZWYuYWZ0ZXJDbG9zZWQoKS5zdWJzY3JpYmUoam9pblRyYW5zZm9ybWF0aW9uID0+IHtcbiAgICAgICAgICAgIGlmIChqb2luVHJhbnNmb3JtYXRpb24pIHtcbiAgICAgICAgICAgICAgICBpZiAoIV8uaXNOaWwoZXhpc3RpbmdJbmRleCkgJiYgZXhpc3RpbmdJbmRleCA+PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0YXNldEluc3RhbmNlU3VtbWFyeS50cmFuc2Zvcm1hdGlvbkluc3RhbmNlc1tleGlzdGluZ0luZGV4XSA9IGpvaW5UcmFuc2Zvcm1hdGlvbjtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFfLmlzTmlsKGluc2VydEluZGV4KSAmJiBpbnNlcnRJbmRleCA+PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0YXNldEluc3RhbmNlU3VtbWFyeS50cmFuc2Zvcm1hdGlvbkluc3RhbmNlcy5zcGxpY2UoaW5zZXJ0SW5kZXgsIDAsIGpvaW5UcmFuc2Zvcm1hdGlvbik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRhc2V0SW5zdGFuY2VTdW1tYXJ5LnRyYW5zZm9ybWF0aW9uSW5zdGFuY2VzLnB1c2goam9pblRyYW5zZm9ybWF0aW9uKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5ldmFsdWF0ZURhdGFzZXQodHJ1ZSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmIChjbG9uZWRUcmFuc2Zvcm1hdGlvbikge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGFzZXRJbnN0YW5jZVN1bW1hcnkudHJhbnNmb3JtYXRpb25JbnN0YW5jZXNbZXhpc3RpbmdJbmRleF0gPSBjbG9uZWRUcmFuc2Zvcm1hdGlvbjtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRhc2V0SW5zdGFuY2VTdW1tYXJ5LnRyYW5zZm9ybWF0aW9uSW5zdGFuY2VzLmZvckVhY2goKGluc3RhbmNlLCBpbmRleCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5zdGFuY2UuZXhjbHVkZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5ldmFsdWF0ZURhdGFzZXQoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHB1YmxpYyBhcHBseUZpbHRlcnMoKSB7XG4gICAgICAgIGNvbnN0IGZpbHRlclRyYW5zZm9ybWF0aW9ucyA9IF8uZmlsdGVyKHRoaXMuZGF0YXNldEluc3RhbmNlU3VtbWFyeS50cmFuc2Zvcm1hdGlvbkluc3RhbmNlcywge3R5cGU6ICdmaWx0ZXInfSk7XG4gICAgICAgIGZpbHRlclRyYW5zZm9ybWF0aW9ucy5mb3JFYWNoKHRyYW5zZm9ybWF0aW9uID0+IHtcbiAgICAgICAgICAgIHRoaXMudmFsaWRhdGVGaWx0ZXJKdW5jdGlvbih0cmFuc2Zvcm1hdGlvbi5jb25maWcpO1xuICAgICAgICB9KTtcblxuICAgICAgICB0aGlzLmV2YWx1YXRlRGF0YXNldCh0cnVlKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgaW5jcmVhc2VPZmZzZXQoKSB7XG4gICAgICAgIHRoaXMucGFnZSA9IHRoaXMucGFnZSArIDE7XG4gICAgICAgIHRoaXMub2Zmc2V0ID0gKHRoaXMubGltaXQgKiB0aGlzLnBhZ2UpIC0gdGhpcy5saW1pdDtcbiAgICAgICAgdGhpcy5ldmFsdWF0ZURhdGFzZXQoKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZGVjcmVhc2VPZmZzZXQoKSB7XG4gICAgICAgIHRoaXMucGFnZSA9IHRoaXMucGFnZSA8PSAxID8gMSA6IHRoaXMucGFnZSAtIDE7XG4gICAgICAgIHRoaXMub2Zmc2V0ID0gKHRoaXMubGltaXQgKiB0aGlzLnBhZ2UpIC0gdGhpcy5saW1pdDtcbiAgICAgICAgdGhpcy5ldmFsdWF0ZURhdGFzZXQoKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgcGFnZVNpemVDaGFuZ2UodmFsdWUpIHtcbiAgICAgICAgdGhpcy5saW1pdCA9IHZhbHVlO1xuICAgICAgICBsb2NhbFN0b3JhZ2Uuc2V0SXRlbSgnZGF0YXNldEluc3RhbmNlTGltaXQnICsgdGhpcy5kYXRhc2V0SW5zdGFuY2VTdW1tYXJ5LmlkLCB0aGlzLmxpbWl0LnRvU3RyaW5nKCkpO1xuICAgICAgICB0aGlzLmV2YWx1YXRlRGF0YXNldCh0cnVlKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgYWRkUGFnaW5nTWFya2VyKCkge1xuICAgICAgICB0aGlzLmRhdGFzZXRJbnN0YW5jZVN1bW1hcnkudHJhbnNmb3JtYXRpb25JbnN0YW5jZXMucHVzaCh7dHlwZTogJ3BhZ2luZ21hcmtlcid9KTtcbiAgICAgICAgdGhpcy5ldmFsdWF0ZURhdGFzZXQoKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgc29ydChldmVudCkge1xuICAgICAgICBjb25zdCBjb2x1bW4gPSBldmVudC5hY3RpdmU7XG4gICAgICAgIGNvbnN0IGRpcmVjdGlvbiA9IGV2ZW50LmRpcmVjdGlvbjtcblxuICAgICAgICBjb25zdCBleGlzdGluZ011bHRpU29ydCA9IF8uZmluZCh0aGlzLmRhdGFzZXRJbnN0YW5jZVN1bW1hcnkudHJhbnNmb3JtYXRpb25JbnN0YW5jZXMsIHt0eXBlOiAnbXVsdGlzb3J0J30pO1xuICAgICAgICBpZiAoZXhpc3RpbmdNdWx0aVNvcnQpIHtcbiAgICAgICAgICAgIGNvbnN0IGV4aXN0aW5nSW5kZXggPSBfLmZpbmRJbmRleChleGlzdGluZ011bHRpU29ydC5jb25maWcuc29ydHMsIHtmaWVsZE5hbWU6IGNvbHVtbn0pO1xuICAgICAgICAgICAgaWYgKGRpcmVjdGlvbikge1xuICAgICAgICAgICAgICAgIGlmIChleGlzdGluZ0luZGV4ID4gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgZXhpc3RpbmdNdWx0aVNvcnQuY29uZmlnLnNvcnRzW2V4aXN0aW5nSW5kZXhdID0ge2ZpZWxkTmFtZTogY29sdW1uLCBkaXJlY3Rpb259O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGV4aXN0aW5nTXVsdGlTb3J0LmNvbmZpZy5zb3J0cy5wdXNoKHtmaWVsZE5hbWU6IGNvbHVtbiwgZGlyZWN0aW9ufSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBleGlzdGluZ011bHRpU29ydC5jb25maWcuc29ydHMuc3BsaWNlKGV4aXN0aW5nSW5kZXgsIDEpO1xuICAgICAgICAgICAgICAgIGlmICghZXhpc3RpbmdNdWx0aVNvcnQuY29uZmlnLnNvcnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICBfLnJlbW92ZSh0aGlzLmRhdGFzZXRJbnN0YW5jZVN1bW1hcnkudHJhbnNmb3JtYXRpb25JbnN0YW5jZXMsIHt0eXBlOiAnbXVsdGlzb3J0J30pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmIChkaXJlY3Rpb24pIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRhdGFzZXRJbnN0YW5jZVN1bW1hcnkudHJhbnNmb3JtYXRpb25JbnN0YW5jZXMucHVzaChcbiAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ211bHRpc29ydCcsXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25maWc6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzb3J0czogW3tmaWVsZE5hbWU6IGNvbHVtbiwgZGlyZWN0aW9ufV1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5ldmFsdWF0ZURhdGFzZXQodHJ1ZSk7XG4gICAgfVxuXG4gICAgcHVibGljIHN1bW1hcmlzZURhdGEoY29uZmlnPzogYW55LCBleGlzdGluZ0luZGV4PzogbnVtYmVyLCBpbnNlcnRJbmRleD86IG51bWJlcikge1xuICAgICAgICBjb25zdCBjbG9uZWRDb25maWcgPSBjb25maWcgPyBfLmNsb25lKGNvbmZpZykgOiBudWxsO1xuICAgICAgICBjb25zdCBzdW1tYXJpc2VEaWFsb2cgPSB0aGlzLmRpYWxvZy5vcGVuKERhdGFzZXRTdW1tYXJpc2VDb21wb25lbnQsIHtcbiAgICAgICAgICAgIHdpZHRoOiAnMTEwMHB4JyxcbiAgICAgICAgICAgIGhlaWdodDogJzkwMHB4JyxcbiAgICAgICAgICAgIGRpc2FibGVDbG9zZTogdHJ1ZSxcbiAgICAgICAgICAgIGRhdGE6IHtcbiAgICAgICAgICAgICAgICBhdmFpbGFibGVDb2x1bW5zOiB0aGlzLmZpbHRlckZpZWxkcyxcbiAgICAgICAgICAgICAgICBjb25maWc6IGNvbmZpZyA/IGNvbmZpZyA6IG51bGwsXG4gICAgICAgICAgICAgICAgb3JpZ2luRGF0YUl0ZW1UaXRsZTogdGhpcy5kYXRhc2V0SW5zdGFuY2VTdW1tYXJ5Lm9yaWdpbkRhdGFJdGVtVGl0bGVcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgc3VtbWFyaXNlRGlhbG9nLmFmdGVyQ2xvc2VkKCkuc3Vic2NyaWJlKHN1bW1hcmlzZVRyYW5zZm9ybWF0aW9uID0+IHtcbiAgICAgICAgICAgIGlmIChzdW1tYXJpc2VUcmFuc2Zvcm1hdGlvbikge1xuICAgICAgICAgICAgICAgIC8vIHRoaXMuZGF0YXNldEluc3RhbmNlU3VtbWFyeS50cmFuc2Zvcm1hdGlvbkluc3RhbmNlcy5mb3JFYWNoKChpbnN0YW5jZSwgaW5kZXgpID0+IHtcbiAgICAgICAgICAgICAgICAvLyAgICAgaW5zdGFuY2UuZXhjbHVkZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIC8vIH0pO1xuICAgICAgICAgICAgICAgIGlmICghXy5pc05pbChleGlzdGluZ0luZGV4KSAmJiBleGlzdGluZ0luZGV4ID49IDApIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gQ2hlY2sgaWYgYW55dGhpbmcgaGFzIGNoYW5nZWRcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFfLmlzRXF1YWwoY2xvbmVkQ29uZmlnLCBzdW1tYXJpc2VUcmFuc2Zvcm1hdGlvbikgJiYgKGV4aXN0aW5nSW5kZXggKyAxKSA8IHRoaXMuZGF0YXNldEluc3RhbmNlU3VtbWFyeS50cmFuc2Zvcm1hdGlvbkluc3RhbmNlcy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoaW5ncyBoYXZlIGNoYW5nZWQsIGFzayB1c2VyIHRvIGNvbmZpcm1cblxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kaWFsb2cub3BlbihVcHN0cmVhbUNoYW5nZXNDb25maXJtYXRpb25Db21wb25lbnQsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWR0aDogJzcwMHB4JyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoZWlnaHQ6ICcyNzVweCdcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pLmFmdGVyQ2xvc2VkKCkuc3Vic2NyaWJlKHJlcyA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJlcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVzID09PSAncmVtb3ZlJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IGV4aXN0aW5nSW5kZXg7IGkgPCB0aGlzLmRhdGFzZXRJbnN0YW5jZVN1bW1hcnkudHJhbnNmb3JtYXRpb25JbnN0YW5jZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGFzZXRJbnN0YW5jZVN1bW1hcnkudHJhbnNmb3JtYXRpb25JbnN0YW5jZXMuc3BsaWNlKGksIDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRhc2V0SW5zdGFuY2VTdW1tYXJ5LnRyYW5zZm9ybWF0aW9uSW5zdGFuY2VzW2V4aXN0aW5nSW5kZXhdID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ3N1bW1hcmlzZScsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25maWc6IHN1bW1hcmlzZVRyYW5zZm9ybWF0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZXZhbHVhdGVEYXRhc2V0KHRydWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRhc2V0SW5zdGFuY2VTdW1tYXJ5LnRyYW5zZm9ybWF0aW9uSW5zdGFuY2VzW2V4aXN0aW5nSW5kZXhdID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6ICdzdW1tYXJpc2UnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbmZpZzogc3VtbWFyaXNlVHJhbnNmb3JtYXRpb25cbiAgICAgICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmV2YWx1YXRlRGF0YXNldCh0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIV8uaXNOaWwoaW5zZXJ0SW5kZXgpICYmIGluc2VydEluZGV4ID49IDApIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRhc2V0SW5zdGFuY2VTdW1tYXJ5LnRyYW5zZm9ybWF0aW9uSW5zdGFuY2VzLnNwbGljZShpbnNlcnRJbmRleCwgMCwge1xuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ3N1bW1hcmlzZScsXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25maWc6IHN1bW1hcmlzZVRyYW5zZm9ybWF0aW9uXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmV2YWx1YXRlRGF0YXNldCh0cnVlKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGFzZXRJbnN0YW5jZVN1bW1hcnkudHJhbnNmb3JtYXRpb25JbnN0YW5jZXMucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAnc3VtbWFyaXNlJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbmZpZzogc3VtbWFyaXNlVHJhbnNmb3JtYXRpb25cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZXZhbHVhdGVEYXRhc2V0KHRydWUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gSWYgd2UgZ2V0IGhlcmUgdGhlbiB0aGUgc3VtbWFyaXNlIHRyYW5zZm9ybWF0aW9uIHdhcyBjYW5jZWxsZWQgLSByZXN0b3JlIGlmIHdlIGhhdmUgb25lXG4gICAgICAgICAgICAgICAgaWYgKGNsb25lZENvbmZpZykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGFzZXRJbnN0YW5jZVN1bW1hcnkudHJhbnNmb3JtYXRpb25JbnN0YW5jZXNbZXhpc3RpbmdJbmRleF0gPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAnc3VtbWFyaXNlJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbmZpZzogY2xvbmVkQ29uZmlnXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0YXNldEluc3RhbmNlU3VtbWFyeS50cmFuc2Zvcm1hdGlvbkluc3RhbmNlcy5mb3JFYWNoKChpbnN0YW5jZSwgaW5kZXgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluc3RhbmNlLmV4Y2x1ZGUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZXZhbHVhdGVEYXRhc2V0KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgcmVtb3ZlUGFyYW1ldGVyKHBhcmFtZXRlcikge1xuICAgICAgICBjb25zdCBtZXNzYWdlID0gJ0FyZSB5b3Ugc3VyZSB5b3Ugd291bGQgbGlrZSB0byByZW1vdmUgdGhpcyBwYXJhbWV0ZXIuIFRoaXMgbWF5IGNhdXNlIHNvbWUgZGFzaGJvYXJkIGl0ZW1zICcgK1xuICAgICAgICAgICAgJ3RvIGZhaWwuJztcbiAgICAgICAgaWYgKHdpbmRvdy5jb25maXJtKG1lc3NhZ2UpKSB7XG4gICAgICAgICAgICBfLnJlbW92ZSh0aGlzLnBhcmFtZXRlclZhbHVlcywge25hbWU6IHBhcmFtZXRlci5uYW1lfSk7XG4gICAgICAgICAgICBfLnJlbW92ZSh0aGlzLmRhdGFzZXRJbnN0YW5jZVN1bW1hcnkucGFyYW1ldGVycywge25hbWU6IHBhcmFtZXRlci5uYW1lfSk7XG4gICAgICAgICAgICB0aGlzLmV2YWx1YXRlRGF0YXNldCgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHVibGljIGFkZFBhcmFtZXRlcihleGlzdGluZ1BhcmFtZXRlcj8sIHBhcmFtZXRlclZhbHVlSW5kZXg/KSB7XG4gICAgICAgIGxldCBjbG9uZWRQYXJhbWV0ZXIgPSBudWxsO1xuICAgICAgICBpZiAoZXhpc3RpbmdQYXJhbWV0ZXIpIHtcbiAgICAgICAgICAgIGNsb25lZFBhcmFtZXRlciA9IF8uY2xvbmUoZXhpc3RpbmdQYXJhbWV0ZXIpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghdGhpcy5zaG93UGFyYW1ldGVycykge1xuICAgICAgICAgICAgdGhpcy5zaG93UGFyYW1ldGVycyA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgZGlhbG9nUmVmID0gdGhpcy5kaWFsb2cub3BlbihEYXRhc2V0QWRkUGFyYW1ldGVyQ29tcG9uZW50LCB7XG4gICAgICAgICAgICB3aWR0aDogJzc1MHB4JyxcbiAgICAgICAgICAgIGhlaWdodDogJzg1MHB4JyxcbiAgICAgICAgICAgIGRpc2FibGVDbG9zZTogdHJ1ZSxcbiAgICAgICAgICAgIGRhdGE6IHtcbiAgICAgICAgICAgICAgICBwYXJhbWV0ZXI6IGNsb25lZFBhcmFtZXRlclxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgZGlhbG9nUmVmLmFmdGVyQ2xvc2VkKCkuc3Vic2NyaWJlKHBhcmFtZXRlciA9PiB7XG4gICAgICAgICAgICBpZiAocGFyYW1ldGVyKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFjbG9uZWRQYXJhbWV0ZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHBhcmFtZXRlci5kZWZhdWx0VmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhcmFtZXRlci52YWx1ZSA9IHBhcmFtZXRlci5kZWZhdWx0VmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB0aGlzLnBhcmFtZXRlclZhbHVlcy5wdXNoKHBhcmFtZXRlcik7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0YXNldEluc3RhbmNlU3VtbWFyeS5wYXJhbWV0ZXJzLnB1c2gocGFyYW1ldGVyKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWNsb25lZFBhcmFtZXRlci52YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGFyYW1ldGVyLnZhbHVlID0gcGFyYW1ldGVyLmRlZmF1bHRWYWx1ZSB8fCAnJztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB0aGlzLnBhcmFtZXRlclZhbHVlc1twYXJhbWV0ZXJWYWx1ZUluZGV4XSA9IHBhcmFtZXRlcjtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRhc2V0SW5zdGFuY2VTdW1tYXJ5LnBhcmFtZXRlcnNbcGFyYW1ldGVyVmFsdWVJbmRleF0gPSBwYXJhbWV0ZXI7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmFtZXRlci50eXBlID09PSAnbGlzdCcpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5sb2FkTGlzdFBhcmFtZXRlcnMocGFyYW1ldGVyKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLnNldEF2YWlsYWJsZUZpbHRlclBhcmFtZXRlcnMoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIGxvYWRMaXN0UGFyYW1ldGVycyhwYXJhbWV0ZXI6IGFueSkge1xuICAgICAgICBpZiAocGFyYW1ldGVyLnNldHRpbmdzICYmIHBhcmFtZXRlci5zZXR0aW5ncy5kYXRhc2V0SW5zdGFuY2UpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmRhdGFzZXRTZXJ2aWNlLmV2YWx1YXRlRGF0YXNldChwYXJhbWV0ZXIuc2V0dGluZ3MuZGF0YXNldEluc3RhbmNlLCAnMCcsICcxMDAwMDAnKVxuICAgICAgICAgICAgICAgIC50aGVuKChkYXRhOiBhbnkpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbGlzdCA9IF8ubWFwKGRhdGEuYWxsRGF0YSwgaXRlbSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsOiBpdGVtW3BhcmFtZXRlci5zZXR0aW5ncy5sYWJlbENvbHVtbl0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IGl0ZW1bcGFyYW1ldGVyLnNldHRpbmdzLnZhbHVlQ29sdW1uXVxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIHBhcmFtZXRlci5saXN0ID0gXy51bmlxV2l0aChsaXN0LCBfLmlzRXF1YWwpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHVibGljIGdldE9yZGluYWwobikge1xuICAgICAgICBjb25zdCBzID0gWyd0aCcsICdzdCcsICduZCcsICdyZCddO1xuICAgICAgICBjb25zdCB2ID0gbiAlIDEwMDtcbiAgICAgICAgcmV0dXJuIG4gKyAoc1sodiAtIDIwKSAlIDEwXSB8fCBzW3ZdIHx8IHNbMF0pO1xuICAgIH1cblxuICAgIHB1YmxpYyB2aWV3RnVsbEl0ZW1EYXRhKGRhdGEsIGNvbHVtbk5hbWUpIHtcbiAgICAgICAgdGhpcy5kaWFsb2cub3BlbihEYXRhc2V0RWRpdG9yUG9wdXBDb21wb25lbnQsIHtcbiAgICAgICAgICAgIHdpZHRoOiAnODAwcHgnLFxuICAgICAgICAgICAgaGVpZ2h0OiAnNDAwcHgnLFxuICAgICAgICAgICAgZGF0YToge1xuICAgICAgICAgICAgICAgIGZ1bGxEYXRhOiBkYXRhLFxuICAgICAgICAgICAgICAgIGNvbHVtbk5hbWVcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHVibGljIGJvb2xlYW5VcGRhdGUoZXZlbnQsIHBhcmFtZXRlcikge1xuICAgICAgICBwYXJhbWV0ZXIudmFsdWUgPSBldmVudC5jaGVja2VkO1xuICAgIH1cblxuICAgIHB1YmxpYyBjaGFuZ2VEYXRlVHlwZShldmVudCwgcGFyYW1ldGVyLCB2YWx1ZSkge1xuICAgICAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgcGFyYW1ldGVyLl9kYXRlVHlwZSA9IHZhbHVlO1xuICAgIH1cblxuICAgIHB1YmxpYyB1cGRhdGVQZXJpb2RWYWx1ZSh2YWx1ZSwgcGVyaW9kLCBwYXJhbWV0ZXIpIHtcbiAgICAgICAgcGFyYW1ldGVyLnZhbHVlID0gYCR7dmFsdWV9XyR7cGVyaW9kfV9BR09gO1xuICAgIH1cblxuICAgIHB1YmxpYyBjYW5jZWxFdmFsdWF0ZSgpIHtcbiAgICAgICAgaWYgKHRoaXMucmVzdWx0c1N1Yikge1xuICAgICAgICAgICAgdGhpcy5yZXN1bHRzU3ViLnVuc3Vic2NyaWJlKCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmxvbmdSdW5uaW5nID0gZmFsc2U7XG4gICAgfVxuXG4gICAgcHVibGljIHNldERhc2hib2FyZFBhcmFtZXRlcihwYXJhbWV0ZXI6IGFueSwgcGFyYW1ldGVyTmFtZTogc3RyaW5nKSB7XG4gICAgICAgIHBhcmFtZXRlci52YWx1ZSA9ICd7eycgKyBwYXJhbWV0ZXJOYW1lICsgJ319JztcbiAgICAgICAgdGhpcy5ldmFsdWF0ZURhdGFzZXQodHJ1ZSk7XG4gICAgfVxuXG4gICAgcHVibGljIHNhdmUoKSB7XG4gICAgICAgIGlmICghdGhpcy5kYXRhc2V0SW5zdGFuY2VTdW1tYXJ5LmlkICYmICh0aGlzLmRhdGFzZXRJbnN0YW5jZVN1bW1hcnkudGl0bGUgPT09IHRoaXMuZGF0YXNldFRpdGxlKSkge1xuICAgICAgICAgICAgY29uc3QgZGlhbG9nUmVmID0gdGhpcy5kaWFsb2cub3BlbihEYXRhc2V0TmFtZURpYWxvZ0NvbXBvbmVudCwge1xuICAgICAgICAgICAgICAgIHdpZHRoOiAnNzAwcHgnLFxuICAgICAgICAgICAgICAgIGhlaWdodDogJzgwMHB4JyxcbiAgICAgICAgICAgICAgICBkaXNhYmxlQ2xvc2U6IHRydWUsXG4gICAgICAgICAgICAgICAgZGF0YToge1xuICAgICAgICAgICAgICAgICAgICBkYXRhc2V0SW5zdGFuY2VTdW1tYXJ5OiB0aGlzLmRhdGFzZXRJbnN0YW5jZVN1bW1hcnlcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGRpYWxvZ1JlZi5hZnRlckNsb3NlZCgpLnN1YnNjcmliZShkYXRhc2V0SW5zdGFuY2VTdW1tYXJ5ID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoZGF0YXNldEluc3RhbmNlU3VtbWFyeSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGFzZXRJbnN0YW5jZVN1bW1hcnkgPSBkYXRhc2V0SW5zdGFuY2VTdW1tYXJ5O1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNhdmVEYXRhc2V0KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnNhdmVEYXRhc2V0KCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIGFzeW5jIHNhdmVEYXRhc2V0KCkge1xuICAgICAgICBhd2FpdCB0aGlzLmRhdGFzZXRTZXJ2aWNlLnNhdmVEYXRhc2V0KHRoaXMuZGF0YXNldEluc3RhbmNlU3VtbWFyeSwgdGhpcy5hY2NvdW50SWQpO1xuICAgICAgICB0aGlzLnNuYWNrQmFyLm9wZW4oJ0RhdGFzZXQgc3VjY2Vzc2Z1bGx5IHNhdmVkLicsICdDbG9zZScsIHtcbiAgICAgICAgICAgIHZlcnRpY2FsUG9zaXRpb246ICd0b3AnLFxuICAgICAgICAgICAgZHVyYXRpb246IDMwMDBcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHVibGljIGFzeW5jIGV4Y2x1ZGVVcHN0cmVhbVRyYW5zZm9ybWF0aW9ucyh0cmFuc2Zvcm1hdGlvbiwgcmVzZXRQYWdlciA9IGZhbHNlKSB7XG4gICAgICAgIGNvbnN0IGNsb25lZFRyYW5zZm9ybWF0aW9uID0gXy5jbG9uZSh0cmFuc2Zvcm1hdGlvbik7XG4gICAgICAgIC8vIEdyYWIgdGhlIGluZGV4IG9mIHRoZSBjdXJyZW50IHRyYW5zZm9ybWF0aW9uIC0gc28gd2Uga25vdyB3aGljaCB1cHN0cmVhbSB0cmFuc2Zvcm1hdGlvbnMgdG8gZXhjbHVkZVxuICAgICAgICBjb25zdCBleGlzdGluZ0luZGV4ID0gXy5maW5kSW5kZXgodGhpcy5kYXRhc2V0SW5zdGFuY2VTdW1tYXJ5LnRyYW5zZm9ybWF0aW9uSW5zdGFuY2VzLCB7XG4gICAgICAgICAgICB0eXBlOiB0cmFuc2Zvcm1hdGlvbi50eXBlLFxuICAgICAgICAgICAgY29uZmlnOiB0cmFuc2Zvcm1hdGlvbi5jb25maWdcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gRXhjbHVkZSBhbGwgdXBzdHJlYW0gdHJhbnNmb3JtYXRpb25zIGZyb20gdGhlIGV2YWx1YXRlXG4gICAgICAgIHRoaXMuZGF0YXNldEluc3RhbmNlU3VtbWFyeS50cmFuc2Zvcm1hdGlvbkluc3RhbmNlcy5mb3JFYWNoKChpbnN0YW5jZSwgaW5kZXgpID0+IHtcbiAgICAgICAgICAgIGlmICgoaW5kZXggPj0gZXhpc3RpbmdJbmRleCkgJiYgaW5zdGFuY2UudHlwZSAhPT0gJ211bHRpc29ydCcpIHtcbiAgICAgICAgICAgICAgICBpbnN0YW5jZS5leGNsdWRlID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgYXdhaXQgdGhpcy5ldmFsdWF0ZURhdGFzZXQocmVzZXRQYWdlcik7XG4gICAgICAgIHJldHVybiBbY2xvbmVkVHJhbnNmb3JtYXRpb24sIGV4aXN0aW5nSW5kZXhdO1xuICAgIH1cblxuICAgIHByaXZhdGUgdmFsaWRhdGVGaWx0ZXJKdW5jdGlvbihmaWx0ZXJDb25maWcpIHtcblxuICAgICAgICBjb25zdCBjaGVjayA9IChmaWx0ZXJKdW5jdGlvbikgPT4ge1xuICAgICAgICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOnByZWZlci1mb3Itb2ZcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZmlsdGVySnVuY3Rpb24uZmlsdGVySnVuY3Rpb25zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgY29uc3QganVuY3Rpb24gPSBmaWx0ZXJKdW5jdGlvbi5maWx0ZXJKdW5jdGlvbnNbaV07XG4gICAgICAgICAgICAgICAgaWYgKCFqdW5jdGlvbi5maWx0ZXJzLmxlbmd0aCAmJiAhanVuY3Rpb24uZmlsdGVySnVuY3Rpb25zLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICBmaWx0ZXJKdW5jdGlvbi5maWx0ZXJKdW5jdGlvbnMuc3BsaWNlKGksIDEpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNoZWNrKGp1bmN0aW9uKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgY2hlY2soZmlsdGVyQ29uZmlnKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGxvYWREYXRhKCkge1xuICAgICAgICB0aGlzLnRhYmxlRGF0YSA9IHRoaXMuZGF0YXNldC5hbGxEYXRhO1xuXG4gICAgICAgIGlmICghdGhpcy50YWJsZURhdGEubGVuZ3RoKSB7XG4gICAgICAgICAgICBjb25zdCBkYXRhID0ge307XG4gICAgICAgICAgICBkYXRhW3RoaXMuZGF0YXNldC5jb2x1bW5zWzBdLm5hbWVdID0gJ05vIFJlc3VsdHMnO1xuICAgICAgICAgICAgdGhpcy50YWJsZURhdGEgPSBbZGF0YV07XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmVuZE9mUmVzdWx0cyA9IHRoaXMuZGF0YXNldC5hbGxEYXRhLmxlbmd0aCA8IHRoaXMubGltaXQ7XG4gICAgICAgIHRoaXMuZGlzcGxheWVkQ29sdW1ucyA9IF8ubWFwKHRoaXMuZGF0YXNldC5jb2x1bW5zLCAnbmFtZScpO1xuICAgICAgICB0aGlzLmZpbHRlckZpZWxkcyA9IF8ubWFwKHRoaXMuZGF0YXNldC5jb2x1bW5zLCBjb2x1bW4gPT4ge1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICB0aXRsZTogY29sdW1uLnRpdGxlLFxuICAgICAgICAgICAgICAgIG5hbWU6IGNvbHVtbi5uYW1lXG4gICAgICAgICAgICB9O1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5kYXRhTG9hZGVkLmVtaXQodGhpcy5kYXRhc2V0KTtcbiAgICAgICAgdGhpcy5kYXRhc2V0SW5zdGFuY2VTdW1tYXJ5Q2hhbmdlLmVtaXQodGhpcy5kYXRhc2V0SW5zdGFuY2VTdW1tYXJ5KTtcbiAgICAgICAgdGhpcy5zZXRUZXJtaW5hdGluZ1RyYW5zZm9ybWF0aW9ucygpO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHNldFBhcmFtZXRlclZhbHVlcyh2YWx1ZXMpIHtcblxuICAgIH1cblxuICAgIHByaXZhdGUgc2V0VGVybWluYXRpbmdUcmFuc2Zvcm1hdGlvbnMoKSB7XG4gICAgICAgIGxldCBzdW1tYXJpc2UgPSAwO1xuICAgICAgICBsZXQgam9pbiA9IDA7XG4gICAgICAgIGNvbnN0IHN1bW1hcmlzZVRvdGFsID0gXy5maWx0ZXIodGhpcy5kYXRhc2V0SW5zdGFuY2VTdW1tYXJ5LnRyYW5zZm9ybWF0aW9uSW5zdGFuY2VzLCB7dHlwZTogJ3N1bW1hcmlzZSd9KS5sZW5ndGg7XG4gICAgICAgIGNvbnN0IGpvaW5Ub3RhbCA9IF8uZmlsdGVyKHRoaXMuZGF0YXNldEluc3RhbmNlU3VtbWFyeS50cmFuc2Zvcm1hdGlvbkluc3RhbmNlcywge3R5cGU6ICdqb2luJ30pLmxlbmd0aDtcblxuICAgICAgICB0aGlzLnRlcm1pbmF0aW5nVHJhbnNmb3JtYXRpb25zID0gXy5maWx0ZXIodGhpcy5kYXRhc2V0SW5zdGFuY2VTdW1tYXJ5LnRyYW5zZm9ybWF0aW9uSW5zdGFuY2VzLCAodHJhbnNmb3JtYXRpb24sIGluZGV4KSA9PiB7XG4gICAgICAgICAgICBpZiAodHJhbnNmb3JtYXRpb24udHlwZSA9PT0gJ3N1bW1hcmlzZScpIHtcbiAgICAgICAgICAgICAgICBzdW1tYXJpc2UrKztcbiAgICAgICAgICAgICAgICB0cmFuc2Zvcm1hdGlvbi5fbGFiZWwgPSB0aGlzLmdldE9yZGluYWwoc3VtbWFyaXNlKSArICcgU3VtbWFyaXNlJztcbiAgICAgICAgICAgICAgICB0cmFuc2Zvcm1hdGlvbi5fZGlzYWJsZSA9IHN1bW1hcmlzZSA8IHN1bW1hcmlzZVRvdGFsO1xuICAgICAgICAgICAgICAgIHRyYW5zZm9ybWF0aW9uLl9hY3RpdmUgPSBzdW1tYXJpc2UgPT09IHN1bW1hcmlzZVRvdGFsO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodHJhbnNmb3JtYXRpb24udHlwZSA9PT0gJ2pvaW4nKSB7XG4gICAgICAgICAgICAgICAgam9pbisrO1xuICAgICAgICAgICAgICAgIHRyYW5zZm9ybWF0aW9uLl9sYWJlbCA9IHRyYW5zZm9ybWF0aW9uLmNvbmZpZy5qb2luZWREYXRhSXRlbVRpdGxlIHx8IHRoaXMuZ2V0T3JkaW5hbChqb2luKSArICcgSm9pbic7XG4gICAgICAgICAgICAgICAgdHJhbnNmb3JtYXRpb24uX2Rpc2FibGUgPSBqb2luIDwgam9pblRvdGFsO1xuICAgICAgICAgICAgICAgIHRyYW5zZm9ybWF0aW9uLl9hY3RpdmUgPSBqb2luID09PSBqb2luVG90YWw7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0cmFuc2Zvcm1hdGlvbi50eXBlID09PSAncGFnaW5nbWFya2VyJykge1xuICAgICAgICAgICAgICAgIHRyYW5zZm9ybWF0aW9uLl9sYWJlbCA9ICdQYWdpbmcgTWFya2VyJztcbiAgICAgICAgICAgICAgICB0cmFuc2Zvcm1hdGlvbi5fZGlzYWJsZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHRyYW5zZm9ybWF0aW9uLl9hY3RpdmUgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRyYW5zZm9ybWF0aW9uLnR5cGUgPT09ICdmb3JtdWxhJykge1xuICAgICAgICAgICAgICAgIHRyYW5zZm9ybWF0aW9uLl9sYWJlbCA9IHRyYW5zZm9ybWF0aW9uLmNvbmZpZy5leHByZXNzaW9uc1swXS5maWVsZFRpdGxlO1xuICAgICAgICAgICAgICAgIHRyYW5zZm9ybWF0aW9uLl9kaXNhYmxlID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdHJhbnNmb3JtYXRpb24uX2FjdGl2ZSA9IHRydWU7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodHJhbnNmb3JtYXRpb24udHlwZSA9PT0gJ2NvbHVtbnMnKSB7XG4gICAgICAgICAgICAgICAgdHJhbnNmb3JtYXRpb24uX2xhYmVsID0gJ0NvbHVtbnMgVXBkYXRlJztcbiAgICAgICAgICAgICAgICB0cmFuc2Zvcm1hdGlvbi5fZGlzYWJsZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHRyYW5zZm9ybWF0aW9uLl9hY3RpdmUgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRyYW5zZm9ybWF0aW9uLnR5cGUgPT09ICdmaWx0ZXInKSB7XG4gICAgICAgICAgICAgICAgdHJhbnNmb3JtYXRpb24uX2xhYmVsID0gJ0ZpbHRlcic7XG4gICAgICAgICAgICAgICAgdHJhbnNmb3JtYXRpb24uX2Rpc2FibGUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB0cmFuc2Zvcm1hdGlvbi5fYWN0aXZlID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBBZGQgYW4gaW4gdmFsdWVcbiAgICAgKi9cbiAgICBwdWJsaWMgYWRkUGFyYW1ldGVyVmFsdWUocGFyYW1ldGVyOiBhbnksIGV2ZW50OiBhbnkpIHtcblxuICAgICAgICBjb25zdCB2YWx1ZSA9IChldmVudC52YWx1ZSB8fCBldmVudC50YXJnZXQ/LnZhbHVlIHx8ICcnKS50cmltKCk7XG5cbiAgICAgICAgaWYgKCFfLmlzQXJyYXkocGFyYW1ldGVyLnZhbHVlKSkge1xuICAgICAgICAgICAgcGFyYW1ldGVyLnZhbHVlID0gW107XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodmFsdWUgJiYgdmFsdWUgIT09ICdudWxsJyAmJiBwYXJhbWV0ZXIudmFsdWUuaW5kZXhPZih2YWx1ZSkgPT09IC0xKSB7XG4gICAgICAgICAgICBwYXJhbWV0ZXIudmFsdWUucHVzaCh2YWx1ZSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDbGVhciB0aGUgaW5wdXQgdmFsdWVcbiAgICAgICAgaWYgKGV2ZW50LmNoaXBJbnB1dCkge1xuICAgICAgICAgICAgZXZlbnQuY2hpcElucHV0IS5jbGVhcigpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlIGFuIGluIHZhbHVlXG4gICAgICpcbiAgICAgKi9cbiAgICBwdWJsaWMgcmVtb3ZlUGFyYW1ldGVyVmFsdWUocGFyYW1ldGVyOiBhbnksIHZhbHVlOiBzdHJpbmcpIHtcblxuICAgICAgICBjb25zdCBpbmRleCA9IHBhcmFtZXRlci52YWx1ZS5pbmRleE9mKHZhbHVlKTtcblxuICAgICAgICBpZiAoaW5kZXggPj0gMCkge1xuICAgICAgICAgICAgcGFyYW1ldGVyLnZhbHVlLnNwbGljZShpbmRleCwgMSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwdWJsaWMgYXN5bmMgZXZhbHVhdGVEYXRhc2V0KHJlc2V0UGFnZXI/OiBib29sZWFuKSB7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZShhc3luYyAocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICBpZiAocmVzZXRQYWdlcikge1xuICAgICAgICAgICAgICAgIHRoaXMucmVzZXRQYWdlcigpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb25zdCBjbG9uZWREYXRhc2V0SW5zdGFuY2UgPSBhd2FpdCB0aGlzLnByZXBhcmVEYXRhc2V0SW5zdGFuY2VGb3JFdmFsdWF0aW9uKCk7XG4gICAgICAgICAgICB0aGlzLnNldEF2YWlsYWJsZUZpbHRlclBhcmFtZXRlcnMoKTtcblxuICAgICAgICAgICAgY29uc3QgdHJhY2tpbmdLZXkgPSBEYXRlLm5vdygpICsgKE1hdGgucmFuZG9tKCkgKyAxKS50b1N0cmluZygzNikuc3Vic3RyKDIsIDUpO1xuICAgICAgICAgICAgbGV0IGZpbmlzaGVkID0gZmFsc2U7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLmRhc2hib2FyZExheW91dFNldHRpbmdzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5kYXNoYm9hcmRMYXlvdXRTZXR0aW5ncy5saW1pdCA9IHRoaXMubGltaXQ7XG4gICAgICAgICAgICAgICAgdGhpcy5kYXNoYm9hcmRMYXlvdXRTZXR0aW5ncy5vZmZzZXQgPSB0aGlzLm9mZnNldDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5ldmFsdWF0ZVN1YiA9IHRoaXMuZGF0YXNldFNlcnZpY2UuZXZhbHVhdGVEYXRhc2V0V2l0aFRyYWNraW5nKFxuICAgICAgICAgICAgICAgIGNsb25lZERhdGFzZXRJbnN0YW5jZSxcbiAgICAgICAgICAgICAgICBTdHJpbmcodGhpcy5vZmZzZXQpLFxuICAgICAgICAgICAgICAgIFN0cmluZyh0aGlzLmxpbWl0KSxcbiAgICAgICAgICAgICAgICB0cmFja2luZ0tleVxuICAgICAgICAgICAgKS5zdWJzY3JpYmUoYXN5bmMgZGF0YXNldCA9PiB7XG4gICAgICAgICAgICAgICAgZmluaXNoZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHRoaXMuZGF0YXNldCA9IGRhdGFzZXQ7XG4gICAgICAgICAgICAgICAgdGhpcy5sb2FkRGF0YSgpO1xuICAgICAgICAgICAgICAgIHJlc29sdmUodHJ1ZSk7XG4gICAgICAgICAgICB9LCBlcnIgPT4ge1xuICAgICAgICAgICAgICAgIGZpbmlzaGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBpZiAoZXJyLmVycm9yICYmIGVyci5lcnJvci5tZXNzYWdlKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBtZXNzYWdlID0gZXJyLmVycm9yLm1lc3NhZ2UudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG1lc3NhZ2UuaW5jbHVkZXMoJ3NxbCcpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlID0gJ0FuIGVycm9yIG9jY3VycmVkIHByb2Nlc3NpbmcgeW91ciBxdWVyeS4gUGxlYXNlIGNoZWNrIGFueSBTUUwgc3ludGF4IGFuZCB0cnkgYWdhaW4uJztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoIW1lc3NhZ2UuaW5jbHVkZXMoJ3BhcmFtZXRlcicpICYmICFtZXNzYWdlLmluY2x1ZGVzKCdyZXF1aXJlZCcpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNuYWNrQmFyLm9wZW4oZXJyLmVycm9yLm1lc3NhZ2UsICdDbG9zZScsIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2ZXJ0aWNhbFBvc2l0aW9uOiAndG9wJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkdXJhdGlvbjogNTAwMFxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gSWYgdGhlIGV2YWx1YXRlIGZhaWxzIHdlIHN0aWxsIHdhbnQgdG8gcHVibGlzaCB0aGUgaW5zdGFuY2UgYW5kIHNldCB0aGUgdGVybWluYXRpbmcgdHJhbnNmb3JtYXRpb25zXG4gICAgICAgICAgICAgICAgdGhpcy5kYXRhc2V0SW5zdGFuY2VTdW1tYXJ5Q2hhbmdlLmVtaXQodGhpcy5kYXRhc2V0SW5zdGFuY2VTdW1tYXJ5KTtcbiAgICAgICAgICAgICAgICB0aGlzLnNldFRlcm1pbmF0aW5nVHJhbnNmb3JtYXRpb25zKCk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVqZWN0KGZhbHNlKTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoIWZpbmlzaGVkKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIElmIHdlIGhhdmUgYW55IHByZS1leGlzdGluZyBsb25nLXJ1bm5pbmcgdGFza3MgY2FuY2VsIHRoZXNlIGJlZm9yZSBzZXR0aW5nIG9mZiBhbm90aGVyIGV2YWx1YXRlLlxuICAgICAgICAgICAgICAgICAgICB0aGlzLmNhbmNlbEV2YWx1YXRlKCk7XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5sb25nUnVubmluZyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZXZhbHVhdGVTdWIudW5zdWJzY3JpYmUoKTtcblxuICAgICAgICAgICAgICAgICAgICB0aGlzLnJlc3VsdHNTdWIgPSB0aGlzLmRhdGFzZXRTZXJ2aWNlLmdldERhdGFUcmFja2luZ1Jlc3VsdHModHJhY2tpbmdLZXkpXG4gICAgICAgICAgICAgICAgICAgICAgICAuc3Vic2NyaWJlKChyZXN1bHRzOiBhbnkpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVzdWx0cy5zdGF0dXMgPT09ICdDT01QTEVURUQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVzdWx0c1N1Yi51bnN1YnNjcmliZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGFzZXQgPSByZXN1bHRzLnJlc3VsdDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5sb25nUnVubmluZyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxvYWREYXRhKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUodHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChyZXN1bHRzLnN0YXR1cyA9PT0gJ0ZBSUxFRCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZXN1bHRzU3ViLnVuc3Vic2NyaWJlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubG9uZ1J1bm5pbmcgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3JNZXNzYWdlID0gcmVzdWx0cy5yZXN1bHQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlcnJvck1lc3NhZ2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1lc3NhZ2UgPSBlcnJvck1lc3NhZ2UudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghbWVzc2FnZS5pbmNsdWRlcygncGFyYW1ldGVyJykgJiYgIW1lc3NhZ2UuaW5jbHVkZXMoJ3JlcXVpcmVkJykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNuYWNrQmFyLm9wZW4oZXJyb3JNZXNzYWdlLCAnQ2xvc2UnLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZlcnRpY2FsUG9zaXRpb246ICd0b3AnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkdXJhdGlvbjogNTAwMFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIElmIHRoZSBldmFsdWF0ZSBmYWlscyB3ZSBzdGlsbCB3YW50IHRvIHB1Ymxpc2ggdGhlIGluc3RhbmNlIGFuZCBzZXQgdGhlIHRlcm1pbmF0aW5nIHRyYW5zZm9ybWF0aW9uc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGFzZXRJbnN0YW5jZVN1bW1hcnlDaGFuZ2UuZW1pdCh0aGlzLmRhdGFzZXRJbnN0YW5jZVN1bW1hcnkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldFRlcm1pbmF0aW5nVHJhbnNmb3JtYXRpb25zKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoZmFsc2UpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sIDMwMDApO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHNldEF2YWlsYWJsZUZpbHRlclBhcmFtZXRlcnMoKSB7XG4gICAgICAgIGNvbnN0IGZpbHRlclBhcmFtZXRlclZhbHVlcyA9IF8ubWFwKF8uY29uY2F0KF8udmFsdWVzKHRoaXMuZGFzaGJvYXJkUGFyYW1ldGVycyksIF8udmFsdWVzKHRoaXMucGFyYW1ldGVyVmFsdWVzKSksIHBhcmFtID0+IHtcbiAgICAgICAgICAgIHJldHVybiB7bmFtZTogcGFyYW0ubmFtZSwgdGl0bGU6IHBhcmFtLnRpdGxlfTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuZmlsdGVyUGFyYW1ldGVyVmFsdWVzID0gXy51bmlxQnkoZmlsdGVyUGFyYW1ldGVyVmFsdWVzLCAnbmFtZScpO1xuICAgIH1cblxuICAgIHByaXZhdGUgX3JlbW92ZVRyYW5zZm9ybWF0aW9uKHRyYW5zZm9ybWF0aW9uLCBpbmRleD8pIHtcbiAgICAgICAgaWYgKCFfLmlzTmlsKGluZGV4KSAmJiBpbmRleCA+PSAwKSB7XG4gICAgICAgICAgICAvLyBJZiBhIGN1cnJlbnQgaW5kZXggaGFzIGJlZW4gc3VwcGxpZWQsIHJlc2V0IGFsbCB0aGUgcHJlIHRyYW5zZm9ybWF0aW9uIGhpZGRlbiBmaWVsZHMgcHJpb3IgdG8gZXZhbC5cbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaW5kZXg7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmRhdGFzZXRJbnN0YW5jZVN1bW1hcnkudHJhbnNmb3JtYXRpb25JbnN0YW5jZXNbaV0udHlwZSAhPT0gJ2ZpbHRlcicpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRhc2V0SW5zdGFuY2VTdW1tYXJ5LnRyYW5zZm9ybWF0aW9uSW5zdGFuY2VzW2ldLmhpZGUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuZGF0YXNldEluc3RhbmNlU3VtbWFyeS50cmFuc2Zvcm1hdGlvbkluc3RhbmNlcy5zcGxpY2UoaW5kZXgsIDEpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgXy5yZW1vdmUodGhpcy5kYXRhc2V0SW5zdGFuY2VTdW1tYXJ5LnRyYW5zZm9ybWF0aW9uSW5zdGFuY2VzLCBfLm9taXRCeSh7XG4gICAgICAgICAgICAgICAgdHlwZTogdHJhbnNmb3JtYXRpb24udHlwZSxcbiAgICAgICAgICAgICAgICBjb25maWc6IHRyYW5zZm9ybWF0aW9uLnR5cGUgIT09ICdwYWdpbmdtYXJrZXInID8gdHJhbnNmb3JtYXRpb24uY29uZmlnIDogbnVsbFxuICAgICAgICAgICAgfSwgXy5pc05pbCkpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5ldmFsdWF0ZURhdGFzZXQodHJ1ZSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSByZXNldFBhZ2VyKCkge1xuICAgICAgICB0aGlzLm9mZnNldCA9IDA7XG4gICAgICAgIHRoaXMucGFnZSA9IDE7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBhc3luYyBwcmVwYXJlRGF0YXNldEluc3RhbmNlRm9yRXZhbHVhdGlvbigpIHtcbiAgICAgICAgY29uc3QgdmFsdWVzOiBhbnkgPSBhd2FpdCB0aGlzLmRhdGFzZXRTZXJ2aWNlLmdldEV2YWx1YXRlZFBhcmFtZXRlcnModGhpcy5kYXRhc2V0SW5zdGFuY2VTdW1tYXJ5KTtcblxuICAgICAgICBjb25zdCBwYXJhbVZhbHVlcyA9IHZhbHVlcy5tYXAodmFsdWUgPT4ge1xuICAgICAgICAgICAgdmFsdWUuX2xvY2tlZCA9ICFfLmZpbmQodGhpcy5kYXRhc2V0SW5zdGFuY2VTdW1tYXJ5LnBhcmFtZXRlcnMsIHtuYW1lOiB2YWx1ZS5uYW1lfSk7XG4gICAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRoaXMuZm9jdXNQYXJhbXMgPSBmYWxzZTtcbiAgICAgICAgY29uc3QgcGFyYW1ldGVyVmFsdWVzID0ge307XG4gICAgICAgIHBhcmFtVmFsdWVzLmZvckVhY2gocGFyYW1WYWx1ZSA9PiB7XG4gICAgICAgICAgICBjb25zdCBleGlzdFBhcmFtID0gXy5maW5kKHRoaXMucGFyYW1ldGVyVmFsdWVzLCB7bmFtZTogcGFyYW1WYWx1ZS5uYW1lfSk7XG4gICAgICAgICAgICBpZiAoIWV4aXN0UGFyYW0pIHtcbiAgICAgICAgICAgICAgICBjb25zdCBleGlzdGluZ1ZhbHVlID0gdGhpcy5kYXRhc2V0SW5zdGFuY2VTdW1tYXJ5LnBhcmFtZXRlclZhbHVlc1twYXJhbVZhbHVlLm5hbWVdO1xuICAgICAgICAgICAgICAgIHBhcmFtVmFsdWUudmFsdWUgPSBfLmlzTmlsKGV4aXN0aW5nVmFsdWUpID8gcGFyYW1WYWx1ZS5kZWZhdWx0VmFsdWUgOiBleGlzdGluZ1ZhbHVlO1xuICAgICAgICAgICAgICAgIHBhcmFtZXRlclZhbHVlc1twYXJhbVZhbHVlLm5hbWVdID0gcGFyYW1WYWx1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLmZvY3VzUGFyYW1zID0gIWV4aXN0aW5nVmFsdWU7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHBhcmFtZXRlclZhbHVlc1tleGlzdFBhcmFtLm5hbWVdID0gZXhpc3RQYXJhbTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMucGFyYW1ldGVyVmFsdWVzID0gXy52YWx1ZXMocGFyYW1ldGVyVmFsdWVzKTtcblxuICAgICAgICBpZiAodGhpcy5kYXRhc2V0SW5zdGFuY2VTdW1tYXJ5ICYmIHRoaXMuZGF0YXNldEluc3RhbmNlU3VtbWFyeS5pZCkge1xuICAgICAgICAgICAgbG9jYWxTdG9yYWdlLnNldEl0ZW0oJ2RhdGFzZXRJbnN0YW5jZUxpbWl0JyArIHRoaXMuZGF0YXNldEluc3RhbmNlU3VtbWFyeS5pZCwgKHRoaXMubGltaXQpLnRvU3RyaW5nKCkpO1xuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuZGF0YXNldEluc3RhbmNlU3VtbWFyeS5pbnN0YW5jZUtleSkge1xuICAgICAgICAgICAgbG9jYWxTdG9yYWdlLnNldEl0ZW0oJ2RhdGFzZXRJbnN0YW5jZUxpbWl0JyArIHRoaXMuZGF0YXNldEluc3RhbmNlU3VtbWFyeS5pbnN0YW5jZUtleSwgKHRoaXMubGltaXQpLnRvU3RyaW5nKCkpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3Qgc29ydCA9IF8uZmluZCh0aGlzLmRhdGFzZXRJbnN0YW5jZVN1bW1hcnkudHJhbnNmb3JtYXRpb25JbnN0YW5jZXMsIHt0eXBlOiAnbXVsdGlzb3J0J30pO1xuICAgICAgICBpZiAoc29ydCkge1xuICAgICAgICAgICAgY29uc3QgY2xvbmUgPSBfLmNsb25lKHNvcnQpO1xuICAgICAgICAgICAgXy5yZW1vdmUodGhpcy5kYXRhc2V0SW5zdGFuY2VTdW1tYXJ5LnRyYW5zZm9ybWF0aW9uSW5zdGFuY2VzLCBzb3J0KTtcbiAgICAgICAgICAgIHRoaXMuZGF0YXNldEluc3RhbmNlU3VtbWFyeS50cmFuc2Zvcm1hdGlvbkluc3RhbmNlcy5wdXNoKGNsb25lKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENsb25lIHRoZSBjdXJyZW50IGluc3RhbmNlIG9iamVjdCwgc28gd2UgY2FuIHJlbW92ZSBhbnkgZXhjbHVkZWQgdHJhbnNmb3JtYXRpb25zLCB3aXRob3V0IGFmZmVjdGluZ1xuICAgICAgICAvLyB0aGUgb3JpZ2luYWwgb2JqZWN0IHdoaWNoIHRoZSBndWkgdXNlcyB0byBkcmF3IHRyYW5zZm9ybWF0aW9uIGl0ZW1zLlxuICAgICAgICBjb25zdCBjbG9uZWREYXRhc2V0SW5zdGFuY2UgPSBfLm1lcmdlKHt9LCB0aGlzLmRhdGFzZXRJbnN0YW5jZVN1bW1hcnkpO1xuICAgICAgICBfLnJlbW92ZShjbG9uZWREYXRhc2V0SW5zdGFuY2UudHJhbnNmb3JtYXRpb25JbnN0YW5jZXMsIHtleGNsdWRlOiB0cnVlfSk7XG5cbiAgICAgICAgY29uc3QgZXhjbHVkZWRUcmFuc2Zvcm1hdGlvbnMgPSBfLmZpbmQodGhpcy5kYXRhc2V0SW5zdGFuY2VTdW1tYXJ5LnRyYW5zZm9ybWF0aW9uSW5zdGFuY2VzLCB7ZXhjbHVkZTogdHJ1ZX0pO1xuICAgICAgICBpZiAoZXhjbHVkZWRUcmFuc2Zvcm1hdGlvbnMpIHtcbiAgICAgICAgICAgIF8ucmVtb3ZlKGNsb25lZERhdGFzZXRJbnN0YW5jZS50cmFuc2Zvcm1hdGlvbkluc3RhbmNlcywge3R5cGU6ICdtdWx0aXNvcnQnfSk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnBhcmFtZXRlclZhbHVlcy5mb3JFYWNoKHBhcmFtID0+IHtcbiAgICAgICAgICAgIGlmIChwYXJhbS50eXBlID09PSAnZGF0ZScgfHwgcGFyYW0udHlwZSA9PT0gJ2RhdGV0aW1lJykge1xuICAgICAgICAgICAgICAgIGlmICghcGFyYW0uX2RhdGVUeXBlICYmIHBhcmFtLnZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGlzUGVyaW9kID0gcGFyYW0udmFsdWUuaW5jbHVkZXMoJ0FHTycpO1xuICAgICAgICAgICAgICAgICAgICBwYXJhbS5fZGF0ZVR5cGUgPSBpc1BlcmlvZCA/ICdwZXJpb2QnIDogJ3BpY2tlcic7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1BlcmlvZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcGVyaW9kVmFsdWVzID0gcGFyYW0udmFsdWUuc3BsaXQoJ18nKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhcmFtLl9wZXJpb2RWYWx1ZSA9IHBlcmlvZFZhbHVlc1swXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhcmFtLl9wZXJpb2QgPSBwZXJpb2RWYWx1ZXNbMV07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocGFyYW0udHlwZSA9PT0gJ2xpc3QnICYmICFwYXJhbS5saXN0Py5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmxvYWRMaXN0UGFyYW1ldGVycyhwYXJhbSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0aGlzLmRhc2hib2FyZFBhcmFtZXRlcnMgJiYgT2JqZWN0LmtleXModGhpcy5kYXNoYm9hcmRQYXJhbWV0ZXJzKS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBpZiAoXy5pc1N0cmluZyhwYXJhbS52YWx1ZSkgJiYgcGFyYW0udmFsdWUuaW5jbHVkZXMoJ3t7JykpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcGFyYW1LZXkgPSBwYXJhbS52YWx1ZS5yZXBsYWNlKCd7eycsICcnKS5yZXBsYWNlKCd9fScsICcnKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5kYXNoYm9hcmRQYXJhbWV0ZXJzW3BhcmFtS2V5XSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xvbmVkRGF0YXNldEluc3RhbmNlLnBhcmFtZXRlclZhbHVlc1twYXJhbS5uYW1lXSA9IHRoaXMuZGFzaGJvYXJkUGFyYW1ldGVyc1twYXJhbUtleV0udmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFjbG9uZWREYXRhc2V0SW5zdGFuY2UucGFyYW1ldGVyVmFsdWVzW3BhcmFtLm5hbWVdICYmIHRoaXMuZGFzaGJvYXJkUGFyYW1ldGVyc1twYXJhbS5uYW1lXSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiBubyB2YWx1ZSBoYXMgYmVlbiBzZXQgZGVmYXVsdCB0byB0aGUgZGFzaGJvYXJkIHBhcmFtIHZhbHVlXG4gICAgICAgICAgICAgICAgICAgIGNsb25lZERhdGFzZXRJbnN0YW5jZS5wYXJhbWV0ZXJWYWx1ZXNbcGFyYW0ubmFtZV0gPSB0aGlzLmRhc2hib2FyZFBhcmFtZXRlcnNbcGFyYW0ubmFtZV0udmFsdWU7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICghY2xvbmVkRGF0YXNldEluc3RhbmNlLnBhcmFtZXRlclZhbHVlc1twYXJhbS5uYW1lXSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBVbmxlc3MgdGhlcmUgaXNuJ3QgYSBkYXNoYm9hcmQgcGFyYW0gdGhhdCBtYXRjaGVzXG4gICAgICAgICAgICAgICAgICAgIGNsb25lZERhdGFzZXRJbnN0YW5jZS5wYXJhbWV0ZXJWYWx1ZXNbcGFyYW0ubmFtZV0gPSBwYXJhbS52YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGNsb25lZERhdGFzZXRJbnN0YW5jZS5wYXJhbWV0ZXJWYWx1ZXNbcGFyYW0ubmFtZV0gPSBwYXJhbS52YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5kYXRhc2V0SW5zdGFuY2VTdW1tYXJ5LnBhcmFtZXRlclZhbHVlc1twYXJhbS5uYW1lXSA9IHBhcmFtLnZhbHVlO1xuICAgICAgICB9KTtcblxuICAgICAgICAvLyBNZXJnZSBpbiBnbG9iYWwgZGFzaGJvYXJkIHBhcmFtc1xuICAgICAgICBpZiAodGhpcy5kYXNoYm9hcmRQYXJhbWV0ZXJzICYmIE9iamVjdC5rZXlzKHRoaXMuZGFzaGJvYXJkUGFyYW1ldGVycykubGVuZ3RoKSB7XG4gICAgICAgICAgICBfLmZvckVhY2godGhpcy5kYXNoYm9hcmRQYXJhbWV0ZXJzLCAocGFyYW0sIG5hbWUpID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoIWNsb25lZERhdGFzZXRJbnN0YW5jZS5wYXJhbWV0ZXJWYWx1ZXNbbmFtZV0pIHtcbiAgICAgICAgICAgICAgICAgICAgY2xvbmVkRGF0YXNldEluc3RhbmNlLnBhcmFtZXRlclZhbHVlc1tuYW1lXSA9IHBhcmFtLnZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gRW5zdXJlIHdlIHNlbmQgYmFjayBhbnkgZGF0ZXMgaW4gY29ycmVjdCBmb3JtYXRcbiAgICAgICAgY29uc3QgZGF0ZXRpbWVQYXJhbXMgPSBfLmZpbHRlcihjbG9uZWREYXRhc2V0SW5zdGFuY2UucGFyYW1ldGVycywgcGFyYW0gPT4ge1xuICAgICAgICAgICAgcmV0dXJuIHBhcmFtLnR5cGUgPT09ICdkYXRlJyB8fCBwYXJhbS50eXBlID09PSAnZGF0ZXRpbWUnO1xuICAgICAgICB9KTtcbiAgICAgICAgZGF0ZXRpbWVQYXJhbXMuZm9yRWFjaChwYXJhbSA9PiB7XG4gICAgICAgICAgICBjb25zdCB2YWx1ZSA9IGNsb25lZERhdGFzZXRJbnN0YW5jZS5wYXJhbWV0ZXJWYWx1ZXNbcGFyYW0ubmFtZV07XG4gICAgICAgICAgICBpZiAodmFsdWUgJiYgIXZhbHVlLmluY2x1ZGVzKCdBR08nKSkge1xuICAgICAgICAgICAgICAgIGNsb25lZERhdGFzZXRJbnN0YW5jZS5wYXJhbWV0ZXJWYWx1ZXNbcGFyYW0ubmFtZV0gPSBtb21lbnQodmFsdWUpLmZvcm1hdCgnWVlZWS1NTS1ERCBISDptbTpzcycpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gY2xvbmVkRGF0YXNldEluc3RhbmNlO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCByZWFkb25seSBkZWNvZGVVUkkgPSBkZWNvZGVVUkk7XG4gICAgcHJvdGVjdGVkIHJlYWRvbmx5IEVOVEVSID0gRU5URVI7XG4gICAgcHJvdGVjdGVkIHJlYWRvbmx5IENPTU1BID0gQ09NTUE7XG59XG5cbkBDb21wb25lbnQoe1xuICAgIHNlbGVjdG9yOiAna2ktZGF0YXNldC1lZGl0b3ItcG9wdXAnLFxuICAgIHRlbXBsYXRlVXJsOiAnZGF0YXNldC1lZGl0b3ItcG9wdXAuaHRtbCcsXG4gICAgaG9zdDoge2NsYXNzOiAnZGlhbG9nLXdyYXBwZXInfVxufSlcbmV4cG9ydCBjbGFzcyBEYXRhc2V0RWRpdG9yUG9wdXBDb21wb25lbnQge1xuXG4gICAgcHVibGljIGZ1bGxEYXRhOiBzdHJpbmc7XG4gICAgcHVibGljIGNvbHVtbk5hbWU6IHN0cmluZztcblxuICAgIGNvbnN0cnVjdG9yKEBJbmplY3QoTUFUX0RJQUxPR19EQVRBKSBwdWJsaWMgZGF0YTogRGF0YXNldEVkaXRvclBvcHVwQ29tcG9uZW50KSB7XG5cbiAgICAgICAgdGhpcy5mdWxsRGF0YSA9IHRoaXMuZGF0YS5mdWxsRGF0YTtcbiAgICAgICAgdGhpcy5jb2x1bW5OYW1lID0gXy5zdGFydENhc2UodGhpcy5kYXRhLmNvbHVtbk5hbWUpO1xuICAgIH1cblxufVxuIiwiPGRpdiAqbmdJZj1cImxvbmdSdW5uaW5nXCIgY2xhc3M9XCJsb25nLXJ1bm5pbmcgZmxleC1jb2xcIj5cblxuICAgIDxkaXYgY2xhc3M9XCJsb2FkaW5nLWJveFwiPlxuICAgICAgICA8bWF0LXNwaW5uZXIgW2RpYW1ldGVyXT1cIjE1MFwiPjwvbWF0LXNwaW5uZXI+XG4gICAgICAgIDxkaXY+TG9hZGluZzwvZGl2PlxuICAgIDwvZGl2PlxuXG4gICAgPHAgY2xhc3M9XCJ0ZXh0LWNlbnRlclwiPlBsZWFzZSB3YWl0IHdoaWxlIHdlIHByb2Nlc3MgdGhpcyBxdWVyeS48L3A+XG4gICAgPHAgY2xhc3M9XCJ0ZXh0LWNlbnRlclwiPlRoZSByZXN1bHRzIHdpbGwgYmUgc2hvd24gaGVyZSBvbmNlIGl0IGhhcyBmaW5pc2hlZCBydW5uaW5nLjwvcD5cbiAgICA8ZGl2PlxuICAgICAgICA8YSBjbGFzcz1cInRleHQtcHJpbWFyeSBob3Zlcjp1bmRlcmxpbmVcIiAoY2xpY2spPVwiY2FuY2VsRXZhbHVhdGUoKVwiPkNhbmNlbCBxdWVyeSBhbmQgcmV0dXJuIHRvIGVkaXRvci48L2E+XG4gICAgPC9kaXY+XG48L2Rpdj5cbjxkaXYgY2xhc3M9XCJwb2ludGVyLWV2ZW50cy1ub25lIGZpeGVkIGluc2V0LXktMCByaWdodC0wIGZsZXggbWF4LXctZnVsbCBwbC0xMCAtei0xMFwiIGlkPVwic2lkZWJhcldyYXBwZXJcIj5cbiAgICA8ZGl2IFtuZ0NsYXNzXT1cInsndHJhbnNsYXRlLXgtMCc6IHNpZGVPcGVuLCAndHJhbnNsYXRlLXgtZnVsbCc6ICFzaWRlT3Blbn1cIlxuICAgICAgICAgKGNsaWNrKT1cIiRldmVudC5zdG9wUHJvcGFnYXRpb24oKVwiXG4gICAgICAgICBjbGFzcz1cInBvaW50ZXItZXZlbnRzLWF1dG8gdy1zY3JlZW4gbWF4LXctbWQgdHJhbnNmb3JtIHRyYW5zaXRpb24gZWFzZS1pbi1vdXQgZHVyYXRpb24tNTAwIHNtOmR1cmF0aW9uLTcwMFwiXG4gICAgICAgICBpZD1cImRvY1NpZGViYXJcIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImZsZXggaC1mdWxsIGZsZXgtY29sIG92ZXJmbG93LXktc2Nyb2xsIGJnLXdoaXRlIHB5LTYgc2hhZG93LXhsXCI+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwicHgtNCBzbTpweC02XCI+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZsZXggaXRlbXMtc3RhcnQganVzdGlmeS1iZXR3ZWVuXCI+XG4gICAgICAgICAgICAgICAgICAgIDxkaXY+PC9kaXY+XG5cbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm1sLTMgZmxleCBoLTcgaXRlbXMtY2VudGVyXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiAoY2xpY2spPVwib3BlblNpZGUubmV4dChmYWxzZSlcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cInJvdW5kZWQtbWQgYmctd2hpdGUgdGV4dC1ncmF5LTQwMCBob3Zlcjp0ZXh0LWdyYXktNTAwIGZvY3VzOm91dGxpbmUtbm9uZVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwic3Itb25seVwiPkNsb3NlIHBhbmVsPC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwhLS0gSGVyb2ljb24gbmFtZTogb3V0bGluZS94IC0tPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzdmcgY2xhc3M9XCJoLTYgdy02XCIgeG1sbnM9XCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiIGZpbGw9XCJub25lXCIgdmlld0JveD1cIjAgMCAyNCAyNFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJva2U9XCJjdXJyZW50Q29sb3JcIiBhcmlhLWhpZGRlbj1cInRydWVcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHBhdGggc3Ryb2tlLWxpbmVjYXA9XCJyb3VuZFwiIHN0cm9rZS1saW5lam9pbj1cInJvdW5kXCIgc3Ryb2tlLXdpZHRoPVwiMlwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGQ9XCJNNiAxOEwxOCA2TTYgNmwxMiAxMlwiLz5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L3N2Zz5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cInJlbGF0aXZlIGZsZXgtMSBweC00IHNtOnB4LTZcIj5cbiAgICAgICAgICAgICAgICA8a2ktd2hpdGVsaXN0ZWQtc3FsLWZ1bmN0aW9ucyBbZmllbGRzXT1cImZpbHRlckZpZWxkc1wiPjwva2ktd2hpdGVsaXN0ZWQtc3FsLWZ1bmN0aW9ucz5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbjwvZGl2PlxuXG48ZGl2ICpuZ0lmPVwiIWRhdGFzZXRFZGl0b3JOb1Rvb2xzXCIgY2xhc3M9XCJib3JkZXItYiBjZWxsLWhlYWRlciBlbmRcIj5cbiAgICA8ZGl2IGNsYXNzPVwibGVhZGluZy01IHB4LTQgdGV4dC14cyB1cHBlcmNhc2UgdHJhY2tpbmctd2lkZXIgZm9udC1tZWRpdW0gYm9yZGVyLXItMiB0ZXh0LWdyYXktNjAwXCI+XG4gICAgICAgIE9wZXJhdGlvbnNcbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwiZGF0YXNldC1kYXRhLWFjdGlvbnNcIj5cbiAgICAgICAgPGJ1dHRvbiAoY2xpY2spPVwiYWRkRmlsdGVyKClcIlxuICAgICAgICAgICAgICAgIHRpdGxlPVwiRmlsdGVyIHRoZSBzZXQgdXNpbmcgY29sdW1uIGJhc2VkIHJlc3RyaWN0aW9uc1wiXG4gICAgICAgICAgICAgICAgY2xhc3M9XCJ3LTIwIGZsZXggZmxleC1jb2wgaXRlbXMtY2VudGVyIGp1c3RpZnktY2VudGVyIHB5LTEgcHgtMiB0ZXh0LXhzIHRleHQtZ3JheS02MDAgY3Vyc29yLXBvaW50ZXIgaG92ZXI6YmctZ3JheS0xMDBcIj5cbiAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwibWF0ZXJpYWwtc3ltYm9scy1vdXRsaW5lZCB0ZXh0LXhsXCI+ZmlsdGVyX2FsdDwvc3Bhbj5cbiAgICAgICAgICAgIGZpbHRlclxuICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgPGJ1dHRvbiAoY2xpY2spPVwic3VtbWFyaXNlRGF0YSgpXCJcbiAgICAgICAgICAgICAgICB0aXRsZT1cIlN1bW1hcmlzZSB0aGlzIGRhdGEgdG8gcHJvZHVjZSBhZ2dyZWdhdGVkIHRvdGFscywgc3VtcyBhbmQgb3RoZXIgZGVyaXZhdGlvbnNcIlxuICAgICAgICAgICAgICAgIGNsYXNzPVwidy0yMCBmbGV4IGZsZXgtY29sIGl0ZW1zLWNlbnRlciBqdXN0aWZ5LWNlbnRlciBweS0xIHB4LTIgdGV4dC14cyB0ZXh0LWdyYXktNjAwIGN1cnNvci1wb2ludGVyIGhvdmVyOmJnLWdyYXktMTAwXCI+XG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cIm1hdGVyaWFsLXN5bWJvbHMtb3V0bGluZWQgdGV4dC14bFwiPnBpdm90X3RhYmxlX2NoYXJ0PC9zcGFuPlxuICAgICAgICAgICAgc3VtbWFyaXNlXG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgICA8YnV0dG9uICpuZ0lmPVwiIWRhdGFzZXRFZGl0b3JTaW1wbGVNb2RlXCIgKGNsaWNrKT1cImpvaW5EYXRhKClcIlxuICAgICAgICAgICAgICAgIHRpdGxlPVwiSm9pbiBhbm90aGVyIGRhdGEgc2V0IHRvIHRoZSBjdXJyZW50IGRhdGFzZXRcIlxuICAgICAgICAgICAgICAgIGNsYXNzPVwidy0yMCBmbGV4IGZsZXgtY29sIGl0ZW1zLWNlbnRlciBqdXN0aWZ5LWNlbnRlciBweS0xIHB4LTIgdGV4dC14cyB0ZXh0LWdyYXktNjAwIGN1cnNvci1wb2ludGVyIGhvdmVyOmJnLWdyYXktMTAwXCI+XG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cIm1hdGVyaWFsLXN5bWJvbHMtb3V0bGluZWQgdGV4dC14bFwiPm1lcmdlX3R5cGU8L3NwYW4+XG4gICAgICAgICAgICBqb2luXG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiZGl2aWRlclwiPjwvZGl2PlxuICAgICAgICA8YnV0dG9uIChjbGljayk9XCJjcmVhdGVGb3JtdWxhKClcIlxuICAgICAgICAgICAgICAgIHRpdGxlPVwiQ3JlYXRlIGEgZm9ybXVsYSBjb2x1bW4gdXNpbmcgYW4gZXhwcmVzc2lvbiBiYXNlZCBvbiBvdGhlciBjb2x1bW5zXCJcbiAgICAgICAgICAgICAgICBjbGFzcz1cInctMjAgZmxleCBmbGV4LWNvbCBpdGVtcy1jZW50ZXIganVzdGlmeS1jZW50ZXIgcHktMSBweC0yIHRleHQteHMgdGV4dC1ncmF5LTYwMCBjdXJzb3ItcG9pbnRlciBob3ZlcjpiZy1ncmF5LTEwMFwiPlxuICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJtYXRlcmlhbC1zeW1ib2xzLW91dGxpbmVkIHRleHQteGxcIj5mdW5jdGlvbnM8L3NwYW4+XG4gICAgICAgICAgICBmb3JtdWxhXG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgICA8YnV0dG9uIChjbGljayk9XCJlZGl0Q29sdW1uU2V0dGluZ3MoKVwiXG4gICAgICAgICAgICAgICAgdGl0bGU9XCJTd2l0Y2ggb24gYW5kIG9mZiBjb2x1bW5zIGZvciBkaXNwbGF5XCJcbiAgICAgICAgICAgICAgICBjbGFzcz1cInctMjAgZmxleCBmbGV4LWNvbCBpdGVtcy1jZW50ZXIganVzdGlmeS1jZW50ZXIgcHktMSBweC0yIHRleHQteHMgdGV4dC1ncmF5LTYwMCBjdXJzb3ItcG9pbnRlciBob3ZlcjpiZy1ncmF5LTEwMFwiPlxuICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJtYXRlcmlhbC1zeW1ib2xzLW91dGxpbmVkIHRleHQteGxcIj50YWJsZV9jaGFydDwvc3Bhbj5cbiAgICAgICAgICAgIGNvbHVtbnNcbiAgICAgICAgPC9idXR0b24+XG4gICAgICAgIDxkaXYgKm5nSWY9XCIhZGF0YXNldEVkaXRvclNpbXBsZU1vZGVcIiBjbGFzcz1cImRpdmlkZXJcIj48L2Rpdj5cbiAgICAgICAgPGJ1dHRvbiAqbmdJZj1cIiFkYXRhc2V0RWRpdG9yU2ltcGxlTW9kZVwiIChjbGljayk9XCJhZGRQYXJhbWV0ZXIoKVwiXG4gICAgICAgICAgICAgICAgdGl0bGU9XCJBZGQgYSBwYXJhbWV0ZXIgdG8gdXNlIGluIGZpbHRlcnMsIGV4cHJlc3Npb25zIGV0Yy5cIlxuICAgICAgICAgICAgICAgIGNsYXNzPVwidy0yMCBmbGV4IGZsZXgtY29sIGl0ZW1zLWNlbnRlciBqdXN0aWZ5LWNlbnRlciBweS0xIHB4LTIgdGV4dC14cyB0ZXh0LWdyYXktNjAwIGN1cnNvci1wb2ludGVyIGhvdmVyOmJnLWdyYXktMTAwXCI+XG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cIm1hdGVyaWFsLXN5bWJvbHMtb3V0bGluZWQgdGV4dC14bFwiPnRleHRfZmllbGRzPC9zcGFuPlxuICAgICAgICAgICAgcGFyYW1ldGVyc1xuICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgPGJ1dHRvbiAqbmdJZj1cIiFkYXRhc2V0RWRpdG9yU2ltcGxlTW9kZVwiIChjbGljayk9XCJhZGRQYWdpbmdNYXJrZXIoKVwiXG4gICAgICAgICAgICAgICAgdGl0bGU9XCJJbnNlcnQgcGFnaW5nIG1hcmtlciB0byBsaW1pdCByZXN1bHRzIGF0IHRoaXMgc3RhZ2UgaW4gdGhlIHF1ZXJ5IGZsb3dcIlxuICAgICAgICAgICAgICAgIGNsYXNzPVwidy0yNCBmbGV4IGZsZXgtY29sIGl0ZW1zLWNlbnRlciBqdXN0aWZ5LWNlbnRlciBweS0xIHB4LTIgdGV4dC14cyB0ZXh0LWdyYXktNjAwIGN1cnNvci1wb2ludGVyIGhvdmVyOmJnLWdyYXktMTAwXCI+XG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cIm1hdGVyaWFsLXN5bWJvbHMtb3V0bGluZWQgdGV4dC14bFwiPnNraXBfbmV4dDwvc3Bhbj5cbiAgICAgICAgICAgIHBhZ2luZyBtYXJrZXJcbiAgICAgICAgPC9idXR0b24+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJkaXZpZGVyXCI+PC9kaXY+XG4gICAgICAgIDxidXR0b24gKGNsaWNrKT1cImV2YWx1YXRlRGF0YXNldCgpXCJcbiAgICAgICAgICAgICAgICB0aXRsZT1cIlJlbG9hZCB0aGlzIHF1ZXJ5IGJhc2VkIHVwb24gY2hhbmdlcyB5b3UgbWF5IGhhdmUgbWFkZVwiXG4gICAgICAgICAgICAgICAgY2xhc3M9XCJ3LTIwIGZsZXggZmxleC1jb2wgaXRlbXMtY2VudGVyIGp1c3RpZnktY2VudGVyIHB5LTEgcHgtMiB0ZXh0LXhzIHRleHQtZ3JheS02MDAgY3Vyc29yLXBvaW50ZXIgaG92ZXI6YmctZ3JheS0xMDBcIj5cbiAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwibWF0ZXJpYWwtc3ltYm9scy1vdXRsaW5lZCB0ZXh0LXhsXCI+c3luYzwvc3Bhbj5cbiAgICAgICAgICAgIHJlbG9hZFxuICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgPG5nLXRlbXBsYXRlIFtuZ0lmXT1cIiFkYXRhc2V0RWRpdG9yUmVhZG9ubHlcIj5cbiAgICAgICAgICAgIDxidXR0b24gW2Rpc2FibGVkXT1cIiFkYXRhc2V0SW5zdGFuY2VTdW1tYXJ5IHx8ICFkYXRhc2V0SW5zdGFuY2VTdW1tYXJ5LmlkXCIgKGNsaWNrKT1cInNoYXJlUXVlcnkoKVwiXG4gICAgICAgICAgICAgICAgICAgIHRpdGxlPVwiU2hhcmUgdGhpcyBxdWVyeSB3aXRoIG90aGVyIGFjY291bnQgaG9sZGVyc1wiXG4gICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiZGlzYWJsZWQ6b3BhY2l0eS01MCB3LTIwIGZsZXggZmxleC1jb2wgaXRlbXMtY2VudGVyIGp1c3RpZnktY2VudGVyIHB5LTEgcHgtMiB0ZXh0LXhzIHRleHQtZ3JheS02MDAgY3Vyc29yLXBvaW50ZXIgaG92ZXI6YmctZ3JheS0xMDBcIj5cbiAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cIm1hdGVyaWFsLXN5bWJvbHMtb3V0bGluZWQgdGV4dC14bFwiPnNoYXJlPC9zcGFuPlxuICAgICAgICAgICAgICAgIHNoYXJlXG4gICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgIDxidXR0b24gKGNsaWNrKT1cInNhdmVBc1F1ZXJ5KClcIlxuICAgICAgICAgICAgICAgICAgICB0aXRsZT1cIk1ha2UgYSBjb3B5IG9mIHRoaXMgcXVlcnlcIlxuICAgICAgICAgICAgICAgICAgICBjbGFzcz1cInctMjAgZmxleCBmbGV4LWNvbCBpdGVtcy1jZW50ZXIganVzdGlmeS1jZW50ZXIgcHktMSBweC0yIHRleHQteHMgdGV4dC1ncmF5LTYwMCBjdXJzb3ItcG9pbnRlciBob3ZlcjpiZy1ncmF5LTEwMFwiPlxuICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwibWF0ZXJpYWwtc3ltYm9scy1vdXRsaW5lZCB0ZXh0LXhsXCI+ZmlsZV9jb3B5PC9zcGFuPlxuICAgICAgICAgICAgICAgIGNvcHkgcXVlcnlcbiAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgPGJ1dHRvbiAqbmdJZj1cIiFkYXNoYm9hcmRMYXlvdXRTZXR0aW5ncyAmJiBkYXRhc2V0SW5zdGFuY2VTdW1tYXJ5LmlkXCIgKGNsaWNrKT1cInNhdmUoKVwiXG4gICAgICAgICAgICAgICAgICAgIGNsYXNzPVwidy0yMCBmbGV4IGZsZXgtY29sIGl0ZW1zLWNlbnRlciBqdXN0aWZ5LWNlbnRlciBweS0xIHB4LTIgdGV4dC14cyB0ZXh0LWdyYXktNjAwIGN1cnNvci1wb2ludGVyIGhvdmVyOmJnLWdyYXktMTAwXCI+XG4gICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJtYXRlcmlhbC1zeW1ib2xzLW91dGxpbmVkIHRleHQteGxcIj5zYXZlPC9zcGFuPlxuICAgICAgICAgICAgICAgIHNhdmVcbiAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgIDwvZGl2PlxuPC9kaXY+XG5cbjxkaXYgY2xhc3M9XCJjZWxsLWhlYWRlclwiPlxuICAgIDxkaXYgY2xhc3M9XCJ0cmFuc2Zvcm1hdGlvbi1saXN0aW5nIHBhcmFtZXRlci1saXN0aW5nXCIgKm5nSWY9XCJzaG93UGFyYW1ldGVycyB8fCBwYXJhbWV0ZXJWYWx1ZXMubGVuZ3RoXCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJsaXN0LXRpdGxlXCI+XG4gICAgICAgICAgICBQYXJhbWV0ZXJzXG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8ZGl2IGNsYXNzPVwiZmxleCBpdGVtcy1jZW50ZXIgZmxleC13cmFwXCI+XG4gICAgICAgICAgICA8bmctdGVtcGxhdGUgbmdGb3IgbGV0LXBhcmFtZXRlciBbbmdGb3JPZl09XCJwYXJhbWV0ZXJWYWx1ZXNcIiBsZXQtaT1pbmRleD5cblxuICAgICAgICAgICAgICAgIDxsYWJlbCBjbGFzcz1cInBsLTRcIj5cbiAgICAgICAgICAgICAgICAgICAge3sgcGFyYW1ldGVyLnRpdGxlIH19XG5cbiAgICAgICAgICAgICAgICAgICAgPGRpdiAqbmdJZj1cIihwYXJhbWV0ZXIudmFsdWUgfHwgJycpLnRvU3RyaW5nKCkuaW5jbHVkZXMoJ319JylcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtY2hpcCBjbGFzcz1cImJnLWdyYXktNTAgbWwtMlwiIHRpdGxlPVwiVXNpbmcgcGFyYW1ldGVyIHZhbHVlIGZyb20ge3twYXJhbWV0ZXIudmFsdWV9fVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJmbGV4IGl0ZW1zLWNlbnRlclwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cIm1hdGVyaWFsLXN5bWJvbHMtb3V0bGluZWQgdGV4dC14bCBtci0xIHRleHQtZ3JheS01MDBcIj5sYXllcnM8L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuICpuZ0lmPVwiZGFzaGJvYXJkUGFyYW1ldGVyc1twYXJhbWV0ZXIudmFsdWUucmVwbGFjZSgne3snLCAnJykucmVwbGFjZSgnfX0nLCAnJyldXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW2lubmVySFRNTF09XCJkYXNoYm9hcmRQYXJhbWV0ZXJzW3BhcmFtZXRlci52YWx1ZS5yZXBsYWNlKCd7eycsICcnKS5yZXBsYWNlKCd9fScsICcnKV0udmFsdWVcIj48L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuICpuZ0lmPVwiIWRhc2hib2FyZFBhcmFtZXRlcnNbcGFyYW1ldGVyLnZhbHVlLnJlcGxhY2UoJ3t7JywgJycpLnJlcGxhY2UoJ319JywgJycpXVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiZm9udC1tZWRpdW0gdGV4dC1vcmFuZ2UtNjAwXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBQYXJhbWV0ZXIgTm90IEZvdW5kICFcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiBtYXRDaGlwUmVtb3ZlIChjbGljayk9XCJwYXJhbWV0ZXIudmFsdWUgPSAnJ1wiIHRpdGxlPVwiXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtaWNvbj5jYW5jZWw8L21hdC1pY29uPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgICAgICAgICAgICAgPC9tYXQtY2hpcD5cbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG5cblxuICAgICAgICAgICAgICAgICAgICA8ZGl2ICpuZ0lmPVwiIShwYXJhbWV0ZXIudmFsdWUgfHwgJycpLnRvU3RyaW5nKCkuaW5jbHVkZXMoJ319JylcIiBjbGFzcz1cInBhcmFtZXRlci1pbnB1dFwiPlxuXG4gICAgICAgICAgICAgICAgICAgICAgICA8bmctdGVtcGxhdGUgW25nSWZdPVwiIXBhcmFtZXRlci5tdWx0aXBsZVwiPlxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPG5nLXRlbXBsYXRlIFtuZ0lmXT1cInBhcmFtZXRlci50eXBlID09PSAndGV4dCdcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0IGNsYXNzPVwicHItOFwiIHR5cGU9XCJ0ZXh0XCIgcGxhY2Vob2xkZXI9XCJFbnRlciB7e3BhcmFtZXRlci50aXRsZX19XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFsobmdNb2RlbCldPVwicGFyYW1ldGVyLnZhbHVlXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChrZXl1cC5lbnRlcik9XCJldmFsdWF0ZURhdGFzZXQodHJ1ZSlcIiByZXF1aXJlZCBhdXRvZm9jdXM+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bmctdGVtcGxhdGUgW25nSWZdPVwicGFyYW1ldGVyLnR5cGUgPT09ICdudW1lcmljJ1wiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgY2xhc3M9XCJwci04XCIgdHlwZT1cIm51bWJlclwiIHBsYWNlaG9sZGVyPVwiRW50ZXIge3twYXJhbWV0ZXIudGl0bGV9fVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cInBhcmFtZXRlci52YWx1ZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoa2V5dXAuZW50ZXIpPVwiZXZhbHVhdGVEYXRhc2V0KHRydWUpXCIgcmVxdWlyZWQgYXV0b2ZvY3VzPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPG5nLXRlbXBsYXRlIFtuZ0lmXT1cInBhcmFtZXRlci50eXBlID09PSAnbGlzdCdcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNlbGVjdCBjbGFzcz1cInByLTggcHktMS41IHBsLTEgc2VsZi1jZW50ZXJcIiBbKG5nTW9kZWwpXT1cInBhcmFtZXRlci52YWx1ZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGNoYW5nZSk9XCJldmFsdWF0ZURhdGFzZXQodHJ1ZSlcIiByZXF1aXJlZCBhdXRvZm9jdXM+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8b3B0aW9uIFt2YWx1ZV09XCJudWxsXCI+LS0gU2VsZWN0IFZhbHVlIC0tPC9vcHRpb24+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8b3B0aW9uICpuZ0Zvcj1cImxldCBpdGVtIG9mIHBhcmFtZXRlci5saXN0XCIgW3ZhbHVlXT1cIml0ZW0udmFsdWVcIj57eyBpdGVtLmxhYmVsIH19XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L29wdGlvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9zZWxlY3Q+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bmctdGVtcGxhdGUgW25nSWZdPVwicGFyYW1ldGVyLnR5cGUgPT09ICdkYXRlJyB8fCBwYXJhbWV0ZXIudHlwZSA9PT0gJ2RhdGV0aW1lJ1wiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bmctdGVtcGxhdGUgW25nSWZdPVwiIXBhcmFtZXRlci5fZGF0ZVR5cGVcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJmbGV4IGl0ZW1zLWNlbnRlciBtci04XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiAoY2xpY2spPVwiY2hhbmdlRGF0ZVR5cGUoJGV2ZW50LCBwYXJhbWV0ZXIsICdwaWNrZXInKVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImhvdmVyOmJnLWdyYXktNTAgdGV4dC1ncmF5LTgwMCBib3JkZXIgYm9yZGVyLWdyYXktMzAwIHB5LTAuNSBwci0yIHJvdW5kZWQgbXItMiBiZy13aGl0ZSBmbGV4IGl0ZW1zLWNlbnRlclwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LWljb24gY2xhc3M9XCJ0ZXh0LWJhc2VcIj5jYWxlbmRhcl9tb250aDwvbWF0LWljb24+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIERhdGUgUGlja2VyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiAoY2xpY2spPVwiY2hhbmdlRGF0ZVR5cGUoJGV2ZW50LCBwYXJhbWV0ZXIsICdwZXJpb2QnKVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImhvdmVyOmJnLWdyYXktNTAgdGV4dC1ncmF5LTgwMCBib3JkZXIgYm9yZGVyLWdyYXktMzAwIHB5LTAuNSBwci0yIHJvdW5kZWQgbXItMiBiZy13aGl0ZSBmbGV4IGl0ZW1zLWNlbnRlclwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LWljb24gY2xhc3M9XCJ0ZXh0LWJhc2VcIj5yZXN0b3JlPC9tYXQtaWNvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVGltZSBQZXJpb2RcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bmctdGVtcGxhdGUgW25nSWZdPVwicGFyYW1ldGVyLl9kYXRlVHlwZSA9PT0gJ3BpY2tlcidcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dCBbdHlwZV09XCJwYXJhbWV0ZXIudHlwZSA9PT0gJ2RhdGUnID8gJ2RhdGUnIDogJ2RhdGV0aW1lLWxvY2FsJ1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCJFbnRlciB7e3BhcmFtZXRlci50aXRsZX19XCIgWyhuZ01vZGVsKV09XCJwYXJhbWV0ZXIudmFsdWVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChrZXl1cC5lbnRlcik9XCJldmFsdWF0ZURhdGFzZXQodHJ1ZSlcIiByZXF1aXJlZCBhdXRvZm9jdXM+XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxhIChjbGljayk9XCJjaGFuZ2VEYXRlVHlwZSgkZXZlbnQsIHBhcmFtZXRlciwgJ3BlcmlvZCcpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdFRvb2x0aXA9XCJUaW1lIFBlcmlvZFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cIm1yLTEwIHRleHQtY2VudGVyIG1sLTIgaG92ZXI6YmctZ3JheS01MCB0ZXh0LWdyYXktODAwIGJvcmRlciBib3JkZXItZ3JheS0zMDAgcHktMC41IHByLTAuNSByb3VuZGVkIG1yLTIgYmctd2hpdGUgZmxleCBpdGVtcy1jZW50ZXJcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LWljb24gY2xhc3M9XCJ0ZXh0LWJhc2VcIj5yZXN0b3JlPC9tYXQtaWNvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvYT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG5nLXRlbXBsYXRlIFtuZ0lmXT1cInBhcmFtZXRlci5fZGF0ZVR5cGUgPT09ICdwZXJpb2QnXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZmxleCBpdGVtcy1jZW50ZXJcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgI3BlcmlvZFZhbHVlIHR5cGU9XCJudW1iZXJcIiBwbGFjZWhvbGRlcj1cIk5vLlwiIHJlcXVpcmVkIGF1dG9mb2N1c1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cInctMTYgbXItMlwiIG1pbj1cIjBcIiBbdmFsdWVdPVwicGFyYW1ldGVyLl9wZXJpb2RWYWx1ZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChjaGFuZ2UpPVwidXBkYXRlUGVyaW9kVmFsdWUocGVyaW9kVmFsdWUudmFsdWUsIHBlcmlvZC52YWx1ZSwgcGFyYW1ldGVyKVwiPlxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNlbGVjdCBjbGFzcz1cInBhcmFtLXBlcmlvZC1waWNrZXIgbXItMlwiIFt2YWx1ZV09XCJwYXJhbWV0ZXIuX3BlcmlvZCB8fCAnREFZUydcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI3BlcmlvZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGNoYW5nZSk9XCJ1cGRhdGVQZXJpb2RWYWx1ZShwZXJpb2RWYWx1ZS52YWx1ZSwgcGVyaW9kLnZhbHVlLCBwYXJhbWV0ZXIpXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxvcHRpb24gdmFsdWU9XCJEQVlTXCI+RGF5czwvb3B0aW9uPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8b3B0aW9uIHZhbHVlPVwiSE9VUlNcIj5Ib3Vyczwvb3B0aW9uPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvc2VsZWN0PlxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdj5BZ288L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8YSAoY2xpY2spPVwiY2hhbmdlRGF0ZVR5cGUoJGV2ZW50LCBwYXJhbWV0ZXIsICdwaWNrZXInKVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRUb29sdGlwPVwiRGF0ZSBQaWNrZXJcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJtci0xMCB0ZXh0LWNlbnRlciBtbC0yIGhvdmVyOmJnLWdyYXktNTAgdGV4dC1ncmF5LTgwMCBib3JkZXIgYm9yZGVyLWdyYXktMzAwIHB5LTAuNSBwci0wLjUgcm91bmRlZCBtci0yIGJnLXdoaXRlIGZsZXggaXRlbXMtY2VudGVyXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1pY29uIGNsYXNzPVwidGV4dC1iYXNlXCI+Y2FsZW5kYXJfbW9udGg8L21hdC1pY29uPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9hPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bmctdGVtcGxhdGUgW25nSWZdPVwicGFyYW1ldGVyLnR5cGUgPT09ICdib29sZWFuJ1wiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LXNsaWRlLXRvZ2dsZSBjbGFzcz1cInByLThcIiBjb2xvcj1cInByaW1hcnlcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbY2hlY2tlZF09XCJwYXJhbWV0ZXIudmFsdWVcIiAoY2hhbmdlKT1cImJvb2xlYW5VcGRhdGUoJGV2ZW50LCBwYXJhbWV0ZXIpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVxdWlyZWQ+PC9tYXQtc2xpZGUtdG9nZ2xlPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuXG4gICAgICAgICAgICAgICAgICAgICAgICA8bmctdGVtcGxhdGUgW25nSWZdPVwicGFyYW1ldGVyLm11bHRpcGxlXCI+XG5cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtY2hpcC1ncmlkIGNsYXNzPVwicGwtMlwiICNjaGlwR3JpZCBhcmlhLWxhYmVsPVwiRW50ZXIgdmFsdWVzXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtY2hpcC1yb3cgKm5nRm9yPVwibGV0IHBhcmFtVmFsdWUgb2YgcGFyYW1ldGVyLnZhbHVlXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImJnLXdoaXRlIG1yLTJcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChyZW1vdmVkKT1cInJlbW92ZVBhcmFtZXRlclZhbHVlKHBhcmFtZXRlciwgcGFyYW1WYWx1ZSlcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt7cGFyYW1WYWx1ZX19XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIG1hdENoaXBSZW1vdmUgW2F0dHIuYXJpYS1sYWJlbF09XCIncmVtb3ZlICcgKyBwYXJhbVZhbHVlXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1pY29uPmNhbmNlbDwvbWF0LWljb24+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9tYXQtY2hpcC1yb3c+XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG5nLXRlbXBsYXRlIFtuZ0lmXT1cInBhcmFtZXRlci50eXBlID09PSAndGV4dCdcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dCBjbGFzcz1cInByLTggcHktMSBzZWxmLWNlbnRlclwiIHR5cGU9XCJ0ZXh0XCIgcGxhY2Vob2xkZXI9XCJFbnRlciB7e3BhcmFtZXRlci50aXRsZX19XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXF1aXJlZCBhdXRvZm9jdXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbWF0Q2hpcElucHV0Rm9yXT1cImNoaXBHcmlkXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbWF0Q2hpcElucHV0U2VwYXJhdG9yS2V5Q29kZXNdPVwiW0VOVEVSLCBDT01NQV1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFttYXRDaGlwSW5wdXRBZGRPbkJsdXJdPVwidHJ1ZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKG1hdENoaXBJbnB1dFRva2VuRW5kKT1cImFkZFBhcmFtZXRlclZhbHVlKHBhcmFtZXRlciwgJGV2ZW50KVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bmctdGVtcGxhdGUgW25nSWZdPVwicGFyYW1ldGVyLnR5cGUgPT09ICdudW1lcmljJ1wiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0IGNsYXNzPVwicHItOFwiIHR5cGU9XCJudW1iZXJcIiBwbGFjZWhvbGRlcj1cIkVudGVyIHt7cGFyYW1ldGVyLnRpdGxlfX1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcXVpcmVkIGF1dG9mb2N1c1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFttYXRDaGlwSW5wdXRGb3JdPVwiY2hpcEdyaWRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFttYXRDaGlwSW5wdXRTZXBhcmF0b3JLZXlDb2Rlc109XCJbRU5URVIsIENPTU1BXVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW21hdENoaXBJbnB1dEFkZE9uQmx1cl09XCJ0cnVlXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAobWF0Q2hpcElucHV0VG9rZW5FbmQpPVwiYWRkUGFyYW1ldGVyVmFsdWUocGFyYW1ldGVyLCAkZXZlbnQpXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxuZy10ZW1wbGF0ZSBbbmdJZl09XCJwYXJhbWV0ZXIudHlwZSA9PT0gJ2xpc3QnXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c2VsZWN0IGNsYXNzPVwicHItOCBweS0xLjUgcGwtMSBzZWxmLWNlbnRlclwiIG1hdE5hdGl2ZUNvbnRyb2xcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGNoYW5nZSk9XCJhZGRQYXJhbWV0ZXJWYWx1ZShwYXJhbWV0ZXIsICRldmVudClcIiByZXF1aXJlZCBhdXRvZm9jdXM+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG9wdGlvbiBbdmFsdWVdPVwibnVsbFwiPi0tIFNlbGVjdCBWYWx1ZSAtLTwvb3B0aW9uPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxvcHRpb24gKm5nRm9yPVwibGV0IGl0ZW0gb2YgcGFyYW1ldGVyLmxpc3RcIiBbdmFsdWVdPVwiaXRlbS52YWx1ZVwiPnt7IGl0ZW0ubGFiZWwgfX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L29wdGlvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvc2VsZWN0PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9tYXQtY2hpcC1ncmlkPlxuXG5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG5cblxuXG4gICAgICAgICAgICAgICAgICAgICAgICA8bmctdGVtcGxhdGUgW25nSWZdPVwiIXBhcmFtZXRlci5fbG9ja2VkXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiBtYXQtaWNvbi1idXR0b24gW21hdE1lbnVUcmlnZ2VyRm9yXT1cInBhcmFtTWVudVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LWljb24+c2V0dGluZ3M8L21hdC1pY29uPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtbWVudSAjcGFyYW1NZW51PVwibWF0TWVudVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIG1hdC1tZW51LWl0ZW0gKGNsaWNrKT1cImFkZFBhcmFtZXRlcihwYXJhbWV0ZXIsIGkpXCI+RWRpdCBQYXJhbWV0ZXI8L2J1dHRvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiBtYXQtbWVudS1pdGVtIChjbGljayk9XCJyZW1vdmVQYXJhbWV0ZXIocGFyYW1ldGVyKVwiPlJlbW92ZSBQYXJhbWV0ZXI8L2J1dHRvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L21hdC1tZW51PlxuICAgICAgICAgICAgICAgICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxuZy10ZW1wbGF0ZSBbbmdJZl09XCJPYmplY3Qua2V5cyhkYXNoYm9hcmRQYXJhbWV0ZXJzIHx8IHt9KS5sZW5ndGhcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIG1hdC1pY29uLWJ1dHRvbiBbbWF0TWVudVRyaWdnZXJGb3JdPVwiZGFzaFBhcmFtTWVudVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aXRsZT1cIkJpbmQgdGhpcyBwYXJhbWV0ZXIgdmFsdWUgdG8gYW5vdGhlclwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LWljb24+dGV4dF9maWVsZHM8L21hdC1pY29uPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtbWVudSAjZGFzaFBhcmFtTWVudT1cIm1hdE1lbnVcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiBtYXQtbWVudS1pdGVtICpuZ0Zvcj1cImxldCBkYXNoUGFyYW1LZXkgb2YgT2JqZWN0LmtleXMoZGFzaGJvYXJkUGFyYW1ldGVycylcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJzZXREYXNoYm9hcmRQYXJhbWV0ZXIocGFyYW1ldGVyLCBkYXNoYm9hcmRQYXJhbWV0ZXJzW2Rhc2hQYXJhbUtleV0ubmFtZSlcIj57eyBkYXNoYm9hcmRQYXJhbWV0ZXJzW2Rhc2hQYXJhbUtleV0udGl0bGUgfX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9tYXQtbWVudT5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgICAgICAgICAgPC9sYWJlbD5cblxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJkaXZpZGVyIG1sLTJcIiAqbmdJZj1cInBhcmFtZXRlclZhbHVlcy5sZW5ndGhcIj48L2Rpdj5cblxuICAgICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgICAgIDxidXR0b24gbWF0LWljb24tYnV0dG9uIGNvbG9yPVwicHJpbWFyeVwiIGNsYXNzPVwibXgtMlwiIChjbGljayk9XCJhZGRQYXJhbWV0ZXIoKVwiPlxuICAgICAgICAgICAgICAgIDxtYXQtaWNvbj5hZGRfY2lyY2xlPC9tYXQtaWNvbj5cbiAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgKGNsaWNrKT1cImV2YWx1YXRlRGF0YXNldCh0cnVlKVwiICpuZ0lmPVwicGFyYW1ldGVyVmFsdWVzLmxlbmd0aFwiXG4gICAgICAgICAgICAgICAgICAgIGNsYXNzPVwibXItMiBmbGV4IGl0ZW1zLWNlbnRlciB3aGl0ZXNwYWNlLW5vd3JhcCBqdXN0aWZ5LWNlbnRlciBweC00IHB5LTEgYm9yZGVyIGJvcmRlci10cmFuc3BhcmVudCB0ZXh0LXNtIHJvdW5kZWQtbWQgc2hhZG93LXNtIHRleHQtd2hpdGUgYmctcHJpbWFyeSBmb2N1czpvdXRsaW5lLW5vbmVcIj5cbiAgICAgICAgICAgICAgICBBcHBseSBQYXJhbWV0ZXJzXG4gICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG48L2Rpdj5cblxuPGRpdiBjbGFzcz1cImNlbGwtaGVhZGVyXCI+XG4gICAgPGRpdiBjbGFzcz1cInRyYW5zZm9ybWF0aW9uLWxpc3RpbmcgcHktMlwiICpuZ0lmPVwidGVybWluYXRpbmdUcmFuc2Zvcm1hdGlvbnMubGVuZ3RoXCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJsaXN0LXRpdGxlXCI+XG4gICAgICAgICAgICBUcmFuc2Zvcm1hdGlvbnNcbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJleGFtcGxlLWxpc3QgZmxleCBmbGV4LXdyYXBcIiBjZGtEcm9wTGlzdEdyb3VwPlxuICAgICAgICAgICAgPG5nLXRlbXBsYXRlIG5nRm9yIGxldC10cmFuc2Zvcm1hdGlvbiBbbmdGb3JPZl09XCJ0ZXJtaW5hdGluZ1RyYW5zZm9ybWF0aW9uc1wiIGxldC1pPVwiaW5kZXhcIj5cbiAgICAgICAgICAgICAgICA8ZGl2IGNka0Ryb3BMaXN0IChjZGtEcm9wTGlzdERyb3BwZWQpPVwiZHJvcCgkZXZlbnQpXCIgY2RrRHJvcExpc3RPcmllbnRhdGlvbj1cImhvcml6b250YWxcIlxuICAgICAgICAgICAgICAgICAgICAgW2Nka0Ryb3BMaXN0RGF0YV09XCJ7aXRlbTp0cmFuc2Zvcm1hdGlvbixpbmRleDppfVwiICpuZ0lmPVwiIXRyYW5zZm9ybWF0aW9uLmhpZGRlblwiPlxuICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZmxleCBpdGVtcy1jZW50ZXJcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJuZXctdHJhbnNmb3JtYXRpb24gZmxleCBpdGVtcy1jZW50ZXIganVzdGlmeS1jZW50ZXIgdy02IGgtNlwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxhIFttYXRNZW51VHJpZ2dlckZvcl09XCJhZGRUcmFuc2Zvcm1hdGlvblwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJpdGVtcy1jZW50ZXIgYWRkLXRyYW5zZm9ybWF0aW9uIHRleHQtcHJpbWFyeVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LWljb24gY2xhc3M9XCJmbGV4IGl0ZW1zLWNlbnRlciB3LTUgaC01IHRleHQteGxcIj5hZGRfY2lyY2xlPC9tYXQtaWNvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2E+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1tZW51ICNhZGRUcmFuc2Zvcm1hdGlvbj1cIm1hdE1lbnVcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiBtYXQtbWVudS1pdGVtIChjbGljayk9XCJpbnNlcnRUcmFuc2Zvcm1hdGlvbihpLCAnY29sdW1ucycsIHRyYW5zZm9ybWF0aW9uKVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSW5zZXJ0IENvbHVtbiBUcmFuc2Zvcm1hdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiBtYXQtbWVudS1pdGVtIChjbGljayk9XCJpbnNlcnRUcmFuc2Zvcm1hdGlvbihpLCAnZm9ybXVsYScsIHRyYW5zZm9ybWF0aW9uKVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSW5zZXJ0IEZvcm11bGEgVHJhbnNmb3JtYXRpb25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b24gbWF0LW1lbnUtaXRlbSAoY2xpY2spPVwiaW5zZXJ0VHJhbnNmb3JtYXRpb24oaSwgJ2pvaW4nLCB0cmFuc2Zvcm1hdGlvbilcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEluc2VydCBKb2luIFRyYW5zZm9ybWF0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIG1hdC1tZW51LWl0ZW0gKGNsaWNrKT1cImluc2VydFRyYW5zZm9ybWF0aW9uKGksICdzdW1tYXJpc2UnLCB0cmFuc2Zvcm1hdGlvbilcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEluc2VydCBTdW1tYXJpc2UgVHJhbnNmb3JtYXRpb25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b24gbWF0LW1lbnUtaXRlbSAoY2xpY2spPVwiaW5zZXJ0VHJhbnNmb3JtYXRpb24oaSwgJ2ZpbHRlcicsIHRyYW5zZm9ybWF0aW9uKVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSW5zZXJ0IEZpbHRlciBUcmFuc2Zvcm1hdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L21hdC1tZW51PlxuICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2RrRHJhZyBjbGFzcz1cInBsLTAgZXhhbXBsZS1ib3ggYmFkZ2UtaXRlbSB3LWF1dG8gbS0wXCIgY2RrT3ZlcmxheU9yaWdpblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAjdHJpZ2dlcj1cImNka092ZXJsYXlPcmlnaW5cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbmdDbGFzc109XCJ7YWN0aXZlOiB0cmFuc2Zvcm1hdGlvbi5fYWN0aXZlLCAnZXhjbHVkZSBiZy1vcmFuZ2UtNTAgYm9yZGVyLW9yYW5nZS0yMDAnOiAhIXRyYW5zZm9ybWF0aW9uLmV4Y2x1ZGUsICdiZy1pbmRpZ28tNTAgYm9yZGVyLWluZGlnby0yMDAnOiAodHJhbnNmb3JtYXRpb24udHlwZSA9PT0gJ2ZpbHRlcicgJiYgdHJhbnNmb3JtYXRpb24uaGlkZSA9PT0gZmFsc2UpfVwiPlxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiBjbGFzcz1cIi1tdC0wLjVcIiB0aXRsZT1cIlNob3cgdHJhbnNmb3JtYXRpb24gZGV0YWlsc1wiIG1hdC1pY29uLWJ1dHRvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cInNob3dUcmFuc2Zvcm1hdGlvbkRldGFpbCh0cmFuc2Zvcm1hdGlvbilcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJtYXRlcmlhbC1zeW1ib2xzLW91dGxpbmVkIG1sLTEgdGV4dC14bFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpuZ0lmPVwidHJhbnNmb3JtYXRpb24udHlwZSA9PT0gJ2NvbHVtbnMnXCI+dGFibGVfY2hhcnQ8L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwibWF0ZXJpYWwtc3ltYm9scy1vdXRsaW5lZCB0ZXh0LXhsXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKm5nSWY9XCJ0cmFuc2Zvcm1hdGlvbi50eXBlID09PSAnZm9ybXVsYSdcIj5mdW5jdGlvbnM8L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwibWF0ZXJpYWwtc3ltYm9scy1vdXRsaW5lZCB0ZXh0LXhsXCIgKm5nSWY9XCJ0cmFuc2Zvcm1hdGlvbi50eXBlID09PSAnam9pbidcIj5tZXJnZV90eXBlPC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cIm1hdGVyaWFsLXN5bWJvbHMtb3V0bGluZWQgbWwtMSB0ZXh0LXhsXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKm5nSWY9XCJ0cmFuc2Zvcm1hdGlvbi50eXBlID09PSAnc3VtbWFyaXNlJ1wiPnBpdm90X3RhYmxlX2NoYXJ0PC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cIm1hdGVyaWFsLXN5bWJvbHMtb3V0bGluZWQgdGV4dC14bFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpuZ0lmPVwidHJhbnNmb3JtYXRpb24udHlwZSA9PT0gJ2ZpbHRlcidcIj5maWx0ZXJfYWx0PC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJ3aGl0ZXNwYWNlLW5vd3JhcCBjdXJzb3ItcG9pbnRlclwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cImVkaXRUZXJtaW5hdGluZ1RyYW5zZm9ybWF0aW9uKHRyYW5zZm9ybWF0aW9uKVwiPnt7IHRyYW5zZm9ybWF0aW9uLl9sYWJlbCB9fTwvc3Bhbj5cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxuZy10ZW1wbGF0ZSBbbmdJZl09XCJ0cmFuc2Zvcm1hdGlvbi5leGNsdWRlXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b24gY2xhc3M9XCItbWwtMVwiIFt0aXRsZV09XCInUmUtZW5hYmxlIHRoaXMgdHJhbnNmb3JtYXRpb24nXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXQtaWNvbi1idXR0b24gKGNsaWNrKT1cImRpc2FibGVUcmFuc2Zvcm1hdGlvbih0cmFuc2Zvcm1hdGlvbiwgaSlcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtaWNvbiBjbGFzcz1cInRleHQtb3JhbmdlLTQwMFwiPnJlcGxheTwvbWF0LWljb24+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPG5nLXRlbXBsYXRlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtuZ0lmXT1cIiF0cmFuc2Zvcm1hdGlvbi5leGNsdWRlICYmIGkgKyAxID09PSB0ZXJtaW5hdGluZ1RyYW5zZm9ybWF0aW9ucy5sZW5ndGhcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiBjbGFzcz1cIi1tbC0xXCIgW3RpdGxlXT1cIidEaXNhYmxlIHRyYW5zZm9ybWF0aW9uJ1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0LWljb24tYnV0dG9uIChjbGljayk9XCJkaXNhYmxlVHJhbnNmb3JtYXRpb24odHJhbnNmb3JtYXRpb24sIGkpXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LWljb24+YmxvY2s8L21hdC1pY29uPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxuZy10ZW1wbGF0ZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbmdJZl09XCIhdHJhbnNmb3JtYXRpb24uZXhjbHVkZSAmJiBpICsgMSAhPT0gdGVybWluYXRpbmdUcmFuc2Zvcm1hdGlvbnMubGVuZ3RoXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b24gY2xhc3M9XCItbWwtMVwiIFttYXRNZW51VHJpZ2dlckZvcl09XCJkaXNhYmxlTWVudVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW3RpdGxlXT1cIidEaXNhYmxlIHRyYW5zZm9ybWF0aW9uJ1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0LWljb24tYnV0dG9uPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1pY29uPmJsb2NrPC9tYXQtaWNvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtbWVudSAjZGlzYWJsZU1lbnU9XCJtYXRNZW51XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIG1hdC1tZW51LWl0ZW0gKGNsaWNrKT1cImRpc2FibGVUcmFuc2Zvcm1hdGlvbih0cmFuc2Zvcm1hdGlvbiwgaSlcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBEaXNhYmxlIHRoaXMgdHJhbnNmb3JtYXRpb25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiBtYXQtbWVudS1pdGVtIChjbGljayk9XCJleGNsdWRlVXBzdHJlYW1UcmFuc2Zvcm1hdGlvbnModHJhbnNmb3JtYXRpb24pXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRGlzYWJsZSBzdWJzZXF1ZW50IHRyYW5zZm9ybWF0aW9uKHMpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9tYXQtbWVudT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiBjbGFzcz1cIi1tbC0xXCIgdGl0bGU9XCJSZW1vdmUgdGhpcyB0cmFuc2Zvcm1hdGlvblwiIG1hdC1pY29uLWJ1dHRvbiBjb2xvcj1cInByaW1hcnlcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cInJlbW92ZVRyYW5zZm9ybWF0aW9uKHRyYW5zZm9ybWF0aW9uLCB0cnVlLCBudWxsLCB0cmFuc2Zvcm1hdGlvbi5fYWN0aXZlKVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LWljb24+Y2FuY2VsPC9tYXQtaWNvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgPG5nLXRlbXBsYXRlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2RrQ29ubmVjdGVkT3ZlcmxheVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtjZGtDb25uZWN0ZWRPdmVybGF5T3JpZ2luXT1cInRyaWdnZXJcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtjZGtDb25uZWN0ZWRPdmVybGF5T3Blbl09XCJ0cmFuc2Zvcm1hdGlvbi5fc2hvd0RldGFpbFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJwLTQgdy05NiBiZy13aGl0ZSBzaGFkb3cgcm91bmRlZFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bmctdGVtcGxhdGUgW25nSWZdPVwidHJhbnNmb3JtYXRpb24udHlwZSA9PT0gJ3N1bW1hcmlzZSdcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxwIGNsYXNzPVwidGV4dC1zbSB0ZXh0LWdyYXktNzAwIG1iLTBcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8Yj5TRUxFQ1QmbmJzcDs8L2I+PHNwYW5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqbmdGb3I9XCJsZXQgZXhwcmVzc2lvbiBvZiB0cmFuc2Zvcm1hdGlvbi5jb25maWcuZXhwcmVzc2lvbnM7IGxldCBpID0gaW5kZXhcIj48c3BhblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpuZ0lmPVwiaSA+IDBcIj4sIDwvc3Bhbj57eyBleHByZXNzaW9uLmN1c3RvbUV4cHJlc3Npb24gfHwgZXhwcmVzc2lvbi5leHByZXNzaW9uVHlwZSArICcoJyArIChleHByZXNzaW9uLmZpZWxkTmFtZSB8fCAnJykgKyAnKScgfX08L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG5nLXRlbXBsYXRlIFtuZ0lmXT1cInRyYW5zZm9ybWF0aW9uLmNvbmZpZy5zdW1tYXJpc2VGaWVsZE5hbWVzLmxlbmd0aFwiPjxicj48Yj5HUk9VUFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBCWSZuYnNwOzwvYj4ge3sgdHJhbnNmb3JtYXRpb24uY29uZmlnLnN1bW1hcmlzZUZpZWxkTmFtZXMuam9pbignLCAnKSB9fVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L3A+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxuZy10ZW1wbGF0ZSBbbmdJZl09XCJ0cmFuc2Zvcm1hdGlvbi50eXBlID09PSAnZm9ybXVsYSdcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJ0ZXh0LXNtIHRleHQtZ3JheS03MDAgbWItMFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxiPkVYUFJFU1NJT048L2I+Jm5ic3A7e3sgZGVjb2RlVVJJQ29tcG9uZW50KHRyYW5zZm9ybWF0aW9uLmNvbmZpZy5leHByZXNzaW9uc1swXS5leHByZXNzaW9uKSB9fVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxuZy10ZW1wbGF0ZSBbbmdJZl09XCJ0cmFuc2Zvcm1hdGlvbi50eXBlID09PSAnY29sdW1ucydcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJ0ZXh0LXNtIHRleHQtZ3JheS03MDAgbWItMFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxiPkNPTFVNTlM8L2I+Jm5ic3A7e3sgXy5tYXAodHJhbnNmb3JtYXRpb24uY29uZmlnLmNvbHVtbnMsICd0aXRsZScpLmpvaW4oJywgJykgfX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bmctdGVtcGxhdGUgW25nSWZdPVwidHJhbnNmb3JtYXRpb24udHlwZSA9PT0gJ2pvaW4nXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwidGV4dC1zbSB0ZXh0LWdyYXktNzAwIG1iLTBcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8Yj5KT0lOXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIENPTFVNTlM8L2I+Jm5ic3A7e3sgXy5tYXAodHJhbnNmb3JtYXRpb24uY29uZmlnLmpvaW5Db2x1bW5zLCAndGl0bGUnKS5qb2luKCcsICcpIH19XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG5nLXRlbXBsYXRlIFtuZ0lmXT1cInRyYW5zZm9ybWF0aW9uLnR5cGUgPT09ICdmaWx0ZXInXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2ICpuZ0Zvcj1cImxldCBmaWx0ZXIgb2YgdHJhbnNmb3JtYXRpb24uY29uZmlnLmZpbHRlcnNcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cInRleHQtc20gdGV4dC1ncmF5LTcwMCBtYi0wXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGI+RklMVEVSPC9iPiZuYnNwO3t7IGZpbHRlci5saHNFeHByZXNzaW9uIH19Jm5ic3A7PGI+e3sgZmlsdGVyLmZpbHRlclR5cGUgfX08L2I+Jm5ic3A7e3sgZmlsdGVyLnJoc0V4cHJlc3Npb24gfX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgICAgICAgICpuZ0lmPVwiXy5zb21lKHRlcm1pbmF0aW5nVHJhbnNmb3JtYXRpb25zLCB7ZXhjbHVkZTogdHJ1ZX0pICYmIGkgPT09IHRlcm1pbmF0aW5nVHJhbnNmb3JtYXRpb25zLmxlbmd0aCAtIDFcIlxuICAgICAgICAgICAgICAgICAgICBjbGFzcz1cIm1sLTQgZmxleCBpdGVtcy1jZW50ZXIgYm9yZGVyLW5vbmUgYmctcHJpbWFyeSB0ZXh0LXNtIHJvdW5kZWQtbWQgdGV4dC13aGl0ZSBwci0yIHBsLTEgcHktMC41XCJcbiAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cImVuYWJsZUFsbFRyYW5zZm9ybWF0aW9uKClcIj5cbiAgICAgICAgICAgICAgICAgICAgPG1hdC1pY29uIGNsYXNzPVwibXItMSB0ZXh0LWJhc2VcIj5yZXBsYXk8L21hdC1pY29uPlxuICAgICAgICAgICAgICAgICAgICBFbmFibGUgQWxsXG4gICAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuXG4gICAgICAgIDwvZGl2PlxuXG4gICAgPC9kaXY+XG48L2Rpdj5cblxuPGRpdiBjbGFzcz1cImNlbGwtaGVhZGVyXCI+XG4gICAgPGRpdiBjbGFzcz1cInRyYW5zZm9ybWF0aW9uLWxpc3RpbmcgcHktMiBmaWx0ZXJzLWxpc3RcIlxuICAgICAgICAgKm5nSWY9XCJfLmZpbHRlcihkYXRhc2V0SW5zdGFuY2VTdW1tYXJ5LnRyYW5zZm9ybWF0aW9uSW5zdGFuY2VzLCB7dHlwZTogJ2ZpbHRlcicsIGhpZGU6IGZhbHNlfSkubGVuZ3RoXCI+XG4gICAgICAgIDxhIGNsYXNzPVwibGlzdC10aXRsZSBmbGV4IGl0ZW1zLWNlbnRlclwiIChjbGljayk9XCJzaG93RmlsdGVycyA9ICFzaG93RmlsdGVyc1wiPlxuICAgICAgICAgICAgRmlsdGVycyZuYnNwO1xuICAgICAgICAgICAgPG1hdC1pY29uICpuZ0lmPVwiIXNob3dGaWx0ZXJzXCI+ZXhwYW5kX21vcmU8L21hdC1pY29uPlxuICAgICAgICAgICAgPG1hdC1pY29uICpuZ0lmPVwic2hvd0ZpbHRlcnNcIj5leHBhbmRfbGVzczwvbWF0LWljb24+XG4gICAgICAgIDwvYT5cbiAgICAgICAgPG5nLXRlbXBsYXRlIG5nRm9yIGxldC1maWx0ZXJUcmFuc2Zvcm1hdGlvblxuICAgICAgICAgICAgICAgICAgICAgW25nRm9yT2ZdPVwiXy5maWx0ZXIoZGF0YXNldEluc3RhbmNlU3VtbWFyeS50cmFuc2Zvcm1hdGlvbkluc3RhbmNlcywge3R5cGU6ICdmaWx0ZXInLCBoaWRlOiBmYWxzZX0pXCI+XG5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJiYWRnZS1pdGVtIHBsLTIgbXItMVwiICpuZ0lmPVwiXy5ldmVyeShmaWx0ZXJUcmFuc2Zvcm1hdGlvbi5jb25maWcuZmlsdGVyc1swXSlcIlxuICAgICAgICAgICAgICAgICAoY2xpY2spPVwic2hvd0ZpbHRlcnMgPSAhc2hvd0ZpbHRlcnNcIj5cbiAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cImN1cnNvci1wb2ludGVyXCIgW2lubmVySHRtbF09XCJnZXRGaWx0ZXJTdHJpbmcoZmlsdGVyVHJhbnNmb3JtYXRpb24uY29uZmlnKVwiPjwvc3Bhbj5cbiAgICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgPC9kaXY+XG48L2Rpdj5cblxuPGRpdiBjbGFzcz1cImRhdGFzZXQtZmlsdGVyc1wiIGlkPVwiZGF0YXNldEZpbHRlcnNcIlxuICAgICAqbmdJZj1cIl8uZmlsdGVyKGRhdGFzZXRJbnN0YW5jZVN1bW1hcnkudHJhbnNmb3JtYXRpb25JbnN0YW5jZXMsIHt0eXBlOiAnZmlsdGVyJywgaGlkZTogZmFsc2V9KS5sZW5ndGhcbiAgICAmJiBzaG93RmlsdGVyc1wiPlxuXG4gICAgPG5nLXRlbXBsYXRlIG5nRm9yIGxldC10cmFuc2Zvcm1hdGlvbiBbbmdGb3JPZl09XCJkYXRhc2V0SW5zdGFuY2VTdW1tYXJ5LnRyYW5zZm9ybWF0aW9uSW5zdGFuY2VzXCIgbGV0LWk9aW5kZXg+XG4gICAgICAgIDxuZy10ZW1wbGF0ZSBbbmdJZl09XCJ0cmFuc2Zvcm1hdGlvbi50eXBlID09PSAnZmlsdGVyJyAmJiB0cmFuc2Zvcm1hdGlvbi5oaWRlID09PSBmYWxzZVwiPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImRhdGFzZXQtZmlsdGVyIGJvcmRlci1iIGJvcmRlci1ncmF5LTIwMFwiPlxuXG4gICAgICAgICAgICAgICAgPGJ1dHRvbiBtYXQtc3Ryb2tlZC1idXR0b24gY2xhc3M9XCJtci0yIGJnLXdoaXRlIHJlbW92ZS1maWx0ZXJcIiBjb2xvcj1cIndhcm5cIlxuICAgICAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cInJlbW92ZVRyYW5zZm9ybWF0aW9uKHRyYW5zZm9ybWF0aW9uLCB0cnVlLCBpKVwiPlxuICAgICAgICAgICAgICAgICAgICBSZW1vdmUgRmlsdGVyXG4gICAgICAgICAgICAgICAgPC9idXR0b24+XG5cbiAgICAgICAgICAgICAgICA8a2ktZGF0YXNldC1maWx0ZXJzICpuZ0lmPVwiZmlsdGVyRmllbGRzLmxlbmd0aFwiIFtmaWx0ZXJGaWVsZHNdPVwiZmlsdGVyRmllbGRzXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtvcGVuU2lkZV09XCJvcGVuU2lkZVwiIFtwYXJhbWV0ZXJWYWx1ZXNdPVwiZmlsdGVyUGFyYW1ldGVyVmFsdWVzXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtmaWx0ZXJKdW5jdGlvbl09XCJ0cmFuc2Zvcm1hdGlvbi5jb25maWdcIj48L2tpLWRhdGFzZXQtZmlsdGVycz5cbiAgICAgICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgICAgICAgICpuZ0lmPVwiXy5maWx0ZXIoZGF0YXNldEluc3RhbmNlU3VtbWFyeS50cmFuc2Zvcm1hdGlvbkluc3RhbmNlcywge3R5cGU6ICdmaWx0ZXInLCBoaWRlOiBmYWxzZX0pLmxlbmd0aFwiXG4gICAgICAgICAgICAgICAgICAgIG1hdC1mbGF0LWJ1dHRvbiBjbGFzcz1cImFwcGx5LWZpbHRlciBtci0yXCIgY29sb3I9XCJwcmltYXJ5XCJcbiAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cImFwcGx5RmlsdGVycygpXCIgW2Rpc2FibGVkXT1cIiFmaWx0ZXJKdW5jdGlvbi5maWx0ZXJzLmxlbmd0aFwiPlxuICAgICAgICAgICAgICAgICAgICBBcHBseSBGaWx0ZXJzXG4gICAgICAgICAgICAgICAgPC9idXR0b24+XG5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgIDwvbmctdGVtcGxhdGU+XG5cbjwvZGl2PlxuXG48ZGl2IGNsYXNzPVwiY2VsbC1oZWFkZXJcIj5cbiAgICA8ZGl2IGNsYXNzPVwidHJhbnNmb3JtYXRpb24tbGlzdGluZyBzb3J0XCJcbiAgICAgICAgICpuZ0lmPVwiXy5maW5kKGRhdGFzZXRJbnN0YW5jZVN1bW1hcnkudHJhbnNmb3JtYXRpb25JbnN0YW5jZXMsIHt0eXBlOiAnbXVsdGlzb3J0J30pXCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJsaXN0LXRpdGxlXCI+XG4gICAgICAgICAgICBTb3J0XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8ZGl2IGNsYXNzPVwiZmxleCBmbGV4LXdyYXBcIj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJiYWRnZS1pdGVtIG91dGxpbmVcIlxuICAgICAgICAgICAgICAgICBbbmdDbGFzc109XCJ7J2V4Y2x1ZGUgYmctb3JhbmdlLTUwIGJvcmRlci1vcmFuZ2UtMjAwJzogXy5maW5kKGRhdGFzZXRJbnN0YW5jZVN1bW1hcnkudHJhbnNmb3JtYXRpb25JbnN0YW5jZXMsIHtleGNsdWRlOiB0cnVlfSl9XCJcbiAgICAgICAgICAgICAgICAgKm5nRm9yPVwibGV0IHNvcnQgb2YgXy5maW5kKGRhdGFzZXRJbnN0YW5jZVN1bW1hcnkudHJhbnNmb3JtYXRpb25JbnN0YW5jZXMsIHt0eXBlOiAnbXVsdGlzb3J0J30pLmNvbmZpZy5zb3J0czsgbGV0IGkgPSBpbmRleFwiPlxuICAgICAgICAgICAgICAgIDxzcGFuPnt7IF8uc3RhcnRDYXNlKHNvcnQuZmllbGROYW1lKSB9fSZuYnNwOzxzcGFuIGNsYXNzPVwidXBwZXJjYXNlXCI+e3sgc29ydC5kaXJlY3Rpb24gfX08L3NwYW4+PC9zcGFuPlxuICAgICAgICAgICAgICAgIDxidXR0b24gbWF0LWljb24tYnV0dG9uIChjbGljayk9XCJyZW1vdmVGaWx0ZXIoaSlcIj5cbiAgICAgICAgICAgICAgICAgICAgPG1hdC1pY29uPmNhbmNlbDwvbWF0LWljb24+XG4gICAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG5cbiAgICA8L2Rpdj5cbjwvZGl2PlxuXG48ZGl2IGNsYXNzPVwiaC1mdWxsIHRhYmxlLW92ZXJmbG93IG92ZXJmbG93LXNjcm9sbFwiPlxuICAgIDx0YWJsZSBtYXQtdGFibGUgW2RhdGFTb3VyY2VdPVwidGFibGVEYXRhXCIgKm5nSWY9XCJkaXNwbGF5ZWRDb2x1bW5zLmxlbmd0aFwiIG1hdFNvcnQgKG1hdFNvcnRDaGFuZ2UpPVwic29ydCgkZXZlbnQpXCJcbiAgICAgICAgICAgY2xhc3M9XCJibG9jayBzdGlja3lcIj5cblxuICAgICAgICA8bmctdGVtcGxhdGUgbmdGb3IgbGV0LWNvbHVtbiBbbmdGb3JPZl09XCJmaWx0ZXJGaWVsZHNcIj5cbiAgICAgICAgICAgIDxuZy1jb250YWluZXIgW21hdENvbHVtbkRlZl09XCJjb2x1bW4ubmFtZVwiPlxuICAgICAgICAgICAgICAgIDx0aCBtYXQtaGVhZGVyLWNlbGwgKm1hdEhlYWRlckNlbGxEZWYgbWF0LXNvcnQtaGVhZGVyXG4gICAgICAgICAgICAgICAgICAgIGNsYXNzPVwidGV4dC14cyBmb250LXNlbWlib2xkIHRleHQtZ3JheS05MDAgcHktMy41IHB4LTRcIj4ge3sgY29sdW1uLnRpdGxlIH19XG4gICAgICAgICAgICAgICAgPC90aD5cbiAgICAgICAgICAgICAgICA8dGQgbWF0LWNlbGwgKm1hdENlbGxEZWY9XCJsZXQgZWxlbWVudFwiIGNsYXNzPVwicHktMyBweC00XCI+XG4gICAgICAgICAgICAgICAgICAgIDxuZy10ZW1wbGF0ZVxuICAgICAgICAgICAgICAgICAgICAgICAgW25nSWZdPVwiIUFycmF5LmlzQXJyYXkoZWxlbWVudFtjb2x1bW4ubmFtZV0pICYmICFfLmlzUGxhaW5PYmplY3QoZWxlbWVudFtjb2x1bW4ubmFtZV0pXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8bmctdGVtcGxhdGUgW25nSWZdPVwiZWxlbWVudFtjb2x1bW4ubmFtZV0gJiYgU3RyaW5nKGVsZW1lbnRbY29sdW1uLm5hbWVdKS5sZW5ndGggPD0gMTAwXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBbaW5uZXJIVE1MXT1cImVsZW1lbnRbY29sdW1uLm5hbWVdXCI+PC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICAgICAgICAgICAgICAgICAgPG5nLXRlbXBsYXRlIFtuZ0lmXT1cImVsZW1lbnRbY29sdW1uLm5hbWVdICYmIFN0cmluZyhlbGVtZW50W2NvbHVtbi5uYW1lXSkubGVuZ3RoID4gMTAwXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdj57eyBlbGVtZW50W2NvbHVtbi5uYW1lXS5zdWJzdHJpbmcoMCwgMTAwKSArICcuLi4nIH19PC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGEgKGNsaWNrKT1cInZpZXdGdWxsSXRlbURhdGEoZWxlbWVudFtjb2x1bW4ubmFtZV0sIGNvbHVtbi5uYW1lKVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJmbGV4IGl0ZW1zLWNlbnRlciB0ZXh0LXNtIHRleHQtY3RhXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpZXcgbW9yZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3ZnIHhtbG5zPVwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIiBjbGFzcz1cIm1sLTEgaC00IHctNFwiIGZpbGw9XCJub25lXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2aWV3Qm94PVwiMCAwIDI0IDI0XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJva2U9XCJjdXJyZW50Q29sb3JcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxwYXRoIHN0cm9rZS1saW5lY2FwPVwicm91bmRcIiBzdHJva2UtbGluZWpvaW49XCJyb3VuZFwiIHN0cm9rZS13aWR0aD1cIjJcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZD1cIk0xMCA2SDZhMiAyIDAgMDAtMiAydjEwYTIgMiAwIDAwMiAyaDEwYTIgMiAwIDAwMi0ydi00TTE0IDRoNm0wIDB2Nm0wLTZMMTAgMTRcIi8+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvc3ZnPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvYT5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgICAgICAgICAgICAgICAgICA8bmctdGVtcGxhdGUgW25nSWZdPVwiIWVsZW1lbnRbY29sdW1uLm5hbWVdXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gKm5nSWY9XCJlbGVtZW50W2NvbHVtbi5uYW1lXSA9PT0gbnVsbFwiIGNsYXNzPVwiZm9udC1tb25vIHRleHQtZ3JheS00MDBcIj5udWxsPC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuICpuZ0lmPVwiZWxlbWVudFtjb2x1bW4ubmFtZV0gIT09IG51bGxcIj57eyBlbGVtZW50W2NvbHVtbi5uYW1lXSB9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgICAgICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgICAgICAgICAgICAgIDxuZy10ZW1wbGF0ZSBbbmdJZl09XCJBcnJheS5pc0FycmF5KGVsZW1lbnRbY29sdW1uLm5hbWVdKVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgQ29udGFpbnMge3sgZWxlbWVudFtjb2x1bW4ubmFtZV0ubGVuZ3RoIH19IGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgICAgICAgICAgICAgIDxuZy10ZW1wbGF0ZSBbbmdJZl09XCJfLmlzUGxhaW5PYmplY3QoZWxlbWVudFtjb2x1bW4ubmFtZV0pXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICBPYmplY3QgaGFzIHt7IE9iamVjdC5rZXlzKGVsZW1lbnRbY29sdW1uLm5hbWVdKS5sZW5ndGggfX0ga2V5c1xuICAgICAgICAgICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICAgICAgICAgIDwvdGQ+XG4gICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICAgICAgPC9uZy10ZW1wbGF0ZT5cblxuICAgICAgICA8dHIgbWF0LWhlYWRlci1yb3cgKm1hdEhlYWRlclJvd0RlZj1cImRpc3BsYXllZENvbHVtbnNcIiBjbGFzcz1cImgtYXV0b1wiPjwvdHI+XG4gICAgICAgIDx0ciBtYXQtcm93ICptYXRSb3dEZWY9XCJsZXQgcm93OyBjb2x1bW5zOiBkaXNwbGF5ZWRDb2x1bW5zO1wiPjwvdHI+XG5cbiAgICA8L3RhYmxlPlxuPC9kaXY+XG5cblxuPGRpdiBjbGFzcz1cImJvcmRlci1iIGJvcmRlci10IGJnLWdyYXktNTAgcHgtNCBweS0xIGZsZXggYWxpZ24tY2VudGVyIGp1c3RpZnktZW5kXCI+XG5cbiAgICA8ZGl2IGNsYXNzPVwiZmxleCBpdGVtcy1jZW50ZXJcIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cInRleHQtc20gdGV4dC1ncmF5LTUwMCBtci0xMFwiPlxuICAgICAgICAgICAgPG5nLXRlbXBsYXRlIFtuZ0lmXT1cImRhdGFzZXRcIj5cbiAgICAgICAgICAgICAgICBTaG93aW5nIHt7IG9mZnNldCArIDEgfX0gLSB7eyAocGFnZSAqIGxpbWl0KSAtIChsaW1pdCAtIHRhYmxlRGF0YS5sZW5ndGgpIH19XG4gICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPHNlbGVjdCBbdmFsdWVdPVwibGltaXRcIiAoY2hhbmdlKT1cInBhZ2VTaXplQ2hhbmdlKCRldmVudC50YXJnZXQudmFsdWUpXCJcbiAgICAgICAgICAgICAgICBjbGFzcz1cIm1yLTggcC0xLjVcIj5cbiAgICAgICAgICAgIDxvcHRpb24gW3ZhbHVlXT1cIjFcIj4xPC9vcHRpb24+XG4gICAgICAgICAgICA8b3B0aW9uIFt2YWx1ZV09XCI1XCI+NTwvb3B0aW9uPlxuICAgICAgICAgICAgPG9wdGlvbiBbdmFsdWVdPVwiMTBcIj4xMDwvb3B0aW9uPlxuICAgICAgICAgICAgPG9wdGlvbiBbdmFsdWVdPVwiMjVcIj4yNTwvb3B0aW9uPlxuICAgICAgICAgICAgPG9wdGlvbiBbdmFsdWVdPVwiNTBcIj41MDwvb3B0aW9uPlxuICAgICAgICAgICAgPG9wdGlvbiBbdmFsdWVdPVwiMTAwXCI+MTAwPC9vcHRpb24+XG4gICAgICAgICAgICA8b3B0aW9uIFt2YWx1ZV09XCIyNTBcIj4yNTA8L29wdGlvbj5cbiAgICAgICAgICAgIDxvcHRpb24gW3ZhbHVlXT1cIjEwMDBcIj4xMDAwPC9vcHRpb24+XG4gICAgICAgIDwvc2VsZWN0PlxuICAgICAgICA8YnV0dG9uIG1hdC1pY29uLWJ1dHRvbiBjbGFzcz1cIm1yLTRcIiAoY2xpY2spPVwiZGVjcmVhc2VPZmZzZXQoKVwiIFtkaXNhYmxlZF09XCJwYWdlIDw9IDFcIj5cbiAgICAgICAgICAgIDxtYXQtaWNvbj5jaGV2cm9uX2xlZnQ8L21hdC1pY29uPlxuICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgPGJ1dHRvbiBtYXQtaWNvbi1idXR0b24gKGNsaWNrKT1cImluY3JlYXNlT2Zmc2V0KClcIiBbZGlzYWJsZWRdPVwiZW5kT2ZSZXN1bHRzXCI+XG4gICAgICAgICAgICA8bWF0LWljb24+Y2hldnJvbl9yaWdodDwvbWF0LWljb24+XG4gICAgICAgIDwvYnV0dG9uPlxuICAgIDwvZGl2PlxuPC9kaXY+XG4iLCI8ZGl2IGNsYXNzPVwiZGlhbG9nXCIgY2RrRHJhZyBjZGtEcmFnUm9vdEVsZW1lbnQ9XCIuY2RrLW92ZXJsYXktcGFuZVwiPlxuXG4gICAgPGRpdiBjbGFzcz1cImRpYWxvZy10aXRsZVwiIGNka0RyYWdIYW5kbGU+XG4gICAgICAgIDxoMiBtYXQtZGlhbG9nLXRpdGxlPnt7Y29sdW1uTmFtZX19PC9oMj5cblxuICAgICAgICA8YnV0dG9uIG1hdC1pY29uLWJ1dHRvbiBtYXQtZGlhbG9nLWNsb3NlPlxuICAgICAgICAgICAgPG1hdC1pY29uPmNsZWFyPC9tYXQtaWNvbj5cbiAgICAgICAgPC9idXR0b24+XG4gICAgPC9kaXY+XG5cbiAgICA8ZGl2IGNsYXNzPVwiZGlhbG9nLWNvbnRlbnRcIj5cblxuICAgICAgICA8ZGl2IFtpbm5lckhUTUxdPVwiZnVsbERhdGFcIj48L2Rpdj5cblxuICAgIDwvZGl2PlxuXG48L2Rpdj5cblxuXG4iXX0=
|