@cqa-lib/cqa-ui 1.1.525 → 1.1.527

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/esm2020/lib/assets/images/image-assets.constants.mjs +3 -1
  2. package/esm2020/lib/compare-runs/compare-runs.component.mjs +1 -1
  3. package/esm2020/lib/execution-screen/db-query-execution-item/db-query-execution-item.component.mjs +1 -1
  4. package/esm2020/lib/execution-screen/db-verification-step/db-verification-step.component.mjs +1 -1
  5. package/esm2020/lib/iterations-loop/iterations-loop.component.mjs +1 -1
  6. package/esm2020/lib/segment-control/segment-control.component.mjs +6 -3
  7. package/esm2020/lib/simulator/simulator.component.mjs +3 -3
  8. package/esm2020/lib/step-builder/step-builder-document-generation-template-step/step-builder-document-generation-template-step.component.mjs +1 -1
  9. package/esm2020/lib/table/dynamic-table/dynamic-table.component.mjs +148 -4
  10. package/esm2020/lib/templates/modular-table-template/dialogs/delete-folder-dialog.component.mjs +181 -0
  11. package/esm2020/lib/templates/modular-table-template/dialogs/move-to-folder-dialog.component.mjs +264 -0
  12. package/esm2020/lib/templates/modular-table-template/dialogs/new-folder-dialog.component.mjs +352 -0
  13. package/esm2020/lib/templates/modular-table-template/directives/folder-drag.directive.mjs +45 -0
  14. package/esm2020/lib/templates/modular-table-template/directives/folder-drop.directive.mjs +95 -0
  15. package/esm2020/lib/templates/modular-table-template/directives/row-drag.directive.mjs +44 -0
  16. package/esm2020/lib/templates/modular-table-template/folder-sidebar/folder-sidebar.component.mjs +479 -0
  17. package/esm2020/lib/templates/modular-table-template/modular-table-template.component.mjs +1475 -0
  18. package/esm2020/lib/templates/modular-table-template/modular-table-template.models.mjs +79 -0
  19. package/esm2020/lib/templates/table-template.component.mjs +88 -12
  20. package/esm2020/lib/test-case-details/api-edit-step/api-edit-step.component.mjs +1 -1
  21. package/esm2020/lib/ui-kit.module.mjs +41 -1
  22. package/esm2020/public-api.mjs +10 -1
  23. package/fesm2015/cqa-lib-cqa-ui.mjs +3409 -179
  24. package/fesm2015/cqa-lib-cqa-ui.mjs.map +1 -1
  25. package/fesm2020/cqa-lib-cqa-ui.mjs +3389 -177
  26. package/fesm2020/cqa-lib-cqa-ui.mjs.map +1 -1
  27. package/lib/assets/images/image-assets.constants.d.ts +1 -0
  28. package/lib/segment-control/segment-control.component.d.ts +2 -1
  29. package/lib/table/dynamic-table/dynamic-table.component.d.ts +43 -1
  30. package/lib/templates/modular-table-template/dialogs/delete-folder-dialog.component.d.ts +34 -0
  31. package/lib/templates/modular-table-template/dialogs/move-to-folder-dialog.component.d.ts +57 -0
  32. package/lib/templates/modular-table-template/dialogs/new-folder-dialog.component.d.ts +79 -0
  33. package/lib/templates/modular-table-template/directives/folder-drag.directive.d.ts +10 -0
  34. package/lib/templates/modular-table-template/directives/folder-drop.directive.d.ts +22 -0
  35. package/lib/templates/modular-table-template/directives/row-drag.directive.d.ts +10 -0
  36. package/lib/templates/modular-table-template/folder-sidebar/folder-sidebar.component.d.ts +149 -0
  37. package/lib/templates/modular-table-template/modular-table-template.component.d.ts +453 -0
  38. package/lib/templates/modular-table-template/modular-table-template.models.d.ts +150 -0
  39. package/lib/templates/table-template.component.d.ts +40 -2
  40. package/lib/ui-kit.module.d.ts +153 -145
  41. package/package.json +1 -1
  42. package/public-api.d.ts +9 -0
  43. package/src/lib/assets/images/EmptyFolderState.png +0 -0
  44. package/src/lib/assets/images/image-assets.constants.ts +3 -0
  45. package/styles.css +1 -1
