@sarasanalytics-com/design-system 0.0.136 → 0.0.138

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 (44) hide show
  1. package/esm2022/interfaces/button-interface.mjs +1 -1
  2. package/esm2022/interfaces/chip-interface.mjs +1 -1
  3. package/esm2022/interfaces/form-layout.interface.mjs +2 -0
  4. package/esm2022/interfaces/grid-interface.mjs +1 -1
  5. package/esm2022/lib/avatar/avatar.component.mjs +3 -3
  6. package/esm2022/lib/categories-nav/categories-nav.component.mjs +27 -0
  7. package/esm2022/lib/chips/chips.component.mjs +3 -3
  8. package/esm2022/lib/data-grid/data-grid.component.mjs +135 -0
  9. package/esm2022/lib/dialog/dialog.component.mjs +43 -3
  10. package/esm2022/lib/filter/filter.component.mjs +232 -0
  11. package/esm2022/lib/form-input/form-input.component.mjs +71 -7
  12. package/esm2022/lib/form-select/form-select.component.mjs +187 -5
  13. package/esm2022/lib/grid-cell/grid-cell.component.mjs +173 -25
  14. package/esm2022/lib/menu/menu-list/menu-item.component.mjs +3 -3
  15. package/esm2022/lib/menu/menu.component.mjs +3 -3
  16. package/esm2022/lib/message-banner-v2/message-banner-v2.component.mjs +256 -7
  17. package/esm2022/lib/query-builder/query-builder-demo.component.mjs +134 -0
  18. package/esm2022/lib/query-builder/query-builder.component.mjs +275 -0
  19. package/esm2022/lib/query-builder/query-builder.service.mjs +107 -0
  20. package/esm2022/lib/query-builder-textarea/query-builder-textarea-demo.component.mjs +130 -0
  21. package/esm2022/lib/query-builder-textarea/query-builder-textarea.component.mjs +805 -0
  22. package/esm2022/lib/tool-tip/tool-tip.component.mjs +8 -3
  23. package/esm2022/public-api.mjs +10 -1
  24. package/fesm2022/sarasanalytics-com-design-system.mjs +3042 -587
  25. package/fesm2022/sarasanalytics-com-design-system.mjs.map +1 -1
  26. package/interfaces/button-interface.d.ts +1 -0
  27. package/interfaces/form-layout.interface.d.ts +59 -0
  28. package/interfaces/grid-interface.d.ts +11 -4
  29. package/lib/categories-nav/categories-nav.component.d.ts +15 -0
  30. package/lib/data-grid/data-grid.component.d.ts +33 -0
  31. package/lib/dialog/dialog.component.d.ts +13 -0
  32. package/lib/filter/filter.component.d.ts +83 -0
  33. package/lib/form-input/form-input.component.d.ts +11 -1
  34. package/lib/form-select/form-select.component.d.ts +8 -0
  35. package/lib/grid-cell/grid-cell.component.d.ts +51 -10
  36. package/lib/message-banner-v2/message-banner-v2.component.d.ts +34 -2
  37. package/lib/query-builder/query-builder-demo.component.d.ts +14 -0
  38. package/lib/query-builder/query-builder.component.d.ts +90 -0
  39. package/lib/query-builder/query-builder.service.d.ts +39 -0
  40. package/lib/query-builder-textarea/query-builder-textarea-demo.component.d.ts +9 -0
  41. package/lib/query-builder-textarea/query-builder-textarea.component.d.ts +143 -0
  42. package/lib/tool-tip/tool-tip.component.d.ts +2 -1
  43. package/package.json +1 -1
  44. package/public-api.d.ts +9 -0
