@cqa-lib/cqa-ui 1.1.175 → 1.1.177
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/esm2020/lib/compare-runs/compare-runs.component.mjs +1 -1
- package/esm2020/lib/dynamic-select/dynamic-select-field.component.mjs +3 -3
- package/esm2020/lib/execution-screen/db-query-execution-item/db-query-execution-item.component.mjs +70 -5
- package/esm2020/lib/execution-screen/db-verification-step/db-verification-step.component.mjs +15 -3
- package/esm2020/lib/iterations-loop/iterations-loop.component.mjs +1 -1
- package/esm2020/lib/step-builder/step-builder-action/step-builder-action.component.mjs +29 -9
- package/esm2020/lib/step-builder/step-builder-condition/step-builder-condition.component.mjs +330 -0
- package/esm2020/lib/step-builder/step-builder-database/step-builder-database.component.mjs +205 -0
- package/esm2020/lib/table/dynamic-table/dynamic-table.component.mjs +35 -3
- package/esm2020/lib/templates/table-template.component.mjs +7 -4
- package/esm2020/lib/test-case-details/custom-edit-step/custom-edit-step-data.mjs +5 -0
- package/esm2020/lib/test-case-details/custom-edit-step/custom-edit-step-ref.mjs +32 -0
- package/esm2020/lib/test-case-details/custom-edit-step/custom-edit-step.component.mjs +71 -0
- package/esm2020/lib/test-case-details/custom-edit-step/custom-edit-step.service.mjs +97 -0
- package/esm2020/lib/test-case-details/normal-step/normal-step.component.mjs +59 -9
- package/esm2020/lib/ui-kit.module.mjs +18 -3
- package/esm2020/lib/utils/tw-overlay-container.mjs +6 -3
- package/esm2020/public-api.mjs +7 -1
- package/fesm2015/cqa-lib-cqa-ui.mjs +939 -34
- package/fesm2015/cqa-lib-cqa-ui.mjs.map +1 -1
- package/fesm2020/cqa-lib-cqa-ui.mjs +926 -34
- package/fesm2020/cqa-lib-cqa-ui.mjs.map +1 -1
- package/lib/dynamic-select/dynamic-select-field.component.d.ts +1 -0
- package/lib/execution-screen/db-query-execution-item/db-query-execution-item.component.d.ts +18 -3
- package/lib/execution-screen/db-verification-step/db-verification-step.component.d.ts +7 -1
- package/lib/step-builder/step-builder-action/step-builder-action.component.d.ts +2 -1
- package/lib/step-builder/step-builder-condition/step-builder-condition.component.d.ts +61 -0
- package/lib/step-builder/step-builder-database/step-builder-database.component.d.ts +61 -0
- package/lib/table/dynamic-table/dynamic-table.component.d.ts +7 -1
- package/lib/templates/table-template.component.d.ts +6 -1
- package/lib/test-case-details/custom-edit-step/custom-edit-step-data.d.ts +8 -0
- package/lib/test-case-details/custom-edit-step/custom-edit-step-ref.d.ts +13 -0
- package/lib/test-case-details/custom-edit-step/custom-edit-step.component.d.ts +25 -0
- package/lib/test-case-details/custom-edit-step/custom-edit-step.service.d.ts +23 -0
- package/lib/test-case-details/normal-step/normal-step.component.d.ts +9 -0
- package/lib/ui-kit.module.d.ts +26 -23
- package/package.json +1 -1
- package/public-api.d.ts +6 -0
- package/styles.css +1 -1
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import { Component, Input, Output, EventEmitter } from '@angular/core';
|
|
2
|
+
import { Validators } from '@angular/forms';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
import * as i1 from "@angular/forms";
|
|
5
|
+
import * as i2 from "../../dynamic-select/dynamic-select-field.component";
|
|
6
|
+
import * as i3 from "../../button/button.component";
|
|
7
|
+
import * as i4 from "../../badge/badge.component";
|
|
8
|
+
import * as i5 from "../../custom-textarea/custom-textarea.component";
|
|
9
|
+
import * as i6 from "../../custom-input/custom-input.component";
|
|
10
|
+
import * as i7 from "@angular/material/icon";
|
|
11
|
+
import * as i8 from "@angular/common";
|
|
12
|
+
export class StepBuilderDatabaseComponent {
|
|
13
|
+
constructor(fb) {
|
|
14
|
+
this.fb = fb;
|
|
15
|
+
/** Options for DB environment dropdown */
|
|
16
|
+
this.dbEnvironmentOptions = [];
|
|
17
|
+
/** Initial queries list */
|
|
18
|
+
this.queries = [];
|
|
19
|
+
/** Query results data */
|
|
20
|
+
this.queryResults = [];
|
|
21
|
+
/** Loading state */
|
|
22
|
+
this.isLoading = false;
|
|
23
|
+
/** Emit when step is created */
|
|
24
|
+
this.createStep = new EventEmitter();
|
|
25
|
+
/** Emit when cancelled */
|
|
26
|
+
this.cancelled = new EventEmitter();
|
|
27
|
+
/** Emit when query is run */
|
|
28
|
+
this.runQuery = new EventEmitter();
|
|
29
|
+
/** Emit when query is added */
|
|
30
|
+
this.addQuery = new EventEmitter();
|
|
31
|
+
/** Emit when query is deleted */
|
|
32
|
+
this.deleteQuery = new EventEmitter();
|
|
33
|
+
this.selectedTab = 'output';
|
|
34
|
+
this.selectedQueryIndex = 0;
|
|
35
|
+
this.databaseForm = this.fb.group({
|
|
36
|
+
dbEnvironment: ['', Validators.required],
|
|
37
|
+
queries: this.fb.array([])
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
ngOnInit() {
|
|
41
|
+
// Initialize with default query if none provided
|
|
42
|
+
if (this.queries.length === 0) {
|
|
43
|
+
this.addNewQuery();
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
this.queries.forEach((query, index) => {
|
|
47
|
+
this.addQueryToForm(query);
|
|
48
|
+
if (index === 0) {
|
|
49
|
+
this.selectedQueryIndex = 0;
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
ngOnChanges(changes) {
|
|
55
|
+
if (changes['queries'] && !changes['queries'].firstChange) {
|
|
56
|
+
// Rebuild form array when queries change
|
|
57
|
+
const queriesArray = this.databaseForm.get('queries');
|
|
58
|
+
while (queriesArray.length !== 0) {
|
|
59
|
+
queriesArray.removeAt(0);
|
|
60
|
+
}
|
|
61
|
+
this.queries.forEach(query => {
|
|
62
|
+
this.addQueryToForm(query);
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
get queriesFormArray() {
|
|
67
|
+
return this.databaseForm.get('queries');
|
|
68
|
+
}
|
|
69
|
+
addNewQuery() {
|
|
70
|
+
const newQuery = {
|
|
71
|
+
id: `query_${Date.now()}`,
|
|
72
|
+
query: '',
|
|
73
|
+
variable: '',
|
|
74
|
+
status: 'pending'
|
|
75
|
+
};
|
|
76
|
+
this.queries.push(newQuery);
|
|
77
|
+
this.addQueryToForm(newQuery);
|
|
78
|
+
this.selectedQueryIndex = this.queries.length - 1;
|
|
79
|
+
this.addQuery.emit();
|
|
80
|
+
}
|
|
81
|
+
addQueryToForm(query) {
|
|
82
|
+
const queryGroup = this.fb.group({
|
|
83
|
+
id: [query.id],
|
|
84
|
+
query: [query.query, Validators.required],
|
|
85
|
+
variable: [query.variable, Validators.required]
|
|
86
|
+
});
|
|
87
|
+
this.queriesFormArray.push(queryGroup);
|
|
88
|
+
}
|
|
89
|
+
deleteQueryById(queryId) {
|
|
90
|
+
const index = this.queries.findIndex(q => q.id === queryId);
|
|
91
|
+
if (index !== -1) {
|
|
92
|
+
this.queries.splice(index, 1);
|
|
93
|
+
this.queriesFormArray.removeAt(index);
|
|
94
|
+
if (this.selectedQueryIndex >= this.queries.length) {
|
|
95
|
+
this.selectedQueryIndex = Math.max(0, this.queries.length - 1);
|
|
96
|
+
}
|
|
97
|
+
this.deleteQuery.emit(queryId);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
getDbEnvironmentConfig() {
|
|
101
|
+
return {
|
|
102
|
+
key: 'dbEnvironment',
|
|
103
|
+
placeholder: 'Select DB environment',
|
|
104
|
+
multiple: false,
|
|
105
|
+
searchable: false,
|
|
106
|
+
options: this.dbEnvironmentOptions
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
getCurrentQuery() {
|
|
110
|
+
if (this.queries.length > 0 && this.selectedQueryIndex >= 0 && this.selectedQueryIndex < this.queries.length) {
|
|
111
|
+
return this.queries[this.selectedQueryIndex];
|
|
112
|
+
}
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
getCurrentQueryFormGroup() {
|
|
116
|
+
if (this.queriesFormArray && this.selectedQueryIndex >= 0 && this.selectedQueryIndex < this.queriesFormArray.length) {
|
|
117
|
+
return this.queriesFormArray.at(this.selectedQueryIndex);
|
|
118
|
+
}
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
onRunQuery() {
|
|
122
|
+
const dbEnvironment = this.databaseForm.get('dbEnvironment')?.value;
|
|
123
|
+
const currentQuery = this.getCurrentQuery();
|
|
124
|
+
const queryFormGroup = this.getCurrentQueryFormGroup();
|
|
125
|
+
if (currentQuery && queryFormGroup && dbEnvironment) {
|
|
126
|
+
const query = queryFormGroup.get('query')?.value || '';
|
|
127
|
+
const variable = queryFormGroup.get('variable')?.value || '';
|
|
128
|
+
// Update the query object
|
|
129
|
+
currentQuery.query = query;
|
|
130
|
+
currentQuery.variable = variable;
|
|
131
|
+
this.runQuery.emit({
|
|
132
|
+
query,
|
|
133
|
+
variable,
|
|
134
|
+
dbEnvironment
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
onSelectQuery(index) {
|
|
139
|
+
this.selectedQueryIndex = index;
|
|
140
|
+
}
|
|
141
|
+
onTabChange(tab) {
|
|
142
|
+
this.selectedTab = tab;
|
|
143
|
+
}
|
|
144
|
+
onCopyResults() {
|
|
145
|
+
// Copy query results to clipboard
|
|
146
|
+
if (this.queryResults && this.queryResults.length > 0) {
|
|
147
|
+
const text = JSON.stringify(this.queryResults, null, 2);
|
|
148
|
+
navigator.clipboard.writeText(text).then(() => {
|
|
149
|
+
// Could emit an event or show a toast notification
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
onCancel() {
|
|
154
|
+
this.cancelled.emit();
|
|
155
|
+
}
|
|
156
|
+
onCreateStep() {
|
|
157
|
+
if (this.databaseForm.valid) {
|
|
158
|
+
const formValue = this.databaseForm.value;
|
|
159
|
+
const stepData = {
|
|
160
|
+
dbEnvironment: formValue.dbEnvironment,
|
|
161
|
+
queries: this.queries.map((query, index) => {
|
|
162
|
+
const queryFormGroup = this.queriesFormArray.at(index);
|
|
163
|
+
return {
|
|
164
|
+
id: query.id,
|
|
165
|
+
query: queryFormGroup.get('query')?.value || '',
|
|
166
|
+
variable: queryFormGroup.get('variable')?.value || '',
|
|
167
|
+
status: query.status
|
|
168
|
+
};
|
|
169
|
+
})
|
|
170
|
+
};
|
|
171
|
+
this.createStep.emit(stepData);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
getTableColumns() {
|
|
175
|
+
if (!this.queryResults || this.queryResults.length === 0) {
|
|
176
|
+
return [];
|
|
177
|
+
}
|
|
178
|
+
return Object.keys(this.queryResults[0]);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
StepBuilderDatabaseComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: StepBuilderDatabaseComponent, deps: [{ token: i1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component });
|
|
182
|
+
StepBuilderDatabaseComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: StepBuilderDatabaseComponent, selector: "cqa-step-builder-database", inputs: { dbEnvironmentOptions: "dbEnvironmentOptions", queries: "queries", queryResults: "queryResults", isLoading: "isLoading" }, outputs: { createStep: "createStep", cancelled: "cancelled", runQuery: "runQuery", addQuery: "addQuery", deleteQuery: "deleteQuery" }, host: { classAttribute: "cqa-ui-root" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"cqa-flex cqa-flex-col cqa-h-full cqa-bg-white cqa-px-4 cqa-py-2\">\n <!-- Header -->\n <h2 class=\"cqa-text-[12px] cqa-font-semibold cqa-text-black-100 cqa-mb-4\">\n Create Database Test Step\n </h2>\n\n <!-- DB Environment Section -->\n <div class=\"cqa-flex cqa-items-start cqa-gap-4 cqa-mb-6\">\n <div class=\"cqa-flex-1\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1.5 cqa-block\">\n DB Environment <span class=\"cqa-text-red-500\">*</span>\n </label>\n <cqa-dynamic-select\n [form]=\"databaseForm\"\n [config]=\"getDbEnvironmentConfig()\">\n </cqa-dynamic-select>\n <p class=\"cqa-text-xs cqa-text-gray-500 cqa-mt-1\">\n Uses Database environments from Environments.\n </p>\n </div>\n <div class=\"cqa-flex cqa-items-end cqa-mb-1\">\n <cqa-button\n variant=\"filled\"\n text=\"Run Query\"\n [customClass]=\"'cqa-whitespace-nowrap'\"\n (clicked)=\"onRunQuery()\"\n [disabled]=\"!databaseForm.get('dbEnvironment')?.value || isLoading\">\n </cqa-button>\n </div>\n </div>\n\n <!-- Main Content: Two Column Layout -->\n <div class=\"cqa-flex cqa-gap-4 cqa-flex-1 cqa-overflow-hidden cqa-mb-6\">\n <!-- Left Panel: Query List -->\n <div class=\"cqa-w-64 cqa-flex-shrink-0 cqa-flex cqa-flex-col cqa-border cqa-border-gray-200 cqa-rounded-lg cqa-overflow-hidden\">\n <div class=\"cqa-p-3 cqa-bg-gray-50 cqa-border-b cqa-border-gray-200\">\n <h3 class=\"cqa-text-sm cqa-font-semibold cqa-text-gray-900\">Queries</h3>\n </div>\n <div class=\"cqa-flex-1 cqa-overflow-y-auto cqa-p-2\">\n <div *ngFor=\"let query of queries; let i = index\"\n class=\"cqa-flex cqa-items-center cqa-justify-between cqa-p-2 cqa-rounded cqa-cursor-pointer cqa-mb-1\"\n [class.cqa-bg-blue-50]=\"selectedQueryIndex === i\"\n [class.cqa-border]=\"selectedQueryIndex === i\"\n [class.cqa-border-blue-500]=\"selectedQueryIndex === i\"\n (click)=\"onSelectQuery(i)\">\n <span class=\"cqa-text-sm cqa-font-medium cqa-text-gray-900\">Query {{ i + 1 }}</span>\n <cqa-badge\n *ngIf=\"query.status\"\n [label]=\"query.status === 'passed' ? 'Passed' : query.status === 'failed' ? 'Failed' : 'Pending'\"\n [variant]=\"query.status === 'passed' ? 'success' : query.status === 'failed' ? 'error' : 'default'\"\n size=\"small\">\n </cqa-badge>\n </div>\n </div>\n </div>\n\n <!-- Right Panel: Query Editor -->\n <div class=\"cqa-flex-1 cqa-flex cqa-flex-col cqa-border cqa-border-gray-200 cqa-rounded-lg cqa-overflow-hidden\">\n <div class=\"cqa-p-3 cqa-bg-gray-50 cqa-border-b cqa-border-gray-200\">\n <h3 class=\"cqa-text-sm cqa-font-semibold cqa-text-gray-900\">Query & Store Response</h3>\n </div>\n \n <div class=\"cqa-flex-1 cqa-overflow-y-auto cqa-p-4 cqa-flex cqa-flex-col cqa-gap-4\">\n <!-- SQL Query Textarea -->\n <div class=\"cqa-flex-1 cqa-flex cqa-flex-col\">\n <cqa-custom-textarea\n [placeholder]=\"'Enter your SQL query here...'\"\n [value]=\"getCurrentQueryFormGroup()?.get('query')?.value || ''\"\n [fullWidth]=\"true\"\n [rows]=\"8\"\n (valueChange)=\"getCurrentQueryFormGroup()?.get('query')?.setValue($event)\">\n </cqa-custom-textarea>\n </div>\n\n <!-- Variable Input -->\n <div class=\"cqa-flex cqa-gap-4\">\n <div class=\"cqa-flex-1\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1.5 cqa-block\">\n Variable\n </label>\n <cqa-custom-input\n [placeholder]=\"'Variable name'\"\n [value]=\"getCurrentQueryFormGroup()?.get('variable')?.value || ''\"\n [fullWidth]=\"true\"\n (valueChange)=\"getCurrentQueryFormGroup()?.get('variable')?.setValue($event)\">\n </cqa-custom-input>\n <p class=\"cqa-text-xs cqa-text-gray-500 cqa-mt-1\">\n Use letters, numbers, underscore. No spaces. Unique per step. Case sensitive.\n </p>\n </div>\n </div>\n\n <!-- Action Buttons -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <cqa-button\n variant=\"outlined\"\n text=\"Add Query\"\n icon=\"add\"\n (clicked)=\"addNewQuery()\">\n </cqa-button>\n <button\n type=\"button\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-10 cqa-h-10 cqa-rounded cqa-text-gray-500 hover:cqa-text-gray-700 hover:cqa-bg-gray-100 cqa-transition-colors cqa-border cqa-border-gray-300\"\n (click)=\"deleteQueryById(getCurrentQuery()?.id || '')\"\n [disabled]=\"queries.length <= 1\"\n [attr.aria-label]=\"'Delete query'\">\n <mat-icon class=\"cqa-text-lg\">delete</mat-icon>\n </button>\n <cqa-button\n variant=\"filled\"\n text=\"Run\"\n icon=\"play_arrow\"\n (clicked)=\"onRunQuery()\"\n [disabled]=\"!databaseForm.get('dbEnvironment')?.value || isLoading\">\n </cqa-button>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Results Section -->\n <div class=\"cqa-flex cqa-flex-col cqa-border cqa-border-gray-200 cqa-rounded-lg cqa-overflow-hidden cqa-mb-6\">\n <!-- Tabs -->\n <div class=\"cqa-flex cqa-items-center cqa-border-b cqa-border-gray-200 cqa-bg-gray-50\">\n <button\n type=\"button\"\n class=\"cqa-px-4 cqa-py-2 cqa-text-sm cqa-font-medium cqa-transition-colors cqa-border-b-2\"\n [class.cqa-text-blue-600]=\"selectedTab === 'output'\"\n [class.cqa-border-blue-600]=\"selectedTab === 'output'\"\n [class.cqa-text-gray-600]=\"selectedTab !== 'output'\"\n [class.cqa-border-transparent]=\"selectedTab !== 'output'\"\n (click)=\"onTabChange('output')\">\n Output\n </button>\n <button\n type=\"button\"\n class=\"cqa-px-4 cqa-py-2 cqa-text-sm cqa-font-medium cqa-transition-colors cqa-border-b-2\"\n [class.cqa-text-blue-600]=\"selectedTab === 'verification'\"\n [class.cqa-border-blue-600]=\"selectedTab === 'verification'\"\n [class.cqa-text-gray-600]=\"selectedTab !== 'verification'\"\n [class.cqa-border-transparent]=\"selectedTab !== 'verification'\"\n (click)=\"onTabChange('verification')\">\n Verification\n </button>\n </div>\n\n <!-- Tab Content -->\n <div class=\"cqa-p-4\">\n <!-- Output Tab -->\n <div *ngIf=\"selectedTab === 'output'\">\n <div class=\"cqa-flex cqa-items-center cqa-justify-between cqa-mb-3\">\n <h4 class=\"cqa-text-sm cqa-font-semibold cqa-text-gray-900\">Query Results</h4>\n <cqa-button\n variant=\"text\"\n text=\"Copy\"\n icon=\"content_copy\"\n [customClass]=\"'cqa-text-blue-600'\"\n (clicked)=\"onCopyResults()\">\n </cqa-button>\n </div>\n \n <!-- Results Table -->\n <div *ngIf=\"queryResults && queryResults.length > 0\" class=\"cqa-overflow-x-auto\">\n <table class=\"cqa-w-full cqa-border-collapse\">\n <thead>\n <tr class=\"cqa-bg-gray-50 cqa-border-b cqa-border-gray-200\">\n <th *ngFor=\"let key of getTableColumns()\" \n class=\"cqa-px-4 cqa-py-2 cqa-text-left cqa-text-xs cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">\n {{ key }}\n </th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let row of queryResults\" \n class=\"cqa-border-b cqa-border-gray-200 hover:cqa-bg-gray-50\">\n <td *ngFor=\"let key of getTableColumns()\" \n class=\"cqa-px-4 cqa-py-2 cqa-text-sm cqa-text-gray-900\">\n {{ row[key] }}\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n \n <div *ngIf=\"!queryResults || queryResults.length === 0\" \n class=\"cqa-text-center cqa-py-8 cqa-text-gray-400 cqa-text-sm\">\n No results yet. Run a query to see results.\n </div>\n </div>\n\n <!-- Verification Tab -->\n <div *ngIf=\"selectedTab === 'verification'\">\n <p class=\"cqa-text-sm cqa-text-gray-600\">Verification settings will be available here.</p>\n </div>\n </div>\n </div>\n\n <!-- Action Buttons -->\n <div class=\"cqa-flex cqa-w-full cqa-gap-2 cqa-mt-auto cqa-pt-4 cqa-border-t cqa-border-gray-200\">\n <cqa-button\n class=\"cqa-w-1/2\"\n variant=\"outlined\"\n text=\"Cancel\"\n [customClass]=\"'cqa-flex-1 cqa-w-full'\"\n (clicked)=\"onCancel()\">\n </cqa-button>\n <cqa-button\n class=\"cqa-w-1/2\"\n variant=\"filled\"\n text=\"Create Step\"\n [customClass]=\"'cqa-flex-1 cqa-w-full'\"\n (clicked)=\"onCreateStep()\">\n </cqa-button>\n </div>\n</div>\n\n", components: [{ type: i2.DynamicSelectFieldComponent, selector: "cqa-dynamic-select", inputs: ["form", "config"], outputs: ["selectionChange", "selectClick", "searchChange", "loadMore"] }, { type: i3.ButtonComponent, selector: "cqa-button", inputs: ["variant", "btnSize", "disabled", "icon", "iconPosition", "fullWidth", "iconColor", "type", "text", "customClass", "inlineStyles", "tooltip", "tooltipPosition"], outputs: ["clicked"] }, { type: i4.BadgeComponent, selector: "cqa-badge", inputs: ["type", "label", "icon", "iconLibrary", "variant", "size", "backgroundColor", "textColor", "borderColor", "iconBackgroundColor", "iconColor", "iconSize", "inlineStyles", "key", "value", "keyTextColor", "valueTextColor", "isLoading"] }, { type: i5.CustomTextareaComponent, selector: "cqa-custom-textarea", inputs: ["label", "placeholder", "value", "disabled", "errors", "required", "ariaLabel", "size", "fullWidth", "maxLength", "showCharCount", "rows", "cols", "resize", "textareaInlineStyle", "labelInlineStyle"], outputs: ["valueChange", "blurred", "focused"] }, { type: i6.CustomInputComponent, selector: "cqa-custom-input", inputs: ["label", "type", "placeholder", "value", "disabled", "errors", "required", "ariaLabel", "size", "fullWidth", "maxLength", "showCharCount", "inputInlineStyle", "labelInlineStyle"], outputs: ["valueChange", "blurred", "focused", "enterPressed"] }, { type: i7.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], directives: [{ type: i8.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i8.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
|
|
183
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: StepBuilderDatabaseComponent, decorators: [{
|
|
184
|
+
type: Component,
|
|
185
|
+
args: [{ selector: 'cqa-step-builder-database', host: { class: 'cqa-ui-root' }, template: "<div class=\"cqa-flex cqa-flex-col cqa-h-full cqa-bg-white cqa-px-4 cqa-py-2\">\n <!-- Header -->\n <h2 class=\"cqa-text-[12px] cqa-font-semibold cqa-text-black-100 cqa-mb-4\">\n Create Database Test Step\n </h2>\n\n <!-- DB Environment Section -->\n <div class=\"cqa-flex cqa-items-start cqa-gap-4 cqa-mb-6\">\n <div class=\"cqa-flex-1\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1.5 cqa-block\">\n DB Environment <span class=\"cqa-text-red-500\">*</span>\n </label>\n <cqa-dynamic-select\n [form]=\"databaseForm\"\n [config]=\"getDbEnvironmentConfig()\">\n </cqa-dynamic-select>\n <p class=\"cqa-text-xs cqa-text-gray-500 cqa-mt-1\">\n Uses Database environments from Environments.\n </p>\n </div>\n <div class=\"cqa-flex cqa-items-end cqa-mb-1\">\n <cqa-button\n variant=\"filled\"\n text=\"Run Query\"\n [customClass]=\"'cqa-whitespace-nowrap'\"\n (clicked)=\"onRunQuery()\"\n [disabled]=\"!databaseForm.get('dbEnvironment')?.value || isLoading\">\n </cqa-button>\n </div>\n </div>\n\n <!-- Main Content: Two Column Layout -->\n <div class=\"cqa-flex cqa-gap-4 cqa-flex-1 cqa-overflow-hidden cqa-mb-6\">\n <!-- Left Panel: Query List -->\n <div class=\"cqa-w-64 cqa-flex-shrink-0 cqa-flex cqa-flex-col cqa-border cqa-border-gray-200 cqa-rounded-lg cqa-overflow-hidden\">\n <div class=\"cqa-p-3 cqa-bg-gray-50 cqa-border-b cqa-border-gray-200\">\n <h3 class=\"cqa-text-sm cqa-font-semibold cqa-text-gray-900\">Queries</h3>\n </div>\n <div class=\"cqa-flex-1 cqa-overflow-y-auto cqa-p-2\">\n <div *ngFor=\"let query of queries; let i = index\"\n class=\"cqa-flex cqa-items-center cqa-justify-between cqa-p-2 cqa-rounded cqa-cursor-pointer cqa-mb-1\"\n [class.cqa-bg-blue-50]=\"selectedQueryIndex === i\"\n [class.cqa-border]=\"selectedQueryIndex === i\"\n [class.cqa-border-blue-500]=\"selectedQueryIndex === i\"\n (click)=\"onSelectQuery(i)\">\n <span class=\"cqa-text-sm cqa-font-medium cqa-text-gray-900\">Query {{ i + 1 }}</span>\n <cqa-badge\n *ngIf=\"query.status\"\n [label]=\"query.status === 'passed' ? 'Passed' : query.status === 'failed' ? 'Failed' : 'Pending'\"\n [variant]=\"query.status === 'passed' ? 'success' : query.status === 'failed' ? 'error' : 'default'\"\n size=\"small\">\n </cqa-badge>\n </div>\n </div>\n </div>\n\n <!-- Right Panel: Query Editor -->\n <div class=\"cqa-flex-1 cqa-flex cqa-flex-col cqa-border cqa-border-gray-200 cqa-rounded-lg cqa-overflow-hidden\">\n <div class=\"cqa-p-3 cqa-bg-gray-50 cqa-border-b cqa-border-gray-200\">\n <h3 class=\"cqa-text-sm cqa-font-semibold cqa-text-gray-900\">Query & Store Response</h3>\n </div>\n \n <div class=\"cqa-flex-1 cqa-overflow-y-auto cqa-p-4 cqa-flex cqa-flex-col cqa-gap-4\">\n <!-- SQL Query Textarea -->\n <div class=\"cqa-flex-1 cqa-flex cqa-flex-col\">\n <cqa-custom-textarea\n [placeholder]=\"'Enter your SQL query here...'\"\n [value]=\"getCurrentQueryFormGroup()?.get('query')?.value || ''\"\n [fullWidth]=\"true\"\n [rows]=\"8\"\n (valueChange)=\"getCurrentQueryFormGroup()?.get('query')?.setValue($event)\">\n </cqa-custom-textarea>\n </div>\n\n <!-- Variable Input -->\n <div class=\"cqa-flex cqa-gap-4\">\n <div class=\"cqa-flex-1\">\n <label class=\"cqa-text-sm cqa-font-medium cqa-text-gray-700 cqa-mb-1.5 cqa-block\">\n Variable\n </label>\n <cqa-custom-input\n [placeholder]=\"'Variable name'\"\n [value]=\"getCurrentQueryFormGroup()?.get('variable')?.value || ''\"\n [fullWidth]=\"true\"\n (valueChange)=\"getCurrentQueryFormGroup()?.get('variable')?.setValue($event)\">\n </cqa-custom-input>\n <p class=\"cqa-text-xs cqa-text-gray-500 cqa-mt-1\">\n Use letters, numbers, underscore. No spaces. Unique per step. Case sensitive.\n </p>\n </div>\n </div>\n\n <!-- Action Buttons -->\n <div class=\"cqa-flex cqa-items-center cqa-gap-2\">\n <cqa-button\n variant=\"outlined\"\n text=\"Add Query\"\n icon=\"add\"\n (clicked)=\"addNewQuery()\">\n </cqa-button>\n <button\n type=\"button\"\n class=\"cqa-flex cqa-items-center cqa-justify-center cqa-w-10 cqa-h-10 cqa-rounded cqa-text-gray-500 hover:cqa-text-gray-700 hover:cqa-bg-gray-100 cqa-transition-colors cqa-border cqa-border-gray-300\"\n (click)=\"deleteQueryById(getCurrentQuery()?.id || '')\"\n [disabled]=\"queries.length <= 1\"\n [attr.aria-label]=\"'Delete query'\">\n <mat-icon class=\"cqa-text-lg\">delete</mat-icon>\n </button>\n <cqa-button\n variant=\"filled\"\n text=\"Run\"\n icon=\"play_arrow\"\n (clicked)=\"onRunQuery()\"\n [disabled]=\"!databaseForm.get('dbEnvironment')?.value || isLoading\">\n </cqa-button>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Results Section -->\n <div class=\"cqa-flex cqa-flex-col cqa-border cqa-border-gray-200 cqa-rounded-lg cqa-overflow-hidden cqa-mb-6\">\n <!-- Tabs -->\n <div class=\"cqa-flex cqa-items-center cqa-border-b cqa-border-gray-200 cqa-bg-gray-50\">\n <button\n type=\"button\"\n class=\"cqa-px-4 cqa-py-2 cqa-text-sm cqa-font-medium cqa-transition-colors cqa-border-b-2\"\n [class.cqa-text-blue-600]=\"selectedTab === 'output'\"\n [class.cqa-border-blue-600]=\"selectedTab === 'output'\"\n [class.cqa-text-gray-600]=\"selectedTab !== 'output'\"\n [class.cqa-border-transparent]=\"selectedTab !== 'output'\"\n (click)=\"onTabChange('output')\">\n Output\n </button>\n <button\n type=\"button\"\n class=\"cqa-px-4 cqa-py-2 cqa-text-sm cqa-font-medium cqa-transition-colors cqa-border-b-2\"\n [class.cqa-text-blue-600]=\"selectedTab === 'verification'\"\n [class.cqa-border-blue-600]=\"selectedTab === 'verification'\"\n [class.cqa-text-gray-600]=\"selectedTab !== 'verification'\"\n [class.cqa-border-transparent]=\"selectedTab !== 'verification'\"\n (click)=\"onTabChange('verification')\">\n Verification\n </button>\n </div>\n\n <!-- Tab Content -->\n <div class=\"cqa-p-4\">\n <!-- Output Tab -->\n <div *ngIf=\"selectedTab === 'output'\">\n <div class=\"cqa-flex cqa-items-center cqa-justify-between cqa-mb-3\">\n <h4 class=\"cqa-text-sm cqa-font-semibold cqa-text-gray-900\">Query Results</h4>\n <cqa-button\n variant=\"text\"\n text=\"Copy\"\n icon=\"content_copy\"\n [customClass]=\"'cqa-text-blue-600'\"\n (clicked)=\"onCopyResults()\">\n </cqa-button>\n </div>\n \n <!-- Results Table -->\n <div *ngIf=\"queryResults && queryResults.length > 0\" class=\"cqa-overflow-x-auto\">\n <table class=\"cqa-w-full cqa-border-collapse\">\n <thead>\n <tr class=\"cqa-bg-gray-50 cqa-border-b cqa-border-gray-200\">\n <th *ngFor=\"let key of getTableColumns()\" \n class=\"cqa-px-4 cqa-py-2 cqa-text-left cqa-text-xs cqa-font-semibold cqa-text-gray-700 cqa-uppercase\">\n {{ key }}\n </th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let row of queryResults\" \n class=\"cqa-border-b cqa-border-gray-200 hover:cqa-bg-gray-50\">\n <td *ngFor=\"let key of getTableColumns()\" \n class=\"cqa-px-4 cqa-py-2 cqa-text-sm cqa-text-gray-900\">\n {{ row[key] }}\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n \n <div *ngIf=\"!queryResults || queryResults.length === 0\" \n class=\"cqa-text-center cqa-py-8 cqa-text-gray-400 cqa-text-sm\">\n No results yet. Run a query to see results.\n </div>\n </div>\n\n <!-- Verification Tab -->\n <div *ngIf=\"selectedTab === 'verification'\">\n <p class=\"cqa-text-sm cqa-text-gray-600\">Verification settings will be available here.</p>\n </div>\n </div>\n </div>\n\n <!-- Action Buttons -->\n <div class=\"cqa-flex cqa-w-full cqa-gap-2 cqa-mt-auto cqa-pt-4 cqa-border-t cqa-border-gray-200\">\n <cqa-button\n class=\"cqa-w-1/2\"\n variant=\"outlined\"\n text=\"Cancel\"\n [customClass]=\"'cqa-flex-1 cqa-w-full'\"\n (clicked)=\"onCancel()\">\n </cqa-button>\n <cqa-button\n class=\"cqa-w-1/2\"\n variant=\"filled\"\n text=\"Create Step\"\n [customClass]=\"'cqa-flex-1 cqa-w-full'\"\n (clicked)=\"onCreateStep()\">\n </cqa-button>\n </div>\n</div>\n\n", styles: [] }]
|
|
186
|
+
}], ctorParameters: function () { return [{ type: i1.FormBuilder }]; }, propDecorators: { dbEnvironmentOptions: [{
|
|
187
|
+
type: Input
|
|
188
|
+
}], queries: [{
|
|
189
|
+
type: Input
|
|
190
|
+
}], queryResults: [{
|
|
191
|
+
type: Input
|
|
192
|
+
}], isLoading: [{
|
|
193
|
+
type: Input
|
|
194
|
+
}], createStep: [{
|
|
195
|
+
type: Output
|
|
196
|
+
}], cancelled: [{
|
|
197
|
+
type: Output
|
|
198
|
+
}], runQuery: [{
|
|
199
|
+
type: Output
|
|
200
|
+
}], addQuery: [{
|
|
201
|
+
type: Output
|
|
202
|
+
}], deleteQuery: [{
|
|
203
|
+
type: Output
|
|
204
|
+
}] } });
|
|
205
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RlcC1idWlsZGVyLWRhdGFiYXNlLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9saWIvc3RlcC1idWlsZGVyL3N0ZXAtYnVpbGRlci1kYXRhYmFzZS9zdGVwLWJ1aWxkZXItZGF0YWJhc2UuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi9zdGVwLWJ1aWxkZXIvc3RlcC1idWlsZGVyLWRhdGFiYXNlL3N0ZXAtYnVpbGRlci1kYXRhYmFzZS5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsWUFBWSxFQUFvQyxNQUFNLGVBQWUsQ0FBQztBQUN6RyxPQUFPLEVBQWtELFVBQVUsRUFBRSxNQUFNLGdCQUFnQixDQUFDOzs7Ozs7Ozs7O0FBcUI1RixNQUFNLE9BQU8sNEJBQTRCO0lBZ0N2QyxZQUFvQixFQUFlO1FBQWYsT0FBRSxHQUFGLEVBQUUsQ0FBYTtRQS9CbkMsMENBQTBDO1FBQ2pDLHlCQUFvQixHQUFtQixFQUFFLENBQUM7UUFFbkQsMkJBQTJCO1FBQ2xCLFlBQU8sR0FBb0IsRUFBRSxDQUFDO1FBRXZDLHlCQUF5QjtRQUNoQixpQkFBWSxHQUFVLEVBQUUsQ0FBQztRQUVsQyxvQkFBb0I7UUFDWCxjQUFTLEdBQVksS0FBSyxDQUFDO1FBRXBDLGdDQUFnQztRQUN0QixlQUFVLEdBQUcsSUFBSSxZQUFZLEVBQW9CLENBQUM7UUFFNUQsMEJBQTBCO1FBQ2hCLGNBQVMsR0FBRyxJQUFJLFlBQVksRUFBUSxDQUFDO1FBRS9DLDZCQUE2QjtRQUNuQixhQUFRLEdBQUcsSUFBSSxZQUFZLEVBQThELENBQUM7UUFFcEcsK0JBQStCO1FBQ3JCLGFBQVEsR0FBRyxJQUFJLFlBQVksRUFBUSxDQUFDO1FBRTlDLGlDQUFpQztRQUN2QixnQkFBVyxHQUFHLElBQUksWUFBWSxFQUFV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QUMsVUFBVSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztTQUNoQztJQUNILENBQUM7SUFFRCxlQUFlO1FBQ2IsSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLElBQUksSUFBSSxDQUFDLFlBQVksQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFO1lBQ3hELE9BQU8sRUFBRSxDQUFDO1NBQ1g7UUFDRCxPQUFPLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzNDLENBQUM7O3lIQW5NVSw0QkFBNEI7NkdBQTVCLDRCQUE0QiwwWUN0QnpDLCtqU0F3TkE7MkZEbE1hLDRCQUE0QjtrQkFOeEMsU0FBUzsrQkFDRSwyQkFBMkIsUUFHL0IsRUFBRSxLQUFLLEVBQUUsYUFBYSxFQUFFO2tHQUlyQixvQkFBb0I7c0JBQTVCLEtBQUs7Z0JBR0csT0FBTztzQkFBZixLQUFLO2dCQUdHLFlBQVk7c0JBQXBCLEtBQUs7Z0JBR0csU0FBUztzQkFBakIsS0FBSztnQkFHSSxVQUFVO3NCQUFuQixNQUFNO2dCQUdHLFNBQVM7c0JBQWxCLE1BQU07Z0JBR0csUUFBUTtzQkFBakIsTUFBTTtnQkFHRyxRQUFRO3NCQUFqQixNQUFNO2dCQUdHLFdBQVc7c0JBQXBCLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIElucHV0LCBPdXRwdXQsIEV2ZW50RW1pdHRlciwgT25Jbml0LCBPbkNoYW5nZXMsIFNpbXBsZUNoYW5nZXMgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEZvcm1CdWlsZGVyLCBGb3JtR3JvdXAsIEZvcm1BcnJheSwgRm9ybUNvbnRyb2wsIFZhbGlkYXRvcnMgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBEeW5hbWljU2VsZWN0RmllbGRDb25maWcsIFNlbGVjdE9wdGlvbiB9IGZyb20gJy4uLy4uL2R5bmFtaWMtc2VsZWN0L2R5bmFtaWMtc2VsZWN0LWZpZWxkLmNvbXBvbmVudCc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgRGF0YWJhc2VRdWVyeSB7XG4gIGlkOiBzdHJpbmc7XG4gIHF1ZXJ5OiBzdHJpbmc7XG4gIHZhcmlhYmxlOiBzdHJpbmc7XG4gIHN0YXR1cz86ICdwYXNzZWQnIHwgJ2ZhaWxlZCcgfCAncGVuZGluZyc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRGF0YWJhc2VGb3JtRGF0YSB7XG4gIGRiRW52aXJvbm1lbnQ6IHN0cmluZztcbiAgcXVlcmllczogRGF0YWJhc2VRdWVyeVtdO1xufVxuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdjcWEtc3RlcC1idWlsZGVyLWRhdGFiYXNlJyxcbiAgdGVtcGxhdGVVcmw6ICcuL3N0ZXAtYnVpbGRlci1kYXRhYmFzZS5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogW10sXG4gIGhvc3Q6IHsgY2xhc3M6ICdjcWEtdWktcm9vdCcgfVxufSlcbmV4cG9ydCBjbGFzcyBTdGVwQnVpbGRlckRhdGFiYXNlQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkNoYW5nZXMge1xuICAvKiogT3B0aW9ucyBmb3IgREIgZW52aXJvbm1lbnQgZHJvcGRvd24gKi9cbiAgQElucHV0KCkgZGJFbnZpcm9ubWVudE9wdGlvbnM6IFNlbGVjdE9wdGlvbltdID0gW107XG5cbiAgLyoqIEluaXRpYWwgcXVlcmllcyBsaXN0ICovXG4gIEBJbnB1dCgpIHF1ZXJpZXM6IERhdGFiYXNlUXVlcnlbXSA9IFtdO1xuXG4gIC8qKiBRdWVyeSByZXN1bHRzIGRhdGEgKi9cbiAgQElucHV0KCkgcXVlcnlSZXN1bHRzOiBhbnlbXSA9IFtdO1xuXG4gIC8qKiBMb2FkaW5nIHN0YXRlICovXG4gIEBJbnB1dCgpIGlzTG9hZGluZzogYm9vbGVhbiA9IGZhbHNlO1xuXG4gIC8qKiBFbWl0IHdoZW4gc3RlcCBpcyBjcmVhdGVkICovXG4gIEBPdXRwdXQoKSBjcmVhdGVTdGVwID0gbmV3IEV2ZW50RW1pdHRlcjxEYXRhYmFzZUZvcm1EYXRhPigpO1xuXG4gIC8qKiBFbWl0IHdoZW4gY2FuY2VsbGVkICovXG4gIEBPdXRwdXQoKSBjYW5jZWxsZWQgPSBuZXcgRXZlbnRFbWl0dGVyPHZvaWQ+KCk7XG5cbiAgLyoqIEVtaXQgd2hlbiBxdWVyeSBpcyBydW4gKi9cbiAgQE91dHB1dCgpIHJ1blF1ZXJ5ID0gbmV3IEV2ZW50RW1pdHRlcjx7IHF1ZXJ5OiBzdHJpbmc7IHZhcmlhYmxlOiBzdHJpbmc7IGRiRW52aXJvbm1lbnQ6IHN0cmluZyB9PigpO1xuXG4gIC8qKiBFbWl0IHdoZW4gcXVlcnkgaXMgYWRkZWQgKi9cbiAgQE91dHB1dCgpIGFkZFF1ZXJ5ID0gbmV3IEV2ZW50RW1pdHRlcjx2b2lkPigpO1xuXG4gIC8qKiBFbWl0IHdoZW4gcXVlcnkgaXMgZGVsZXRlZCAqL1xuICBAT3V0cHV0KCkgZGVsZXRlUXVlcnkgPSBuZXcgRXZlbnRFbWl0dGVyPHN0cmluZz4oKTtcblxuICBkYXRhYmFzZUZvcm06IEZvcm1Hcm91cDtcbiAgc2VsZWN0ZWRUYWI6ICdvdXRwdXQnIHwgJ3ZlcmlmaWNhdGlvbicgPSAnb3V0cHV0JztcbiAgc2VsZWN0ZWRRdWVyeUluZGV4OiBudW1iZXIgPSAwO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgZmI6IEZvcm1CdWlsZGVyKSB7XG4gICAgdGhpcy5kYXRhYmFzZUZvcm0gPSB0aGlzLmZiLmdyb3VwKHtcbiAgICAgIGRiRW52aXJvbm1lbnQ6IFsnJywgVmFsaWRhdG9ycy5yZXF1aXJlZF0sXG4gICAgICBxdWVyaWVzOiB0aGlzLmZiLmFycmF5KFtdKVxuICAgIH0pO1xuICB9XG5cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgLy8gSW5pdGlhbGl6ZSB3aXRoIGRlZmF1bHQgcXVlcnkgaWYgbm9uZSBwcm92aWRlZFxuICAgIGlmICh0aGlzLnF1ZXJpZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aGlzLmFkZE5ld1F1ZXJ5KCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMucXVlcmllcy5mb3JFYWNoKChxdWVyeSwgaW5kZXgpID0+IHtcbiAgICAgICAgdGhpcy5hZGRRdWVyeVRvRm9ybShxdWVyeSk7XG4gICAgICAgIGlmIChpbmRleCA9PT0gMCkge1xuICAgICAgICAgIHRoaXMuc2VsZWN0ZWRRdWVyeUluZGV4ID0gMDtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xuICAgIGlmIChjaGFuZ2VzWydxdWVyaWVzJ10gJiYgIWNoYW5nZXNbJ3F1ZXJpZXMnXS5maXJzdENoYW5nZSkge1xuICAgICAgLy8gUmVidWlsZCBmb3JtIGFycmF5IHdoZW4gcXVlcmllcyBjaGFuZ2VcbiAgICAgIGNvbnN0IHF1ZXJpZXNBcnJheSA9IHRoaXMuZGF0YWJhc2VGb3JtLmdldCgncXVlcmllcycpIGFzIEZvcm1BcnJheTtcbiAgICAgIHdoaWxlIChxdWVyaWVzQXJyYXkubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgIHF1ZXJpZXNBcnJheS5yZW1vdmVBdCgwKTtcbiAgICAgIH1cbiAgICAgIHRoaXMucXVlcmllcy5mb3JFYWNoKHF1ZXJ5ID0+IHtcbiAgICAgICAgdGhpcy5hZGRRdWVyeVRvRm9ybShxdWVyeSk7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBnZXQgcXVlcmllc0Zvcm1BcnJheSgpOiBGb3JtQXJyYXkge1xuICAgIHJldHVybiB0aGlzLmRhdGFiYXNlRm9ybS5nZXQoJ3F1ZXJpZXMnKSBhcyBGb3JtQXJyYXk7XG4gIH1cblxuICBhZGROZXdRdWVyeSgpOiB2b2lkIHtcbiAgICBjb25zdCBuZXdRdWVyeTogRGF0YWJhc2VRdWVyeSA9IHtcbiAgICAgIGlkOiBgcXVlcnlfJHtEYXRlLm5vdygpfWAsXG4gICAgICBxdWVyeTogJycsXG4gICAgICB2YXJpYWJsZTogJycsXG4gICAgICBzdGF0dXM6ICdwZW5kaW5nJ1xuICAgIH07XG4gICAgdGhpcy5xdWVyaWVzLnB1c2gobmV3UXVlcnkpO1xuICAgIHRoaXMuYWRkUXVlcnlUb0Zvcm0obmV3UXVlcnkpO1xuICAgIHRoaXMuc2VsZWN0ZWRRdWVyeUluZGV4ID0gdGhpcy5xdWVyaWVzLmxlbmd0aCAtIDE7XG4gICAgdGhpcy5hZGRRdWVyeS5lbWl0KCk7XG4gIH1cblxuICBwcml2YXRlIGFkZFF1ZXJ5VG9Gb3JtKHF1ZXJ5OiBEYXRhYmFzZVF1ZXJ5KTogdm9pZCB7XG4gICAgY29uc3QgcXVlcnlHcm91cCA9IHRoaXMuZmIuZ3JvdXAoe1xuICAgICAgaWQ6IFtxdWVyeS5pZF0sXG4gICAgICBxdWVyeTogW3F1ZXJ5LnF1ZXJ5LCBWYWxpZGF0b3JzLnJlcXVpcmVkXSxcbiAgICAgIHZhcmlhYmxlOiBbcXVlcnkudmFyaWFibGUsIFZhbGlkYXRvcnMucmVxdWlyZWRdXG4gICAgfSk7XG4gICAgdGhpcy5xdWVyaWVzRm9ybUFycmF5LnB1c2gocXVlcnlHcm91cCk7XG4gIH1cblxuICBkZWxldGVRdWVyeUJ5SWQocXVlcnlJZDogc3RyaW5nKTogdm9pZCB7XG4gICAgY29uc3QgaW5kZXggPSB0aGlzLnF1ZXJpZXMuZmluZEluZGV4KHEgPT4gcS5pZCA9PT0gcXVlcnlJZCk7XG4gICAgaWYgKGluZGV4ICE9PSAtMSkge1xuICAgICAgdGhpcy5xdWVyaWVzLnNwbGljZShpbmRleCwgMSk7XG4gICAgICB0aGlzLnF1ZXJpZXNGb3JtQXJyYXkucmVtb3ZlQXQoaW5kZXgpO1xuICAgICAgaWYgKHRoaXMuc2VsZWN0ZWRRdWVyeUluZGV4ID49IHRoaXMucXVlcmllcy5sZW5ndGgpIHtcbiAgICAgICAgdGhpcy5zZWxlY3RlZFF1ZXJ5SW5kZXggPSBNYXRoLm1heCgwLCB0aGlzLnF1ZXJpZXMubGVuZ3RoIC0gMSk7XG4gICAgICB9XG4gICAgICB0aGlzLmRlbGV0ZVF1ZXJ5LmVtaXQocXVlcnlJZCk7XG4gICAgfVxuICB9XG5cbiAgZ2V0RGJFbnZpcm9ubWVudENvbmZpZygpOiBEeW5hbWljU2VsZWN0RmllbGRDb25maWcge1xuICAgIHJldHVybiB7XG4gICAgICBrZXk6ICdkYkVudmlyb25tZW50JyxcbiAgICAgIHBsYWNlaG9sZGVyOiAnU2VsZWN0IERCIGVudmlyb25tZW50JyxcbiAgICAgIG11bHRpcGxlOiBmYWxzZSxcbiAgICAgIHNlYXJjaGFibGU6IGZhbHNlLFxuICAgICAgb3B0aW9uczogdGhpcy5kYkVudmlyb25tZW50T3B0aW9uc1xuICAgIH07XG4gIH1cblxuICBnZXRDdXJyZW50UXVlcnkoKTogRGF0YWJhc2VRdWVyeSB8IG51bGwge1xuICAgIGlmICh0aGlzLnF1ZXJpZXMubGVuZ3RoID4gMCAmJiB0aGlzLnNlbGVjdGVkUXVlcnlJbmRleCA+PSAwICYmIHRoaXMuc2VsZWN0ZWRRdWVyeUluZGV4IDwgdGhpcy5xdWVyaWVzLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIHRoaXMucXVlcmllc1t0aGlzLnNlbGVjdGVkUXVlcnlJbmRleF07XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgZ2V0Q3VycmVudFF1ZXJ5Rm9ybUdyb3VwKCk6IEZvcm1Hcm91cCB8IG51bGwge1xuICAgIGlmICh0aGlzLnF1ZXJpZXNGb3JtQXJyYXkgJiYgdGhpcy5zZWxlY3RlZFF1ZXJ5SW5kZXggPj0gMCAmJiB0aGlzLnNlbGVjdGVkUXVlcnlJbmRleCA8IHRoaXMucXVlcmllc0Zvcm1BcnJheS5sZW5ndGgpIHtcbiAgICAgIHJldHVybiB0aGlzLnF1ZXJpZXNGb3JtQXJyYXkuYXQodGhpcy5zZWxlY3RlZFF1ZXJ5SW5kZXgpIGFzIEZvcm1Hcm91cDtcbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBvblJ1blF1ZXJ5KCk6IHZvaWQge1xuICAgIGNvbnN0IGRiRW52aXJvbm1lbnQgPSB0aGlzLmRhdGFiYXNlRm9ybS5nZXQoJ2RiRW52aXJvbm1lbnQnKT8udmFsdWU7XG4gICAgY29uc3QgY3VycmVudFF1ZXJ5ID0gdGhpcy5nZXRDdXJyZW50UXVlcnkoKTtcbiAgICBjb25zdCBxdWVyeUZvcm1Hcm91cCA9IHRoaXMuZ2V0Q3VycmVudFF1ZXJ5Rm9ybUdyb3VwKCk7XG5cbiAgICBpZiAoY3VycmVudFF1ZXJ5ICYmIHF1ZXJ5Rm9ybUdyb3VwICYmIGRiRW52aXJvbm1lbnQpIHtcbiAgICAgIGNvbnN0IHF1ZXJ5ID0gcXVlcnlGb3JtR3JvdXAuZ2V0KCdxdWVyeScpPy52YWx1ZSB8fCAnJztcbiAgICAgIGNvbnN0IHZhcmlhYmxlID0gcXVlcnlGb3JtR3JvdXAuZ2V0KCd2YXJpYWJsZScpPy52YWx1ZSB8fCAnJztcbiAgICAgIFxuICAgICAgLy8gVXBkYXRlIHRoZSBxdWVyeSBvYmplY3RcbiAgICAgIGN1cnJlbnRRdWVyeS5xdWVyeSA9IHF1ZXJ5O1xuICAgICAgY3VycmVudFF1ZXJ5LnZhcmlhYmxlID0gdmFyaWFibGU7XG5cbiAgICAgIHRoaXMucnVuUXVlcnkuZW1pdCh7XG4gICAgICAgIHF1ZXJ5LFxuICAgICAgICB2YXJpYWJsZSxcbiAgICAgICAgZGJFbnZpcm9ubWVudFxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgb25TZWxlY3RRdWVyeShpbmRleDogbnVtYmVyKTogdm9pZCB7XG4gICAgdGhpcy5zZWxlY3RlZFF1ZXJ5SW5kZXggPSBpbmRleDtcbiAgfVxuXG4gIG9uVGFiQ2hhbmdlKHRhYjogJ291dHB1dCcgfCAndmVyaWZpY2F0aW9uJyk6IHZvaWQge1xuICAgIHRoaXMuc2VsZWN0ZWRUYWIgPSB0YWI7XG4gIH1cblxuICBvbkNvcHlSZXN1bHRzKCk6IHZvaWQge1xuICAgIC8vIENvcHkgcXVlcnkgcmVzdWx0cyB0byBjbGlwYm9hcmRcbiAgICBpZiAodGhpcy5xdWVyeVJlc3VsdHMgJiYgdGhpcy5xdWVyeVJlc3VsdHMubGVuZ3RoID4gMCkge1xuICAgICAgY29uc3QgdGV4dCA9IEpTT04uc3RyaW5naWZ5KHRoaXMucXVlcnlSZXN1bHRzLCBudWxsLCAyKTtcbiAgICAgIG5hdmlnYXRvci5jbGlwYm9hcmQud3JpdGVUZXh0KHRleHQpLnRoZW4oKCkgPT4ge1xuICAgICAgICAvLyBDb3VsZCBlbWl0IGFuIGV2ZW50IG9yIHNob3cgYSB0b2FzdCBub3RpZmljYXRpb25cbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIG9uQ2FuY2VsKCk6IHZvaWQge1xuICAgIHRoaXMuY2FuY2VsbGVkLmVtaXQoKTtcbiAgfVxuXG4gIG9uQ3JlYXRlU3RlcCgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5kYXRhYmFzZUZvcm0udmFsaWQpIHtcbiAgICAgIGNvbnN0IGZvcm1WYWx1ZSA9IHRoaXMuZGF0YWJhc2VGb3JtLnZhbHVlO1xuICAgICAgY29uc3Qgc3RlcERhdGE6IERhdGFiYXNlRm9ybURhdGEgPSB7XG4gICAgICAgIGRiRW52aXJvbm1lbnQ6IGZvcm1WYWx1ZS5kYkVudmlyb25tZW50LFxuICAgICAgICBxdWVyaWVzOiB0aGlzLnF1ZXJpZXMubWFwKChxdWVyeSwgaW5kZXgpID0+IHtcbiAgICAgICAgICBjb25zdCBxdWVyeUZvcm1Hcm91cCA9IHRoaXMucXVlcmllc0Zvcm1BcnJheS5hdChpbmRleCkgYXMgRm9ybUdyb3VwO1xuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBpZDogcXVlcnkuaWQsXG4gICAgICAgICAgICBxdWVyeTogcXVlcnlGb3JtR3JvdXAuZ2V0KCdxdWVyeScpPy52YWx1ZSB8fCAnJyxcbiAgICAgICAgICAgIHZhcmlhYmxlOiBxdWVyeUZvcm1Hcm91cC5nZXQoJ3ZhcmlhYmxlJyk/LnZhbHVlIHx8ICcnLFxuICAgICAgICAgICAgc3RhdHVzOiBxdWVyeS5zdGF0dXNcbiAgICAgICAgICB9O1xuICAgICAgICB9KVxuICAgICAgfTtcbiAgICAgIHRoaXMuY3JlYXRlU3RlcC5lbWl0KHN0ZXBEYXRhKTtcbiAgICB9XG4gIH1cblxuICBnZXRUYWJsZUNvbHVtbnMoKTogc3RyaW5nW10ge1xuICAgIGlmICghdGhpcy5xdWVyeVJlc3VsdHMgfHwgdGhpcy5xdWVyeVJlc3VsdHMubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gW107XG4gICAgfVxuICAgIHJldHVybiBPYmplY3Qua2V5cyh0aGlzLnF1ZXJ5UmVzdWx0c1swXSk7XG4gIH1cbn1cblxuIiwiPGRpdiBjbGFzcz1cImNxYS1mbGV4IGNxYS1mbGV4LWNvbCBjcWEtaC1mdWxsIGNxYS1iZy13aGl0ZSBjcWEtcHgtNCBjcWEtcHktMlwiPlxuICA8IS0tIEhlYWRlciAtLT5cbiAgPGgyIGNsYXNzPVwiY3FhLXRleHQtWzEycHhdIGNxYS1mb250LXNlbWlib2xkIGNxYS10ZXh0LWJsYWNrLTEwMCBjcWEtbWItNFwiPlxuICAgIENyZWF0ZSBEYXRhYmFzZSBUZXN0IFN0ZXBcbiAgPC9oMj5cblxuICA8IS0tIERCIEVudmlyb25tZW50IFNlY3Rpb24gLS0+XG4gIDxkaXYgY2xhc3M9XCJjcWEtZmxleCBjcWEtaXRlbXMtc3RhcnQgY3FhLWdhcC00IGNxYS1tYi02XCI+XG4gICAgPGRpdiBjbGFzcz1cImNxYS1mbGV4LTFcIj5cbiAgICAgIDxsYWJlbCBjbGFzcz1cImNxYS10ZXh0LXNtIGNxYS1mb250LW1lZGl1bSBjcWEtdGV4dC1ncmF5LTcwMCBjcWEtbWItMS41IGNxYS1ibG9ja1wiPlxuICAgICAgICBEQiBFbnZpcm9ubWVudCA8c3BhbiBjbGFzcz1cImNxYS10ZXh0LXJlZC01MDBcIj4qPC9zcGFuPlxuICAgICAgPC9sYWJlbD5cbiAgICAgIDxjcWEtZHluYW1pYy1zZWxlY3RcbiAgICAgICAgW2Zvcm1dPVwiZGF0YWJhc2VGb3JtXCJcbiAgICAgICAgW2NvbmZpZ109XCJnZXREYkVudmlyb25tZW50Q29uZmlnKClcIj5cbiAgICAgIDwvY3FhLWR5bmFtaWMtc2VsZWN0PlxuICAgICAgPHAgY2xhc3M9XCJjcWEtdGV4dC14cyBjcWEtdGV4dC1ncmF5LTUwMCBjcWEtbXQtMVwiPlxuICAgICAgICBVc2VzIERhdGFiYXNlIGVudmlyb25tZW50cyBmcm9tIEVudmlyb25tZW50cy5cbiAgICAgIDwvcD5cbiAgICA8L2Rpdj5cbiAgICA8ZGl2IGNsYXNzPVwiY3FhLWZsZXggY3FhLWl0ZW1zLWVuZCBjcWEtbWItMVwiPlxuICAgICAgPGNxYS1idXR0b25cbiAgICAgICAgdmFyaWFudD1cImZpbGxlZFwiXG4gICAgICAgIHRleHQ9XCJSdW4gUXVlcnlcIlxuICAgICAgICBbY3VzdG9tQ2xhc3NdPVwiJ2NxYS13aGl0ZXNwYWNlLW5vd3JhcCdcIlxuICAgICAgICAoY2xpY2tlZCk9XCJvblJ1blF1ZXJ5KClcIlxuICAgICAgICBbZGlzYWJsZWRdPVwiIWRhdGFiYXNlRm9ybS5nZXQoJ2RiRW52aXJvbm1lbnQnKT8udmFsdWUgfHwgaXNMb2FkaW5nXCI+XG4gICAgICA8L2NxYS1idXR0b24+XG4gICAgPC9kaXY+XG4gIDwvZGl2PlxuXG4gIDwhLS0gTWFpbiBDb250ZW50OiBUd28gQ29sdW1uIExheW91dCAtLT5cbiAgPGRpdiBjbGFzcz1cImNxYS1mbGV4IGNxYS1nYXAtNCBjcWEtZmxleC0xIGNxYS1vdmVyZmxvdy1oaWRkZW4gY3FhLW1iLTZcIj5cbiAgICA8IS0tIExlZnQgUGFuZWw6IFF1ZXJ5IExpc3QgLS0+XG4gICAgPGRpdiBjbGFzcz1cImNxYS13LTY0IGNxYS1mbGV4LXNocmluay0wIGNxYS1mbGV4IGNxYS1mbGV4LWNvbCBjcWEtYm9yZGVyIGNxYS1ib3JkZXItZ3JheS0yMDAgY3FhLXJvdW5kZWQtbGcgY3FhLW92ZXJmbG93LWhpZGRlblwiPlxuICAgICAgPGRpdiBjbGFzcz1cImNxYS1wLTMgY3FhLWJnLWdyYXktNTAgY3FhLWJvcmRlci1iIGNxYS1ib3JkZXItZ3JheS0yMDBcIj5cbiAgICAgICAgPGgzIGNsYXNzPVwiY3FhLXRleHQtc20gY3FhLWZvbnQtc2VtaWJvbGQgY3FhLXRleHQtZ3JheS05MDBcIj5RdWVyaWVzPC9oMz5cbiAgICAgIDwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cImNxYS1mbGV4LTEgY3FhLW92ZXJmbG93LXktYXV0byBjcWEtcC0yXCI+XG4gICAgICAgIDxkaXYgKm5nRm9yPVwibGV0IHF1ZXJ5IG9mIHF1ZXJpZXM7IGxldCBpID0gaW5kZXhcIlxuICAgICAgICAgICAgIGNsYXNzPVwiY3FhLWZsZXggY3FhLWl0ZW1zLWNlbnRlciBjcWEtanVzdGlmeS1iZXR3ZWVuIGNxYS1wLTIgY3FhLXJvdW5kZWQgY3FhLWN1cnNvci1wb2ludGVyIGNxYS1tYi0xXCJcbiAgICAgICAgICAgICBbY2xhc3MuY3FhLWJnLWJsdWUtNTBdPVwic2VsZWN0ZWRRdWVyeUluZGV4ID09PSBpXCJcbiAgICAgICAgICAgICBbY2xhc3MuY3FhLWJvcmRlcl09XCJzZWxlY3RlZFF1ZXJ5SW5kZXggPT09IGlcIlxuICAgICAgICAgICAgIFtjbGFzcy5jcWEtYm9yZGVyLWJsdWUtNTAwXT1cInNlbGVjdGVkUXVlcnlJbmRleCA9PT0gaVwiXG4gICAgICAgICAgICAgKGNsaWNrKT1cIm9uU2VsZWN0UXVlcnkoaSlcIj5cbiAgICAgICAgICA8c3BhbiBjbGFzcz1cImNxYS10ZXh0LXNtIGNxYS1mb250LW1lZGl1bSBjcWEtdGV4dC1ncmF5LTkwMFwiPlF1ZXJ5IHt7IGkgKyAxIH19PC9zcGFuPlxuICAgICAgICAgIDxjcWEtYmFkZ2VcbiAgICAgICAgICAgICpuZ0lmPVwicXVlcnkuc3RhdHVzXCJcbiAgICAgICAgICAgIFtsYWJlbF09XCJxdWVyeS5zdGF0dXMgPT09ICdwYXNzZWQnID8gJ1Bhc3NlZCcgOiBxdWVyeS5zdGF0dXMgPT09ICdmYWlsZWQnID8gJ0ZhaWxlZCcgOiAnUGVuZGluZydcIlxuICAgICAgICAgICAgW3ZhcmlhbnRdPVwicXVlcnkuc3RhdHVzID09PSAncGFzc2VkJyA/ICdzdWNjZXNzJyA6IHF1ZXJ5LnN0YXR1cyA9PT0gJ2ZhaWxlZCcgPyAnZXJyb3InIDogJ2RlZmF1bHQnXCJcbiAgICAgICAgICAgIHNpemU9XCJzbWFsbFwiPlxuICAgICAgICAgIDwvY3FhLWJhZGdlPlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuXG4gICAgPCEtLSBSaWdodCBQYW5lbDogUXVlcnkgRWRpdG9yIC0tPlxuICAgIDxkaXYgY2xhc3M9XCJjcWEtZmxleC0xIGNxYS1mbGV4IGNxYS1mbGV4LWNvbCBjcWEtYm9yZGVyIGNxYS1ib3JkZXItZ3JheS0yMDAgY3FhLXJvdW5kZWQtbGcgY3FhLW92ZXJmbG93LWhpZGRlblwiPlxuICAgICAgPGRpdiBjbGFzcz1cImNxYS1wLTMgY3FhLWJnLWdyYXktNTAgY3FhLWJvcmRlci1iIGNxYS1ib3JkZXItZ3JheS0yMDBcIj5cbiAgICAgICAgPGgzIGNsYXNzPVwiY3FhLXRleHQtc20gY3FhLWZvbnQtc2VtaWJvbGQgY3FhLXRleHQtZ3JheS05MDBcIj5RdWVyeSAmIFN0b3JlIFJlc3BvbnNlPC9oMz5cbiAgICAgIDwvZGl2PlxuICAgICAgXG4gICAgICA8ZGl2IGNsYXNzPVwiY3FhLWZsZXgtMSBjcWEtb3ZlcmZsb3cteS1hdXRvIGNxYS1wLTQgY3FhLWZsZXggY3FhLWZsZXgtY29sIGNxYS1nYXAtNFwiPlxuICAgICAgICA8IS0tIFNRTCBRdWVyeSBUZXh0YXJlYSAtLT5cbiAgICAgICAgPGRpdiBjbGFzcz1cImNxYS1mbGV4LTEgY3FhLWZsZXggY3FhLWZsZXgtY29sXCI+XG4gICAgICAgICAgPGNxYS1jdXN0b20tdGV4dGFyZWFcbiAgICAgICAgICAgIFtwbGFjZWhvbGRlcl09XCInRW50ZXIgeW91ciBTUUwgcXVlcnkgaGVyZS4uLidcIlxuICAgICAgICAgICAgW3ZhbHVlXT1cImdldEN1cnJlbnRRdWVyeUZvcm1Hcm91cCgpPy5nZXQoJ3F1ZXJ5Jyk/LnZhbHVlIHx8ICcnXCJcbiAgICAgICAgICAgIFtmdWxsV2lkdGhdPVwidHJ1ZVwiXG4gICAgICAgICAgICBbcm93c109XCI4XCJcbiAgICAgICAgICAgICh2YWx1ZUNoYW5nZSk9XCJnZXRDdXJyZW50UXVlcnlGb3JtR3JvdXAoKT8uZ2V0KCdxdWVyeScpPy5zZXRWYWx1ZSgkZXZlbnQpXCI+XG4gICAgICAgICAgPC9jcWEtY3VzdG9tLXRleHRhcmVhPlxuICAgICAgICA8L2Rpdj5cblxuICAgICAgICA8IS0tIFZhcmlhYmxlIElucHV0IC0tPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiY3FhLWZsZXggY3FhLWdhcC00XCI+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImNxYS1mbGV4LTFcIj5cbiAgICAgICAgICAgIDxsYWJlbCBjbGFzcz1cImNxYS10ZXh0LXNtIGNxYS1mb250LW1lZGl1bSBjcWEtdGV4dC1ncmF5LTcwMCBjcWEtbWItMS41IGNxYS1ibG9ja1wiPlxuICAgICAgICAgICAgICBWYXJpYWJsZVxuICAgICAgICAgICAgPC9sYWJlbD5cbiAgICAgICAgICAgIDxjcWEtY3VzdG9tLWlucHV0XG4gICAgICAgICAgICAgIFtwbGFjZWhvbGRlcl09XCInVmFyaWFibGUgbmFtZSdcIlxuICAgICAgICAgICAgICBbdmFsdWVdPVwiZ2V0Q3VycmVudFF1ZXJ5Rm9ybUdyb3VwKCk/LmdldCgndmFyaWFibGUnKT8udmFsdWUgfHwgJydcIlxuICAgICAgICAgICAgICBbZnVsbFdpZHRoXT1cInRydWVcIlxuICAgICAgICAgICAgICAodmFsdWVDaGFuZ2UpPVwiZ2V0Q3VycmVudFF1ZXJ5Rm9ybUdyb3VwKCk/LmdldCgndmFyaWFibGUnKT8uc2V0VmFsdWUoJGV2ZW50KVwiPlxuICAgICAgICAgICAgPC9jcWEtY3VzdG9tLWlucHV0PlxuICAgICAgICAgICAgPHAgY2xhc3M9XCJjcWEtdGV4dC14cyBjcWEtdGV4dC1ncmF5LTUwMCBjcWEtbXQtMVwiPlxuICAgICAgICAgICAgICBVc2UgbGV0dGVycywgbnVtYmVycywgdW5kZXJzY29yZS4gTm8gc3BhY2VzLiBVbmlxdWUgcGVyIHN0ZXAuIENhc2Ugc2Vuc2l0aXZlLlxuICAgICAgICAgICAgPC9wPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cblxuICAgICAgICA8IS0tIEFjdGlvbiBCdXR0b25zIC0tPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiY3FhLWZsZXggY3FhLWl0ZW1zLWNlbnRlciBjcWEtZ2FwLTJcIj5cbiAgICAgICAgICA8Y3FhLWJ1dHRvblxuICAgICAgICAgICAgdmFyaWFudD1cIm91dGxpbmVkXCJcbiAgICAgICAgICAgIHRleHQ9XCJBZGQgUXVlcnlcIlxuICAgICAgICAgICAgaWNvbj1cImFkZFwiXG4gICAgICAgICAgICAoY2xpY2tlZCk9XCJhZGROZXdRdWVyeSgpXCI+XG4gICAgICAgICAgPC9jcWEtYnV0dG9uPlxuICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgY2xhc3M9XCJjcWEtZmxleCBjcWEtaXRlbXMtY2VudGVyIGNxYS1qdXN0aWZ5LWNlbnRlciBjcWEtdy0xMCBjcWEtaC0xMCBjcWEtcm91bmRlZCBjcWEtdGV4dC1ncmF5LTUwMCBob3ZlcjpjcWEtdGV4dC1ncmF5LTcwMCBob3ZlcjpjcWEtYmctZ3JheS0xMDAgY3FhLXRyYW5zaXRpb24tY29sb3JzIGNxYS1ib3JkZXIgY3FhLWJvcmRlci1ncmF5LTMwMFwiXG4gICAgICAgICAgICAoY2xpY2spPVwiZGVsZXRlUXVlcnlCeUlkKGdldEN1cnJlbnRRdWVyeSgpPy5pZCB8fCAnJylcIlxuICAgICAgICAgICAgW2Rpc2FibGVkXT1cInF1ZXJpZXMubGVuZ3RoIDw9IDFcIlxuICAgICAgICAgICAgW2F0dHIuYXJpYS1sYWJlbF09XCInRGVsZXRlIHF1ZXJ5J1wiPlxuICAgICAgICAgICAgPG1hdC1pY29uIGNsYXNzPVwiY3FhLXRleHQtbGdcIj5kZWxldGU8L21hdC1pY29uPlxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgIDxjcWEtYnV0dG9uXG4gICAgICAgICAgICB2YXJpYW50PVwiZmlsbGVkXCJcbiAgICAgICAgICAgIHRleHQ9XCJSdW5cIlxuICAgICAgICAgICAgaWNvbj1cInBsYXlfYXJyb3dcIlxuICAgICAgICAgICAgKGNsaWNrZWQpPVwib25SdW5RdWVyeSgpXCJcbiAgICAgICAgICAgIFtkaXNhYmxlZF09XCIhZGF0YWJhc2VGb3JtLmdldCgnZGJFbnZpcm9ubWVudCcpPy52YWx1ZSB8fCBpc0xvYWRpbmdcIj5cbiAgICAgICAgICA8L2NxYS1idXR0b24+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG4gIDwvZGl2PlxuXG4gIDwhLS0gUmVzdWx0cyBTZWN0aW9uIC0tPlxuICA8ZGl2IGNsYXNzPVwiY3FhLWZsZXggY3FhLWZsZXgtY29sIGNxYS1ib3JkZXIgY3FhLWJvcmRlci1ncmF5LTIwMCBjcWEtcm91bmRlZC1sZyBjcWEtb3ZlcmZsb3ctaGlkZGVuIGNxYS1tYi02XCI+XG4gICAgPCEtLSBUYWJzIC0tPlxuICAgIDxkaXYgY2xhc3M9XCJjcWEtZmxleCBjcWEtaXRlbXMtY2VudGVyIGNxYS1ib3JkZXItYiBjcWEtYm9yZGVyLWdyYXktMjAwIGNxYS1iZy1ncmF5LTUwXCI+XG4gICAgICA8YnV0dG9uXG4gICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICBjbGFzcz1cImNxYS1weC00IGNxYS1weS0yIGNxYS10ZXh0LXNtIGNxYS1mb250LW1lZGl1bSBjcWEtdHJhbnNpdGlvbi1jb2xvcnMgY3FhLWJvcmRlci1iLTJcIlxuICAgICAgICBbY2xhc3MuY3FhLXRleHQtYmx1ZS02MDBdPVwic2VsZWN0ZWRUYWIgPT09ICdvdXRwdXQnXCJcbiAgICAgICAgW2NsYXNzLmNxYS1ib3JkZXItYmx1ZS02MDBdPVwic2VsZWN0ZWRUYWIgPT09ICdvdXRwdXQnXCJcbiAgICAgICAgW2NsYXNzLmNxYS10ZXh0LWdyYXktNjAwXT1cInNlbGVjdGVkVGFiICE9PSAnb3V0cHV0J1wiXG4gICAgICAgIFtjbGFzcy5jcWEtYm9yZGVyLXRyYW5zcGFyZW50XT1cInNlbGVjdGVkVGFiICE9PSAnb3V0cHV0J1wiXG4gICAgICAgIChjbGljayk9XCJvblRhYkNoYW5nZSgnb3V0cHV0JylcIj5cbiAgICAgICAgT3V0cHV0XG4gICAgICA8L2J1dHRvbj5cbiAgICAgIDxidXR0b25cbiAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgIGNsYXNzPVwiY3FhLXB4LTQgY3FhLXB5LTIgY3FhLXRleHQtc20gY3FhLWZvbnQtbWVkaXVtIGNxYS10cmFuc2l0aW9uLWNvbG9ycyBjcWEtYm9yZGVyLWItMlwiXG4gICAgICAgIFtjbGFzcy5jcWEtdGV4dC1ibHVlLTYwMF09XCJzZWxlY3RlZFRhYiA9PT0gJ3ZlcmlmaWNhdGlvbidcIlxuICAgICAgICBbY2xhc3MuY3FhLWJvcmRlci1ibHVlLTYwMF09XCJzZWxlY3RlZFRhYiA9PT0gJ3ZlcmlmaWNhdGlvbidcIlxuICAgICAgICBbY2xhc3MuY3FhLXRleHQtZ3JheS02MDBdPVwic2VsZWN0ZWRUYWIgIT09ICd2ZXJpZmljYXRpb24nXCJcbiAgICAgICAgW2NsYXNzLmNxYS1ib3JkZXItdHJhbnNwYXJlbnRdPVwic2VsZWN0ZWRUYWIgIT09ICd2ZXJpZmljYXRpb24nXCJcbiAgICAgICAgKGNsaWNrKT1cIm9uVGFiQ2hhbmdlKCd2ZXJpZmljYXRpb24nKVwiPlxuICAgICAgICBWZXJpZmljYXRpb25cbiAgICAgIDwvYnV0dG9uPlxuICAgIDwvZGl2PlxuXG4gICAgPCEtLSBUYWIgQ29udGVudCAtLT5cbiAgICA8ZGl2IGNsYXNzPVwiY3FhLXAtNFwiPlxuICAgICAgPCEtLSBPdXRwdXQgVGFiIC0tPlxuICAgICAgPGRpdiAqbmdJZj1cInNlbGVjdGVkVGFiID09PSAnb3V0cHV0J1wiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiY3FhLWZsZXggY3FhLWl0ZW1zLWNlbnRlciBjcWEtanVzdGlmeS1iZXR3ZWVuIGNxYS1tYi0zXCI+XG4gICAgICAgICAgPGg0IGNsYXNzPVwiY3FhLXRleHQtc20gY3FhLWZvbnQtc2VtaWJvbGQgY3FhLXRleHQtZ3JheS05MDBcIj5RdWVyeSBSZXN1bHRzPC9oND5cbiAgICAgICAgICA8Y3FhLWJ1dHRvblxuICAgICAgICAgICAgdmFyaWFudD1cInRleHRcIlxuICAgICAgICAgICAgdGV4dD1cIkNvcHlcIlxuICAgICAgICAgICAgaWNvbj1cImNvbnRlbnRfY29weVwiXG4gICAgICAgICAgICBbY3VzdG9tQ2xhc3NdPVwiJ2NxYS10ZXh0LWJsdWUtNjAwJ1wiXG4gICAgICAgICAgICAoY2xpY2tlZCk9XCJvbkNvcHlSZXN1bHRzKClcIj5cbiAgICAgICAgICA8L2NxYS1idXR0b24+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICBcbiAgICAgICAgPCEtLSBSZXN1bHRzIFRhYmxlIC0tPlxuICAgICAgICA8ZGl2ICpuZ0lmPVwicXVlcnlSZXN1bHRzICYmIHF1ZXJ5UmVzdWx0cy5sZW5ndGggPiAwXCIgY2xhc3M9XCJjcWEtb3ZlcmZsb3cteC1hdXRvXCI+XG4gICAgICAgICAgPHRhYmxlIGNsYXNzPVwiY3FhLXctZnVsbCBjcWEtYm9yZGVyLWNvbGxhcHNlXCI+XG4gICAgICAgICAgICA8dGhlYWQ+XG4gICAgICAgICAgICAgIDx0ciBjbGFzcz1cImNxYS1iZy1ncmF5LTUwIGNxYS1ib3JkZXItYiBjcWEtYm9yZGVyLWdyYXktMjAwXCI+XG4gICAgICAgICAgICAgICAgPHRoICpuZ0Zvcj1cImxldCBrZXkgb2YgZ2V0VGFibGVDb2x1bW5zKClcIiBcbiAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJjcWEtcHgtNCBjcWEtcHktMiBjcWEtdGV4dC1sZWZ0IGNxYS10ZXh0LXhzIGNxYS1mb250LXNlbWlib2xkIGNxYS10ZXh0LWdyYXktNzAwIGNxYS11cHBlcmNhc2VcIj5cbiAgICAgICAgICAgICAgICAgIHt7IGtleSB9fVxuICAgICAgICAgICAgICAgIDwvdGg+XG4gICAgICAgICAgICAgIDwvdHI+XG4gICAgICAgICAgICA8L3RoZWFkPlxuICAgICAgICAgICAgPHRib2R5PlxuICAgICAgICAgICAgICA8dHIgKm5nRm9yPVwibGV0IHJvdyBvZiBxdWVyeVJlc3VsdHNcIiBcbiAgICAgICAgICAgICAgICAgIGNsYXNzPVwiY3FhLWJvcmRlci1iIGNxYS1ib3JkZXItZ3JheS0yMDAgaG92ZXI6Y3FhLWJnLWdyYXktNTBcIj5cbiAgICAgICAgICAgICAgICA8dGQgKm5nRm9yPVwibGV0IGtleSBvZiBnZXRUYWJsZUNvbHVtbnMoKVwiIFxuICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImNxYS1weC00IGNxYS1weS0yIGNxYS10ZXh0LXNtIGNxYS10ZXh0LWdyYXktOTAwXCI+XG4gICAgICAgICAgICAgICAgICB7eyByb3dba2V5XSB9fVxuICAgICAgICAgICAgICAgIDwvdGQ+XG4gICAgICAgICAgICAgIDwvdHI+XG4gICAgICAgICAgICA8L3Rib2R5PlxuICAgICAgICAgIDwvdGFibGU+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICBcbiAgICAgICAgPGRpdiAqbmdJZj1cIiFxdWVyeVJlc3VsdHMgfHwgcXVlcnlSZXN1bHRzLmxlbmd0aCA9PT0gMFwiIFxuICAgICAgICAgICAgIGNsYXNzPVwiY3FhLXRleHQtY2VudGVyIGNxYS1weS04IGNxYS10ZXh0LWdyYXktNDAwIGNxYS10ZXh0LXNtXCI+XG4gICAgICAgICAgTm8gcmVzdWx0cyB5ZXQuIFJ1biBhIHF1ZXJ5IHRvIHNlZSByZXN1bHRzLlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuXG4gICAgICA8IS0tIFZlcmlmaWNhdGlvbiBUYWIgLS0+XG4gICAgICA8ZGl2ICpuZ0lmPVwic2VsZWN0ZWRUYWIgPT09ICd2ZXJpZmljYXRpb24nXCI+XG4gICAgICAgIDxwIGNsYXNzPVwiY3FhLXRleHQtc20gY3FhLXRleHQtZ3JheS02MDBcIj5WZXJpZmljYXRpb24gc2V0dGluZ3Mgd2lsbCBiZSBhdmFpbGFibGUgaGVyZS48L3A+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG5cbiAgPCEtLSBBY3Rpb24gQnV0dG9ucyAtLT5cbiAgPGRpdiBjbGFzcz1cImNxYS1mbGV4IGNxYS13LWZ1bGwgY3FhLWdhcC0yIGNxYS1tdC1hdXRvIGNxYS1wdC00IGNxYS1ib3JkZXItdCBjcWEtYm9yZGVyLWdyYXktMjAwXCI+XG4gICAgPGNxYS1idXR0b25cbiAgICAgIGNsYXNzPVwiY3FhLXctMS8yXCJcbiAgICAgIHZhcmlhbnQ9XCJvdXRsaW5lZFwiXG4gICAgICB0ZXh0PVwiQ2FuY2VsXCJcbiAgICAgIFtjdXN0b21DbGFzc109XCInY3FhLWZsZXgtMSBjcWEtdy1mdWxsJ1wiXG4gICAgICAoY2xpY2tlZCk9XCJvbkNhbmNlbCgpXCI+XG4gICAgPC9jcWEtYnV0dG9uPlxuICAgIDxjcWEtYnV0dG9uXG4gICAgICBjbGFzcz1cImNxYS13LTEvMlwiXG4gICAgICB2YXJpYW50PVwiZmlsbGVkXCJcbiAgICAgIHRleHQ9XCJDcmVhdGUgU3RlcFwiXG4gICAgICBbY3VzdG9tQ2xhc3NdPVwiJ2NxYS1mbGV4LTEgY3FhLXctZnVsbCdcIlxuICAgICAgKGNsaWNrZWQpPVwib25DcmVhdGVTdGVwKClcIj5cbiAgICA8L2NxYS1idXR0b24+XG4gIDwvZGl2PlxuPC9kaXY+XG5cbiJdfQ==
|