UNPKG

@c8y/ngx-components

Version:

Angular modules for Cumulocity IoT applications

218 lines 35.7 kB
import { Component } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { ActionBarItemComponent, AlertService, BuiltInActionType, C8yTranslateDirective, C8yTranslatePipe, DataGridModule, EmptyComponent, EmptyStateComponent, gettext, IconDirective, ModalService, Status, TitleComponent } from '@c8y/ngx-components'; import { RemoteAccessService } from '@c8y/ngx-components/remote-access/data'; import { RemoteAccessConnectButtonComponent } from './remote-access-connect-button/remote-access-connect-button.component'; import { BsModalService } from 'ngx-bootstrap/modal'; import { RemoteAccessPickProtocolModalComponent } from '../remote-access-pick-protocol-modal/remote-access-pick-protocol-modal.component'; import { IconDeviceGridColumn } from '@c8y/ngx-components/device-grid'; import { TranslateService } from '@ngx-translate/core'; import * as i0 from "@angular/core"; import * as i1 from "@c8y/ngx-components/remote-access/data"; import * as i2 from "@angular/router"; import * as i3 from "@c8y/ngx-components"; import * as i4 from "ngx-bootstrap/modal"; import * as i5 from "@ngx-translate/core"; export class RemoteAccessConfigurationListComponent { constructor(remoteAccess, activatedRoute, modalService, alert, bsModalService, translateService) { this.remoteAccess = remoteAccess; this.activatedRoute = activatedRoute; this.modalService = modalService; this.alert = alert; this.bsModalService = bsModalService; this.translateService = translateService; this.rows = []; this.columns = [ new IconDeviceGridColumn({ headerCellRendererComponent: EmptyComponent }, context => { const provider = this.protocolProviders.find(p => p.protocolName === context.item.protocol); return provider?.protocolIcon || 'laptop'; }), { name: 'name', header: gettext('Endpoint'), path: 'name' }, { name: 'hostname', header: gettext('Host'), path: 'hostname' }, { name: 'port', header: gettext('Port'), path: 'port' }, { name: 'protocol', header: gettext('Protocol'), path: 'protocol' }, { name: 'connect', header: gettext('Connect'), cellRendererComponent: RemoteAccessConnectButtonComponent } ]; this.actionControls = [ { type: BuiltInActionType.Edit, callback: async (entry) => { const provider = this.getProtocolProviderForConfiguration(entry); try { let result; if (provider.editEndpoint) { result = await provider.editEndpoint(this.deviceId, entry); } else { result = await this.defaultEditEndpoint(this.deviceId, entry); } if (!result) { return; } this.alert.success(gettext('Endpoint saved.')); } catch (e) { console.warn(e); this.alert.danger(gettext('Failed to save endpoint.'), e); } this.reload(); } }, { type: BuiltInActionType.Delete, callback: async (entry) => { const result = await this.modalService.confirm(gettext('Delete endpoint'), this.translateService.instant(gettext(`You are about to delete endpoint "{{ endpointName }}". Do you want to proceed?`), { endpointName: entry.name }), Status.DANGER, { cancel: gettext('Cancel'), ok: gettext('Delete') }); if (!result) { return; } const provider = this.getProtocolProviderForConfiguration(entry); try { await provider.removeEndpoint(this.deviceId, entry); this.alert.success(gettext('Endpoint deleted.')); } catch (e) { console.warn(e); this.alert.danger(gettext('Failed to delete endpoint.'), e); } this.reload(); } } ]; this.pagination = { pageSize: 10, currentPage: 1 }; this.displayOptions = { bordered: false, striped: true, filter: true, gridHeader: true, hover: true }; this.protocolProviders = []; this.gridTitle = gettext('Remote access endpoints'); this.protocolProviders = this.remoteAccess.getProtocolProviders(); this.deviceId = this.activatedRoute.parent.snapshot.params.id; const connectColum = this.columns.find(c => c.name === 'connect'); if (connectColum) { connectColum.target = this.deviceId; } } ngOnInit() { this.reload(); } async reload() { const configurations = await this.remoteAccess.listConfigurations(this.deviceId); const supportedProtocols = this.protocolProviders.map(p => p.protocolName); this.rows = configurations.filter(c => supportedProtocols.includes(c.protocol)); } async addEndpoint() { let provider = null; if (this.protocolProviders.length > 1) { try { const modalRef = this.bsModalService.show(RemoteAccessPickProtocolModalComponent); provider = await modalRef.content.result; } catch (e) { // modal closed return; } } else if (this.protocolProviders.length === 1) { provider = this.protocolProviders[0]; } else { return; } try { let addModalResult = null; if (provider.addEndpoint) { addModalResult = await provider.addEndpoint(this.deviceId); } else { addModalResult = await this.defaultAddEndpoint(this.deviceId, provider); } if (!addModalResult) { return; } this.alert.success(gettext('Endpoint added.')); } catch (e) { console.warn(e); this.alert.danger(gettext('Failed to add endpoint.'), e); } this.reload(); } getProtocolProviderForConfiguration(configuration) { return this.protocolProviders.find(p => p.protocolName === configuration.protocol); } async defaultEditEndpoint(deviceId, configuration) { const modalResult = await this.openBasicEndpointModal(configuration); if (!modalResult) { return modalResult; } return this.remoteAccess.updateConfiguration(deviceId, modalResult); } async defaultAddEndpoint(deviceId, provider) { let defaultConfig = { protocol: provider.protocolName }; if (provider.getDefaultEndpointConfiguration) { const defaultConfigFromProvider = await provider.getDefaultEndpointConfiguration(); defaultConfig = { ...defaultConfig, ...defaultConfigFromProvider }; } const modalResult = await this.openBasicEndpointModal(defaultConfig); if (!modalResult) { return modalResult; } return this.remoteAccess.addConfiguration(deviceId, modalResult); } async openBasicEndpointModal(currentConfiguration) { const { RemoteAccessBasicEndpointModalComponent } = await import('@c8y/ngx-components/remote-access/shared'); try { const modalRef = this.bsModalService.show(RemoteAccessBasicEndpointModalComponent, { initialState: { currentValue: currentConfiguration } }); return (await modalRef.content.result); } catch (e) { // modal closed return null; } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: RemoteAccessConfigurationListComponent, deps: [{ token: i1.RemoteAccessService }, { token: i2.ActivatedRoute }, { token: i3.ModalService }, { token: i3.AlertService }, { token: i4.BsModalService }, { token: i5.TranslateService }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: RemoteAccessConfigurationListComponent, isStandalone: true, selector: "c8y-remote-access-configuration-list", ngImport: i0, template: "<c8y-title translate>Remote access</c8y-title>\n\n<c8y-action-bar-item [placement]=\"'right'\">\n <button\n class=\"btn btn-link\"\n (click)=\"addEndpoint()\"\n [disabled]=\"!protocolProviders?.length\"\n [attr.data-cy]=\"'remoteAccessConfigurationList--add-endpoint'\"\n >\n <i [c8yIcon]=\"'plus-circle'\"></i>\n <span translate>Add endpoint</span>\n </button>\n</c8y-action-bar-item>\n\n<div class=\"content-fullpage d-flex d-col border-top\">\n <c8y-data-grid\n [title]=\"gridTitle\"\n [rows]=\"rows\"\n [columns]=\"columns\"\n [pagination]=\"pagination\"\n (onReload)=\"reload()\"\n [actionControls]=\"actionControls\"\n [displayOptions]=\"displayOptions\"\n >\n <c8y-ui-empty-state\n [icon]=\"'window-restore'\"\n [title]=\"'No endpoints configured.' | translate\"\n [subtitle]=\"'Click below to add your first endpoint.' | translate\"\n [horizontal]=\"false\"\n >\n <button\n class=\"btn btn-default\"\n (click)=\"addEndpoint()\"\n translate\n >\n Add endpoint\n </button>\n </c8y-ui-empty-state>\n </c8y-data-grid>\n</div>\n", dependencies: [{ kind: "ngmodule", type: DataGridModule }, { kind: "component", type: i3.DataGridComponent, selector: "c8y-data-grid", inputs: ["title", "loadMoreItemsLabel", "loadingItemsLabel", "showSearch", "refresh", "columns", "rows", "pagination", "infiniteScroll", "serverSideDataCallback", "selectable", "singleSelection", "selectionPrimaryKey", "displayOptions", "actionControls", "bulkActionControls", "headerActionControls", "searchText", "configureColumnsEnabled", "showCounterWarning", "activeClassName", "expandableRows", "hideReload"], outputs: ["rowMouseOver", "rowMouseLeave", "rowClick", "onConfigChange", "onBeforeFilter", "onBeforeSearch", "onFilter", "itemsSelect", "onReload", "onAddCustomColumn", "onRemoveCustomColumn", "onColumnFilterReset", "onSort", "onPageSizeChange", "onColumnReordered", "onColumnVisibilityChange"] }, { kind: "component", type: TitleComponent, selector: "c8y-title", inputs: ["pageTitleUpdate"] }, { kind: "directive", type: C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "component", type: ActionBarItemComponent, selector: "c8y-action-bar-item", inputs: ["placement", "priority", "itemClass", "injector", "groupId", "inGroupPriority"] }, { kind: "directive", type: IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "component", type: EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "pipe", type: C8yTranslatePipe, name: "translate" }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: RemoteAccessConfigurationListComponent, decorators: [{ type: Component, args: [{ selector: 'c8y-remote-access-configuration-list', standalone: true, imports: [ DataGridModule, TitleComponent, C8yTranslateDirective, ActionBarItemComponent, IconDirective, EmptyStateComponent, C8yTranslatePipe ], template: "<c8y-title translate>Remote access</c8y-title>\n\n<c8y-action-bar-item [placement]=\"'right'\">\n <button\n class=\"btn btn-link\"\n (click)=\"addEndpoint()\"\n [disabled]=\"!protocolProviders?.length\"\n [attr.data-cy]=\"'remoteAccessConfigurationList--add-endpoint'\"\n >\n <i [c8yIcon]=\"'plus-circle'\"></i>\n <span translate>Add endpoint</span>\n </button>\n</c8y-action-bar-item>\n\n<div class=\"content-fullpage d-flex d-col border-top\">\n <c8y-data-grid\n [title]=\"gridTitle\"\n [rows]=\"rows\"\n [columns]=\"columns\"\n [pagination]=\"pagination\"\n (onReload)=\"reload()\"\n [actionControls]=\"actionControls\"\n [displayOptions]=\"displayOptions\"\n >\n <c8y-ui-empty-state\n [icon]=\"'window-restore'\"\n [title]=\"'No endpoints configured.' | translate\"\n [subtitle]=\"'Click below to add your first endpoint.' | translate\"\n [horizontal]=\"false\"\n >\n <button\n class=\"btn btn-default\"\n (click)=\"addEndpoint()\"\n translate\n >\n Add endpoint\n </button>\n </c8y-ui-empty-state>\n </c8y-data-grid>\n</div>\n" }] }], ctorParameters: () => [{ type: i1.RemoteAccessService }, { type: i2.ActivatedRoute }, { type: i3.ModalService }, { type: i3.AlertService }, { type: i4.BsModalService }, { type: i5.TranslateService }] }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVtb3RlLWFjY2Vzcy1jb25maWd1cmF0aW9uLWxpc3QuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcmVtb3RlLWFjY2Vzcy9jb25maWd1cmF0aW9ucy9yZW1vdGUtYWNjZXNzLWNvbmZpZ3VyYXRpb24tbGlzdC9yZW1vdGUtYWNjZXNzLWNvbmZpZ3VyYXRpb24tbGlzdC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi9yZW1vdGUtYWNjZXNzL2NvbmZpZ3VyYXRpb25zL3JlbW90ZS1hY2Nlc3MtY29uZmlndXJhdGlvbi1saXN0L3JlbW90ZS1hY2Nlc3MtY29uZmlndXJhdGlvbi1saXN0LmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQVUsTUFBTSxlQUFlLENBQUM7QUFDbEQsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ2pELE9BQU8sRUFDTCxzQkFBc0IsRUFFdEIsWUFBWSxFQUNaLGlCQUFpQixFQUNqQixxQkFBcUIsRUFDckIsZ0JBQWdCLEVBRWhCLGNBQWMsRUFFZCxjQUFjLEVBQ2QsbUJBQW1CLEVBQ25CLE9BQU8sRUFDUCxhQUFhLEVBQ2IsWUFBWSxFQUVaLE1BQU0sRUFDTixjQUFjLEVBQ2YsTUFBTSxxQkFBcUIsQ0FBQztBQUM3QixPQUFPLEVBR0wsbUJBQW1CLEVBQ3BCLE1BQU0sd0NBQXdDLENBQUM7QUFDaEQsT0FBTyxFQUFFLGtDQUFrQyxFQUFFLE1BQU0sdUVBQXVFLENBQUM7QUFDM0gsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3JELE9BQU8sRUFBRSxzQ0FBc0MsRUFBRSxNQUFNLGtGQUFrRixDQUFDO0FBQzFJLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQ3ZFLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHFCQUFxQixDQUFD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T25Jbml0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBBY3RpdmF0ZWRSb3V0ZSB9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5pbXBvcnQge1xuICBBY3Rpb25CYXJJdGVtQ29tcG9uZW50LFxuICBBY3Rpb25Db250cm9sLFxuICBBbGVydFNlcnZpY2UsXG4gIEJ1aWx0SW5BY3Rpb25UeXBlLFxuICBDOHlUcmFuc2xhdGVEaXJlY3RpdmUsXG4gIEM4eVRyYW5zbGF0ZVBpcGUsXG4gIENvbHVtbixcbiAgRGF0YUdyaWRNb2R1bGUsXG4gIERpc3BsYXlPcHRpb25zLFxuICBFbXB0eUNvbXBvbmVudCxcbiAgRW1wdHlTdGF0ZUNvbXBvbmVudCxcbiAgZ2V0dGV4dCxcbiAgSWNvbkRpcmVjdGl2ZSxcbiAgTW9kYWxTZXJ2aWNlLFxuICBQYWdpbmF0aW9uLFxuICBTdGF0dXMsXG4gIFRpdGxlQ29tcG9uZW50XG59IGZyb20gJ0BjOHkvbmd4LWNvbXBvbmVudHMnO1xuaW1wb3J0IHtcbiAgUmVtb3RlQWNjZXNzQ29uZmlndXJhdGlvbixcbiAgUmVtb3RlQWNjZXNzUHJvdG9jb2xQcm92aWRlcixcbiAgUmVtb3RlQWNjZXNzU2VydmljZVxufSBmcm9tICdAYzh5L25neC1jb21wb25lbnRzL3JlbW90ZS1hY2Nlc3MvZGF0YSc7XG5pbXBvcnQgeyBSZW1vdGVBY2Nlc3NDb25uZWN0QnV0dG9uQ29tcG9uZW50IH0gZnJvbSAnLi9yZW1vdGUtYWNjZXNzLWNvbm5lY3QtYnV0dG9uL3JlbW90ZS1hY2Nlc3MtY29ubmVjdC1idXR0b24uY29tcG9uZW50JztcbmltcG9ydCB7IEJzTW9kYWxTZXJ2aWNlIH0gZnJvbSAnbmd4LWJvb3RzdHJhcC9tb2RhbCc7XG5pbXBvcnQgeyBSZW1vdGVBY2Nlc3NQaWNrUHJvdG9jb2xNb2RhbENvbXBvbmVudCB9IGZyb20gJy4uL3JlbW90ZS1hY2Nlc3MtcGljay1wcm90b2NvbC1tb2RhbC9yZW1vdGUtYWNjZXNzLXBpY2stcHJvdG9jb2wtbW9kYWwuY29tcG9uZW50JztcbmltcG9ydCB7IEljb25EZXZpY2VHcmlkQ29sdW1uIH0gZnJvbSAnQGM4eS9uZ3gtY29tcG9uZW50cy9kZXZpY2UtZ3JpZCc7XG5pbXBvcnQgeyBUcmFuc2xhdGVTZXJ2aWNlIH0gZnJvbSAnQG5neC10cmFuc2xhdGUvY29yZSc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2M4eS1yZW1vdGUtYWNjZXNzLWNvbmZpZ3VyYXRpb24tbGlzdCcsXG4gIHRlbXBsYXRlVXJsOiAnLi9yZW1vdGUtYWNjZXNzLWNvbmZpZ3VyYXRpb24tbGlzdC5jb21wb25lbnQuaHRtbCcsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtcbiAgICBEYXRhR3JpZE1vZHVsZSxcbiAgICBUaXRsZUNvbXBvbmVudCxcbiAgICBDOHlUcmFuc2xhdGVEaXJlY3RpdmUsXG4gICAgQWN0aW9uQmFySXRlbUNvbXBvbmVudCxcbiAgICBJY29uRGlyZWN0aXZlLFxuICAgIEVtcHR5U3RhdGVDb21wb25lbnQsXG4gICAgQzh5VHJhbnNsYXRlUGlwZVxuICBdXG59KVxuZXhwb3J0IGNsYXNzIFJlbW90ZUFjY2Vzc0NvbmZpZ3VyYXRpb25MaXN0Q29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcbiAgcm93czogUmVtb3RlQWNjZXNzQ29uZmlndXJhdGlvbltdID0gW107XG4gIGNvbHVtbnM6IENvbHVtbltdID0gW1xuICAgIG5ldyBJY29uRGV2aWNlR3JpZENvbHVtbihcbiAgICAgIHtcbiAgICAgICAgaGVhZGVyQ2VsbFJlbmRlcmVyQ29tcG9uZW50OiBFbXB0eUNvbXBvbmVudFxuICAgICAgfSxcbiAgICAgIGNvbnRleHQgPT4ge1xuICAgICAgICBjb25zdCBwcm92aWRlciA9IHRoaXMucHJvdG9jb2xQcm92aWRlcnMuZmluZChwID0+IHAucHJvdG9jb2xOYW1lID09PSBjb250ZXh0Lml0ZW0ucHJvdG9jb2wpO1xuICAgICAgICByZXR1cm4gcHJvdmlkZXI/LnByb3RvY29sSWNvbiB8fCAnbGFwdG9wJztcbiAgICAgIH1cbiAgICApLFxuICAgIHtcbiAgICAgIG5hbWU6ICduYW1lJyxcbiAgICAgIGhlYWRlcjogZ2V0dGV4dCgnRW5kcG9pbnQnKSxcbiAgICAgIHBhdGg6ICduYW1lJ1xuICAgIH0sXG4gICAge1xuICAgICAgbmFtZTogJ2hvc3RuYW1lJyxcbiAgICAgIGhlYWRlcjogZ2V0dGV4dCgnSG9zdCcpLFxuICAgICAgcGF0aDogJ2hvc3RuYW1lJ1xuICAgIH0sXG4gICAge1xuICAgICAgbmFtZTogJ3BvcnQnLFxuICAgICAgaGVhZGVyOiBnZXR0ZXh0KCdQb3J0JyksXG4gICAgICBwYXRoOiAncG9ydCdcbiAgICB9LFxuICAgIHtcbiAgICAgIG5hbWU6ICdwcm90b2NvbCcsXG4gICAgICBoZWFkZXI6IGdldHRleHQoJ1Byb3RvY29sJyksXG4gICAgICBwYXRoOiAncHJvdG9jb2wnXG4gICAgfSxcbiAgICB7XG4gICAgICBuYW1lOiAnY29ubmVjdCcsXG4gICAgICBoZWFkZXI6IGdldHRleHQoJ0Nvbm5lY3QnKSxcbiAgICAgIGNlbGxSZW5kZXJlckNvbXBvbmVudDogUmVtb3RlQWNjZXNzQ29ubmVjdEJ1dHRvbkNvbXBvbmVudFxuICAgIH1cbiAgXTtcbiAgYWN0aW9uQ29udHJvbHM6IEFjdGlvbkNvbnRyb2xbXSA9IFtcbiAgICB7XG4gICAgICB0eXBlOiBCdWlsdEluQWN0aW9uVHlwZS5FZGl0LFxuICAgICAgY2FsbGJhY2s6IGFzeW5jIChlbnRyeTogUmVtb3RlQWNjZXNzQ29uZmlndXJhdGlvbikgPT4ge1xuICAgICAgICBjb25zdCBwcm92aWRlciA9IHRoaXMuZ2V0UHJvdG9jb2xQcm92aWRlckZvckNvbmZpZ3VyYXRpb24oZW50cnkpO1xuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgbGV0IHJlc3VsdDogUmVtb3RlQWNjZXNzQ29uZmlndXJhdGlvbjtcbiAgICAgICAgICBpZiAocHJvdmlkZXIuZWRpdEVuZHBvaW50KSB7XG4gICAgICAgICAgICByZXN1bHQgPSBhd2FpdCBwcm92aWRlci5lZGl0RW5kcG9pbnQodGhpcy5kZXZpY2VJZCwgZW50cnkpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXN1bHQgPSBhd2FpdCB0aGlzLmRlZmF1bHRFZGl0RW5kcG9pbnQodGhpcy5kZXZpY2VJZCwgZW50cnkpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICghcmVzdWx0KSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdGhpcy5hbGVydC5zdWNjZXNzKGdldHRleHQoJ0VuZHBvaW50IHNhdmVkLicpKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIGNvbnNvbGUud2FybihlKTtcbiAgICAgICAgICB0aGlzLmFsZXJ0LmRhbmdlcihnZXR0ZXh0KCdGYWlsZWQgdG8gc2F2ZSBlbmRwb2ludC4nKSwgZSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5yZWxvYWQoKTtcbiAgICAgIH1cbiAgICB9LFxuICAgIHtcbiAgICAgIHR5cGU6IEJ1aWx0SW5BY3Rpb25UeXBlLkRlbGV0ZSxcbiAgICAgIGNhbGxiYWNrOiBhc3luYyAoZW50cnk6IFJlbW90ZUFjY2Vzc0NvbmZpZ3VyYXRpb24pID0+IHtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy5tb2RhbFNlcnZpY2UuY29uZmlybShcbiAgICAgICAgICBnZXR0ZXh0KCdEZWxldGUgZW5kcG9pbnQnKSxcbiAgICAgICAgICB0aGlzLnRyYW5zbGF0ZVNlcnZpY2UuaW5zdGFudChcbiAgICAgICAgICAgIGdldHRleHQoXG4gICAgICAgICAgICAgIGBZb3UgYXJlIGFib3V0IHRvIGRlbGV0ZSBlbmRwb2ludCBcInt7IGVuZHBvaW50TmFtZSB9fVwiLiBEbyB5b3Ugd2FudCB0byBwcm9jZWVkP2BcbiAgICAgICAgICAgICksXG4gICAgICAgICAgICB7IGVuZHBvaW50TmFtZTogZW50cnkubmFtZSB9XG4gICAgICAgICAgKSxcbiAgICAgICAgICBTdGF0dXMuREFOR0VSLFxuICAgICAgICAgIHsgY2FuY2VsOiBnZXR0ZXh0KCdDYW5jZWwnKSwgb2s6IGdldHRleHQoJ0RlbGV0ZScpIH1cbiAgICAgICAgKTtcbiAgICAgICAgaWYgKCFyZXN1bHQpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBwcm92aWRlciA9IHRoaXMuZ2V0UHJvdG9jb2xQcm92aWRlckZvckNvbmZpZ3VyYXRpb24oZW50cnkpO1xuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgYXdhaXQgcHJvdmlkZXIucmVtb3ZlRW5kcG9pbnQodGhpcy5kZXZpY2VJZCwgZW50cnkpO1xuICAgICAgICAgIHRoaXMuYWxlcnQuc3VjY2VzcyhnZXR0ZXh0KCdFbmRwb2ludCBkZWxldGVkLicpKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIGNvbnNvbGUud2FybihlKTtcbiAgICAgICAgICB0aGlzLmFsZXJ0LmRhbmdlcihnZXR0ZXh0KCdGYWlsZWQgdG8gZGVsZXRlIGVuZHBvaW50LicpLCBlKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJlbG9hZCgpO1xuICAgICAgfVxuICAgIH1cbiAgXTtcbiAgZGV2aWNlSWQ6IHN0cmluZztcbiAgcGFnaW5hdGlvbjogUGFnaW5hdGlvbiA9IHtcbiAgICBwYWdlU2l6ZTogMTAsXG4gICAgY3VycmVudFBhZ2U6IDFcbiAgfTtcbiAgZGlzcGxheU9wdGlvbnM6IERpc3BsYXlPcHRpb25zID0ge1xuICAgIGJvcmRlcmVkOiBmYWxzZSxcbiAgICBzdHJpcGVkOiB0cnVlLFxuICAgIGZpbHRlcjogdHJ1ZSxcbiAgICBncmlkSGVhZGVyOiB0cnVlLFxuICAgIGhvdmVyOiB0cnVlXG4gIH07XG4gIHByb3RvY29sUHJvdmlkZXJzOiBSZW1vdGVBY2Nlc3NQcm90b2NvbFByb3ZpZGVyW10gPSBbXTtcbiAgZ3JpZFRpdGxlID0gZ2V0dGV4dCgnUmVtb3RlIGFjY2VzcyBlbmRwb2ludHMnKTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJlbW90ZUFjY2VzczogUmVtb3RlQWNjZXNzU2VydmljZSxcbiAgICBwcml2YXRlIGFjdGl2YXRlZFJvdXRlOiBBY3RpdmF0ZWRSb3V0ZSxcbiAgICBwcml2YXRlIG1vZGFsU2VydmljZTogTW9kYWxTZXJ2aWNlLFxuICAgIHByaXZhdGUgYWxlcnQ6IEFsZXJ0U2VydmljZSxcbiAgICBwcml2YXRlIGJzTW9kYWxTZXJ2aWNlOiBCc01vZGFsU2VydmljZSxcbiAgICBwcml2YXRlIHRyYW5zbGF0ZVNlcnZpY2U6IFRyYW5zbGF0ZVNlcnZpY2VcbiAgKSB7XG4gICAgdGhpcy5wcm90b2NvbFByb3ZpZGVycyA9IHRoaXMucmVtb3RlQWNjZXNzLmdldFByb3RvY29sUHJvdmlkZXJzKCk7XG4gICAgdGhpcy5kZXZpY2VJZCA9IHRoaXMuYWN0aXZhdGVkUm91dGUucGFyZW50LnNuYXBzaG90LnBhcmFtcy5pZDtcbiAgICBjb25zdCBjb25uZWN0Q29sdW0gPSB0aGlzLmNvbHVtbnMuZmluZChjID0+IGMubmFtZSA9PT0gJ2Nvbm5lY3QnKTtcbiAgICBpZiAoY29ubmVjdENvbHVtKSB7XG4gICAgICAoPGFueT5jb25uZWN0Q29sdW0pLnRhcmdldCA9IHRoaXMuZGV2aWNlSWQ7XG4gICAgfVxuICB9XG5cbiAgbmdPbkluaXQoKSB7XG4gICAgdGhpcy5yZWxvYWQoKTtcbiAgfVxuXG4gIGFzeW5jIHJlbG9hZCgpIHtcbiAgICBjb25zdCBjb25maWd1cmF0aW9ucyA9IGF3YWl0IHRoaXMucmVtb3RlQWNjZXNzLmxpc3RDb25maWd1cmF0aW9ucyh0aGlzLmRldmljZUlkKTtcbiAgICBjb25zdCBzdXBwb3J0ZWRQcm90b2NvbHMgPSB0aGlzLnByb3RvY29sUHJvdmlkZXJzLm1hcChwID0+IHAucHJvdG9jb2xOYW1lKTtcbiAgICB0aGlzLnJvd3MgPSBjb25maWd1cmF0aW9ucy5maWx0ZXIoYyA9PiBzdXBwb3J0ZWRQcm90b2NvbHMuaW5jbHVkZXMoYy5wcm90b2NvbCkpO1xuICB9XG5cbiAgYXN5bmMgYWRkRW5kcG9pbnQoKSB7XG4gICAgbGV0IHByb3ZpZGVyOiBSZW1vdGVBY2Nlc3NQcm90b2NvbFByb3ZpZGVyID0gbnVsbDtcbiAgICBpZiAodGhpcy5wcm90b2NvbFByb3ZpZGVycy5sZW5ndGggPiAxKSB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCBtb2RhbFJlZiA9IHRoaXMuYnNNb2RhbFNlcnZpY2Uuc2hvdyhSZW1vdGVBY2Nlc3NQaWNrUHJvdG9jb2xNb2RhbENvbXBvbmVudCk7XG4gICAgICAgIHByb3ZpZGVyID0gYXdhaXQgbW9kYWxSZWYuY29udGVudC5yZXN1bHQ7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIC8vIG1vZGFsIGNsb3NlZFxuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgfSBlbHNlIGlmICh0aGlzLnByb3RvY29sUHJvdmlkZXJzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgcHJvdmlkZXIgPSB0aGlzLnByb3RvY29sUHJvdmlkZXJzWzBdO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIGxldCBhZGRNb2RhbFJlc3VsdDogUmVtb3RlQWNjZXNzQ29uZmlndXJhdGlvbiA9IG51bGw7XG4gICAgICBpZiAocHJvdmlkZXIuYWRkRW5kcG9pbnQpIHtcbiAgICAgICAgYWRkTW9kYWxSZXN1bHQgPSBhd2FpdCBwcm92aWRlci5hZGRFbmRwb2ludCh0aGlzLmRldmljZUlkKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGFkZE1vZGFsUmVzdWx0ID0gYXdhaXQgdGhpcy5kZWZhdWx0QWRkRW5kcG9pbnQodGhpcy5kZXZpY2VJZCwgcHJvdmlkZXIpO1xuICAgICAgfVxuICAgICAgaWYgKCFhZGRNb2RhbFJlc3VsdCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICB0aGlzLmFsZXJ0LnN1Y2Nlc3MoZ2V0dGV4dCgnRW5kcG9pbnQgYWRkZWQuJykpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGNvbnNvbGUud2FybihlKTtcbiAgICAgIHRoaXMuYWxlcnQuZGFuZ2VyKGdldHRleHQoJ0ZhaWxlZCB0byBhZGQgZW5kcG9pbnQuJyksIGUpO1xuICAgIH1cbiAgICB0aGlzLnJlbG9hZCgpO1xuICB9XG5cbiAgZ2V0UHJvdG9jb2xQcm92aWRlckZvckNvbmZpZ3VyYXRpb24oY29uZmlndXJhdGlvbjogUmVtb3RlQWNjZXNzQ29uZmlndXJhdGlvbikge1xuICAgIHJldHVybiB0aGlzLnByb3RvY29sUHJvdmlkZXJzLmZpbmQocCA9PiBwLnByb3RvY29sTmFtZSA9PT0gY29uZmlndXJhdGlvbi5wcm90b2NvbCk7XG4gIH1cblxuICBhc3luYyBkZWZhdWx0RWRpdEVuZHBvaW50KGRldmljZUlkOiBzdHJpbmcsIGNvbmZpZ3VyYXRpb246IFJlbW90ZUFjY2Vzc0NvbmZpZ3VyYXRpb24pIHtcbiAgICBjb25zdCBtb2RhbFJlc3VsdCA9IGF3YWl0IHRoaXMub3BlbkJhc2ljRW5kcG9pbnRNb2RhbChjb25maWd1cmF0aW9uKTtcbiAgICBpZiAoIW1vZGFsUmVzdWx0KSB7XG4gICAgICByZXR1cm4gbW9kYWxSZXN1bHQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucmVtb3RlQWNjZXNzLnVwZGF0ZUNvbmZpZ3VyYXRpb24oZGV2aWNlSWQsIG1vZGFsUmVzdWx0KTtcbiAgfVxuXG4gIGFzeW5jIGRlZmF1bHRBZGRFbmRwb2ludChkZXZpY2VJZDogc3RyaW5nLCBwcm92aWRlcjogUmVtb3RlQWNjZXNzUHJvdG9jb2xQcm92aWRlcikge1xuICAgIGxldCBkZWZhdWx0Q29uZmlnID0geyBwcm90b2NvbDogcHJvdmlkZXIucHJvdG9jb2xOYW1lIH07XG4gICAgaWYgKHByb3ZpZGVyLmdldERlZmF1bHRFbmRwb2ludENvbmZpZ3VyYXRpb24pIHtcbiAgICAgIGNvbnN0IGRlZmF1bHRDb25maWdGcm9tUHJvdmlkZXIgPSBhd2FpdCBwcm92aWRlci5nZXREZWZhdWx0RW5kcG9pbnRDb25maWd1cmF0aW9uKCk7XG4gICAgICBkZWZhdWx0Q29uZmlnID0geyAuLi5kZWZhdWx0Q29uZmlnLCAuLi5kZWZhdWx0Q29uZmlnRnJvbVByb3ZpZGVyIH07XG4gICAgfVxuICAgIGNvbnN0IG1vZGFsUmVzdWx0ID0gYXdhaXQgdGhpcy5vcGVuQmFzaWNFbmRwb2ludE1vZGFsKGRlZmF1bHRDb25maWcpO1xuICAgIGlmICghbW9kYWxSZXN1bHQpIHtcbiAgICAgIHJldHVybiBtb2RhbFJlc3VsdDtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5yZW1vdGVBY2Nlc3MuYWRkQ29uZmlndXJhdGlvbihkZXZpY2VJZCwgbW9kYWxSZXN1bHQpO1xuICB9XG5cbiAgYXN5bmMgb3BlbkJhc2ljRW5kcG9pbnRNb2RhbChcbiAgICBjdXJyZW50Q29uZmlndXJhdGlvbjogUGFydGlhbDxSZW1vdGVBY2Nlc3NDb25maWd1cmF0aW9uPlxuICApOiBQcm9taXNlPFJlbW90ZUFjY2Vzc0NvbmZpZ3VyYXRpb24gfCBudWxsPiB7XG4gICAgY29uc3QgeyBSZW1vdGVBY2Nlc3NCYXNpY0VuZHBvaW50TW9kYWxDb21wb25lbnQgfSA9IGF3YWl0IGltcG9ydChcbiAgICAgICdAYzh5L25neC1jb21wb25lbnRzL3JlbW90ZS1hY2Nlc3Mvc2hhcmVkJ1xuICAgICk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgbW9kYWxSZWYgPSB0aGlzLmJzTW9kYWxTZXJ2aWNlLnNob3coUmVtb3RlQWNjZXNzQmFzaWNFbmRwb2ludE1vZGFsQ29tcG9uZW50LCB7XG4gICAgICAgIGluaXRpYWxTdGF0ZTogeyBjdXJyZW50VmFsdWU6IGN1cnJlbnRDb25maWd1cmF0aW9uIH1cbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIChhd2FpdCBtb2RhbFJlZi5jb250ZW50LnJlc3VsdCkgYXMgUmVtb3RlQWNjZXNzQ29uZmlndXJhdGlvbjtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAvLyBtb2RhbCBjbG9zZWRcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgfVxufVxuIiwiPGM4eS10aXRsZSB0cmFuc2xhdGU+UmVtb3RlIGFjY2VzczwvYzh5LXRpdGxlPlxuXG48Yzh5LWFjdGlvbi1iYXItaXRlbSBbcGxhY2VtZW50XT1cIidyaWdodCdcIj5cbiAgPGJ1dHRvblxuICAgIGNsYXNzPVwiYnRuIGJ0bi1saW5rXCJcbiAgICAoY2xpY2spPVwiYWRkRW5kcG9pbnQoKVwiXG4gICAgW2Rpc2FibGVkXT1cIiFwcm90b2NvbFByb3ZpZGVycz8ubGVuZ3RoXCJcbiAgICBbYXR0ci5kYXRhLWN5XT1cIidyZW1vdGVBY2Nlc3NDb25maWd1cmF0aW9uTGlzdC0tYWRkLWVuZHBvaW50J1wiXG4gID5cbiAgICA8aSBbYzh5SWNvbl09XCIncGx1cy1jaXJjbGUnXCI+PC9pPlxuICAgIDxzcGFuIHRyYW5zbGF0ZT5BZGQgZW5kcG9pbnQ8L3NwYW4+XG4gIDwvYnV0dG9uPlxuPC9jOHktYWN0aW9uLWJhci1pdGVtPlxuXG48ZGl2IGNsYXNzPVwiY29udGVudC1mdWxscGFnZSBkLWZsZXggZC1jb2wgYm9yZGVyLXRvcFwiPlxuICA8Yzh5LWRhdGEtZ3JpZFxuICAgIFt0aXRsZV09XCJncmlkVGl0bGVcIlxuICAgIFtyb3dzXT1cInJvd3NcIlxuICAgIFtjb2x1bW5zXT1cImNvbHVtbnNcIlxuICAgIFtwYWdpbmF0aW9uXT1cInBhZ2luYXRpb25cIlxuICAgIChvblJlbG9hZCk9XCJyZWxvYWQoKVwiXG4gICAgW2FjdGlvbkNvbnRyb2xzXT1cImFjdGlvbkNvbnRyb2xzXCJcbiAgICBbZGlzcGxheU9wdGlvbnNdPVwiZGlzcGxheU9wdGlvbnNcIlxuICA+XG4gICAgPGM4eS11aS1lbXB0eS1zdGF0ZVxuICAgICAgW2ljb25dPVwiJ3dpbmRvdy1yZXN0b3JlJ1wiXG4gICAgICBbdGl0bGVdPVwiJ05vIGVuZHBvaW50cyBjb25maWd1cmVkLicgfCB0cmFuc2xhdGVcIlxuICAgICAgW3N1YnRpdGxlXT1cIidDbGljayBiZWxvdyB0byBhZGQgeW91ciBmaXJzdCBlbmRwb2ludC4nIHwgdHJhbnNsYXRlXCJcbiAgICAgIFtob3Jpem9udGFsXT1cImZhbHNlXCJcbiAgICA+XG4gICAgICA8YnV0dG9uXG4gICAgICAgIGNsYXNzPVwiYnRuIGJ0bi1kZWZhdWx0XCJcbiAgICAgICAgKGNsaWNrKT1cImFkZEVuZHBvaW50KClcIlxuICAgICAgICB0cmFuc2xhdGVcbiAgICAgID5cbiAgICAgICAgQWRkIGVuZHBvaW50XG4gICAgICA8L2J1dHRvbj5cbiAgICA8L2M4eS11aS1lbXB0eS1zdGF0ZT5cbiAgPC9jOHktZGF0YS1ncmlkPlxuPC9kaXY+XG4iXX0=