@firestitch/app-acl 13.0.0 → 15.0.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.
Files changed (65) hide show
  1. package/app/components/acl-entries/acl-entries.component.d.ts +33 -33
  2. package/app/components/acl-entry/acl-entry.component.d.ts +31 -31
  3. package/app/components/acl-object-roles/acl-object-roles.component.d.ts +18 -18
  4. package/app/components/acl-permission-popover/acl-permission-popover.component.d.ts +12 -12
  5. package/app/components/acl-role/acl-role.component.d.ts +56 -56
  6. package/app/components/acl-role-popover/acl-role-popover.component.d.ts +13 -13
  7. package/app/components/acl-roles/acl-roles.component.d.ts +38 -38
  8. package/app/consts/acl-role-accesses.d.ts +5 -5
  9. package/app/enums/acl-role-access.d.ts +6 -6
  10. package/app/fs-app-acl.module.d.ts +33 -33
  11. package/app/injectors/app-acl-config.injector.d.ts +2 -2
  12. package/app/interfaces/acl-entry-data.d.ts +11 -11
  13. package/app/interfaces/acl-entry.d.ts +18 -18
  14. package/app/interfaces/acl-level.d.ts +3 -3
  15. package/app/interfaces/acl-object-entry.d.ts +11 -11
  16. package/app/interfaces/acl-object-role.d.ts +6 -6
  17. package/app/interfaces/acl-object.d.ts +4 -4
  18. package/app/interfaces/acl-permission.d.ts +7 -7
  19. package/app/interfaces/acl-role-config.d.ts +5 -5
  20. package/app/interfaces/acl-role.d.ts +16 -16
  21. package/app/interfaces/app-acl-config.d.ts +7 -7
  22. package/app/interfaces/index.d.ts +2 -2
  23. package/app/interfaces/name-value.d.ts +4 -4
  24. package/app/interfaces/role-config.d.ts +12 -12
  25. package/app/pipes/acl-role-permission-available.pipe.d.ts +7 -7
  26. package/app/pipes/bulk-options-filter.pipe.d.ts +13 -13
  27. package/app/pipes/index.d.ts +2 -2
  28. package/app/services/app-acl.service.d.ts +16 -16
  29. package/esm2020/app/components/acl-entries/acl-entries.component.mjs +174 -174
  30. package/esm2020/app/components/acl-entry/acl-entry.component.mjs +93 -93
  31. package/esm2020/app/components/acl-object-roles/acl-object-roles.component.mjs +52 -52
  32. package/esm2020/app/components/acl-permission-popover/acl-permission-popover.component.mjs +29 -29
  33. package/esm2020/app/components/acl-role/acl-role.component.mjs +254 -254
  34. package/esm2020/app/components/acl-role-popover/acl-role-popover.component.mjs +34 -34
  35. package/esm2020/app/components/acl-roles/acl-roles.component.mjs +170 -170
  36. package/esm2020/app/consts/acl-role-accesses.mjs +7 -7
  37. package/esm2020/app/enums/acl-role-access.mjs +7 -7
  38. package/esm2020/app/fs-app-acl.module.mjs +127 -129
  39. package/esm2020/app/injectors/app-acl-config.injector.mjs +2 -2
  40. package/esm2020/app/interfaces/acl-entry-data.mjs +1 -1
  41. package/esm2020/app/interfaces/acl-entry.mjs +1 -1
  42. package/esm2020/app/interfaces/acl-level.mjs +1 -1
  43. package/esm2020/app/interfaces/acl-object-entry.mjs +1 -1
  44. package/esm2020/app/interfaces/acl-object-role.mjs +1 -1
  45. package/esm2020/app/interfaces/acl-object.mjs +1 -1
  46. package/esm2020/app/interfaces/acl-permission.mjs +1 -1
  47. package/esm2020/app/interfaces/acl-role-config.mjs +1 -1
  48. package/esm2020/app/interfaces/acl-role.mjs +1 -1
  49. package/esm2020/app/interfaces/app-acl-config.mjs +1 -1
  50. package/esm2020/app/interfaces/index.mjs +2 -2
  51. package/esm2020/app/interfaces/name-value.mjs +1 -1
  52. package/esm2020/app/interfaces/role-config.mjs +1 -1
  53. package/esm2020/app/pipes/acl-role-permission-available.pipe.mjs +21 -21
  54. package/esm2020/app/pipes/bulk-options-filter.pipe.mjs +27 -27
  55. package/esm2020/app/pipes/index.mjs +2 -2
  56. package/esm2020/app/services/app-acl.service.mjs +51 -51
  57. package/esm2020/firestitch-app-acl.mjs +4 -4
  58. package/esm2020/public_api.mjs +10 -10
  59. package/fesm2015/firestitch-app-acl.mjs +887 -889
  60. package/fesm2015/firestitch-app-acl.mjs.map +1 -1
  61. package/fesm2020/firestitch-app-acl.mjs +900 -902
  62. package/fesm2020/firestitch-app-acl.mjs.map +1 -1
  63. package/{firestitch-app-acl.d.ts → index.d.ts} +5 -5
  64. package/package.json +3 -3
  65. package/public_api.d.ts +20 -20