@@ -0,0 +1,134 @@
1
+ import { Component } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { QueryBuilderComponent } from './query-builder.component';
4
+ import { MatCardModule } from '@angular/material/card';
5
+ import * as i0 from "@angular/core";
6
+ import * as i1 from "./query-builder.service";
7
+ import * as i2 from "@angular/common";
8
+ import * as i3 from "@angular/material/card";
9
+ export class QueryBuilderDemoComponent {
10
+ constructor(queryBuilderService) {
11
+ this.queryBuilderService = queryBuilderService;
12
+ this.queryConfig = {
13
+ fields: [
14
+ {
15
+ key: 'name',
16
+ label: 'Name',
17
+ type: 'string'
18
+ },
19
+ {
20
+ key: 'age',
21
+ label: 'Age',
22
+ type: 'number',
23
+ operators: ['=', '!=', '>', '<', '>=', '<=', 'between']
24
+ },
25
+ {
26
+ key: 'email',
27
+ label: 'Email',
28
+ type: 'string',
29
+ operators: ['=', '!=', 'contains']
30
+ },
31
+ {
32
+ key: 'birthdate',
33
+ label: 'Birth Date',
34
+ type: 'date'
35
+ },
36
+ {
37
+ key: 'status',
38
+ label: 'Status',
39
+ type: 'select',
40
+ options: [
41
+ { label: 'Active', value: 'active' },
42
+ { label: 'Inactive', value: 'inactive' },
43
+ { label: 'Pending', value: 'pending' }
44
+ ]
45
+ },
46
+ {
47
+ key: 'isVerified',
48
+ label: 'Is Verified',
49
+ type: 'boolean'
50
+ },
51
+ {
52
+ key: 'lifecycle',
53
+ label: 'Lifecycle',
54
+ type: 'select',
55
+ options: [
56
+ { label: 'Active', value: 'active' },
57
+ { label: 'At Risk', value: 'at_risk' },
58
+ { label: 'Churned', value: 'churned' }
59
+ ]
60
+ }
61
+ ],
62
+ operators: [
63
+ { value: '=', label: '=' },
64
+ { value: '!=', label: '!=' },
65
+ { value: '>', label: '>' },
66
+ { value: '<', label: '<' },
67
+ { value: '>=', label: '>=' },
68
+ { value: '<=', label: '<=' },
69
+ { value: 'contains', label: 'contains' },
70
+ { value: 'between', label: 'between' }
71
+ ],
72
+ defaultCondition: 'and'
73
+ };
74
+ this.queryString = '';
75
+ this.queryJson = '';
76
+ this.currentQuery = null;
77
+ }
78
+ onQueryChange(query) {
79
+ this.currentQuery = query;
80
+ this.queryString = this.queryBuilderService.queryToString(query);
81
+ this.queryJson = JSON.stringify(this.queryBuilderService.queryToJson(query), null, 2);
82
+ }
83
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: QueryBuilderDemoComponent, deps: [{ token: i1.QueryBuilderService }], target: i0.ɵɵFactoryTarget.Component }); }
84
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.2.4", type: QueryBuilderDemoComponent, isStandalone: true, selector: "sa-query-builder-demo", ngImport: i0, template: `
85
+ <mat-card>
86
+ <mat-card-header>
87
+ <mat-card-title>Query Builder Demo</mat-card-title>
88
+ </mat-card-header>
89
+ <mat-card-content>
90
+ <sa-query-builder [config]="queryConfig" (queryChange)="onQueryChange($event)"></sa-query-builder>
91
+
92
+ <div class="query-result" *ngIf="queryString">
93
+ <h3>Query Result:</h3>
94
+ <pre>{{ queryString }}</pre>
95
+ <h3>JSON:</h3>
96
+ <pre>{{ queryJson }}</pre>
97
+ <h3>Per-Row Conditions:</h3>
98
+ <ul>
99
+ <li *ngFor="let rule of currentQuery?.rules; let i = index">
100
+ Row {{ i + 1 }}: {{ i === 0 ? 'First row' : rule.condition?.toUpperCase() }}
101
+ </li>
102
+ </ul>
103
+ </div>
104
+ </mat-card-content>
105
+ </mat-card>
106
+ `, isInline: true, styles: [".query-result{margin-top:20px;padding:16px;background-color:#f5f5f5;border-radius:4px}pre{white-space:pre-wrap;word-break:break-all;background-color:#e0e0e0;padding:8px;border-radius:4px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: QueryBuilderComponent, selector: "sa-query-builder", inputs: ["config"], outputs: ["queryChange"] }, { kind: "ngmodule", type: MatCardModule }, { kind: "component", type: i3.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i3.MatCardContent, selector: "mat-card-content" }, { kind: "component", type: i3.MatCardHeader, selector: "mat-card-header" }, { kind: "directive", type: i3.MatCardTitle, selector: "mat-card-title, [mat-card-title], [matCardTitle]" }] }); }
107
+ }
108
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: QueryBuilderDemoComponent, decorators: [{
109
+ type: Component,
110
+ args: [{ selector: 'sa-query-builder-demo', standalone: true, imports: [CommonModule, QueryBuilderComponent, MatCardModule], template: `
111
+ <mat-card>
112
+ <mat-card-header>
113
+ <mat-card-title>Query Builder Demo</mat-card-title>
114
+ </mat-card-header>
115
+ <mat-card-content>
116
+ <sa-query-builder [config]="queryConfig" (queryChange)="onQueryChange($event)"></sa-query-builder>
117
+
118
+ <div class="query-result" *ngIf="queryString">
119
+ <h3>Query Result:</h3>
120
+ <pre>{{ queryString }}</pre>
121
+ <h3>JSON:</h3>
122
+ <pre>{{ queryJson }}</pre>
123
+ <h3>Per-Row Conditions:</h3>
124
+ <ul>
125
+ <li *ngFor="let rule of currentQuery?.rules; let i = index">
126
+ Row {{ i + 1 }}: {{ i === 0 ? 'First row' : rule.condition?.toUpperCase() }}
127
+ </li>
128
+ </ul>
129
+ </div>
130
+ </mat-card-content>
131
+ </mat-card>
132
+ `, styles: [".query-result{margin-top:20px;padding:16px;background-color:#f5f5f5;border-radius:4px}pre{white-space:pre-wrap;word-break:break-all;background-color:#e0e0e0;padding:8px;border-radius:4px}\n"] }]
133
+ }], ctorParameters: () => [{ type: i1.QueryBuilderService }] });
134
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicXVlcnktYnVpbGRlci1kZW1vLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2NvbXBvbmVudC1saWJyYXJ5L3NyYy9saWIvcXVlcnktYnVpbGRlci9xdWVyeS1idWlsZGVyLWRlbW8uY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDMUMsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQy9DLE9BQU8sRUFBRSxxQkFBcUIsRUFBMkIsTUFBTSwyQkFBMkIsQ0FBQztBQUUzRixPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7Ozs7O0FBOEN2RCxNQUFNLE9BQU8seUJBQXlCO0lBb0VwQyxZQUFvQixtQkFBd0M7UUFBeEMsd0JBQW1CLEdBQW5CLG1CQUFtQixDQUFxQjtRQW5FNUQsZ0JBQVcsR0FBZ0I7WUFDekIsTUFBTSxFQUFFO2dCQUNOO29CQUNFLEdBQUcsRUFBRSxNQUFNO29CQUNYLEtBQUssRUFBRSxNQUFNO29CQUNiLElBQUksRUFBRSxRQUFRO2lCQUNmO2dCQUNEO29CQUNFLEdBQUcsRUFBRSxLQUFLO29CQUNWLEtBQUssRUFBRSxLQUFLO29CQUNaLElBQUksRUFBRSxRQUFRO29CQUNkLFNBQVMsRUFBRSxDQUFDLEdBQUcsRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLFNBQVMsQ0FBQztpQkFDeEQ7Z0JBQ0Q7b0JBQ0UsR0FBRyxFQUFFLE9BQU87b0JBQ1osS0FBSyxFQUFFLE9BQU87b0JBQ2QsSUFBSSxFQUFFLFFBQVE7b0JBQ2QsU0FBUyxFQUFFLENBQUMsR0FBRyxFQUFFLElBQUksRUFBRSxVQUFVLENBQUM7aUJBQ25DO2dCQUNEO29CQUNFLEdBQUcsRUFBRSxXQUFXO29CQUNoQixLQUFLLEVBQUUsWUFBWTtvQkFDbkIsSUFBSSxFQUFFLE1BQU07aUJBQ2I7Z0JBQ0Q7b0JBQ0UsR0FBRyxFQUFFLFFBQVE7b0JBQ2IsS0FBSyxFQUFFLFFBQVE7b0JBQ2YsSUFBSSxFQUFFLFFBQVE7b0JBQ2QsT0FBTyxFQUFFO3dCQUNQLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFO3dCQUNwQyxFQUFFLEtBQUssRUFBRSxVQUFVLEVBQUUsS0FBSyxFQUFFLFVBQVUsRUFBRTt3QkFDeEMsRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUU7cUJBQ3ZDO2lCQUNGO2dCQUNEO29CQUNFLEdBQUcsRUFBRSxZQUFZO29CQUNqQixLQUFLLEVBQUUsYUFBYTtvQkFDcEIsSUFBSSxFQUFFLFNBQVM7aUJBQ2hCO2dCQUNEO29CQUNFLEdBQUcsRUFBRSxXQUFXO29CQUNoQixLQUFLLEVBQUUsV0FBVztvQkFDbEIsSUFBSSxFQUFFLFFBQVE7b0JBQ2QsT0FBTyxFQUFFO3dCQUNQLEVBQUUsS0FBSyxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFO3dCQUNwQyxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRTt3QkFDdEMsRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUU7cUJBQ3ZDO2lCQUNGO2FBQ0Y7WUFDRCxTQUFTLEVBQUU7Z0JBQ1QsRUFBRSxLQUFLLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBRSxHQUFHLEVBQUU7Z0JBQzFCLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFO2dCQUM1QixFQUFFLEtBQUssRUFBRSxHQUFHLEVBQUUsS0FBSyxFQUFFLEdBQUcsRUFBRTtnQkFDMUIsRUFBRSxLQUFLLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBRSxHQUFHLEVBQUU7Z0JBQzFCLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFO2dCQUM1QixFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRTtnQkFDNUIsRUFBRSxLQUFLLEVBQUUsVUFBVSxFQUFFLEtBQUssRUFBRSxVQUFVLEVBQUU7Z0JBQ3hDLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFO2FBQ3ZDO1lBQ0QsZ0JBQWdCLEVBQUUsS0FBSztTQUN4QixDQUFDO1FBRUYsZ0JBQVcsR0FBVyxFQUFFLENBQUM7UUFDekIsY0FBUyxHQUFXLEVBQUUsQ0FBQztRQUN2QixpQkFBWSxHQUFzQixJQUFJLENBQUM7SUFFd0IsQ0FBQztJQUVoRSxhQUFhLENBQUMsS0FBaUI7UUFDN0IsSUFBSSxDQUFDLFlBQVksR0FBRyxLQUFLLENBQUM7UUFDMUIsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUMsbUJBQW1CLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ2pFLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsbUJBQW1CLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQztJQUN4RixDQUFDOzhHQTFFVSx5QkFBeUI7a0dBQXpCLHlCQUF5QixpRkF4QzFCOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBc0JULHNRQXZCUyxZQUFZLGdRQUFFLHFCQUFxQiwwR0FBRSxhQUFhOzsyRkF5Q2pELHlCQUF5QjtrQkE1Q3JDLFNBQVM7K0JBQ0UsdUJBQXVCLGNBQ3JCLElBQUksV0FDUCxDQUFDLFlBQVksRUFBRSxxQkFBcUIsRUFBRSxhQUFhLENBQUMsWUFDbkQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FzQlQiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcclxuaW1wb3J0IHsgUXVlcnlCdWlsZGVyQ29tcG9uZW50LCBRdWVyeUNvbmZpZywgUXVlcnlHcm91cCB9IGZyb20gJy4vcXVlcnktYnVpbGRlci5jb21wb25lbnQnO1xyXG5pbXBvcnQgeyBRdWVyeUJ1aWxkZXJTZXJ2aWNlIH0gZnJvbSAnLi9xdWVyeS1idWlsZGVyLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBNYXRDYXJkTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvY2FyZCc7XHJcblxyXG5AQ29tcG9uZW50KHtcclxuICBzZWxlY3RvcjogJ3NhLXF1ZXJ5LWJ1aWxkZXItZGVtbycsXHJcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcclxuICBpbXBvcnRzOiBbQ29tbW9uTW9kdWxlLCBRdWVyeUJ1aWxkZXJDb21wb25lbnQsIE1hdENhcmRNb2R1bGVdLFxyXG4gIHRlbXBsYXRlOiBgXHJcbiAgICA8bWF0LWNhcmQ+XHJcbiAgICAgIDxtYXQtY2FyZC1oZWFkZXI+XHJcbiAgICAgICAgPG1hdC1jYXJkLXRpdGxlPlF1ZXJ5IEJ1aWxkZXIgRGVtbzwvbWF0LWNhcmQtdGl0bGU+XHJcbiAgICAgIDwvbWF0LWNhcmQtaGVhZGVyPlxyXG4gICAgICA8bWF0LWNhcmQtY29udGVudD5cclxuICAgICAgICA8c2EtcXVlcnktYnVpbGRlciBbY29uZmlnXT1cInF1ZXJ5Q29uZmlnXCIgKHF1ZXJ5Q2hhbmdlKT1cIm9uUXVlcnlDaGFuZ2UoJGV2ZW50KVwiPjwvc2EtcXVlcnktYnVpbGRlcj5cclxuICAgICAgICBcclxuICAgICAgICA8ZGl2IGNsYXNzPVwicXVlcnktcmVzdWx0XCIgKm5nSWY9XCJxdWVyeVN0cmluZ1wiPlxyXG4gICAgICAgICAgPGgzPlF1ZXJ5IFJlc3VsdDo8L2gzPlxyXG4gICAgICAgICAgPHByZT57eyBxdWVyeVN0cmluZyB9fTwvcHJlPlxyXG4gICAgICAgICAgPGgzPkpTT046PC9oMz5cclxuICAgICAgICAgIDxwcmU+e3sgcXVlcnlKc29uIH19PC9wcmU+XHJcbiAgICAgICAgICA8aDM+UGVyLVJvdyBDb25kaXRpb25zOjwvaDM+XHJcbiAgICAgICAgICA8dWw+XHJcbiAgICAgICAgICAgIDxsaSAqbmdGb3I9XCJsZXQgcnVsZSBvZiBjdXJyZW50UXVlcnk/LnJ1bGVzOyBsZXQgaSA9IGluZGV4XCI+XHJcbiAgICAgICAgICAgICAgUm93IHt7IGkgKyAxIH19OiB7eyBpID09PSAwID8gJ0ZpcnN0IHJvdycgOiBydWxlLmNvbmRpdGlvbj8udG9VcHBlckNhc2UoKSB9fVxyXG4gICAgICAgICAgICA8L2xpPlxyXG4gICAgICAgICAgPC91bD5cclxuICAgICAgICA8L2Rpdj5cclxuICAgICAgPC9tYXQtY2FyZC1jb250ZW50PlxyXG4gICAgPC9tYXQtY2FyZD5cclxuICBgLFxyXG4gIHN0eWxlczogW2BcclxuICAgIC5xdWVyeS1yZXN1bHQge1xyXG4gICAgICBtYXJnaW4tdG9wOiAyMHB4O1xyXG4gICAgICBwYWRkaW5nOiAxNnB4O1xyXG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjZjVmNWY1O1xyXG4gICAgICBib3JkZXItcmFkaXVzOiA0cHg7XHJcbiAgICB9XHJcbiAgICBcclxuICAgIHByZSB7XHJcbiAgICAgIHdoaXRlLXNwYWNlOiBwcmUtd3JhcDtcclxuICAgICAgd29yZC1icmVhazogYnJlYWstYWxsO1xyXG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjZTBlMGUwO1xyXG4gICAgICBwYWRkaW5nOiA4cHg7XHJcbiAgICAgIGJvcmRlci1yYWRpdXM6IDRweDtcclxuICAgIH1cclxuICBgXVxyXG59KVxyXG5leHBvcnQgY2xhc3MgUXVlcnlCdWlsZGVyRGVtb0NvbXBvbmVudCB7XHJcbiAgcXVlcnlDb25maWc6IFF1ZXJ5Q29uZmlnID0ge1xyXG4gICAgZmllbGRzOiBbXHJcbiAgICAgIHtcclxuICAgICAgICBrZXk6ICduYW1lJyxcclxuICAgICAgICBsYWJlbDogJ05hbWUnLFxyXG4gICAgICAgIHR5cGU6ICdzdHJpbmcnXHJcbiAgICAgIH0sXHJcbiAgICAgIHtcclxuICAgICAgICBrZXk6ICdhZ2UnLFxyXG4gICAgICAgIGxhYmVsOiAnQWdlJyxcclxuICAgICAgICB0eXBlOiAnbnVtYmVyJyxcclxuICAgICAgICBvcGVyYXRvcnM6IFsnPScsICchPScsICc+JywgJzwnLCAnPj0nLCAnPD0nLCAnYmV0d2VlbiddXHJcbiAgICAgIH0sXHJcbiAgICAgIHtcclxuICAgICAgICBrZXk6ICdlbWFpbCcsXHJcbiAgICAgICAgbGFiZWw6ICdFbWFpbCcsXHJcbiAgICAgICAgdHlwZTogJ3N0cmluZycsXHJcbiAgICAgICAgb3BlcmF0b3JzOiBbJz0nLCAnIT0nLCAnY29udGFpbnMnXVxyXG4gICAgICB9LFxyXG4gICAgICB7XHJcbiAgICAgICAga2V5OiAnYmlydGhkYXRlJyxcclxuICAgICAgICBsYWJlbDogJ0JpcnRoIERhdGUnLFxyXG4gICAgICAgIHR5cGU6ICdkYXRlJ1xyXG4gICAgICB9LFxyXG4gICAgICB7XHJcbiAgICAgICAga2V5OiAnc3RhdHVzJyxcclxuICAgICAgICBsYWJlbDogJ1N0YXR1cycsXHJcbiAgICAgICAgdHlwZTogJ3NlbGVjdCcsXHJcbiAgICAgICAgb3B0aW9uczogW1xyXG4gICAgICAgICAgeyBsYWJlbDogJ0FjdGl2ZScsIHZhbHVlOiAnYWN0aXZlJyB9LFxyXG4gICAgICAgICAgeyBsYWJlbDogJ0luYWN0aXZlJywgdmFsdWU6ICdpbmFjdGl2ZScgfSxcclxuICAgICAgICAgIHsgbGFiZWw6ICdQZW5kaW5nJywgdmFsdWU6ICdwZW5kaW5nJyB9XHJcbiAgICAgICAgXVxyXG4gICAgICB9LFxyXG4gICAgICB7XHJcbiAgICAgICAga2V5OiAnaXNWZXJpZmllZCcsXHJcbiAgICAgICAgbGFiZWw6ICdJcyBWZXJpZmllZCcsXHJcbiAgICAgICAgdHlwZTogJ2Jvb2xlYW4nXHJcbiAgICAgIH0sXHJcbiAgICAgIHtcclxuICAgICAgICBrZXk6ICdsaWZlY3ljbGUnLFxyXG4gICAgICAgIGxhYmVsOiAnTGlmZWN5Y2xlJyxcclxuICAgICAgICB0eXBlOiAnc2VsZWN0JyxcclxuICAgICAgICBvcHRpb25zOiBbXHJcbiAgICAgICAgICB7IGxhYmVsOiAnQWN0aXZlJywgdmFsdWU6ICdhY3RpdmUnIH0sXHJcbiAgICAgICAgICB7IGxhYmVsOiAnQXQgUmlzaycsIHZhbHVlOiAnYXRfcmlzaycgfSxcclxuICAgICAgICAgIHsgbGFiZWw6ICdDaHVybmVkJywgdmFsdWU6ICdjaHVybmVkJyB9XHJcbiAgICAgICAgXVxyXG4gICAgICB9XHJcbiAgICBdLFxyXG4gICAgb3BlcmF0b3JzOiBbXHJcbiAgICAgIHsgdmFsdWU6ICc9JywgbGFiZWw6ICc9JyB9LFxyXG4gICAgICB7IHZhbHVlOiAnIT0nLCBsYWJlbDogJyE9JyB9LFxyXG4gICAgICB7IHZhbHVlOiAnPicsIGxhYmVsOiAnPicgfSxcclxuICAgICAgeyB2YWx1ZTogJzwnLCBsYWJlbDogJzwnIH0sXHJcbiAgICAgIHsgdmFsdWU6ICc+PScsIGxhYmVsOiAnPj0nIH0sXHJcbiAgICAgIHsgdmFsdWU6ICc8PScsIGxhYmVsOiAnPD0nIH0sXHJcbiAgICAgIHsgdmFsdWU6ICdjb250YWlucycsIGxhYmVsOiAnY29udGFpbnMnIH0sXHJcbiAgICAgIHsgdmFsdWU6ICdiZXR3ZWVuJywgbGFiZWw6ICdiZXR3ZWVuJyB9XHJcbiAgICBdLFxyXG4gICAgZGVmYXVsdENvbmRpdGlvbjogJ2FuZCdcclxuICB9O1xyXG5cclxuICBxdWVyeVN0cmluZzogc3RyaW5nID0gJyc7XHJcbiAgcXVlcnlKc29uOiBzdHJpbmcgPSAnJztcclxuICBjdXJyZW50UXVlcnk6IFF1ZXJ5R3JvdXAgfCBudWxsID0gbnVsbDtcclxuXHJcbiAgY29uc3RydWN0b3IocHJpdmF0ZSBxdWVyeUJ1aWxkZXJTZXJ2aWNlOiBRdWVyeUJ1aWxkZXJTZXJ2aWNlKSB7fVxyXG5cclxuICBvblF1ZXJ5Q2hhbmdlKHF1ZXJ5OiBRdWVyeUdyb3VwKTogdm9pZCB7XHJcbiAgICB0aGlzLmN1cnJlbnRRdWVyeSA9IHF1ZXJ5O1xyXG4gICAgdGhpcy5xdWVyeVN0cmluZyA9IHRoaXMucXVlcnlCdWlsZGVyU2VydmljZS5xdWVyeVRvU3RyaW5nKHF1ZXJ5KTtcclxuICAgIHRoaXMucXVlcnlKc29uID0gSlNPTi5zdHJpbmdpZnkodGhpcy5xdWVyeUJ1aWxkZXJTZXJ2aWNlLnF1ZXJ5VG9Kc29uKHF1ZXJ5KSwgbnVsbCwgMik7XHJcbiAgfVxyXG59XHJcbiJdfQ==
@@ -0,0 +1,275 @@
1
+ import { Component, EventEmitter, Input, Output } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { ReactiveFormsModule } from '@angular/forms';
4
+ import { FormlyModule } from '@ngx-formly/core';
5
+ import { MatButtonModule } from '@angular/material/button';
6
+ import { MatIconModule } from '@angular/material/icon';
7
+ import { MatSelectModule } from '@angular/material/select';
8
+ import { MatFormFieldModule } from '@angular/material/form-field';
9
+ import { MatInputModule } from '@angular/material/input';
10
+ import { MatTooltipModule } from '@angular/material/tooltip';
11
+ import { MatButtonToggleModule } from '@angular/material/button-toggle';
12
+ import { MatDatepickerModule } from '@angular/material/datepicker';
13
+ import { provideNativeDateAdapter } from '@angular/material/core';
14
+ import * as i0 from "@angular/core";
15
+ import * as i1 from "@angular/forms";
16
+ import * as i2 from "@angular/material/button";
17
+ import * as i3 from "@angular/material/icon";
18
+ import * as i4 from "@angular/material/form-field";
19
+ import * as i5 from "@angular/material/select";
20
+ import * as i6 from "@angular/material/core";
21
+ import * as i7 from "@angular/material/input";
22
+ import * as i8 from "@angular/material/tooltip";
23
+ import * as i9 from "@angular/material/datepicker";
24
+ export class QueryBuilderComponent {
25
+ constructor(fb) {
26
+ this.fb = fb;
27
+ this.config = {
28
+ fields: [],
29
+ operators: [
30
+ { value: '=', label: '=' },
31
+ { value: '!=', label: '!=' },
32
+ { value: '>', label: '>' },
33
+ { value: '<', label: '<' },
34
+ { value: '>=', label: '>=' },
35
+ { value: '<=', label: '<=' },
36
+ { value: 'contains', label: 'contains' },
37
+ { value: 'between', label: 'between' }
38
+ ],
39
+ defaultCondition: 'and'
40
+ };
41
+ this.queryChange = new EventEmitter();
42
+ this.form = this.fb.group({
43
+ condition: ['and'],
44
+ rules: this.fb.array([])
45
+ });
46
+ this.model = {
47
+ condition: 'and',
48
+ rules: []
49
+ };
50
+ }
51
+ ngOnInit() {
52
+ this.initializeForm();
53
+ this.addRule();
54
+ this.form.valueChanges.subscribe(value => {
55
+ this.model = this.transformFormToModel(value);
56
+ this.queryChange.emit(this.model);
57
+ });
58
+ }
59
+ get rulesArray() {
60
+ return this.form.get('rules');
61
+ }
62
+ initializeForm() {
63
+ this.form = this.fb.group({
64
+ condition: [this.config.defaultCondition || 'and'],
65
+ rules: this.fb.array([])
66
+ });
67
+ }
68
+ addRule() {
69
+ if (this.config.fields.length === 0) {
70
+ return;
71
+ }
72
+ const defaultField = this.config.fields[0];
73
+ const defaultOperator = defaultField.defaultOperator || this.getOperatorsForType(defaultField.type)[0]?.value || '=';
74
+ const ruleGroup = this.fb.group({
75
+ field: [defaultField.key],
76
+ operator: [defaultOperator],
77
+ value: [null],
78
+ condition: ['and']
79
+ });
80
+ this.rulesArray.push(ruleGroup);
81
+ }
82
+ removeRule(index) {
83
+ this.rulesArray.removeAt(index);
84
+ }
85
+ getFieldByKey(key) {
86
+ return this.config.fields.find(field => field.key === key);
87
+ }
88
+ getOperatorsForType(type) {
89
+ return this.config.operators.filter(op => !op.types || op.types.includes(type));
90
+ }
91
+ getOperatorsForField(fieldKey) {
92
+ const field = this.getFieldByKey(fieldKey);
93
+ if (!field)
94
+ return [];
95
+ if (field.operators) {
96
+ return this.config.operators.filter(op => field.operators?.includes(op.value));
97
+ }
98
+ return this.getOperatorsForType(field.type);
99
+ }
100
+ getFieldType(fieldKey) {
101
+ const field = this.getFieldByKey(fieldKey);
102
+ return field ? field.type : 'string';
103
+ }
104
+ isOperatorBetween(index) {
105
+ const ruleGroup = this.rulesArray.at(index);
106
+ return ruleGroup?.get('operator')?.value === 'between';
107
+ }
108
+ getFieldOptions(fieldKey) {
109
+ const field = this.getFieldByKey(fieldKey);
110
+ return field?.options || [];
111
+ }
112
+ onFieldChange(index, fieldKey) {
113
+ const ruleGroup = this.rulesArray.at(index);
114
+ const field = this.getFieldByKey(fieldKey);
115
+ if (field) {
116
+ const operators = this.getOperatorsForField(fieldKey);
117
+ const defaultOperator = field.defaultOperator || (operators.length > 0 ? operators[0].value : '=');
118
+ ruleGroup.get('operator')?.setValue(defaultOperator);
119
+ ruleGroup.get('value')?.setValue(null);
120
+ // Reset range values if they exist
121
+ if (ruleGroup.get('valueStart')) {
122
+ ruleGroup.get('valueStart')?.setValue(null);
123
+ }
124
+ if (ruleGroup.get('valueEnd')) {
125
+ ruleGroup.get('valueEnd')?.setValue(null);
126
+ }
127
+ // Add range form controls if needed
128
+ this.updateFormControlsForOperator(index, defaultOperator, field.type);
129
+ }
130
+ }
131
+ onOperatorChange(index, operator, fieldKey) {
132
+ const fieldType = this.getFieldType(fieldKey);
133
+ this.updateFormControlsForOperator(index, operator, fieldType);
134
+ // Reset values when operator changes
135
+ const ruleGroup = this.rulesArray.at(index);
136
+ ruleGroup.get('value')?.setValue(null);
137
+ if (ruleGroup.get('valueStart')) {
138
+ ruleGroup.get('valueStart')?.setValue(null);
139
+ }
140
+ if (ruleGroup.get('valueEnd')) {
141
+ ruleGroup.get('valueEnd')?.setValue(null);
142
+ }
143
+ }
144
+ /**
145
+ * Gets the minimum allowed date for the end date picker based on the selected start date
146
+ * @param index The index of the rule row
147
+ * @returns The minimum date for the end date picker (the start date or today if no start date)
148
+ */
149
+ getMinEndDate(index) {
150
+ const ruleGroup = this.rulesArray.at(index);
151
+ const startDate = ruleGroup.get('valueStart')?.value;
152
+ // If start date is selected, use it as minimum for end date
153
+ // Otherwise use today's date
154
+ return startDate ? new Date(startDate) : new Date();
155
+ }
156
+ /**
157
+ * Handles changes to the start date
158
+ * @param index The index of the rule row
159
+ * @param event The date change event
160
+ */
161
+ onStartDateChange(index, event) {
162
+ const ruleGroup = this.rulesArray.at(index);
163
+ const endDate = ruleGroup.get('valueEnd')?.value;
164
+ const startDate = event.value;
165
+ // If end date is before start date, reset it
166
+ if (endDate && startDate && new Date(endDate) < new Date(startDate)) {
167
+ ruleGroup.get('valueEnd')?.setValue(null);
168
+ }
169
+ }
170
+ updateFormControlsForOperator(index, operator, fieldType) {
171
+ const ruleGroup = this.rulesArray.at(index);
172
+ // Handle date range for 'between' operator
173
+ if (operator === 'between' && fieldType === 'date') {
174
+ // Add start and end date controls if they don't exist
175
+ if (!ruleGroup.contains('valueStart')) {
176
+ ruleGroup.addControl('valueStart', this.fb.control(null));
177
+ }
178
+ if (!ruleGroup.contains('valueEnd')) {
179
+ ruleGroup.addControl('valueEnd', this.fb.control(null));
180
+ }
181
+ }
182
+ else {
183
+ // Remove range controls if they exist and aren't needed
184
+ if (ruleGroup.contains('valueStart')) {
185
+ ruleGroup.removeControl('valueStart');
186
+ }
187
+ if (ruleGroup.contains('valueEnd')) {
188
+ ruleGroup.removeControl('valueEnd');
189
+ }
190
+ }
191
+ }
192
+ transformFormToModel(formValue) {
193
+ return {
194
+ condition: formValue.condition,
195
+ rules: formValue.rules.map((rule) => {
196
+ // Handle date range for 'between' operator
197
+ if (rule.operator === 'between' && this.getFieldType(rule.field) === 'date') {
198
+ return {
199
+ field: rule.field,
200
+ operator: rule.operator,
201
+ value: { start: rule.valueStart, end: rule.valueEnd },
202
+ condition: rule.condition
203
+ };
204
+ }
205
+ // Standard case
206
+ return {
207
+ field: rule.field,
208
+ operator: rule.operator,
209
+ value: rule.value,
210
+ condition: rule.condition
211
+ };
212
+ })
213
+ };
214
+ }
215
+ /**
216
+ * Gets the condition for a specific row
217
+ * @param index The index of the row
218
+ * @returns The condition (and/or) for the row
219
+ */
220
+ getRowCondition(index) {
221
+ if (index === 0)
222
+ return 'and'; // First row doesn't have a condition
223
+ const ruleGroup = this.rulesArray.at(index);
224
+ return ruleGroup.get('condition')?.value || 'and';
225
+ }
226
+ /**
227
+ * Sets the condition for a specific row
228
+ * @param index The index of the row
229
+ * @param condition The condition to set (and/or)
230
+ */
231
+ setRowCondition(index, condition) {
232
+ if (index === 0)
233
+ return; // First row doesn't have a condition
234
+ const ruleGroup = this.rulesArray.at(index);
235
+ ruleGroup.get('condition')?.setValue(condition);
236
+ }
237
+ toggleCondition() {
238
+ const currentCondition = this.form.get('condition')?.value;
239
+ const newCondition = currentCondition === 'and' ? 'or' : 'and';
240
+ this.form.get('condition')?.setValue(newCondition);
241
+ }
242
+ getConditionLabel() {
243
+ return this.form.get('condition')?.value === 'and' ? 'AND' : 'OR';
244
+ }
245
+ resetQuery() {
246
+ this.rulesArray.clear();
247
+ this.addRule();
248
+ }
249
+ applyQuery() {
250
+ this.queryChange.emit(this.model);
251
+ }
252
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: QueryBuilderComponent, deps: [{ token: i1.FormBuilder }], target: i0.ɵɵFactoryTarget.Component }); }
253
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.2.4", type: QueryBuilderComponent, isStandalone: true, selector: "sa-query-builder", inputs: { config: "config" }, outputs: { queryChange: "queryChange" }, providers: [provideNativeDateAdapter()], ngImport: i0, template: "<div class=\"sa-query-builder\">\r\n <form [formGroup]=\"form\">\r\n <div class=\"query-builder-header\">\r\n <div class=\"where-label\">Where</div>\r\n </div>\r\n\r\n <div class=\"query-builder-body\">\r\n <div class=\"rules-container\" formArrayName=\"rules\">\r\n @for (rule of rulesArray.controls; track $index) {\r\n <div class=\"rule-row\" [formGroupName]=\"$index\">\r\n <!-- Condition selector (And/Or) -->\r\n @if ($index > 0) {\r\n <div class=\"condition-selector\">\r\n <mat-form-field appearance=\"fill\">\r\n <mat-select [value]=\"getRowCondition($index)\" (selectionChange)=\"setRowCondition($index, $event.value)\">\r\n <mat-option value=\"and\">And</mat-option>\r\n <mat-option value=\"or\">Or</mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </div>\r\n } @else {\r\n <div class=\"condition-placeholder\"></div>\r\n }\r\n \r\n <!-- Field selection -->\r\n <mat-form-field class=\"field-select\">\r\n <mat-label>Select a filter</mat-label>\r\n <mat-select formControlName=\"field\" (selectionChange)=\"onFieldChange($index, $event.value)\">\r\n @for (field of config.fields; track field.key) {\r\n <mat-option [value]=\"field.key\">\r\n {{ field.label }}\r\n </mat-option>\r\n }\r\n </mat-select>\r\n </mat-form-field>\r\n\r\n <!-- Operator selection -->\r\n <mat-form-field class=\"operator-select\">\r\n <mat-select formControlName=\"operator\" (selectionChange)=\"onOperatorChange($index, $event.value, rule.value.field)\">\r\n @for (op of getOperatorsForField(rule.value.field); track op.value) {\r\n <mat-option [value]=\"op.value\">\r\n {{ op.label }}\r\n </mat-option>\r\n }\r\n </mat-select>\r\n </mat-form-field>\r\n\r\n <!-- Value input based on field type -->\r\n @switch (getFieldType(rule.value.field)) {\r\n @case ('string') {\r\n <mat-form-field class=\"value-input\">\r\n <input matInput formControlName=\"value\" placeholder=\"Enter a value...\">\r\n </mat-form-field>\r\n }\r\n @case ('number') {\r\n <mat-form-field class=\"value-input\">\r\n <input matInput type=\"number\" formControlName=\"value\" placeholder=\"Enter a value...\">\r\n </mat-form-field>\r\n }\r\n @case ('date') {\r\n @if (!isOperatorBetween($index)) {\r\n <mat-form-field class=\"value-input\">\r\n <input matInput type=\"date\" [matDatepicker]=\"picker\" formControlName=\"value\" (click)=\"picker.open()\">\r\n <mat-datepicker-toggle matIconSuffix [for]=\"picker\"></mat-datepicker-toggle>\r\n <mat-datepicker #picker></mat-datepicker>\r\n </mat-form-field>\r\n } @else {\r\n <div class=\"date-range-container\">\r\n <mat-form-field class=\"value-input start-date\">\r\n <mat-label>Start date</mat-label>\r\n <input matInput [matDatepicker]=\"startPicker\" formControlName=\"valueStart\" (click)=\"startPicker.open()\" (dateChange)=\"onStartDateChange($index, $event)\">\r\n <mat-datepicker-toggle matIconSuffix [for]=\"startPicker\"></mat-datepicker-toggle>\r\n <mat-datepicker #startPicker></mat-datepicker>\r\n </mat-form-field>\r\n <mat-form-field class=\"value-input end-date\">\r\n <mat-label>End date</mat-label>\r\n <input matInput [matDatepicker]=\"endPicker\" formControlName=\"valueEnd\" (click)=\"endPicker.open()\" [min]=\"getMinEndDate($index)\">\r\n <mat-datepicker-toggle matIconSuffix [for]=\"endPicker\"></mat-datepicker-toggle>\r\n <mat-datepicker #endPicker [startAt]=\"getMinEndDate($index)\"></mat-datepicker>\r\n </mat-form-field>\r\n </div>\r\n }\r\n }\r\n @case ('boolean') {\r\n <mat-form-field class=\"value-input\">\r\n <mat-select formControlName=\"value\">\r\n <mat-option [value]=\"true\">True</mat-option>\r\n <mat-option [value]=\"false\">False</mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n }\r\n @case ('select') {\r\n <mat-form-field class=\"value-input\">\r\n <mat-select formControlName=\"value\">\r\n @for (option of getFieldOptions(rule.value.field); track option.value) {\r\n <mat-option [value]=\"option.value\">\r\n {{ option.label }}\r\n </mat-option>\r\n }\r\n </mat-select>\r\n </mat-form-field>\r\n }\r\n @default {\r\n <mat-form-field class=\"value-input\">\r\n <input matInput formControlName=\"value\" placeholder=\"Enter a value...\">\r\n </mat-form-field>\r\n }\r\n }\r\n\r\n <!-- Remove rule button -->\r\n <button mat-icon-button class=\"remove-rule-btn\" \r\n (click)=\"removeRule($index)\" \r\n [disabled]=\"rulesArray.length === 1\"\r\n matTooltip=\"Remove filter\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- Add rule button -->\r\n <div class=\"add-rule-container\">\r\n <button mat-button color=\"primary\" class=\"add-rule-btn\" (click)=\"addRule()\">\r\n <mat-icon>add</mat-icon> Add a filter\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div class=\"query-builder-footer\">\r\n <button mat-button class=\"reset-btn\" (click)=\"resetQuery()\">Reset</button>\r\n <button mat-raised-button color=\"primary\" class=\"apply-btn\" (click)=\"applyQuery()\">Apply filters</button>\r\n </div>\r\n </form>\r\n</div>\r\n", styles: [".sa-query-builder{display:flex;flex-direction:column;width:100%;background-color:#fff;border-radius:8px;padding:16px;box-sizing:border-box}.sa-query-builder .query-builder-header{display:flex;align-items:center;margin-bottom:16px;height:36px;padding-left:128px}.sa-query-builder .query-builder-header .where-label{font-size:16px;font-weight:500;color:#000000de;margin-right:16px;line-height:36px}.sa-query-builder .query-builder-body .rules-container{display:flex;flex-direction:column;gap:12px;margin-bottom:16px}.sa-query-builder .query-builder-body .rules-container .rule-row{display:flex;align-items:center;gap:12px;width:100%}.sa-query-builder .query-builder-body .rules-container .rule-row .condition-selector{width:120px;min-width:120px;margin-right:8px}.sa-query-builder .query-builder-body .rules-container .rule-row .condition-selector .mat-form-field{width:100%}.sa-query-builder .query-builder-body .rules-container .rule-row .condition-selector ::ng-deep .mat-form-field-wrapper{padding-bottom:0;margin:0}.sa-query-builder .query-builder-body .rules-container .rule-row .condition-selector ::ng-deep .mat-form-field-infix{padding:.5em 0;border-top:0}.sa-query-builder .query-builder-body .rules-container .rule-row .condition-placeholder{width:120px;min-width:120px;margin-right:8px}.sa-query-builder .query-builder-body .rules-container .rule-row .field-select{flex:2;min-width:180px}.sa-query-builder .query-builder-body .rules-container .rule-row .operator-select{flex:1;min-width:100px}.sa-query-builder .query-builder-body .rules-container .rule-row .value-input{flex:2;min-width:180px}.sa-query-builder .query-builder-body .rules-container .rule-row .date-range-container{display:flex;flex:2;gap:8px}.sa-query-builder .query-builder-body .rules-container .rule-row .date-range-container .start-date,.sa-query-builder .query-builder-body .rules-container .rule-row .date-range-container .end-date{flex:1;min-width:140px}.sa-query-builder .query-builder-body .rules-container .rule-row .remove-rule-btn{color:#0000008a}.sa-query-builder .query-builder-body .add-rule-container{margin-bottom:16px}.sa-query-builder .query-builder-body .add-rule-container .add-rule-btn{display:flex;align-items:center;gap:4px;color:#673ab7;font-weight:500}.sa-query-builder .query-builder-footer{display:flex;justify-content:flex-end;gap:12px;margin-top:16px}.sa-query-builder .query-builder-footer .reset-btn{color:#0000008a}.sa-query-builder .query-builder-footer .apply-btn{background-color:#673ab7;color:#fff}::ng-deep .mat-mdc-form-field-subscript-wrapper{display:none}::ng-deep .mat-mdc-form-field-infix{min-height:40px}::ng-deep .mat-mdc-select-panel{max-height:300px}::ng-deep .mat-mdc-option{font-size:14px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "ngmodule", type: FormlyModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i2.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { 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: MatSelectModule }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "directive", type: i4.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: i5.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i7.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i8.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatButtonToggleModule }, { kind: "ngmodule", type: MatDatepickerModule }, { kind: "component", type: i9.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i9.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i9.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }] }); }
254
+ }
255
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.4", ngImport: i0, type: QueryBuilderComponent, decorators: [{
256
+ type: Component,
257
+ args: [{ selector: 'sa-query-builder', standalone: true, providers: [provideNativeDateAdapter()], imports: [
258
+ CommonModule,
259
+ ReactiveFormsModule,
260
+ FormlyModule,
261
+ MatButtonModule,
262
+ MatIconModule,
263
+ MatSelectModule,
264
+ MatFormFieldModule,
265
+ MatInputModule,
266
+ MatTooltipModule,
267
+ MatButtonToggleModule,
268
+ MatDatepickerModule
269
+ ], template: "<div class=\"sa-query-builder\">\r\n <form [formGroup]=\"form\">\r\n <div class=\"query-builder-header\">\r\n <div class=\"where-label\">Where</div>\r\n </div>\r\n\r\n <div class=\"query-builder-body\">\r\n <div class=\"rules-container\" formArrayName=\"rules\">\r\n @for (rule of rulesArray.controls; track $index) {\r\n <div class=\"rule-row\" [formGroupName]=\"$index\">\r\n <!-- Condition selector (And/Or) -->\r\n @if ($index > 0) {\r\n <div class=\"condition-selector\">\r\n <mat-form-field appearance=\"fill\">\r\n <mat-select [value]=\"getRowCondition($index)\" (selectionChange)=\"setRowCondition($index, $event.value)\">\r\n <mat-option value=\"and\">And</mat-option>\r\n <mat-option value=\"or\">Or</mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </div>\r\n } @else {\r\n <div class=\"condition-placeholder\"></div>\r\n }\r\n \r\n <!-- Field selection -->\r\n <mat-form-field class=\"field-select\">\r\n <mat-label>Select a filter</mat-label>\r\n <mat-select formControlName=\"field\" (selectionChange)=\"onFieldChange($index, $event.value)\">\r\n @for (field of config.fields; track field.key) {\r\n <mat-option [value]=\"field.key\">\r\n {{ field.label }}\r\n </mat-option>\r\n }\r\n </mat-select>\r\n </mat-form-field>\r\n\r\n <!-- Operator selection -->\r\n <mat-form-field class=\"operator-select\">\r\n <mat-select formControlName=\"operator\" (selectionChange)=\"onOperatorChange($index, $event.value, rule.value.field)\">\r\n @for (op of getOperatorsForField(rule.value.field); track op.value) {\r\n <mat-option [value]=\"op.value\">\r\n {{ op.label }}\r\n </mat-option>\r\n }\r\n </mat-select>\r\n </mat-form-field>\r\n\r\n <!-- Value input based on field type -->\r\n @switch (getFieldType(rule.value.field)) {\r\n @case ('string') {\r\n <mat-form-field class=\"value-input\">\r\n <input matInput formControlName=\"value\" placeholder=\"Enter a value...\">\r\n </mat-form-field>\r\n }\r\n @case ('number') {\r\n <mat-form-field class=\"value-input\">\r\n <input matInput type=\"number\" formControlName=\"value\" placeholder=\"Enter a value...\">\r\n </mat-form-field>\r\n }\r\n @case ('date') {\r\n @if (!isOperatorBetween($index)) {\r\n <mat-form-field class=\"value-input\">\r\n <input matInput type=\"date\" [matDatepicker]=\"picker\" formControlName=\"value\" (click)=\"picker.open()\">\r\n <mat-datepicker-toggle matIconSuffix [for]=\"picker\"></mat-datepicker-toggle>\r\n <mat-datepicker #picker></mat-datepicker>\r\n </mat-form-field>\r\n } @else {\r\n <div class=\"date-range-container\">\r\n <mat-form-field class=\"value-input start-date\">\r\n <mat-label>Start date</mat-label>\r\n <input matInput [matDatepicker]=\"startPicker\" formControlName=\"valueStart\" (click)=\"startPicker.open()\" (dateChange)=\"onStartDateChange($index, $event)\">\r\n <mat-datepicker-toggle matIconSuffix [for]=\"startPicker\"></mat-datepicker-toggle>\r\n <mat-datepicker #startPicker></mat-datepicker>\r\n </mat-form-field>\r\n <mat-form-field class=\"value-input end-date\">\r\n <mat-label>End date</mat-label>\r\n <input matInput [matDatepicker]=\"endPicker\" formControlName=\"valueEnd\" (click)=\"endPicker.open()\" [min]=\"getMinEndDate($index)\">\r\n <mat-datepicker-toggle matIconSuffix [for]=\"endPicker\"></mat-datepicker-toggle>\r\n <mat-datepicker #endPicker [startAt]=\"getMinEndDate($index)\"></mat-datepicker>\r\n </mat-form-field>\r\n </div>\r\n }\r\n }\r\n @case ('boolean') {\r\n <mat-form-field class=\"value-input\">\r\n <mat-select formControlName=\"value\">\r\n <mat-option [value]=\"true\">True</mat-option>\r\n <mat-option [value]=\"false\">False</mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n }\r\n @case ('select') {\r\n <mat-form-field class=\"value-input\">\r\n <mat-select formControlName=\"value\">\r\n @for (option of getFieldOptions(rule.value.field); track option.value) {\r\n <mat-option [value]=\"option.value\">\r\n {{ option.label }}\r\n </mat-option>\r\n }\r\n </mat-select>\r\n </mat-form-field>\r\n }\r\n @default {\r\n <mat-form-field class=\"value-input\">\r\n <input matInput formControlName=\"value\" placeholder=\"Enter a value...\">\r\n </mat-form-field>\r\n }\r\n }\r\n\r\n <!-- Remove rule button -->\r\n <button mat-icon-button class=\"remove-rule-btn\" \r\n (click)=\"removeRule($index)\" \r\n [disabled]=\"rulesArray.length === 1\"\r\n matTooltip=\"Remove filter\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n }\r\n </div>\r\n\r\n <!-- Add rule button -->\r\n <div class=\"add-rule-container\">\r\n <button mat-button color=\"primary\" class=\"add-rule-btn\" (click)=\"addRule()\">\r\n <mat-icon>add</mat-icon> Add a filter\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <div class=\"query-builder-footer\">\r\n <button mat-button class=\"reset-btn\" (click)=\"resetQuery()\">Reset</button>\r\n <button mat-raised-button color=\"primary\" class=\"apply-btn\" (click)=\"applyQuery()\">Apply filters</button>\r\n </div>\r\n </form>\r\n</div>\r\n", styles: [".sa-query-builder{display:flex;flex-direction:column;width:100%;background-color:#fff;border-radius:8px;padding:16px;box-sizing:border-box}.sa-query-builder .query-builder-header{display:flex;align-items:center;margin-bottom:16px;height:36px;padding-left:128px}.sa-query-builder .query-builder-header .where-label{font-size:16px;font-weight:500;color:#000000de;margin-right:16px;line-height:36px}.sa-query-builder .query-builder-body .rules-container{display:flex;flex-direction:column;gap:12px;margin-bottom:16px}.sa-query-builder .query-builder-body .rules-container .rule-row{display:flex;align-items:center;gap:12px;width:100%}.sa-query-builder .query-builder-body .rules-container .rule-row .condition-selector{width:120px;min-width:120px;margin-right:8px}.sa-query-builder .query-builder-body .rules-container .rule-row .condition-selector .mat-form-field{width:100%}.sa-query-builder .query-builder-body .rules-container .rule-row .condition-selector ::ng-deep .mat-form-field-wrapper{padding-bottom:0;margin:0}.sa-query-builder .query-builder-body .rules-container .rule-row .condition-selector ::ng-deep .mat-form-field-infix{padding:.5em 0;border-top:0}.sa-query-builder .query-builder-body .rules-container .rule-row .condition-placeholder{width:120px;min-width:120px;margin-right:8px}.sa-query-builder .query-builder-body .rules-container .rule-row .field-select{flex:2;min-width:180px}.sa-query-builder .query-builder-body .rules-container .rule-row .operator-select{flex:1;min-width:100px}.sa-query-builder .query-builder-body .rules-container .rule-row .value-input{flex:2;min-width:180px}.sa-query-builder .query-builder-body .rules-container .rule-row .date-range-container{display:flex;flex:2;gap:8px}.sa-query-builder .query-builder-body .rules-container .rule-row .date-range-container .start-date,.sa-query-builder .query-builder-body .rules-container .rule-row .date-range-container .end-date{flex:1;min-width:140px}.sa-query-builder .query-builder-body .rules-container .rule-row .remove-rule-btn{color:#0000008a}.sa-query-builder .query-builder-body .add-rule-container{margin-bottom:16px}.sa-query-builder .query-builder-body .add-rule-container .add-rule-btn{display:flex;align-items:center;gap:4px;color:#673ab7;font-weight:500}.sa-query-builder .query-builder-footer{display:flex;justify-content:flex-end;gap:12px;margin-top:16px}.sa-query-builder .query-builder-footer .reset-btn{color:#0000008a}.sa-query-builder .query-builder-footer .apply-btn{background-color:#673ab7;color:#fff}::ng-deep .mat-mdc-form-field-subscript-wrapper{display:none}::ng-deep .mat-mdc-form-field-infix{min-height:40px}::ng-deep .mat-mdc-select-panel{max-height:300px}::ng-deep .mat-mdc-option{font-size:14px}\n"] }]
270
+ }], ctorParameters: () => [{ type: i1.FormBuilder }], propDecorators: { config: [{
271
+ type: Input
272
+ }], queryChange: [{
273
+ type: Output
274
+ }] } });
275
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicXVlcnktYnVpbGRlci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9jb21wb25lbnQtbGlicmFyeS9zcmMvbGliL3F1ZXJ5LWJ1aWxkZXIvcXVlcnktYnVpbGRlci5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9jb21wb25lbnQtbGlicmFyeS9zcmMvbGliL3F1ZXJ5LWJ1aWxkZXIvcXVlcnktYnVpbGRlci5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLFlBQVksRUFBRSxLQUFLLEVBQVUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQy9FLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQWtELG1CQUFtQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDckcsT0FBTyxFQUFxQixZQUFZLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUNuRSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDM0QsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUMzRCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUNsRSxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDekQsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDN0QsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDeEUsT0FBTyxFQUFDLG1CQUFtQixFQUFDLE1BQU0sOEJBQThCLENBQUM7QUFDakUsT0FBTyxFQUFFLHdCQUF3QixFQUFFLE1BQU0sd0JBQXdCLENBQUM7Ozs7Ozs7Ozs7O0FB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QUFDLFdBQzlCO3dCQUNQLFlBQVk7d0JBQ1osbUJBQW1CO3dCQUNuQixZQUFZO3dCQUNaLGVBQWU7d0JBQ2YsYUFBYTt3QkFDYixlQUFlO3dCQUNmLGtCQUFrQjt3QkFDbEIsY0FBYzt3QkFDZCxnQkFBZ0I7d0JBQ2hCLHFCQUFxQjt3QkFDckIsbUJBQW1CO3FCQUNwQjtnRkFHUSxNQUFNO3NCQUFkLEtBQUs7Z0JBZUksV0FBVztzQkFBcEIsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgRXZlbnRFbWl0dGVyLCBJbnB1dCwgT25Jbml0LCBPdXRwdXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcclxuaW1wb3J0IHsgRm9ybUFycmF5LCBGb3JtQnVpbGRlciwgRm9ybUNvbnRyb2wsIEZvcm1Hcm91cCwgUmVhY3RpdmVGb3Jtc01vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcclxuaW1wb3J0IHsgRm9ybWx5RmllbGRDb25maWcsIEZvcm1seU1vZHVsZSB9IGZyb20gJ0BuZ3gtZm9ybWx5L2NvcmUnO1xyXG5pbXBvcnQgeyBNYXRCdXR0b25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9idXR0b24nO1xyXG5pbXBvcnQgeyBNYXRJY29uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvaWNvbic7XHJcbmltcG9ydCB7IE1hdFNlbGVjdE1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL3NlbGVjdCc7XHJcbmltcG9ydCB7IE1hdEZvcm1GaWVsZE1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2Zvcm0tZmllbGQnO1xyXG5pbXBvcnQgeyBNYXRJbnB1dE1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2lucHV0JztcclxuaW1wb3J0IHsgTWF0VG9vbHRpcE1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL3Rvb2x0aXAnO1xyXG5pbXBvcnQgeyBNYXRCdXR0b25Ub2dnbGVNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9idXR0b24tdG9nZ2xlJztcclxuaW1wb3J0IHtNYXREYXRlcGlja2VyTW9kdWxlfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9kYXRlcGlja2VyJztcclxuaW1wb3J0IHsgcHJvdmlkZU5hdGl2ZURhdGVBZGFwdGVyIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvY29yZSc7XHJcblxyXG5cclxuZXhwb3J0IGludGVyZmFjZSBRdWVyeUZpZWxkIHtcclxuICBrZXk6IHN0cmluZztcclxuICBsYWJlbDogc3RyaW5nO1xyXG4gIHR5cGU6IHN0cmluZztcclxuICBvcHRpb25zPzogeyBsYWJlbDogc3RyaW5nOyB2YWx1ZTogYW55IH1bXTtcclxuICBvcGVyYXRvcnM/OiBzdHJpbmdbXTtcclxuICBkZWZhdWx0T3BlcmF0b3I/OiBzdHJpbmc7XHJcbn1cclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgUXVlcnlPcGVyYXRvciB7XHJcbiAgdmFsdWU6IHN0cmluZztcclxuICBsYWJlbDogc3RyaW5nO1xyXG4gIHR5cGVzPzogc3RyaW5nW107XHJcbn1cclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgUXVlcnlDb25maWcge1xyXG4gIGZpZWxkczogUXVlcnlGaWVsZFtdO1xyXG4gIG9wZXJhdG9yczogUXVlcnlPcGVyYXRvcltdO1xyXG4gIGRlZmF1bHRDb25kaXRpb24/OiAnYW5kJyB8ICdvcic7XHJcbn1cclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgUXVlcnlSdWxlIHtcclxuICBmaWVsZDogc3RyaW5nO1xyXG4gIG9wZXJhdG9yOiBzdHJpbmc7XHJcbiAgdmFsdWU6IGFueTtcclxuICBjb25kaXRpb24/OiAnYW5kJyB8ICdvcic7XHJcbn1cclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgUXVlcnlHcm91cCB7XHJcbiAgY29uZGl0aW9uOiAnYW5kJyB8ICdvcic7XHJcbiAgcnVsZXM6IChRdWVyeVJ1bGUgfCBRdWVyeUdyb3VwKVtdO1xyXG59XHJcblxyXG5AQ29tcG9uZW50KHtcclxuICBzZWxlY3RvcjogJ3NhLXF1ZXJ5LWJ1aWxkZXInLFxyXG4gIHRlbXBsYXRlVXJsOiAnLi9xdWVyeS1idWlsZGVyLmNvbXBvbmVudC5odG1sJyxcclxuICBzdHlsZVVybHM6IFsnLi9xdWVyeS1idWlsZGVyLmNvbXBvbmVudC5zY3NzJ10sXHJcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcclxuICBwcm92aWRlcnM6IFtwcm92aWRlTmF0aXZlRGF0ZUFkYXB0ZXIoKV0sXHJcbiAgaW1wb3J0czogW1xyXG4gICAgQ29tbW9uTW9kdWxlLFxyXG4gICAgUmVhY3RpdmVGb3Jtc01vZHVsZSxcclxuICAgIEZvcm1seU1vZHVsZSxcclxuICAgIE1hdEJ1dHRvbk1vZHVsZSxcclxuICAgIE1hdEljb25Nb2R1bGUsXHJcbiAgICBNYXRTZWxlY3RNb2R1bGUsXHJcbiAgICBNYXRGb3JtRmllbGRNb2R1bGUsXHJcbiAgICBNYXRJbnB1dE1vZHVsZSxcclxuICAgIE1hdFRvb2x0aXBNb2R1bGUsXHJcbiAgICBNYXRCdXR0b25Ub2dnbGVNb2R1bGUsXHJcbiAgICBNYXREYXRlcGlja2VyTW9kdWxlXHJcbiAgXVxyXG59KVxyXG5leHBvcnQgY2xhc3MgUXVlcnlCdWlsZGVyQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcclxuICBASW5wdXQoKSBjb25maWc6IFF1ZXJ5Q29uZmlnID0ge1xyXG4gICAgZmllbGRzOiBbXSxcclxuICAgIG9wZXJhdG9yczogW1xyXG4gICAgICB7IHZhbHVlOiAnPScsIGxhYmVsOiAnPScgfSxcclxuICAgICAgeyB2YWx1ZTogJyE9JywgbGFiZWw6ICchPScgfSxcclxuICAgICAgeyB2YWx1ZTogJz4nLCBsYWJlbDogJz4nIH0sXHJcbiAgICAgIHsgdmFsdWU6ICc8JywgbGFiZWw6ICc8JyB9LFxyXG4gICAgICB7IHZhbHVlOiAnPj0nLCBsYWJlbDogJz49JyB9LFxyXG4gICAgICB7IHZhbHVlOiAnPD0nLCBsYWJlbDogJzw9JyB9LFxyXG4gICAgICB7IHZhbHVlOiAnY29udGFpbnMnLCBsYWJlbDogJ2NvbnRhaW5zJyB9LFxyXG4gICAgICB7IHZhbHVlOiAnYmV0d2VlbicsIGxhYmVsOiAnYmV0d2VlbicgfVxyXG4gICAgXSxcclxuICAgIGRlZmF1bHRDb25kaXRpb246ICdhbmQnXHJcbiAgfTtcclxuXHJcbiAgQE91dHB1dCgpIHF1ZXJ5Q2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxRdWVyeUdyb3VwPigpO1xyXG5cclxuICBmb3JtOiBGb3JtR3JvdXA7XHJcbiAgbW9kZWw6IFF1ZXJ5R3JvdXA7XHJcblxyXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgZmI6IEZvcm1CdWlsZGVyKSB7XHJcbiAgICB0aGlzLmZvcm0gPSB0aGlzLmZiLmdyb3VwKHtcclxuICAgICAgY29uZGl0aW9uOiBbJ2FuZCddLFxyXG4gICAgICBydWxlczogdGhpcy5mYi5hcnJheShbXSlcclxuICAgIH0pO1xyXG5cclxuICAgIHRoaXMubW9kZWwgPSB7XHJcbiAgICAgIGNvbmRpdGlvbjogJ2FuZCcsXHJcbiAgICAgIHJ1bGVzOiBbXVxyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIG5nT25Jbml0KCk6IHZvaWQge1xyXG4gICAgdGhpcy5pbml0aWFsaXplRm9ybSgpO1xyXG4gICAgdGhpcy5hZGRSdWxlKCk7XHJcblxyXG4gICAgdGhpcy5mb3JtLnZhbHVlQ2hhbmdlcy5zdWJzY3JpYmUodmFsdWUgPT4ge1xyXG4gICAgICB0aGlzLm1vZGVsID0gdGhpcy50cmFuc2Zvcm1Gb3JtVG9Nb2RlbCh2YWx1ZSk7XHJcbiAgICAgIHRoaXMucXVlcnlDaGFuZ2UuZW1pdCh0aGlzLm1vZGVsKTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgZ2V0IHJ1bGVzQXJyYXkoKTogRm9ybUFycmF5IHtcclxuICAgIHJldHVybiB0aGlzLmZvcm0uZ2V0KCdydWxlcycpIGFzIEZvcm1BcnJheTtcclxuICB9XHJcblxyXG4gIGluaXRpYWxpemVGb3JtKCk6IHZvaWQge1xyXG4gICAgdGhpcy5mb3JtID0gdGhpcy5mYi5ncm91cCh7XHJcbiAgICAgIGNvbmRpdGlvbjogW3RoaXMuY29uZmlnLmRlZmF1bHRDb25kaXRpb24gfHwgJ2FuZCddLFxyXG4gICAgICBydWxlczogdGhpcy5mYi5hcnJheShbXSlcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgYWRkUnVsZSgpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLmNvbmZpZy5maWVsZHMubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBkZWZhdWx0RmllbGQgPSB0aGlzLmNvbmZpZy5maWVsZHNbMF07XHJcbiAgICBjb25zdCBkZWZhdWx0T3BlcmF0b3IgPSBkZWZhdWx0RmllbGQuZGVmYXVsdE9wZXJhdG9yIHx8IHRoaXMuZ2V0T3BlcmF0b3JzRm9yVHlwZShkZWZhdWx0RmllbGQudHlwZSlbMF0/LnZhbHVlIHx8ICc9JztcclxuXHJcbiAgICBjb25zdCBydWxlR3JvdXAgPSB0aGlzLmZiLmdyb3VwKHtcclxuICAgICAgZmllbGQ6IFtkZWZhdWx0RmllbGQua2V5XSxcclxuICAgICAgb3BlcmF0b3I6IFtkZWZhdWx0T3BlcmF0b3JdLFxyXG4gICAgICB2YWx1ZTogW251bGxdLFxyXG4gICAgICBjb25kaXRpb246IFsnYW5kJ11cclxuICAgIH0pO1xyXG5cclxuICAgIHRoaXMucnVsZXNBcnJheS5wdXNoKHJ1bGVHcm91cCk7XHJcbiAgfVxyXG5cclxuICByZW1vdmVSdWxlKGluZGV4OiBudW1iZXIpOiB2b2lkIHtcclxuICAgIHRoaXMucnVsZXNBcnJheS5yZW1vdmVBdChpbmRleCk7XHJcbiAgfVxyXG5cclxuICBnZXRGaWVsZEJ5S2V5KGtleTogc3RyaW5nKTogUXVlcnlGaWVsZCB8IHVuZGVmaW5lZCB7XHJcbiAgICByZXR1cm4gdGhpcy5jb25maWcuZmllbGRzLmZpbmQoZmllbGQgPT4gZmllbGQua2V5ID09PSBrZXkpO1xyXG4gIH1cclxuXHJcbiAgZ2V0T3BlcmF0b3JzRm9yVHlwZSh0eXBlOiBzdHJpbmcpOiBRdWVyeU9wZXJhdG9yW10ge1xyXG4gICAgcmV0dXJuIHRoaXMuY29uZmlnLm9wZXJhdG9ycy5maWx0ZXIob3AgPT4gIW9wLnR5cGVzIHx8IG9wLnR5cGVzLmluY2x1ZGVzKHR5cGUpKTtcclxuICB9XHJcblxyXG4gIGdldE9wZXJhdG9yc0ZvckZpZWxkKGZpZWxkS2V5OiBzdHJpbmcpOiBRdWVyeU9wZXJhdG9yW10ge1xyXG4gICAgY29uc3QgZmllbGQgPSB0aGlzLmdldEZpZWxkQnlLZXkoZmllbGRLZXkpO1xyXG4gICAgaWYgKCFmaWVsZCkgcmV0dXJuIFtdO1xyXG5cclxuICAgIGlmIChmaWVsZC5vcGVyYXRvcnMpIHtcclxuICAgICAgcmV0dXJuIHRoaXMuY29uZmlnLm9wZXJhdG9ycy5maWx0ZXIob3AgPT4gZmllbGQub3BlcmF0b3JzPy5pbmNsdWRlcyhvcC52YWx1ZSkpO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiB0aGlzLmdldE9wZXJhdG9yc0ZvclR5cGUoZmllbGQudHlwZSk7XHJcbiAgfVxyXG5cclxuICBnZXRGaWVsZFR5cGUoZmllbGRLZXk6IHN0cmluZyk6IHN0cmluZyB7XHJcbiAgICBjb25zdCBmaWVsZCA9IHRoaXMuZ2V0RmllbGRCeUtleShmaWVsZEtleSk7XHJcbiAgICByZXR1cm4gZmllbGQgPyBmaWVsZC50eXBlIDogJ3N0cmluZyc7XHJcbiAgfVxyXG4gIFxyXG4gIGlzT3BlcmF0b3JCZXR3ZWVuKGluZGV4OiBudW1iZXIpOiBib29sZWFuIHtcclxuICAgIGNvbnN0IHJ1bGVHcm91cCA9IHRoaXMucnVsZXNBcnJheS5hdChpbmRleCkgYXMgRm9ybUdyb3VwO1xyXG4gICAgcmV0dXJuIHJ1bGVHcm91cD8uZ2V0KCdvcGVyYXRvcicpPy52YWx1ZSA9PT0gJ2JldHdlZW4nO1xyXG4gIH1cclxuXHJcbiAgZ2V0RmllbGRPcHRpb25zKGZpZWxkS2V5OiBzdHJpbmcpOiB7IGxhYmVsOiBzdHJpbmc7IHZhbHVlOiBhbnkgfVtdIHtcclxuICAgIGNvbnN0IGZpZWxkID0gdGhpcy5nZXRGaWVsZEJ5S2V5KGZpZWxkS2V5KTtcclxuICAgIHJldHVybiBmaWVsZD8ub3B0aW9ucyB8fCBbXTtcclxuICB9XHJcblxyXG4gIG9uRmllbGRDaGFuZ2UoaW5kZXg6IG51bWJlciwgZmllbGRLZXk6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgY29uc3QgcnVsZUdyb3VwID0gdGhpcy5ydWxlc0FycmF5LmF0KGluZGV4KSBhcyBGb3JtR3JvdXA7XHJcbiAgICBjb25zdCBmaWVsZCA9IHRoaXMuZ2V0RmllbGRCeUtleShmaWVsZEtleSk7XHJcbiAgICBcclxuICAgIGlmIChmaWVsZCkge1xyXG4gICAgICBjb25zdCBvcGVyYXRvcnMgPSB0aGlzLmdldE9wZXJhdG9yc0ZvckZpZWxkKGZpZWxkS2V5KTtcclxuICAgICAgY29uc3QgZGVmYXVsdE9wZXJhdG9yID0gZmllbGQuZGVmYXVsdE9wZXJhdG9yIHx8IChvcGVyYXRvcnMubGVuZ3RoID4gMCA/IG9wZXJhdG9yc1swXS52YWx1ZSA6ICc9Jyk7XHJcbiAgICAgIFxyXG4gICAgICBydWxlR3JvdXAuZ2V0KCdvcGVyYXRvcicpPy5zZXRWYWx1ZShkZWZhdWx0T3BlcmF0b3IpO1xyXG4gICAgICBydWxlR3JvdXAuZ2V0KCd2YWx1ZScpPy5zZXRWYWx1ZShudWxsKTtcclxuICAgICAgXHJcbiAgICAgIC8vIFJlc2V0IHJhbmdlIHZhbHVlcyBpZiB0aGV5IGV4aXN0XHJcbiAgICAgIGlmIChydWxlR3JvdXAuZ2V0KCd2YWx1ZVN0YXJ0JykpIHtcclxuICAgICAgICBydWxlR3JvdXAuZ2V0KCd2YWx1ZVN0YXJ0Jyk/LnNldFZhbHVlKG51bGwpO1xyXG4gICAgICB9XHJcbiAgICAgIGlmIChydWxlR3JvdXAuZ2V0KCd2YWx1ZUVuZCcpKSB7XHJcbiAgICAgICAgcnVsZUdyb3VwLmdldCgndmFsdWVFbmQnKT8uc2V0VmFsdWUobnVsbCk7XHJcbiAgICAgIH1cclxuICAgICAgXHJcbiAgICAgIC8vIEFkZCByYW5nZSBmb3JtIGNvbnRyb2xzIGlmIG5lZWRlZFxyXG4gICAgICB0aGlzLnVwZGF0ZUZvcm1Db250cm9sc0Zvck9wZXJhdG9yKGluZGV4LCBkZWZhdWx0T3BlcmF0b3IsIGZpZWxkLnR5cGUpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgb25PcGVyYXRvckNoYW5nZShpbmRleDogbnVtYmVyLCBvcGVyYXRvcjogc3RyaW5nLCBmaWVsZEtleTogc3RyaW5nKTogdm9pZCB7XHJcbiAgICBjb25zdCBmaWVsZFR5cGUgPSB0aGlzLmdldEZpZWxkVHlwZShmaWVsZEtleSk7XHJcbiAgICB0aGlzLnVwZGF0ZUZvcm1Db250cm9sc0Zvck9wZXJhdG9yKGluZGV4LCBvcGVyYXRvciwgZmllbGRUeXBlKTtcclxuICAgIFxyXG4gICAgLy8gUmVzZXQgdmFsdWVzIHdoZW4gb3BlcmF0b3IgY2hhbmdlc1xyXG4gICAgY29uc3QgcnVsZUdyb3VwID0gdGhpcy5ydWxlc0FycmF5LmF0KGluZGV4KSBhcyBGb3JtR3JvdXA7XHJcbiAgICBydWxlR3JvdXAuZ2V0KCd2YWx1ZScpPy5zZXRWYWx1ZShudWxsKTtcclxuICAgIGlmIChydWxlR3JvdXAuZ2V0KCd2YWx1ZVN0YXJ0JykpIHtcclxuICAgICAgcnVsZUdyb3VwLmdldCgndmFsdWVTdGFydCcpPy5zZXRWYWx1ZShudWxsKTtcclxuICAgIH1cclxuICAgIGlmIChydWxlR3JvdXAuZ2V0KCd2YWx1ZUVuZCcpKSB7XHJcbiAgICAgIHJ1bGVHcm91cC5nZXQoJ3ZhbHVlRW5kJyk/LnNldFZhbHVlKG51bGwpO1xyXG4gICAgfVxyXG4gIH1cclxuICBcclxuICAvKipcclxuICAgKiBHZXRzIHRoZSBtaW5pbXVtIGFsbG93ZWQgZGF0ZSBmb3IgdGhlIGVuZCBkYXRlIHBpY2tlciBiYXNlZCBvbiB0aGUgc2VsZWN0ZWQgc3RhcnQgZGF0ZVxyXG4gICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIHJ1bGUgcm93XHJcbiAgICogQHJldHVybnMgVGhlIG1pbmltdW0gZGF0ZSBmb3IgdGhlIGVuZCBkYXRlIHBpY2tlciAodGhlIHN0YXJ0IGRhdGUgb3IgdG9kYXkgaWYgbm8gc3RhcnQgZGF0ZSlcclxuICAgKi9cclxuICBnZXRNaW5FbmREYXRlKGluZGV4OiBudW1iZXIpOiBEYXRlIHwgbnVsbCB7XHJcbiAgICBjb25zdCBydWxlR3JvdXAgPSB0aGlzLnJ1bGVzQXJyYXkuYXQoaW5kZXgpIGFzIEZvcm1Hcm91cDtcclxuICAgIGNvbnN0IHN0YXJ0RGF0ZSA9IHJ1bGVHcm91cC5nZXQoJ3ZhbHVlU3RhcnQnKT8udmFsdWU7XHJcbiAgICBcclxuICAgIC8vIElmIHN0YXJ0IGRhdGUgaXMgc2VsZWN0ZWQsIHVzZSBpdCBhcyBtaW5pbXVtIGZvciBlbmQgZGF0ZVxyXG4gICAgLy8gT3RoZXJ3aXNlIHVzZSB0b2RheSdzIGRhdGVcclxuICAgIHJldHVybiBzdGFydERhdGUgPyBuZXcgRGF0ZShzdGFydERhdGUpIDogbmV3IERhdGUoKTtcclxuICB9XHJcbiAgXHJcbiAgLyoqXHJcbiAgICogSGFuZGxlcyBjaGFuZ2VzIHRvIHRoZSBzdGFydCBkYXRlXHJcbiAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgcnVsZSByb3dcclxuICAgKiBAcGFyYW0gZXZlbnQgVGhlIGRhdGUgY2hhbmdlIGV2ZW50XHJcbiAgICovXHJcbiAgb25TdGFydERhdGVDaGFuZ2UoaW5kZXg6IG51bWJlciwgZXZlbnQ6IGFueSk6IHZvaWQge1xyXG4gICAgY29uc3QgcnVsZUdyb3VwID0gdGhpcy5ydWxlc0FycmF5LmF0KGluZGV4KSBhcyBGb3JtR3JvdXA7XHJcbiAgICBjb25zdCBlbmREYXRlID0gcnVsZUdyb3VwLmdldCgndmFsdWVFbmQnKT8udmFsdWU7XHJcbiAgICBjb25zdCBzdGFydERhdGUgPSBldmVudC52YWx1ZTtcclxuICAgIFxyXG4gICAgLy8gSWYgZW5kIGRhdGUgaXMgYmVmb3JlIHN0YXJ0IGRhdGUsIHJlc2V0IGl0XHJcbiAgICBpZiAoZW5kRGF0ZSAmJiBzdGFydERhdGUgJiYgbmV3IERhdGUoZW5kRGF0ZSkgPCBuZXcgRGF0ZShzdGFydERhdGUpKSB7XHJcbiAgICAgIHJ1bGVHcm91cC5nZXQoJ3ZhbHVlRW5kJyk/LnNldFZhbHVlKG51bGwpO1xyXG4gICAgfVxyXG4gIH1cclxuICBcclxuICB1cGRhdGVGb3JtQ29udHJvbHNGb3JPcGVyYXRvcihpbmRleDogbnVtYmVyLCBvcGVyYXRvcjogc3RyaW5nLCBmaWVsZFR5cGU6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgY29uc3QgcnVsZUdyb3VwID0gdGhpcy5ydWxlc0FycmF5LmF0KGluZGV4KSBhcyBGb3JtR3JvdXA7XHJcbiAgICBcclxuICAgIC8vIEhhbmRsZSBkYXRlIHJhbmdlIGZvciAnYmV0d2Vlbicgb3BlcmF0b3JcclxuICAgIGlmIChvcGVyYXRvciA9PT0gJ2JldHdlZW4nICYmIGZpZWxkVHlwZSA9PT0gJ2RhdGUnKSB7XHJcbiAgICAgIC8vIEFkZCBzdGFydCBhbmQgZW5kIGRhdGUgY29udHJvbHMgaWYgdGhleSBkb24ndCBleGlzdFxyXG4gICAgICBpZiAoIXJ1bGVHcm91cC5jb250YWlucygndmFsdWVTdGFydCcpKSB7XHJcbiAgICAgICAgcnVsZUdyb3VwLmFkZENvbnRyb2woJ3ZhbHVlU3RhcnQnLCB0aGlzLmZiLmNvbnRyb2wobnVsbCkpO1xyXG4gICAgICB9XHJcbiAgICAgIGlmICghcnVsZUdyb3VwLmNvbnRhaW5zKCd2YWx1ZUVuZCcpKSB7XHJcbiAgICAgICAgcnVsZUdyb3VwLmFkZENvbnRyb2woJ3ZhbHVlRW5kJywgdGhpcy5mYi5jb250cm9sKG51bGwpKTtcclxuICAgICAgfVxyXG4gICAgfSBlbHNlIHtcclxuICAgICAgLy8gUmVtb3ZlIHJhbmdlIGNvbnRyb2xzIGlmIHRoZXkgZXhpc3QgYW5kIGFyZW4ndCBuZWVkZWRcclxuICAgICAgaWYgKHJ1bGVHcm91cC5jb250YWlucygndmFsdWVTdGFydCcpKSB7XHJcbiAgICAgICAgcnVsZUdyb3VwLnJlbW92ZUNvbnRyb2woJ3ZhbHVlU3RhcnQnKTtcclxuICAgICAgfVxyXG4gICAgICBpZiAocnVsZUdyb3VwLmNvbnRhaW5zKCd2YWx1ZUVuZCcpKSB7XHJcbiAgICAgICAgcnVsZUdyb3VwLnJlbW92ZUNvbnRyb2woJ3ZhbHVlRW5kJyk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbiAgXHJcbiAgdHJhbnNmb3JtRm9ybVRvTW9kZWwoZm9ybVZhbHVlOiBhbnkpOiBRdWVyeUdyb3VwIHtcclxuICAgIHJldHVybiB7XHJcbiAgICAgIGNvbmRpdGlvbjogZm9ybVZhbHVlLmNvbmRpdGlvbixcclxuICAgICAgcnVsZXM6IGZvcm1WYWx1ZS5ydWxlcy5tYXAoKHJ1bGU6IGFueSkgPT4ge1xyXG4gICAgICAgIC8vIEhhbmRsZSBkYXRlIHJhbmdlIGZvciAnYmV0d2Vlbicgb3BlcmF0b3JcclxuICAgICAgICBpZiAocnVsZS5vcGVyYXRvciA9PT0gJ2JldHdlZW4nICYmIHRoaXMuZ2V0RmllbGRUeXBlKHJ1bGUuZmllbGQpID09PSAnZGF0ZScpIHtcclxuICAgICAgICAgIHJldHVybiB7XHJcbiAgICAgICAgICAgIGZpZWxkOiBydWxlLmZpZWxkLFxyXG4gICAgICAgICAgICBvcGVyYXRvcjogcnVsZS5vcGVyYXRvcixcclxuICAgICAgICAgICAgdmFsdWU6IHsgc3RhcnQ6IHJ1bGUudmFsdWVTdGFydCwgZW5kOiBydWxlLnZhbHVlRW5kIH0sXHJcbiAgICAgICAgICAgIGNvbmRpdGlvbjogcnVsZS5jb25kaXRpb25cclxuICAgICAgICAgIH07XHJcbiAgICAgICAgfVxyXG4gICAgICAgIFxyXG4gICAgICAgIC8vIFN0YW5kYXJkIGNhc2VcclxuICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgZmllbGQ6IHJ1bGUuZmllbGQsXHJcbiAgICAgICAgICBvcGVyYXRvcjogcnVsZS5vcGVyYXRvcixcclxuICAgICAgICAgIHZhbHVlOiBydWxlLnZhbHVlLFxyXG4gICAgICAgICAgY29uZGl0aW9uOiBydWxlLmNvbmRpdGlvblxyXG4gICAgICAgIH07XHJcbiAgICAgIH0pXHJcbiAgICB9O1xyXG4gIH1cclxuICBcclxuICAvKipcclxuICAgKiBHZXRzIHRoZSBjb25kaXRpb24gZm9yIGEgc3BlY2lmaWMgcm93XHJcbiAgICogQHBhcmFtIGluZGV4IFRoZSBpbmRleCBvZiB0aGUgcm93XHJcbiAgICogQHJldHVybnMgVGhlIGNvbmRpdGlvbiAoYW5kL29yKSBmb3IgdGhlIHJvd1xyXG4gICAqL1xyXG4gIGdldFJvd0NvbmRpdGlvbihpbmRleDogbnVtYmVyKTogJ2FuZCcgfCAnb3InIHtcclxuICAgIGlmIChpbmRleCA9PT0gMCkgcmV0dXJuICdhbmQnOyAvLyBGaXJzdCByb3cgZG9lc24ndCBoYXZlIGEgY29uZGl0aW9uXHJcbiAgICBcclxuICAgIGNvbnN0IHJ1bGVHcm91cCA9IHRoaXMucnVsZXNBcnJheS5hdChpbmRleCkgYXMgRm9ybUdyb3VwO1xyXG4gICAgcmV0dXJuIHJ1bGVHcm91cC5nZXQoJ2NvbmRpdGlvbicpPy52YWx1ZSB8fCAnYW5kJztcclxuICB9XHJcbiAgXHJcbiAgLyoqXHJcbiAgICogU2V0cyB0aGUgY29uZGl0aW9uIGZvciBhIHNwZWNpZmljIHJvd1xyXG4gICAqIEBwYXJhbSBpbmRleCBUaGUgaW5kZXggb2YgdGhlIHJvd1xyXG4gICAqIEBwYXJhbSBjb25kaXRpb24gVGhlIGNvbmRpdGlvbiB0byBzZXQgKGFuZC9vcilcclxuICAgKi9cclxuICBzZXRSb3dDb25kaXRpb24oaW5kZXg6IG51bWJlciwgY29uZGl0aW9uOiAnYW5kJyB8ICdvcicpOiB2b2lkIHtcclxuICAgIGlmIChpbmRleCA9PT0gMCkgcmV0dXJuOyAvLyBGaXJzdCByb3cgZG9lc24ndCBoYXZlIGEgY29uZGl0aW9uXHJcbiAgICBcclxuICAgIGNvbnN0IHJ1bGVHcm91cCA9IHRoaXMucnVsZXNBcnJheS5hdChpbmRleCkgYXMgRm9ybUdyb3VwO1xyXG4gICAgcnVsZUdyb3VwLmdldCgnY29uZGl0aW9uJyk/LnNldFZhbHVlKGNvbmRpdGlvbik7XHJcbiAgfVxyXG5cclxuICB0b2dnbGVDb25kaXRpb24oKTogdm9pZCB7XHJcbiAgICBjb25zdCBjdXJyZW50Q29uZGl0aW9uID0gdGhpcy5mb3JtLmdldCgnY29uZGl0aW9uJyk/LnZhbHVlO1xyXG4gICAgY29uc3QgbmV3Q29uZGl0aW9uID0gY3VycmVudENvbmRpdGlvbiA9PT0gJ2FuZCcgPyAnb3InIDogJ2FuZCc7XHJcbiAgICB0aGlzLmZvcm0uZ2V0KCdjb25kaXRpb24nKT8uc2V0VmFsdWUobmV3Q29uZGl0aW9uKTtcclxuICB9XHJcblxyXG4gIGdldENvbmRpdGlvbkxhYmVsKCk6IHN0cmluZyB7XHJcbiAgICByZXR1cm4gdGhpcy5mb3JtLmdldCgnY29uZGl0aW9uJyk/LnZhbHVlID09PSAnYW5kJyA/ICdBTkQnIDogJ09SJztcclxuICB9XHJcblxyXG4gIHJlc2V0UXVlcnkoKTogdm9pZCB7XHJcbiAgICB0aGlzLnJ1bGVzQXJyYXkuY2xlYXIoKTtcclxuICAgIHRoaXMuYWRkUnVsZSgpO1xyXG4gIH1cclxuXHJcbiAgYXBwbHlRdWVyeSgpOiB2b2lkIHtcclxuICAgIHRoaXMucXVlcnlDaGFuZ2UuZW1pdCh0aGlzLm1vZGVsKTtcclxuICB9XHJcbn1cclxuIiwiPGRpdiBjbGFzcz1cInNhLXF1ZXJ5LWJ1aWxkZXJcIj5cclxuICA8Zm9ybSBbZm9ybUdyb3VwXT1cImZvcm1cIj5cclxuICAgIDxkaXYgY2xhc3M9XCJxdWVyeS1idWlsZGVyLWhlYWRlclwiPlxyXG4gICAgICA8ZGl2IGNsYXNzPVwid2hlcmUtbGFiZWxcIj5XaGVyZTwvZGl2PlxyXG4gICAgPC9kaXY+XHJcblxyXG4gICAgPGRpdiBjbGFzcz1cInF1ZXJ5LWJ1aWxkZXItYm9keVwiPlxyXG4gICAgICA8ZGl2IGNsYXNzPVwicnVsZXMtY29udGFpbmVyXCIgZm9ybUFycmF5TmFtZT1cInJ1bGVzXCI+XHJcbiAgICAgICAgQGZvciAocnVsZSBvZiBydWxlc0FycmF5LmNvbnRyb2xzOyB0cmFjayAkaW5kZXgpIHtcclxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJydWxlLXJvd1wiIFtmb3JtR3JvdXBOYW1lXT1cIiRpbmRleFwiPlxyXG4gICAgICAgICAgICA8IS0tIENvbmRpdGlvbiBzZWxlY3RvciAoQW5kL09yKSAtLT5cclxuICAgICAgICAgICAgQGlmICgkaW5kZXggPiAwKSB7XHJcbiAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNvbmRpdGlvbi1zZWxlY3RvclwiPlxyXG4gICAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGFwcGVhcmFuY2U9XCJmaWxsXCI+XHJcbiAgICAgICAgICAgICAgICAgIDxtYXQtc2VsZWN0IFt2YWx1ZV09XCJnZXRSb3dDb25kaXRpb24oJGluZGV4KVwiIChzZWxlY3Rpb25DaGFuZ2UpPVwic2V0Um93Q29uZGl0aW9uKCRpbmRleCwgJGV2ZW50LnZhbHVlKVwiPlxyXG4gICAgICAgICAgICAgICAgICAgIDxtYXQtb3B0aW9uIHZhbHVlPVwiYW5kXCI+QW5kPC9tYXQtb3B0aW9uPlxyXG4gICAgICAgICAgICAgICAgICAgIDxtYXQtb3B0aW9uIHZhbHVlPVwib3JcIj5PcjwvbWF0LW9wdGlvbj5cclxuICAgICAgICAgICAgICAgICAgPC9tYXQtc2VsZWN0PlxyXG4gICAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cclxuICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgfSBAZWxzZSB7XHJcbiAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNvbmRpdGlvbi1wbGFjZWhvbGRlclwiPjwvZGl2PlxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIFxyXG4gICAgICAgICAgICA8IS0tIEZpZWxkIHNlbGVjdGlvbiAtLT5cclxuICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiZmllbGQtc2VsZWN0XCI+XHJcbiAgICAgICAgICAgICAgPG1hdC1sYWJlbD5TZWxlY3QgYSBmaWx0ZXI8L21hdC1sYWJlbD5cclxuICAgICAgICAgICAgICA8bWF0LXNlbGVjdCBmb3JtQ29udHJvbE5hbWU9XCJmaWVsZFwiIChzZWxlY3Rpb25DaGFuZ2UpPVwib25GaWVsZENoYW5nZSgkaW5kZXgsICRldmVudC52YWx1ZSlcIj5cclxuICAgICAgICAgICAgICAgIEBmb3IgKGZpZWxkIG9mIGNvbmZpZy5maWVsZHM7IHRyYWNrIGZpZWxkLmtleSkge1xyXG4gICAgICAgICAgICAgICAgICA8bWF0LW9wdGlvbiBbdmFsdWVdPVwiZmllbGQua2V5XCI+XHJcbiAgICAgICAgICAgICAgICAgICAge3sgZmllbGQubGFiZWwgfX1cclxuICAgICAgICAgICAgICAgICAgPC9tYXQtb3B0aW9uPlxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgIDwvbWF0LXNlbGVjdD5cclxuICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cclxuXHJcbiAgICAgICAgICAgIDwhLS0gT3BlcmF0b3Igc2VsZWN0aW9uIC0tPlxyXG4gICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJvcGVyYXRvci1zZWxlY3RcIj5cclxuICAgICAgICAgICAgICA8bWF0LXNlbGVjdCBmb3JtQ29udHJvbE5hbWU9XCJvcGVyYXRvclwiIChzZWxlY3Rpb25DaGFuZ2UpPVwib25PcGVyYXRvckNoYW5nZSgkaW5kZXgsICRldmVudC52YWx1ZSwgcnVsZS52YWx1ZS5maWVsZClcIj5cclxuICAgICAgICAgICAgICAgIEBmb3IgKG9wIG9mIGdldE9wZXJhdG9yc0ZvckZpZWxkKHJ1bGUudmFsdWUuZmllbGQpOyB0cmFjayBvcC52YWx1ZSkge1xyXG4gICAgICAgICAgICAgICAgICA8bWF0LW9wdGlvbiBbdmFsdWVdPVwib3AudmFsdWVcIj5cclxuICAgICAgICAgICAgICAgICAgICB7eyBvcC5sYWJlbCB9fVxyXG4gICAgICAgICAgICAgICAgICA8L21hdC1vcHRpb24+XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgPC9tYXQtc2VsZWN0PlxyXG4gICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxyXG5cclxuICAgICAgICAgICAgPCEtLSBWYWx1ZSBpbnB1dCBiYXNlZCBvbiBmaWVsZCB0eXBlIC0tPlxyXG4gICAgICAgICAgICBAc3dpdGNoIChnZXRGaWVsZFR5cGUocnVsZS52YWx1ZS5maWVsZCkpIHtcclxuICAgICAgICAgICAgICBAY2FzZSAoJ3N0cmluZycpIHtcclxuICAgICAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cInZhbHVlLWlucHV0XCI+XHJcbiAgICAgICAgICAgICAgICAgIDxpbnB1dCBtYXRJbnB1dCBmb3JtQ29udHJvbE5hbWU9XCJ2YWx1ZVwiIHBsYWNlaG9sZGVyPVwiRW50ZXIgYSB2YWx1ZS4uLlwiPlxyXG4gICAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgQGNhc2UgKCdudW1iZXInKSB7XHJcbiAgICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgY2xhc3M9XCJ2YWx1ZS1pbnB1dFwiPlxyXG4gICAgICAgICAgICAgICAgICA8aW5wdXQgbWF0SW5wdXQgdHlwZT1cIm51bWJlclwiIGZvcm1Db250cm9sTmFtZT1cInZhbHVlXCIgcGxhY2Vob2xkZXI9XCJFbnRlciBhIHZhbHVlLi4uXCI+XHJcbiAgICAgICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxyXG4gICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICBAY2FzZSAoJ2RhdGUnKSB7XHJcbiAgICAgICAgICAgICAgICBAaWYgKCFpc09wZXJhdG9yQmV0d2VlbigkaW5kZXgpKSB7XHJcbiAgICAgICAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cInZhbHVlLWlucHV0XCI+XHJcbiAgICAgICAgICAgICAgICAgICAgPGlucHV0IG1hdElucHV0IHR5cGU9XCJkYXRlXCIgW21hdERhdGVwaWNrZXJdPVwicGlja2VyXCIgZm9ybUNvbnRyb2xOYW1lPVwidmFsdWVcIiAoY2xpY2spPVwicGlja2VyLm9wZW4oKVwiPlxyXG4gICAgICAgICAgICAgICAgICAgIDxtYXQtZGF0ZXBpY2tlci10b2dnbGUgbWF0SWNvblN1ZmZpeCBbZm9yXT1cInBpY2tlclwiPjwvbWF0LWRhdGVwaWNrZXItdG9nZ2xlPlxyXG4gICAgICAgICAgICAgICAgICAgIDxtYXQtZGF0ZXBpY2tlciAjcGlja2VyPjwvbWF0LWRhdGVwaWNrZXI+XHJcbiAgICAgICAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XHJcbiAgICAgICAgICAgICAgICB9IEBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImRhdGUtcmFuZ2UtY29udGFpbmVyXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwidmFsdWUtaW5wdXQgc3RhcnQtZGF0ZVwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgPG1hdC1sYWJlbD5TdGFydCBkYXRlPC9tYXQtbGFiZWw+XHJcbiAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgbWF0SW5wdXQgW21hdERhdGVwaWNrZXJdPVwic3RhcnRQaWNrZXJcIiBmb3JtQ29udHJvbE5hbWU9XCJ2YWx1ZVN0YXJ0XCIgKGNsaWNrKT1cInN0YXJ0UGlja2VyLm9wZW4oKVwiIChkYXRlQ2hhbmdlKT1cIm9uU3RhcnREYXRlQ2hhbmdlKCRpbmRleCwgJGV2ZW50KVwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgPG1hdC1kYXRlcGlja2VyLXRvZ2dsZSBtYXRJY29uU3VmZml4IFtmb3JdPVwic3RhcnRQaWNrZXJcIj48L21hdC1kYXRlcGlja2VyLXRvZ2dsZT5cclxuICAgICAgICAgICAgICAgICAgICAgIDxtYXQtZGF0ZXBpY2tlciAjc3RhcnRQaWNrZXI+PC9tYXQtZGF0ZXBpY2tlcj5cclxuICAgICAgICAgICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxyXG4gICAgICAgICAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cInZhbHVlLWlucHV0IGVuZC1kYXRlXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICA8bWF0LWxhYmVsPkVuZCBkYXRlPC9tYXQtbGFiZWw+XHJcbiAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgbWF0SW5wdXQgW21hdERhdGVwaWNrZXJdPVwiZW5kUGlja2VyXCIgZm9ybUNvbnRyb2xOYW1lPVwidmFsdWVFbmRcIiAoY2xpY2spPVwiZW5kUGlja2VyLm9wZW4oKVwiIFttaW5dPVwiZ2V0TWluRW5kRGF0ZSgkaW5kZXgpXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICA8bWF0LWRhdGVwaWNrZXItdG9nZ2xlIG1hdEljb25TdWZmaXggW2Zvcl09XCJlbmRQaWNrZXJcIj48L21hdC1kYXRlcGlja2VyLXRvZ2dsZT5cclxuICAgICAgICAgICAgICAgICAgICAgIDxtYXQtZGF0ZXBpY2tlciAjZW5kUGlja2VyIFtzdGFydEF0XT1cImdldE1pbkVuZERhdGUoJGluZGV4KVwiPjwvbWF0LWRhdGVwaWNrZXI+XHJcbiAgICAgICAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cclxuICAgICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgIEBjYXNlICgnYm9vbGVhbicpIHtcclxuICAgICAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cInZhbHVlLWlucHV0XCI+XHJcbiAgICAgICAgICAgICAgICAgIDxtYXQtc2VsZWN0IGZvcm1Db250cm9sTmFtZT1cInZhbHVlXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgPG1hdC1vcHRpb24gW3ZhbHVlXT1cInRydWVcIj5UcnVlPC9tYXQtb3B0aW9uPlxyXG4gICAgICAgICAgICAgICAgICAgIDxtYXQtb3B0aW9uIFt2YWx1ZV09XCJmYWxzZVwiPkZhbHNlPC9tYXQtb3B0aW9uPlxyXG4gICAgICAgICAgICAgICAgICA8L21hdC1zZWxlY3Q+XHJcbiAgICAgICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxyXG4gICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICBAY2FzZSAoJ3NlbGVjdCcpIHtcclxuICAgICAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cInZhbHVlLWlucHV0XCI+XHJcbiAgICAgICAgICAgICAgICAgIDxtYXQtc2VsZWN0IGZvcm1Db250cm9sTmFtZT1cInZhbHVlXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgQGZvciAob3B0aW9uIG9mIGdldEZpZWxkT3B0aW9ucyhydWxlLnZhbHVlLmZpZWxkKTsgdHJhY2sgb3B0aW9uLnZhbHVlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICA8bWF0LW9wdGlvbiBbdmFsdWVdPVwib3B0aW9uLnZhbHVlXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHt7IG9wdGlvbi5sYWJlbCB9fVxyXG4gICAgICAgICAgICAgICAgICAgICAgPC9tYXQtb3B0aW9uPlxyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgPC9tYXQtc2VsZWN0PlxyXG4gICAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgQGRlZmF1bHQge1xyXG4gICAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwidmFsdWUtaW5wdXRcIj5cclxuICAgICAgICAgICAgICAgICAgPGlucHV0IG1hdElucHV0IGZvcm1Db250cm9sTmFtZT1cInZhbHVlXCIgcGxhY2Vob2xkZXI9XCJFbnRlciBhIHZhbHVlLi4uXCI+XHJcbiAgICAgICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxyXG4gICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgPCEtLSBSZW1vdmUgcnVsZSBidXR0b24gLS0+XHJcbiAgICAgICAgICAgIDxidXR0b24gbWF0LWljb24tYnV0dG9uIGNsYXNzPVwicmVtb3ZlLXJ1bGUtYnRuXCIgXHJcbiAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cInJlbW92ZVJ1bGUoJGluZGV4KVwiIFxyXG4gICAgICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCJydWxlc0FycmF5Lmxlbmd0aCA9PT0gMVwiXHJcbiAgICAgICAgICAgICAgICAgICAgbWF0VG9vbHRpcD1cIlJlbW92ZSBmaWx0ZXJcIj5cclxuICAgICAgICAgICAgICA8bWF0LWljb24+Y2xvc2U8L21hdC1pY29uPlxyXG4gICAgICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgIH1cclxuICAgICAgPC9kaXY+XHJcblxyXG4gICAgICA8IS0tIEFkZCBydWxlIGJ1dHRvbiAtLT5cclxuICAgICAgPGRpdiBjbGFzcz1cImFkZC1ydWxlLWNvbnRhaW5lclwiPlxyXG4gICAgICAgIDxidXR0b24gbWF0LWJ1dHRvbiBjb2xvcj1cInByaW1hcnlcIiBjbGFzcz1cImFkZC1ydWxlLWJ0blwiIChjbGljayk9XCJhZGRSdWxlKClcIj5cclxuICAgICAgICAgIDxtYXQtaWNvbj5hZGQ8L21hdC1pY29uPiBBZGQgYSBmaWx0ZXJcclxuICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgPC9kaXY+XHJcbiAgICA8L2Rpdj5cclxuXHJcbiAgICA8ZGl2IGNsYXNzPVwicXVlcnktYnVpbGRlci1mb290ZXJcIj5cclxuICAgICAgPGJ1dHRvbiBtYXQtYnV0dG9uIGNsYXNzPVwicmVzZXQtYnRuXCIgKGNsaWNrKT1cInJlc2V0UXVlcnkoKVwiPlJlc2V0PC9idXR0b24+XHJcbiAgICAgIDxidXR0b24gbWF0LXJhaXNlZC1idXR0b24gY29sb3I9XCJwcmltYXJ5XCIgY2xhc3M9XCJhcHBseS1idG5cIiAoY2xpY2spPVwiYXBwbHlRdWVyeSgpXCI+QXBwbHkgZmlsdGVyczwvYnV0dG9uPlxyXG4gICAgPC9kaXY+XHJcbiAgPC9mb3JtPlxyXG48L2Rpdj5cclxuIl19