@alfresco/adf-content-services
Version:
Alfresco ADF content services
103 lines • 34.8 kB
JavaScript
/*!
* @license
* Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { SearchConfigurationService } from '../../../search/services/search-configuration.service';
import { SearchService } from '../../../search/services/search.service';
import { Node, NodeEntry } from '@alfresco/js-api';
import { Component, EventEmitter, Output, ViewChild, ViewEncapsulation } from '@angular/core';
import { ReactiveFormsModule, UntypedFormControl } from '@angular/forms';
import { debounceTime } from 'rxjs/operators';
import { SearchPermissionConfigurationService } from './search-config-permission.service';
import { SearchComponent } from '../../../search/components/search.component';
import { MatListModule, MatSelectionList } from '@angular/material/list';
import { CommonModule } from '@angular/common';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { TranslateModule } from '@ngx-translate/core';
import { MatIconModule } from '@angular/material/icon';
import { UserIconColumnComponent } from '../user-icon-column/user-icon-column.component';
import * as i0 from "@angular/core";
import * as i1 from "@angular/common";
import * as i2 from "@angular/material/form-field";
import * as i3 from "@angular/material/input";
import * as i4 from "@ngx-translate/core";
import * as i5 from "@angular/forms";
import * as i6 from "@angular/material/icon";
import * as i7 from "@angular/material/list";
export class AddPermissionPanelComponent {
constructor() {
/** Emitted when a permission list item is selected. */
this.select = new EventEmitter();
this.searchInput = new UntypedFormControl();
this.searchedWord = '';
this.debounceSearch = 200;
this.selectedItems = [];
// eslint-disable-next-line @typescript-eslint/naming-convention
this.EVERYONE = new NodeEntry({
entry: new Node({ nodeType: 'cm:authorityContainer', properties: { 'cm:authorityName': 'GROUP_EVERYONE' } })
});
this.searchInput.valueChanges.pipe(debounceTime(this.debounceSearch)).subscribe((searchValue) => {
const selectionOptions = this.matSelectionList.selectedOptions.selected.map((option) => option.value);
this.selectedItems.push(...selectionOptions);
this.matSelectionList.deselectAll();
this.searchedWord = searchValue;
if (!searchValue) {
this.search.resetResults();
}
});
}
onSelectionChange() {
const currentSelection = this.matSelectionList.selectedOptions.selected.map((option) => option.value);
const uniqueSelection = [...currentSelection, ...this.selectedItems].reduce((uniquesElements, currentElement) => {
const isExist = uniquesElements.find((uniqueElement) => uniqueElement.entry.id === currentElement.entry.id);
if (!isExist) {
uniquesElements.push(currentElement);
}
return uniquesElements;
}, []);
this.select.emit(uniqueSelection);
}
clearSearch() {
this.searchedWord = '';
this.selectedItems.splice(0, this.selectedItems.length);
this.search.resetResults();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: AddPermissionPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.1.3", type: AddPermissionPanelComponent, isStandalone: true, selector: "adf-add-permission-panel", outputs: { select: "select" }, providers: [{ provide: SearchConfigurationService, useClass: SearchPermissionConfigurationService }, SearchService], viewQueries: [{ propertyName: "search", first: true, predicate: ["search"], descendants: true, static: true }, { propertyName: "matSelectionList", first: true, predicate: MatSelectionList, descendants: true }], ngImport: i0, template: "<mat-form-field appearance=\"fill\" class=\"adf-permission-search-input\">\n <input\n matInput\n id=\"searchInput\"\n class=\"adf-permission-search-input-control\"\n [formControl]=\"searchInput\"\n type=\"text\"\n title=\"{{ 'PERMISSION_MANAGER.ADD-PERMISSION.SEARCH' | translate }}\"\n placeholder=\"{{ 'PERMISSION_MANAGER.ADD-PERMISSION.SEARCH' | translate }}\"\n [value]=\"searchedWord\"\n />\n\n <mat-icon\n *ngIf=\"searchedWord?.length > 0\"\n class=\"adf-permission-search-icon\"\n data-automation-id=\"adf-permission-clear-input\"\n id=\"adf-permission-clear-input\"\n matSuffix\n (click)=\"clearSearch()\"\n >clear\n </mat-icon>\n\n <mat-icon *ngIf=\"searchedWord?.length === 0\" class=\"adf-permission-search-icon\" data-automation-id=\"adf-permission-search-icon\" matSuffix\n >search\n </mat-icon>\n</mat-form-field>\n\n<div *ngIf=\"searchedWord?.length === 0\" class=\"adf-permission-start-message\" id=\"adf-add-permission-type-search\">\n <span>{{ 'PERMISSION_MANAGER.ADD-PERMISSION.TYPE-MESSAGE' | translate }}</span>\n</div>\n\n<adf-search\n #search\n [searchTerm]=\"searchedWord\"\n id=\"adf-add-permission-authority-results\"\n class=\"adf-permission-result-list\"\n [class.adf-permission-result-list-search]=\"searchedWord.length === 0\"\n>\n <ng-template let-data>\n <mat-selection-list\n class=\"adf-permission-result-list-elements\"\n title=\"{{ 'PERMISSION_MANAGER.ADD-PERMISSION.USER-GROUP-LIST' | translate }}\"\n (selectionChange)=\"onSelectionChange()\"\n >\n <mat-list-option id=\"adf-add-permission-group-everyone\" #eveyone [disableRipple]=\"true\" [value]=\"EVERYONE\">\n <div class=\"adf-list-option-item\">\n <adf-user-icon-column [node]=\"EVERYONE\" id=\"add-group-icon\" [selected]=\"eveyone.selected\" />\n <p class=\"adf-result-name\">\n {{ 'PERMISSION_MANAGER.ADD-PERMISSION.EVERYONE' | translate }}\n </p>\n </div>\n </mat-list-option>\n\n <mat-list-option\n *ngFor=\"let item of data?.list?.entries; let idx = index\"\n [disableRipple]=\"true\"\n [value]=\"item\"\n id=\"result_option_{{ idx }}\"\n #option\n >\n <div class=\"adf-list-option-item\">\n <adf-user-icon-column [node]=\"item\" [selected]=\"option.selected\" />\n <p class=\"adf-result-name\">\n <ng-container *ngIf=\"item.entry?.properties['cm:authorityDisplayName']; else authorityName\">\n {{ item.entry.properties['cm:authorityDisplayName'] }}\n </ng-container>\n <ng-template #authorityName>\n <ng-container *ngIf=\"item.entry?.properties['cm:authorityName']; else owner\">\n {{ item.entry.properties['cm:authorityName'] }}\n </ng-container>\n </ng-template>\n <ng-template #owner>\n {{ item.entry?.properties['cm:firstName'] ? item.entry?.properties['cm:firstName'] : '' }}\n {{ item.entry?.properties['cm:lastName'] ? item.entry?.properties['cm:lastName'] : '' }}\n </ng-template>\n </p>\n </div>\n </mat-list-option>\n </mat-selection-list>\n </ng-template>\n</adf-search>\n", styles: [".adf-permission-result-list{display:flex;height:calc(100% - 60px);overflow:auto;border:2px solid var(--adf-theme-foreground-text-color-007)}.adf-permission-result-list .mdc-list-item__end{display:none}.adf-permission-result-list-elements{width:100%}.adf-permission-result-list-search{display:none}.adf-list-option-item{display:flex;flex-direction:row;align-items:center}.adf-list-option-item .adf-result-name{padding-left:16px}.adf-permission-start-message{display:flex;align-items:center;justify-content:space-around;height:calc(100% - 60px);overflow:auto;border:2px solid var(--adf-theme-foreground-text-color-007)}.adf-permission-no-result{display:flex;align-items:center;justify-content:space-around;width:100%}.adf-permission-search-input{width:100%;padding-bottom:0;padding-top:12px}.adf-permission-search-input .mat-mdc-text-field-wrapper .mat-mdc-form-field-flex{align-items:center}.adf-permission-search-input .mat-mdc-text-field-wrapper .mat-mdc-form-field-flex .mat-mdc-form-field-infix{padding-top:0;padding-bottom:0}.adf-permission-search-input .mat-mdc-form-field-subscript-wrapper{height:16px}.adf-permission-search-input .adf-permission-search-input-control:focus::placeholder{color:var(--theme-primary-color)}.adf-permission-search-input .adf-permission-search-icon:is(mat-icon){padding:0 0 12px;width:1em;height:1em;font-size:20px;cursor:pointer}.adf-permission-search-input .adf-permission-search-icon:is(mat-icon):hover{color:var(--adf-theme-foreground-base-color)}.adf-permission-action[disabled]{opacity:.6}.adf-permission-action:enabled{color:var(--theme-primary-color)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i4.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: ReactiveFormsModule }, { 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.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i6.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatListModule }, { kind: "component", type: i7.MatSelectionList, selector: "mat-selection-list", inputs: ["color", "compareWith", "multiple", "hideSingleSelectionIndicator", "disabled"], outputs: ["selectionChange"], exportAs: ["matSelectionList"] }, { kind: "component", type: i7.MatListOption, selector: "mat-list-option", inputs: ["togglePosition", "checkboxPosition", "color", "value", "selected"], outputs: ["selectedChange"], exportAs: ["matListOption"] }, { kind: "component", type: UserIconColumnComponent, selector: "adf-user-icon-column", inputs: ["context", "node", "selected"] }, { kind: "component", type: SearchComponent, selector: "adf-search", inputs: ["displayWith", "maxResults", "skipResults", "searchTerm", "class"], outputs: ["resultLoaded", "error"], exportAs: ["searchAutocomplete"] }], encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: AddPermissionPanelComponent, decorators: [{
type: Component,
args: [{ selector: 'adf-add-permission-panel', standalone: true, imports: [
CommonModule,
MatFormFieldModule,
MatInputModule,
TranslateModule,
ReactiveFormsModule,
MatIconModule,
MatListModule,
UserIconColumnComponent,
SearchComponent
], encapsulation: ViewEncapsulation.None, providers: [{ provide: SearchConfigurationService, useClass: SearchPermissionConfigurationService }, SearchService], template: "<mat-form-field appearance=\"fill\" class=\"adf-permission-search-input\">\n <input\n matInput\n id=\"searchInput\"\n class=\"adf-permission-search-input-control\"\n [formControl]=\"searchInput\"\n type=\"text\"\n title=\"{{ 'PERMISSION_MANAGER.ADD-PERMISSION.SEARCH' | translate }}\"\n placeholder=\"{{ 'PERMISSION_MANAGER.ADD-PERMISSION.SEARCH' | translate }}\"\n [value]=\"searchedWord\"\n />\n\n <mat-icon\n *ngIf=\"searchedWord?.length > 0\"\n class=\"adf-permission-search-icon\"\n data-automation-id=\"adf-permission-clear-input\"\n id=\"adf-permission-clear-input\"\n matSuffix\n (click)=\"clearSearch()\"\n >clear\n </mat-icon>\n\n <mat-icon *ngIf=\"searchedWord?.length === 0\" class=\"adf-permission-search-icon\" data-automation-id=\"adf-permission-search-icon\" matSuffix\n >search\n </mat-icon>\n</mat-form-field>\n\n<div *ngIf=\"searchedWord?.length === 0\" class=\"adf-permission-start-message\" id=\"adf-add-permission-type-search\">\n <span>{{ 'PERMISSION_MANAGER.ADD-PERMISSION.TYPE-MESSAGE' | translate }}</span>\n</div>\n\n<adf-search\n #search\n [searchTerm]=\"searchedWord\"\n id=\"adf-add-permission-authority-results\"\n class=\"adf-permission-result-list\"\n [class.adf-permission-result-list-search]=\"searchedWord.length === 0\"\n>\n <ng-template let-data>\n <mat-selection-list\n class=\"adf-permission-result-list-elements\"\n title=\"{{ 'PERMISSION_MANAGER.ADD-PERMISSION.USER-GROUP-LIST' | translate }}\"\n (selectionChange)=\"onSelectionChange()\"\n >\n <mat-list-option id=\"adf-add-permission-group-everyone\" #eveyone [disableRipple]=\"true\" [value]=\"EVERYONE\">\n <div class=\"adf-list-option-item\">\n <adf-user-icon-column [node]=\"EVERYONE\" id=\"add-group-icon\" [selected]=\"eveyone.selected\" />\n <p class=\"adf-result-name\">\n {{ 'PERMISSION_MANAGER.ADD-PERMISSION.EVERYONE' | translate }}\n </p>\n </div>\n </mat-list-option>\n\n <mat-list-option\n *ngFor=\"let item of data?.list?.entries; let idx = index\"\n [disableRipple]=\"true\"\n [value]=\"item\"\n id=\"result_option_{{ idx }}\"\n #option\n >\n <div class=\"adf-list-option-item\">\n <adf-user-icon-column [node]=\"item\" [selected]=\"option.selected\" />\n <p class=\"adf-result-name\">\n <ng-container *ngIf=\"item.entry?.properties['cm:authorityDisplayName']; else authorityName\">\n {{ item.entry.properties['cm:authorityDisplayName'] }}\n </ng-container>\n <ng-template #authorityName>\n <ng-container *ngIf=\"item.entry?.properties['cm:authorityName']; else owner\">\n {{ item.entry.properties['cm:authorityName'] }}\n </ng-container>\n </ng-template>\n <ng-template #owner>\n {{ item.entry?.properties['cm:firstName'] ? item.entry?.properties['cm:firstName'] : '' }}\n {{ item.entry?.properties['cm:lastName'] ? item.entry?.properties['cm:lastName'] : '' }}\n </ng-template>\n </p>\n </div>\n </mat-list-option>\n </mat-selection-list>\n </ng-template>\n</adf-search>\n", styles: [".adf-permission-result-list{display:flex;height:calc(100% - 60px);overflow:auto;border:2px solid var(--adf-theme-foreground-text-color-007)}.adf-permission-result-list .mdc-list-item__end{display:none}.adf-permission-result-list-elements{width:100%}.adf-permission-result-list-search{display:none}.adf-list-option-item{display:flex;flex-direction:row;align-items:center}.adf-list-option-item .adf-result-name{padding-left:16px}.adf-permission-start-message{display:flex;align-items:center;justify-content:space-around;height:calc(100% - 60px);overflow:auto;border:2px solid var(--adf-theme-foreground-text-color-007)}.adf-permission-no-result{display:flex;align-items:center;justify-content:space-around;width:100%}.adf-permission-search-input{width:100%;padding-bottom:0;padding-top:12px}.adf-permission-search-input .mat-mdc-text-field-wrapper .mat-mdc-form-field-flex{align-items:center}.adf-permission-search-input .mat-mdc-text-field-wrapper .mat-mdc-form-field-flex .mat-mdc-form-field-infix{padding-top:0;padding-bottom:0}.adf-permission-search-input .mat-mdc-form-field-subscript-wrapper{height:16px}.adf-permission-search-input .adf-permission-search-input-control:focus::placeholder{color:var(--theme-primary-color)}.adf-permission-search-input .adf-permission-search-icon:is(mat-icon){padding:0 0 12px;width:1em;height:1em;font-size:20px;cursor:pointer}.adf-permission-search-input .adf-permission-search-icon:is(mat-icon):hover{color:var(--adf-theme-foreground-base-color)}.adf-permission-action[disabled]{opacity:.6}.adf-permission-action:enabled{color:var(--theme-primary-color)}\n"] }]
}], ctorParameters: () => [], propDecorators: { search: [{
type: ViewChild,
args: ['search', { static: true }]
}], matSelectionList: [{
type: ViewChild,
args: [MatSelectionList, { static: false }]
}], select: [{
type: Output
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWRkLXBlcm1pc3Npb24tcGFuZWwuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vbGliL2NvbnRlbnQtc2VydmljZXMvc3JjL2xpYi9wZXJtaXNzaW9uLW1hbmFnZXIvY29tcG9uZW50cy9hZGQtcGVybWlzc2lvbi9hZGQtcGVybWlzc2lvbi1wYW5lbC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9saWIvY29udGVudC1zZXJ2aWNlcy9zcmMvbGliL3Blcm1pc3Npb24tbWFuYWdlci9jb21wb25lbnRzL2FkZC1wZXJtaXNzaW9uL2FkZC1wZXJtaXNzaW9uLXBhbmVsLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7R0FlRztBQUVILE9BQU8sRUFBRSwwQkFBMEIsRUFBRSxNQUFNLHVEQUF1RCxDQUFDO0FBQ25HLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSx5Q0FBeUMsQ0FBQztBQUN4RSxPQUFPLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQ25ELE9BQU8sRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFFLE1BQU0sRUFBRSxTQUFTLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDOUYsT0FBTyxFQUFFLG1CQUFtQixFQUFFLGtCQUFrQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDekUsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzlDLE9BQU8sRUFBRSxvQ0FBb0MsRUFBRSxNQUFNLG9DQUFvQyxDQUFDO0FBQzFGLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSw2Q0FBNkMsQ0FBQztBQUM5RSxPQUFPLEVBQUUsYUFBYSxFQUFFLGdCQUFnQixFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDekUsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlC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eEQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxZQUFZLEVBQUUsQ0FBQztJQUMvQixDQUFDOzhHQWxEUSwyQkFBMkI7a0dBQTNCLDJCQUEyQixzR0FGekIsQ0FBQyxFQUFFLE9BQU8sRUFBRSwwQkFBMEIsRUFBRSxRQUFRLEVBQUUsb0NBQW9DLEVBQUUsRUFBRSxhQUFhLENBQUMsNktBTXhHLGdCQUFnQixnREN4RC9CLDZvSEFpRkEsb25ERDVDUSxZQUFZLCtQQUNaLGtCQUFrQiwwV0FDbEIsY0FBYywwV0FDZCxlQUFlLDJGQUNmLG1CQUFtQix5a0JBQ25CLGFBQWEsbUxBQ2IsYUFBYSw2ZEFDYix1QkFBdUIsMEdBQ3ZCLGVBQWU7OzJGQU9WLDJCQUEyQjtrQkFuQnZDLFNBQVM7K0JBQ0ksMEJBQTBCLGNBQ3hCLElBQUksV0FDUDt3QkFDTCxZQUFZO3dCQUNaLGtCQUFrQjt3QkFDbEIsY0FBYzt3QkFDZCxlQUFlO3dCQUNmLG1CQUFtQjt3QkFDbkIsYUFBYTt3QkFDYixhQUFhO3dCQUNiLHVCQUF1Qjt3QkFDdkIsZUFBZTtxQkFDbEIsaUJBR2MsaUJBQWlCLENBQUMsSUFBSSxhQUMxQixDQUFDLEVBQUUsT0FBTyxFQUFFLDBCQUEwQixFQUFFLFFBQVEsRUFBRSxvQ0FBb0MsRUFBRSxFQUFFLGFBQWEsQ0FBQzt3REFJbkgsTUFBTTtzQkFETCxTQUFTO3VCQUFDLFFBQVEsRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUU7Z0JBSXJDLGdCQUFnQjtzQkFEZixTQUFTO3VCQUFDLGdCQUFnQixFQUFFLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRTtnQkFLOUMsTUFBTTtzQkFETCxNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiLyohXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IMKpIDIwMDUtMjAyNSBIeWxhbmQgU29mdHdhcmUsIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBTZWFyY2hDb25maWd1cmF0aW9uU2VydmljZSB9IGZyb20gJy4uLy4uLy4uL3NlYXJjaC9zZXJ2aWNlcy9zZWFyY2gtY29uZmlndXJhdGlvbi5zZXJ2aWNlJztcbmltcG9ydCB7IFNlYXJjaFNlcnZpY2UgfSBmcm9tICcuLi8uLi8uLi9zZWFyY2gvc2VydmljZXMvc2VhcmNoLnNlcnZpY2UnO1xuaW1wb3J0IHsgTm9kZSwgTm9kZUVudHJ5IH0gZnJvbSAnQGFsZnJlc2NvL2pzLWFwaSc7XG5pbXBvcnQgeyBDb21wb25lbnQsIEV2ZW50RW1pdHRlciwgT3V0cHV0LCBWaWV3Q2hpbGQsIFZpZXdFbmNhcHN1bGF0aW9uIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBSZWFjdGl2ZUZvcm1zTW9kdWxlLCBVbnR5cGVkRm9ybUNvbnRyb2wgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBkZWJvdW5jZVRpbWUgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgeyBTZWFyY2hQZXJtaXNzaW9uQ29uZmlndXJhdGlvblNlcnZpY2UgfSBmcm9tICcuL3NlYXJjaC1jb25maWctcGVybWlzc2lvbi5zZXJ2aWNlJztcbmltcG9ydCB7IFNlYXJjaENvbXBvbmVudCB9IGZyb20gJy4uLy4uLy4uL3NlYXJjaC9jb21wb25lbnRzL3NlYXJjaC5jb21wb25lbnQnO1xuaW1wb3J0IHsgTWF0TGlzdE1vZHVsZSwgTWF0U2VsZWN0aW9uTGlzdCB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2xpc3QnO1xuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7IE1hdEZvcm1GaWVsZE1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2Zvcm0tZmllbGQnO1xuaW1wb3J0IHsgTWF0SW5wdXRNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9pbnB1dCc7XG5pbXBvcnQgeyBUcmFuc2xhdGVNb2R1bGUgfSBmcm9tICdAbmd4LXRyYW5zbGF0ZS9jb3JlJztcbmltcG9ydCB7IE1hdEljb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9pY29uJztcbmltcG9ydCB7IFVzZXJJY29uQ29sdW1uQ29tcG9uZW50IH0gZnJvbSAnLi4vdXNlci1pY29uLWNvbHVtbi91c2VyLWljb24tY29sdW1uLmNvbXBvbmVudCc7XG5cbkBDb21wb25lbnQoe1xuICAgIHNlbGVjdG9yOiAnYWRmLWFkZC1wZXJtaXNzaW9uLXBhbmVsJyxcbiAgICBzdGFuZGFsb25lOiB0cnVlLFxuICAgIGltcG9ydHM6IFtcbiAgICAgICAgQ29tbW9uTW9kdWxlLFxuICAgICAgICBNYXRGb3JtRmllbGRNb2R1bGUsXG4gICAgICAgIE1hdElucHV0TW9kdWxlLFxuICAgICAgICBUcmFuc2xhdGVNb2R1bGUsXG4gICAgICAgIFJlYWN0aXZlRm9ybXNNb2R1bGUsXG4gICAgICAgIE1hdEljb25Nb2R1bGUsXG4gICAgICAgIE1hdExpc3RNb2R1bGUsXG4gICAgICAgIFVzZXJJY29uQ29sdW1uQ29tcG9uZW50LFxuICAgICAgICBTZWFyY2hDb21wb25lbnRcbiAgICBdLFxuICAgIHRlbXBsYXRlVXJsOiAnLi9hZGQtcGVybWlzc2lvbi1wYW5lbC5jb21wb25lbnQuaHRtbCcsXG4gICAgc3R5bGVVcmxzOiBbJy4vYWRkLXBlcm1pc3Npb24tcGFuZWwuY29tcG9uZW50LnNjc3MnXSxcbiAgICBlbmNhcHN1bGF0aW9uOiBWaWV3RW5jYXBzdWxhdGlvbi5Ob25lLFxuICAgIHByb3ZpZGVyczogW3sgcHJvdmlkZTogU2VhcmNoQ29uZmlndXJhdGlvblNlcnZpY2UsIHVzZUNsYXNzOiBTZWFyY2hQZXJtaXNzaW9uQ29uZmlndXJhdGlvblNlcnZpY2UgfSwgU2VhcmNoU2VydmljZV1cbn0pXG5leHBvcnQgY2xhc3MgQWRkUGVybWlzc2lvblBhbmVsQ29tcG9uZW50IHtcbiAgICBAVmlld0NoaWxkKCdzZWFyY2gnLCB7IHN0YXRpYzogdHJ1ZSB9KVxuICAgIHNlYXJjaDogU2VhcmNoQ29tcG9uZW50O1xuXG4gICAgQFZpZXdDaGlsZChNYXRTZWxlY3Rpb25MaXN0LCB7IHN0YXRpYzogZmFsc2UgfSlcbiAgICBtYXRTZWxlY3Rpb25MaXN0OiBNYXRTZWxlY3Rpb25MaXN0O1xuXG4gICAgLyoqIEVtaXR0ZWQgd2hlbiBhIHBlcm1pc3Npb24gbGlzdCBpdGVtIGlzIHNlbGVjdGVkLiAqL1xuICAgIEBPdXRwdXQoKVxuICAgIHNlbGVjdDogRXZlbnRFbWl0dGVyPE5vZGVFbnRyeVtdPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICAgIHNlYXJjaElucHV0OiBVbnR5cGVkRm9ybUNvbnRyb2wgPSBuZXcgVW50eXBlZEZvcm1Db250cm9sKCk7XG4gICAgc2VhcmNoZWRXb3JkID0gJyc7XG4gICAgZGVib3VuY2VTZWFyY2g6IG51bWJlciA9IDIwMDtcblxuICAgIHNlbGVjdGVkSXRlbXM6IE5vZGVFbnRyeVtdID0gW107XG5cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25hbWluZy1jb252ZW50aW9uXG4gICAgRVZFUllPTkU6IE5vZGVFbnRyeSA9IG5ldyBOb2RlRW50cnkoe1xuICAgICAgICBlbnRyeTogbmV3IE5vZGUoeyBub2RlVHlwZTogJ2NtOmF1dGhvcml0eUNvbnRhaW5lcicsIHByb3BlcnRpZXM6IHsgJ2NtOmF1dGhvcml0eU5hbWUnOiAnR1JPVVBfRVZFUllPTkUnIH0gfSlcbiAgICB9KTtcblxuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB0aGlzLnNlYXJjaElucHV0LnZhbHVlQ2hhbmdlcy5waXBlKGRlYm91bmNlVGltZSh0aGlzLmRlYm91bmNlU2VhcmNoKSkuc3Vic2NyaWJlKChzZWFyY2hWYWx1ZSkgPT4ge1xuICAgICAgICAgICAgY29uc3Qgc2VsZWN0aW9uT3B0aW9ucyA9IHRoaXMubWF0U2VsZWN0aW9uTGlzdC5zZWxlY3RlZE9wdGlvbnMuc2VsZWN0ZWQubWFwKChvcHRpb24pID0+IG9wdGlvbi52YWx1ZSk7XG4gICAgICAgICAgICB0aGlzLnNlbGVjdGVkSXRlbXMucHVzaCguLi5zZWxlY3Rpb25PcHRpb25zKTtcbiAgICAgICAgICAgIHRoaXMubWF0U2VsZWN0aW9uTGlzdC5kZXNlbGVjdEFsbCgpO1xuICAgICAgICAgICAgdGhpcy5zZWFyY2hlZFdvcmQgPSBzZWFyY2hWYWx1ZTtcbiAgICAgICAgICAgIGlmICghc2VhcmNoVmFsdWUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNlYXJjaC5yZXNldFJlc3VsdHMoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgb25TZWxlY3Rpb25DaGFuZ2UoKSB7XG4gICAgICAgIGNvbnN0IGN1cnJlbnRTZWxlY3Rpb24gPSB0aGlzLm1hdFNlbGVjdGlvbkxpc3Quc2VsZWN0ZWRPcHRpb25zLnNlbGVjdGVkLm1hcCgob3B0aW9uKSA9PiBvcHRpb24udmFsdWUpO1xuICAgICAgICBjb25zdCB1bmlxdWVTZWxlY3Rpb24gPSBbLi4uY3VycmVudFNlbGVjdGlvbiwgLi4udGhpcy5zZWxlY3RlZEl0ZW1zXS5yZWR1Y2UoKHVuaXF1ZXNFbGVtZW50cywgY3VycmVudEVsZW1lbnQpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGlzRXhpc3QgPSB1bmlxdWVzRWxlbWVudHMuZmluZCgodW5pcXVlRWxlbWVudCkgPT4gdW5pcXVlRWxlbWVudC5lbnRyeS5pZCA9PT0gY3VycmVudEVsZW1lbnQuZW50cnkuaWQpO1xuICAgICAgICAgICAgaWYgKCFpc0V4aXN0KSB7XG4gICAgICAgICAgICAgICAgdW5pcXVlc0VsZW1lbnRzLnB1c2goY3VycmVudEVsZW1lbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHVuaXF1ZXNFbGVtZW50cztcbiAgICAgICAgfSwgW10pO1xuICAgICAgICB0aGlzLnNlbGVjdC5lbWl0KHVuaXF1ZVNlbGVjdGlvbik7XG4gICAgfVxuXG4gICAgY2xlYXJTZWFyY2goKSB7XG4gICAgICAgIHRoaXMuc2VhcmNoZWRXb3JkID0gJyc7XG4gICAgICAgIHRoaXMuc2VsZWN0ZWRJdGVtcy5zcGxpY2UoMCwgdGhpcy5zZWxlY3RlZEl0ZW1zLmxlbmd0aCk7XG4gICAgICAgIHRoaXMuc2VhcmNoLnJlc2V0UmVzdWx0cygpO1xuICAgIH1cbn1cbiIsIjxtYXQtZm9ybS1maWVsZCBhcHBlYXJhbmNlPVwiZmlsbFwiIGNsYXNzPVwiYWRmLXBlcm1pc3Npb24tc2VhcmNoLWlucHV0XCI+XG4gICAgPGlucHV0XG4gICAgICAgIG1hdElucHV0XG4gICAgICAgIGlkPVwic2VhcmNoSW5wdXRcIlxuICAgICAgICBjbGFzcz1cImFkZi1wZXJtaXNzaW9uLXNlYXJjaC1pbnB1dC1jb250cm9sXCJcbiAgICAgICAgW2Zvcm1Db250cm9sXT1cInNlYXJjaElucHV0XCJcbiAgICAgICAgdHlwZT1cInRleHRcIlxuICAgICAgICB0aXRsZT1cInt7ICdQRVJNSVNTSU9OX01BTkFHRVIuQURELVBFUk1JU1NJT04uU0VBUkNIJyB8IHRyYW5zbGF0ZSB9fVwiXG4gICAgICAgIHBsYWNlaG9sZGVyPVwie3sgJ1BFUk1JU1NJT05fTUFOQUdFUi5BREQtUEVSTUlTU0lPTi5TRUFSQ0gnIHwgdHJhbnNsYXRlIH19XCJcbiAgICAgICAgW3ZhbHVlXT1cInNlYXJjaGVkV29yZFwiXG4gICAgLz5cblxuICAgIDxtYXQtaWNvblxuICAgICAgICAqbmdJZj1cInNlYXJjaGVkV29yZD8ubGVuZ3RoID4gMFwiXG4gICAgICAgIGNsYXNzPVwiYWRmLXBlcm1pc3Npb24tc2VhcmNoLWljb25cIlxuICAgICAgICBkYXRhLWF1dG9tYXRpb24taWQ9XCJhZGYtcGVybWlzc2lvbi1jbGVhci1pbnB1dFwiXG4gICAgICAgIGlkPVwiYWRmLXBlcm1pc3Npb24tY2xlYXItaW5wdXRcIlxuICAgICAgICBtYXRTdWZmaXhcbiAgICAgICAgKGNsaWNrKT1cImNsZWFyU2VhcmNoKClcIlxuICAgICAgICA+Y2xlYXJcbiAgICA8L21hdC1pY29uPlxuXG4gICAgPG1hdC1pY29uICpuZ0lmPVwic2VhcmNoZWRXb3JkPy5sZW5ndGggPT09IDBcIiBjbGFzcz1cImFkZi1wZXJtaXNzaW9uLXNlYXJjaC1pY29uXCIgZGF0YS1hdXRvbWF0aW9uLWlkPVwiYWRmLXBlcm1pc3Npb24tc2VhcmNoLWljb25cIiBtYXRTdWZmaXhcbiAgICAgICAgPnNlYXJjaFxuICAgIDwvbWF0LWljb24+XG48L21hdC1mb3JtLWZpZWxkPlxuXG48ZGl2ICpuZ0lmPVwic2VhcmNoZWRXb3JkPy5sZW5ndGggPT09IDBcIiBjbGFzcz1cImFkZi1wZXJtaXNzaW9uLXN0YXJ0LW1lc3NhZ2VcIiBpZD1cImFkZi1hZGQtcGVybWlzc2lvbi10eXBlLXNlYXJjaFwiPlxuICAgIDxzcGFuPnt7ICdQRVJNSVNTSU9OX01BTkFHRVIuQURELVBFUk1JU1NJT04uVFlQRS1NRVNTQUdFJyB8IHRyYW5zbGF0ZSB9fTwvc3Bhbj5cbjwvZGl2PlxuXG48YWRmLXNlYXJjaFxuICAgICNzZWFyY2hcbiAgICBbc2VhcmNoVGVybV09XCJzZWFyY2hlZFdvcmRcIlxuICAgIGlkPVwiYWRmLWFkZC1wZXJtaXNzaW9uLWF1dGhvcml0eS1yZXN1bHRzXCJcbiAgICBjbGFzcz1cImFkZi1wZXJtaXNzaW9uLXJlc3VsdC1saXN0XCJcbiAgICBbY2xhc3MuYWRmLXBlcm1pc3Npb24tcmVzdWx0LWxpc3Qtc2VhcmNoXT1cInNlYXJjaGVkV29yZC5sZW5ndGggPT09IDBcIlxuPlxuICAgIDxuZy10ZW1wbGF0ZSBsZXQtZGF0YT5cbiAgICAgICAgPG1hdC1zZWxlY3Rpb24tbGlzdFxuICAgICAgICAgICAgY2xhc3M9XCJhZGYtcGVybWlzc2lvbi1yZXN1bHQtbGlzdC1lbGVtZW50c1wiXG4gICAgICAgICAgICB0aXRsZT1cInt7ICdQRVJNSVNTSU9OX01BTkFHRVIuQURELVBFUk1JU1NJT04uVVNFUi1HUk9VUC1MSVNUJyB8IHRyYW5zbGF0ZSB9fVwiXG4gICAgICAgICAgICAoc2VsZWN0aW9uQ2hhbmdlKT1cIm9uU2VsZWN0aW9uQ2hhbmdlKClcIlxuICAgICAgICA+XG4gICAgICAgICAgICA8bWF0LWxpc3Qtb3B0aW9uIGlkPVwiYWRmLWFkZC1wZXJtaXNzaW9uLWdyb3VwLWV2ZXJ5b25lXCIgI2V2ZXlvbmUgW2Rpc2FibGVSaXBwbGVdPVwidHJ1ZVwiIFt2YWx1ZV09XCJFVkVSWU9ORVwiPlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJhZGYtbGlzdC1vcHRpb24taXRlbVwiPlxuICAgICAgICAgICAgICAgICAgICA8YWRmLXVzZXItaWNvbi1jb2x1bW4gW25vZGVdPVwiRVZFUllPTkVcIiBpZD1cImFkZC1ncm91cC1pY29uXCIgW3NlbGVjdGVkXT1cImV2ZXlvbmUuc2VsZWN0ZWRcIiAvPlxuICAgICAgICAgICAgICAgICAgICA8cCBjbGFzcz1cImFkZi1yZXN1bHQtbmFtZVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAge3sgJ1BFUk1JU1NJT05fTUFOQUdFUi5BREQtUEVSTUlTU0lPTi5FVkVSWU9ORScgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgICAgICAgICAgICAgPC9wPlxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPC9tYXQtbGlzdC1vcHRpb24+XG5cbiAgICAgICAgICAgIDxtYXQtbGlzdC1vcHRpb25cbiAgICAgICAgICAgICAgICAqbmdGb3I9XCJsZXQgaXRlbSBvZiBkYXRhPy5saXN0Py5lbnRyaWVzOyBsZXQgaWR4ID0gaW5kZXhcIlxuICAgICAgICAgICAgICAgIFtkaXNhYmxlUmlwcGxlXT1cInRydWVcIlxuICAgICAgICAgICAgICAgIFt2YWx1ZV09XCJpdGVtXCJcbiAgICAgICAgICAgICAgICBpZD1cInJlc3VsdF9vcHRpb25fe3sgaWR4IH19XCJcbiAgICAgICAgICAgICAgICAjb3B0aW9uXG4gICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImFkZi1saXN0LW9wdGlvbi1pdGVtXCI+XG4gICAgICAgICAgICAgICAgICAgIDxhZGYtdXNlci1pY29uLWNvbHVtbiBbbm9kZV09XCJpdGVtXCIgW3NlbGVjdGVkXT1cIm9wdGlvbi5zZWxlY3RlZFwiIC8+XG4gICAgICAgICAgICAgICAgICAgIDxwIGNsYXNzPVwiYWRmLXJlc3VsdC1uYW1lXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiaXRlbS5lbnRyeT8ucHJvcGVydGllc1snY206YXV0aG9yaXR5RGlzcGxheU5hbWUnXTsgZWxzZSBhdXRob3JpdHlOYW1lXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAge3sgaXRlbS5lbnRyeS5wcm9wZXJ0aWVzWydjbTphdXRob3JpdHlEaXNwbGF5TmFtZSddIH19XG4gICAgICAgICAgICAgICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxuZy10ZW1wbGF0ZSAjYXV0aG9yaXR5TmFtZT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiaXRlbS5lbnRyeT8ucHJvcGVydGllc1snY206YXV0aG9yaXR5TmFtZSddOyBlbHNlIG93bmVyXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt7IGl0ZW0uZW50cnkucHJvcGVydGllc1snY206YXV0aG9yaXR5TmFtZSddIH19XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICAgICAgICAgICAgICAgICAgPG5nLXRlbXBsYXRlICNvd25lcj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7eyBpdGVtLmVudHJ5Py5wcm9wZXJ0aWVzWydjbTpmaXJzdE5hbWUnXSA/IGl0ZW0uZW50cnk/LnByb3BlcnRpZXNbJ2NtOmZpcnN0TmFtZSddIDogJycgfX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7eyBpdGVtLmVudHJ5Py5wcm9wZXJ0aWVzWydjbTpsYXN0TmFtZSddID8gaXRlbS5lbnRyeT8ucHJvcGVydGllc1snY206bGFzdE5hbWUnXSA6ICcnIH19XG4gICAgICAgICAgICAgICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICAgICAgICAgICAgICA8L3A+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L21hdC1saXN0LW9wdGlvbj5cbiAgICAgICAgPC9tYXQtc2VsZWN0aW9uLWxpc3Q+XG4gICAgPC9uZy10ZW1wbGF0ZT5cbjwvYWRmLXNlYXJjaD5cbiJdfQ==