@@ -1,254 +1,254 @@
1
- import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Inject, ViewChild } from '@angular/core';
2
- import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
3
- import { AclRoleAccesses } from './../../consts/acl-role-accesses';
4
- import { takeUntil, tap } from 'rxjs/operators';
5
- import { FsMessage } from '@firestitch/message';
6
- import { list } from '@firestitch/common';
7
- import { FsListComponent } from '@firestitch/list';
8
- import { forkJoin, of, Subject } from 'rxjs';
9
- import { FsAppAclService } from './../../services/app-acl.service';
10
- import { AclRoleAccess } from '../../enums/acl-role-access';
11
- import { MatButton } from '@angular/material/button';
12
- import * as i0 from "@angular/core";
13
- import * as i1 from "./../../services/app-acl.service";
14
- import * as i2 from "@angular/material/dialog";
15
- import * as i3 from "@firestitch/message";
16
- import * as i4 from "@firestitch/dialog";
17
- import * as i5 from "@angular/material/form-field";
18
- import * as i6 from "@firestitch/label";
19
- import * as i7 from "@firestitch/radiogroup";
20
- import * as i8 from "@angular/material/radio";
21
- import * as i9 from "@angular/material/checkbox";
22
- import * as i10 from "@angular/material/select";
23
- import * as i11 from "@angular/material/core";
24
- import * as i12 from "@firestitch/list";
25
- import * as i13 from "@firestitch/menu";
26
- import * as i14 from "@angular/material/button";
27
- import * as i15 from "@angular/forms";
28
- import * as i16 from "@firestitch/form";
29
- import * as i17 from "@angular/common";
30
- import * as i18 from "@angular/material/input";
31
- import * as i19 from "../../pipes/bulk-options-filter.pipe";
32
- import * as i20 from "../../pipes/acl-role-permission-available.pipe";
33
- export class FsAclRoleComponent {
34
- constructor(_data, _appAclService, _dialogRef, _message, _cdRef) {
35
- this._data = _data;
36
- this._appAclService = _appAclService;
37
- this._dialogRef = _dialogRef;
38
- this._message = _message;
39
- this._cdRef = _cdRef;
40
- this.aclRole = null;
41
- this.permissions = [];
42
- this.levelPermissions = [];
43
- this.AclRoleAccesses = AclRoleAccesses;
44
- this.indexedAccesses = {};
45
- this.aclLevels = [];
46
- this.indexedAclLevels = {};
47
- this.onlyFullAccess = false;
48
- this.AclLevels = {};
49
- this.roleConfigs = [];
50
- this.aclRoleConfigValues = {};
51
- this.aclRolePermissions = {};
52
- this._destroy$ = new Subject();
53
- this.save = () => {
54
- const aclRoleConfigs = this.roleConfigs
55
- .map((roleConfig) => {
56
- return {
57
- name: roleConfig.name,
58
- value: this.aclRoleConfigValues[roleConfig.name],
59
- };
60
- });
61
- const aclRole = {
62
- ...this.aclRole,
63
- permissions: this.levelPermissions.map((permission) => {
64
- return {
65
- value: permission.value,
66
- access: this.aclRolePermissions[permission.value] || 0,
67
- };
68
- }),
69
- aclRoleConfigs,
70
- };
71
- return this._data.saveAclRole(aclRole)
72
- .pipe(tap((response) => {
73
- this._message.success('Saved Changes');
74
- this.close(response);
75
- }));
76
- };
77
- }
78
- ngOnInit() {
79
- forkJoin(this.getRole(), this._appAclService.getPermissions())
80
- .pipe(takeUntil(this._destroy$))
81
- .subscribe(([aclRole, aclPermissions,]) => {
82
- this.permissions = aclPermissions;
83
- this.aclLevels = this._data.aclLevels;
84
- this.disabled = this._data.disabled;
85
- this.indexedAclLevels = list(this.aclLevels, 'name', 'value');
86
- this.indexedAccesses = list(AclRoleAccesses, 'name', 'value');
87
- this.aclRole = {
88
- ...{
89
- aclPermissions: [],
90
- allPermissions: true,
91
- aclRoleConfigs: [],
92
- permissions: {},
93
- level: this.aclLevels[0].value,
94
- },
95
- ...aclRole,
96
- };
97
- this.aclRoleConfigValues = (aclRole.aclRoleConfigs || [])
98
- .reduce((accum, aclRoleConfig) => {
99
- return {
100
- ...accum,
101
- [aclRoleConfig.name]: aclRoleConfig.value,
102
- };
103
- }, {});
104
- if (this.aclRole.id) {
105
- this.permissions.forEach((permission) => {
106
- let access = 0;
107
- const aclPermission = this.aclRole.aclPermissions.find((item) => {
108
- return item.permission === permission.value;
109
- });
110
- if (aclPermission) {
111
- access = aclPermission.access;
112
- }
113
- this.aclRolePermissions[permission.value] = access;
114
- });
115
- }
116
- if (this.aclRole.allPermissions) {
117
- this._applyMaxPermissionAccess();
118
- }
119
- this._updatePermissions();
120
- this._updateRoleConfigs();
121
- this._cdRef.markForCheck();
122
- });
123
- this.listConfig = {
124
- status: false,
125
- paging: false,
126
- rowHighlight: false,
127
- noResults: {
128
- message: '',
129
- },
130
- group: {
131
- initialExpand: true,
132
- groupBy: (data) => {
133
- return data;
134
- },
135
- compareBy: (data) => {
136
- return data.category || 'General';
137
- },
138
- },
139
- fetch: () => {
140
- return of({
141
- data: this.levelPermissions.sort((a, b) => {
142
- a = a.name.toUpperCase();
143
- b = b.name.toUpperCase();
144
- if (a < b) {
145
- return -1;
146
- }
147
- else if (a > b) {
148
- return 1;
149
- }
150
- return 0;
151
- }),
152
- });
153
- },
154
- };
155
- }
156
- bulkChange(value, groupChildren, group) {
157
- groupChildren
158
- .forEach((permission) => {
159
- const access = permission.accesses
160
- .find((access) => value === access);
161
- if (access || !value) {
162
- this.aclRolePermissions[permission.value] = value;
163
- }
164
- });
165
- setTimeout(() => {
166
- this.submitButton.disabled = false;
167
- this.permissionChange();
168
- });
169
- }
170
- permissionChange() {
171
- this.aclRolePermissions = {
172
- ...this.aclRolePermissions,
173
- };
174
- this._cdRef.markForCheck();
175
- }
176
- levelChange() {
177
- this._updatePermissions();
178
- this._updateRoleConfigs();
179
- this.list.reload();
180
- }
181
- getRole() {
182
- if (!this._data.aclRole.id) {
183
- return of(this._data.aclRole);
184
- }
185
- const query = {
186
- aclPermissions: true,
187
- aclRoleConfigs: true,
188
- };
189
- if (!this.environment) {
190
- query.environmentId = null;
191
- }
192
- return this._data.loadAclRole(this._data.aclRole, query);
193
- }
194
- close(data = null) {
195
- this._dialogRef.close(data);
196
- }
197
- allPermissionsChange(all) {
198
- this._updatePermissions();
199
- if (all) {
200
- this._applyMaxPermissionAccess();
201
- }
202
- else {
203
- this._applyNonePermissionAccess();
204
- }
205
- }
206
- ngOnDestroy() {
207
- this._destroy$.next();
208
- this._destroy$.complete();
209
- }
210
- _updatePermissions() {
211
- this.levelPermissions = this.permissions
212
- .filter((permission) => {
213
- return permission.levels.some((item) => {
214
- return item === this.aclRole.level;
215
- });
216
- });
217
- }
218
- _updateRoleConfigs() {
219
- if (this._data.loadRoleConfigs) {
220
- this._data.loadRoleConfigs()
221
- .subscribe((roleConfigs) => {
222
- this.roleConfigs = roleConfigs
223
- .filter((roleConfig) => roleConfig.level === this.aclRole.level);
224
- this._cdRef.markForCheck();
225
- });
226
- }
227
- }
228
- _applyMaxPermissionAccess() {
229
- this.permissions.forEach((permission) => {
230
- this.aclRolePermissions[permission.value] = Math.max(...permission.accesses);
231
- });
232
- }
233
- _applyNonePermissionAccess() {
234
- this.permissions.forEach((permission) => {
235
- this.aclRolePermissions[permission.value] = AclRoleAccess.None;
236
- });
237
- }
238
- }
239
- FsAclRoleComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: FsAclRoleComponent, deps: [{ token: MAT_DIALOG_DATA }, { token: i1.FsAppAclService }, { token: i2.MatDialogRef }, { token: i3.FsMessage }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
240
- FsAclRoleComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: FsAclRoleComponent, selector: "ng-component", viewQueries: [{ propertyName: "list", first: true, predicate: FsListComponent, descendants: true }, { propertyName: "submitButton", first: true, predicate: ["submit"], descendants: true }], ngImport: i0, template: "<form fsForm [submit]=\"save\">\n <fs-dialog>\n <ng-container *ngIf=\"aclRole\">\n <div mat-dialog-title>\n <ng-container *ngIf=\"!disabled\">{{ aclRole.id ? 'Edit' : 'Create' }}</ng-container>\n <ng-container *ngIf=\"disabled\">View</ng-container>\n Role\n </div>\n <mat-dialog-content>\n <div class=\"fs-row.gap-large.align-start\">\n <div class=\"fs-column left-column\">\n <mat-form-field> \n <mat-label>Name</mat-label>\n <input\n matInput\n [(ngModel)]=\"aclRole.name\"\n [disabled]=\"disabled\"\n name=\"name\"\n fsFormRequired>\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Description</mat-label>\n <input\n matInput\n [(ngModel)]=\"aclRole.description\"\n [disabled]=\"disabled\"\n name=\"description\">\n </mat-form-field>\n\n <fs-label-field *ngIf=\"aclRole.id || aclLevels.length === 1; else levels\">\n <fs-label>Level</fs-label>\n {{indexedAclLevels[aclRole.level]}}\n </fs-label-field>\n\n <ng-template #levels>\n <div class=\"level\">\n <fs-radio-group\n [(ngModel)]=\"aclRole.level\"\n [disabled]=\"disabled\"\n (ngModelChange)=\"levelChange()\"\n fsFormRequired\n label=\"Level\"\n orientation=\"vertical\"\n name=\"level\">\n <mat-radio-button\n *ngFor=\"let item of aclLevels\"\n [value]=\"item.value\"\n [disabled]=\"!!aclRole.protected\">\n {{ item.name }}\n </mat-radio-button>\n </fs-radio-group>\n </div>\n </ng-template>\n\n <fs-label-field *ngIf=\"levelPermissions.length\">\n <fs-label>All Permissions</fs-label>\n <mat-checkbox\n [(ngModel)]=\"aclRole.allPermissions\"\n (ngModelChange)=\"allPermissionsChange($event)\"\n [disabled]=\"!!aclRole.protected || disabled\"\n name=\"allPermissions\">\n Enable\n </mat-checkbox>\n </fs-label-field>\n\n <div class=\"fs-column\" *ngFor=\"let roleConfig of roleConfigs\">\n <fs-label-field *ngIf=\"roleConfig.type === 'checkbox'\">\n <fs-label>{{roleConfig.label}}</fs-label>\n <mat-checkbox\n [(ngModel)]=\"aclRoleConfigValues[roleConfig.name]\"\n [disabled]=\"disabled\"\n [name]=\"roleConfig.name\">\n Enable\n </mat-checkbox>\n <fs-label-message>\n <mat-hint>{{roleConfig.description}}</mat-hint>\n </fs-label-message>\n </fs-label-field>\n\n <mat-form-field *ngIf=\"roleConfig.type === 'select'\">\n <mat-select\n [(ngModel)]=\"aclRoleConfigValues[roleConfig.name]\"\n [name]=\"roleConfig.name\"\n [required]=\"roleConfig.required\"\n [disabled]=\"disabled\"\n [placeholder]=\"roleConfig.label\">\n <mat-option\n *ngFor=\"let item of roleConfig.values\"\n [value]=\"item.value\">\n {{ item.name }}\n </mat-option>\n </mat-select>\n <mat-hint>{{roleConfig.description}}</mat-hint>\n </mat-form-field>\n </div>\n </div>\n\n <div *ngIf=\"aclRole.level\" [hidden]=\"!levelPermissions.length\" class=\"permissions fs-column\">\n <fs-list [config]=\"listConfig\">\n <fs-list-column title=\"Permissions\">\n <ng-template fs-list-group-cell let-row=\"row\" class=\"permission-group\">\n <div class=\"permission-group\">{{row.category || 'General'}}</div>\n </ng-template>\n <ng-template fs-list-cell let-row=\"row\">\n <div class=\"permission\">{{ row.name }}</div>\n <div class=\"description small\">{{ row.description }}</div>\n </ng-template>\n </fs-list-column>\n <fs-list-column title=\"Access\" width=\"1%\" class=\"access\">\n <ng-template \n fs-list-group-cell\n let-row=\"row\"\n let-group=\"group\"\n let-groupChildren=\"groupChildren\"\n class=\"permission-group\"\n align=\"right\">\n <ng-container *ngIf=\"!aclRole.allPermissions && !disabled\">\n <fs-menu>\n <ng-container *ngFor=\"let access of AclRoleAccesses | builkOptionsFilter: groupChildren\">\n <ng-template\n fs-menu-item\n (click)=\"bulkChange(access.value, groupChildren, group)\">\n {{ access.name }}\n </ng-template>\n </ng-container>\n </fs-menu>\n </ng-container>\n </ng-template>\n <ng-template fs-list-cell let-row=\"permission\" let-permission=\"row\">\n <span *ngIf=\"aclRole.allPermissions || disabled; else elseAll\">\n {{indexedAccesses[aclRolePermissions[permission.value]]}}\n </span>\n <ng-template #elseAll>\n <ng-container *ngIf=\"permission|aclRolePermissionAvailable:aclRolePermissions; else permissionRequires\">\n <mat-form-field>\n <mat-select\n [(ngModel)]=\"aclRolePermissions[permission.value]\"\n [disabled]=\"!!aclRole.protected\"\n required\n [name]=\"'access-' + permission.value\"\n (ngModelChange)=\"permissionChange()\">\n <ng-container *ngFor=\"let access of AclRoleAccesses\">\n <mat-option\n *ngIf=\"access.value === 0 || permission.accesses.indexOf(access.value) !== -1\"\n [value]=\"access.value\">\n {{access.name}}\n </mat-option>\n </ng-container>\n </mat-select>\n </mat-form-field>\n </ng-container>\n <ng-template #permissionRequires>\n Unavailable\n </ng-template>\n </ng-template>\n </ng-template>\n </fs-list-column>\n </fs-list>\n </div>\n </div>\n </mat-dialog-content>\n <mat-dialog-actions>\n <button\n *ngIf=\"!disabled\"\n #submit\n mat-button\n type=\"submit\"\n color=\"primary\">\n {{ aclRole.id ? 'Save' : 'Create' }}\n </button>\n <button mat-button [mat-dialog-close]=\"null\" type=\"button\">{{ disabled ? 'Done' : 'Cancel' }}</button>\n </mat-dialog-actions>\n </ng-container>\n </fs-dialog>\n</form>\n", styles: [".permissions{flex:1}.permissions ::ng-deep .fs-list-row-group{background-color:#e4e4e4;font-size:112%}.permissions ::ng-deep fs-list .access{white-space:nowrap}.permissions ::ng-deep .mat-form-field{width:100px}.permissions ::ng-deep .mat-form-field .mat-form-field-wrapper{padding-bottom:0}.permissions ::ng-deep .mat-form-field .mat-form-field-infix{border-top:0}.permissions ::ng-deep .mat-form-field .mat-form-field-underline{bottom:0}.permissions ::ng-deep fs-radio-group{width:100%}.permissions ::ng-deep fs-label-field{width:100%}.permissions .level{width:100%}.left-column{width:40%;max-width:400px}\n"], components: [{ type: i4.FsDialogComponent, selector: "fs-dialog", inputs: ["mobileMode", "mobileButtonPlacement", "mobileWidth", "mode", "buttonLayout"] }, { type: i5.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { type: i6.FsLabelFieldComponent, selector: "fs-label-field", inputs: ["bottomMargin", "topMargin", "labelMargin"] }, { type: i6.FsLabelComponent, selector: "fs-label" }, { type: i7.FsRadioGroupComponent, selector: "fs-radio-group", inputs: ["orientation", "label", "name", "disabled", "radioPosition", "compareWith", "required"] }, { type: i8.MatRadioButton, selector: "mat-radio-button", inputs: ["disableRipple", "tabIndex"], exportAs: ["matRadioButton"] }, { type: i9.MatCheckbox, selector: "mat-checkbox", inputs: ["disableRipple", "color", "tabIndex", "aria-label", "aria-labelledby", "aria-describedby", "id", "required", "labelPosition", "name", "value", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { type: i6.FsLabelMessageComponent, selector: "fs-label-message" }, { type: i10.MatSelect, selector: "mat-select", inputs: ["disabled", "disableRipple", "tabIndex"], exportAs: ["matSelect"] }, { type: i11.MatOption, selector: "mat-option", exportAs: ["matOption"] }, { type: i12.FsListComponent, selector: "fs-list", inputs: ["config", "loaderLines"], outputs: ["filtersReady"] }, { type: i13.FsMenuComponent, selector: "fs-menu", inputs: ["class", "buttonClass", "buttonType", "buttonColor"], outputs: ["opened", "closed"] }, { type: i14.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }], directives: [{ type: i15.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { type: i15.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i15.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i16.FsFormDirective, selector: "[fsForm]", inputs: ["wrapperSelector", "messageSelector", "hintSelector", "labelSelector", "autocomplete", "shortcuts", "confirm", "confirmDialog", "confirmDrawer", "confirmBrowser", "confirmTabs", "dirtySubmitButton", "submit", "successDelay", "errorDelay", "tabGroup", "deactivationGuard"], outputs: ["fsForm", "invalid", "valid", "submitted", "reseted", "cleared"], exportAs: ["fsForm"] }, { type: i17.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i2.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { type: i2.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { type: i5.MatLabel, selector: "mat-label" }, { type: i18.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"] }, { type: i15.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { type: i16.FsFormRequiredDirective, selector: "[fsFormRequired],[ngModel][required]", inputs: ["fsFormRequired", "required", "fsFormRequiredMessage"] }, { type: i15.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i15.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { type: i16.FsFormNoFsValidatorsDirective, selector: "[ngModel]:not([required]):not([fsFormRequired]):not([fsFormCompare]):not([fsFormDateRange]):not([fsFormEmail]):not([fsFormEmails]):not([fsFormFunction]):not([fsFormGreater]):not([fsFormInteger]):not([fsFormLesser]):not([fsFormMax]):not([fsFormMaxLength]):not([fsFormMin]):not([fsFormMinLength]):not([fsFormNumeric]):not([fsFormPattern]):not([fsFormPhone]):not([fsFormUrl]):not([validate])" }, { type: i17.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i5.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { type: i15.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { type: i12.FsListColumnDirective, selector: "fs-list-column", inputs: ["show", "title", "name", "customize", "sortable", "sortableDefault", "sortableDirection", "direction", "align", "width", "class"] }, { type: i12.FsListGroupHeaderDirective, selector: "[fs-list-group-cell],[fs-list-group-header]" }, { type: i12.FsListCellDirective, selector: "[fs-list-cell]", inputs: ["colspan", "align", "class"] }, { type: i13.FsMenuItemDirective, selector: "fs-menu-group,[fs-menu-item]" }, { type: i2.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]" }, { type: i16.FsButtonDirective, selector: "[mat-raised-button],[mat-button],[mat-flat-button],[mat-stroked-button]", inputs: ["name", "dirtySubmit", "form"] }, { type: i2.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }], pipes: { "builkOptionsFilter": i19.BulkOptionsFilterPipe, "aclRolePermissionAvailable": i20.AclRolePermissionAvailablePipe }, changeDetection: i0.ChangeDetectionStrategy.OnPush });
241
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: FsAclRoleComponent, decorators: [{
242
- type: Component,
243
- args: [{ changeDetection: ChangeDetectionStrategy.OnPush, template: "<form fsForm [submit]=\"save\">\n <fs-dialog>\n <ng-container *ngIf=\"aclRole\">\n <div mat-dialog-title>\n <ng-container *ngIf=\"!disabled\">{{ aclRole.id ? 'Edit' : 'Create' }}</ng-container>\n <ng-container *ngIf=\"disabled\">View</ng-container>\n Role\n </div>\n <mat-dialog-content>\n <div class=\"fs-row.gap-large.align-start\">\n <div class=\"fs-column left-column\">\n <mat-form-field> \n <mat-label>Name</mat-label>\n <input\n matInput\n [(ngModel)]=\"aclRole.name\"\n [disabled]=\"disabled\"\n name=\"name\"\n fsFormRequired>\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Description</mat-label>\n <input\n matInput\n [(ngModel)]=\"aclRole.description\"\n [disabled]=\"disabled\"\n name=\"description\">\n </mat-form-field>\n\n <fs-label-field *ngIf=\"aclRole.id || aclLevels.length === 1; else levels\">\n <fs-label>Level</fs-label>\n {{indexedAclLevels[aclRole.level]}}\n </fs-label-field>\n\n <ng-template #levels>\n <div class=\"level\">\n <fs-radio-group\n [(ngModel)]=\"aclRole.level\"\n [disabled]=\"disabled\"\n (ngModelChange)=\"levelChange()\"\n fsFormRequired\n label=\"Level\"\n orientation=\"vertical\"\n name=\"level\">\n <mat-radio-button\n *ngFor=\"let item of aclLevels\"\n [value]=\"item.value\"\n [disabled]=\"!!aclRole.protected\">\n {{ item.name }}\n </mat-radio-button>\n </fs-radio-group>\n </div>\n </ng-template>\n\n <fs-label-field *ngIf=\"levelPermissions.length\">\n <fs-label>All Permissions</fs-label>\n <mat-checkbox\n [(ngModel)]=\"aclRole.allPermissions\"\n (ngModelChange)=\"allPermissionsChange($event)\"\n [disabled]=\"!!aclRole.protected || disabled\"\n name=\"allPermissions\">\n Enable\n </mat-checkbox>\n </fs-label-field>\n\n <div class=\"fs-column\" *ngFor=\"let roleConfig of roleConfigs\">\n <fs-label-field *ngIf=\"roleConfig.type === 'checkbox'\">\n <fs-label>{{roleConfig.label}}</fs-label>\n <mat-checkbox\n [(ngModel)]=\"aclRoleConfigValues[roleConfig.name]\"\n [disabled]=\"disabled\"\n [name]=\"roleConfig.name\">\n Enable\n </mat-checkbox>\n <fs-label-message>\n <mat-hint>{{roleConfig.description}}</mat-hint>\n </fs-label-message>\n </fs-label-field>\n\n <mat-form-field *ngIf=\"roleConfig.type === 'select'\">\n <mat-select\n [(ngModel)]=\"aclRoleConfigValues[roleConfig.name]\"\n [name]=\"roleConfig.name\"\n [required]=\"roleConfig.required\"\n [disabled]=\"disabled\"\n [placeholder]=\"roleConfig.label\">\n <mat-option\n *ngFor=\"let item of roleConfig.values\"\n [value]=\"item.value\">\n {{ item.name }}\n </mat-option>\n </mat-select>\n <mat-hint>{{roleConfig.description}}</mat-hint>\n </mat-form-field>\n </div>\n </div>\n\n <div *ngIf=\"aclRole.level\" [hidden]=\"!levelPermissions.length\" class=\"permissions fs-column\">\n <fs-list [config]=\"listConfig\">\n <fs-list-column title=\"Permissions\">\n <ng-template fs-list-group-cell let-row=\"row\" class=\"permission-group\">\n <div class=\"permission-group\">{{row.category || 'General'}}</div>\n </ng-template>\n <ng-template fs-list-cell let-row=\"row\">\n <div class=\"permission\">{{ row.name }}</div>\n <div class=\"description small\">{{ row.description }}</div>\n </ng-template>\n </fs-list-column>\n <fs-list-column title=\"Access\" width=\"1%\" class=\"access\">\n <ng-template \n fs-list-group-cell\n let-row=\"row\"\n let-group=\"group\"\n let-groupChildren=\"groupChildren\"\n class=\"permission-group\"\n align=\"right\">\n <ng-container *ngIf=\"!aclRole.allPermissions && !disabled\">\n <fs-menu>\n <ng-container *ngFor=\"let access of AclRoleAccesses | builkOptionsFilter: groupChildren\">\n <ng-template\n fs-menu-item\n (click)=\"bulkChange(access.value, groupChildren, group)\">\n {{ access.name }}\n </ng-template>\n </ng-container>\n </fs-menu>\n </ng-container>\n </ng-template>\n <ng-template fs-list-cell let-row=\"permission\" let-permission=\"row\">\n <span *ngIf=\"aclRole.allPermissions || disabled; else elseAll\">\n {{indexedAccesses[aclRolePermissions[permission.value]]}}\n </span>\n <ng-template #elseAll>\n <ng-container *ngIf=\"permission|aclRolePermissionAvailable:aclRolePermissions; else permissionRequires\">\n <mat-form-field>\n <mat-select\n [(ngModel)]=\"aclRolePermissions[permission.value]\"\n [disabled]=\"!!aclRole.protected\"\n required\n [name]=\"'access-' + permission.value\"\n (ngModelChange)=\"permissionChange()\">\n <ng-container *ngFor=\"let access of AclRoleAccesses\">\n <mat-option\n *ngIf=\"access.value === 0 || permission.accesses.indexOf(access.value) !== -1\"\n [value]=\"access.value\">\n {{access.name}}\n </mat-option>\n </ng-container>\n </mat-select>\n </mat-form-field>\n </ng-container>\n <ng-template #permissionRequires>\n Unavailable\n </ng-template>\n </ng-template>\n </ng-template>\n </fs-list-column>\n </fs-list>\n </div>\n </div>\n </mat-dialog-content>\n <mat-dialog-actions>\n <button\n *ngIf=\"!disabled\"\n #submit\n mat-button\n type=\"submit\"\n color=\"primary\">\n {{ aclRole.id ? 'Save' : 'Create' }}\n </button>\n <button mat-button [mat-dialog-close]=\"null\" type=\"button\">{{ disabled ? 'Done' : 'Cancel' }}</button>\n </mat-dialog-actions>\n </ng-container>\n </fs-dialog>\n</form>\n", styles: [".permissions{flex:1}.permissions ::ng-deep .fs-list-row-group{background-color:#e4e4e4;font-size:112%}.permissions ::ng-deep fs-list .access{white-space:nowrap}.permissions ::ng-deep .mat-form-field{width:100px}.permissions ::ng-deep .mat-form-field .mat-form-field-wrapper{padding-bottom:0}.permissions ::ng-deep .mat-form-field .mat-form-field-infix{border-top:0}.permissions ::ng-deep .mat-form-field .mat-form-field-underline{bottom:0}.permissions ::ng-deep fs-radio-group{width:100%}.permissions ::ng-deep fs-label-field{width:100%}.permissions .level{width:100%}.left-column{width:40%;max-width:400px}\n"] }]
244
- }], ctorParameters: function () { return [{ type: undefined, decorators: [{
245
- type: Inject,
246
- args: [MAT_DIALOG_DATA]
247
- }] }, { type: i1.FsAppAclService }, { type: i2.MatDialogRef }, { type: i3.FsMessage }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { list: [{
248
- type: ViewChild,
249
- args: [FsListComponent]
250
- }], submitButton: [{
251
- type: ViewChild,
252
- args: ['submit', { static: false }]
253
- }] } });
254
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWNsLXJvbGUuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9jb21wb25lbnRzL2FjbC1yb2xlL2FjbC1yb2xlLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3NyYy9hcHAvY29tcG9uZW50cy9hY2wtcm9sZS9hY2wtcm9sZS5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsdUJBQXVCLEVBQ3ZCLGlCQUFpQixFQUNqQixTQUFTLEVBQ1QsTUFBTSxFQUdOLFNBQVMsRUFDVixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsZUFBZSxFQUFFLFlBQVksRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBRXpFLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxrQ0FBa0MsQ0FBQztBQUVuRSxPQUFPLEVBQUUsU0FBUyxFQUFFLEdBQUcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRWhELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUNoRCxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDMUMsT0FBTyxFQUFFLGVBQWUsRUFBZ0IsTUFBTSxrQkFBa0IsQ0FBQztBQUVqRSxPQUFPLEVBQUUsUUFBUSxFQUFjLEVBQUUsRUFBRSxPQUFPLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDekQsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBRW5FLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUM1RCxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sMEJBQTBCLENBQUM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFRckQsTUFBTSxPQUFPLGtCQUFrQjtJQTJCN0IsWUFDNEMsS0FBVSxFQUNuQyxjQUErQixFQUMvQixVQUE0QyxFQUM1QyxRQUFtQixFQUM1QixNQUF5QjtRQUpT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ZXRlY3RvclJlZixcbiAgQ29tcG9uZW50LFxuICBJbmplY3QsXG4gIE9uRGVzdHJveSxcbiAgT25Jbml0LFxuICBWaWV3Q2hpbGRcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBNQVRfRElBTE9HX0RBVEEsIE1hdERpYWxvZ1JlZiB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2RpYWxvZyc7XG5cbmltcG9ydCB7IEFjbFJvbGVBY2Nlc3NlcyB9IGZyb20gJy4vLi4vLi4vY29uc3RzL2FjbC1yb2xlLWFjY2Vzc2VzJztcbmltcG9ydCB7IEFjbFJvbGUgfSBmcm9tICcuLy4uLy4uL2ludGVyZmFjZXMvYWNsLXJvbGUnO1xuaW1wb3J0IHsgdGFrZVVudGlsLCB0YXAgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5cbmltcG9ydCB7IEZzTWVzc2FnZSB9IGZyb20gJ0BmaXJlc3RpdGNoL21lc3NhZ2UnO1xuaW1wb3J0IHsgbGlzdCB9IGZyb20gJ0BmaXJlc3RpdGNoL2NvbW1vbic7XG5pbXBvcnQgeyBGc0xpc3RDb21wb25lbnQsIEZzTGlzdENvbmZpZyB9IGZyb20gJ0BmaXJlc3RpdGNoL2xpc3QnO1xuXG5pbXBvcnQgeyBmb3JrSm9pbiwgT2JzZXJ2YWJsZSwgb2YsIFN1YmplY3QgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IEZzQXBwQWNsU2VydmljZSB9IGZyb20gJy4vLi4vLi4vc2VydmljZXMvYXBwLWFjbC5zZXJ2aWNlJztcbmltcG9ydCB7IFJvbGVDb25maWcgfSBmcm9tICcuLi8uLi9pbnRlcmZhY2VzJztcbmltcG9ydCB7IEFjbFJvbGVBY2Nlc3MgfSBmcm9tICcuLi8uLi9lbnVtcy9hY2wtcm9sZS1hY2Nlc3MnO1xuaW1wb3J0IHsgTWF0QnV0dG9uIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvYnV0dG9uJztcblxuXG5AQ29tcG9uZW50KHtcbiAgdGVtcGxhdGVVcmw6ICcuL2FjbC1yb2xlLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vYWNsLXJvbGUuY29tcG9uZW50LnNjc3MnXSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG59KVxuZXhwb3J0IGNsYXNzIEZzQWNsUm9sZUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25EZXN0cm95IHtcblxuICBAVmlld0NoaWxkKEZzTGlzdENvbXBvbmVudClcbiAgcHVibGljIGxpc3Q6IEZzTGlzdENvbXBvbmVudDtcblxuICBAVmlld0NoaWxkKCdzdWJtaXQnLCB7IHN0YXRpYzogZmFsc2UgfSlcbiAgcHVibGljIHN1Ym1pdEJ1dHRvbjogTWF0QnV0dG9uO1xuXG4gIHB1YmxpYyBhY2xSb2xlOiBBY2xSb2xlID0gbnVsbDtcbiAgcHVibGljIGVudmlyb25tZW50O1xuICBwdWJsaWMgcGVybWlzc2lvbnM6IGFueVtdID0gW107XG4gIHB1YmxpYyBsaXN0Q29uZmlnOiBGc0xpc3RDb25maWc7XG4gIHB1YmxpYyBsZXZlbFBlcm1pc3Npb25zID0gW107XG4gIHB1YmxpYyBBY2xSb2xlQWNjZXNzZXMgPSBBY2xSb2xlQWNjZXNzZXM7XG4gIHB1YmxpYyBpbmRleGVkQWNjZXNzZXMgPSB7fTtcbiAgcHVibGljIGFjbExldmVsczogYW55W10gPSBbXTtcbiAgcHVibGljIGluZGV4ZWRBY2xMZXZlbHMgPSB7fTtcbiAgcHVibGljIG9ubHlGdWxsQWNjZXNzID0gZmFsc2U7XG4gIHB1YmxpYyBBY2xMZXZlbHMgPSB7fTtcbiAgcHVibGljIHJvbGVDb25maWdzOiBSb2xlQ29uZmlnW10gPSBbXTtcbiAgcHVibGljIGFjbFJvbGVDb25maWdWYWx1ZXMgPSB7fTtcbiAgcHVibGljIGFjbFJvbGVQZXJtaXNzaW9ucyA9IHt9O1xuICBwdWJsaWMgbG9hZFJvbGVDb25maWdzOiAoYWNsUm9sZTogQWNsUm9sZSwgcXVlcnkpID0+IE9ic2VydmFibGU8Um9sZUNvbmZpZ1tdPjtcbiAgcHVibGljIGRpc2FibGVkOiBib29sZWFuO1xuXG4gIHByaXZhdGUgX2Rlc3Ryb3kkID0gbmV3IFN1YmplY3QoKTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBASW5qZWN0KE1BVF9ESUFMT0dfREFUQSkgcHJpdmF0ZSByZWFkb25seSBfZGF0YTogYW55LFxuICAgIHByaXZhdGUgcmVhZG9ubHkgX2FwcEFjbFNlcnZpY2U6IEZzQXBwQWNsU2VydmljZSxcbiAgICBwcml2YXRlIHJlYWRvbmx5IF9kaWFsb2dSZWY6IE1hdERpYWxvZ1JlZjxGc0FjbFJvbGVDb21wb25lbnQ+LFxuICAgIHByaXZhdGUgcmVhZG9ubHkgX21lc3NhZ2U6IEZzTWVzc2FnZSxcbiAgICBwcml2YXRlIF9jZFJlZjogQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gICkgeyB9XG5cbiAgcHVibGljIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIGZvcmtKb2luKFxuICAgICAgdGhpcy5nZXRSb2xlKCksXG4gICAgICB0aGlzLl9hcHBBY2xTZXJ2aWNlLmdldFBlcm1pc3Npb25zKCksXG4gICAgKVxuICAgICAgLnBpcGUodGFrZVVudGlsKHRoaXMuX2Rlc3Ryb3kkKSlcbiAgICAgIC5zdWJzY3JpYmUoKFtcbiAgICAgICAgYWNsUm9sZSxcbiAgICAgICAgYWNsUGVybWlzc2lvbnMsXG4gICAgICBdKSA9PiB7XG5cbiAgICAgICAgdGhpcy5wZXJtaXNzaW9ucyA9IGFjbFBlcm1pc3Npb25zO1xuICAgICAgICB0aGlzLmFjbExldmVscyA9IHRoaXMuX2RhdGEuYWNsTGV2ZWxzO1xuICAgICAgICB0aGlzLmRpc2FibGVkID0gdGhpcy5fZGF0YS5kaXNhYmxlZDtcblxuICAgICAgICB0aGlzLmluZGV4ZWRBY2xMZXZlbHMgPSBsaXN0KHRoaXMuYWNsTGV2ZWxzLCAnbmFtZScsICd2YWx1ZScpO1xuICAgICAgICB0aGlzLmluZGV4ZWRBY2Nlc3NlcyA9IGxpc3QoQWNsUm9sZUFjY2Vzc2VzLCAnbmFtZScsICd2YWx1ZScpO1xuXG4gICAgICAgIHRoaXMuYWNsUm9sZSA9IHtcbiAgICAgICAgICAuLi57XG4gICAgICAgICAgICBhY2xQZXJtaXNzaW9uczogW10sXG4gICAgICAgICAgICBhbGxQZXJtaXNzaW9uczogdHJ1ZSxcbiAgICAgICAgICAgIGFjbFJvbGVDb25maWdzOiBbXSxcbiAgICAgICAgICAgIHBlcm1pc3Npb25zOiB7fSxcbiAgICAgICAgICAgIGxldmVsOiB0aGlzLmFjbExldmVsc1swXS52YWx1ZSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIC4uLmFjbFJvbGUsXG4gICAgICAgIH07XG5cbiAgICAgICAgdGhpcy5hY2xSb2xlQ29uZmlnVmFsdWVzID0gKGFjbFJvbGUuYWNsUm9sZUNvbmZpZ3MgfHwgW10pXG4gICAgICAgICAgLnJlZHVjZSgoYWNjdW0sIGFjbFJvbGVDb25maWcpID0+IHtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgIC4uLmFjY3VtLFxuICAgICAgICAgICAgICBbYWNsUm9sZUNvbmZpZy5uYW1lXTogYWNsUm9sZUNvbmZpZy52YWx1ZSxcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9LCB7fSk7XG5cbiAgICAgICAgaWYgKHRoaXMuYWNsUm9sZS5pZCkge1xuICAgICAgICAgIHRoaXMucGVybWlzc2lvbnMuZm9yRWFjaCgocGVybWlzc2lvbikgPT4ge1xuICAgICAgICAgICAgbGV0IGFjY2VzcyA9IDA7XG5cbiAgICAgICAgICAgIGNvbnN0IGFjbFBlcm1pc3Npb24gPSB0aGlzLmFjbFJvbGUuYWNsUGVybWlzc2lvbnMuZmluZCgoaXRlbSkgPT4ge1xuICAgICAgICAgICAgICByZXR1cm4gaXRlbS5wZXJtaXNzaW9uID09PSBwZXJtaXNzaW9uLnZhbHVlO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIGlmIChhY2xQZXJtaXNzaW9uKSB7XG4gICAgICAgICAgICAgIGFjY2VzcyA9IGFjbFBlcm1pc3Npb24uYWNjZXNzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLmFjbFJvbGVQZXJtaXNzaW9uc1twZXJtaXNzaW9uLnZhbHVlXSA9IGFjY2VzcztcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLmFjbFJvbGUuYWxsUGVybWlzc2lvbnMpIHtcbiAgICAgICAgICB0aGlzLl9hcHBseU1heFBlcm1pc3Npb25BY2Nlc3MoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX3VwZGF0ZVBlcm1pc3Npb25zKCk7XG4gICAgICAgIHRoaXMuX3VwZGF0ZVJvbGVDb25maWdzKCk7XG5cbiAgICAgICAgdGhpcy5fY2RSZWYubWFya0ZvckNoZWNrKCk7XG4gICAgICB9KTtcblxuICAgIHRoaXMubGlzdENvbmZpZyA9IHtcbiAgICAgIHN0YXR1czogZmFsc2UsXG4gICAgICBwYWdpbmc6IGZhbHNlLFxuICAgICAgcm93SGlnaGxpZ2h0OiBmYWxzZSxcbiAgICAgIG5vUmVzdWx0czoge1xuICAgICAgICBtZXNzYWdlOiAnJyxcbiAgICAgIH0sXG4gICAgICBncm91cDoge1xuICAgICAgICBpbml0aWFsRXhwYW5kOiB0cnVlLFxuICAgICAgICBncm91cEJ5OiAoZGF0YSkgPT4ge1xuICAgICAgICAgIHJldHVybiBkYXRhO1xuICAgICAgICB9LFxuICAgICAgICBjb21wYXJlQnk6IChkYXRhKSA9PiB7XG4gICAgICAgICAgcmV0dXJuIGRhdGEuY2F0ZWdvcnkgfHwgJ0dlbmVyYWwnO1xuICAgICAgICB9LFxuICAgICAgfSxcbiAgICAgIGZldGNoOiAoKSA9PiB7XG4gICAgICAgIHJldHVybiBvZih7XG4gICAgICAgICAgZGF0YTogdGhpcy5sZXZlbFBlcm1pc3Npb25zLnNvcnQoKGEsIGIpID0+IHtcbiAgICAgICAgICAgIGEgPSBhLm5hbWUudG9VcHBlckNhc2UoKTtcbiAgICAgICAgICAgIGIgPSBiLm5hbWUudG9VcHBlckNhc2UoKTtcbiAgICAgICAgICAgIGlmIChhIDwgYikge1xuICAgICAgICAgICAgICByZXR1cm4gLTE7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGEgPiBiKSB7XG4gICAgICAgICAgICAgIHJldHVybiAxO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgICB9KSxcbiAgICAgICAgfSk7XG4gICAgICB9LFxuICAgIH07XG4gIH1cblxuICBwdWJsaWMgYnVsa0NoYW5nZSh2YWx1ZTogbnVtYmVyLCBncm91cENoaWxkcmVuLCBncm91cCk6IHZvaWQge1xuICAgIGdyb3VwQ2hpbGRyZW5cbiAgICAgIC5mb3JFYWNoKChwZXJtaXNzaW9uKSA9PiB7XG4gICAgICAgIGNvbnN0IGFjY2VzcyA9IHBlcm1pc3Npb24uYWNjZXNzZXNcbiAgICAgICAgICAuZmluZCgoYWNjZXNzKSA9PiB2YWx1ZSA9PT0gYWNjZXNzKTtcblxuICAgICAgICBpZihhY2Nlc3MgfHwgIXZhbHVlKSB7XG4gICAgICAgICAgdGhpcy5hY2xSb2xlUGVybWlzc2lvbnNbcGVybWlzc2lvbi52YWx1ZV0gPSB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIHRoaXMuc3VibWl0QnV0dG9uLmRpc2FibGVkID0gZmFsc2U7XG4gICAgICB0aGlzLnBlcm1pc3Npb25DaGFuZ2UoKTtcbiAgICB9KTtcbiAgfVxuXG4gIHB1YmxpYyBwZXJtaXNzaW9uQ2hhbmdlKCk6IHZvaWQge1xuICAgIHRoaXMuYWNsUm9sZVBlcm1pc3Npb25zID0ge1xuICAgICAgLi4udGhpcy5hY2xSb2xlUGVybWlzc2lvbnMsICAgICAgICBcbiAgICB9O1xuICAgIHRoaXMuX2NkUmVmLm1hcmtGb3JDaGVjaygpO1xuICB9XG5cbiAgcHVibGljIGxldmVsQ2hhbmdlKCk6IHZvaWQge1xuICAgIHRoaXMuX3VwZGF0ZVBlcm1pc3Npb25zKCk7XG4gICAgdGhpcy5fdXBkYXRlUm9sZUNvbmZpZ3MoKTtcbiAgICB0aGlzLmxpc3QucmVsb2FkKCk7XG4gIH1cblxuICBwdWJsaWMgZ2V0Um9sZSgpOiBPYnNlcnZhYmxlPGFueT4ge1xuICAgIGlmICghdGhpcy5fZGF0YS5hY2xSb2xlLmlkKSB7XG4gICAgICByZXR1cm4gb2YodGhpcy5fZGF0YS5hY2xSb2xlKTtcbiAgICB9XG5cbiAgICBjb25zdCBxdWVyeTogYW55ID0ge1xuICAgICAgYWNsUGVybWlzc2lvbnM6IHRydWUsXG4gICAgICBhY2xSb2xlQ29uZmlnczogdHJ1ZSxcbiAgICB9O1xuXG4gICAgaWYgKCF0aGlzLmVudmlyb25tZW50KSB7XG4gICAgICBxdWVyeS5lbnZpcm9ubWVudElkID0gbnVsbDtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5fZGF0YS5sb2FkQWNsUm9sZSh0aGlzLl9kYXRhLmFjbFJvbGUsIHF1ZXJ5KTtcbiAgfVxuXG4gIHB1YmxpYyBzYXZlID0gKCk6IE9ic2VydmFibGU8YW55PiA9PiB7XG4gICAgY29uc3QgYWNsUm9sZUNvbmZpZ3MgPSB0aGlzLnJvbGVDb25maWdzXG4gICAgICAubWFwKChyb2xlQ29uZmlnKSA9PiB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgbmFtZTogcm9sZUNvbmZpZy5uYW1lLFxuICAgICAgICAgIHZhbHVlOiB0aGlzLmFjbFJvbGVDb25maWdWYWx1ZXNbcm9sZUNvbmZpZy5uYW1lXSxcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICBjb25zdCBhY2xSb2xlID0ge1xuICAgICAgLi4udGhpcy5hY2xSb2xlLFxuICAgICAgcGVybWlzc2lvbnM6IHRoaXMubGV2ZWxQZXJtaXNzaW9ucy5tYXAoKHBlcm1pc3Npb24pID0+IHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICB2YWx1ZTogcGVybWlzc2lvbi52YWx1ZSxcbiAgICAgICAgICBhY2Nlc3M6IHRoaXMuYWNsUm9sZVBlcm1pc3Npb25zW3Blcm1pc3Npb24udmFsdWVdIHx8IDAsXG4gICAgICAgIH07XG4gICAgICB9KSxcbiAgICAgIGFjbFJvbGVDb25maWdzLFxuICAgIH07XG5cbiAgICByZXR1cm4gdGhpcy5fZGF0YS5zYXZlQWNsUm9sZShhY2xSb2xlKVxuICAgICAgLnBpcGUoXG4gICAgICAgIHRhcCgocmVzcG9uc2UpID0+IHtcbiAgICAgICAgICB0aGlzLl9tZXNzYWdlLnN1Y2Nlc3MoJ1NhdmVkIENoYW5nZXMnKTtcbiAgICAgICAgICB0aGlzLmNsb3NlKHJlc3BvbnNlKTtcbiAgICAgICAgfSksXG4gICAgICApO1xuICB9XG5cbiAgcHVibGljIGNsb3NlKGRhdGE6IGFueSA9IG51bGwpOiB2b2lkIHtcbiAgICB0aGlzLl9kaWFsb2dSZWYuY2xvc2UoZGF0YSk7XG4gIH1cblxuICBwdWJsaWMgYWxsUGVybWlzc2lvbnNDaGFuZ2UoYWxsOiBib29sZWFuKTogdm9pZCB7XG4gICAgdGhpcy5fdXBkYXRlUGVybWlzc2lvbnMoKTtcbiAgICBpZiAoYWxsKSB7XG4gICAgICB0aGlzLl9hcHBseU1heFBlcm1pc3Npb25BY2Nlc3MoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5fYXBwbHlOb25lUGVybWlzc2lvbkFjY2VzcygpO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICB0aGlzLl9kZXN0cm95JC5uZXh0KCk7XG4gICAgdGhpcy5fZGVzdHJveSQuY29tcGxldGUoKTtcbiAgfVxuXG4gIHByaXZhdGUgX3VwZGF0ZVBlcm1pc3Npb25zKCk6IHZvaWQge1xuICAgIHRoaXMubGV2ZWxQZXJtaXNzaW9ucyA9IHRoaXMucGVybWlzc2lvbnNcbiAgICAuZmlsdGVyKChwZXJtaXNzaW9uKSA9PiB7XG4gICAgICByZXR1cm4gcGVybWlzc2lvbi5sZXZlbHMuc29tZSgoaXRlbSkgPT4ge1xuICAgICAgICByZXR1cm4gaXRlbSA9PT0gdGhpcy5hY2xSb2xlLmxldmVsO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIF91cGRhdGVSb2xlQ29uZmlncygpOiB2b2lkIHtcbiAgICBpZih0aGlzLl9kYXRhLmxvYWRSb2xlQ29uZmlncykge1xuICAgICAgdGhpcy5fZGF0YS5sb2FkUm9sZUNvbmZpZ3MoKVxuICAgICAgLnN1YnNjcmliZSgocm9sZUNvbmZpZ3M6IFJvbGVDb25maWdbXSkgPT4ge1xuICAgICAgICB0aGlzLnJvbGVDb25maWdzID0gcm9sZUNvbmZpZ3NcbiAgICAgICAgICAuZmlsdGVyKChyb2xlQ29uZmlnKSA9PiByb2xlQ29uZmlnLmxldmVsID09PSB0aGlzLmFjbFJvbGUubGV2ZWwpO1xuICAgICAgICB0aGlzLl9jZFJlZi5tYXJrRm9yQ2hlY2soKTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgX2FwcGx5TWF4UGVybWlzc2lvbkFjY2VzcygpOiB2b2lkIHtcbiAgICB0aGlzLnBlcm1pc3Npb25zLmZvckVhY2goKHBlcm1pc3Npb24pID0+IHtcbiAgICAgIHRoaXMuYWNsUm9sZVBlcm1pc3Npb25zW3Blcm1pc3Npb24udmFsdWVdID0gTWF0aC5tYXgoLi4ucGVybWlzc2lvbi5hY2Nlc3Nlcyk7XG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIF9hcHBseU5vbmVQZXJtaXNzaW9uQWNjZXNzKCk6IHZvaWQge1xuICAgIHRoaXMucGVybWlzc2lvbnMuZm9yRWFjaCgocGVybWlzc2lvbikgPT4ge1xuICAgICAgdGhpcy5hY2xSb2xlUGVybWlzc2lvbnNbcGVybWlzc2lvbi52YWx1ZV0gPSBBY2xSb2xlQWNjZXNzLk5vbmU7XG4gICAgfSk7XG4gIH1cblxufVxuIiwiPGZvcm0gZnNGb3JtIFtzdWJtaXRdPVwic2F2ZVwiPlxuICA8ZnMtZGlhbG9nPlxuICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJhY2xSb2xlXCI+XG4gICAgICA8ZGl2IG1hdC1kaWFsb2ctdGl0bGU+XG4gICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCIhZGlzYWJsZWRcIj57eyBhY2xSb2xlLmlkID8gJ0VkaXQnIDogJ0NyZWF0ZScgfX08L25nLWNvbnRhaW5lcj5cbiAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cImRpc2FibGVkXCI+VmlldzwvbmctY29udGFpbmVyPlxuICAgICAgICBSb2xlXG4gICAgICA8L2Rpdj5cbiAgICAgIDxtYXQtZGlhbG9nLWNvbnRlbnQ+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJmcy1yb3cuZ2FwLWxhcmdlLmFsaWduLXN0YXJ0XCI+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImZzLWNvbHVtbiBsZWZ0LWNvbHVtblwiPlxuICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkPiAgICAgICAgICAgIFxuICAgICAgICAgICAgICA8bWF0LWxhYmVsPk5hbWU8L21hdC1sYWJlbD5cbiAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cImFjbFJvbGUubmFtZVwiXG4gICAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cImRpc2FibGVkXCJcbiAgICAgICAgICAgICAgICBuYW1lPVwibmFtZVwiXG4gICAgICAgICAgICAgICAgZnNGb3JtUmVxdWlyZWQ+XG4gICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuXG4gICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgIDxtYXQtbGFiZWw+RGVzY3JpcHRpb248L21hdC1sYWJlbD5cbiAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cImFjbFJvbGUuZGVzY3JpcHRpb25cIlxuICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCJkaXNhYmxlZFwiXG4gICAgICAgICAgICAgICAgbmFtZT1cImRlc2NyaXB0aW9uXCI+XG4gICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuXG4gICAgICAgICAgICA8ZnMtbGFiZWwtZmllbGQgKm5nSWY9XCJhY2xSb2xlLmlkIHx8IGFjbExldmVscy5sZW5ndGggPT09IDE7IGVsc2UgbGV2ZWxzXCI+XG4gICAgICAgICAgICAgIDxmcy1sYWJlbD5MZXZlbDwvZnMtbGFiZWw+XG4gICAgICAgICAgICAgIHt7aW5kZXhlZEFjbExldmVsc1thY2xSb2xlLmxldmVsXX19XG4gICAgICAgICAgICA8L2ZzLWxhYmVsLWZpZWxkPlxuXG4gICAgICAgICAgICA8bmctdGVtcGxhdGUgI2xldmVscz5cbiAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImxldmVsXCI+XG4gICAgICAgICAgICAgICAgPGZzLXJhZGlvLWdyb3VwXG4gICAgICAgICAgICAgICAgICAgIFsobmdNb2RlbCldPVwiYWNsUm9sZS5sZXZlbFwiXG4gICAgICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCJkaXNhYmxlZFwiXG4gICAgICAgICAgICAgICAgICAgIChuZ01vZGVsQ2hhbmdlKT1cImxldmVsQ2hhbmdlKClcIlxuICAgICAgICAgICAgICAgICAgICBmc0Zvcm1SZXF1aXJlZFxuICAgICAgICAgICAgICAgICAgICBsYWJlbD1cIkxldmVsXCJcbiAgICAgICAgICAgICAgICAgICAgb3JpZW50YXRpb249XCJ2ZXJ0aWNhbFwiXG4gICAgICAgICAgICAgICAgICAgIG5hbWU9XCJsZXZlbFwiPlxuICAgICAgICAgICAgICAgICAgPG1hdC1yYWRpby1idXR0b25cbiAgICAgICAgICAgICAgICAgICAgICAqbmdGb3I9XCJsZXQgaXRlbSBvZiBhY2xMZXZlbHNcIlxuICAgICAgICAgICAgICAgICAgICAgIFt2YWx1ZV09XCJpdGVtLnZhbHVlXCJcbiAgICAgICAgICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiISFhY2xSb2xlLnByb3RlY3RlZFwiPlxuICAgICAgICAgICAgICAgICAgICB7eyBpdGVtLm5hbWUgfX1cbiAgICAgICAgICAgICAgICAgIDwvbWF0LXJhZGlvLWJ1dHRvbj5cbiAgICAgICAgICAgICAgICA8L2ZzLXJhZGlvLWdyb3VwPlxuICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG5cbiAgICAgICAgICAgIDxmcy1sYWJlbC1maWVsZCAqbmdJZj1cImxldmVsUGVybWlzc2lvbnMubGVuZ3RoXCI+XG4gICAgICAgICAgICAgIDxmcy1sYWJlbD5BbGwgUGVybWlzc2lvbnM8L2ZzLWxhYmVsPlxuICAgICAgICAgICAgICA8bWF0LWNoZWNrYm94XG4gICAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cImFjbFJvbGUuYWxsUGVybWlzc2lvbnNcIlxuICAgICAgICAgICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwiYWxsUGVybWlzc2lvbnNDaGFuZ2UoJGV2ZW50KVwiXG4gICAgICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiISFhY2xSb2xlLnByb3RlY3RlZCB8fCBkaXNhYmxlZFwiXG4gICAgICAgICAgICAgICAgICBuYW1lPVwiYWxsUGVybWlzc2lvbnNcIj5cbiAgICAgICAgICAgICAgICBFbmFibGVcbiAgICAgICAgICAgICAgPC9tYXQtY2hlY2tib3g+XG4gICAgICAgICAgICA8L2ZzLWxhYmVsLWZpZWxkPlxuXG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZnMtY29sdW1uXCIgKm5nRm9yPVwibGV0IHJvbGVDb25maWcgb2Ygcm9sZUNvbmZpZ3NcIj5cbiAgICAgICAgICAgICAgPGZzLWxhYmVsLWZpZWxkICpuZ0lmPVwicm9sZUNvbmZpZy50eXBlID09PSAnY2hlY2tib3gnXCI+XG4gICAgICAgICAgICAgICAgPGZzLWxhYmVsPnt7cm9sZUNvbmZpZy5sYWJlbH19PC9mcy1sYWJlbD5cbiAgICAgICAgICAgICAgICA8bWF0LWNoZWNrYm94XG4gICAgICAgICAgICAgICAgICAgIFsobmdNb2RlbCldPVwiYWNsUm9sZUNvbmZpZ1ZhbHVlc1tyb2xlQ29uZmlnLm5hbWVdXCJcbiAgICAgICAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cImRpc2FibGVkXCJcbiAgICAgICAgICAgICAgICAgICAgW25hbWVdPVwicm9sZUNvbmZpZy5uYW1lXCI+XG4gICAgICAgICAgICAgICAgICBFbmFibGVcbiAgICAgICAgICAgICAgICA8L21hdC1jaGVja2JveD5cbiAgICAgICAgICAgICAgICA8ZnMtbGFiZWwtbWVzc2FnZT5cbiAgICAgICAgICAgICAgICAgIDxtYXQtaGludD57e3JvbGVDb25maWcuZGVzY3JpcHRpb259fTwvbWF0LWhpbnQ+XG4gICAgICAgICAgICAgICAgPC9mcy1sYWJlbC1tZXNzYWdlPlxuICAgICAgICAgICAgICA8L2ZzLWxhYmVsLWZpZWxkPlxuXG4gICAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCAqbmdJZj1cInJvbGVDb25maWcudHlwZSA9PT0gJ3NlbGVjdCdcIj5cbiAgICAgICAgICAgICAgICA8bWF0LXNlbGVjdFxuICAgICAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cImFjbFJvbGVDb25maWdWYWx1ZXNbcm9sZUNvbmZpZy5uYW1lXVwiXG4gICAgICAgICAgICAgICAgICAgIFtuYW1lXT1cInJvbGVDb25maWcubmFtZVwiXG4gICAgICAgICAgICAgICAgICAgIFtyZXF1aXJlZF09XCJyb2xlQ29uZmlnLnJlcXVpcmVkXCJcbiAgICAgICAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cImRpc2FibGVkXCJcbiAgICAgICAgICAgICAgICAgICAgW3BsYWNlaG9sZGVyXT1cInJvbGVDb25maWcubGFiZWxcIj5cbiAgICAgICAgICAgICAgICAgIDxtYXQtb3B0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgKm5nRm9yPVwibGV0IGl0ZW0gb2Ygcm9sZUNvbmZpZy52YWx1ZXNcIlxuICAgICAgICAgICAgICAgICAgICAgIFt2YWx1ZV09XCJpdGVtLnZhbHVlXCI+XG4gICAgICAgICAgICAgICAgICAgIHt7IGl0ZW0ubmFtZSB9fVxuICAgICAgICAgICAgICAgICAgPC9tYXQtb3B0aW9uPlxuICAgICAgICAgICAgICAgIDwvbWF0LXNlbGVjdD5cbiAgICAgICAgICAgICAgICA8bWF0LWhpbnQ+e3tyb2xlQ29uZmlnLmRlc2NyaXB0aW9ufX08L21hdC1oaW50PlxuICAgICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICA8ZGl2ICpuZ0lmPVwiYWNsUm9sZS5sZXZlbFwiIFtoaWRkZW5dPVwiIWxldmVsUGVybWlzc2lvbnMubGVuZ3RoXCIgY2xhc3M9XCJwZXJtaXNzaW9ucyBmcy1jb2x1bW5cIj5cbiAgICAgICAgICAgIDxmcy1saXN0IFtjb25maWddPVwibGlzdENvbmZpZ1wiPlxuICAgICAgICAgICAgICA8ZnMtbGlzdC1jb2x1bW4gdGl0bGU9XCJQZXJtaXNzaW9uc1wiPlxuICAgICAgICAgICAgICAgIDxuZy10ZW1wbGF0ZSBmcy1saXN0LWdyb3VwLWNlbGwgbGV0LXJvdz1cInJvd1wiIGNsYXNzPVwicGVybWlzc2lvbi1ncm91cFwiPlxuICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInBlcm1pc3Npb24tZ3JvdXBcIj57e3Jvdy5jYXRlZ29yeSB8fCAnR2VuZXJhbCd9fTwvZGl2PlxuICAgICAgICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgICAgICAgICAgPG5nLXRlbXBsYXRlIGZzLWxpc3QtY2VsbCBsZXQtcm93PVwicm93XCI+XG4gICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwicGVybWlzc2lvblwiPnt7IHJvdy5uYW1lIH19PC9kaXY+XG4gICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZGVzY3JpcHRpb24gc21hbGxcIj57eyByb3cuZGVzY3JpcHRpb24gfX08L2Rpdj5cbiAgICAgICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICAgICAgICA8L2ZzLWxpc3QtY29sdW1uPlxuICAgICAgICAgICAgICA8ZnMtbGlzdC1jb2x1bW4gdGl0bGU9XCJBY2Nlc3NcIiB3aWR0aD1cIjElXCIgY2xhc3M9XCJhY2Nlc3NcIj5cbiAgICAgICAgICAgICAgICA8bmctdGVtcGxhdGUgXG4gICAgICAgICAgICAgICAgICAgIGZzLWxpc3QtZ3JvdXAtY2VsbFxuICAgICAgICAgICAgICAgICAgICBsZXQtcm93PVwicm93XCJcbiAgICAgICAgICAgICAgICAgICAgbGV0LWdyb3VwPVwiZ3JvdXBcIlxuICAgICAgICAgICAgICAgICAgICBsZXQtZ3JvdXBDaGlsZHJlbj1cImdyb3VwQ2hpbGRyZW5cIlxuICAgICAgICAgICAgICAgICAgICBjbGFzcz1cInBlcm1pc3Npb24tZ3JvdXBcIlxuICAgICAgICAgICAgICAgICAgICBhbGlnbj1cInJpZ2h0XCI+XG4gICAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiIWFjbFJvbGUuYWxsUGVybWlzc2lvbnMgJiYgIWRpc2FibGVkXCI+XG4gICAgICAgICAgICAgICAgICAgIDxmcy1tZW51PlxuICAgICAgICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nRm9yPVwibGV0IGFjY2VzcyBvZiBBY2xSb2xlQWNjZXNzZXMgfCBidWlsa09wdGlvbnNGaWx0ZXI6IGdyb3VwQ2hpbGRyZW5cIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxuZy10ZW1wbGF0ZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZzLW1lbnUtaXRlbVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJidWxrQ2hhbmdlKGFjY2Vzcy52YWx1ZSwgZ3JvdXBDaGlsZHJlbiwgZ3JvdXApXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHt7IGFjY2Vzcy5uYW1lIH19XG4gICAgICAgICAgICAgICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICAgICAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxuICAgICAgICAgICAgICAgICAgICA8L2ZzLW1lbnU+XG4gICAgICAgICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICAgICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICAgICAgICAgIDxuZy10ZW1wbGF0ZSBmcy1saXN0LWNlbGwgbGV0LXJvdz1cInBlcm1pc3Npb25cIiBsZXQtcGVybWlzc2lvbj1cInJvd1wiPlxuICAgICAgICAgICAgICAgICAgPHNwYW4gKm5nSWY9XCJhY2xSb2xlLmFsbFBlcm1pc3Npb25zIHx8IGRpc2FibGVkOyBlbHNlIGVsc2VBbGxcIj5cbiAgICAgICAgICAgICAgICAgICAge3tpbmRleGVkQWNjZXNzZXNbYWNsUm9sZVBlcm1pc3Npb25zW3Blcm1pc3Npb24udmFsdWVdXX19XG4gICAgICAgICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgICAgICAgICA8bmctdGVtcGxhdGUgI2Vsc2VBbGw+XG4gICAgICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJwZXJtaXNzaW9ufGFjbFJvbGVQZXJtaXNzaW9uQXZhaWxhYmxlOmFjbFJvbGVQZXJtaXNzaW9uczsgZWxzZSBwZXJtaXNzaW9uUmVxdWlyZXNcIj5cbiAgICAgICAgICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgICAgICAgICAgICA8bWF0LXNlbGVjdFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFsobmdNb2RlbCldPVwiYWNsUm9sZVBlcm1pc3Npb25zW3Blcm1pc3Npb24udmFsdWVdXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiISFhY2xSb2xlLnByb3RlY3RlZFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVxdWlyZWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbmFtZV09XCInYWNjZXNzLScgKyBwZXJtaXNzaW9uLnZhbHVlXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAobmdNb2RlbENoYW5nZSk9XCJwZXJtaXNzaW9uQ2hhbmdlKClcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdGb3I9XCJsZXQgYWNjZXNzIG9mIEFjbFJvbGVBY2Nlc3Nlc1wiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtb3B0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICpuZ0lmPVwiYWNjZXNzLnZhbHVlID09PSAwIHx8IHBlcm1pc3Npb24uYWNjZXNzZXMuaW5kZXhPZihhY2Nlc3MudmFsdWUpICE9PSAtMVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFt2YWx1ZV09XCJhY2Nlc3MudmFsdWVcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt7YWNjZXNzLm5hbWV9fVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LW9wdGlvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L21hdC1zZWxlY3Q+XG4gICAgICAgICAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgICAgICAgICAgICAgICAgIDxuZy10ZW1wbGF0ZSAjcGVybWlzc2lvblJlcXVpcmVzPlxuICAgICAgICAgICAgICAgICAgICAgIFVuYXZhaWxhYmxlXG4gICAgICAgICAgICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgICAgICAgIDwvZnMtbGlzdC1jb2x1bW4+XG4gICAgICAgICAgICA8L2ZzLWxpc3Q+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9tYXQtZGlhbG9nLWNvbnRlbnQ+XG4gICAgICA8bWF0LWRpYWxvZy1hY3Rpb25zPlxuICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAqbmdJZj1cIiFkaXNhYmxlZFwiXG4gICAgICAgICAgICAjc3VibWl0XG4gICAgICAgICAgICBtYXQtYnV0dG9uXG4gICAgICAgICAgICB0eXBlPVwic3VibWl0XCJcbiAgICAgICAgICAgIGNvbG9yPVwicHJpbWFyeVwiPlxuICAgICAgICAgIHt7IGFjbFJvbGUuaWQgPyAnU2F2ZScgOiAnQ3JlYXRlJyB9fVxuICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgPGJ1dHRvbiBtYXQtYnV0dG9uIFttYXQtZGlhbG9nLWNsb3NlXT1cIm51bGxcIiB0eXBlPVwiYnV0dG9uXCI+e3sgZGlzYWJsZWQgPyAnRG9uZScgOiAnQ2FuY2VsJyB9fTwvYnV0dG9uPlxuICAgICAgPC9tYXQtZGlhbG9nLWFjdGlvbnM+XG4gICAgPC9uZy1jb250YWluZXI+XG4gIDwvZnMtZGlhbG9nPlxuPC9mb3JtPlxuIl19
1
+ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Inject, ViewChild } from '@angular/core';
2
+ import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
3
+ import { AclRoleAccesses } from './../../consts/acl-role-accesses';
4
+ import { takeUntil, tap } from 'rxjs/operators';
5
+ import { FsMessage } from '@firestitch/message';
6
+ import { list } from '@firestitch/common';
7
+ import { FsListComponent } from '@firestitch/list';
8
+ import { forkJoin, of, Subject } from 'rxjs';
9
+ import { FsAppAclService } from './../../services/app-acl.service';
10
+ import { AclRoleAccess } from '../../enums/acl-role-access';
11
+ import { MatButton } from '@angular/material/button';
12
+ import * as i0 from "@angular/core";
13
+ import * as i1 from "./../../services/app-acl.service";
14
+ import * as i2 from "@angular/material/dialog";
15
+ import * as i3 from "@firestitch/message";
16
+ import * as i4 from "@angular/common";
17
+ import * as i5 from "@angular/forms";
18
+ import * as i6 from "@angular/material/form-field";
19
+ import * as i7 from "@angular/material/checkbox";
20
+ import * as i8 from "@angular/material/select";
21
+ import * as i9 from "@angular/material/core";
22
+ import * as i10 from "@angular/material/button";
23
+ import * as i11 from "@angular/material/radio";
24
+ import * as i12 from "@angular/material/input";
25
+ import * as i13 from "@firestitch/list";
26
+ import * as i14 from "@firestitch/dialog";
27
+ import * as i15 from "@firestitch/form";
28
+ import * as i16 from "@firestitch/label";
29
+ import * as i17 from "@firestitch/radiogroup";
30
+ import * as i18 from "@firestitch/menu";
31
+ import * as i19 from "../../pipes/bulk-options-filter.pipe";
32
+ import * as i20 from "../../pipes/acl-role-permission-available.pipe";
33
+ export class FsAclRoleComponent {
34
+ constructor(_data, _appAclService, _dialogRef, _message, _cdRef) {
35
+ this._data = _data;
36
+ this._appAclService = _appAclService;
37
+ this._dialogRef = _dialogRef;
38
+ this._message = _message;
39
+ this._cdRef = _cdRef;
40
+ this.aclRole = null;
41
+ this.permissions = [];
42
+ this.levelPermissions = [];
43
+ this.AclRoleAccesses = AclRoleAccesses;
44
+ this.indexedAccesses = {};
45
+ this.aclLevels = [];
46
+ this.indexedAclLevels = {};
47
+ this.onlyFullAccess = false;
48
+ this.AclLevels = {};
49
+ this.roleConfigs = [];
50
+ this.aclRoleConfigValues = {};
51
+ this.aclRolePermissions = {};
52
+ this._destroy$ = new Subject();
53
+ this.save = () => {
54
+ const aclRoleConfigs = this.roleConfigs
55
+ .map((roleConfig) => {
56
+ return {
57
+ name: roleConfig.name,
58
+ value: this.aclRoleConfigValues[roleConfig.name],
59
+ };
60
+ });
61
+ const aclRole = {
62
+ ...this.aclRole,
63
+ permissions: this.levelPermissions.map((permission) => {
64
+ return {
65
+ value: permission.value,
66
+ access: this.aclRolePermissions[permission.value] || 0,
67
+ };
68
+ }),
69
+ aclRoleConfigs,
70
+ };
71
+ return this._data.saveAclRole(aclRole)
72
+ .pipe(tap((response) => {
73
+ this._message.success('Saved Changes');
74
+ this.close(response);
75
+ }));
76
+ };
77
+ }
78
+ ngOnInit() {
79
+ forkJoin(this.getRole(), this._appAclService.getPermissions())
80
+ .pipe(takeUntil(this._destroy$))
81
+ .subscribe(([aclRole, aclPermissions,]) => {
82
+ this.permissions = aclPermissions;
83
+ this.aclLevels = this._data.aclLevels;
84
+ this.disabled = this._data.disabled;
85
+ this.indexedAclLevels = list(this.aclLevels, 'name', 'value');
86
+ this.indexedAccesses = list(AclRoleAccesses, 'name', 'value');
87
+ this.aclRole = {
88
+ ...{
89
+ aclPermissions: [],
90
+ allPermissions: true,
91
+ aclRoleConfigs: [],
92
+ permissions: {},
93
+ level: this.aclLevels[0].value,
94
+ },
95
+ ...aclRole,
96
+ };
97
+ this.aclRoleConfigValues = (aclRole.aclRoleConfigs || [])
98
+ .reduce((accum, aclRoleConfig) => {
99
+ return {
100
+ ...accum,
101
+ [aclRoleConfig.name]: aclRoleConfig.value,
102
+ };
103
+ }, {});
104
+ if (this.aclRole.id) {
105
+ this.permissions.forEach((permission) => {
106
+ let access = 0;
107
+ const aclPermission = this.aclRole.aclPermissions.find((item) => {
108
+ return item.permission === permission.value;
109
+ });
110
+ if (aclPermission) {
111
+ access = aclPermission.access;
112
+ }
113
+ this.aclRolePermissions[permission.value] = access;
114
+ });
115
+ }
116
+ if (this.aclRole.allPermissions) {
117
+ this._applyMaxPermissionAccess();
118
+ }
119
+ this._updatePermissions();
120
+ this._updateRoleConfigs();
121
+ this._cdRef.markForCheck();
122
+ });
123
+ this.listConfig = {
124
+ status: false,
125
+ paging: false,
126
+ rowHoverHighlight: false,
127
+ noResults: {
128
+ message: '',
129
+ },
130
+ group: {
131
+ initialExpand: true,
132
+ groupBy: (data) => {
133
+ return data;
134
+ },
135
+ compareBy: (data) => {
136
+ return data.category || 'General';
137
+ },
138
+ },
139
+ fetch: () => {
140
+ return of({
141
+ data: this.levelPermissions.sort((a, b) => {
142
+ a = a.name.toUpperCase();
143
+ b = b.name.toUpperCase();
144
+ if (a < b) {
145
+ return -1;
146
+ }
147
+ else if (a > b) {
148
+ return 1;
149
+ }
150
+ return 0;
151
+ }),
152
+ });
153
+ },
154
+ };
155
+ }
156
+ bulkChange(value, groupChildren, group) {
157
+ groupChildren
158
+ .forEach((permission) => {
159
+ const access = permission.accesses
160
+ .find((access) => value === access);
161
+ if (access || !value) {
162
+ this.aclRolePermissions[permission.value] = value;
163
+ }
164
+ });
165
+ setTimeout(() => {
166
+ this.submitButton.disabled = false;
167
+ this.permissionChange();
168
+ });
169
+ }
170
+ permissionChange() {
171
+ this.aclRolePermissions = {
172
+ ...this.aclRolePermissions,
173
+ };
174
+ this._cdRef.markForCheck();
175
+ }
176
+ levelChange() {
177
+ this._updatePermissions();
178
+ this._updateRoleConfigs();
179
+ this.list.reload();
180
+ }
181
+ getRole() {
182
+ if (!this._data.aclRole.id) {
183
+ return of(this._data.aclRole);
184
+ }
185
+ const query = {
186
+ aclPermissions: true,
187
+ aclRoleConfigs: true,
188
+ };
189
+ if (!this.environment) {
190
+ query.environmentId = null;
191
+ }
192
+ return this._data.loadAclRole(this._data.aclRole, query);
193
+ }
194
+ close(data = null) {
195
+ this._dialogRef.close(data);
196
+ }
197
+ allPermissionsChange(all) {
198
+ this._updatePermissions();
199
+ if (all) {
200
+ this._applyMaxPermissionAccess();
201
+ }
202
+ else {
203
+ this._applyNonePermissionAccess();
204
+ }
205
+ }
206
+ ngOnDestroy() {
207
+ this._destroy$.next();
208
+ this._destroy$.complete();
209
+ }
210
+ _updatePermissions() {
211
+ this.levelPermissions = this.permissions
212
+ .filter((permission) => {
213
+ return permission.levels.some((item) => {
214
+ return item === this.aclRole.level;
215
+ });
216
+ });
217
+ }
218
+ _updateRoleConfigs() {
219
+ if (this._data.loadRoleConfigs) {
220
+ this._data.loadRoleConfigs()
221
+ .subscribe((roleConfigs) => {
222
+ this.roleConfigs = roleConfigs
223
+ .filter((roleConfig) => roleConfig.level === this.aclRole.level);
224
+ this._cdRef.markForCheck();
225
+ });
226
+ }
227
+ }
228
+ _applyMaxPermissionAccess() {
229
+ this.permissions.forEach((permission) => {
230
+ this.aclRolePermissions[permission.value] = Math.max(...permission.accesses);
231
+ });
232
+ }
233
+ _applyNonePermissionAccess() {
234
+ this.permissions.forEach((permission) => {
235
+ this.aclRolePermissions[permission.value] = AclRoleAccess.None;
236
+ });
237
+ }
238
+ }
239
+ FsAclRoleComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: FsAclRoleComponent, deps: [{ token: MAT_DIALOG_DATA }, { token: i1.FsAppAclService }, { token: i2.MatDialogRef }, { token: i3.FsMessage }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
240
+ FsAclRoleComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: FsAclRoleComponent, selector: "ng-component", viewQueries: [{ propertyName: "list", first: true, predicate: FsListComponent, descendants: true }, { propertyName: "submitButton", first: true, predicate: ["submit"], descendants: true }], ngImport: i0, template: "<form fsForm [submit]=\"save\">\n <fs-dialog>\n <ng-container *ngIf=\"aclRole\">\n <div mat-dialog-title>\n <ng-container *ngIf=\"!disabled\">{{ aclRole.id ? 'Edit' : 'Create' }}</ng-container>\n <ng-container *ngIf=\"disabled\">View</ng-container>\n Role\n </div>\n <mat-dialog-content>\n <div class=\"fs-row.gap-large.align-start\">\n <div class=\"fs-column left-column\">\n <mat-form-field> \n <mat-label>Name</mat-label>\n <input\n matInput\n [(ngModel)]=\"aclRole.name\"\n [disabled]=\"disabled\"\n name=\"name\"\n fsFormRequired>\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Description</mat-label>\n <input\n matInput\n [(ngModel)]=\"aclRole.description\"\n [disabled]=\"disabled\"\n name=\"description\">\n </mat-form-field>\n\n <fs-label-field *ngIf=\"aclRole.id || aclLevels.length === 1; else levels\">\n <fs-label>Level</fs-label>\n {{indexedAclLevels[aclRole.level]}}\n </fs-label-field>\n\n <ng-template #levels>\n <div class=\"level\">\n <fs-radio-group\n [(ngModel)]=\"aclRole.level\"\n [disabled]=\"disabled\"\n (ngModelChange)=\"levelChange()\"\n fsFormRequired\n label=\"Level\"\n orientation=\"vertical\"\n name=\"level\">\n <mat-radio-button\n *ngFor=\"let item of aclLevels\"\n [value]=\"item.value\"\n [disabled]=\"!!aclRole.protected\">\n {{ item.name }}\n </mat-radio-button>\n </fs-radio-group>\n </div>\n </ng-template>\n\n <fs-label-field *ngIf=\"levelPermissions.length\">\n <fs-label>All Permissions</fs-label>\n <mat-checkbox\n [(ngModel)]=\"aclRole.allPermissions\"\n (ngModelChange)=\"allPermissionsChange($event)\"\n [disabled]=\"!!aclRole.protected || disabled\"\n name=\"allPermissions\">\n Enable\n </mat-checkbox>\n </fs-label-field>\n\n <div class=\"fs-column\" *ngFor=\"let roleConfig of roleConfigs\">\n <fs-label-field *ngIf=\"roleConfig.type === 'checkbox'\">\n <fs-label>{{roleConfig.label}}</fs-label>\n <mat-checkbox\n [(ngModel)]=\"aclRoleConfigValues[roleConfig.name]\"\n [disabled]=\"disabled\"\n [name]=\"roleConfig.name\">\n Enable\n </mat-checkbox>\n <fs-label-message>\n <mat-hint>{{roleConfig.description}}</mat-hint>\n </fs-label-message>\n </fs-label-field>\n\n <mat-form-field *ngIf=\"roleConfig.type === 'select'\">\n <mat-select\n [(ngModel)]=\"aclRoleConfigValues[roleConfig.name]\"\n [name]=\"roleConfig.name\"\n [required]=\"roleConfig.required\"\n [disabled]=\"disabled\"\n [placeholder]=\"roleConfig.label\">\n <mat-option\n *ngFor=\"let item of roleConfig.values\"\n [value]=\"item.value\">\n {{ item.name }}\n </mat-option>\n </mat-select>\n <mat-hint>{{roleConfig.description}}</mat-hint>\n </mat-form-field>\n </div>\n </div>\n\n <div *ngIf=\"aclRole.level\" [hidden]=\"!levelPermissions.length\" class=\"permissions fs-column\">\n <fs-list [config]=\"listConfig\">\n <fs-list-column title=\"Permissions\">\n <ng-template fs-list-group-cell let-row=\"row\" class=\"permission-group\">\n <div class=\"permission-group\">{{row.category || 'General'}}</div>\n </ng-template>\n <ng-template fs-list-cell let-row=\"row\">\n <div class=\"permission\">{{ row.name }}</div>\n <div class=\"description small\">{{ row.description }}</div>\n </ng-template>\n </fs-list-column>\n <fs-list-column title=\"Access\" width=\"1%\" class=\"access\">\n <ng-template \n fs-list-group-cell\n let-row=\"row\"\n let-group=\"group\"\n let-groupChildren=\"groupChildren\"\n class=\"permission-group\"\n align=\"right\">\n <ng-container *ngIf=\"!aclRole.allPermissions && !disabled\">\n <fs-menu>\n <ng-container *ngFor=\"let access of AclRoleAccesses | builkOptionsFilter: groupChildren\">\n <ng-template\n fs-menu-item\n (click)=\"bulkChange(access.value, groupChildren, group)\">\n {{ access.name }}\n </ng-template>\n </ng-container>\n </fs-menu>\n </ng-container>\n </ng-template>\n <ng-template fs-list-cell let-row=\"permission\" let-permission=\"row\">\n <span *ngIf=\"aclRole.allPermissions || disabled; else elseAll\">\n {{indexedAccesses[aclRolePermissions[permission.value]]}}\n </span>\n <ng-template #elseAll>\n <ng-container *ngIf=\"permission|aclRolePermissionAvailable:aclRolePermissions; else permissionRequires\">\n <mat-form-field>\n <mat-select\n [(ngModel)]=\"aclRolePermissions[permission.value]\"\n [disabled]=\"!!aclRole.protected\"\n required\n [name]=\"'access-' + permission.value\"\n (ngModelChange)=\"permissionChange()\">\n <ng-container *ngFor=\"let access of AclRoleAccesses\">\n <mat-option\n *ngIf=\"access.value === 0 || permission.accesses.indexOf(access.value) !== -1\"\n [value]=\"access.value\">\n {{access.name}}\n </mat-option>\n </ng-container>\n </mat-select>\n </mat-form-field>\n </ng-container>\n <ng-template #permissionRequires>\n Unavailable\n </ng-template>\n </ng-template>\n </ng-template>\n </fs-list-column>\n </fs-list>\n </div>\n </div>\n </mat-dialog-content>\n <mat-dialog-actions>\n <button\n *ngIf=\"!disabled\"\n #submit\n mat-button\n type=\"submit\"\n color=\"primary\">\n {{ aclRole.id ? 'Save' : 'Create' }}\n </button>\n <button mat-button [mat-dialog-close]=\"null\" type=\"button\">{{ disabled ? 'Done' : 'Cancel' }}</button>\n </mat-dialog-actions>\n </ng-container>\n </fs-dialog>\n</form>\n", styles: [".permissions{flex:1}.permissions ::ng-deep .fs-list-row-group{background-color:#e4e4e4;font-size:112%}.permissions ::ng-deep fs-list .access{white-space:nowrap}.permissions ::ng-deep .mat-form-field{width:100px}.permissions ::ng-deep .mat-form-field .mat-form-field-wrapper{padding-bottom:0}.permissions ::ng-deep .mat-form-field .mat-form-field-infix{border-top:0}.permissions ::ng-deep .mat-form-field .mat-form-field-underline{bottom:0}.permissions ::ng-deep fs-radio-group{width:100%}.permissions ::ng-deep fs-label-field{width:100%}.permissions .level{width:100%}.left-column{width:40%;max-width:400px}\n"], dependencies: [{ kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i5.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: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i5.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i5.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i2.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i2.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "directive", type: i2.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "component", type: i6.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i6.MatLabel, selector: "mat-label" }, { kind: "directive", type: i6.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "component", type: i7.MatCheckbox, selector: "mat-checkbox", inputs: ["disableRipple", "color", "tabIndex"], exportAs: ["matCheckbox"] }, { kind: "component", type: i8.MatSelect, selector: "mat-select", inputs: ["disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator"], exportAs: ["matSelect"] }, { kind: "component", type: i9.MatOption, selector: "mat-option", exportAs: ["matOption"] }, { kind: "component", type: i10.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "component", type: i11.MatRadioButton, selector: "mat-radio-button", inputs: ["disableRipple", "tabIndex"], exportAs: ["matRadioButton"] }, { kind: "directive", type: i12.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: "component", type: i13.FsListComponent, selector: "fs-list", inputs: ["config", "loaderLines"], outputs: ["filtersReady"] }, { kind: "directive", type: i13.FsListColumnDirective, selector: "fs-list-column", inputs: ["show", "title", "name", "customize", "sortable", "sortableDefault", "sortableDirection", "direction", "align", "width", "class"] }, { kind: "directive", type: i13.FsListCellDirective, selector: "[fs-list-cell]", inputs: ["colspan", "align", "class"] }, { kind: "directive", type: i13.FsListGroupHeaderDirective, selector: "[fs-list-group-cell],[fs-list-group-header]" }, { kind: "component", type: i14.FsDialogComponent, selector: "fs-dialog", inputs: ["mobileMode", "mobileButtonPlacement", "mobileWidth", "mode", "buttonLayout", "dock", "dockable", "fullscreenPercent"] }, { kind: "directive", type: i15.FsFormDirective, selector: "[fsForm]", inputs: ["wrapperSelector", "messageSelector", "hintSelector", "labelSelector", "autocomplete", "shortcuts", "confirm", "confirmDialog", "confirmDrawer", "confirmBrowser", "confirmTabs", "dirtySubmitButton", "submit", "successDelay", "errorDelay", "tabGroup", "deactivationGuard"], outputs: ["fsForm", "invalid", "valid", "submitted", "reseted", "cleared"], exportAs: ["fsForm"] }, { kind: "directive", type: i15.FsFormRequiredDirective, selector: "[fsFormRequired],[ngModel][required]", inputs: ["fsFormRequired", "required", "fsFormRequiredMessage"] }, { kind: "directive", type: i15.FsFormNoFsValidatorsDirective, selector: "[ngModel]:not([required]):not([fsFormRequired]):not([fsFormCompare]):not([fsFormDateRange]):not([fsFormEmail]):not([fsFormEmails]):not([fsFormFunction]):not([fsFormGreater]):not([fsFormGreaterEqual]):not([fsFormInteger]):not([fsFormLesser]):not([fsFormMax]):not([fsFormMaxLength]):not([fsFormMin]):not([fsFormMinLength]):not([fsFormNumeric]):not([fsFormPattern]):not([fsFormPhone]):not([fsFormUrl]):not([validate])" }, { kind: "directive", type: i15.FsButtonDirective, selector: "[mat-raised-button]:not([fsFormButtonStandalone]),[mat-button]:not([fsFormButtonStandalone]),[mat-flat-button]:not([fsFormButtonStandalone]),[mat-stroked-button]:not([fsFormButtonStandalone])", inputs: ["name", "dirtySubmit", "form"] }, { kind: "component", type: i16.FsLabelComponent, selector: "fs-label" }, { kind: "component", type: i16.FsLabelFieldComponent, selector: "fs-label-field", inputs: ["bottomMargin", "topMargin", "labelMargin"] }, { kind: "component", type: i16.FsLabelMessageComponent, selector: "fs-label-message" }, { kind: "component", type: i17.FsRadioGroupComponent, selector: "fs-radio-group", inputs: ["orientation", "label", "name", "disabled", "radioPosition", "compareWith", "required"] }, { kind: "component", type: i18.FsMenuComponent, selector: "fs-menu", inputs: ["class", "buttonClass", "buttonType", "buttonColor"], outputs: ["opened", "closed"] }, { kind: "directive", type: i18.FsMenuItemDirective, selector: "fs-menu-group,[fs-menu-item]" }, { kind: "pipe", type: i19.BulkOptionsFilterPipe, name: "builkOptionsFilter" }, { kind: "pipe", type: i20.AclRolePermissionAvailablePipe, name: "aclRolePermissionAvailable" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
241
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: FsAclRoleComponent, decorators: [{
242
+ type: Component,
243
+ args: [{ changeDetection: ChangeDetectionStrategy.OnPush, template: "<form fsForm [submit]=\"save\">\n <fs-dialog>\n <ng-container *ngIf=\"aclRole\">\n <div mat-dialog-title>\n <ng-container *ngIf=\"!disabled\">{{ aclRole.id ? 'Edit' : 'Create' }}</ng-container>\n <ng-container *ngIf=\"disabled\">View</ng-container>\n Role\n </div>\n <mat-dialog-content>\n <div class=\"fs-row.gap-large.align-start\">\n <div class=\"fs-column left-column\">\n <mat-form-field> \n <mat-label>Name</mat-label>\n <input\n matInput\n [(ngModel)]=\"aclRole.name\"\n [disabled]=\"disabled\"\n name=\"name\"\n fsFormRequired>\n </mat-form-field>\n\n <mat-form-field>\n <mat-label>Description</mat-label>\n <input\n matInput\n [(ngModel)]=\"aclRole.description\"\n [disabled]=\"disabled\"\n name=\"description\">\n </mat-form-field>\n\n <fs-label-field *ngIf=\"aclRole.id || aclLevels.length === 1; else levels\">\n <fs-label>Level</fs-label>\n {{indexedAclLevels[aclRole.level]}}\n </fs-label-field>\n\n <ng-template #levels>\n <div class=\"level\">\n <fs-radio-group\n [(ngModel)]=\"aclRole.level\"\n [disabled]=\"disabled\"\n (ngModelChange)=\"levelChange()\"\n fsFormRequired\n label=\"Level\"\n orientation=\"vertical\"\n name=\"level\">\n <mat-radio-button\n *ngFor=\"let item of aclLevels\"\n [value]=\"item.value\"\n [disabled]=\"!!aclRole.protected\">\n {{ item.name }}\n </mat-radio-button>\n </fs-radio-group>\n </div>\n </ng-template>\n\n <fs-label-field *ngIf=\"levelPermissions.length\">\n <fs-label>All Permissions</fs-label>\n <mat-checkbox\n [(ngModel)]=\"aclRole.allPermissions\"\n (ngModelChange)=\"allPermissionsChange($event)\"\n [disabled]=\"!!aclRole.protected || disabled\"\n name=\"allPermissions\">\n Enable\n </mat-checkbox>\n </fs-label-field>\n\n <div class=\"fs-column\" *ngFor=\"let roleConfig of roleConfigs\">\n <fs-label-field *ngIf=\"roleConfig.type === 'checkbox'\">\n <fs-label>{{roleConfig.label}}</fs-label>\n <mat-checkbox\n [(ngModel)]=\"aclRoleConfigValues[roleConfig.name]\"\n [disabled]=\"disabled\"\n [name]=\"roleConfig.name\">\n Enable\n </mat-checkbox>\n <fs-label-message>\n <mat-hint>{{roleConfig.description}}</mat-hint>\n </fs-label-message>\n </fs-label-field>\n\n <mat-form-field *ngIf=\"roleConfig.type === 'select'\">\n <mat-select\n [(ngModel)]=\"aclRoleConfigValues[roleConfig.name]\"\n [name]=\"roleConfig.name\"\n [required]=\"roleConfig.required\"\n [disabled]=\"disabled\"\n [placeholder]=\"roleConfig.label\">\n <mat-option\n *ngFor=\"let item of roleConfig.values\"\n [value]=\"item.value\">\n {{ item.name }}\n </mat-option>\n </mat-select>\n <mat-hint>{{roleConfig.description}}</mat-hint>\n </mat-form-field>\n </div>\n </div>\n\n <div *ngIf=\"aclRole.level\" [hidden]=\"!levelPermissions.length\" class=\"permissions fs-column\">\n <fs-list [config]=\"listConfig\">\n <fs-list-column title=\"Permissions\">\n <ng-template fs-list-group-cell let-row=\"row\" class=\"permission-group\">\n <div class=\"permission-group\">{{row.category || 'General'}}</div>\n </ng-template>\n <ng-template fs-list-cell let-row=\"row\">\n <div class=\"permission\">{{ row.name }}</div>\n <div class=\"description small\">{{ row.description }}</div>\n </ng-template>\n </fs-list-column>\n <fs-list-column title=\"Access\" width=\"1%\" class=\"access\">\n <ng-template \n fs-list-group-cell\n let-row=\"row\"\n let-group=\"group\"\n let-groupChildren=\"groupChildren\"\n class=\"permission-group\"\n align=\"right\">\n <ng-container *ngIf=\"!aclRole.allPermissions && !disabled\">\n <fs-menu>\n <ng-container *ngFor=\"let access of AclRoleAccesses | builkOptionsFilter: groupChildren\">\n <ng-template\n fs-menu-item\n (click)=\"bulkChange(access.value, groupChildren, group)\">\n {{ access.name }}\n </ng-template>\n </ng-container>\n </fs-menu>\n </ng-container>\n </ng-template>\n <ng-template fs-list-cell let-row=\"permission\" let-permission=\"row\">\n <span *ngIf=\"aclRole.allPermissions || disabled; else elseAll\">\n {{indexedAccesses[aclRolePermissions[permission.value]]}}\n </span>\n <ng-template #elseAll>\n <ng-container *ngIf=\"permission|aclRolePermissionAvailable:aclRolePermissions; else permissionRequires\">\n <mat-form-field>\n <mat-select\n [(ngModel)]=\"aclRolePermissions[permission.value]\"\n [disabled]=\"!!aclRole.protected\"\n required\n [name]=\"'access-' + permission.value\"\n (ngModelChange)=\"permissionChange()\">\n <ng-container *ngFor=\"let access of AclRoleAccesses\">\n <mat-option\n *ngIf=\"access.value === 0 || permission.accesses.indexOf(access.value) !== -1\"\n [value]=\"access.value\">\n {{access.name}}\n </mat-option>\n </ng-container>\n </mat-select>\n </mat-form-field>\n </ng-container>\n <ng-template #permissionRequires>\n Unavailable\n </ng-template>\n </ng-template>\n </ng-template>\n </fs-list-column>\n </fs-list>\n </div>\n </div>\n </mat-dialog-content>\n <mat-dialog-actions>\n <button\n *ngIf=\"!disabled\"\n #submit\n mat-button\n type=\"submit\"\n color=\"primary\">\n {{ aclRole.id ? 'Save' : 'Create' }}\n </button>\n <button mat-button [mat-dialog-close]=\"null\" type=\"button\">{{ disabled ? 'Done' : 'Cancel' }}</button>\n </mat-dialog-actions>\n </ng-container>\n </fs-dialog>\n</form>\n", styles: [".permissions{flex:1}.permissions ::ng-deep .fs-list-row-group{background-color:#e4e4e4;font-size:112%}.permissions ::ng-deep fs-list .access{white-space:nowrap}.permissions ::ng-deep .mat-form-field{width:100px}.permissions ::ng-deep .mat-form-field .mat-form-field-wrapper{padding-bottom:0}.permissions ::ng-deep .mat-form-field .mat-form-field-infix{border-top:0}.permissions ::ng-deep .mat-form-field .mat-form-field-underline{bottom:0}.permissions ::ng-deep fs-radio-group{width:100%}.permissions ::ng-deep fs-label-field{width:100%}.permissions .level{width:100%}.left-column{width:40%;max-width:400px}\n"] }]
244
+ }], ctorParameters: function () { return [{ type: undefined, decorators: [{
245
+ type: Inject,
246
+ args: [MAT_DIALOG_DATA]
247
+ }] }, { type: i1.FsAppAclService }, { type: i2.MatDialogRef }, { type: i3.FsMessage }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { list: [{
248
+ type: ViewChild,
249
+ args: [FsListComponent]
250
+ }], submitButton: [{
251
+ type: ViewChild,
252
+ args: ['submit', { static: false }]
253
+ }] } });
254
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWNsLXJvbGUuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9jb21wb25lbnRzL2FjbC1yb2xlL2FjbC1yb2xlLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3NyYy9hcHAvY29tcG9uZW50cy9hY2wtcm9sZS9hY2wtcm9sZS5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsdUJBQXVCLEVBQ3ZCLGlCQUFpQixFQUNqQixTQUFTLEVBQ1QsTUFBTSxFQUdOLFNBQVMsRUFDVixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsZUFBZSxFQUFFLFlBQVksRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBRXpFLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxrQ0FBa0MsQ0FBQztBQUVuRSxPQUFPLEVBQUUsU0FBUyxFQUFFLEdBQUcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRWhELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUNoRCxPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDMUMsT0FBTyxFQUFFLGVBQWUsRUFBZ0IsTUFBTSxrQkFBa0IsQ0FBQztBQUVqRSxPQUFPLEVBQUUsUUFBUSxFQUFjLEVBQUUsRUFBRSxPQUFPLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDekQsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBRW5FLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUM1RCxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sMEJBQTBCLENBQUM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFRckQsTUFBTSxPQUFPLGtCQUFrQjtJQTJCN0IsWUFDNEMsS0FBVSxFQUNuQyxjQUErQixFQUMvQixVQUE0QyxFQUM1QyxRQUFtQixFQUM1QixNQUF5QjtRQUpT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ZURldGVjdG9yUmVmLFxuICBDb21wb25lbnQsXG4gIEluamVjdCxcbiAgT25EZXN0cm95LFxuICBPbkluaXQsXG4gIFZpZXdDaGlsZFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IE1BVF9ESUFMT0dfREFUQSwgTWF0RGlhbG9nUmVmIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvZGlhbG9nJztcblxuaW1wb3J0IHsgQWNsUm9sZUFjY2Vzc2VzIH0gZnJvbSAnLi8uLi8uLi9jb25zdHMvYWNsLXJvbGUtYWNjZXNzZXMnO1xuaW1wb3J0IHsgQWNsUm9sZSB9IGZyb20gJy4vLi4vLi4vaW50ZXJmYWNlcy9hY2wtcm9sZSc7XG5pbXBvcnQgeyB0YWtlVW50aWwsIHRhcCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcblxuaW1wb3J0IHsgRnNNZXNzYWdlIH0gZnJvbSAnQGZpcmVzdGl0Y2gvbWVzc2FnZSc7XG5pbXBvcnQgeyBsaXN0IH0gZnJvbSAnQGZpcmVzdGl0Y2gvY29tbW9uJztcbmltcG9ydCB7IEZzTGlzdENvbXBvbmVudCwgRnNMaXN0Q29uZmlnIH0gZnJvbSAnQGZpcmVzdGl0Y2gvbGlzdCc7XG5cbmltcG9ydCB7IGZvcmtKb2luLCBPYnNlcnZhYmxlLCBvZiwgU3ViamVjdCB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgRnNBcHBBY2xTZXJ2aWNlIH0gZnJvbSAnLi8uLi8uLi9zZXJ2aWNlcy9hcHAtYWNsLnNlcnZpY2UnO1xuaW1wb3J0IHsgUm9sZUNvbmZpZyB9IGZyb20gJy4uLy4uL2ludGVyZmFjZXMnO1xuaW1wb3J0IHsgQWNsUm9sZUFjY2VzcyB9IGZyb20gJy4uLy4uL2VudW1zL2FjbC1yb2xlLWFjY2Vzcyc7XG5pbXBvcnQgeyBNYXRCdXR0b24gfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9idXR0b24nO1xuXG5cbkBDb21wb25lbnQoe1xuICB0ZW1wbGF0ZVVybDogJy4vYWNsLXJvbGUuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9hY2wtcm9sZS5jb21wb25lbnQuc2NzcyddLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbn0pXG5leHBvcnQgY2xhc3MgRnNBY2xSb2xlQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkRlc3Ryb3kge1xuXG4gIEBWaWV3Q2hpbGQoRnNMaXN0Q29tcG9uZW50KVxuICBwdWJsaWMgbGlzdDogRnNMaXN0Q29tcG9uZW50O1xuXG4gIEBWaWV3Q2hpbGQoJ3N1Ym1pdCcsIHsgc3RhdGljOiBmYWxzZSB9KVxuICBwdWJsaWMgc3VibWl0QnV0dG9uOiBNYXRCdXR0b247XG5cbiAgcHVibGljIGFjbFJvbGU6IEFjbFJvbGUgPSBudWxsO1xuICBwdWJsaWMgZW52aXJvbm1lbnQ7XG4gIHB1YmxpYyBwZXJtaXNzaW9uczogYW55W10gPSBbXTtcbiAgcHVibGljIGxpc3RDb25maWc6IEZzTGlzdENvbmZpZztcbiAgcHVibGljIGxldmVsUGVybWlzc2lvbnMgPSBbXTtcbiAgcHVibGljIEFjbFJvbGVBY2Nlc3NlcyA9IEFjbFJvbGVBY2Nlc3NlcztcbiAgcHVibGljIGluZGV4ZWRBY2Nlc3NlcyA9IHt9O1xuICBwdWJsaWMgYWNsTGV2ZWxzOiBhbnlbXSA9IFtdO1xuICBwdWJsaWMgaW5kZXhlZEFjbExldmVscyA9IHt9O1xuICBwdWJsaWMgb25seUZ1bGxBY2Nlc3MgPSBmYWxzZTtcbiAgcHVibGljIEFjbExldmVscyA9IHt9O1xuICBwdWJsaWMgcm9sZUNvbmZpZ3M6IFJvbGVDb25maWdbXSA9IFtdO1xuICBwdWJsaWMgYWNsUm9sZUNvbmZpZ1ZhbHVlcyA9IHt9O1xuICBwdWJsaWMgYWNsUm9sZVBlcm1pc3Npb25zID0ge307XG4gIHB1YmxpYyBsb2FkUm9sZUNvbmZpZ3M6IChhY2xSb2xlOiBBY2xSb2xlLCBxdWVyeSkgPT4gT2JzZXJ2YWJsZTxSb2xlQ29uZmlnW10+O1xuICBwdWJsaWMgZGlzYWJsZWQ6IGJvb2xlYW47XG5cbiAgcHJpdmF0ZSBfZGVzdHJveSQgPSBuZXcgU3ViamVjdCgpO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIEBJbmplY3QoTUFUX0RJQUxPR19EQVRBKSBwcml2YXRlIHJlYWRvbmx5IF9kYXRhOiBhbnksXG4gICAgcHJpdmF0ZSByZWFkb25seSBfYXBwQWNsU2VydmljZTogRnNBcHBBY2xTZXJ2aWNlLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgX2RpYWxvZ1JlZjogTWF0RGlhbG9nUmVmPEZzQWNsUm9sZUNvbXBvbmVudD4sXG4gICAgcHJpdmF0ZSByZWFkb25seSBfbWVzc2FnZTogRnNNZXNzYWdlLFxuICAgIHByaXZhdGUgX2NkUmVmOiBDaGFuZ2VEZXRlY3RvclJlZixcbiAgKSB7IH1cblxuICBwdWJsaWMgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgZm9ya0pvaW4oXG4gICAgICB0aGlzLmdldFJvbGUoKSxcbiAgICAgIHRoaXMuX2FwcEFjbFNlcnZpY2UuZ2V0UGVybWlzc2lvbnMoKSxcbiAgICApXG4gICAgICAucGlwZSh0YWtlVW50aWwodGhpcy5fZGVzdHJveSQpKVxuICAgICAgLnN1YnNjcmliZSgoW1xuICAgICAgICBhY2xSb2xlLFxuICAgICAgICBhY2xQZXJtaXNzaW9ucyxcbiAgICAgIF0pID0+IHtcblxuICAgICAgICB0aGlzLnBlcm1pc3Npb25zID0gYWNsUGVybWlzc2lvbnM7XG4gICAgICAgIHRoaXMuYWNsTGV2ZWxzID0gdGhpcy5fZGF0YS5hY2xMZXZlbHM7XG4gICAgICAgIHRoaXMuZGlzYWJsZWQgPSB0aGlzLl9kYXRhLmRpc2FibGVkO1xuXG4gICAgICAgIHRoaXMuaW5kZXhlZEFjbExldmVscyA9IGxpc3QodGhpcy5hY2xMZXZlbHMsICduYW1lJywgJ3ZhbHVlJyk7XG4gICAgICAgIHRoaXMuaW5kZXhlZEFjY2Vzc2VzID0gbGlzdChBY2xSb2xlQWNjZXNzZXMsICduYW1lJywgJ3ZhbHVlJyk7XG5cbiAgICAgICAgdGhpcy5hY2xSb2xlID0ge1xuICAgICAgICAgIC4uLntcbiAgICAgICAgICAgIGFjbFBlcm1pc3Npb25zOiBbXSxcbiAgICAgICAgICAgIGFsbFBlcm1pc3Npb25zOiB0cnVlLFxuICAgICAgICAgICAgYWNsUm9sZUNvbmZpZ3M6IFtdLFxuICAgICAgICAgICAgcGVybWlzc2lvbnM6IHt9LFxuICAgICAgICAgICAgbGV2ZWw6IHRoaXMuYWNsTGV2ZWxzWzBdLnZhbHVlLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgLi4uYWNsUm9sZSxcbiAgICAgICAgfTtcblxuICAgICAgICB0aGlzLmFjbFJvbGVDb25maWdWYWx1ZXMgPSAoYWNsUm9sZS5hY2xSb2xlQ29uZmlncyB8fCBbXSlcbiAgICAgICAgICAucmVkdWNlKChhY2N1bSwgYWNsUm9sZUNvbmZpZykgPT4ge1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgLi4uYWNjdW0sXG4gICAgICAgICAgICAgIFthY2xSb2xlQ29uZmlnLm5hbWVdOiBhY2xSb2xlQ29uZmlnLnZhbHVlLFxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sIHt9KTtcblxuICAgICAgICBpZiAodGhpcy5hY2xSb2xlLmlkKSB7XG4gICAgICAgICAgdGhpcy5wZXJtaXNzaW9ucy5mb3JFYWNoKChwZXJtaXNzaW9uKSA9PiB7XG4gICAgICAgICAgICBsZXQgYWNjZXNzID0gMDtcblxuICAgICAgICAgICAgY29uc3QgYWNsUGVybWlzc2lvbiA9IHRoaXMuYWNsUm9sZS5hY2xQZXJtaXNzaW9ucy5maW5kKChpdGVtKSA9PiB7XG4gICAgICAgICAgICAgIHJldHVybiBpdGVtLnBlcm1pc3Npb24gPT09IHBlcm1pc3Npb24udmFsdWU7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgaWYgKGFjbFBlcm1pc3Npb24pIHtcbiAgICAgICAgICAgICAgYWNjZXNzID0gYWNsUGVybWlzc2lvbi5hY2Nlc3M7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuYWNsUm9sZVBlcm1pc3Npb25zW3Blcm1pc3Npb24udmFsdWVdID0gYWNjZXNzO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuYWNsUm9sZS5hbGxQZXJtaXNzaW9ucykge1xuICAgICAgICAgIHRoaXMuX2FwcGx5TWF4UGVybWlzc2lvbkFjY2VzcygpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fdXBkYXRlUGVybWlzc2lvbnMoKTtcbiAgICAgICAgdGhpcy5fdXBkYXRlUm9sZUNvbmZpZ3MoKTtcblxuICAgICAgICB0aGlzLl9jZFJlZi5tYXJrRm9yQ2hlY2soKTtcbiAgICAgIH0pO1xuXG4gICAgdGhpcy5saXN0Q29uZmlnID0ge1xuICAgICAgc3RhdHVzOiBmYWxzZSxcbiAgICAgIHBhZ2luZzogZmFsc2UsXG4gICAgICByb3dIb3ZlckhpZ2hsaWdodDogZmFsc2UsXG4gICAgICBub1Jlc3VsdHM6IHtcbiAgICAgICAgbWVzc2FnZTogJycsXG4gICAgICB9LFxuICAgICAgZ3JvdXA6IHtcbiAgICAgICAgaW5pdGlhbEV4cGFuZDogdHJ1ZSxcbiAgICAgICAgZ3JvdXBCeTogKGRhdGEpID0+IHtcbiAgICAgICAgICByZXR1cm4gZGF0YTtcbiAgICAgICAgfSxcbiAgICAgICAgY29tcGFyZUJ5OiAoZGF0YSkgPT4ge1xuICAgICAgICAgIHJldHVybiBkYXRhLmNhdGVnb3J5IHx8ICdHZW5lcmFsJztcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgICBmZXRjaDogKCkgPT4ge1xuICAgICAgICByZXR1cm4gb2Yoe1xuICAgICAgICAgIGRhdGE6IHRoaXMubGV2ZWxQZXJtaXNzaW9ucy5zb3J0KChhLCBiKSA9PiB7XG4gICAgICAgICAgICBhID0gYS5uYW1lLnRvVXBwZXJDYXNlKCk7XG4gICAgICAgICAgICBiID0gYi5uYW1lLnRvVXBwZXJDYXNlKCk7XG4gICAgICAgICAgICBpZiAoYSA8IGIpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChhID4gYikge1xuICAgICAgICAgICAgICByZXR1cm4gMTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgICAgfSksXG4gICAgICAgIH0pO1xuICAgICAgfSxcbiAgICB9O1xuICB9XG5cbiAgcHVibGljIGJ1bGtDaGFuZ2UodmFsdWU6IG51bWJlciwgZ3JvdXBDaGlsZHJlbiwgZ3JvdXApOiB2b2lkIHtcbiAgICBncm91cENoaWxkcmVuXG4gICAgICAuZm9yRWFjaCgocGVybWlzc2lvbikgPT4ge1xuICAgICAgICBjb25zdCBhY2Nlc3MgPSBwZXJtaXNzaW9uLmFjY2Vzc2VzXG4gICAgICAgICAgLmZpbmQoKGFjY2VzcykgPT4gdmFsdWUgPT09IGFjY2Vzcyk7XG5cbiAgICAgICAgaWYoYWNjZXNzIHx8ICF2YWx1ZSkge1xuICAgICAgICAgIHRoaXMuYWNsUm9sZVBlcm1pc3Npb25zW3Blcm1pc3Npb24udmFsdWVdID0gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICB0aGlzLnN1Ym1pdEJ1dHRvbi5kaXNhYmxlZCA9IGZhbHNlO1xuICAgICAgdGhpcy5wZXJtaXNzaW9uQ2hhbmdlKCk7XG4gICAgfSk7XG4gIH1cblxuICBwdWJsaWMgcGVybWlzc2lvbkNoYW5nZSgpOiB2b2lkIHtcbiAgICB0aGlzLmFjbFJvbGVQZXJtaXNzaW9ucyA9IHtcbiAgICAgIC4uLnRoaXMuYWNsUm9sZVBlcm1pc3Npb25zLCAgICAgICAgXG4gICAgfTtcbiAgICB0aGlzLl9jZFJlZi5tYXJrRm9yQ2hlY2soKTtcbiAgfVxuXG4gIHB1YmxpYyBsZXZlbENoYW5nZSgpOiB2b2lkIHtcbiAgICB0aGlzLl91cGRhdGVQZXJtaXNzaW9ucygpO1xuICAgIHRoaXMuX3VwZGF0ZVJvbGVDb25maWdzKCk7XG4gICAgdGhpcy5saXN0LnJlbG9hZCgpO1xuICB9XG5cbiAgcHVibGljIGdldFJvbGUoKTogT2JzZXJ2YWJsZTxhbnk+IHtcbiAgICBpZiAoIXRoaXMuX2RhdGEuYWNsUm9sZS5pZCkge1xuICAgICAgcmV0dXJuIG9mKHRoaXMuX2RhdGEuYWNsUm9sZSk7XG4gICAgfVxuXG4gICAgY29uc3QgcXVlcnk6IGFueSA9IHtcbiAgICAgIGFjbFBlcm1pc3Npb25zOiB0cnVlLFxuICAgICAgYWNsUm9sZUNvbmZpZ3M6IHRydWUsXG4gICAgfTtcblxuICAgIGlmICghdGhpcy5lbnZpcm9ubWVudCkge1xuICAgICAgcXVlcnkuZW52aXJvbm1lbnRJZCA9IG51bGw7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuX2RhdGEubG9hZEFjbFJvbGUodGhpcy5fZGF0YS5hY2xSb2xlLCBxdWVyeSk7XG4gIH1cblxuICBwdWJsaWMgc2F2ZSA9ICgpOiBPYnNlcnZhYmxlPGFueT4gPT4ge1xuICAgIGNvbnN0IGFjbFJvbGVDb25maWdzID0gdGhpcy5yb2xlQ29uZmlnc1xuICAgICAgLm1hcCgocm9sZUNvbmZpZykgPT4ge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIG5hbWU6IHJvbGVDb25maWcubmFtZSxcbiAgICAgICAgICB2YWx1ZTogdGhpcy5hY2xSb2xlQ29uZmlnVmFsdWVzW3JvbGVDb25maWcubmFtZV0sXG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgY29uc3QgYWNsUm9sZSA9IHtcbiAgICAgIC4uLnRoaXMuYWNsUm9sZSxcbiAgICAgIHBlcm1pc3Npb25zOiB0aGlzLmxldmVsUGVybWlzc2lvbnMubWFwKChwZXJtaXNzaW9uKSA9PiB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgdmFsdWU6IHBlcm1pc3Npb24udmFsdWUsXG4gICAgICAgICAgYWNjZXNzOiB0aGlzLmFjbFJvbGVQZXJtaXNzaW9uc1twZXJtaXNzaW9uLnZhbHVlXSB8fCAwLFxuICAgICAgICB9O1xuICAgICAgfSksXG4gICAgICBhY2xSb2xlQ29uZmlncyxcbiAgICB9O1xuXG4gICAgcmV0dXJuIHRoaXMuX2RhdGEuc2F2ZUFjbFJvbGUoYWNsUm9sZSlcbiAgICAgIC5waXBlKFxuICAgICAgICB0YXAoKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgdGhpcy5fbWVzc2FnZS5zdWNjZXNzKCdTYXZlZCBDaGFuZ2VzJyk7XG4gICAgICAgICAgdGhpcy5jbG9zZShyZXNwb25zZSk7XG4gICAgICAgIH0pLFxuICAgICAgKTtcbiAgfVxuXG4gIHB1YmxpYyBjbG9zZShkYXRhOiBhbnkgPSBudWxsKTogdm9pZCB7XG4gICAgdGhpcy5fZGlhbG9nUmVmLmNsb3NlKGRhdGEpO1xuICB9XG5cbiAgcHVibGljIGFsbFBlcm1pc3Npb25zQ2hhbmdlKGFsbDogYm9vbGVhbik6IHZvaWQge1xuICAgIHRoaXMuX3VwZGF0ZVBlcm1pc3Npb25zKCk7XG4gICAgaWYgKGFsbCkge1xuICAgICAgdGhpcy5fYXBwbHlNYXhQZXJtaXNzaW9uQWNjZXNzKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuX2FwcGx5Tm9uZVBlcm1pc3Npb25BY2Nlc3MoKTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy5fZGVzdHJveSQubmV4dCgpO1xuICAgIHRoaXMuX2Rlc3Ryb3kkLmNvbXBsZXRlKCk7XG4gIH1cblxuICBwcml2YXRlIF91cGRhdGVQZXJtaXNzaW9ucygpOiB2b2lkIHtcbiAgICB0aGlzLmxldmVsUGVybWlzc2lvbnMgPSB0aGlzLnBlcm1pc3Npb25zXG4gICAgLmZpbHRlcigocGVybWlzc2lvbikgPT4ge1xuICAgICAgcmV0dXJuIHBlcm1pc3Npb24ubGV2ZWxzLnNvbWUoKGl0ZW0pID0+IHtcbiAgICAgICAgcmV0dXJuIGl0ZW0gPT09IHRoaXMuYWNsUm9sZS5sZXZlbDtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBfdXBkYXRlUm9sZUNvbmZpZ3MoKTogdm9pZCB7XG4gICAgaWYodGhpcy5fZGF0YS5sb2FkUm9sZUNvbmZpZ3MpIHtcbiAgICAgIHRoaXMuX2RhdGEubG9hZFJvbGVDb25maWdzKClcbiAgICAgIC5zdWJzY3JpYmUoKHJvbGVDb25maWdzOiBSb2xlQ29uZmlnW10pID0+IHtcbiAgICAgICAgdGhpcy5yb2xlQ29uZmlncyA9IHJvbGVDb25maWdzXG4gICAgICAgICAgLmZpbHRlcigocm9sZUNvbmZpZykgPT4gcm9sZUNvbmZpZy5sZXZlbCA9PT0gdGhpcy5hY2xSb2xlLmxldmVsKTtcbiAgICAgICAgdGhpcy5fY2RSZWYubWFya0ZvckNoZWNrKCk7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIF9hcHBseU1heFBlcm1pc3Npb25BY2Nlc3MoKTogdm9pZCB7XG4gICAgdGhpcy5wZXJtaXNzaW9ucy5mb3JFYWNoKChwZXJtaXNzaW9uKSA9PiB7XG4gICAgICB0aGlzLmFjbFJvbGVQZXJtaXNzaW9uc1twZXJtaXNzaW9uLnZhbHVlXSA9IE1hdGgubWF4KC4uLnBlcm1pc3Npb24uYWNjZXNzZXMpO1xuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBfYXBwbHlOb25lUGVybWlzc2lvbkFjY2VzcygpOiB2b2lkIHtcbiAgICB0aGlzLnBlcm1pc3Npb25zLmZvckVhY2goKHBlcm1pc3Npb24pID0+IHtcbiAgICAgIHRoaXMuYWNsUm9sZVBlcm1pc3Npb25zW3Blcm1pc3Npb24udmFsdWVdID0gQWNsUm9sZUFjY2Vzcy5Ob25lO1xuICAgIH0pO1xuICB9XG5cbn1cbiIsIjxmb3JtIGZzRm9ybSBbc3VibWl0XT1cInNhdmVcIj5cbiAgPGZzLWRpYWxvZz5cbiAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiYWNsUm9sZVwiPlxuICAgICAgPGRpdiBtYXQtZGlhbG9nLXRpdGxlPlxuICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiIWRpc2FibGVkXCI+e3sgYWNsUm9sZS5pZCA/ICdFZGl0JyA6ICdDcmVhdGUnIH19PC9uZy1jb250YWluZXI+XG4gICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJkaXNhYmxlZFwiPlZpZXc8L25nLWNvbnRhaW5lcj5cbiAgICAgICAgUm9sZVxuICAgICAgPC9kaXY+XG4gICAgICA8bWF0LWRpYWxvZy1jb250ZW50PlxuICAgICAgICA8ZGl2IGNsYXNzPVwiZnMtcm93LmdhcC1sYXJnZS5hbGlnbi1zdGFydFwiPlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJmcy1jb2x1bW4gbGVmdC1jb2x1bW5cIj5cbiAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZD4gICAgICAgICAgICBcbiAgICAgICAgICAgICAgPG1hdC1sYWJlbD5OYW1lPC9tYXQtbGFiZWw+XG4gICAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJhY2xSb2xlLm5hbWVcIlxuICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCJkaXNhYmxlZFwiXG4gICAgICAgICAgICAgICAgbmFtZT1cIm5hbWVcIlxuICAgICAgICAgICAgICAgIGZzRm9ybVJlcXVpcmVkPlxuICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cblxuICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgICA8bWF0LWxhYmVsPkRlc2NyaXB0aW9uPC9tYXQtbGFiZWw+XG4gICAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICAgIG1hdElucHV0XG4gICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJhY2xSb2xlLmRlc2NyaXB0aW9uXCJcbiAgICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxuICAgICAgICAgICAgICAgIG5hbWU9XCJkZXNjcmlwdGlvblwiPlxuICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cblxuICAgICAgICAgICAgPGZzLWxhYmVsLWZpZWxkICpuZ0lmPVwiYWNsUm9sZS5pZCB8fCBhY2xMZXZlbHMubGVuZ3RoID09PSAxOyBlbHNlIGxldmVsc1wiPlxuICAgICAgICAgICAgICA8ZnMtbGFiZWw+TGV2ZWw8L2ZzLWxhYmVsPlxuICAgICAgICAgICAgICB7e2luZGV4ZWRBY2xMZXZlbHNbYWNsUm9sZS5sZXZlbF19fVxuICAgICAgICAgICAgPC9mcy1sYWJlbC1maWVsZD5cblxuICAgICAgICAgICAgPG5nLXRlbXBsYXRlICNsZXZlbHM+XG4gICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJsZXZlbFwiPlxuICAgICAgICAgICAgICAgIDxmcy1yYWRpby1ncm91cFxuICAgICAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cImFjbFJvbGUubGV2ZWxcIlxuICAgICAgICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxuICAgICAgICAgICAgICAgICAgICAobmdNb2RlbENoYW5nZSk9XCJsZXZlbENoYW5nZSgpXCJcbiAgICAgICAgICAgICAgICAgICAgZnNGb3JtUmVxdWlyZWRcbiAgICAgICAgICAgICAgICAgICAgbGFiZWw9XCJMZXZlbFwiXG4gICAgICAgICAgICAgICAgICAgIG9yaWVudGF0aW9uPVwidmVydGljYWxcIlxuICAgICAgICAgICAgICAgICAgICBuYW1lPVwibGV2ZWxcIj5cbiAgICAgICAgICAgICAgICAgIDxtYXQtcmFkaW8tYnV0dG9uXG4gICAgICAgICAgICAgICAgICAgICAgKm5nRm9yPVwibGV0IGl0ZW0gb2YgYWNsTGV2ZWxzXCJcbiAgICAgICAgICAgICAgICAgICAgICBbdmFsdWVdPVwiaXRlbS52YWx1ZVwiXG4gICAgICAgICAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cIiEhYWNsUm9sZS5wcm90ZWN0ZWRcIj5cbiAgICAgICAgICAgICAgICAgICAge3sgaXRlbS5uYW1lIH19XG4gICAgICAgICAgICAgICAgICA8L21hdC1yYWRpby1idXR0b24+XG4gICAgICAgICAgICAgICAgPC9mcy1yYWRpby1ncm91cD5cbiAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuXG4gICAgICAgICAgICA8ZnMtbGFiZWwtZmllbGQgKm5nSWY9XCJsZXZlbFBlcm1pc3Npb25zLmxlbmd0aFwiPlxuICAgICAgICAgICAgICA8ZnMtbGFiZWw+QWxsIFBlcm1pc3Npb25zPC9mcy1sYWJlbD5cbiAgICAgICAgICAgICAgPG1hdC1jaGVja2JveFxuICAgICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJhY2xSb2xlLmFsbFBlcm1pc3Npb25zXCJcbiAgICAgICAgICAgICAgICAgIChuZ01vZGVsQ2hhbmdlKT1cImFsbFBlcm1pc3Npb25zQ2hhbmdlKCRldmVudClcIlxuICAgICAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cIiEhYWNsUm9sZS5wcm90ZWN0ZWQgfHwgZGlzYWJsZWRcIlxuICAgICAgICAgICAgICAgICAgbmFtZT1cImFsbFBlcm1pc3Npb25zXCI+XG4gICAgICAgICAgICAgICAgRW5hYmxlXG4gICAgICAgICAgICAgIDwvbWF0LWNoZWNrYm94PlxuICAgICAgICAgICAgPC9mcy1sYWJlbC1maWVsZD5cblxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZzLWNvbHVtblwiICpuZ0Zvcj1cImxldCByb2xlQ29uZmlnIG9mIHJvbGVDb25maWdzXCI+XG4gICAgICAgICAgICAgIDxmcy1sYWJlbC1maWVsZCAqbmdJZj1cInJvbGVDb25maWcudHlwZSA9PT0gJ2NoZWNrYm94J1wiPlxuICAgICAgICAgICAgICAgIDxmcy1sYWJlbD57e3JvbGVDb25maWcubGFiZWx9fTwvZnMtbGFiZWw+XG4gICAgICAgICAgICAgICAgPG1hdC1jaGVja2JveFxuICAgICAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cImFjbFJvbGVDb25maWdWYWx1ZXNbcm9sZUNvbmZpZy5uYW1lXVwiXG4gICAgICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCJkaXNhYmxlZFwiXG4gICAgICAgICAgICAgICAgICAgIFtuYW1lXT1cInJvbGVDb25maWcubmFtZVwiPlxuICAgICAgICAgICAgICAgICAgRW5hYmxlXG4gICAgICAgICAgICAgICAgPC9tYXQtY2hlY2tib3g+XG4gICAgICAgICAgICAgICAgPGZzLWxhYmVsLW1lc3NhZ2U+XG4gICAgICAgICAgICAgICAgICA8bWF0LWhpbnQ+e3tyb2xlQ29uZmlnLmRlc2NyaXB0aW9ufX08L21hdC1oaW50PlxuICAgICAgICAgICAgICAgIDwvZnMtbGFiZWwtbWVzc2FnZT5cbiAgICAgICAgICAgICAgPC9mcy1sYWJlbC1maWVsZD5cblxuICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgKm5nSWY9XCJyb2xlQ29uZmlnLnR5cGUgPT09ICdzZWxlY3QnXCI+XG4gICAgICAgICAgICAgICAgPG1hdC1zZWxlY3RcbiAgICAgICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJhY2xSb2xlQ29uZmlnVmFsdWVzW3JvbGVDb25maWcubmFtZV1cIlxuICAgICAgICAgICAgICAgICAgICBbbmFtZV09XCJyb2xlQ29uZmlnLm5hbWVcIlxuICAgICAgICAgICAgICAgICAgICBbcmVxdWlyZWRdPVwicm9sZUNvbmZpZy5yZXF1aXJlZFwiXG4gICAgICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCJkaXNhYmxlZFwiXG4gICAgICAgICAgICAgICAgICAgIFtwbGFjZWhvbGRlcl09XCJyb2xlQ29uZmlnLmxhYmVsXCI+XG4gICAgICAgICAgICAgICAgICA8bWF0LW9wdGlvblxuICAgICAgICAgICAgICAgICAgICAgICpuZ0Zvcj1cImxldCBpdGVtIG9mIHJvbGVDb25maWcudmFsdWVzXCJcbiAgICAgICAgICAgICAgICAgICAgICBbdmFsdWVdPVwiaXRlbS52YWx1ZVwiPlxuICAgICAgICAgICAgICAgICAgICB7eyBpdGVtLm5hbWUgfX1cbiAgICAgICAgICAgICAgICAgIDwvbWF0LW9wdGlvbj5cbiAgICAgICAgICAgICAgICA8L21hdC1zZWxlY3Q+XG4gICAgICAgICAgICAgICAgPG1hdC1oaW50Pnt7cm9sZUNvbmZpZy5kZXNjcmlwdGlvbn19PC9tYXQtaGludD5cbiAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgICAgPGRpdiAqbmdJZj1cImFjbFJvbGUubGV2ZWxcIiBbaGlkZGVuXT1cIiFsZXZlbFBlcm1pc3Npb25zLmxlbmd0aFwiIGNsYXNzPVwicGVybWlzc2lvbnMgZnMtY29sdW1uXCI+XG4gICAgICAgICAgICA8ZnMtbGlzdCBbY29uZmlnXT1cImxpc3RDb25maWdcIj5cbiAgICAgICAgICAgICAgPGZzLWxpc3QtY29sdW1uIHRpdGxlPVwiUGVybWlzc2lvbnNcIj5cbiAgICAgICAgICAgICAgICA8bmctdGVtcGxhdGUgZnMtbGlzdC1ncm91cC1jZWxsIGxldC1yb3c9XCJyb3dcIiBjbGFzcz1cInBlcm1pc3Npb24tZ3JvdXBcIj5cbiAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJwZXJtaXNzaW9uLWdyb3VwXCI+e3tyb3cuY2F0ZWdvcnkgfHwgJ0dlbmVyYWwnfX08L2Rpdj5cbiAgICAgICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICAgICAgICAgIDxuZy10ZW1wbGF0ZSBmcy1saXN0LWNlbGwgbGV0LXJvdz1cInJvd1wiPlxuICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInBlcm1pc3Npb25cIj57eyByb3cubmFtZSB9fTwvZGl2PlxuICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImRlc2NyaXB0aW9uIHNtYWxsXCI+e3sgcm93LmRlc2NyaXB0aW9uIH19PC9kaXY+XG4gICAgICAgICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgICAgICAgPC9mcy1saXN0LWNvbHVtbj5cbiAgICAgICAgICAgICAgPGZzLWxpc3QtY29sdW1uIHRpdGxlPVwiQWNjZXNzXCIgd2lkdGg9XCIxJVwiIGNsYXNzPVwiYWNjZXNzXCI+XG4gICAgICAgICAgICAgICAgPG5nLXRlbXBsYXRlIFxuICAgICAgICAgICAgICAgICAgICBmcy1saXN0LWdyb3VwLWNlbGxcbiAgICAgICAgICAgICAgICAgICAgbGV0LXJvdz1cInJvd1wiXG4gICAgICAgICAgICAgICAgICAgIGxldC1ncm91cD1cImdyb3VwXCJcbiAgICAgICAgICAgICAgICAgICAgbGV0LWdyb3VwQ2hpbGRyZW49XCJncm91cENoaWxkcmVuXCJcbiAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJwZXJtaXNzaW9uLWdyb3VwXCJcbiAgICAgICAgICAgICAgICAgICAgYWxpZ249XCJyaWdodFwiPlxuICAgICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cIiFhY2xSb2xlLmFsbFBlcm1pc3Npb25zICYmICFkaXNhYmxlZFwiPlxuICAgICAgICAgICAgICAgICAgICA8ZnMtbWVudT5cbiAgICAgICAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0Zvcj1cImxldCBhY2Nlc3Mgb2YgQWNsUm9sZUFjY2Vzc2VzIHwgYnVpbGtPcHRpb25zRmlsdGVyOiBncm91cENoaWxkcmVuXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8bmctdGVtcGxhdGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmcy1tZW51LWl0ZW1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoY2xpY2spPVwiYnVsa0NoYW5nZShhY2Nlc3MudmFsdWUsIGdyb3VwQ2hpbGRyZW4sIGdyb3VwKVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICB7eyBhY2Nlc3MubmFtZSB9fVxuICAgICAgICAgICAgICAgICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgICAgICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICAgICAgICAgICAgICAgICAgPC9mcy1tZW51PlxuICAgICAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgICAgICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgICAgICAgICA8bmctdGVtcGxhdGUgZnMtbGlzdC1jZWxsIGxldC1yb3c9XCJwZXJtaXNzaW9uXCIgbGV0LXBlcm1pc3Npb249XCJyb3dcIj5cbiAgICAgICAgICAgICAgICAgIDxzcGFuICpuZ0lmPVwiYWNsUm9sZS5hbGxQZXJtaXNzaW9ucyB8fCBkaXNhYmxlZDsgZWxzZSBlbHNlQWxsXCI+XG4gICAgICAgICAgICAgICAgICAgIHt7aW5kZXhlZEFjY2Vzc2VzW2FjbFJvbGVQZXJtaXNzaW9uc1twZXJtaXNzaW9uLnZhbHVlXV19fVxuICAgICAgICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgICAgICAgICAgPG5nLXRlbXBsYXRlICNlbHNlQWxsPlxuICAgICAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwicGVybWlzc2lvbnxhY2xSb2xlUGVybWlzc2lvbkF2YWlsYWJsZTphY2xSb2xlUGVybWlzc2lvbnM7IGVsc2UgcGVybWlzc2lvblJlcXVpcmVzXCI+XG4gICAgICAgICAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1zZWxlY3RcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cImFjbFJvbGVQZXJtaXNzaW9uc1twZXJtaXNzaW9uLnZhbHVlXVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cIiEhYWNsUm9sZS5wcm90ZWN0ZWRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlcXVpcmVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW25hbWVdPVwiJ2FjY2Vzcy0nICsgcGVybWlzc2lvbi52YWx1ZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwicGVybWlzc2lvbkNoYW5nZSgpXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nRm9yPVwibGV0IGFjY2VzcyBvZiBBY2xSb2xlQWNjZXNzZXNcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LW9wdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqbmdJZj1cImFjY2Vzcy52YWx1ZSA9PT0gMCB8fCBwZXJtaXNzaW9uLmFjY2Vzc2VzLmluZGV4T2YoYWNjZXNzLnZhbHVlKSAhPT0gLTFcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbdmFsdWVdPVwiYWNjZXNzLnZhbHVlXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7e2FjY2Vzcy5uYW1lfX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L21hdC1vcHRpb24+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxuICAgICAgICAgICAgICAgICAgICAgICAgPC9tYXQtc2VsZWN0PlxuICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxuICAgICAgICAgICAgICAgICAgICA8bmctdGVtcGxhdGUgI3Blcm1pc3Npb25SZXF1aXJlcz5cbiAgICAgICAgICAgICAgICAgICAgICBVbmF2YWlsYWJsZVxuICAgICAgICAgICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICAgICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICAgICAgICA8L2ZzLWxpc3QtY29sdW1uPlxuICAgICAgICAgICAgPC9mcy1saXN0PlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvbWF0LWRpYWxvZy1jb250ZW50PlxuICAgICAgPG1hdC1kaWFsb2ctYWN0aW9ucz5cbiAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgKm5nSWY9XCIhZGlzYWJsZWRcIlxuICAgICAgICAgICAgI3N1Ym1pdFxuICAgICAgICAgICAgbWF0LWJ1dHRvblxuICAgICAgICAgICAgdHlwZT1cInN1Ym1pdFwiXG4gICAgICAgICAgICBjb2xvcj1cInByaW1hcnlcIj5cbiAgICAgICAgICB7eyBhY2xSb2xlLmlkID8gJ1NhdmUnIDogJ0NyZWF0ZScgfX1cbiAgICAgICAgPC9idXR0b24+XG4gICAgICAgIDxidXR0b24gbWF0LWJ1dHRvbiBbbWF0LWRpYWxvZy1jbG9zZV09XCJudWxsXCIgdHlwZT1cImJ1dHRvblwiPnt7IGRpc2FibGVkID8gJ0RvbmUnIDogJ0NhbmNlbCcgfX08L2J1dHRvbj5cbiAgICAgIDwvbWF0LWRpYWxvZy1hY3Rpb25zPlxuICAgIDwvbmctY29udGFpbmVyPlxuICA8L2ZzLWRpYWxvZz5cbjwvZm9ybT5cbiJdfQ==