@c8y/ngx-components
Version:
Angular modules for Cumulocity IoT applications
161 lines • 34.8 kB
JavaScript
import { Component, EventEmitter } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { AlertService, BuiltInActionType, DataGridService, ModalService, Status, gettext } from '@c8y/ngx-components';
import { DescriptionGridColumn, DeviceTypeGridColumn, PRODUCT_EXPERIENCE_REPOSITORY_SHARED, RepositoryItemNameGridColumn, RepositoryService, RepositoryType, VersionsGridColumn } from '@c8y/ngx-components/repository/shared';
import { TranslateService } from '@ngx-translate/core';
import { BsModalService } from 'ngx-bootstrap/modal';
import { from, map } from 'rxjs';
import { AddFirmwareModalComponent } from './add-firmware-modal.component';
import { AddFirmwarePatchModalComponent } from './add-firmware-patch-modal.component';
import * as i0 from "@angular/core";
import * as i1 from "@c8y/ngx-components/repository/shared";
import * as i2 from "@c8y/ngx-components";
import * as i3 from "ngx-bootstrap/modal";
import * as i4 from "@ngx-translate/core";
import * as i5 from "@angular/router";
import * as i6 from "@angular/common";
export class FirmwareListComponent {
constructor(repositoryService, gridService, modalService, bsModalService, translateService, alertService, router, activatedRoute) {
this.repositoryService = repositoryService;
this.gridService = gridService;
this.modalService = modalService;
this.bsModalService = bsModalService;
this.translateService = translateService;
this.alertService = alertService;
this.router = router;
this.activatedRoute = activatedRoute;
this.sizeRequestDone = false;
this.refresh$ = new EventEmitter();
this.isDataPresent$ = from(this.repositoryService.listRepositoryEntries(RepositoryType.FIRMWARE, { skipLegacy: true })).pipe(map(({ data }) => data.length > 0));
this.columns = [
new RepositoryItemNameGridColumn({
filterLabel: gettext('Filter firmware by name'),
placeholder: gettext('ubuntu core')
}),
new DescriptionGridColumn({
filterLabel: gettext('Filter firmware by description'),
placeholder: gettext('Firmware for hardware revision B')
}),
new DeviceTypeGridColumn({ filterLabel: gettext('Filter firmware by device type') }),
new VersionsGridColumn()
];
this.actionControls = [];
this.pagination = {
pageSize: 50,
currentPage: 1
};
this.noResultsMessage = gettext('No results to display.');
this.noDataMessage = gettext('No firmware to display.');
this.noResultsSubtitle = gettext('Refine your search terms or check your spelling.');
this.noDataSubtitle = gettext('Add a new firmware by clicking below.');
this.serverSideDataCallback = this.onDataSourceModifier.bind(this);
}
ngOnInit() {
this.actionControls.push({
type: BuiltInActionType.Edit,
callback: this.editFirmware.bind(this)
});
this.actionControls.push({
type: BuiltInActionType.Delete,
callback: this.deleteFirmware.bind(this)
});
}
addFirmware() {
const config = {
class: 'modal-sm',
ariaDescribedby: 'addFirmwareModalDescription',
ariaLabelledBy: 'addFirmwareModalTitle',
ignoreBackdropClick: true,
keyboard: false
};
const modalRef = this.bsModalService.show(AddFirmwareModalComponent, config);
modalRef.content.saved.subscribe(savedFirmware => this.editFirmware(savedFirmware));
}
addFirmwarePatch() {
const config = {
class: 'modal-sm',
ariaDescribedby: 'addFirmwarePatchModalDescription',
ariaLabelledBy: 'addFirmwarePatchModalTitle',
ignoreBackdropClick: true,
keyboard: false
};
const modalRef = this.bsModalService.show(AddFirmwarePatchModalComponent, config);
modalRef.content.saved.subscribe(savedFirmware => this.editFirmware(savedFirmware));
}
editFirmware(firmware) {
this.router.navigate([firmware.id], { relativeTo: this.activatedRoute });
}
async deleteFirmware(firmware) {
try {
const title = gettext('Delete firmware');
const body = `
${this.translateService.instant(gettext('You are about to delete firmware "{{ name }}" with all its versions and patches.'), { name: firmware.name })}
${this.translateService.instant(gettext('This operation is irreversible.'))}
${this.translateService.instant(gettext('Do you want to proceed?'))}
`;
const labels = {
ok: gettext('Delete')
};
await this.modalService.confirm(title, body, Status.DANGER, labels, {}, { eventName: PRODUCT_EXPERIENCE_REPOSITORY_SHARED.FIRMWARE.EVENTS.REPOSITORY });
await this.repositoryService.delete(firmware);
this.alertService.success(gettext('Firmware deleted.'));
this.refresh$.next();
}
catch (ex) {
// only if not cancel from modal
if (ex) {
this.alertService.addServerFailure(ex);
}
}
}
async onDataSourceModifier(dataSourceModifier) {
const dataRequest = this.repositoryService.listRepositoryEntries(RepositoryType.FIRMWARE, {
query: this.gridService.getQueryObj(dataSourceModifier.columns),
skipDefaultOrder: true,
params: {
pageSize: dataSourceModifier.pagination.pageSize,
currentPage: dataSourceModifier.pagination.currentPage
}
});
const filtererdSizeRequest = this.repositoryService
.listRepositoryEntries(RepositoryType.FIRMWARE, {
skipDefaultOrder: true,
query: this.gridService.getQueryObj(dataSourceModifier.columns),
params: { pageSize: 1 }
})
.then(response => response?.paging?.totalPages);
this.sizeRequest = this.repositoryService
.listRepositoryEntries(RepositoryType.FIRMWARE, {
skipDefaultOrder: true,
params: { pageSize: 1 }
})
.then(response => {
this.sizeRequestDone = true;
return response?.paging?.totalPages;
});
const [dataResponse, size, filteredSize] = await Promise.all([
dataRequest,
this.sizeRequest,
filtererdSizeRequest
]);
const { res, data, paging } = dataResponse;
const serverSideDataResult = {
res,
data,
paging,
filteredSize,
size
};
return serverSideDataResult;
}
trackByName(_index, column) {
return column.name;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FirmwareListComponent, deps: [{ token: i1.RepositoryService }, { token: i2.DataGridService }, { token: i2.ModalService }, { token: i3.BsModalService }, { token: i4.TranslateService }, { token: i2.AlertService }, { token: i5.Router }, { token: i5.ActivatedRoute }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: FirmwareListComponent, selector: "c8y-firmware-list", ngImport: i0, template: "<c8y-title>\n {{ 'Firmware repository' | translate }}\n</c8y-title>\n\n<c8y-breadcrumb>\n <c8y-breadcrumb-item\n icon=\"c8y-management\"\n label=\"{{ 'Management' | translate }}\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item\n icon=\"c8y-firmware\"\n label=\"{{ 'Firmware repository' | translate }}\"\n ></c8y-breadcrumb-item>\n</c8y-breadcrumb>\n\n<c8y-action-bar-item [placement]=\"'right'\">\n <button\n class=\"btn btn-link\"\n title=\"{{ 'Add firmware' | translate }}\"\n (click)=\"addFirmware()\"\n data-cy=\"firmware-list--toolbar-add-firmware-btn\"\n >\n <i c8yIcon=\"plus-circle\"></i>\n {{ 'Add firmware' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]=\"'right'\">\n <button\n class=\"btn btn-link\"\n title=\"{{ 'Add firmware patch' | translate }}\"\n *ngIf=\"isDataPresent$ | async\"\n (click)=\"addFirmwarePatch()\"\n >\n <i c8yIcon=\"plus-circle\"></i>\n {{ 'Add firmware patch' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-help\n src=\"/docs/device-management-application/managing-device-data/#managing-firmware\"\n></c8y-help>\n\n<div class=\"content-fullpage border-top border-bottom\">\n <c8y-data-grid\n [title]=\"'Firmware' | translate\"\n [refresh]=\"refresh$\"\n [pagination]=\"pagination\"\n [columns]=\"columns\"\n [actionControls]=\"actionControls\"\n [infiniteScroll]=\"'auto'\"\n [serverSideDataCallback]=\"serverSideDataCallback\"\n >\n <c8y-ui-empty-state\n [icon]=\"stats?.size > 0 ? 'search' : 'c8y-tools'\"\n [title]=\"stats?.size > 0 ? (noResultsMessage | translate) : (noDataMessage | translate)\"\n [subtitle]=\"stats?.size > 0 ? (noResultsSubtitle | translate) : (noDataSubtitle | translate)\"\n *emptyStateContext=\"let stats\"\n [horizontal]=\"stats?.size > 0\"\n >\n <p *ngIf=\"stats?.size === 0\">\n <button\n class=\"btn btn-primary\"\n title=\"{{ 'Add firmware' | translate }}\"\n type=\"button\"\n (click)=\"addFirmware()\"\n >\n {{ 'Add firmware' | translate }}\n </button>\n </p>\n </c8y-ui-empty-state>\n <ng-container *ngFor=\"let column of columns; trackBy: trackByName\">\n <c8y-column [name]=\"column.name\"></c8y-column>\n </ng-container>\n </c8y-data-grid>\n</div>\n", dependencies: [{ kind: "directive", type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2.ActionBarItemComponent, selector: "c8y-action-bar-item", inputs: ["placement", "priority", "itemClass", "injector", "groupId", "inGroupPriority"] }, { kind: "component", type: i2.BreadcrumbComponent, selector: "c8y-breadcrumb" }, { kind: "component", type: i2.BreadcrumbItemComponent, selector: "c8y-breadcrumb-item", inputs: ["icon", "translate", "label", "path", "injector"] }, { kind: "component", type: i2.EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "directive", type: i2.EmptyStateContextDirective, selector: "[emptyStateContext]" }, { kind: "directive", type: i2.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: i2.ColumnDirective, selector: "c8y-column", inputs: ["name"] }, { kind: "component", type: i2.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"], outputs: ["rowMouseOver", "rowMouseLeave", "rowClick", "onConfigChange", "onBeforeFilter", "onBeforeSearch", "onFilter", "itemsSelect", "onReload", "onAddCustomColumn", "onRemoveCustomColumn", "onColumnFilterReset", "onSort", "onPageSizeChange", "onColumnReordered", "onColumnVisibilityChange"] }, { kind: "component", type: i2.TitleComponent, selector: "c8y-title", inputs: ["pageTitleUpdate"] }, { kind: "component", type: i2.HelpComponent, selector: "c8y-help", inputs: ["src", "isCollapsed", "priority", "icon"] }, { kind: "pipe", type: i6.AsyncPipe, name: "async" }, { kind: "pipe", type: i2.C8yTranslatePipe, name: "translate" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: FirmwareListComponent, decorators: [{
type: Component,
args: [{ selector: 'c8y-firmware-list', template: "<c8y-title>\n {{ 'Firmware repository' | translate }}\n</c8y-title>\n\n<c8y-breadcrumb>\n <c8y-breadcrumb-item\n icon=\"c8y-management\"\n label=\"{{ 'Management' | translate }}\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item\n icon=\"c8y-firmware\"\n label=\"{{ 'Firmware repository' | translate }}\"\n ></c8y-breadcrumb-item>\n</c8y-breadcrumb>\n\n<c8y-action-bar-item [placement]=\"'right'\">\n <button\n class=\"btn btn-link\"\n title=\"{{ 'Add firmware' | translate }}\"\n (click)=\"addFirmware()\"\n data-cy=\"firmware-list--toolbar-add-firmware-btn\"\n >\n <i c8yIcon=\"plus-circle\"></i>\n {{ 'Add firmware' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]=\"'right'\">\n <button\n class=\"btn btn-link\"\n title=\"{{ 'Add firmware patch' | translate }}\"\n *ngIf=\"isDataPresent$ | async\"\n (click)=\"addFirmwarePatch()\"\n >\n <i c8yIcon=\"plus-circle\"></i>\n {{ 'Add firmware patch' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<c8y-help\n src=\"/docs/device-management-application/managing-device-data/#managing-firmware\"\n></c8y-help>\n\n<div class=\"content-fullpage border-top border-bottom\">\n <c8y-data-grid\n [title]=\"'Firmware' | translate\"\n [refresh]=\"refresh$\"\n [pagination]=\"pagination\"\n [columns]=\"columns\"\n [actionControls]=\"actionControls\"\n [infiniteScroll]=\"'auto'\"\n [serverSideDataCallback]=\"serverSideDataCallback\"\n >\n <c8y-ui-empty-state\n [icon]=\"stats?.size > 0 ? 'search' : 'c8y-tools'\"\n [title]=\"stats?.size > 0 ? (noResultsMessage | translate) : (noDataMessage | translate)\"\n [subtitle]=\"stats?.size > 0 ? (noResultsSubtitle | translate) : (noDataSubtitle | translate)\"\n *emptyStateContext=\"let stats\"\n [horizontal]=\"stats?.size > 0\"\n >\n <p *ngIf=\"stats?.size === 0\">\n <button\n class=\"btn btn-primary\"\n title=\"{{ 'Add firmware' | translate }}\"\n type=\"button\"\n (click)=\"addFirmware()\"\n >\n {{ 'Add firmware' | translate }}\n </button>\n </p>\n </c8y-ui-empty-state>\n <ng-container *ngFor=\"let column of columns; trackBy: trackByName\">\n <c8y-column [name]=\"column.name\"></c8y-column>\n </ng-container>\n </c8y-data-grid>\n</div>\n" }]
}], ctorParameters: () => [{ type: i1.RepositoryService }, { type: i2.DataGridService }, { type: i2.ModalService }, { type: i3.BsModalService }, { type: i4.TranslateService }, { type: i2.AlertService }, { type: i5.Router }, { type: i5.ActivatedRoute }] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmlybXdhcmUtbGlzdC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9yZXBvc2l0b3J5L2Zpcm13YXJlL2xpc3QvZmlybXdhcmUtbGlzdC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi9yZXBvc2l0b3J5L2Zpcm13YXJlL2xpc3QvZmlybXdhcmUtbGlzdC5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLFlBQVksRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUN4RCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBRXpELE9BQU8sRUFFTCxZQUFZLEVBQ1osaUJBQWlCLEVBRWpCLGVBQWUsRUFFZixZQUFZLEVBR1osTUFBTSxFQUNOLE9BQU8sRUFDUixNQUFNLHFCQUFxQixDQUFDO0FBQzdCLE9BQU8sRUFDTCxxQkFBcUIsRUFDckIsb0JBQW9CLEVBQ3BCLG9DQUFvQyxFQUNwQyw0QkFBNEIsRUFDNUIsaUJBQWlCLEVBQ2pCLGNBQWMsRUFDZCxrQkFBa0IsRUFDbkIsTUFBTSx1Q0FBdUMsQ0FBQztBQUMvQyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUN2RCxPQUFPLEVBQUUsY0FBYyxFQUFnQixNQUFNLHFCQUFxQixDQUFDO0FBQ25FLE9BQU8sRUFBYyxJQUFJLEVBQUUsR0FBRyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQzdDLE9BQU8sRUFBRSx5QkFBeUIsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQzNFLE9BQU8sRUFBRSw4QkFBOEIsRUFBRSxNQUFNLHNDQUFzQyxDQUFDOzs7Ozs7OztBQU10RixNQUFNLE9BQU8scUJBQXFCO0lBZ0NoQyxZQUNVLGlCQUFvQyxFQUNwQyxXQUE0QixFQUM1QixZQUEwQixFQUMxQixjQUE4QixFQUM5QixnQkFBa0MsRUFDbEMsWUFBMEIs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QztJQUVELFdBQVcsQ0FBQyxNQUFNLEVBQUUsTUFBYztRQUNoQyxPQUFPLE1BQU0sQ0FBQyxJQUFJLENBQUM7SUFDckIsQ0FBQzsrR0EzS1UscUJBQXFCO21HQUFyQixxQkFBcUIseURDbkNsQywrMEVBNEVBOzs0RkR6Q2EscUJBQXFCO2tCQUpqQyxTQUFTOytCQUNFLG1CQUFtQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgRXZlbnRFbWl0dGVyIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBBY3RpdmF0ZWRSb3V0ZSwgUm91dGVyIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7IElNYW5hZ2VkT2JqZWN0LCBJUmVzdWx0TGlzdCB9IGZyb20gJ0BjOHkvY2xpZW50JztcbmltcG9ydCB7XG4gIEFjdGlvbkNvbnRyb2wsXG4gIEFsZXJ0U2VydmljZSxcbiAgQnVpbHRJbkFjdGlvblR5cGUsXG4gIENvbHVtbixcbiAgRGF0YUdyaWRTZXJ2aWNlLFxuICBEYXRhU291cmNlTW9kaWZpZXIsXG4gIE1vZGFsU2VydmljZSxcbiAgU2VydmVyU2lkZURhdGFDYWxsYmFjayxcbiAgU2VydmVyU2lkZURhdGFSZXN1bHQsXG4gIFN0YXR1cyxcbiAgZ2V0dGV4dFxufSBmcm9tICdAYzh5L25neC1jb21wb25lbnRzJztcbmltcG9ydCB7XG4gIERlc2NyaXB0aW9uR3JpZENvbHVtbixcbiAgRGV2aWNlVHlwZUdyaWRDb2x1bW4sXG4gIFBST0RVQ1RfRVhQRVJJRU5DRV9SRVBPU0lUT1JZX1NIQVJFRCxcbiAgUmVwb3NpdG9yeUl0ZW1OYW1lR3JpZENvbHVtbixcbiAgUmVwb3NpdG9yeVNlcnZpY2UsXG4gIFJlcG9zaXRvcnlUeXBlLFxuICBWZXJzaW9uc0dyaWRDb2x1bW5cbn0gZnJvbSAnQGM4eS9uZ3gtY29tcG9uZW50cy9yZXBvc2l0b3J5L3NoYXJlZCc7XG5pbXBvcnQgeyBUcmFuc2xhdGVTZXJ2aWNlIH0gZnJvbSAnQG5neC10cmFuc2xhdGUvY29yZSc7XG5pbXBvcnQgeyBCc01vZGFsU2VydmljZSwgTW9kYWxPcHRpb25zIH0gZnJvbSAnbmd4LWJvb3RzdHJhcC9tb2RhbCc7XG5pbXBvcnQgeyBPYnNlcnZhYmxlLCBmcm9tLCBtYXAgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IEFkZEZpcm13YXJlTW9kYWxDb21wb25lbnQgfSBmcm9tICcuL2FkZC1maXJtd2FyZS1tb2RhbC5jb21wb25lbnQnO1xuaW1wb3J0IHsgQWRkRmlybXdhcmVQYXRjaE1vZGFsQ29tcG9uZW50IH0gZnJvbSAnLi9hZGQtZmlybXdhcmUtcGF0Y2gtbW9kYWwuY29tcG9uZW50JztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnYzh5LWZpcm13YXJlLWxpc3QnLFxuICB0ZW1wbGF0ZVVybDogJ2Zpcm13YXJlLWxpc3QuY29tcG9uZW50Lmh0bWwnXG59KVxuZXhwb3J0IGNsYXNzIEZpcm13YXJlTGlzdENvbXBvbmVudCB7XG4gIHNpemVSZXF1ZXN0OiBQcm9taXNlPG51bWJlcj47XG4gIHNpemVSZXF1ZXN0RG9uZSA9IGZhbHNlO1xuICByZWZyZXNoJDogRXZlbnRFbWl0dGVyPHZvaWQ+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICBpc0RhdGFQcmVzZW50JDogT2JzZXJ2YWJsZTxib29sZWFuPiA9IGZyb20oXG4gICAgdGhpcy5yZXBvc2l0b3J5U2VydmljZS5saXN0UmVwb3NpdG9yeUVudHJpZXMoUmVwb3NpdG9yeVR5cGUuRklSTVdBUkUsIHsgc2tpcExlZ2FjeTogdHJ1ZSB9KVxuICApLnBpcGUobWFwKCh7IGRhdGEgfSkgPT4gZGF0YS5sZW5ndGggPiAwKSk7XG5cbiAgY29sdW1uczogQ29sdW1uW10gPSBbXG4gICAgbmV3IFJlcG9zaXRvcnlJdGVtTmFtZUdyaWRDb2x1bW4oe1xuICAgICAgZmlsdGVyTGFiZWw6IGdldHRleHQoJ0ZpbHRlciBmaXJtd2FyZSBieSBuYW1lJyksXG4gICAgICBwbGFjZWhvbGRlcjogZ2V0dGV4dCgndWJ1bnR1IGNvcmUnKVxuICAgIH0pLFxuICAgIG5ldyBEZXNjcmlwdGlvbkdyaWRDb2x1bW4oe1xuICAgICAgZmlsdGVyTGFiZWw6IGdldHRleHQoJ0ZpbHRlciBmaXJtd2FyZSBieSBkZXNjcmlwdGlvbicpLFxuICAgICAgcGxhY2Vob2xkZXI6IGdldHRleHQoJ0Zpcm13YXJlIGZvciBoYXJkd2FyZSByZXZpc2lvbiBCJylcbiAgICB9KSxcbiAgICBuZXcgRGV2aWNlVHlwZUdyaWRDb2x1bW4oeyBmaWx0ZXJMYWJlbDogZ2V0dGV4dCgnRmlsdGVyIGZpcm13YXJlIGJ5IGRldmljZSB0eXBlJykgfSksXG4gICAgbmV3IFZlcnNpb25zR3JpZENvbHVtbigpXG4gIF07XG4gIGFjdGlvbkNvbnRyb2xzOiBBY3Rpb25Db250cm9sW10gPSBbXTtcbiAgc2VydmVyU2lkZURhdGFDYWxsYmFjazogU2VydmVyU2lkZURhdGFDYWxsYmFjaztcbiAgcGFnaW5hdGlvbiA9IHtcbiAgICBwYWdlU2l6ZTogNTAsXG4gICAgY3VycmVudFBhZ2U6IDFcbiAgfTtcblxuICBub1Jlc3VsdHNNZXNzYWdlID0gZ2V0dGV4dCgnTm8gcmVzdWx0cyB0byBkaXNwbGF5LicpO1xuICBub0RhdGFNZXNzYWdlID0gZ2V0dGV4dCgnTm8gZmlybXdhcmUgdG8gZGlzcGxheS4nKTtcbiAgbm9SZXN1bHRzU3VidGl0bGUgPSBnZXR0ZXh0KCdSZWZpbmUgeW91ciBzZWFyY2ggdGVybXMgb3IgY2hlY2sgeW91ciBzcGVsbGluZy4nKTtcbiAgbm9EYXRhU3VidGl0bGUgPSBnZXR0ZXh0KCdBZGQgYSBuZXcgZmlybXdhcmUgYnkgY2xpY2tpbmcgYmVsb3cuJyk7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZXBvc2l0b3J5U2VydmljZTogUmVwb3NpdG9yeVNlcnZpY2UsXG4gICAgcHJpdmF0ZSBncmlkU2VydmljZTogRGF0YUdyaWRTZXJ2aWNlLFxuICAgIHByaXZhdGUgbW9kYWxTZXJ2aWNlOiBNb2RhbFNlcnZpY2UsXG4gICAgcHJpdmF0ZSBic01vZGFsU2VydmljZTogQnNNb2RhbFNlcnZpY2UsXG4gICAgcHJpdmF0ZSB0cmFuc2xhdGVTZXJ2aWNlOiBUcmFuc2xhdGVTZXJ2aWNlLFxuICAgIHByaXZhdGUgYWxlcnRTZXJ2aWNlOiBBbGVydFNlcnZpY2UsXG4gICAgcHJpdmF0ZSByb3V0ZXI6IFJvdXRlcixcbiAgICBwcml2YXRlIGFjdGl2YXRlZFJvdXRlOiBBY3RpdmF0ZWRSb3V0ZVxuICApIHtcbiAgICB0aGlzLnNlcnZlclNpZGVEYXRhQ2FsbGJhY2sgPSB0aGlzLm9uRGF0YVNvdXJjZU1vZGlmaWVyLmJpbmQodGhpcyk7XG4gIH1cblxuICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICB0aGlzLmFjdGlvbkNvbnRyb2xzLnB1c2goe1xuICAgICAgdHlwZTogQnVpbHRJbkFjdGlvblR5cGUuRWRpdCxcbiAgICAgIGNhbGxiYWNrOiB0aGlzLmVkaXRGaXJtd2FyZS5iaW5kKHRoaXMpXG4gICAgfSk7XG4gICAgdGhpcy5hY3Rpb25Db250cm9scy5wdXNoKHtcbiAgICAgIHR5cGU6IEJ1aWx0SW5BY3Rpb25UeXBlLkRlbGV0ZSxcbiAgICAgIGNhbGxiYWNrOiB0aGlzLmRlbGV0ZUZpcm13YXJlLmJpbmQodGhpcylcbiAgICB9KTtcbiAgfVxuXG4gIGFkZEZpcm13YXJlKCkge1xuICAgIGNvbnN0IGNvbmZpZzogTW9kYWxPcHRpb25zPEFkZEZpcm13YXJlTW9kYWxDb21wb25lbnQ+ID0ge1xuICAgICAgY2xhc3M6ICdtb2RhbC1zbScsXG4gICAgICBhcmlhRGVzY3JpYmVkYnk6ICdhZGRGaXJtd2FyZU1vZGFsRGVzY3JpcHRpb24nLFxuICAgICAgYXJpYUxhYmVsbGVkQnk6ICdhZGRGaXJtd2FyZU1vZGFsVGl0bGUnLFxuICAgICAgaWdub3JlQmFja2Ryb3BDbGljazogdHJ1ZSxcbiAgICAgIGtleWJvYXJkOiBmYWxzZVxuICAgIH07XG4gICAgY29uc3QgbW9kYWxSZWYgPSB0aGlzLmJzTW9kYWxTZXJ2aWNlLnNob3coQWRkRmlybXdhcmVNb2RhbENvbXBvbmVudCwgY29uZmlnKTtcbiAgICBtb2RhbFJlZi5jb250ZW50LnNhdmVkLnN1YnNjcmliZShzYXZlZEZpcm13YXJlID0+IHRoaXMuZWRpdEZpcm13YXJlKHNhdmVkRmlybXdhcmUpKTtcbiAgfVxuXG4gIGFkZEZpcm13YXJlUGF0Y2goKSB7XG4gICAgY29uc3QgY29uZmlnOiBNb2RhbE9wdGlvbnM8QWRkRmlybXdhcmVQYXRjaE1vZGFsQ29tcG9uZW50PiA9IHtcbiAgICAgIGNsYXNzOiAnbW9kYWwtc20nLFxuICAgICAgYXJpYURlc2NyaWJlZGJ5OiAnYWRkRmlybXdhcmVQYXRjaE1vZGFsRGVzY3JpcHRpb24nLFxuICAgICAgYXJpYUxhYmVsbGVkQnk6ICdhZGRGaXJtd2FyZVBhdGNoTW9kYWxUaXRsZScsXG4gICAgICBpZ25vcmVCYWNrZHJvcENsaWNrOiB0cnVlLFxuICAgICAga2V5Ym9hcmQ6IGZhbHNlXG4gICAgfTtcbiAgICBjb25zdCBtb2RhbFJlZiA9IHRoaXMuYnNNb2RhbFNlcnZpY2Uuc2hvdyhBZGRGaXJtd2FyZVBhdGNoTW9kYWxDb21wb25lbnQsIGNvbmZpZyk7XG4gICAgbW9kYWxSZWYuY29udGVudC5zYXZlZC5zdWJzY3JpYmUoc2F2ZWRGaXJtd2FyZSA9PiB0aGlzLmVkaXRGaXJtd2FyZShzYXZlZEZpcm13YXJlKSk7XG4gIH1cblxuICBlZGl0RmlybXdhcmUoZmlybXdhcmU6IFBhcnRpYWw8SU1hbmFnZWRPYmplY3Q+KSB7XG4gICAgdGhpcy5yb3V0ZXIubmF2aWdhdGUoW2Zpcm13YXJlLmlkXSwgeyByZWxhdGl2ZVRvOiB0aGlzLmFjdGl2YXRlZFJvdXRlIH0pO1xuICB9XG5cbiAgYXN5bmMgZGVsZXRlRmlybXdhcmUoZmlybXdhcmU6IElNYW5hZ2VkT2JqZWN0KSB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHRpdGxlID0gZ2V0dGV4dCgnRGVsZXRlIGZpcm13YXJlJyk7XG4gICAgICBjb25zdCBib2R5ID0gYFxuICAgICAgICAke3RoaXMudHJhbnNsYXRlU2VydmljZS5pbnN0YW50KFxuICAgICAgICAgIGdldHRleHQoXG4gICAgICAgICAgICAnWW91IGFyZSBhYm91dCB0byBkZWxldGUgZmlybXdhcmUgXCJ7eyBuYW1lIH19XCIgd2l0aCBhbGwgaXRzIHZlcnNpb25zIGFuZCBwYXRjaGVzLidcbiAgICAgICAgICApLFxuICAgICAgICAgIHsgbmFtZTogZmlybXdhcmUubmFtZSB9XG4gICAgICAgICl9XG4gICAgICAgICR7dGhpcy50cmFuc2xhdGVTZXJ2aWNlLmluc3RhbnQoZ2V0dGV4dCgnVGhpcyBvcGVyYXRpb24gaXMgaXJyZXZlcnNpYmxlLicpKX1cbiAgICAgICAgJHt0aGlzLnRyYW5zbGF0ZVNlcnZpY2UuaW5zdGFudChnZXR0ZXh0KCdEbyB5b3Ugd2FudCB0byBwcm9jZWVkPycpKX1cbiAgICAgIGA7XG4gICAgICBjb25zdCBsYWJlbHMgPSB7XG4gICAgICAgIG9rOiBnZXR0ZXh0KCdEZWxldGUnKVxuICAgICAgfTtcbiAgICAgIGF3YWl0IHRoaXMubW9kYWxTZXJ2aWNlLmNvbmZpcm0oXG4gICAgICAgIHRpdGxlLFxuICAgICAgICBib2R5LFxuICAgICAgICBTdGF0dXMuREFOR0VSLFxuICAgICAgICBsYWJlbHMsXG4gICAgICAgIHt9LFxuICAgICAgICB7IGV2ZW50TmFtZTogUFJPRFVDVF9FWFBFUklFTkNFX1JFUE9TSVRPUllfU0hBUkVELkZJUk1XQVJFLkVWRU5UUy5SRVBPU0lUT1JZIH1cbiAgICAgICk7XG4gICAgICBhd2FpdCB0aGlzLnJlcG9zaXRvcnlTZXJ2aWNlLmRlbGV0ZShmaXJtd2FyZSk7XG4gICAgICB0aGlzLmFsZXJ0U2VydmljZS5zdWNjZXNzKGdldHRleHQoJ0Zpcm13YXJlIGRlbGV0ZWQuJykpO1xuICAgICAgdGhpcy5yZWZyZXNoJC5uZXh0KCk7XG4gICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgIC8vIG9ubHkgaWYgbm90IGNhbmNlbCBmcm9tIG1vZGFsXG4gICAgICBpZiAoZXgpIHtcbiAgICAgICAgdGhpcy5hbGVydFNlcnZpY2UuYWRkU2VydmVyRmFpbHVyZShleCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgb25EYXRhU291cmNlTW9kaWZpZXIoXG4gICAgZGF0YVNvdXJjZU1vZGlmaWVyOiBEYXRhU291cmNlTW9kaWZpZXJcbiAgKTogUHJvbWlzZTxTZXJ2ZXJTaWRlRGF0YVJlc3VsdD4ge1xuICAgIGNvbnN0IGRhdGFSZXF1ZXN0OiBQcm9taXNlPElSZXN1bHRMaXN0PElNYW5hZ2VkT2JqZWN0Pj4gPVxuICAgICAgdGhpcy5yZXBvc2l0b3J5U2VydmljZS5saXN0UmVwb3NpdG9yeUVudHJpZXMoUmVwb3NpdG9yeVR5cGUuRklSTVdBUkUsIHtcbiAgICAgICAgcXVlcnk6IHRoaXMuZ3JpZFNlcnZpY2UuZ2V0UXVlcnlPYmooZGF0YVNvdXJjZU1vZGlmaWVyLmNvbHVtbnMpLFxuICAgICAgICBza2lwRGVmYXVsdE9yZGVyOiB0cnVlLFxuICAgICAgICBwYXJhbXM6IHtcbiAgICAgICAgICBwYWdlU2l6ZTogZGF0YVNvdXJjZU1vZGlmaWVyLnBhZ2luYXRpb24ucGFnZVNpemUsXG4gICAgICAgICAgY3VycmVudFBhZ2U6IGRhdGFTb3VyY2VNb2RpZmllci5wYWdpbmF0aW9uLmN1cnJlbnRQYWdlXG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgY29uc3QgZmlsdGVyZXJkU2l6ZVJlcXVlc3Q6IFByb21pc2U8bnVtYmVyPiA9IHRoaXMucmVwb3NpdG9yeVNlcnZpY2VcbiAgICAgIC5saXN0UmVwb3NpdG9yeUVudHJpZXMoUmVwb3NpdG9yeVR5cGUuRklSTVdBUkUsIHtcbiAgICAgICAgc2tpcERlZmF1bHRPcmRlcjogdHJ1ZSxcbiAgICAgICAgcXVlcnk6IHRoaXMuZ3JpZFNlcnZpY2UuZ2V0UXVlcnlPYmooZGF0YVNvdXJjZU1vZGlmaWVyLmNvbHVtbnMpLFxuICAgICAgICBwYXJhbXM6IHsgcGFnZVNpemU6IDEgfVxuICAgICAgfSlcbiAgICAgIC50aGVuKHJlc3BvbnNlID0+IHJlc3BvbnNlPy5wYWdpbmc/LnRvdGFsUGFnZXMpO1xuXG4gICAgdGhpcy5zaXplUmVxdWVzdCA9IHRoaXMucmVwb3NpdG9yeVNlcnZpY2VcbiAgICAgIC5saXN0UmVwb3NpdG9yeUVudHJpZXMoUmVwb3NpdG9yeVR5cGUuRklSTVdBUkUsIHtcbiAgICAgICAgc2tpcERlZmF1bHRPcmRlcjogdHJ1ZSxcbiAgICAgICAgcGFyYW1zOiB7IHBhZ2VTaXplOiAxIH1cbiAgICAgIH0pXG4gICAgICAudGhlbihyZXNwb25zZSA9PiB7XG4gICAgICAgIHRoaXMuc2l6ZVJlcXVlc3REb25lID0gdHJ1ZTtcbiAgICAgICAgcmV0dXJuIHJlc3BvbnNlPy5wYWdpbmc/LnRvdGFsUGFnZXM7XG4gICAgICB9KTtcblxuICAgIGNvbnN0IFtkYXRhUmVzcG9uc2UsIHNpemUsIGZpbHRlcmVkU2l6ZV0gPSBhd2FpdCBQcm9taXNlLmFsbChbXG4gICAgICBkYXRhUmVxdWVzdCxcbiAgICAgIHRoaXMuc2l6ZVJlcXVlc3QsXG4gICAgICBmaWx0ZXJlcmRTaXplUmVxdWVzdFxuICAgIF0pO1xuXG4gICAgY29uc3QgeyByZXMsIGRhdGEsIHBhZ2luZyB9ID0gZGF0YVJlc3BvbnNlO1xuXG4gICAgY29uc3Qgc2VydmVyU2lkZURhdGFSZXN1bHQ6IFNlcnZlclNpZGVEYXRhUmVzdWx0ID0ge1xuICAgICAgcmVzLFxuICAgICAgZGF0YSxcbiAgICAgIHBhZ2luZyxcbiAgICAgIGZpbHRlcmVkU2l6ZSxcbiAgICAgIHNpemVcbiAgICB9O1xuXG4gICAgcmV0dXJuIHNlcnZlclNpZGVEYXRhUmVzdWx0O1xuICB9XG5cbiAgdHJhY2tCeU5hbWUoX2luZGV4LCBjb2x1bW46IENvbHVtbik6IHN0cmluZyB7XG4gICAgcmV0dXJuIGNvbHVtbi5uYW1lO1xuICB9XG59XG4iLCI8Yzh5LXRpdGxlPlxuICB7eyAnRmlybXdhcmUgcmVwb3NpdG9yeScgfCB0cmFuc2xhdGUgfX1cbjwvYzh5LXRpdGxlPlxuXG48Yzh5LWJyZWFkY3J1bWI+XG4gIDxjOHktYnJlYWRjcnVtYi1pdGVtXG4gICAgaWNvbj1cImM4eS1tYW5hZ2VtZW50XCJcbiAgICBsYWJlbD1cInt7ICdNYW5hZ2VtZW50JyB8IHRyYW5zbGF0ZSB9fVwiXG4gID48L2M4eS1icmVhZGNydW1iLWl0ZW0+XG4gIDxjOHktYnJlYWRjcnVtYi1pdGVtXG4gICAgaWNvbj1cImM4eS1maXJtd2FyZVwiXG4gICAgbGFiZWw9XCJ7eyAnRmlybXdhcmUgcmVwb3NpdG9yeScgfCB0cmFuc2xhdGUgfX1cIlxuICA+PC9jOHktYnJlYWRjcnVtYi1pdGVtPlxuPC9jOHktYnJlYWRjcnVtYj5cblxuPGM4eS1hY3Rpb24tYmFyLWl0ZW0gW3BsYWNlbWVudF09XCIncmlnaHQnXCI+XG4gIDxidXR0b25cbiAgICBjbGFzcz1cImJ0biBidG4tbGlua1wiXG4gICAgdGl0bGU9XCJ7eyAnQWRkIGZpcm13YXJlJyB8IHRyYW5zbGF0ZSB9fVwiXG4gICAgKGNsaWNrKT1cImFkZEZpcm13YXJlKClcIlxuICAgIGRhdGEtY3k9XCJmaXJtd2FyZS1saXN0LS10b29sYmFyLWFkZC1maXJtd2FyZS1idG5cIlxuICA+XG4gICAgPGkgYzh5SWNvbj1cInBsdXMtY2lyY2xlXCI+PC9pPlxuICAgIHt7ICdBZGQgZmlybXdhcmUnIHwgdHJhbnNsYXRlIH19XG4gIDwvYnV0dG9uPlxuPC9jOHktYWN0aW9uLWJhci1pdGVtPlxuXG48Yzh5LWFjdGlvbi1iYXItaXRlbSBbcGxhY2VtZW50XT1cIidyaWdodCdcIj5cbiAgPGJ1dHRvblxuICAgIGNsYXNzPVwiYnRuIGJ0bi1saW5rXCJcbiAgICB0aXRsZT1cInt7ICdBZGQgZmlybXdhcmUgcGF0Y2gnIHwgdHJhbnNsYXRlIH19XCJcbiAgICAqbmdJZj1cImlzRGF0YVByZXNlbnQkIHwgYXN5bmNcIlxuICAgIChjbGljayk9XCJhZGRGaXJtd2FyZVBhdGNoKClcIlxuICA+XG4gICAgPGkgYzh5SWNvbj1cInBsdXMtY2lyY2xlXCI+PC9pPlxuICAgIHt7ICdBZGQgZmlybXdhcmUgcGF0Y2gnIHwgdHJhbnNsYXRlIH19XG4gIDwvYnV0dG9uPlxuPC9jOHktYWN0aW9uLWJhci1pdGVtPlxuXG48Yzh5LWhlbHBcbiAgc3JjPVwiL2RvY3MvZGV2aWNlLW1hbmFnZW1lbnQtYXBwbGljYXRpb24vbWFuYWdpbmctZGV2aWNlLWRhdGEvI21hbmFnaW5nLWZpcm13YXJlXCJcbj48L2M4eS1oZWxwPlxuXG48ZGl2IGNsYXNzPVwiY29udGVudC1mdWxscGFnZSBib3JkZXItdG9wIGJvcmRlci1ib3R0b21cIj5cbiAgPGM4eS1kYXRhLWdyaWRcbiAgICBbdGl0bGVdPVwiJ0Zpcm13YXJlJyB8IHRyYW5zbGF0ZVwiXG4gICAgW3JlZnJlc2hdPVwicmVmcmVzaCRcIlxuICAgIFtwYWdpbmF0aW9uXT1cInBhZ2luYXRpb25cIlxuICAgIFtjb2x1bW5zXT1cImNvbHVtbnNcIlxuICAgIFthY3Rpb25Db250cm9sc109XCJhY3Rpb25Db250cm9sc1wiXG4gICAgW2luZmluaXRlU2Nyb2xsXT1cIidhdXRvJ1wiXG4gICAgW3NlcnZlclNpZGVEYXRhQ2FsbGJhY2tdPVwic2VydmVyU2lkZURhdGFDYWxsYmFja1wiXG4gID5cbiAgICA8Yzh5LXVpLWVtcHR5LXN0YXRlXG4gICAgICBbaWNvbl09XCJzdGF0cz8uc2l6ZSA+IDAgPyAnc2VhcmNoJyA6ICdjOHktdG9vbHMnXCJcbiAgICAgIFt0aXRsZV09XCJzdGF0cz8uc2l6ZSA+IDAgPyAobm9SZXN1bHRzTWVzc2FnZSB8IHRyYW5zbGF0ZSkgOiAobm9EYXRhTWVzc2FnZSB8IHRyYW5zbGF0ZSlcIlxuICAgICAgW3N1YnRpdGxlXT1cInN0YXRzPy5zaXplID4gMCA/IChub1Jlc3VsdHNTdWJ0aXRsZSB8IHRyYW5zbGF0ZSkgOiAobm9EYXRhU3VidGl0bGUgfCB0cmFuc2xhdGUpXCJcbiAgICAgICplbXB0eVN0YXRlQ29udGV4dD1cImxldCBzdGF0c1wiXG4gICAgICBbaG9yaXpvbnRhbF09XCJzdGF0cz8uc2l6ZSA+IDBcIlxuICAgID5cbiAgICAgIDxwICpuZ0lmPVwic3RhdHM/LnNpemUgPT09IDBcIj5cbiAgICAgICAgPGJ1dHRvblxuICAgICAgICAgIGNsYXNzPVwiYnRuIGJ0bi1wcmltYXJ5XCJcbiAgICAgICAgICB0aXRsZT1cInt7ICdBZGQgZmlybXdhcmUnIHwgdHJhbnNsYXRlIH19XCJcbiAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAoY2xpY2spPVwiYWRkRmlybXdhcmUoKVwiXG4gICAgICAgID5cbiAgICAgICAgICB7eyAnQWRkIGZpcm13YXJlJyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICA8L2J1dHRvbj5cbiAgICAgIDwvcD5cbiAgICA8L2M4eS11aS1lbXB0eS1zdGF0ZT5cbiAgICA8bmctY29udGFpbmVyICpuZ0Zvcj1cImxldCBjb2x1bW4gb2YgY29sdW1uczsgdHJhY2tCeTogdHJhY2tCeU5hbWVcIj5cbiAgICAgIDxjOHktY29sdW1uIFtuYW1lXT1cImNvbHVtbi5uYW1lXCI+PC9jOHktY29sdW1uPlxuICAgIDwvbmctY29udGFpbmVyPlxuICA8L2M4eS1kYXRhLWdyaWQ+XG48L2Rpdj5cbiJdfQ==