ngx-dynamic-entity-builder 1.3.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/fesm2022/ngx-dynamic-entity-builder.mjs +521 -105
- package/fesm2022/ngx-dynamic-entity-builder.mjs.map +1 -1
- package/package.json +7 -7
- package/types/ngx-dynamic-entity-builder.d.ts +582 -0
- package/esm2022/lib/builder-store.service.mjs +0 -1057
- package/esm2022/lib/clone.mjs +0 -14
- package/esm2022/lib/components/entity-builder-canvas.component.mjs +0 -84
- package/esm2022/lib/components/entity-builder-tree-node.component.mjs +0 -192
- package/esm2022/lib/components/entity-reference-config.component.mjs +0 -405
- package/esm2022/lib/components/field-inspector.component.mjs +0 -139
- package/esm2022/lib/components/field-palette.component.mjs +0 -57
- package/esm2022/lib/components/field-rules-list.component.mjs +0 -224
- package/esm2022/lib/components/referenced-field-config.component.mjs +0 -235
- package/esm2022/lib/components/rule-form.component.mjs +0 -201
- package/esm2022/lib/components/tab-manager.component.mjs +0 -354
- package/esm2022/lib/entity-builder.component.mjs +0 -159
- package/esm2022/lib/field-catalog.mjs +0 -6
- package/esm2022/ngx-dynamic-entity-builder.mjs +0 -5
- package/esm2022/public-api.mjs +0 -16
- package/index.d.ts +0 -5
- package/lib/builder-store.service.d.ts +0 -206
- package/lib/clone.d.ts +0 -9
- package/lib/components/entity-builder-canvas.component.d.ts +0 -9
- package/lib/components/entity-builder-tree-node.component.d.ts +0 -17
- package/lib/components/entity-reference-config.component.d.ts +0 -29
- package/lib/components/field-inspector.component.d.ts +0 -33
- package/lib/components/field-palette.component.d.ts +0 -13
- package/lib/components/field-rules-list.component.d.ts +0 -19
- package/lib/components/referenced-field-config.component.d.ts +0 -24
- package/lib/components/rule-form.component.d.ts +0 -16
- package/lib/components/tab-manager.component.d.ts +0 -28
- package/lib/entity-builder.component.d.ts +0 -45
- package/lib/field-catalog.d.ts +0 -5
- package/public-api.d.ts +0 -12
package/esm2022/lib/clone.mjs
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Deep clone with a JSON fallback.
|
|
3
|
-
*
|
|
4
|
-
* `structuredClone` is not universally available (older browsers, and jsdom before v22),
|
|
5
|
-
* so it must never be called unguarded — an unguarded call throws a ReferenceError and the
|
|
6
|
-
* caller silently does nothing. Config and rule objects are JSON-safe, so the fallback is
|
|
7
|
-
* lossless here.
|
|
8
|
-
*/
|
|
9
|
-
export function deepClone(value) {
|
|
10
|
-
if (typeof structuredClone === 'function')
|
|
11
|
-
return structuredClone(value);
|
|
12
|
-
return JSON.parse(JSON.stringify(value));
|
|
13
|
-
}
|
|
14
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xvbmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL2Nsb25lLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7O0dBT0c7QUFDSCxNQUFNLFVBQVUsU0FBUyxDQUFJLEtBQVE7SUFDbkMsSUFBSSxPQUFPLGVBQWUsS0FBSyxVQUFVO1FBQUUsT0FBTyxlQUFlLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDekUsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQU0sQ0FBQztBQUNoRCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBEZWVwIGNsb25lIHdpdGggYSBKU09OIGZhbGxiYWNrLlxuICpcbiAqIGBzdHJ1Y3R1cmVkQ2xvbmVgIGlzIG5vdCB1bml2ZXJzYWxseSBhdmFpbGFibGUgKG9sZGVyIGJyb3dzZXJzLCBhbmQganNkb20gYmVmb3JlIHYyMiksXG4gKiBzbyBpdCBtdXN0IG5ldmVyIGJlIGNhbGxlZCB1bmd1YXJkZWQg4oCUIGFuIHVuZ3VhcmRlZCBjYWxsIHRocm93cyBhIFJlZmVyZW5jZUVycm9yIGFuZCB0aGVcbiAqIGNhbGxlciBzaWxlbnRseSBkb2VzIG5vdGhpbmcuIENvbmZpZyBhbmQgcnVsZSBvYmplY3RzIGFyZSBKU09OLXNhZmUsIHNvIHRoZSBmYWxsYmFjayBpc1xuICogbG9zc2xlc3MgaGVyZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRlZXBDbG9uZTxUPih2YWx1ZTogVCk6IFQge1xuICBpZiAodHlwZW9mIHN0cnVjdHVyZWRDbG9uZSA9PT0gJ2Z1bmN0aW9uJykgcmV0dXJuIHN0cnVjdHVyZWRDbG9uZSh2YWx1ZSk7XG4gIHJldHVybiBKU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KHZhbHVlKSkgYXMgVDtcbn1cbiJdfQ==
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import { ChangeDetectionStrategy, Component, inject } from '@angular/core';
|
|
2
|
-
import { CommonModule } from '@angular/common';
|
|
3
|
-
import { DragDropModule } from '@angular/cdk/drag-drop';
|
|
4
|
-
import { MatCardModule } from '@angular/material/card';
|
|
5
|
-
import { MatIconModule } from '@angular/material/icon';
|
|
6
|
-
import { BuilderStore } from '../builder-store.service';
|
|
7
|
-
import { EntityBuilderTreeNodeComponent } from './entity-builder-tree-node.component';
|
|
8
|
-
import * as i0 from "@angular/core";
|
|
9
|
-
import * as i1 from "@angular/cdk/drag-drop";
|
|
10
|
-
import * as i2 from "@angular/material/card";
|
|
11
|
-
import * as i3 from "@angular/material/icon";
|
|
12
|
-
export class EntityBuilderCanvasComponent {
|
|
13
|
-
store = inject(BuilderStore);
|
|
14
|
-
onDrop(event) {
|
|
15
|
-
this.store.reorderField(event.previousIndex, event.currentIndex);
|
|
16
|
-
}
|
|
17
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: EntityBuilderCanvasComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
18
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: EntityBuilderCanvasComponent, isStandalone: true, selector: "ngx-entity-builder-canvas", ngImport: i0, template: `
|
|
19
|
-
<mat-card class="deb-canvas">
|
|
20
|
-
<mat-card-header>
|
|
21
|
-
<mat-card-title>Fields ({{ store.fields().length }})</mat-card-title>
|
|
22
|
-
</mat-card-header>
|
|
23
|
-
<mat-card-content>
|
|
24
|
-
@if (store.fields().length === 0) {
|
|
25
|
-
<div class="deb-empty">
|
|
26
|
-
<mat-icon>widgets</mat-icon>
|
|
27
|
-
<p>No fields yet. Pick a type from <strong>Add field</strong> to get started.</p>
|
|
28
|
-
</div>
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
<div cdkDropList class="deb-field-list" data-testid="builder-field-list" (cdkDropListDropped)="onDrop($event)">
|
|
32
|
-
@for (f of store.fields(); track f.id; let i = $index, count = $count) {
|
|
33
|
-
<ngx-entity-builder-tree-node
|
|
34
|
-
[field]="f"
|
|
35
|
-
[index]="i"
|
|
36
|
-
[totalCount]="count"
|
|
37
|
-
/>
|
|
38
|
-
}
|
|
39
|
-
</div>
|
|
40
|
-
</mat-card-content>
|
|
41
|
-
</mat-card>
|
|
42
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i1.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "ngmodule", type: MatCardModule }, { kind: "component", type: i2.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i2.MatCardContent, selector: "mat-card-content" }, { kind: "component", type: i2.MatCardHeader, selector: "mat-card-header" }, { kind: "directive", type: i2.MatCardTitle, selector: "mat-card-title, [mat-card-title], [matCardTitle]" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: EntityBuilderTreeNodeComponent, selector: "ngx-entity-builder-tree-node", inputs: ["field", "index", "totalCount"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
43
|
-
}
|
|
44
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: EntityBuilderCanvasComponent, decorators: [{
|
|
45
|
-
type: Component,
|
|
46
|
-
args: [{
|
|
47
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
48
|
-
selector: 'ngx-entity-builder-canvas',
|
|
49
|
-
standalone: true,
|
|
50
|
-
imports: [
|
|
51
|
-
CommonModule,
|
|
52
|
-
DragDropModule,
|
|
53
|
-
MatCardModule,
|
|
54
|
-
MatIconModule,
|
|
55
|
-
EntityBuilderTreeNodeComponent,
|
|
56
|
-
],
|
|
57
|
-
template: `
|
|
58
|
-
<mat-card class="deb-canvas">
|
|
59
|
-
<mat-card-header>
|
|
60
|
-
<mat-card-title>Fields ({{ store.fields().length }})</mat-card-title>
|
|
61
|
-
</mat-card-header>
|
|
62
|
-
<mat-card-content>
|
|
63
|
-
@if (store.fields().length === 0) {
|
|
64
|
-
<div class="deb-empty">
|
|
65
|
-
<mat-icon>widgets</mat-icon>
|
|
66
|
-
<p>No fields yet. Pick a type from <strong>Add field</strong> to get started.</p>
|
|
67
|
-
</div>
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
<div cdkDropList class="deb-field-list" data-testid="builder-field-list" (cdkDropListDropped)="onDrop($event)">
|
|
71
|
-
@for (f of store.fields(); track f.id; let i = $index, count = $count) {
|
|
72
|
-
<ngx-entity-builder-tree-node
|
|
73
|
-
[field]="f"
|
|
74
|
-
[index]="i"
|
|
75
|
-
[totalCount]="count"
|
|
76
|
-
/>
|
|
77
|
-
}
|
|
78
|
-
</div>
|
|
79
|
-
</mat-card-content>
|
|
80
|
-
</mat-card>
|
|
81
|
-
`,
|
|
82
|
-
}]
|
|
83
|
-
}] });
|
|
84
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW50aXR5LWJ1aWxkZXItY2FudmFzLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvY29tcG9uZW50cy9lbnRpdHktYnVpbGRlci1jYW52YXMuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzNFLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQWUsY0FBYyxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDckUsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUN2RCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDeEQsT0FBTyxFQUFFLDhCQUE4QixFQUFFLE1BQU0sc0NBQXNDLENBQUM7Ozs7O0FBdUN0RixNQUFNLE9BQU8sNEJBQTRCO0lBQ3BCLEtBQUssR0FBRyxNQUFNLENBQUMsWUFBWSxDQUFDLENBQUM7SUFFdEMsTUFBTSxDQUFDLEtBQTJCO1FBQzFDLElBQUksQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLEtBQUssQ0FBQyxhQUFhLEVBQUUsS0FBSyxDQUFDLFlBQVksQ0FBQyxDQUFDO0lBQ25FLENBQUM7d0dBTFUsNEJBQTRCOzRGQUE1Qiw0QkFBNEIscUZBMUI3Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBd0JULDJEQTlCQyxZQUFZLDhCQUNaLGNBQWMsMmdCQUNkLGFBQWEsa1pBQ2IsYUFBYSxvTEFDYiw4QkFBOEI7OzRGQTRCckIsNEJBQTRCO2tCQXJDeEMsU0FBUzttQkFBQztvQkFDVCxlQUFlLEVBQUUsdUJBQXVCLENBQUMsTUFBTTtvQkFDL0MsUUFBUSxFQUFFLDJCQUEyQjtvQkFDckMsVUFBVSxFQUFFLElBQUk7b0JBQ2hCLE9BQU8sRUFBRTt3QkFDUCxZQUFZO3dCQUNaLGNBQWM7d0JBQ2QsYUFBYTt3QkFDYixhQUFhO3dCQUNiLDhCQUE4QjtxQkFDL0I7b0JBQ0QsUUFBUSxFQUFFOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0F3QlQ7aUJBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSwgQ29tcG9uZW50LCBpbmplY3QgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBDZGtEcmFnRHJvcCwgRHJhZ0Ryb3BNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jZGsvZHJhZy1kcm9wJztcbmltcG9ydCB7IE1hdENhcmRNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9jYXJkJztcbmltcG9ydCB7IE1hdEljb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9pY29uJztcbmltcG9ydCB7IEJ1aWxkZXJTdG9yZSB9IGZyb20gJy4uL2J1aWxkZXItc3RvcmUuc2VydmljZSc7XG5pbXBvcnQgeyBFbnRpdHlCdWlsZGVyVHJlZU5vZGVDb21wb25lbnQgfSBmcm9tICcuL2VudGl0eS1idWlsZGVyLXRyZWUtbm9kZS5jb21wb25lbnQnO1xuXG5AQ29tcG9uZW50KHtcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIHNlbGVjdG9yOiAnbmd4LWVudGl0eS1idWlsZGVyLWNhbnZhcycsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtcbiAgICBDb21tb25Nb2R1bGUsXG4gICAgRHJhZ0Ryb3BNb2R1bGUsXG4gICAgTWF0Q2FyZE1vZHVsZSxcbiAgICBNYXRJY29uTW9kdWxlLFxuICAgIEVudGl0eUJ1aWxkZXJUcmVlTm9kZUNvbXBvbmVudCxcbiAgXSxcbiAgdGVtcGxhdGU6IGBcbiAgICA8bWF0LWNhcmQgY2xhc3M9XCJkZWItY2FudmFzXCI+XG4gICAgICA8bWF0LWNhcmQtaGVhZGVyPlxuICAgICAgICA8bWF0LWNhcmQtdGl0bGU+RmllbGRzICh7eyBzdG9yZS5maWVsZHMoKS5sZW5ndGggfX0pPC9tYXQtY2FyZC10aXRsZT5cbiAgICAgIDwvbWF0LWNhcmQtaGVhZGVyPlxuICAgICAgPG1hdC1jYXJkLWNvbnRlbnQ+XG4gICAgICAgIEBpZiAoc3RvcmUuZmllbGRzKCkubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImRlYi1lbXB0eVwiPlxuICAgICAgICAgICAgPG1hdC1pY29uPndpZGdldHM8L21hdC1pY29uPlxuICAgICAgICAgICAgPHA+Tm8gZmllbGRzIHlldC4gUGljayBhIHR5cGUgZnJvbSA8c3Ryb25nPkFkZCBmaWVsZDwvc3Ryb25nPiB0byBnZXQgc3RhcnRlZC48L3A+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIH1cblxuICAgICAgICA8ZGl2IGNka0Ryb3BMaXN0IGNsYXNzPVwiZGViLWZpZWxkLWxpc3RcIiBkYXRhLXRlc3RpZD1cImJ1aWxkZXItZmllbGQtbGlzdFwiIChjZGtEcm9wTGlzdERyb3BwZWQpPVwib25Ecm9wKCRldmVudClcIj5cbiAgICAgICAgICBAZm9yIChmIG9mIHN0b3JlLmZpZWxkcygpOyB0cmFjayBmLmlkOyBsZXQgaSA9ICRpbmRleCwgY291bnQgPSAkY291bnQpIHtcbiAgICAgICAgICAgIDxuZ3gtZW50aXR5LWJ1aWxkZXItdHJlZS1ub2RlXG4gICAgICAgICAgICAgIFtmaWVsZF09XCJmXCJcbiAgICAgICAgICAgICAgW2luZGV4XT1cImlcIlxuICAgICAgICAgICAgICBbdG90YWxDb3VudF09XCJjb3VudFwiXG4gICAgICAgICAgICAvPlxuICAgICAgICAgIH1cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L21hdC1jYXJkLWNvbnRlbnQ+XG4gICAgPC9tYXQtY2FyZD5cbiAgYCxcbn0pXG5leHBvcnQgY2xhc3MgRW50aXR5QnVpbGRlckNhbnZhc0NvbXBvbmVudCB7XG4gIHByb3RlY3RlZCByZWFkb25seSBzdG9yZSA9IGluamVjdChCdWlsZGVyU3RvcmUpO1xuXG4gIHByb3RlY3RlZCBvbkRyb3AoZXZlbnQ6IENka0RyYWdEcm9wPHVua25vd24+KTogdm9pZCB7XG4gICAgdGhpcy5zdG9yZS5yZW9yZGVyRmllbGQoZXZlbnQucHJldmlvdXNJbmRleCwgZXZlbnQuY3VycmVudEluZGV4KTtcbiAgfVxufVxuIl19
|
|
@@ -1,192 +0,0 @@
|
|
|
1
|
-
import { ChangeDetectionStrategy, Component, Input, inject } from '@angular/core';
|
|
2
|
-
import { CommonModule } from '@angular/common';
|
|
3
|
-
import { DragDropModule } from '@angular/cdk/drag-drop';
|
|
4
|
-
import { MatButtonModule } from '@angular/material/button';
|
|
5
|
-
import { MatIconModule } from '@angular/material/icon';
|
|
6
|
-
import { MatTooltipModule } from '@angular/material/tooltip';
|
|
7
|
-
import { resolveLabel } from '@dynamic-entity/core';
|
|
8
|
-
import { BuilderStore } from '../builder-store.service';
|
|
9
|
-
import { getFieldTypeMeta } from '../field-catalog';
|
|
10
|
-
import * as i0 from "@angular/core";
|
|
11
|
-
import * as i1 from "@angular/cdk/drag-drop";
|
|
12
|
-
import * as i2 from "@angular/material/button";
|
|
13
|
-
import * as i3 from "@angular/material/icon";
|
|
14
|
-
import * as i4 from "@angular/material/tooltip";
|
|
15
|
-
export class EntityBuilderTreeNodeComponent {
|
|
16
|
-
store = inject(BuilderStore);
|
|
17
|
-
field;
|
|
18
|
-
index;
|
|
19
|
-
totalCount;
|
|
20
|
-
fieldTypeLabel(type) {
|
|
21
|
-
return getFieldTypeMeta(type)?.label ?? type;
|
|
22
|
-
}
|
|
23
|
-
fieldTypeIcon(type) {
|
|
24
|
-
return getFieldTypeMeta(type)?.icon ?? 'help_outline';
|
|
25
|
-
}
|
|
26
|
-
fieldLabel(field) {
|
|
27
|
-
const lang = this.store.activeLanguage();
|
|
28
|
-
return resolveLabel(field.label, lang) || field.id;
|
|
29
|
-
}
|
|
30
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: EntityBuilderTreeNodeComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
31
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: EntityBuilderTreeNodeComponent, isStandalone: true, selector: "ngx-entity-builder-tree-node", inputs: { field: "field", index: "index", totalCount: "totalCount" }, ngImport: i0, template: `
|
|
32
|
-
<div
|
|
33
|
-
cdkDrag
|
|
34
|
-
class="deb-field-row"
|
|
35
|
-
data-testid="builder-field-row"
|
|
36
|
-
[class.deb-field-row--active]="store.selectedFieldId() === field.id"
|
|
37
|
-
(click)="store.selectField(field.id)"
|
|
38
|
-
(keydown.enter)="store.selectField(field.id)"
|
|
39
|
-
(keydown.space)="store.selectField(field.id); $event.preventDefault()"
|
|
40
|
-
role="button"
|
|
41
|
-
tabindex="0"
|
|
42
|
-
[attr.aria-pressed]="store.selectedFieldId() === field.id"
|
|
43
|
-
[attr.aria-label]="'Select field ' + fieldLabel(field)"
|
|
44
|
-
>
|
|
45
|
-
<mat-icon class="deb-drag-handle" cdkDragHandle aria-hidden="true" title="Drag to reorder (or use the move buttons)">drag_indicator</mat-icon>
|
|
46
|
-
<mat-icon class="deb-field-type" [matTooltip]="fieldTypeLabel(field.type)">{{ fieldTypeIcon(field.type) }}</mat-icon>
|
|
47
|
-
<div class="deb-field-meta">
|
|
48
|
-
<div class="deb-row" style="gap:6px">
|
|
49
|
-
<span class="deb-field-label" [attr.data-testid]="'row-label-' + field.id">{{ fieldLabel(field) }}</span>
|
|
50
|
-
<span class="deb-type-badge">{{ field.type }}</span>
|
|
51
|
-
@if (field.isReferenced) {
|
|
52
|
-
<mat-icon style="font-size: 16px; width: 16px; height: 16px; color: #1976d2;" matTooltip="Referenced field (linked to {{ field.referencedEntityKey }})">link</mat-icon>
|
|
53
|
-
}
|
|
54
|
-
@if (field.hasDrift) {
|
|
55
|
-
<mat-icon style="font-size: 16px; width: 16px; height: 16px; color: #d32f2f;" data-testid="drift-warning-icon" matTooltip="Drift detected: source field has evolved">sync_problem</mat-icon>
|
|
56
|
-
}
|
|
57
|
-
</div>
|
|
58
|
-
<span class="deb-field-id" [attr.data-testid]="'row-id-' + field.id">{{ field.id }}</span>
|
|
59
|
-
</div>
|
|
60
|
-
@if (field.validators?.required) { <span class="deb-req" title="Required">*</span> }
|
|
61
|
-
|
|
62
|
-
<button mat-icon-button type="button" [disabled]="index === 0"
|
|
63
|
-
[attr.data-testid]="'row-up-' + field.id"
|
|
64
|
-
[attr.aria-label]="'Move ' + fieldLabel(field) + ' up'"
|
|
65
|
-
(click)="store.moveField(field.id, -1); $event.stopPropagation()" matTooltip="Move up">
|
|
66
|
-
<mat-icon>arrow_upward</mat-icon>
|
|
67
|
-
</button>
|
|
68
|
-
<button mat-icon-button type="button" [disabled]="index === totalCount - 1"
|
|
69
|
-
[attr.data-testid]="'row-down-' + field.id"
|
|
70
|
-
[attr.aria-label]="'Move ' + fieldLabel(field) + ' down'"
|
|
71
|
-
(click)="store.moveField(field.id, 1); $event.stopPropagation()" matTooltip="Move down">
|
|
72
|
-
<mat-icon>arrow_downward</mat-icon>
|
|
73
|
-
</button>
|
|
74
|
-
<button mat-icon-button type="button"
|
|
75
|
-
[attr.data-testid]="'row-duplicate-' + field.id"
|
|
76
|
-
[attr.aria-label]="'Duplicate ' + fieldLabel(field)"
|
|
77
|
-
(click)="store.duplicateField(field.id); $event.stopPropagation()" matTooltip="Duplicate">
|
|
78
|
-
<mat-icon>content_copy</mat-icon>
|
|
79
|
-
</button>
|
|
80
|
-
<button mat-icon-button type="button" color="warn"
|
|
81
|
-
[attr.data-testid]="'row-delete-' + field.id"
|
|
82
|
-
(click)="store.removeField(field.id); $event.stopPropagation()" matTooltip="Delete">
|
|
83
|
-
<mat-icon>delete</mat-icon>
|
|
84
|
-
</button>
|
|
85
|
-
</div>
|
|
86
|
-
|
|
87
|
-
@if (field.children && field.children.length > 0) {
|
|
88
|
-
<div class="deb-tree-children" style="padding-left: 20px; border-left: 2px solid rgba(0,0,0,0.08); margin-left: 12px; margin-top: 4px;">
|
|
89
|
-
@for (child of field.children; track child.id; let ci = $index, cCount = $count) {
|
|
90
|
-
<ngx-entity-builder-tree-node
|
|
91
|
-
[field]="child"
|
|
92
|
-
[index]="ci"
|
|
93
|
-
[totalCount]="cCount"
|
|
94
|
-
/>
|
|
95
|
-
}
|
|
96
|
-
</div>
|
|
97
|
-
}
|
|
98
|
-
`, isInline: true, dependencies: [{ kind: "component", type: EntityBuilderTreeNodeComponent, selector: "ngx-entity-builder-tree-node", inputs: ["field", "index", "totalCount"] }, { kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: DragDropModule }, { kind: "directive", type: i1.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i1.CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i4.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
99
|
-
}
|
|
100
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: EntityBuilderTreeNodeComponent, decorators: [{
|
|
101
|
-
type: Component,
|
|
102
|
-
args: [{
|
|
103
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
104
|
-
selector: 'ngx-entity-builder-tree-node',
|
|
105
|
-
standalone: true,
|
|
106
|
-
imports: [
|
|
107
|
-
CommonModule,
|
|
108
|
-
DragDropModule,
|
|
109
|
-
MatButtonModule,
|
|
110
|
-
MatIconModule,
|
|
111
|
-
MatTooltipModule,
|
|
112
|
-
],
|
|
113
|
-
template: `
|
|
114
|
-
<div
|
|
115
|
-
cdkDrag
|
|
116
|
-
class="deb-field-row"
|
|
117
|
-
data-testid="builder-field-row"
|
|
118
|
-
[class.deb-field-row--active]="store.selectedFieldId() === field.id"
|
|
119
|
-
(click)="store.selectField(field.id)"
|
|
120
|
-
(keydown.enter)="store.selectField(field.id)"
|
|
121
|
-
(keydown.space)="store.selectField(field.id); $event.preventDefault()"
|
|
122
|
-
role="button"
|
|
123
|
-
tabindex="0"
|
|
124
|
-
[attr.aria-pressed]="store.selectedFieldId() === field.id"
|
|
125
|
-
[attr.aria-label]="'Select field ' + fieldLabel(field)"
|
|
126
|
-
>
|
|
127
|
-
<mat-icon class="deb-drag-handle" cdkDragHandle aria-hidden="true" title="Drag to reorder (or use the move buttons)">drag_indicator</mat-icon>
|
|
128
|
-
<mat-icon class="deb-field-type" [matTooltip]="fieldTypeLabel(field.type)">{{ fieldTypeIcon(field.type) }}</mat-icon>
|
|
129
|
-
<div class="deb-field-meta">
|
|
130
|
-
<div class="deb-row" style="gap:6px">
|
|
131
|
-
<span class="deb-field-label" [attr.data-testid]="'row-label-' + field.id">{{ fieldLabel(field) }}</span>
|
|
132
|
-
<span class="deb-type-badge">{{ field.type }}</span>
|
|
133
|
-
@if (field.isReferenced) {
|
|
134
|
-
<mat-icon style="font-size: 16px; width: 16px; height: 16px; color: #1976d2;" matTooltip="Referenced field (linked to {{ field.referencedEntityKey }})">link</mat-icon>
|
|
135
|
-
}
|
|
136
|
-
@if (field.hasDrift) {
|
|
137
|
-
<mat-icon style="font-size: 16px; width: 16px; height: 16px; color: #d32f2f;" data-testid="drift-warning-icon" matTooltip="Drift detected: source field has evolved">sync_problem</mat-icon>
|
|
138
|
-
}
|
|
139
|
-
</div>
|
|
140
|
-
<span class="deb-field-id" [attr.data-testid]="'row-id-' + field.id">{{ field.id }}</span>
|
|
141
|
-
</div>
|
|
142
|
-
@if (field.validators?.required) { <span class="deb-req" title="Required">*</span> }
|
|
143
|
-
|
|
144
|
-
<button mat-icon-button type="button" [disabled]="index === 0"
|
|
145
|
-
[attr.data-testid]="'row-up-' + field.id"
|
|
146
|
-
[attr.aria-label]="'Move ' + fieldLabel(field) + ' up'"
|
|
147
|
-
(click)="store.moveField(field.id, -1); $event.stopPropagation()" matTooltip="Move up">
|
|
148
|
-
<mat-icon>arrow_upward</mat-icon>
|
|
149
|
-
</button>
|
|
150
|
-
<button mat-icon-button type="button" [disabled]="index === totalCount - 1"
|
|
151
|
-
[attr.data-testid]="'row-down-' + field.id"
|
|
152
|
-
[attr.aria-label]="'Move ' + fieldLabel(field) + ' down'"
|
|
153
|
-
(click)="store.moveField(field.id, 1); $event.stopPropagation()" matTooltip="Move down">
|
|
154
|
-
<mat-icon>arrow_downward</mat-icon>
|
|
155
|
-
</button>
|
|
156
|
-
<button mat-icon-button type="button"
|
|
157
|
-
[attr.data-testid]="'row-duplicate-' + field.id"
|
|
158
|
-
[attr.aria-label]="'Duplicate ' + fieldLabel(field)"
|
|
159
|
-
(click)="store.duplicateField(field.id); $event.stopPropagation()" matTooltip="Duplicate">
|
|
160
|
-
<mat-icon>content_copy</mat-icon>
|
|
161
|
-
</button>
|
|
162
|
-
<button mat-icon-button type="button" color="warn"
|
|
163
|
-
[attr.data-testid]="'row-delete-' + field.id"
|
|
164
|
-
(click)="store.removeField(field.id); $event.stopPropagation()" matTooltip="Delete">
|
|
165
|
-
<mat-icon>delete</mat-icon>
|
|
166
|
-
</button>
|
|
167
|
-
</div>
|
|
168
|
-
|
|
169
|
-
@if (field.children && field.children.length > 0) {
|
|
170
|
-
<div class="deb-tree-children" style="padding-left: 20px; border-left: 2px solid rgba(0,0,0,0.08); margin-left: 12px; margin-top: 4px;">
|
|
171
|
-
@for (child of field.children; track child.id; let ci = $index, cCount = $count) {
|
|
172
|
-
<ngx-entity-builder-tree-node
|
|
173
|
-
[field]="child"
|
|
174
|
-
[index]="ci"
|
|
175
|
-
[totalCount]="cCount"
|
|
176
|
-
/>
|
|
177
|
-
}
|
|
178
|
-
</div>
|
|
179
|
-
}
|
|
180
|
-
`,
|
|
181
|
-
}]
|
|
182
|
-
}], propDecorators: { field: [{
|
|
183
|
-
type: Input,
|
|
184
|
-
args: [{ required: true }]
|
|
185
|
-
}], index: [{
|
|
186
|
-
type: Input,
|
|
187
|
-
args: [{ required: true }]
|
|
188
|
-
}], totalCount: [{
|
|
189
|
-
type: Input,
|
|
190
|
-
args: [{ required: true }]
|
|
191
|
-
}] } });
|
|
192
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW50aXR5LWJ1aWxkZXItdHJlZS1ub2RlLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvY29tcG9uZW50cy9lbnRpdHktYnVpbGRlci10cmVlLW5vZGUuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNsRixPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDL0MsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ3hELE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUMzRCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDdkQsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDN0QsT0FBTyxFQUFFLFlBQVksRUFBMEIsTUFBTSxzQkFBc0IsQ0FBQztBQUM1RSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDeEQsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sa0JBQWtCLENBQUM7Ozs7OztBQWtGcEQsTUFBTSxPQUFPLDhCQUE4QjtJQUN0QixLQUFLLEdBQUcsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDO0lBRXJCLEtBQUssQ0FBcUI7SUFDMUIsS0FBSyxDQUFVO0lBQ2YsVUFBVSxDQUFVO0lBRXJDLGNBQWMsQ0FBQyxJQUFZO1FBQ25DLE9BQU8sZ0JBQWdCLENBQUMsSUFBSSxDQUFDLEVBQUUsS0FBSyxJQUFJLElBQUksQ0FBQztJQUMvQyxDQUFDO0lBRVMsYUFBYSxDQUFDLElBQVk7UUFDbEMsT0FBTyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsRUFBRSxJQUFJLElBQUksY0FBYyxDQUFDO0lBQ3hELENBQUM7SUFFUyxVQUFVLENBQUMsS0FBa0M7UUFDckQsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxjQUFjLEVBQUUsQ0FBQztRQUN6QyxPQUFPLFlBQVksQ0FBQyxLQUFLLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxJQUFJLEtBQUssQ0FBQyxFQUFFLENBQUM7SUFDckQsQ0FBQzt3R0FsQlUsOEJBQThCOzRGQUE5Qiw4QkFBOEIsOEpBckUvQjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQW1FVCw0REFFVSw4QkFBOEIsa0hBM0V2QyxZQUFZLDhCQUNaLGNBQWMsK2tCQUNkLGVBQWUsMklBQ2YsYUFBYSxtTEFDYixnQkFBZ0I7OzRGQXVFUCw4QkFBOEI7a0JBaEYxQyxTQUFTO21CQUFDO29CQUNULGVBQWUsRUFBRSx1QkFBdUIsQ0FBQyxNQUFNO29CQUMvQyxRQUFRLEVBQUUsOEJBQThCO29CQUN4QyxVQUFVLEVBQUUsSUFBSTtvQkFDaEIsT0FBTyxFQUFFO3dCQUNQLFlBQVk7d0JBQ1osY0FBYzt3QkFDZCxlQUFlO3dCQUNmLGFBQWE7d0JBQ2IsZ0JBQWdCO3FCQUNqQjtvQkFDRCxRQUFRLEVBQUU7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FtRVQ7aUJBQ0Y7OEJBSTRCLEtBQUs7c0JBQS9CLEtBQUs7dUJBQUMsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFO2dCQUNFLEtBQUs7c0JBQS9CLEtBQUs7dUJBQUMsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFO2dCQUNFLFVBQVU7c0JBQXBDLEtBQUs7dUJBQUMsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksIENvbXBvbmVudCwgSW5wdXQsIGluamVjdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7IERyYWdEcm9wTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY2RrL2RyYWctZHJvcCc7XG5pbXBvcnQgeyBNYXRCdXR0b25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9idXR0b24nO1xuaW1wb3J0IHsgTWF0SWNvbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2ljb24nO1xuaW1wb3J0IHsgTWF0VG9vbHRpcE1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL3Rvb2x0aXAnO1xuaW1wb3J0IHsgcmVzb2x2ZUxhYmVsLCB0eXBlIE5lc3RlZEZpZWxkQ29uZmlnIH0gZnJvbSAnQGR5bmFtaWMtZW50aXR5L2NvcmUnO1xuaW1wb3J0IHsgQnVpbGRlclN0b3JlIH0gZnJvbSAnLi4vYnVpbGRlci1zdG9yZS5zZXJ2aWNlJztcbmltcG9ydCB7IGdldEZpZWxkVHlwZU1ldGEgfSBmcm9tICcuLi9maWVsZC1jYXRhbG9nJztcblxuQENvbXBvbmVudCh7XG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICBzZWxlY3RvcjogJ25neC1lbnRpdHktYnVpbGRlci10cmVlLW5vZGUnLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbXG4gICAgQ29tbW9uTW9kdWxlLFxuICAgIERyYWdEcm9wTW9kdWxlLFxuICAgIE1hdEJ1dHRvbk1vZHVsZSxcbiAgICBNYXRJY29uTW9kdWxlLFxuICAgIE1hdFRvb2x0aXBNb2R1bGUsXG4gIF0sXG4gIHRlbXBsYXRlOiBgXG4gICAgPGRpdlxuICAgICAgY2RrRHJhZ1xuICAgICAgY2xhc3M9XCJkZWItZmllbGQtcm93XCJcbiAgICAgIGRhdGEtdGVzdGlkPVwiYnVpbGRlci1maWVsZC1yb3dcIlxuICAgICAgW2NsYXNzLmRlYi1maWVsZC1yb3ctLWFjdGl2ZV09XCJzdG9yZS5zZWxlY3RlZEZpZWxkSWQoKSA9PT0gZmllbGQuaWRcIlxuICAgICAgKGNsaWNrKT1cInN0b3JlLnNlbGVjdEZpZWxkKGZpZWxkLmlkKVwiXG4gICAgICAoa2V5ZG93bi5lbnRlcik9XCJzdG9yZS5zZWxlY3RGaWVsZChmaWVsZC5pZClcIlxuICAgICAgKGtleWRvd24uc3BhY2UpPVwic3RvcmUuc2VsZWN0RmllbGQoZmllbGQuaWQpOyAkZXZlbnQucHJldmVudERlZmF1bHQoKVwiXG4gICAgICByb2xlPVwiYnV0dG9uXCJcbiAgICAgIHRhYmluZGV4PVwiMFwiXG4gICAgICBbYXR0ci5hcmlhLXByZXNzZWRdPVwic3RvcmUuc2VsZWN0ZWRGaWVsZElkKCkgPT09IGZpZWxkLmlkXCJcbiAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwiJ1NlbGVjdCBmaWVsZCAnICsgZmllbGRMYWJlbChmaWVsZClcIlxuICAgID5cbiAgICAgIDxtYXQtaWNvbiBjbGFzcz1cImRlYi1kcmFnLWhhbmRsZVwiIGNka0RyYWdIYW5kbGUgYXJpYS1oaWRkZW49XCJ0cnVlXCIgdGl0bGU9XCJEcmFnIHRvIHJlb3JkZXIgKG9yIHVzZSB0aGUgbW92ZSBidXR0b25zKVwiPmRyYWdfaW5kaWNhdG9yPC9tYXQtaWNvbj5cbiAgICAgIDxtYXQtaWNvbiBjbGFzcz1cImRlYi1maWVsZC10eXBlXCIgW21hdFRvb2x0aXBdPVwiZmllbGRUeXBlTGFiZWwoZmllbGQudHlwZSlcIj57eyBmaWVsZFR5cGVJY29uKGZpZWxkLnR5cGUpIH19PC9tYXQtaWNvbj5cbiAgICAgIDxkaXYgY2xhc3M9XCJkZWItZmllbGQtbWV0YVwiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiZGViLXJvd1wiIHN0eWxlPVwiZ2FwOjZweFwiPlxuICAgICAgICAgIDxzcGFuIGNsYXNzPVwiZGViLWZpZWxkLWxhYmVsXCIgW2F0dHIuZGF0YS10ZXN0aWRdPVwiJ3Jvdy1sYWJlbC0nICsgZmllbGQuaWRcIj57eyBmaWVsZExhYmVsKGZpZWxkKSB9fTwvc3Bhbj5cbiAgICAgICAgICA8c3BhbiBjbGFzcz1cImRlYi10eXBlLWJhZGdlXCI+e3sgZmllbGQudHlwZSB9fTwvc3Bhbj5cbiAgICAgICAgICBAaWYgKGZpZWxkLmlzUmVmZXJlbmNlZCkge1xuICAgICAgICAgICAgPG1hdC1pY29uIHN0eWxlPVwiZm9udC1zaXplOiAxNnB4OyB3aWR0aDogMTZweDsgaGVpZ2h0OiAxNnB4OyBjb2xvcjogIzE5NzZkMjtcIiBtYXRUb29sdGlwPVwiUmVmZXJlbmNlZCBmaWVsZCAobGlua2VkIHRvIHt7IGZpZWxkLnJlZmVyZW5jZWRFbnRpdHlLZXkgfX0pXCI+bGluazwvbWF0LWljb24+XG4gICAgICAgICAgfVxuICAgICAgICAgIEBpZiAoZmllbGQuaGFzRHJpZnQpIHtcbiAgICAgICAgICAgIDxtYXQtaWNvbiBzdHlsZT1cImZvbnQtc2l6ZTogMTZweDsgd2lkdGg6IDE2cHg7IGhlaWdodDogMTZweDsgY29sb3I6ICNkMzJmMmY7XCIgZGF0YS10ZXN0aWQ9XCJkcmlmdC13YXJuaW5nLWljb25cIiBtYXRUb29sdGlwPVwiRHJpZnQgZGV0ZWN0ZWQ6IHNvdXJjZSBmaWVsZCBoYXMgZXZvbHZlZFwiPnN5bmNfcHJvYmxlbTwvbWF0LWljb24+XG4gICAgICAgICAgfVxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPHNwYW4gY2xhc3M9XCJkZWItZmllbGQtaWRcIiBbYXR0ci5kYXRhLXRlc3RpZF09XCIncm93LWlkLScgKyBmaWVsZC5pZFwiPnt7IGZpZWxkLmlkIH19PC9zcGFuPlxuICAgICAgPC9kaXY+XG4gICAgICBAaWYgKGZpZWxkLnZhbGlkYXRvcnM/LnJlcXVpcmVkKSB7IDxzcGFuIGNsYXNzPVwiZGViLXJlcVwiIHRpdGxlPVwiUmVxdWlyZWRcIj4qPC9zcGFuPiB9XG5cbiAgICAgIDxidXR0b24gbWF0LWljb24tYnV0dG9uIHR5cGU9XCJidXR0b25cIiBbZGlzYWJsZWRdPVwiaW5kZXggPT09IDBcIlxuICAgICAgICBbYXR0ci5kYXRhLXRlc3RpZF09XCIncm93LXVwLScgKyBmaWVsZC5pZFwiXG4gICAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwiJ01vdmUgJyArIGZpZWxkTGFiZWwoZmllbGQpICsgJyB1cCdcIlxuICAgICAgICAoY2xpY2spPVwic3RvcmUubW92ZUZpZWxkKGZpZWxkLmlkLCAtMSk7ICRldmVudC5zdG9wUHJvcGFnYXRpb24oKVwiIG1hdFRvb2x0aXA9XCJNb3ZlIHVwXCI+XG4gICAgICAgIDxtYXQtaWNvbj5hcnJvd191cHdhcmQ8L21hdC1pY29uPlxuICAgICAgPC9idXR0b24+XG4gICAgICA8YnV0dG9uIG1hdC1pY29uLWJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgW2Rpc2FibGVkXT1cImluZGV4ID09PSB0b3RhbENvdW50IC0gMVwiXG4gICAgICAgIFthdHRyLmRhdGEtdGVzdGlkXT1cIidyb3ctZG93bi0nICsgZmllbGQuaWRcIlxuICAgICAgICBbYXR0ci5hcmlhLWxhYmVsXT1cIidNb3ZlICcgKyBmaWVsZExhYmVsKGZpZWxkKSArICcgZG93bidcIlxuICAgICAgICAoY2xpY2spPVwic3RvcmUubW92ZUZpZWxkKGZpZWxkLmlkLCAxKTsgJGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpXCIgbWF0VG9vbHRpcD1cIk1vdmUgZG93blwiPlxuICAgICAgICA8bWF0LWljb24+YXJyb3dfZG93bndhcmQ8L21hdC1pY29uPlxuICAgICAgPC9idXR0b24+XG4gICAgICA8YnV0dG9uIG1hdC1pY29uLWJ1dHRvbiB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgW2F0dHIuZGF0YS10ZXN0aWRdPVwiJ3Jvdy1kdXBsaWNhdGUtJyArIGZpZWxkLmlkXCJcbiAgICAgICAgW2F0dHIuYXJpYS1sYWJlbF09XCInRHVwbGljYXRlICcgKyBmaWVsZExhYmVsKGZpZWxkKVwiXG4gICAgICAgIChjbGljayk9XCJzdG9yZS5kdXBsaWNhdGVGaWVsZChmaWVsZC5pZCk7ICRldmVudC5zdG9wUHJvcGFnYXRpb24oKVwiIG1hdFRvb2x0aXA9XCJEdXBsaWNhdGVcIj5cbiAgICAgICAgPG1hdC1pY29uPmNvbnRlbnRfY29weTwvbWF0LWljb24+XG4gICAgICA8L2J1dHRvbj5cbiAgICAgIDxidXR0b24gbWF0LWljb24tYnV0dG9uIHR5cGU9XCJidXR0b25cIiBjb2xvcj1cIndhcm5cIlxuICAgICAgICBbYXR0ci5kYXRhLXRlc3RpZF09XCIncm93LWRlbGV0ZS0nICsgZmllbGQuaWRcIlxuICAgICAgICAoY2xpY2spPVwic3RvcmUucmVtb3ZlRmllbGQoZmllbGQuaWQpOyAkZXZlbnQuc3RvcFByb3BhZ2F0aW9uKClcIiBtYXRUb29sdGlwPVwiRGVsZXRlXCI+XG4gICAgICAgIDxtYXQtaWNvbj5kZWxldGU8L21hdC1pY29uPlxuICAgICAgPC9idXR0b24+XG4gICAgPC9kaXY+XG5cbiAgICBAaWYgKGZpZWxkLmNoaWxkcmVuICYmIGZpZWxkLmNoaWxkcmVuLmxlbmd0aCA+IDApIHtcbiAgICAgIDxkaXYgY2xhc3M9XCJkZWItdHJlZS1jaGlsZHJlblwiIHN0eWxlPVwicGFkZGluZy1sZWZ0OiAyMHB4OyBib3JkZXItbGVmdDogMnB4IHNvbGlkIHJnYmEoMCwwLDAsMC4wOCk7IG1hcmdpbi1sZWZ0OiAxMnB4OyBtYXJnaW4tdG9wOiA0cHg7XCI+XG4gICAgICAgIEBmb3IgKGNoaWxkIG9mIGZpZWxkLmNoaWxkcmVuOyB0cmFjayBjaGlsZC5pZDsgbGV0IGNpID0gJGluZGV4LCBjQ291bnQgPSAkY291bnQpIHtcbiAgICAgICAgICA8bmd4LWVudGl0eS1idWlsZGVyLXRyZWUtbm9kZVxuICAgICAgICAgICAgW2ZpZWxkXT1cImNoaWxkXCJcbiAgICAgICAgICAgIFtpbmRleF09XCJjaVwiXG4gICAgICAgICAgICBbdG90YWxDb3VudF09XCJjQ291bnRcIlxuICAgICAgICAgIC8+XG4gICAgICAgIH1cbiAgICAgIDwvZGl2PlxuICAgIH1cbiAgYCxcbn0pXG5leHBvcnQgY2xhc3MgRW50aXR5QnVpbGRlclRyZWVOb2RlQ29tcG9uZW50IHtcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IHN0b3JlID0gaW5qZWN0KEJ1aWxkZXJTdG9yZSk7XG5cbiAgQElucHV0KHsgcmVxdWlyZWQ6IHRydWUgfSkgZmllbGQhOiBOZXN0ZWRGaWVsZENvbmZpZztcbiAgQElucHV0KHsgcmVxdWlyZWQ6IHRydWUgfSkgaW5kZXghOiBudW1iZXI7XG4gIEBJbnB1dCh7IHJlcXVpcmVkOiB0cnVlIH0pIHRvdGFsQ291bnQhOiBudW1iZXI7XG5cbiAgcHJvdGVjdGVkIGZpZWxkVHlwZUxhYmVsKHR5cGU6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGdldEZpZWxkVHlwZU1ldGEodHlwZSk/LmxhYmVsID8/IHR5cGU7XG4gIH1cblxuICBwcm90ZWN0ZWQgZmllbGRUeXBlSWNvbih0eXBlOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiBnZXRGaWVsZFR5cGVNZXRhKHR5cGUpPy5pY29uID8/ICdoZWxwX291dGxpbmUnO1xuICB9XG5cbiAgcHJvdGVjdGVkIGZpZWxkTGFiZWwoZmllbGQ6IHsgaWQ6IHN0cmluZzsgbGFiZWw/OiBhbnkgfSk6IHN0cmluZyB7XG4gICAgY29uc3QgbGFuZyA9IHRoaXMuc3RvcmUuYWN0aXZlTGFuZ3VhZ2UoKTtcbiAgICByZXR1cm4gcmVzb2x2ZUxhYmVsKGZpZWxkLmxhYmVsLCBsYW5nKSB8fCBmaWVsZC5pZDtcbiAgfVxufVxuIl19
|