@@ -0,0 +1,352 @@
1
+ import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output, } from '@angular/core';
2
+ import { FormControl, FormGroup } from '@angular/forms';
3
+ import { DEFAULT_MODULAR_LABELS } from '../modular-table-template.models';
4
+ import * as i0 from "@angular/core";
5
+ import * as i1 from "../../../custom-input/custom-input.component";
6
+ import * as i2 from "../../../dynamic-select/dynamic-select-field.component";
7
+ import * as i3 from "@angular/common";
8
+ export const DEFAULT_FOLDER_COLOR = '#99999E';
9
+ const PRESET_FOLDER_COLORS = [
10
+ DEFAULT_FOLDER_COLOR,
11
+ '#4F46E5',
12
+ '#06B6D4',
13
+ '#10B981',
14
+ '#F59E0B',
15
+ '#EF4444',
16
+ '#EC4899',
17
+ '#8B5CF6',
18
+ ];
19
+ /**
20
+ * Body of the "New Folder" dialog.
21
+ *
22
+ * Uses reusable library components (`cqa-custom-input` for the name field,
23
+ * `cqa-dynamic-select` for the parent dropdown) so hosts can drop this dialog
24
+ * into their own modal shell without worrying about styling drift.
25
+ *
26
+ * Two integration paths:
27
+ *
28
+ * 1. **From within this library** via `DialogService.open(...)`. The outer
29
+ * `cqa-dialog` supplies title/description/Cancel/Create-folder buttons; the
30
+ * Create button reads `name` + `parentId` via `getComponentInstance()`.
31
+ *
32
+ * 2. **Host-driven** — host renders `<cqa-new-folder-dialog>` inside its own
33
+ * modal and listens to `(submitted)` / `(cancelled)` / `(nameChange)` /
34
+ * `(parentIdChange)`.
35
+ */
36
+ export class NewFolderDialogComponent {
37
+ constructor(cdr) {
38
+ this.cdr = cdr;
39
+ // NOTE: These inputs are declared as setters (instead of plain @Input fields)
40
+ // because `DialogService.open(...)` assigns the `inputs` map via direct
41
+ // property assignment *after* `attachComponent` has already run the
42
+ // component's `ngOnInit`. Direct assignment bypasses `ngOnChanges`, so without
43
+ // setters the `parentSelectConfig` would be built from a default empty folders
44
+ // array and the parent-folder dropdown would render empty / appear broken.
45
+ this._folders = [];
46
+ this._labels = { ...DEFAULT_MODULAR_LABELS };
47
+ this.name = '';
48
+ this._parentId = null;
49
+ this.color = DEFAULT_FOLDER_COLOR;
50
+ this.presetColors = PRESET_FOLDER_COLORS;
51
+ this.rainbowBorder = 'conic-gradient(from 0deg, #ef4444, #f59e0b, #eab308, #10b981, #06b6d4, #4f46e5, #8b5cf6, #ec4899, #ef4444)';
52
+ this.nameChange = new EventEmitter();
53
+ this.parentIdChange = new EventEmitter();
54
+ this.colorChange = new EventEmitter();
55
+ this.submitted = new EventEmitter();
56
+ this.cancelled = new EventEmitter();
57
+ /** Reactive form used by cqa-dynamic-select. Untyped to match the project's Angular 13.4 forms API. */
58
+ this.parentForm = new FormGroup({ parentId: new FormControl(null) });
59
+ this.parentOptions = [];
60
+ this.rebuildSelectConfig(); // ensure config exists even before first input set
61
+ }
62
+ set folders(value) {
63
+ this._folders = value || [];
64
+ this.rebuildOptions();
65
+ this.rebuildSelectConfig();
66
+ }
67
+ get folders() { return this._folders; }
68
+ set labels(value) {
69
+ this._labels = value || { ...DEFAULT_MODULAR_LABELS };
70
+ this.rebuildSelectConfig();
71
+ }
72
+ get labels() { return this._labels; }
73
+ set parentId(value) {
74
+ this._parentId = value ?? null;
75
+ this.syncParentControl();
76
+ }
77
+ get parentId() { return this._parentId; }
78
+ ngOnInit() {
79
+ // Setters above already rebuilt config once folders/labels were assigned. This
80
+ // just ensures the form control matches the current parentId value in case
81
+ // ordering of input assignment differs.
82
+ this.syncParentControl();
83
+ }
84
+ rebuildSelectConfig() {
85
+ this.parentSelectConfig = {
86
+ key: 'parentId',
87
+ label: this.labels.newFolderDialogParentLabel,
88
+ placeholder: this.labels.newFolderDialogParentNone,
89
+ searchable: false,
90
+ multiple: false,
91
+ closeOnSelect: true,
92
+ options: [
93
+ // `getOptionValue` in cqa-dynamic-select returns `id ?? value`, so using
94
+ // `value: null` (with no id) yields a stable `null` resolved value that
95
+ // matches the FormControl's null state.
96
+ { value: null, name: this.labels.newFolderDialogParentNone },
97
+ ...this.parentOptions.map(o => ({ id: o.id, name: o.label })),
98
+ ],
99
+ };
100
+ }
101
+ rebuildOptions() {
102
+ const opts = [];
103
+ const walk = (nodes, trail) => {
104
+ for (const n of nodes || []) {
105
+ const label = [...trail, n.name].join(' › ');
106
+ opts.push({ id: n.id, label });
107
+ if (n.children?.length)
108
+ walk(n.children, [...trail, n.name]);
109
+ }
110
+ };
111
+ walk(this.folders, []);
112
+ this.parentOptions = opts;
113
+ this.cdr.markForCheck();
114
+ }
115
+ syncParentControl() {
116
+ // Keep the reactive form in sync with the `parentId` input without bouncing events.
117
+ this.parentForm.get('parentId')?.setValue(this.parentId ?? null, { emitEvent: false });
118
+ }
119
+ onNameChange(value) {
120
+ this.name = value;
121
+ this.nameChange.emit(value);
122
+ }
123
+ onParentSelectionChange(event) {
124
+ // cqa-dynamic-select resolves options to `id ?? value`; option ids in the
125
+ // parent tree are numeric so we coerce defensively.
126
+ const raw = event?.value;
127
+ let next = null;
128
+ if (raw != null) {
129
+ const coerced = typeof raw === 'number' ? raw : Number(raw);
130
+ if (Number.isFinite(coerced))
131
+ next = coerced;
132
+ }
133
+ this.parentId = next;
134
+ this.parentIdChange.emit(next);
135
+ }
136
+ isColor(c) {
137
+ return (this.color || '').toLowerCase() === (c || '').toLowerCase();
138
+ }
139
+ get isCustomColor() {
140
+ const c = (this.color || '').toLowerCase();
141
+ return !!c && !this.presetColors.some(p => p.toLowerCase() === c);
142
+ }
143
+ onColorChange(value) {
144
+ const next = value || DEFAULT_FOLDER_COLOR;
145
+ if (this.color === next)
146
+ return;
147
+ this.color = next;
148
+ this.colorChange.emit(next);
149
+ this.cdr.markForCheck();
150
+ }
151
+ onColorInputEvent(event) {
152
+ const target = event.target;
153
+ if (target)
154
+ this.onColorChange(target.value);
155
+ }
156
+ /** Returns true when the current state is a valid submission (non-empty, trimmed name). */
157
+ get isValid() {
158
+ return !!(this.name || '').trim();
159
+ }
160
+ submit() {
161
+ if (!this.isValid)
162
+ return;
163
+ this.submitted.emit({
164
+ name: (this.name || '').trim(),
165
+ parentId: this.parentId,
166
+ color: this.color || DEFAULT_FOLDER_COLOR,
167
+ });
168
+ }
169
+ }
170
+ NewFolderDialogComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: NewFolderDialogComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
171
+ NewFolderDialogComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: NewFolderDialogComponent, selector: "cqa-new-folder-dialog", inputs: { folders: "folders", labels: "labels", name: "name", parentId: "parentId", color: "color" }, outputs: { nameChange: "nameChange", parentIdChange: "parentIdChange", colorChange: "colorChange", submitted: "submitted", cancelled: "cancelled" }, host: { classAttribute: "cqa-ui-root" }, ngImport: i0, template: `
172
+ <div class="cqa-flex cqa-flex-col cqa-gap-5 cqa-w-full">
173
+ <!-- Folder name -->
174
+ <cqa-custom-input
175
+ [label]="labels.newFolderDialogNameLabel"
176
+ [required]="true"
177
+ [placeholder]="labels.newFolderDialogNamePlaceholder"
178
+ [value]="name"
179
+ [fullWidth]="true"
180
+ (valueChange)="onNameChange($event)"
181
+ (enterPressed)="submit()"
182
+ ></cqa-custom-input>
183
+
184
+ <!-- Parent folder -->
185
+ <cqa-dynamic-select
186
+ class="cqa-block cqa-w-full"
187
+ [form]="parentForm"
188
+ [config]="parentSelectConfig"
189
+ (selectionChange)="onParentSelectionChange($event)"
190
+ ></cqa-dynamic-select>
191
+
192
+ <!-- Folder color (optional) -->
193
+ <div class="cqa-flex cqa-flex-col cqa-gap-2">
194
+ <label class="cqa-text-sm cqa-font-medium cqa-text-neutral-700">
195
+ {{ labels.newFolderDialogColorLabel }}
196
+ </label>
197
+ <div class="cqa-flex cqa-items-center cqa-gap-2.5 cqa-flex-wrap">
198
+ <button
199
+ *ngFor="let c of presetColors"
200
+ type="button"
201
+ class="cqa-relative cqa-w-7 cqa-h-7 cqa-rounded-full cqa-cursor-pointer cqa-border-0 cqa-p-0 cqa-transition-transform"
202
+ [style.backgroundColor]="c"
203
+ [style.boxShadow]="isColor(c) ? ('0 0 0 2px #ffffff, 0 0 0 4px ' + c) : '0 0 0 1px rgba(15, 23, 42, 0.08)'"
204
+ (click)="onColorChange(c)"
205
+ [attr.aria-label]="'Set folder color ' + c"
206
+ [attr.aria-pressed]="isColor(c)"
207
+ [title]="c"
208
+ >
209
+ <svg
210
+ *ngIf="isColor(c)"
211
+ class="cqa-absolute cqa-inset-0 cqa-m-auto"
212
+ width="14" height="14" viewBox="0 0 24 24" fill="none" aria-hidden="true"
213
+ >
214
+ <path d="M5 12l4.5 4.5L19 7" stroke="#ffffff" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
215
+ </svg>
216
+ </button>
217
+
218
+ <label
219
+ class="cqa-relative cqa-inline-flex cqa-items-center cqa-justify-center cqa-w-7 cqa-h-7 cqa-rounded-full cqa-cursor-pointer cqa-transition-transform"
220
+ [style.background]="rainbowBorder"
221
+ [title]="isCustomColor ? ('Custom color (' + color + ')') : 'Pick a custom color'"
222
+ >
223
+ <span
224
+ class="cqa-absolute cqa-flex cqa-items-center cqa-justify-center cqa-rounded-full"
225
+ [style.top.px]="2"
226
+ [style.right.px]="2"
227
+ [style.bottom.px]="2"
228
+ [style.left.px]="2"
229
+ [style.backgroundColor]="isCustomColor ? color : '#ffffff'"
230
+ >
231
+ <svg *ngIf="!isCustomColor" width="14" height="14" viewBox="0 0 24 24" fill="none" aria-hidden="true">
232
+ <path d="M12 5v14M5 12h14" stroke="#525258" stroke-width="2" stroke-linecap="round"/>
233
+ </svg>
234
+ <svg *ngIf="isCustomColor" width="14" height="14" viewBox="0 0 24 24" fill="none" aria-hidden="true">
235
+ <path d="M5 12l4.5 4.5L19 7" stroke="#ffffff" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
236
+ </svg>
237
+ </span>
238
+ <input
239
+ type="color"
240
+ [value]="color"
241
+ (input)="onColorInputEvent($event)"
242
+ class="cqa-absolute cqa-inset-0 cqa-w-full cqa-h-full cqa-opacity-0 cqa-cursor-pointer cqa-border-0 cqa-p-0"
243
+ aria-label="Pick custom folder color"
244
+ />
245
+ </label>
246
+ </div>
247
+ </div>
248
+ </div>
249
+ `, isInline: true, components: [{ type: i1.CustomInputComponent, selector: "cqa-custom-input", inputs: ["inputId", "label", "type", "placeholder", "value", "disabled", "errors", "required", "ariaLabel", "size", "fullWidth", "maxLength", "showCharCount", "inputInlineStyle", "labelInlineStyle"], outputs: ["valueChange", "blurred", "focused", "enterPressed"] }, { type: i2.DynamicSelectFieldComponent, selector: "cqa-dynamic-select", inputs: ["form", "config"], outputs: ["selectionChange", "selectClick", "searchChange", "loadMore", "addCustomValue"] }], directives: [{ type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
250
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: NewFolderDialogComponent, decorators: [{
251
+ type: Component,
252
+ args: [{ selector: 'cqa-new-folder-dialog', template: `
253
+ <div class="cqa-flex cqa-flex-col cqa-gap-5 cqa-w-full">
254
+ <!-- Folder name -->
255
+ <cqa-custom-input
256
+ [label]="labels.newFolderDialogNameLabel"
257
+ [required]="true"
258
+ [placeholder]="labels.newFolderDialogNamePlaceholder"
259
+ [value]="name"
260
+ [fullWidth]="true"
261
+ (valueChange)="onNameChange($event)"
262
+ (enterPressed)="submit()"
263
+ ></cqa-custom-input>
264
+
265
+ <!-- Parent folder -->
266
+ <cqa-dynamic-select
267
+ class="cqa-block cqa-w-full"
268
+ [form]="parentForm"
269
+ [config]="parentSelectConfig"
270
+ (selectionChange)="onParentSelectionChange($event)"
271
+ ></cqa-dynamic-select>
272
+
273
+ <!-- Folder color (optional) -->
274
+ <div class="cqa-flex cqa-flex-col cqa-gap-2">
275
+ <label class="cqa-text-sm cqa-font-medium cqa-text-neutral-700">
276
+ {{ labels.newFolderDialogColorLabel }}
277
+ </label>
278
+ <div class="cqa-flex cqa-items-center cqa-gap-2.5 cqa-flex-wrap">
279
+ <button
280
+ *ngFor="let c of presetColors"
281
+ type="button"
282
+ class="cqa-relative cqa-w-7 cqa-h-7 cqa-rounded-full cqa-cursor-pointer cqa-border-0 cqa-p-0 cqa-transition-transform"
283
+ [style.backgroundColor]="c"
284
+ [style.boxShadow]="isColor(c) ? ('0 0 0 2px #ffffff, 0 0 0 4px ' + c) : '0 0 0 1px rgba(15, 23, 42, 0.08)'"
285
+ (click)="onColorChange(c)"
286
+ [attr.aria-label]="'Set folder color ' + c"
287
+ [attr.aria-pressed]="isColor(c)"
288
+ [title]="c"
289
+ >
290
+ <svg
291
+ *ngIf="isColor(c)"
292
+ class="cqa-absolute cqa-inset-0 cqa-m-auto"
293
+ width="14" height="14" viewBox="0 0 24 24" fill="none" aria-hidden="true"
294
+ >
295
+ <path d="M5 12l4.5 4.5L19 7" stroke="#ffffff" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
296
+ </svg>
297
+ </button>
298
+
299
+ <label
300
+ class="cqa-relative cqa-inline-flex cqa-items-center cqa-justify-center cqa-w-7 cqa-h-7 cqa-rounded-full cqa-cursor-pointer cqa-transition-transform"
301
+ [style.background]="rainbowBorder"
302
+ [title]="isCustomColor ? ('Custom color (' + color + ')') : 'Pick a custom color'"
303
+ >
304
+ <span
305
+ class="cqa-absolute cqa-flex cqa-items-center cqa-justify-center cqa-rounded-full"
306
+ [style.top.px]="2"
307
+ [style.right.px]="2"
308
+ [style.bottom.px]="2"
309
+ [style.left.px]="2"
310
+ [style.backgroundColor]="isCustomColor ? color : '#ffffff'"
311
+ >
312
+ <svg *ngIf="!isCustomColor" width="14" height="14" viewBox="0 0 24 24" fill="none" aria-hidden="true">
313
+ <path d="M12 5v14M5 12h14" stroke="#525258" stroke-width="2" stroke-linecap="round"/>
314
+ </svg>
315
+ <svg *ngIf="isCustomColor" width="14" height="14" viewBox="0 0 24 24" fill="none" aria-hidden="true">
316
+ <path d="M5 12l4.5 4.5L19 7" stroke="#ffffff" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
317
+ </svg>
318
+ </span>
319
+ <input
320
+ type="color"
321
+ [value]="color"
322
+ (input)="onColorInputEvent($event)"
323
+ class="cqa-absolute cqa-inset-0 cqa-w-full cqa-h-full cqa-opacity-0 cqa-cursor-pointer cqa-border-0 cqa-p-0"
324
+ aria-label="Pick custom folder color"
325
+ />
326
+ </label>
327
+ </div>
328
+ </div>
329
+ </div>
330
+ `, host: { class: 'cqa-ui-root' }, changeDetection: ChangeDetectionStrategy.OnPush, styles: [] }]
331
+ }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }]; }, propDecorators: { folders: [{
332
+ type: Input
333
+ }], labels: [{
334
+ type: Input
335
+ }], name: [{
336
+ type: Input
337
+ }], parentId: [{
338
+ type: Input
339
+ }], color: [{
340
+ type: Input
341
+ }], nameChange: [{
342
+ type: Output
343
+ }], parentIdChange: [{
344
+ type: Output
345
+ }], colorChange: [{
346
+ type: Output
347
+ }], submitted: [{
348
+ type: Output
349
+ }], cancelled: [{
350
+ type: Output
351
+ }] } });
352
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmV3LWZvbGRlci1kaWFsb2cuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi90ZW1wbGF0ZXMvbW9kdWxhci10YWJsZS10ZW1wbGF0ZS9kaWFsb2dzL25ldy1mb2xkZXItZGlhbG9nLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsdUJBQXVCLEVBRXZCLFNBQVMsRUFDVCxZQUFZLEVBQ1osS0FBSyxFQUVMLE1BQU0sR0FDUCxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsV0FBVyxFQUFFLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRXhELE9BQU8sRUFBRSxzQkFBc0IsRUFBNkIsTUFBTSxrQ0FBa0MsQ0FBQzs7Ozs7QUFPckcsTUFBTSxDQUFDLE1BQU0sb0JBQW9CLEdBQUcsU0FBUyxDQUFDO0FBRTlDLE1BQU0sb0JBQW9CLEdBQWE7SUFDckMsb0JBQW9CO0lBQ3BCLFNBQVM7SUFDVCxTQUFTO0lBQ1QsU0FBUztJQUNULFNBQVM7SUFDVCxTQUFTO0lBQ1QsU0FBUztJQUNULFNBQVM7Q0FDVixDQUFDO0FBRUY7Ozs7Ozs7Ozs7Ozs7Ozs7R0FnQkc7QUFzRkgsTUFBTSxPQUFPLHdCQUF3QjtJQTJEbkMsWUFBb0IsR0FBc0I7UUFBdEIsUUFBRyxHQUFILEdBQUcsQ0FBbUI7UUExRDFDLDhFQUE4RTtRQUM5RSx3RUFBd0U7UUFDeEUsb0VBQW9FO1FBQ3BFLCtFQUErRTtRQUMvRSwrRUFBK0U7UUFDL0UsMkVBQTJFO1FBRW5FLGFBQVEsR0FBaUIsRUFBRSxDQUFDO1FBUTVCLFlBQU8sR0FBa0IsRUFBRSxHQUFHLHNCQUFzQixFQUFFLENBQUM7UUFPdEQsU0FBSSxHQUFXLEVBQUUsQ0FBQztRQUVuQixjQUFTLEdBQWtCLElBQUksQ0FBQztRQU8vQixVQUFLLEdBQVcsb0JBQW9CLENBQUM7UUFFckMsaUJBQVksR0FBYSxvQkFBb0IsQ0FBQztRQUM5QyxrQkFBYSxHQUNwQiw0R0FBNEcsQ0FBQztRQUVyRyxlQUFVLEdBQUcsSUFBSSxZQUFZLEVBQVUsQ0FBQztRQUN4QyxtQkFBYyxHQUFHLElBQUksWUFBWSxFQUFpQixDQUFDO1FBQ25ELGdCQUFXLEdBQUcsSUFBSSxZQUFZLEVBQVUsQ0FBQztRQUN6QyxjQUFTLEdBQUcsSUFBSSxZQUFZLEVBQTRELENBQUM7UUFDekYsY0FBUyxHQUFHLElBQUksWUFBWSxFQUFRLENBQUM7UUFFL0MsdUdBQXVHO1FBQ3ZHLGVBQVUsR0FBRyxJQUFJLFNBQVMsQ0FBQyxFQUFFLFFBQVEsRUFBRSxJQUFJLFdBQVcsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7UUFZeEQsa0JBQWEsR0FBbUIsRUFBRSxDQUFDO1FBR3pDLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxDQUFDLENBQUMsbURBQW1EO0lBQ2pGLENBQUM7SUFwREQsSUFBYSxPQUFPLENBQUMsS0FBbUI7UUFDdEMsSUFBSSxDQUFDLFFBQVEsR0FBRyxLQUFLLElBQUksRUFBRSxDQUFDO1FBQzVCLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztRQUN0QixJQUFJLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztJQUM3QixDQUFDO0lBQ0QsSUFBSSxPQUFPLEtBQW1CLE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7SUFHckQsSUFBYSxNQUFNLENBQUMsS0FBb0I7UUFDdEMsSUFBSSxDQUFDLE9BQU8sR0FBRyxLQUFLLElBQUksRUFBRSxHQUFHLHNCQUFzQixFQUFFLENBQUM7UUFDdEQsSUFBSSxDQUFDLG1CQUFtQixFQUFFLENBQUM7SUFDN0IsQ0FBQztJQUNELElBQUksTUFBTSxLQUFvQixPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO0lBS3BELElBQWEsUUFBUSxDQUFDLEtBQW9CO1FBQ3hDLElBQUksQ0FBQyxTQUFTLEdBQUcsS0FBSyxJQUFJLElBQUksQ0FBQztRQUMvQixJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztJQUMzQixDQUFDO0lBQ0QsSUFBSSxRQUFRLEtBQW9CLE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7SUFpQ3hELFFBQVE7UUFDTiwrRUFBK0U7UUFDL0UsMkVBQTJFO1FBQzNFLHdDQUF3QztRQUN4QyxJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztJQUMzQixDQUFDO0lBRU8sbUJBQW1CO1FBQ3pCLElBQUksQ0FBQyxrQkFBa0IsR0FBRztZQUN4QixHQUFHLEVBQUUsVUFBVTtZQUNmLEtBQUssRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLDBCQUEwQjtZQUM3QyxXQUFXLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyx5QkFBeUI7WUFDbEQsVUFBVSxFQUFFLEtBQUs7WUFDakIsUUFBUSxFQUFFLEtBQUs7WUFDZixhQUFhLEVBQUUsSUFBSTtZQUNuQixPQUFPLEVBQUU7Z0JBQ1AseUVBQXlFO2dCQUN6RSx3RUFBd0U7Z0JBQ3hFLHdDQUF3QztnQkFDeEMsRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLHlCQUF5QixFQUFFO2dCQUM1RCxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUMsRUFBRSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQzthQUM5RDtTQUNGLENBQUM7SUFDSixDQUFDO0lBRU8sY0FBYztRQUNwQixNQUFNLElBQUksR0FBbUIsRUFBRSxDQUFDO1FBQ2hDLE1BQU0sSUFBSSxHQUFHLENBQUMsS0FBbUIsRUFBRSxLQUFlLEVBQVEsRUFBRTtZQUMxRCxLQUFLLE1BQU0sQ0FBQyxJQUFJLEtBQUssSUFBSSxFQUFFLEVBQUU7Z0JBQzNCLE1BQU0sS0FBSyxHQUFHLENBQUMsR0FBRyxLQUFLLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztnQkFDN0MsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUMsRUFBRSxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7Z0JBQy9CLElBQUksQ0FBQyxDQUFDLFFBQVEsRUFBRSxNQUFNO29CQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUMsR0FBRyxLQUFLLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7YUFDOUQ7UUFDSCxDQUFDLENBQUM7UUFDRixJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsQ0FBQztRQUN2QixJQUFJLENBQUMsYUFBYSxHQUFHLElBQUksQ0FBQztRQUMxQixJQUFJLENBQUMsR0FBRyxDQUFDLFlBQVksRUFBRSxDQUFDO0lBQzFCLENBQUM7SUFFTyxpQkFBaUI7UUFDdkIsb0ZBQW9GO1FBQ3BGLElBQUksQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxFQUFFLFFBQVEsQ0FBQyxJQUFJLENBQUMsUUFBUSxJQUFJLElBQUksRUFBRSxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO0lBQ3pGLENBQUM7SUFFRCxZQUFZLENBQUMsS0FBYTtRQUN4QixJQUFJLENBQUMsSUFBSSxHQUFHLEtBQUssQ0FBQztRQUNsQixJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUM5QixDQUFDO0lBRUQsdUJBQXVCLENBQUMsS0FBa0M7UUFDeEQsMEVBQTBFO1FBQzFFLG9EQUFvRDtRQUNwRCxNQUFNLEdBQUcsR0FBRyxLQUFLLEVBQUUsS0FBSyxDQUFDO1FBQ3pCLElBQUksSUFBSSxHQUFrQixJQUFJLENBQUM7UUFDL0IsSUFBSSxHQUFHLElBQUksSUFBSSxFQUFFO1lBQ2YsTUFBTSxPQUFPLEdBQUcsT0FBTyxHQUFHLEtBQUssUUFBUSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUM1RCxJQUFJLE1BQU0sQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDO2dCQUFFLElBQUksR0FBRyxPQUFPLENBQUM7U0FDOUM7UUFDRCxJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQztRQUNyQixJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNqQyxDQUFDO0lBRUQsT0FBTyxDQUFDLENBQVM7UUFDZixPQUFPLENBQUMsSUFBSSxDQUFDLEtBQUssSUFBSSxFQUFFLENBQUMsQ0FBQyxXQUFXLEVBQUUsS0FBSyxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUN0RSxDQUFDO0lBRUQsSUFBSSxhQUFhO1FBQ2YsTUFBTSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsS0FBSyxJQUFJLEVBQUUsQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQzNDLE9BQU8sQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLFdBQVcsRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDO0lBQ3BFLENBQUM7SUFFRCxhQUFhLENBQUMsS0FBYTtRQUN6QixNQUFNLElBQUksR0FBRyxLQUFLLElBQUksb0JBQW9CLENBQUM7UUFDM0MsSUFBSSxJQUFJLENBQUMsS0FBSyxLQUFLLElBQUk7WUFBRSxPQUFPO1FBQ2hDLElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDO1FBQ2xCLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQzVCLElBQUksQ0FBQyxHQUFHLENBQUMsWUFBWSxFQUFFLENBQUM7SUFDMUIsQ0FBQztJQUVELGlCQUFpQixDQUFDLEtBQVk7UUFDNUIsTUFBTSxNQUFNLEdBQUcsS0FBSyxDQUFDLE1BQWlDLENBQUM7UUFDdkQsSUFBSSxNQUFNO1lBQUUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDL0MsQ0FBQztJQUVELDJGQUEyRjtJQUMzRixJQUFJLE9BQU87UUFDVCxPQUFPLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLElBQUksRUFBRSxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDcEMsQ0FBQztJQUVELE1BQU07UUFDSixJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU87WUFBRSxPQUFPO1FBQzFCLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDO1lBQ2xCLElBQUksRUFBRSxDQUFDLElBQUksQ0FBQyxJQUFJLElBQUksRUFBRSxDQUFDLENBQUMsSUFBSSxFQUFFO1lBQzlCLFFBQVEsRUFBRSxJQUFJLENBQUMsUUFBUTtZQUN2QixLQUFLLEVBQUUsSUFBSSxDQUFDLEtBQUssSUFBSSxvQkFBb0I7U0FDMUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQzs7cUhBL0pVLHdCQUF3Qjt5R0FBeEIsd0JBQXdCLGlXQW5GekI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQThFVDsyRkFLVSx3QkFBd0I7a0JBckZwQyxTQUFTOytCQUNFLHVCQUF1QixZQUN2Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBOEVULFFBRUssRUFBRSxLQUFLLEVBQUUsYUFBYSxFQUFFLG1CQUNiLHVCQUF1QixDQUFDLE1BQU07d0dBV2xDLE9BQU87c0JBQW5CLEtBQUs7Z0JBUU8sTUFBTTtzQkFBbEIsS0FBSztnQkFNRyxJQUFJO3NCQUFaLEtBQUs7Z0JBR08sUUFBUTtzQkFBcEIsS0FBSztnQkFNRyxLQUFLO3NCQUFiLEtBQUs7Z0JBTUksVUFBVTtzQkFBbkIsTUFBTTtnQkFDRyxjQUFjO3NCQUF2QixNQUFNO2dCQUNHLFdBQVc7c0JBQXBCLE1BQU07Z0JBQ0csU0FBUztzQkFBbEIsTUFBTTtnQkFDRyxTQUFTO3NCQUFsQixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIENoYW5nZURldGVjdG9yUmVmLFxuICBDb21wb25lbnQsXG4gIEV2ZW50RW1pdHRlcixcbiAgSW5wdXQsXG4gIE9uSW5pdCxcbiAgT3V0cHV0LFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEZvcm1Db250cm9sLCBGb3JtR3JvdXAgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBEeW5hbWljU2VsZWN0RmllbGRDb25maWcgfSBmcm9tICcuLi8uLi8uLi9keW5hbWljLXNlbGVjdC9keW5hbWljLXNlbGVjdC1maWVsZC5jb21wb25lbnQnO1xuaW1wb3J0IHsgREVGQVVMVF9NT0RVTEFSX0xBQkVMUywgRm9sZGVyTm9kZSwgTW9kdWxhckxhYmVscyB9IGZyb20gJy4uL21vZHVsYXItdGFibGUtdGVtcGxhdGUubW9kZWxzJztcblxuaW50ZXJmYWNlIFBhcmVudE9wdGlvbiB7XG4gIGlkOiBudW1iZXI7XG4gIGxhYmVsOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBjb25zdCBERUZBVUxUX0ZPTERFUl9DT0xPUiA9ICcjOTk5OTlFJztcblxuY29uc3QgUFJFU0VUX0ZPTERFUl9DT0xPUlM6IHN0cmluZ1tdID0gW1xuICBERUZBVUxUX0ZPTERFUl9DT0xPUixcbiAgJyM0RjQ2RTUnLFxuICAnIzA2QjZENCcsXG4gICcjMTBCOTgxJyxcbiAgJyNGNTlFMEInLFxuICAnI0VGNDQ0NCcsXG4gICcjRUM0ODk5JyxcbiAgJyM4QjVDRjYnLFxuXTtcblxuLyoqXG4gKiBCb2R5IG9mIHRoZSBcIk5ldyBGb2xkZXJcIiBkaWFsb2cuXG4gKlxuICogVXNlcyByZXVzYWJsZSBsaWJyYXJ5IGNvbXBvbmVudHMgKGBjcWEtY3VzdG9tLWlucHV0YCBmb3IgdGhlIG5hbWUgZmllbGQsXG4gKiBgY3FhLWR5bmFtaWMtc2VsZWN0YCBmb3IgdGhlIHBhcmVudCBkcm9wZG93bikgc28gaG9zdHMgY2FuIGRyb3AgdGhpcyBkaWFsb2dcbiAqIGludG8gdGhlaXIgb3duIG1vZGFsIHNoZWxsIHdpdGhvdXQgd29ycnlpbmcgYWJvdXQgc3R5bGluZyBkcmlmdC5cbiAqXG4gKiBUd28gaW50ZWdyYXRpb24gcGF0aHM6XG4gKlxuICogIDEuICoqRnJvbSB3aXRoaW4gdGhpcyBsaWJyYXJ5KiogdmlhIGBEaWFsb2dTZXJ2aWNlLm9wZW4oLi4uKWAuIFRoZSBvdXRlclxuICogICAgIGBjcWEtZGlhbG9nYCBzdXBwbGllcyB0aXRsZS9kZXNjcmlwdGlvbi9DYW5jZWwvQ3JlYXRlLWZvbGRlciBidXR0b25zOyB0aGVcbiAqICAgICBDcmVhdGUgYnV0dG9uIHJlYWRzIGBuYW1lYCArIGBwYXJlbnRJZGAgdmlhIGBnZXRDb21wb25lbnRJbnN0YW5jZSgpYC5cbiAqXG4gKiAgMi4gKipIb3N0LWRyaXZlbioqIOKAlCBob3N0IHJlbmRlcnMgYDxjcWEtbmV3LWZvbGRlci1kaWFsb2c+YCBpbnNpZGUgaXRzIG93blxuICogICAgIG1vZGFsIGFuZCBsaXN0ZW5zIHRvIGAoc3VibWl0dGVkKWAgLyBgKGNhbmNlbGxlZClgIC8gYChuYW1lQ2hhbmdlKWAgL1xuICogICAgIGAocGFyZW50SWRDaGFuZ2UpYC5cbiAqL1xuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnY3FhLW5ldy1mb2xkZXItZGlhbG9nJyxcbiAgdGVtcGxhdGU6IGBcbiAgICA8ZGl2IGNsYXNzPVwiY3FhLWZsZXggY3FhLWZsZXgtY29sIGNxYS1nYXAtNSBjcWEtdy1mdWxsXCI+XG4gICAgICA8IS0tIEZvbGRlciBuYW1lIC0tPlxuICAgICAgPGNxYS1jdXN0b20taW5wdXRcbiAgICAgICAgW2xhYmVsXT1cImxhYmVscy5uZXdGb2xkZXJEaWFsb2dOYW1lTGFiZWxcIlxuICAgICAgICBbcmVxdWlyZWRdPVwidHJ1ZVwiXG4gICAgICAgIFtwbGFjZWhvbGRlcl09XCJsYWJlbHMubmV3Rm9sZGVyRGlhbG9nTmFtZVBsYWNlaG9sZGVyXCJcbiAgICAgICAgW3ZhbHVlXT1cIm5hbWVcIlxuICAgICAgICBbZnVsbFdpZHRoXT1cInRydWVcIlxuICAgICAgICAodmFsdWVDaGFuZ2UpPVwib25OYW1lQ2hhbmdlKCRldmVudClcIlxuICAgICAgICAoZW50ZXJQcmVzc2VkKT1cInN1Ym1pdCgpXCJcbiAgICAgID48L2NxYS1jdXN0b20taW5wdXQ+XG5cbiAgICAgIDwhLS0gUGFyZW50IGZvbGRlciAtLT5cbiAgICAgIDxjcWEtZHluYW1pYy1zZWxlY3RcbiAgICAgICAgY2xhc3M9XCJjcWEtYmxvY2sgY3FhLXctZnVsbFwiXG4gICAgICAgIFtmb3JtXT1cInBhcmVudEZvcm1cIlxuICAgICAgICBbY29uZmlnXT1cInBhcmVudFNlbGVjdENvbmZpZ1wiXG4gICAgICAgIChzZWxlY3Rpb25DaGFuZ2UpPVwib25QYXJlbnRTZWxlY3Rpb25DaGFuZ2UoJGV2ZW50KVwiXG4gICAgICA+PC9jcWEtZHluYW1pYy1zZWxlY3Q+XG5cbiAgICAgIDwhLS0gRm9sZGVyIGNvbG9yIChvcHRpb25hbCkgLS0+XG4gICAgICA8ZGl2IGNsYXNzPVwiY3FhLWZsZXggY3FhLWZsZXgtY29sIGNxYS1nYXAtMlwiPlxuICAgICAgICA8bGFiZWwgY2xhc3M9XCJjcWEtdGV4dC1zbSBjcWEtZm9udC1tZWRpdW0gY3FhLXRleHQtbmV1dHJhbC03MDBcIj5cbiAgICAgICAgICB7eyBsYWJlbHMubmV3Rm9sZGVyRGlhbG9nQ29sb3JMYWJlbCB9fVxuICAgICAgICA8L2xhYmVsPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiY3FhLWZsZXggY3FhLWl0ZW1zLWNlbnRlciBjcWEtZ2FwLTIuNSBjcWEtZmxleC13cmFwXCI+XG4gICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgKm5nRm9yPVwibGV0IGMgb2YgcHJlc2V0Q29sb3JzXCJcbiAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgY2xhc3M9XCJjcWEtcmVsYXRpdmUgY3FhLXctNyBjcWEtaC03IGNxYS1yb3VuZGVkLWZ1bGwgY3FhLWN1cnNvci1wb2ludGVyIGNxYS1ib3JkZXItMCBjcWEtcC0wIGNxYS10cmFuc2l0aW9uLXRyYW5zZm9ybVwiXG4gICAgICAgICAgICBbc3R5bGUuYmFja2dyb3VuZENvbG9yXT1cImNcIlxuICAgICAgICAgICAgW3N0eWxlLmJveFNoYWRvd109XCJpc0NvbG9yKGMpID8gKCcwIDAgMCAycHggI2ZmZmZmZiwgMCAwIDAgNHB4ICcgKyBjKSA6ICcwIDAgMCAxcHggcmdiYSgxNSwgMjMsIDQyLCAwLjA4KSdcIlxuICAgICAgICAgICAgKGNsaWNrKT1cIm9uQ29sb3JDaGFuZ2UoYylcIlxuICAgICAgICAgICAgW2F0dHIuYXJpYS1sYWJlbF09XCInU2V0IGZvbGRlciBjb2xvciAnICsgY1wiXG4gICAgICAgICAgICBbYXR0ci5hcmlhLXByZXNzZWRdPVwiaXNDb2xvcihjKVwiXG4gICAgICAgICAgICBbdGl0bGVdPVwiY1wiXG4gICAgICAgICAgPlxuICAgICAgICAgICAgPHN2Z1xuICAgICAgICAgICAgICAqbmdJZj1cImlzQ29sb3IoYylcIlxuICAgICAgICAgICAgICBjbGFzcz1cImNxYS1hYnNvbHV0ZSBjcWEtaW5zZXQtMCBjcWEtbS1hdXRvXCJcbiAgICAgICAgICAgICAgd2lkdGg9XCIxNFwiIGhlaWdodD1cIjE0XCIgdmlld0JveD1cIjAgMCAyNCAyNFwiIGZpbGw9XCJub25lXCIgYXJpYS1oaWRkZW49XCJ0cnVlXCJcbiAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgPHBhdGggZD1cIk01IDEybDQuNSA0LjVMMTkgN1wiIHN0cm9rZT1cIiNmZmZmZmZcIiBzdHJva2Utd2lkdGg9XCIzXCIgc3Ryb2tlLWxpbmVjYXA9XCJyb3VuZFwiIHN0cm9rZS1saW5lam9pbj1cInJvdW5kXCIvPlxuICAgICAgICAgICAgPC9zdmc+XG4gICAgICAgICAgPC9idXR0b24+XG5cbiAgICAgICAgICA8bGFiZWxcbiAgICAgICAgICAgIGNsYXNzPVwiY3FhLXJlbGF0aXZlIGNxYS1pbmxpbmUtZmxleCBjcWEtaXRlbXMtY2VudGVyIGNxYS1qdXN0aWZ5LWNlbnRlciBjcWEtdy03IGNxYS1oLTcgY3FhLXJvdW5kZWQtZnVsbCBjcWEtY3Vyc29yLXBvaW50ZXIgY3FhLXRyYW5zaXRpb24tdHJhbnNmb3JtXCJcbiAgICAgICAgICAgIFtzdHlsZS5iYWNrZ3JvdW5kXT1cInJhaW5ib3dCb3JkZXJcIlxuICAgICAgICAgICAgW3RpdGxlXT1cImlzQ3VzdG9tQ29sb3IgPyAoJ0N1c3RvbSBjb2xvciAoJyArIGNvbG9yICsgJyknKSA6ICdQaWNrIGEgY3VzdG9tIGNvbG9yJ1wiXG4gICAgICAgICAgPlxuICAgICAgICAgICAgPHNwYW5cbiAgICAgICAgICAgICAgY2xhc3M9XCJjcWEtYWJzb2x1dGUgY3FhLWZsZXggY3FhLWl0ZW1zLWNlbnRlciBjcWEtanVzdGlmeS1jZW50ZXIgY3FhLXJvdW5kZWQtZnVsbFwiXG4gICAgICAgICAgICAgIFtzdHlsZS50b3AucHhdPVwiMlwiXG4gICAgICAgICAgICAgIFtzdHlsZS5yaWdodC5weF09XCIyXCJcbiAgICAgICAgICAgICAgW3N0eWxlLmJvdHRvbS5weF09XCIyXCJcbiAgICAgICAgICAgICAgW3N0eWxlLmxlZnQucHhdPVwiMlwiXG4gICAgICAgICAgICAgIFtzdHlsZS5iYWNrZ3JvdW5kQ29sb3JdPVwiaXNDdXN0b21Db2xvciA/IGNvbG9yIDogJyNmZmZmZmYnXCJcbiAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgPHN2ZyAqbmdJZj1cIiFpc0N1c3RvbUNvbG9yXCIgd2lkdGg9XCIxNFwiIGhlaWdodD1cIjE0XCIgdmlld0JveD1cIjAgMCAyNCAyNFwiIGZpbGw9XCJub25lXCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+XG4gICAgICAgICAgICAgICAgPHBhdGggZD1cIk0xMiA1djE0TTUgMTJoMTRcIiBzdHJva2U9XCIjNTI1MjU4XCIgc3Ryb2tlLXdpZHRoPVwiMlwiIHN0cm9rZS1saW5lY2FwPVwicm91bmRcIi8+XG4gICAgICAgICAgICAgIDwvc3ZnPlxuICAgICAgICAgICAgICA8c3ZnICpuZ0lmPVwiaXNDdXN0b21Db2xvclwiIHdpZHRoPVwiMTRcIiBoZWlnaHQ9XCIxNFwiIHZpZXdCb3g9XCIwIDAgMjQgMjRcIiBmaWxsPVwibm9uZVwiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPlxuICAgICAgICAgICAgICAgIDxwYXRoIGQ9XCJNNSAxMmw0LjUgNC41TDE5IDdcIiBzdHJva2U9XCIjZmZmZmZmXCIgc3Ryb2tlLXdpZHRoPVwiM1wiIHN0cm9rZS1saW5lY2FwPVwicm91bmRcIiBzdHJva2UtbGluZWpvaW49XCJyb3VuZFwiLz5cbiAgICAgICAgICAgICAgPC9zdmc+XG4gICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgdHlwZT1cImNvbG9yXCJcbiAgICAgICAgICAgICAgW3ZhbHVlXT1cImNvbG9yXCJcbiAgICAgICAgICAgICAgKGlucHV0KT1cIm9uQ29sb3JJbnB1dEV2ZW50KCRldmVudClcIlxuICAgICAgICAgICAgICBjbGFzcz1cImNxYS1hYnNvbHV0ZSBjcWEtaW5zZXQtMCBjcWEtdy1mdWxsIGNxYS1oLWZ1bGwgY3FhLW9wYWNpdHktMCBjcWEtY3Vyc29yLXBvaW50ZXIgY3FhLWJvcmRlci0wIGNxYS1wLTBcIlxuICAgICAgICAgICAgICBhcmlhLWxhYmVsPVwiUGljayBjdXN0b20gZm9sZGVyIGNvbG9yXCJcbiAgICAgICAgICAgIC8+XG4gICAgICAgICAgPC9sYWJlbD5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgYCxcbiAgc3R5bGVVcmxzOiBbXSxcbiAgaG9zdDogeyBjbGFzczogJ2NxYS11aS1yb290JyB9LFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbn0pXG5leHBvcnQgY2xhc3MgTmV3Rm9sZGVyRGlhbG9nQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcbiAgLy8gTk9URTogVGhlc2UgaW5wdXRzIGFyZSBkZWNsYXJlZCBhcyBzZXR0ZXJzIChpbnN0ZWFkIG9mIHBsYWluIEBJbnB1dCBmaWVsZHMpXG4gIC8vIGJlY2F1c2UgYERpYWxvZ1NlcnZpY2Uub3BlbiguLi4pYCBhc3NpZ25zIHRoZSBgaW5wdXRzYCBtYXAgdmlhIGRpcmVjdFxuICAvLyBwcm9wZXJ0eSBhc3NpZ25tZW50ICphZnRlciogYGF0dGFjaENvbXBvbmVudGAgaGFzIGFscmVhZHkgcnVuIHRoZVxuICAvLyBjb21wb25lbnQncyBgbmdPbkluaXRgLiBEaXJlY3QgYXNzaWdubWVudCBieXBhc3NlcyBgbmdPbkNoYW5nZXNgLCBzbyB3aXRob3V0XG4gIC8vIHNldHRlcnMgdGhlIGBwYXJlbnRTZWxlY3RDb25maWdgIHdvdWxkIGJlIGJ1aWx0IGZyb20gYSBkZWZhdWx0IGVtcHR5IGZvbGRlcnNcbiAgLy8gYXJyYXkgYW5kIHRoZSBwYXJlbnQtZm9sZGVyIGRyb3Bkb3duIHdvdWxkIHJlbmRlciBlbXB0eSAvIGFwcGVhciBicm9rZW4uXG5cbiAgcHJpdmF0ZSBfZm9sZGVyczogRm9sZGVyTm9kZVtdID0gW107XG4gIEBJbnB1dCgpIHNldCBmb2xkZXJzKHZhbHVlOiBGb2xkZXJOb2RlW10pIHtcbiAgICB0aGlzLl9mb2xkZXJzID0gdmFsdWUgfHwgW107XG4gICAgdGhpcy5yZWJ1aWxkT3B0aW9ucygpO1xuICAgIHRoaXMucmVidWlsZFNlbGVjdENvbmZpZygpO1xuICB9XG4gIGdldCBmb2xkZXJzKCk6IEZvbGRlck5vZGVbXSB7IHJldHVybiB0aGlzLl9mb2xkZXJzOyB9XG5cbiAgcHJpdmF0ZSBfbGFiZWxzOiBNb2R1bGFyTGFiZWxzID0geyAuLi5ERUZBVUxUX01PRFVMQVJfTEFCRUxTIH07XG4gIEBJbnB1dCgpIHNldCBsYWJlbHModmFsdWU6IE1vZHVsYXJMYWJlbHMpIHtcbiAgICB0aGlzLl9sYWJlbHMgPSB2YWx1ZSB8fCB7IC4uLkRFRkFVTFRfTU9EVUxBUl9MQUJFTFMgfTtcbiAgICB0aGlzLnJlYnVpbGRTZWxlY3RDb25maWcoKTtcbiAgfVxuICBnZXQgbGFiZWxzKCk6IE1vZHVsYXJMYWJlbHMgeyByZXR1cm4gdGhpcy5fbGFiZWxzOyB9XG5cbiAgQElucHV0KCkgbmFtZTogc3RyaW5nID0gJyc7XG5cbiAgcHJpdmF0ZSBfcGFyZW50SWQ6IG51bWJlciB8IG51bGwgPSBudWxsO1xuICBASW5wdXQoKSBzZXQgcGFyZW50SWQodmFsdWU6IG51bWJlciB8IG51bGwpIHtcbiAgICB0aGlzLl9wYXJlbnRJZCA9IHZhbHVlID8/IG51bGw7XG4gICAgdGhpcy5zeW5jUGFyZW50Q29udHJvbCgpO1xuICB9XG4gIGdldCBwYXJlbnRJZCgpOiBudW1iZXIgfCBudWxsIHsgcmV0dXJuIHRoaXMuX3BhcmVudElkOyB9XG5cbiAgQElucHV0KCkgY29sb3I6IHN0cmluZyA9IERFRkFVTFRfRk9MREVSX0NPTE9SO1xuXG4gIHJlYWRvbmx5IHByZXNldENvbG9yczogc3RyaW5nW10gPSBQUkVTRVRfRk9MREVSX0NPTE9SUztcbiAgcmVhZG9ubHkgcmFpbmJvd0JvcmRlcjogc3RyaW5nID1cbiAgICAnY29uaWMtZ3JhZGllbnQoZnJvbSAwZGVnLCAjZWY0NDQ0LCAjZjU5ZTBiLCAjZWFiMzA4LCAjMTBiOTgxLCAjMDZiNmQ0LCAjNGY0NmU1LCAjOGI1Y2Y2LCAjZWM0ODk5LCAjZWY0NDQ0KSc7XG5cbiAgQE91dHB1dCgpIG5hbWVDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPHN0cmluZz4oKTtcbiAgQE91dHB1dCgpIHBhcmVudElkQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxudW1iZXIgfCBudWxsPigpO1xuICBAT3V0cHV0KCkgY29sb3JDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPHN0cmluZz4oKTtcbiAgQE91dHB1dCgpIHN1Ym1pdHRlZCA9IG5ldyBFdmVudEVtaXR0ZXI8eyBuYW1lOiBzdHJpbmc7IHBhcmVudElkOiBudW1iZXIgfCBudWxsOyBjb2xvcjogc3RyaW5nIH0+KCk7XG4gIEBPdXRwdXQoKSBjYW5jZWxsZWQgPSBuZXcgRXZlbnRFbWl0dGVyPHZvaWQ+KCk7XG5cbiAgLyoqIFJlYWN0aXZlIGZvcm0gdXNlZCBieSBjcWEtZHluYW1pYy1zZWxlY3QuIFVudHlwZWQgdG8gbWF0Y2ggdGhlIHByb2plY3QncyBBbmd1bGFyIDEzLjQgZm9ybXMgQVBJLiAqL1xuICBwYXJlbnRGb3JtID0gbmV3IEZvcm1Hcm91cCh7IHBhcmVudElkOiBuZXcgRm9ybUNvbnRyb2wobnVsbCkgfSk7XG5cbiAgLyoqXG4gICAqIENvbmZpZyBwYXNzZWQgdG8gYGNxYS1keW5hbWljLXNlbGVjdGAuIFN0b3JlZCBhcyBhIGZpZWxkIChub3QgYSBnZXR0ZXIpIHNvXG4gICAqIHRoZSBvYmplY3QgcmVmZXJlbmNlIGlzIHN0YWJsZSBhY3Jvc3MgY2hhbmdlLWRldGVjdGlvbiBwYXNzZXMg4oCUIGEgZ2V0dGVyXG4gICAqIHJldHVybnMgYSBmcmVzaCBvYmplY3QgZXZlcnkgQ0QgdGljayBhbmQgY2F1c2VzXG4gICAqIGBFeHByZXNzaW9uQ2hhbmdlZEFmdGVySXRIYXNCZWVuQ2hlY2tlZEVycm9yYCArIHJlcGVhdGVkIGBuZ09uQ2hhbmdlc2Agb25cbiAgICogdGhlIGNoaWxkIHNlbGVjdC4gT3RoZXIgY29uc3VtZXJzIGluIHRoaXMgbGliIChlLmcuIGBsb29wLXN0ZXBgKSBmb2xsb3dcbiAgICogdGhlIHNhbWUgcGF0dGVybi5cbiAgICovXG4gIHBhcmVudFNlbGVjdENvbmZpZyE6IER5bmFtaWNTZWxlY3RGaWVsZENvbmZpZztcblxuICBwcml2YXRlIHBhcmVudE9wdGlvbnM6IFBhcmVudE9wdGlvbltdID0gW107XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSBjZHI6IENoYW5nZURldGVjdG9yUmVmKSB7XG4gICAgdGhpcy5yZWJ1aWxkU2VsZWN0Q29uZmlnKCk7IC8vIGVuc3VyZSBjb25maWcgZXhpc3RzIGV2ZW4gYmVmb3JlIGZpcnN0IGlucHV0IHNldFxuICB9XG5cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgLy8gU2V0dGVycyBhYm92ZSBhbHJlYWR5IHJlYnVpbHQgY29uZmlnIG9uY2UgZm9sZGVycy9sYWJlbHMgd2VyZSBhc3NpZ25lZC4gVGhpc1xuICAgIC8vIGp1c3QgZW5zdXJlcyB0aGUgZm9ybSBjb250cm9sIG1hdGNoZXMgdGhlIGN1cnJlbnQgcGFyZW50SWQgdmFsdWUgaW4gY2FzZVxuICAgIC8vIG9yZGVyaW5nIG9mIGlucHV0IGFzc2lnbm1lbnQgZGlmZmVycy5cbiAgICB0aGlzLnN5bmNQYXJlbnRDb250cm9sKCk7XG4gIH1cblxuICBwcml2YXRlIHJlYnVpbGRTZWxlY3RDb25maWcoKTogdm9pZCB7XG4gICAgdGhpcy5wYXJlbnRTZWxlY3RDb25maWcgPSB7XG4gICAgICBrZXk6ICdwYXJlbnRJZCcsXG4gICAgICBsYWJlbDogdGhpcy5sYWJlbHMubmV3Rm9sZGVyRGlhbG9nUGFyZW50TGFiZWwsXG4gICAgICBwbGFjZWhvbGRlcjogdGhpcy5sYWJlbHMubmV3Rm9sZGVyRGlhbG9nUGFyZW50Tm9uZSxcbiAgICAgIHNlYXJjaGFibGU6IGZhbHNlLFxuICAgICAgbXVsdGlwbGU6IGZhbHNlLFxuICAgICAgY2xvc2VPblNlbGVjdDogdHJ1ZSxcbiAgICAgIG9wdGlvbnM6IFtcbiAgICAgICAgLy8gYGdldE9wdGlvblZhbHVlYCBpbiBjcWEtZHluYW1pYy1zZWxlY3QgcmV0dXJucyBgaWQgPz8gdmFsdWVgLCBzbyB1c2luZ1xuICAgICAgICAvLyBgdmFsdWU6IG51bGxgICh3aXRoIG5vIGlkKSB5aWVsZHMgYSBzdGFibGUgYG51bGxgIHJlc29sdmVkIHZhbHVlIHRoYXRcbiAgICAgICAgLy8gbWF0Y2hlcyB0aGUgRm9ybUNvbnRyb2wncyBudWxsIHN0YXRlLlxuICAgICAgICB7IHZhbHVlOiBudWxsLCBuYW1lOiB0aGlzLmxhYmVscy5uZXdGb2xkZXJEaWFsb2dQYXJlbnROb25lIH0sXG4gICAgICAgIC4uLnRoaXMucGFyZW50T3B0aW9ucy5tYXAobyA9PiAoeyBpZDogby5pZCwgbmFtZTogby5sYWJlbCB9KSksXG4gICAgICBdLFxuICAgIH07XG4gIH1cblxuICBwcml2YXRlIHJlYnVpbGRPcHRpb25zKCk6IHZvaWQge1xuICAgIGNvbnN0IG9wdHM6IFBhcmVudE9wdGlvbltdID0gW107XG4gICAgY29uc3Qgd2FsayA9IChub2RlczogRm9sZGVyTm9kZVtdLCB0cmFpbDogc3RyaW5nW10pOiB2b2lkID0+IHtcbiAgICAgIGZvciAoY29uc3QgbiBvZiBub2RlcyB8fCBbXSkge1xuICAgICAgICBjb25zdCBsYWJlbCA9IFsuLi50cmFpbCwgbi5uYW1lXS5qb2luKCcg4oC6ICcpO1xuICAgICAgICBvcHRzLnB1c2goeyBpZDogbi5pZCwgbGFiZWwgfSk7XG4gICAgICAgIGlmIChuLmNoaWxkcmVuPy5sZW5ndGgpIHdhbGsobi5jaGlsZHJlbiwgWy4uLnRyYWlsLCBuLm5hbWVdKTtcbiAgICAgIH1cbiAgICB9O1xuICAgIHdhbGsodGhpcy5mb2xkZXJzLCBbXSk7XG4gICAgdGhpcy5wYXJlbnRPcHRpb25zID0gb3B0cztcbiAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcbiAgfVxuXG4gIHByaXZhdGUgc3luY1BhcmVudENvbnRyb2woKTogdm9pZCB7XG4gICAgLy8gS2VlcCB0aGUgcmVhY3RpdmUgZm9ybSBpbiBzeW5jIHdpdGggdGhlIGBwYXJlbnRJZGAgaW5wdXQgd2l0aG91dCBib3VuY2luZyBldmVudHMuXG4gICAgdGhpcy5wYXJlbnRGb3JtLmdldCgncGFyZW50SWQnKT8uc2V0VmFsdWUodGhpcy5wYXJlbnRJZCA/PyBudWxsLCB7IGVtaXRFdmVudDogZmFsc2UgfSk7XG4gIH1cblxuICBvbk5hbWVDaGFuZ2UodmFsdWU6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMubmFtZSA9IHZhbHVlO1xuICAgIHRoaXMubmFtZUNoYW5nZS5lbWl0KHZhbHVlKTtcbiAgfVxuXG4gIG9uUGFyZW50U2VsZWN0aW9uQ2hhbmdlKGV2ZW50OiB7IGtleTogc3RyaW5nOyB2YWx1ZTogYW55IH0pOiB2b2lkIHtcbiAgICAvLyBjcWEtZHluYW1pYy1zZWxlY3QgcmVzb2x2ZXMgb3B0aW9ucyB0byBgaWQgPz8gdmFsdWVgOyBvcHRpb24gaWRzIGluIHRoZVxuICAgIC8vIHBhcmVudCB0cmVlIGFyZSBudW1lcmljIHNvIHdlIGNvZXJjZSBkZWZlbnNpdmVseS5cbiAgICBjb25zdCByYXcgPSBldmVudD8udmFsdWU7XG4gICAgbGV0IG5leHQ6IG51bWJlciB8IG51bGwgPSBudWxsO1xuICAgIGlmIChyYXcgIT0gbnVsbCkge1xuICAgICAgY29uc3QgY29lcmNlZCA9IHR5cGVvZiByYXcgPT09ICdudW1iZXInID8gcmF3IDogTnVtYmVyKHJhdyk7XG4gICAgICBpZiAoTnVtYmVyLmlzRmluaXRlKGNvZXJjZWQpKSBuZXh0ID0gY29lcmNlZDtcbiAgICB9XG4gICAgdGhpcy5wYXJlbnRJZCA9IG5leHQ7XG4gICAgdGhpcy5wYXJlbnRJZENoYW5nZS5lbWl0KG5leHQpO1xuICB9XG5cbiAgaXNDb2xvcihjOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gKHRoaXMuY29sb3IgfHwgJycpLnRvTG93ZXJDYXNlKCkgPT09IChjIHx8ICcnKS50b0xvd2VyQ2FzZSgpO1xuICB9XG5cbiAgZ2V0IGlzQ3VzdG9tQ29sb3IoKTogYm9vbGVhbiB7XG4gICAgY29uc3QgYyA9ICh0aGlzLmNvbG9yIHx8ICcnKS50b0xvd2VyQ2FzZSgpO1xuICAgIHJldHVybiAhIWMgJiYgIXRoaXMucHJlc2V0Q29sb3JzLnNvbWUocCA9PiBwLnRvTG93ZXJDYXNlKCkgPT09IGMpO1xuICB9XG5cbiAgb25Db2xvckNoYW5nZSh2YWx1ZTogc3RyaW5nKTogdm9pZCB7XG4gICAgY29uc3QgbmV4dCA9IHZhbHVlIHx8IERFRkFVTFRfRk9MREVSX0NPTE9SO1xuICAgIGlmICh0aGlzLmNvbG9yID09PSBuZXh0KSByZXR1cm47XG4gICAgdGhpcy5jb2xvciA9IG5leHQ7XG4gICAgdGhpcy5jb2xvckNoYW5nZS5lbWl0KG5leHQpO1xuICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xuICB9XG5cbiAgb25Db2xvcklucHV0RXZlbnQoZXZlbnQ6IEV2ZW50KTogdm9pZCB7XG4gICAgY29uc3QgdGFyZ2V0ID0gZXZlbnQudGFyZ2V0IGFzIEhUTUxJbnB1dEVsZW1lbnQgfCBudWxsO1xuICAgIGlmICh0YXJnZXQpIHRoaXMub25Db2xvckNoYW5nZSh0YXJnZXQudmFsdWUpO1xuICB9XG5cbiAgLyoqIFJldHVybnMgdHJ1ZSB3aGVuIHRoZSBjdXJyZW50IHN0YXRlIGlzIGEgdmFsaWQgc3VibWlzc2lvbiAobm9uLWVtcHR5LCB0cmltbWVkIG5hbWUpLiAqL1xuICBnZXQgaXNWYWxpZCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gISEodGhpcy5uYW1lIHx8ICcnKS50cmltKCk7XG4gIH1cblxuICBzdWJtaXQoKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmlzVmFsaWQpIHJldHVybjtcbiAgICB0aGlzLnN1Ym1pdHRlZC5lbWl0KHtcbiAgICAgIG5hbWU6ICh0aGlzLm5hbWUgfHwgJycpLnRyaW0oKSxcbiAgICAgIHBhcmVudElkOiB0aGlzLnBhcmVudElkLFxuICAgICAgY29sb3I6IHRoaXMuY29sb3IgfHwgREVGQVVMVF9GT0xERVJfQ09MT1IsXG4gICAgfSk7XG4gIH1cbn1cbiJdfQ==
@@ -0,0 +1,45 @@
1
+ import { Directive, HostBinding, HostListener, Input } from '@angular/core';
2
+ import { FOLDER_DRAG_MIME } from '../modular-table-template.models';
3
+ import * as i0 from "@angular/core";
4
+ export class FolderDragDirective {
5
+ constructor() {
6
+ this.dragEnabled = true;
7
+ }
8
+ get draggable() {
9
+ return this.dragEnabled && this.folderId != null ? 'true' : null;
10
+ }
11
+ onDragStart(event) {
12
+ if (!this.dragEnabled || this.folderId == null || !event.dataTransfer)
13
+ return;
14
+ event.stopPropagation();
15
+ const payload = JSON.stringify(this.folderId);
16
+ event.dataTransfer.effectAllowed = 'move';
17
+ try {
18
+ event.dataTransfer.setData(FOLDER_DRAG_MIME, payload);
19
+ }
20
+ catch {
21
+ /* some browsers reject custom MIME — fall through */
22
+ }
23
+ event.dataTransfer.setData('text/plain', payload);
24
+ }
25
+ }
26
+ FolderDragDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: FolderDragDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
27
+ FolderDragDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.4.0", type: FolderDragDirective, selector: "[cqaFolderDrag]", inputs: { folderId: ["cqaFolderDrag", "folderId"], dragEnabled: "dragEnabled" }, host: { listeners: { "dragstart": "onDragStart($event)" }, properties: { "attr.draggable": "this.draggable" } }, ngImport: i0 });
28
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: FolderDragDirective, decorators: [{
29
+ type: Directive,
30
+ args: [{
31
+ selector: '[cqaFolderDrag]',
32
+ }]
33
+ }], propDecorators: { folderId: [{
34
+ type: Input,
35
+ args: ['cqaFolderDrag']
36
+ }], dragEnabled: [{
37
+ type: Input
38
+ }], draggable: [{
39
+ type: HostBinding,
40
+ args: ['attr.draggable']
41
+ }], onDragStart: [{
42
+ type: HostListener,
43
+ args: ['dragstart', ['$event']]
44
+ }] } });
45
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9sZGVyLWRyYWcuZGlyZWN0aXZlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi90ZW1wbGF0ZXMvbW9kdWxhci10YWJsZS10ZW1wbGF0ZS9kaXJlY3RpdmVzL2ZvbGRlci1kcmFnLmRpcmVjdGl2ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLFdBQVcsRUFBRSxZQUFZLEVBQUUsS0FBSyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzVFLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLGtDQUFrQyxDQUFDOztBQUtwRSxNQUFNLE9BQU8sbUJBQW1CO0lBSGhDO1FBTVcsZ0JBQVcsR0FBWSxJQUFJLENBQUM7S0FrQnRDO0lBaEJDLElBQW1DLFNBQVM7UUFDMUMsT0FBTyxJQUFJLENBQUMsV0FBVyxJQUFJLElBQUksQ0FBQyxRQUFRLElBQUksSUFBSSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztJQUNuRSxDQUFDO0lBRXNDLFdBQVcsQ0FBQyxLQUFnQjtRQUNqRSxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsSUFBSSxJQUFJLENBQUMsUUFBUSxJQUFJLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxZQUFZO1lBQUUsT0FBTztRQUM5RSxLQUFLLENBQUMsZUFBZSxFQUFFLENBQUM7UUFDeEIsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDOUMsS0FBSyxDQUFDLFlBQVksQ0FBQyxhQUFhLEdBQUcsTUFBTSxDQUFDO1FBQzFDLElBQUk7WUFDRixLQUFLLENBQUMsWUFBWSxDQUFDLE9BQU8sQ0FBQyxnQkFBZ0IsRUFBRSxPQUFPLENBQUMsQ0FBQztTQUN2RDtRQUFDLE1BQU07WUFDTixxREFBcUQ7U0FDdEQ7UUFDRCxLQUFLLENBQUMsWUFBWSxDQUFDLE9BQU8sQ0FBQyxZQUFZLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDcEQsQ0FBQzs7Z0hBcEJVLG1CQUFtQjtvR0FBbkIsbUJBQW1COzJGQUFuQixtQkFBbUI7a0JBSC9CLFNBQVM7bUJBQUM7b0JBQ1QsUUFBUSxFQUFFLGlCQUFpQjtpQkFDNUI7OEJBR3lCLFFBQVE7c0JBQS9CLEtBQUs7dUJBQUMsZUFBZTtnQkFDYixXQUFXO3NCQUFuQixLQUFLO2dCQUU2QixTQUFTO3NCQUEzQyxXQUFXO3VCQUFDLGdCQUFnQjtnQkFJVSxXQUFXO3NCQUFqRCxZQUFZO3VCQUFDLFdBQVcsRUFBRSxDQUFDLFFBQVEsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IERpcmVjdGl2ZSwgSG9zdEJpbmRpbmcsIEhvc3RMaXN0ZW5lciwgSW5wdXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEZPTERFUl9EUkFHX01JTUUgfSBmcm9tICcuLi9tb2R1bGFyLXRhYmxlLXRlbXBsYXRlLm1vZGVscyc7XG5cbkBEaXJlY3RpdmUoe1xuICBzZWxlY3RvcjogJ1tjcWFGb2xkZXJEcmFnXScsXG59KVxuZXhwb3J0IGNsYXNzIEZvbGRlckRyYWdEaXJlY3RpdmUge1xuICAvKiogRm9sZGVyIGlkIGJlaW5nIGRyYWdnZWQuICovXG4gIEBJbnB1dCgnY3FhRm9sZGVyRHJhZycpIGZvbGRlcklkITogbnVtYmVyIHwgbnVsbDtcbiAgQElucHV0KCkgZHJhZ0VuYWJsZWQ6IGJvb2xlYW4gPSB0cnVlO1xuXG4gIEBIb3N0QmluZGluZygnYXR0ci5kcmFnZ2FibGUnKSBnZXQgZHJhZ2dhYmxlKCkge1xuICAgIHJldHVybiB0aGlzLmRyYWdFbmFibGVkICYmIHRoaXMuZm9sZGVySWQgIT0gbnVsbCA/ICd0cnVlJyA6IG51bGw7XG4gIH1cblxuICBASG9zdExpc3RlbmVyKCdkcmFnc3RhcnQnLCBbJyRldmVudCddKSBvbkRyYWdTdGFydChldmVudDogRHJhZ0V2ZW50KSB7XG4gICAgaWYgKCF0aGlzLmRyYWdFbmFibGVkIHx8IHRoaXMuZm9sZGVySWQgPT0gbnVsbCB8fCAhZXZlbnQuZGF0YVRyYW5zZmVyKSByZXR1cm47XG4gICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgY29uc3QgcGF5bG9hZCA9IEpTT04uc3RyaW5naWZ5KHRoaXMuZm9sZGVySWQpO1xuICAgIGV2ZW50LmRhdGFUcmFuc2Zlci5lZmZlY3RBbGxvd2VkID0gJ21vdmUnO1xuICAgIHRyeSB7XG4gICAgICBldmVudC5kYXRhVHJhbnNmZXIuc2V0RGF0YShGT0xERVJfRFJBR19NSU1FLCBwYXlsb2FkKTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIC8qIHNvbWUgYnJvd3NlcnMgcmVqZWN0IGN1c3RvbSBNSU1FIOKAlCBmYWxsIHRocm91Z2ggKi9cbiAgICB9XG4gICAgZXZlbnQuZGF0YVRyYW5zZmVyLnNldERhdGEoJ3RleHQvcGxhaW4nLCBwYXlsb2FkKTtcbiAgfVxufVxuIl19
@@ -0,0 +1,95 @@
1
+ import { Directive, EventEmitter, HostBinding, HostListener, Input, Output } from '@angular/core';
2
+ import { FOLDER_DRAG_MIME, ROW_DRAG_MIME } from '../modular-table-template.models';
3
+ import * as i0 from "@angular/core";
4
+ export class FolderDropDirective {
5
+ constructor() {
6
+ /** Folder id this drop target represents. `null` means "unorganised / root". */
7
+ this.targetFolderId = null;
8
+ this.dropEnabled = true;
9
+ this.testsDropped = new EventEmitter();
10
+ /** Fires when a folder row is dropped here. `folderId` is the dragged folder's id. */
11
+ this.folderDropped = new EventEmitter();
12
+ this.isOver = false;
13
+ }
14
+ onDragOver(event) {
15
+ if (!this.dropEnabled)
16
+ return;
17
+ event.preventDefault();
18
+ if (event.dataTransfer) {
19
+ event.dataTransfer.dropEffect = 'move';
20
+ }
21
+ this.isOver = true;
22
+ }
23
+ onDragLeave() {
24
+ this.isOver = false;
25
+ }
26
+ onDrop(event) {
27
+ this.isOver = false;
28
+ if (!this.dropEnabled || !event.dataTransfer)
29
+ return;
30
+ event.preventDefault();
31
+ // Folder drops take precedence — the sidebar writes the folder MIME on dragstart.
32
+ const folderRaw = event.dataTransfer.getData(FOLDER_DRAG_MIME);
33
+ if (folderRaw) {
34
+ let folderId = null;
35
+ try {
36
+ const parsed = JSON.parse(folderRaw);
37
+ if (typeof parsed === 'number' && Number.isFinite(parsed))
38
+ folderId = parsed;
39
+ }
40
+ catch {
41
+ return;
42
+ }
43
+ if (folderId == null)
44
+ return;
45
+ this.folderDropped.emit({ folderId, targetFolderId: this.targetFolderId });
46
+ return;
47
+ }
48
+ // Fall through to the test-ids path (unchanged).
49
+ const raw = event.dataTransfer.getData(ROW_DRAG_MIME) || event.dataTransfer.getData('text/plain');
50
+ if (!raw)
51
+ return;
52
+ let ids = [];
53
+ try {
54
+ const parsed = JSON.parse(raw);
55
+ if (Array.isArray(parsed))
56
+ ids = parsed;
57
+ }
58
+ catch {
59
+ return;
60
+ }
61
+ if (!ids.length)
62
+ return;
63
+ this.testsDropped.emit({ testIds: ids, targetFolderId: this.targetFolderId });
64
+ }
65
+ }
66
+ FolderDropDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: FolderDropDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
67
+ FolderDropDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.4.0", type: FolderDropDirective, selector: "[cqaFolderDrop]", inputs: { targetFolderId: ["cqaFolderDrop", "targetFolderId"], dropEnabled: "dropEnabled" }, outputs: { testsDropped: "testsDropped", folderDropped: "folderDropped" }, host: { listeners: { "dragover": "onDragOver($event)", "dragleave": "onDragLeave()", "drop": "onDrop($event)" }, properties: { "class.cqa-folder-drop-over": "this.isOver" } }, ngImport: i0 });
68
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: FolderDropDirective, decorators: [{
69
+ type: Directive,
70
+ args: [{
71
+ selector: '[cqaFolderDrop]',
72
+ }]
73
+ }], propDecorators: { targetFolderId: [{
74
+ type: Input,
75
+ args: ['cqaFolderDrop']
76
+ }], dropEnabled: [{
77
+ type: Input
78
+ }], testsDropped: [{
79
+ type: Output
80
+ }], folderDropped: [{
81
+ type: Output
82
+ }], isOver: [{
83
+ type: HostBinding,
84
+ args: ['class.cqa-folder-drop-over']
85
+ }], onDragOver: [{
86
+ type: HostListener,
87
+ args: ['dragover', ['$event']]
88
+ }], onDragLeave: [{
89
+ type: HostListener,
90
+ args: ['dragleave']
91
+ }], onDrop: [{
92
+ type: HostListener,
93
+ args: ['drop', ['$event']]
94
+ }] } });
95
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9sZGVyLWRyb3AuZGlyZWN0aXZlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi90ZW1wbGF0ZXMvbW9kdWxhci10YWJsZS10ZW1wbGF0ZS9kaXJlY3RpdmVzL2ZvbGRlci1kcm9wLmRpcmVjdGl2ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLFlBQVksRUFBRSxXQUFXLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDbEcsT0FBTyxFQUFFLGdCQUFnQixFQUFFLGFBQWEsRUFBRSxNQUFNLGtDQUFrQyxDQUFDOztBQUtuRixNQUFNLE9BQU8sbUJBQW1CO0lBSGhDO1FBSUUsZ0ZBQWdGO1FBQ3hELG1CQUFjLEdBQWtCLElBQUksQ0FBQztRQUNwRCxnQkFBVyxHQUFZLElBQUksQ0FBQztRQUUzQixpQkFBWSxHQUFHLElBQUksWUFBWSxFQUFzRSxDQUFDO1FBQ2hILHNGQUFzRjtRQUM1RSxrQkFBYSxHQUFHLElBQUksWUFBWSxFQUF1RCxDQUFDO1FBRXZELFdBQU0sR0FBRyxLQUFLLENBQUM7S0FnRDNEO0lBOUN1QyxVQUFVLENBQUMsS0FBZ0I7UUFDL0QsSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXO1lBQUUsT0FBTztRQUM5QixLQUFLLENBQUMsY0FBYyxFQUFFLENBQUM7UUFDdkIsSUFBSSxLQUFLLENBQUMsWUFBWSxFQUFFO1lBQ3RCLEtBQUssQ0FBQyxZQUFZLENBQUMsVUFBVSxHQUFHLE1BQU0sQ0FBQztTQUN4QztRQUNELElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDO0lBQ3JCLENBQUM7SUFFMEIsV0FBVztRQUNwQyxJQUFJLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQztJQUN0QixDQUFDO0lBRWlDLE1BQU0sQ0FBQyxLQUFnQjtRQUN2RCxJQUFJLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQztRQUNwQixJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsSUFBSSxDQUFDLEtBQUssQ0FBQyxZQUFZO1lBQUUsT0FBTztRQUNyRCxLQUFLLENBQUMsY0FBYyxFQUFFLENBQUM7UUFFdkIsa0ZBQWtGO1FBQ2xGLE1BQU0sU0FBUyxHQUFHLEtBQUssQ0FBQyxZQUFZLENBQUMsT0FBTyxDQUFDLGdCQUFnQixDQUFDLENBQUM7UUFDL0QsSUFBSSxTQUFTLEVBQUU7WUFDYixJQUFJLFFBQVEsR0FBa0IsSUFBSSxDQUFDO1lBQ25DLElBQUk7Z0JBQ0YsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsQ0FBQztnQkFDckMsSUFBSSxPQUFPLE1BQU0sS0FBSyxRQUFRLElBQUksTUFBTSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUM7b0JBQUUsUUFBUSxHQUFHLE1BQU0sQ0FBQzthQUM5RTtZQUFDLE1BQU07Z0JBQ04sT0FBTzthQUNSO1lBQ0QsSUFBSSxRQUFRLElBQUksSUFBSTtnQkFBRSxPQUFPO1lBQzdCLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLEVBQUUsUUFBUSxFQUFFLGNBQWMsRUFBRSxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUMsQ0FBQztZQUMzRSxPQUFPO1NBQ1I7UUFFRCxpREFBaUQ7UUFDakQsTUFBTSxHQUFHLEdBQUcsS0FBSyxDQUFDLFlBQVksQ0FBQyxPQUFPLENBQUMsYUFBYSxDQUFDLElBQUksS0FBSyxDQUFDLFlBQVksQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDbEcsSUFBSSxDQUFDLEdBQUc7WUFBRSxPQUFPO1FBQ2pCLElBQUksR0FBRyxHQUEyQixFQUFFLENBQUM7UUFDckMsSUFBSTtZQUNGLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDL0IsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQztnQkFBRSxHQUFHLEdBQUcsTUFBTSxDQUFDO1NBQ3pDO1FBQUMsTUFBTTtZQUNOLE9BQU87U0FDUjtRQUNELElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTTtZQUFFLE9BQU87UUFDeEIsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsRUFBRSxPQUFPLEVBQUUsR0FBRyxFQUFFLGNBQWMsRUFBRSxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUMsQ0FBQztJQUNoRixDQUFDOztnSEF4RFUsbUJBQW1CO29HQUFuQixtQkFBbUI7MkZBQW5CLG1CQUFtQjtrQkFIL0IsU0FBUzttQkFBQztvQkFDVCxRQUFRLEVBQUUsaUJBQWlCO2lCQUM1Qjs4QkFHeUIsY0FBYztzQkFBckMsS0FBSzt1QkFBQyxlQUFlO2dCQUNiLFdBQVc7c0JBQW5CLEtBQUs7Z0JBRUksWUFBWTtzQkFBckIsTUFBTTtnQkFFRyxhQUFhO3NCQUF0QixNQUFNO2dCQUVvQyxNQUFNO3NCQUFoRCxXQUFXO3VCQUFDLDRCQUE0QjtnQkFFSCxVQUFVO3NCQUEvQyxZQUFZO3VCQUFDLFVBQVUsRUFBRSxDQUFDLFFBQVEsQ0FBQztnQkFTVCxXQUFXO3NCQUFyQyxZQUFZO3VCQUFDLFdBQVc7Z0JBSVMsTUFBTTtzQkFBdkMsWUFBWTt1QkFBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBEaXJlY3RpdmUsIEV2ZW50RW1pdHRlciwgSG9zdEJpbmRpbmcsIEhvc3RMaXN0ZW5lciwgSW5wdXQsIE91dHB1dCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRk9MREVSX0RSQUdfTUlNRSwgUk9XX0RSQUdfTUlNRSB9IGZyb20gJy4uL21vZHVsYXItdGFibGUtdGVtcGxhdGUubW9kZWxzJztcblxuQERpcmVjdGl2ZSh7XG4gIHNlbGVjdG9yOiAnW2NxYUZvbGRlckRyb3BdJyxcbn0pXG5leHBvcnQgY2xhc3MgRm9sZGVyRHJvcERpcmVjdGl2ZSB7XG4gIC8qKiBGb2xkZXIgaWQgdGhpcyBkcm9wIHRhcmdldCByZXByZXNlbnRzLiBgbnVsbGAgbWVhbnMgXCJ1bm9yZ2FuaXNlZCAvIHJvb3RcIi4gKi9cbiAgQElucHV0KCdjcWFGb2xkZXJEcm9wJykgdGFyZ2V0Rm9sZGVySWQ6IG51bWJlciB8IG51bGwgPSBudWxsO1xuICBASW5wdXQoKSBkcm9wRW5hYmxlZDogYm9vbGVhbiA9IHRydWU7XG5cbiAgQE91dHB1dCgpIHRlc3RzRHJvcHBlZCA9IG5ldyBFdmVudEVtaXR0ZXI8eyB0ZXN0SWRzOiBBcnJheTxzdHJpbmcgfCBudW1iZXI+OyB0YXJnZXRGb2xkZXJJZDogbnVtYmVyIHwgbnVsbCB9PigpO1xuICAvKiogRmlyZXMgd2hlbiBhIGZvbGRlciByb3cgaXMgZHJvcHBlZCBoZXJlLiBgZm9sZGVySWRgIGlzIHRoZSBkcmFnZ2VkIGZvbGRlcidzIGlkLiAqL1xuICBAT3V0cHV0KCkgZm9sZGVyRHJvcHBlZCA9IG5ldyBFdmVudEVtaXR0ZXI8eyBmb2xkZXJJZDogbnVtYmVyOyB0YXJnZXRGb2xkZXJJZDogbnVtYmVyIHwgbnVsbCB9PigpO1xuXG4gIEBIb3N0QmluZGluZygnY2xhc3MuY3FhLWZvbGRlci1kcm9wLW92ZXInKSBpc092ZXIgPSBmYWxzZTtcblxuICBASG9zdExpc3RlbmVyKCdkcmFnb3ZlcicsIFsnJGV2ZW50J10pIG9uRHJhZ092ZXIoZXZlbnQ6IERyYWdFdmVudCkge1xuICAgIGlmICghdGhpcy5kcm9wRW5hYmxlZCkgcmV0dXJuO1xuICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgaWYgKGV2ZW50LmRhdGFUcmFuc2Zlcikge1xuICAgICAgZXZlbnQuZGF0YVRyYW5zZmVyLmRyb3BFZmZlY3QgPSAnbW92ZSc7XG4gICAgfVxuICAgIHRoaXMuaXNPdmVyID0gdHJ1ZTtcbiAgfVxuXG4gIEBIb3N0TGlzdGVuZXIoJ2RyYWdsZWF2ZScpIG9uRHJhZ0xlYXZlKCkge1xuICAgIHRoaXMuaXNPdmVyID0gZmFsc2U7XG4gIH1cblxuICBASG9zdExpc3RlbmVyKCdkcm9wJywgWyckZXZlbnQnXSkgb25Ecm9wKGV2ZW50OiBEcmFnRXZlbnQpIHtcbiAgICB0aGlzLmlzT3ZlciA9IGZhbHNlO1xuICAgIGlmICghdGhpcy5kcm9wRW5hYmxlZCB8fCAhZXZlbnQuZGF0YVRyYW5zZmVyKSByZXR1cm47XG4gICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuICAgIC8vIEZvbGRlciBkcm9wcyB0YWtlIHByZWNlZGVuY2Ug4oCUIHRoZSBzaWRlYmFyIHdyaXRlcyB0aGUgZm9sZGVyIE1JTUUgb24gZHJhZ3N0YXJ0LlxuICAgIGNvbnN0IGZvbGRlclJhdyA9IGV2ZW50LmRhdGFUcmFuc2Zlci5nZXREYXRhKEZPTERFUl9EUkFHX01JTUUpO1xuICAgIGlmIChmb2xkZXJSYXcpIHtcbiAgICAgIGxldCBmb2xkZXJJZDogbnVtYmVyIHwgbnVsbCA9IG51bGw7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCBwYXJzZWQgPSBKU09OLnBhcnNlKGZvbGRlclJhdyk7XG4gICAgICAgIGlmICh0eXBlb2YgcGFyc2VkID09PSAnbnVtYmVyJyAmJiBOdW1iZXIuaXNGaW5pdGUocGFyc2VkKSkgZm9sZGVySWQgPSBwYXJzZWQ7XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgaWYgKGZvbGRlcklkID09IG51bGwpIHJldHVybjtcbiAgICAgIHRoaXMuZm9sZGVyRHJvcHBlZC5lbWl0KHsgZm9sZGVySWQsIHRhcmdldEZvbGRlcklkOiB0aGlzLnRhcmdldEZvbGRlcklkIH0pO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIEZhbGwgdGhyb3VnaCB0byB0aGUgdGVzdC1pZHMgcGF0aCAodW5jaGFuZ2VkKS5cbiAgICBjb25zdCByYXcgPSBldmVudC5kYXRhVHJhbnNmZXIuZ2V0RGF0YShST1dfRFJBR19NSU1FKSB8fCBldmVudC5kYXRhVHJhbnNmZXIuZ2V0RGF0YSgndGV4dC9wbGFpbicpO1xuICAgIGlmICghcmF3KSByZXR1cm47XG4gICAgbGV0IGlkczogQXJyYXk8c3RyaW5nIHwgbnVtYmVyPiA9IFtdO1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBwYXJzZWQgPSBKU09OLnBhcnNlKHJhdyk7XG4gICAgICBpZiAoQXJyYXkuaXNBcnJheShwYXJzZWQpKSBpZHMgPSBwYXJzZWQ7XG4gICAgfSBjYXRjaCB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmICghaWRzLmxlbmd0aCkgcmV0dXJuO1xuICAgIHRoaXMudGVzdHNEcm9wcGVkLmVtaXQoeyB0ZXN0SWRzOiBpZHMsIHRhcmdldEZvbGRlcklkOiB0aGlzLnRhcmdldEZvbGRlcklkIH0pO1xuICB9XG59XG4iXX0=
@@ -0,0 +1,44 @@
1
+ import { Directive, HostBinding, HostListener, Input } from '@angular/core';
2
+ import { ROW_DRAG_MIME } from '../modular-table-template.models';
3
+ import * as i0 from "@angular/core";
4
+ export class RowDragDirective {
5
+ constructor() {
6
+ this.dragEnabled = true;
7
+ }
8
+ get draggable() {
9
+ return this.dragEnabled ? 'true' : null;
10
+ }
11
+ onDragStart(event) {
12
+ if (!this.dragEnabled || !event.dataTransfer || !this.buildPayload)
13
+ return;
14
+ const ids = this.buildPayload() ?? [];
15
+ event.dataTransfer.effectAllowed = 'move';
16
+ try {
17
+ event.dataTransfer.setData(ROW_DRAG_MIME, JSON.stringify(ids));
18
+ }
19
+ catch {
20
+ /* some browsers reject custom MIME — fall through */
21
+ }
22
+ event.dataTransfer.setData('text/plain', JSON.stringify(ids));
23
+ }
24
+ }
25
+ RowDragDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: RowDragDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
26
+ RowDragDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.4.0", type: RowDragDirective, selector: "[cqaRowDrag]", inputs: { buildPayload: ["cqaRowDrag", "buildPayload"], dragEnabled: "dragEnabled" }, host: { listeners: { "dragstart": "onDragStart($event)" }, properties: { "attr.draggable": "this.draggable" } }, ngImport: i0 });
27
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: RowDragDirective, decorators: [{
28
+ type: Directive,
29
+ args: [{
30
+ selector: '[cqaRowDrag]',
31
+ }]
32
+ }], propDecorators: { buildPayload: [{
33
+ type: Input,
34
+ args: ['cqaRowDrag']
35
+ }], dragEnabled: [{
36
+ type: Input
37
+ }], draggable: [{
38
+ type: HostBinding,
39
+ args: ['attr.draggable']
40
+ }], onDragStart: [{
41
+ type: HostListener,
42
+ args: ['dragstart', ['$event']]
43
+ }] } });
44
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm93LWRyYWcuZGlyZWN0aXZlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2xpYi90ZW1wbGF0ZXMvbW9kdWxhci10YWJsZS10ZW1wbGF0ZS9kaXJlY3RpdmVzL3Jvdy1kcmFnLmRpcmVjdGl2ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLFdBQVcsRUFBRSxZQUFZLEVBQUUsS0FBSyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzVFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxrQ0FBa0MsQ0FBQzs7QUFLakUsTUFBTSxPQUFPLGdCQUFnQjtJQUg3QjtRQU1XLGdCQUFXLEdBQVksSUFBSSxDQUFDO0tBaUJ0QztJQWZDLElBQW1DLFNBQVM7UUFDMUMsT0FBTyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztJQUMxQyxDQUFDO0lBRXNDLFdBQVcsQ0FBQyxLQUFnQjtRQUNqRSxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsSUFBSSxDQUFDLEtBQUssQ0FBQyxZQUFZLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWTtZQUFFLE9BQU87UUFDM0UsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLFlBQVksRUFBRSxJQUFJLEVBQUUsQ0FBQztRQUN0QyxLQUFLLENBQUMsWUFBWSxDQUFDLGFBQWEsR0FBRyxNQUFNLENBQUM7UUFDMUMsSUFBSTtZQUNGLEtBQUssQ0FBQyxZQUFZLENBQUMsT0FBTyxDQUFDLGFBQWEsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7U0FDaEU7UUFBQyxNQUFNO1lBQ04scURBQXFEO1NBQ3REO1FBQ0QsS0FBSyxDQUFDLFlBQVksQ0FBQyxPQUFPLENBQUMsWUFBWSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUNoRSxDQUFDOzs2R0FuQlUsZ0JBQWdCO2lHQUFoQixnQkFBZ0I7MkZBQWhCLGdCQUFnQjtrQkFINUIsU0FBUzttQkFBQztvQkFDVCxRQUFRLEVBQUUsY0FBYztpQkFDekI7OEJBR3NCLFlBQVk7c0JBQWhDLEtBQUs7dUJBQUMsWUFBWTtnQkFDVixXQUFXO3NCQUFuQixLQUFLO2dCQUU2QixTQUFTO3NCQUEzQyxXQUFXO3VCQUFDLGdCQUFnQjtnQkFJVSxXQUFXO3NCQUFqRCxZQUFZO3VCQUFDLFdBQVcsRUFBRSxDQUFDLFFBQVEsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IERpcmVjdGl2ZSwgSG9zdEJpbmRpbmcsIEhvc3RMaXN0ZW5lciwgSW5wdXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IFJPV19EUkFHX01JTUUgfSBmcm9tICcuLi9tb2R1bGFyLXRhYmxlLXRlbXBsYXRlLm1vZGVscyc7XG5cbkBEaXJlY3RpdmUoe1xuICBzZWxlY3RvcjogJ1tjcWFSb3dEcmFnXScsXG59KVxuZXhwb3J0IGNsYXNzIFJvd0RyYWdEaXJlY3RpdmUge1xuICAvKiogRnVuY3Rpb24gdGhhdCByZXR1cm5zIHRoZSB0ZXN0IGlkIHBheWxvYWQgZm9yIHRoaXMgcm93IChhcnJheSBvZiBpZHMpLiAqL1xuICBASW5wdXQoJ2NxYVJvd0RyYWcnKSBidWlsZFBheWxvYWQhOiAoKSA9PiBBcnJheTxzdHJpbmcgfCBudW1iZXI+O1xuICBASW5wdXQoKSBkcmFnRW5hYmxlZDogYm9vbGVhbiA9IHRydWU7XG5cbiAgQEhvc3RCaW5kaW5nKCdhdHRyLmRyYWdnYWJsZScpIGdldCBkcmFnZ2FibGUoKSB7XG4gICAgcmV0dXJuIHRoaXMuZHJhZ0VuYWJsZWQgPyAndHJ1ZScgOiBudWxsO1xuICB9XG5cbiAgQEhvc3RMaXN0ZW5lcignZHJhZ3N0YXJ0JywgWyckZXZlbnQnXSkgb25EcmFnU3RhcnQoZXZlbnQ6IERyYWdFdmVudCkge1xuICAgIGlmICghdGhpcy5kcmFnRW5hYmxlZCB8fCAhZXZlbnQuZGF0YVRyYW5zZmVyIHx8ICF0aGlzLmJ1aWxkUGF5bG9hZCkgcmV0dXJuO1xuICAgIGNvbnN0IGlkcyA9IHRoaXMuYnVpbGRQYXlsb2FkKCkgPz8gW107XG4gICAgZXZlbnQuZGF0YVRyYW5zZmVyLmVmZmVjdEFsbG93ZWQgPSAnbW92ZSc7XG4gICAgdHJ5IHtcbiAgICAgIGV2ZW50LmRhdGFUcmFuc2Zlci5zZXREYXRhKFJPV19EUkFHX01JTUUsIEpTT04uc3RyaW5naWZ5KGlkcykpO1xuICAgIH0gY2F0Y2gge1xuICAgICAgLyogc29tZSBicm93c2VycyByZWplY3QgY3VzdG9tIE1JTUUg4oCUIGZhbGwgdGhyb3VnaCAqL1xuICAgIH1cbiAgICBldmVudC5kYXRhVHJhbnNmZXIuc2V0RGF0YSgndGV4dC9wbGFpbicsIEpTT04uc3RyaW5naWZ5KGlkcykpO1xuICB9XG59XG4iXX0=