@c8y/ngx-components
Version:
Angular modules for Cumulocity IoT applications
97 lines • 33.2 kB
JavaScript
import { Component, forwardRef, input, ViewChild } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { CoreModule, gettext, OperationRealtimeService, PRODUCT_EXPERIENCE_EVENT_SOURCE } from '@c8y/ngx-components';
import { SINGLE_OPERATION_EVENT_DEVICE_TAB, SINGLE_OPERATION_EVENT_OVERVIEW } from '@c8y/ngx-components/operations/product-experience';
import { OPERATION_STATUS_OPTIONS_MAP } from '@c8y/ngx-components/operations/shared';
import { StatusFilterComponent, StatusFilterModule } from '@c8y/ngx-components/operations/status-filter';
import { flatten } from 'lodash-es';
import { BehaviorSubject, combineLatest, pipe } from 'rxjs';
import { map, shareReplay, switchMap, tap } from 'rxjs/operators';
import { OperationsListItemComponent } from './operations-list-item.component';
import { OperationsListService } from './operations-list.service';
import * as i0 from "@angular/core";
import * as i1 from "@c8y/ngx-components";
import * as i2 from "./operations-list.service";
import * as i3 from "@angular/router";
import * as i4 from "@angular/common";
import * as i5 from "@c8y/ngx-components/operations/status-filter";
export class OperationsListComponent {
constructor(realtime, operationsListService, route) {
this.realtime = realtime;
this.operationsListService = operationsListService;
this.route = route;
this.fragmentType = input();
this.readOnlyItems = input(false);
this.deviceId = this.route.snapshot.parent.data.contextData?.id;
this.OPERATION_STATUS_OPTIONS_MAP = OPERATION_STATUS_OPTIONS_MAP;
this.refreshLoading = false;
this.isSmartRulesMicroserviceAvailable = false;
this.showOverviewBreadcrumbs = false;
this.statusFilter$ = new BehaviorSubject(null);
this.reload$ = new BehaviorSubject(null);
this.operations$ = combineLatest(this.statusFilter$, this.reload$).pipe(tap(() => {
this.refreshLoading = true;
}), switchMap(([statusFilters]) => this.filter(statusFilters)), tap(() => {
this.refreshLoading = false;
}), shareReplay(1));
this.operationsFilterPipe = pipe(map((operations) => {
const statusFilters = this.statusFilter$.getValue();
if (!statusFilters || !statusFilters.length) {
return operations;
}
const allowedStatuses = flatten(statusFilters.map(sf => sf.status));
return operations.filter(op => allowedStatuses.includes(op.status));
}));
this.productExperienceEvent = {
eventName: !!this.deviceId ? SINGLE_OPERATION_EVENT_DEVICE_TAB : SINGLE_OPERATION_EVENT_OVERVIEW
};
this.title = this.route.snapshot.parent.data.contextData
? this.route.snapshot.parent.data.contextData.name
: gettext('Single operations');
this.showOverviewBreadcrumbs = !this.deviceId;
}
async ngOnInit() {
this.isSmartRulesMicroserviceAvailable =
await this.operationsListService.isSmartRulesMicroserviceAvailable();
}
filter(statusFilters) {
const status = statusFilters && statusFilters.length > 0
? {
status: flatten(statusFilters.map(statusFilter => statusFilter.status))
}
: {};
return this.getOperations(status);
}
getOperations(filter) {
let queryFilter = this.deviceId ? { ...filter, deviceId: this.deviceId } : filter;
if (this.fragmentType()) {
queryFilter = { ...queryFilter, fragmentType: this.fragmentType() };
}
return this.operationsListService.getOperations(queryFilter);
}
compareOperations(operationA, operationB) {
return (new Date(operationA.creationTime).getTime() - new Date(operationB.creationTime).getTime());
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: OperationsListComponent, deps: [{ token: i1.OperationRealtimeService }, { token: i2.OperationsListService }, { token: i3.ActivatedRoute }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "18.2.13", type: OperationsListComponent, isStandalone: true, selector: "c8y-operations-list", inputs: { fragmentType: { classPropertyName: "fragmentType", publicName: "fragmentType", isSignal: true, isRequired: false, transformFunction: null }, readOnlyItems: { classPropertyName: "readOnlyItems", publicName: "readOnlyItems", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
OperationRealtimeService,
{
provide: PRODUCT_EXPERIENCE_EVENT_SOURCE,
useExisting: forwardRef(() => OperationsListComponent)
}
], viewQueries: [{ propertyName: "statusFilter", first: true, predicate: ["statusFilter"], descendants: true, static: true }], ngImport: i0, template: "<c8y-title>{{ title | translate }}</c8y-title>\n\n<c8y-breadcrumb *ngIf=\"showOverviewBreadcrumbs\">\n <c8y-breadcrumb-item\n [icon]=\"'c8y-overviews'\"\n [label]=\"'Overviews' | translate\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item\n [icon]=\"'c8y-device-control'\"\n [label]=\"'Device Control' | translate\"\n [path]=\"'devicecontrol/single'\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item\n [icon]=\"'c8y-device-control'\"\n [label]=\"'Single operations' | translate\"\n ></c8y-breadcrumb-item>\n</c8y-breadcrumb>\n\n<c8y-action-bar-item\n [placement]=\"'left'\"\n itemClass=\"navbar-form\"\n>\n <c8y-status-filter\n #statusFilter\n [options]=\"OPERATION_STATUS_OPTIONS_MAP\"\n (onFilterChanged)=\"statusFilter$.next($event)\"\n c8yProductExperience\n inherit\n ></c8y-status-filter>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]=\"'right'\">\n <c8y-realtime-btn [service]=\"realtime\"></c8y-realtime-btn>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]=\"'right'\">\n <button\n class=\"btn btn-link d-flex a-i-center\"\n title=\"{{ 'Reload' | translate }}\"\n (click)=\"reload$.next()\"\n >\n <i\n class=\"m-r-4\"\n c8yIcon=\"refresh\"\n [ngClass]=\"{ 'icon-spin': refreshLoading }\"\n ></i>\n <span class=\"text-truncate\">\n {{ 'Reload' | translate }}\n </span>\n </button>\n</c8y-action-bar-item>\n\n<ng-content select=\"c8y-help\">\n <c8y-help\n src=\"/docs/device-management-application/monitoring-and-controlling-devices/#to-view-single-operations\"\n ></c8y-help>\n</ng-content>\n\n<!-- Empty state -->\n<c8y-ui-empty-state\n [icon]=\"'c8y-energy'\"\n [title]=\"'No items to display.' | translate\"\n [subtitle]=\"'Operations will be displayed here.' | translate\"\n *ngIf=\"(operations$ | async)?.data.length === 0 && !(statusFilter$ | async)\"\n></c8y-ui-empty-state>\n<!-- No results empty state -->\n<c8y-ui-empty-state\n [icon]=\"'search'\"\n [title]=\"'No results to display.' | translate\"\n [subtitle]=\"'Adjust or reset the filter.' | translate\"\n *ngIf=\"(operations$ | async)?.data.length === 0 && (statusFilter$ | async)\"\n>\n <button\n class=\"btn btn-primary\"\n title=\"{{ 'Reset filter' | translate }}\"\n type=\"button\"\n (click)=\"statusFilter.reset()\"\n translate\n >\n Reset filter\n </button>\n</c8y-ui-empty-state>\n\n<!-- Detailed list of operations + load more button -->\n<c8y-list-group class=\"m-b-24\">\n <div\n class=\"page-sticky-header c8y-list__item c8y-list__item--double-actions hidden-xs\"\n *ngIf=\"(operations$ | async)?.data.length\"\n >\n <div class=\"c8y-list__item__block\">\n <div class=\"c8y-list__item__icon\">\n <i class=\"p-l-24\"></i>\n </div>\n <div class=\"c8y-list__item__body text-truncate-wrap\">\n <div class=\"content-flex-57\">\n <div class=\"col-5\">\n {{ 'Operation' | translate }}\n </div>\n <div\n class=\"flex-grow\"\n *ngIf=\"!deviceId\"\n >\n {{ 'Device' | translate }}\n </div>\n <div class=\"col-4\">\n {{ 'Date created' | translate }}\n </div>\n </div>\n </div>\n <div class=\"c8y-list__item__actions\"></div>\n </div>\n </div>\n <div\n class=\"d-contents\"\n *c8yFor=\"\n let op of operations$ | async;\n let i = index;\n realtime: realtime;\n realtimeOptions: { entityOrId: deviceId, removeOnUpdate: true, insertOnUpdate: true };\n comparator: compareOperations.bind(this);\n loadMore: 'auto';\n pipe: operationsFilterPipe\n \"\n >\n <c8y-operations-list-item\n class=\"d-contents\"\n [operation]=\"op\"\n [readOnly]=\"readOnlyItems()\"\n [isSmartRulesMicroserviceAvailable]=\"isSmartRulesMicroserviceAvailable\"\n (reload)=\"reload$.next()\"\n c8yProductExperience\n inherit\n ></c8y-operations-list-item>\n </div>\n</c8y-list-group>\n", dependencies: [{ kind: "ngmodule", type: CoreModule }, { kind: "component", type: i1.ActionBarItemComponent, selector: "c8y-action-bar-item", inputs: ["placement", "priority", "itemClass", "injector", "groupId", "inGroupPriority"] }, { kind: "component", type: i1.BreadcrumbComponent, selector: "c8y-breadcrumb" }, { kind: "component", type: i1.BreadcrumbItemComponent, selector: "c8y-breadcrumb-item", inputs: ["icon", "translate", "label", "path", "injector"] }, { kind: "component", type: i1.EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "directive", type: i1.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "pipe", type: i1.C8yTranslatePipe, name: "translate" }, { kind: "directive", type: i1.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }, { kind: "directive", type: i1.ForOfDirective, selector: "[c8yFor]", inputs: ["c8yForOf", "c8yForLoadMore", "c8yForPipe", "c8yForNotFound", "c8yForMaxIterations", "c8yForLoadingTemplate", "c8yForLoadNextLabel", "c8yForLoadingLabel", "c8yForRealtime", "c8yForRealtimeOptions", "c8yForComparator", "c8yForEnableVirtualScroll", "c8yForVirtualScrollElementSize", "c8yForVirtualScrollStrategy", "c8yForVirtualScrollContainerHeight"], outputs: ["c8yForCount", "c8yForChange", "c8yForLoadMoreComponent"] }, { kind: "component", type: i1.TitleComponent, selector: "c8y-title", inputs: ["pageTitleUpdate"] }, { kind: "component", type: i1.ListGroupComponent, selector: "c8y-list-group" }, { kind: "directive", type: i1.ProductExperienceDirective, selector: "[c8yProductExperience]", inputs: ["actionName", "actionData", "inherit", "suppressDataOverriding"] }, { kind: "component", type: i1.HelpComponent, selector: "c8y-help", inputs: ["src", "isCollapsed", "priority", "icon"] }, { kind: "component", type: i1.RealtimeButtonComponent, selector: "c8y-realtime-btn", inputs: ["service", "label", "title", "disabled"], outputs: ["onToggle"] }, { kind: "ngmodule", type: StatusFilterModule }, { kind: "component", type: i5.StatusFilterComponent, selector: "c8y-status-filter", inputs: ["options", "multiple", "small"], outputs: ["onFilterChanged"] }, { kind: "component", type: OperationsListItemComponent, selector: "c8y-operations-list-item", inputs: ["operation", "collapsed", "readOnly", "noExpandToggle", "isSmartRulesMicroserviceAvailable"] }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: OperationsListComponent, decorators: [{
type: Component,
args: [{ selector: 'c8y-operations-list', standalone: true, imports: [CoreModule, StatusFilterModule, OperationsListItemComponent], providers: [
OperationRealtimeService,
{
provide: PRODUCT_EXPERIENCE_EVENT_SOURCE,
useExisting: forwardRef(() => OperationsListComponent)
}
], template: "<c8y-title>{{ title | translate }}</c8y-title>\n\n<c8y-breadcrumb *ngIf=\"showOverviewBreadcrumbs\">\n <c8y-breadcrumb-item\n [icon]=\"'c8y-overviews'\"\n [label]=\"'Overviews' | translate\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item\n [icon]=\"'c8y-device-control'\"\n [label]=\"'Device Control' | translate\"\n [path]=\"'devicecontrol/single'\"\n ></c8y-breadcrumb-item>\n <c8y-breadcrumb-item\n [icon]=\"'c8y-device-control'\"\n [label]=\"'Single operations' | translate\"\n ></c8y-breadcrumb-item>\n</c8y-breadcrumb>\n\n<c8y-action-bar-item\n [placement]=\"'left'\"\n itemClass=\"navbar-form\"\n>\n <c8y-status-filter\n #statusFilter\n [options]=\"OPERATION_STATUS_OPTIONS_MAP\"\n (onFilterChanged)=\"statusFilter$.next($event)\"\n c8yProductExperience\n inherit\n ></c8y-status-filter>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]=\"'right'\">\n <c8y-realtime-btn [service]=\"realtime\"></c8y-realtime-btn>\n</c8y-action-bar-item>\n\n<c8y-action-bar-item [placement]=\"'right'\">\n <button\n class=\"btn btn-link d-flex a-i-center\"\n title=\"{{ 'Reload' | translate }}\"\n (click)=\"reload$.next()\"\n >\n <i\n class=\"m-r-4\"\n c8yIcon=\"refresh\"\n [ngClass]=\"{ 'icon-spin': refreshLoading }\"\n ></i>\n <span class=\"text-truncate\">\n {{ 'Reload' | translate }}\n </span>\n </button>\n</c8y-action-bar-item>\n\n<ng-content select=\"c8y-help\">\n <c8y-help\n src=\"/docs/device-management-application/monitoring-and-controlling-devices/#to-view-single-operations\"\n ></c8y-help>\n</ng-content>\n\n<!-- Empty state -->\n<c8y-ui-empty-state\n [icon]=\"'c8y-energy'\"\n [title]=\"'No items to display.' | translate\"\n [subtitle]=\"'Operations will be displayed here.' | translate\"\n *ngIf=\"(operations$ | async)?.data.length === 0 && !(statusFilter$ | async)\"\n></c8y-ui-empty-state>\n<!-- No results empty state -->\n<c8y-ui-empty-state\n [icon]=\"'search'\"\n [title]=\"'No results to display.' | translate\"\n [subtitle]=\"'Adjust or reset the filter.' | translate\"\n *ngIf=\"(operations$ | async)?.data.length === 0 && (statusFilter$ | async)\"\n>\n <button\n class=\"btn btn-primary\"\n title=\"{{ 'Reset filter' | translate }}\"\n type=\"button\"\n (click)=\"statusFilter.reset()\"\n translate\n >\n Reset filter\n </button>\n</c8y-ui-empty-state>\n\n<!-- Detailed list of operations + load more button -->\n<c8y-list-group class=\"m-b-24\">\n <div\n class=\"page-sticky-header c8y-list__item c8y-list__item--double-actions hidden-xs\"\n *ngIf=\"(operations$ | async)?.data.length\"\n >\n <div class=\"c8y-list__item__block\">\n <div class=\"c8y-list__item__icon\">\n <i class=\"p-l-24\"></i>\n </div>\n <div class=\"c8y-list__item__body text-truncate-wrap\">\n <div class=\"content-flex-57\">\n <div class=\"col-5\">\n {{ 'Operation' | translate }}\n </div>\n <div\n class=\"flex-grow\"\n *ngIf=\"!deviceId\"\n >\n {{ 'Device' | translate }}\n </div>\n <div class=\"col-4\">\n {{ 'Date created' | translate }}\n </div>\n </div>\n </div>\n <div class=\"c8y-list__item__actions\"></div>\n </div>\n </div>\n <div\n class=\"d-contents\"\n *c8yFor=\"\n let op of operations$ | async;\n let i = index;\n realtime: realtime;\n realtimeOptions: { entityOrId: deviceId, removeOnUpdate: true, insertOnUpdate: true };\n comparator: compareOperations.bind(this);\n loadMore: 'auto';\n pipe: operationsFilterPipe\n \"\n >\n <c8y-operations-list-item\n class=\"d-contents\"\n [operation]=\"op\"\n [readOnly]=\"readOnlyItems()\"\n [isSmartRulesMicroserviceAvailable]=\"isSmartRulesMicroserviceAvailable\"\n (reload)=\"reload$.next()\"\n c8yProductExperience\n inherit\n ></c8y-operations-list-item>\n </div>\n</c8y-list-group>\n" }]
}], ctorParameters: () => [{ type: i1.OperationRealtimeService }, { type: i2.OperationsListService }, { type: i3.ActivatedRoute }], propDecorators: { statusFilter: [{
type: ViewChild,
args: ['statusFilter', { static: true }]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3BlcmF0aW9ucy1saXN0LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL29wZXJhdGlvbnMvb3BlcmF0aW9ucy1saXN0L29wZXJhdGlvbnMtbGlzdC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi9vcGVyYXRpb25zL29wZXJhdGlvbnMtbGlzdC9vcGVyYXRpb25zLWxpc3QuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxVQUFVLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUN4RSxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFFakQsT0FBTyxFQUNMLFVBQVUsRUFDVixPQUFPLEVBQ1Asd0JBQXdCLEVBQ3hCLCtCQUErQixFQUdoQyxNQUFNLHFCQUFxQixDQUFDO0FBQzdCLE9BQU8sRUFDTCxpQ0FBaUMsRUFDakMsK0JBQStCLEVBQ2hDLE1BQU0sbURBQW1ELENBQUM7QUFDM0QsT0FBTyxFQUNMLDRCQUE0QixFQUc3QixNQUFNLHVDQUF1QyxDQUFDO0FBQy9DLE9BQU8sRUFDTCxxQkFBcUIsRUFDckIsa0JBQWtCLEVBQ25CLE1BQU0sOENBQThDLENBQUM7QUFDdEQsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUNwQyxPQUFPLEVBQUUsZUFBZSxFQUFFLGFBQWEsRUFBYyxJQUFJLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDeEUsT0FBTyxFQUFFLEdBQUcsRUFBRSxXQUFXLEVBQUUsU0FBUyxFQUFFLEdBQUcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ2xFLE9BQU8sRUFBRSwyQkFBMkIsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBQy9FLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLDJCQUEyQixDQUFDOzs7Ozs7O0FBZWxFLE1BQU0sT0FBTyx1QkFBdUI7SUEyQ2xD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aTlIQXVJQSwyQ0RyR1ksVUFBVSxncUVBQUUsa0JBQWtCLDZMQUFFLDJCQUEyQjs7NEZBUzFELHVCQUF1QjtrQkFibkMsU0FBUzsrQkFDRSxxQkFBcUIsY0FDbkIsSUFBSSxXQUVQLENBQUMsVUFBVSxFQUFFLGtCQUFrQixFQUFFLDJCQUEyQixDQUFDLGFBQzNEO3dCQUNULHdCQUF3Qjt3QkFDeEI7NEJBQ0UsT0FBTyxFQUFFLCtCQUErQjs0QkFDeEMsV0FBVyxFQUFFLFVBQVUsQ0FBQyxHQUFHLEVBQUUsd0JBQXdCLENBQUM7eUJBQ3ZEO3FCQUNGOzhKQWM0QyxZQUFZO3NCQUF4RCxTQUFTO3VCQUFDLGNBQWMsRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIGZvcndhcmRSZWYsIGlucHV0LCBWaWV3Q2hpbGQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEFjdGl2YXRlZFJvdXRlIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7IElPcGVyYXRpb24sIElSZXN1bHRMaXN0IH0gZnJvbSAnQGM4eS9jbGllbnQnO1xuaW1wb3J0IHtcbiAgQ29yZU1vZHVsZSxcbiAgZ2V0dGV4dCxcbiAgT3BlcmF0aW9uUmVhbHRpbWVTZXJ2aWNlLFxuICBQUk9EVUNUX0VYUEVSSUVOQ0VfRVZFTlRfU09VUkNFLFxuICBQcm9kdWN0RXhwZXJpZW5jZUV2ZW50LFxuICBQcm9kdWN0RXhwZXJpZW5jZUV2ZW50U291cmNlXG59IGZyb20gJ0BjOHkvbmd4LWNvbXBvbmVudHMnO1xuaW1wb3J0IHtcbiAgU0lOR0xFX09QRVJBVElPTl9FVkVOVF9ERVZJQ0VfVEFCLFxuICBTSU5HTEVfT1BFUkFUSU9OX0VWRU5UX09WRVJWSUVXXG59IGZyb20gJ0BjOHkvbmd4LWNvbXBvbmVudHMvb3BlcmF0aW9ucy9wcm9kdWN0LWV4cGVyaWVuY2UnO1xuaW1wb3J0IHtcbiAgT1BFUkFUSU9OX1NUQVRVU19PUFRJT05TX01BUCxcbiAgT3BlcmF0aW9uU3RhdHVzT3B0aW9uLFxuICBPcGVyYXRpb25TdGF0dXNPcHRpb25zTWFwU2hhcmVkXG59IGZyb20gJ0BjOHkvbmd4LWNvbXBvbmVudHMvb3BlcmF0aW9ucy9zaGFyZWQnO1xuaW1wb3J0IHtcbiAgU3RhdHVzRmlsdGVyQ29tcG9uZW50LFxuICBTdGF0dXNGaWx0ZXJNb2R1bGVcbn0gZnJvbSAnQGM4eS9uZ3gtY29tcG9uZW50cy9vcGVyYXRpb25zL3N0YXR1cy1maWx0ZXInO1xuaW1wb3J0IHsgZmxhdHRlbiB9IGZyb20gJ2xvZGFzaC1lcyc7XG5pbXBvcnQgeyBCZWhhdmlvclN1YmplY3QsIGNvbWJpbmVMYXRlc3QsIE9ic2VydmFibGUsIHBpcGUgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IG1hcCwgc2hhcmVSZXBsYXksIHN3aXRjaE1hcCwgdGFwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgT3BlcmF0aW9uc0xpc3RJdGVtQ29tcG9uZW50IH0gZnJvbSAnLi9vcGVyYXRpb25zLWxpc3QtaXRlbS5jb21wb25lbnQnO1xuaW1wb3J0IHsgT3BlcmF0aW9uc0xpc3RTZXJ2aWNlIH0gZnJvbSAnLi9vcGVyYXRpb25zLWxpc3Quc2VydmljZSc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2M4eS1vcGVyYXRpb25zLWxpc3QnLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICB0ZW1wbGF0ZVVybDogJ29wZXJhdGlvbnMtbGlzdC5jb21wb25lbnQuaHRtbCcsXG4gIGltcG9ydHM6IFtDb3JlTW9kdWxlLCBTdGF0dXNGaWx0ZXJNb2R1bGUsIE9wZXJhdGlvbnNMaXN0SXRlbUNvbXBvbmVudF0sXG4gIHByb3ZpZGVyczogW1xuICAgIE9wZXJhdGlvblJlYWx0aW1lU2VydmljZSxcbiAgICB7XG4gICAgICBwcm92aWRlOiBQUk9EVUNUX0VYUEVSSUVOQ0VfRVZFTlRfU09VUkNFLFxuICAgICAgdXNlRXhpc3Rpbmc6IGZvcndhcmRSZWYoKCkgPT4gT3BlcmF0aW9uc0xpc3RDb21wb25lbnQpXG4gICAgfVxuICBdXG59KVxuZXhwb3J0IGNsYXNzIE9wZXJhdGlvbnNMaXN0Q29tcG9uZW50IGltcGxlbWVudHMgUHJvZHVjdEV4cGVyaWVuY2VFdmVudFNvdXJjZSB7XG4gIGZyYWdtZW50VHlwZSA9IGlucHV0PHN0cmluZz4oKTtcbiAgcmVhZE9ubHlJdGVtcyA9IGlucHV0KGZhbHNlKTtcbiAgZGV2aWNlSWQ6IHN0cmluZyB8IG51bWJlciA9IHRoaXMucm91dGUuc25hcHNob3QucGFyZW50LmRhdGEuY29udGV4dERhdGE/LmlkO1xuICBPUEVSQVRJT05fU1RBVFVTX09QVElPTlNfTUFQOiBPcGVyYXRpb25TdGF0dXNPcHRpb25zTWFwU2hhcmVkID0gT1BFUkFUSU9OX1NUQVRVU19PUFRJT05TX01BUDtcblxuICB0aXRsZTogc3RyaW5nO1xuICByZWZyZXNoTG9hZGluZyA9IGZhbHNlO1xuICBpc1NtYXJ0UnVsZXNNaWNyb3NlcnZpY2VBdmFpbGFibGUgPSBmYWxzZTtcbiAgc2hvd092ZXJ2aWV3QnJlYWRjcnVtYnMgPSBmYWxzZTtcbiAgc3RhdHVzRmlsdGVyJDogQmVoYXZpb3JTdWJqZWN0PE9wZXJhdGlvblN0YXR1c09wdGlvbltdPiA9IG5ldyBCZWhhdmlvclN1YmplY3QobnVsbCk7XG4gIHJlbG9hZCQ6IEJlaGF2aW9yU3ViamVjdDx2b2lkPiA9IG5ldyBCZWhhdmlvclN1YmplY3QobnVsbCk7XG4gIEBWaWV3Q2hpbGQoJ3N0YXR1c0ZpbHRlcicsIHsgc3RhdGljOiB0cnVlIH0pIHN0YXR1c0ZpbHRlcjogU3RhdHVzRmlsdGVyQ29tcG9uZW50O1xuXG4gIG9wZXJhdGlvbnMkOiBPYnNlcnZhYmxlPElSZXN1bHRMaXN0PElPcGVyYXRpb24+PiA9IGNvbWJpbmVMYXRlc3QoXG4gICAgdGhpcy5zdGF0dXNGaWx0ZXIkLFxuICAgIHRoaXMucmVsb2FkJFxuICApLnBpcGUoXG4gICAgdGFwKCgpID0+IHtcbiAgICAgIHRoaXMucmVmcmVzaExvYWRpbmcgPSB0cnVlO1xuICAgIH0pLFxuICAgIHN3aXRjaE1hcCgoW3N0YXR1c0ZpbHRlcnNdKSA9PiB0aGlzLmZpbHRlcihzdGF0dXNGaWx0ZXJzKSksXG4gICAgdGFwKCgpID0+IHtcbiAgICAgIHRoaXMucmVmcmVzaExvYWRpbmcgPSBmYWxzZTtcbiAgICB9KSxcbiAgICBzaGFyZVJlcGxheSgxKVxuICApO1xuXG4gIG9wZXJhdGlvbnNGaWx0ZXJQaXBlID0gcGlwZShcbiAgICBtYXAoKG9wZXJhdGlvbnM6IElPcGVyYXRpb25bXSkgPT4ge1xuICAgICAgY29uc3Qgc3RhdHVzRmlsdGVycyA9IHRoaXMuc3RhdHVzRmlsdGVyJC5nZXRWYWx1ZSgpO1xuICAgICAgaWYgKCFzdGF0dXNGaWx0ZXJzIHx8ICFzdGF0dXNGaWx0ZXJzLmxlbmd0aCkge1xuICAgICAgICByZXR1cm4gb3BlcmF0aW9ucztcbiAgICAgIH1cbiAgICAgIGNvbnN0IGFsbG93ZWRTdGF0dXNlcyA9IGZsYXR0ZW4oc3RhdHVzRmlsdGVycy5tYXAoc2YgPT4gc2Yuc3RhdHVzKSk7XG4gICAgICByZXR1cm4gb3BlcmF0aW9ucy5maWx0ZXIob3AgPT4gYWxsb3dlZFN0YXR1c2VzLmluY2x1ZGVzKG9wLnN0YXR1cykpO1xuICAgIH0pXG4gICk7XG5cbiAgcHJvZHVjdEV4cGVyaWVuY2VFdmVudDogUHJvZHVjdEV4cGVyaWVuY2VFdmVudCA9IHtcbiAgICBldmVudE5hbWU6ICEhdGhpcy5kZXZpY2VJZCA/IFNJTkdMRV9PUEVSQVRJT05fRVZFTlRfREVWSUNFX1RBQiA6IFNJTkdMRV9PUEVSQVRJT05fRVZFTlRfT1ZFUlZJRVdcbiAgfTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwdWJsaWMgcmVhbHRpbWU6IE9wZXJhdGlvblJlYWx0aW1lU2VydmljZSxcbiAgICBwcml2YXRlIG9wZXJhdGlvbnNMaXN0U2VydmljZTogT3BlcmF0aW9uc0xpc3RTZXJ2aWNlLFxuICAgIHByaXZhdGUgcm91dGU6IEFjdGl2YXRlZFJvdXRlXG4gICkge1xuICAgIHRoaXMudGl0bGUgPSB0aGlzLnJvdXRlLnNuYXBzaG90LnBhcmVudC5kYXRhLmNvbnRleHREYXRhXG4gICAgICA/IHRoaXMucm91dGUuc25hcHNob3QucGFyZW50LmRhdGEuY29udGV4dERhdGEubmFtZVxuICAgICAgOiBnZXR0ZXh0KCdTaW5nbGUgb3BlcmF0aW9ucycpO1xuICAgIHRoaXMuc2hvd092ZXJ2aWV3QnJlYWRjcnVtYnMgPSAhdGhpcy5kZXZpY2VJZDtcbiAgfVxuXG4gIGFzeW5jIG5nT25Jbml0KCkge1xuICAgIHRoaXMuaXNTbWFydFJ1bGVzTWljcm9zZXJ2aWNlQXZhaWxhYmxlID1cbiAgICAgIGF3YWl0IHRoaXMub3BlcmF0aW9uc0xpc3RTZXJ2aWNlLmlzU21hcnRSdWxlc01pY3Jvc2VydmljZUF2YWlsYWJsZSgpO1xuICB9XG5cbiAgZmlsdGVyKHN0YXR1c0ZpbHRlcnM6IE9wZXJhdGlvblN0YXR1c09wdGlvbltdKSB7XG4gICAgY29uc3Qgc3RhdHVzID1cbiAgICAgIHN0YXR1c0ZpbHRlcnMgJiYgc3RhdHVzRmlsdGVycy5sZW5ndGggPiAwXG4gICAgICAgID8ge1xuICAgICAgICAgICAgc3RhdHVzOiBmbGF0dGVuKHN0YXR1c0ZpbHRlcnMubWFwKHN0YXR1c0ZpbHRlciA9PiBzdGF0dXNGaWx0ZXIuc3RhdHVzKSlcbiAgICAgICAgICB9XG4gICAgICAgIDoge307XG5cbiAgICByZXR1cm4gdGhpcy5nZXRPcGVyYXRpb25zKHN0YXR1cyk7XG4gIH1cblxuICBnZXRPcGVyYXRpb25zKGZpbHRlcj8pIHtcbiAgICBsZXQgcXVlcnlGaWx0ZXIgPSB0aGlzLmRldmljZUlkID8geyAuLi5maWx0ZXIsIGRldmljZUlkOiB0aGlzLmRldmljZUlkIH0gOiBmaWx0ZXI7XG4gICAgaWYgKHRoaXMuZnJhZ21lbnRUeXBlKCkpIHtcbiAgICAgIHF1ZXJ5RmlsdGVyID0geyAuLi5xdWVyeUZpbHRlciwgZnJhZ21lbnRUeXBlOiB0aGlzLmZyYWdtZW50VHlwZSgpIH07XG4gICAgfVxuICAgIHJldHVybiB0aGlzLm9wZXJhdGlvbnNMaXN0U2VydmljZS5nZXRPcGVyYXRpb25zKHF1ZXJ5RmlsdGVyKTtcbiAgfVxuXG4gIGNvbXBhcmVPcGVyYXRpb25zKG9wZXJhdGlvbkE6IElPcGVyYXRpb24sIG9wZXJhdGlvbkI6IElPcGVyYXRpb24pOiBudW1iZXIge1xuICAgIHJldHVybiAoXG4gICAgICBuZXcgRGF0ZShvcGVyYXRpb25BLmNyZWF0aW9uVGltZSkuZ2V0VGltZSgpIC0gbmV3IERhdGUob3BlcmF0aW9uQi5jcmVhdGlvblRpbWUpLmdldFRpbWUoKVxuICAgICk7XG4gIH1cbn1cbiIsIjxjOHktdGl0bGU+e3sgdGl0bGUgfCB0cmFuc2xhdGUgfX08L2M4eS10aXRsZT5cblxuPGM4eS1icmVhZGNydW1iICpuZ0lmPVwic2hvd092ZXJ2aWV3QnJlYWRjcnVtYnNcIj5cbiAgPGM4eS1icmVhZGNydW1iLWl0ZW1cbiAgICBbaWNvbl09XCInYzh5LW92ZXJ2aWV3cydcIlxuICAgIFtsYWJlbF09XCInT3ZlcnZpZXdzJyB8IHRyYW5zbGF0ZVwiXG4gID48L2M4eS1icmVhZGNydW1iLWl0ZW0+XG4gIDxjOHktYnJlYWRjcnVtYi1pdGVtXG4gICAgW2ljb25dPVwiJ2M4eS1kZXZpY2UtY29udHJvbCdcIlxuICAgIFtsYWJlbF09XCInRGV2aWNlIENvbnRyb2wnIHwgdHJhbnNsYXRlXCJcbiAgICBbcGF0aF09XCInZGV2aWNlY29udHJvbC9zaW5nbGUnXCJcbiAgPjwvYzh5LWJyZWFkY3J1bWItaXRlbT5cbiAgPGM4eS1icmVhZGNydW1iLWl0ZW1cbiAgICBbaWNvbl09XCInYzh5LWRldmljZS1jb250cm9sJ1wiXG4gICAgW2xhYmVsXT1cIidTaW5nbGUgb3BlcmF0aW9ucycgfCB0cmFuc2xhdGVcIlxuICA+PC9jOHktYnJlYWRjcnVtYi1pdGVtPlxuPC9jOHktYnJlYWRjcnVtYj5cblxuPGM4eS1hY3Rpb24tYmFyLWl0ZW1cbiAgW3BsYWNlbWVudF09XCInbGVmdCdcIlxuICBpdGVtQ2xhc3M9XCJuYXZiYXItZm9ybVwiXG4+XG4gIDxjOHktc3RhdHVzLWZpbHRlclxuICAgICNzdGF0dXNGaWx0ZXJcbiAgICBbb3B0aW9uc109XCJPUEVSQVRJT05fU1RBVFVTX09QVElPTlNfTUFQXCJcbiAgICAob25GaWx0ZXJDaGFuZ2VkKT1cInN0YXR1c0ZpbHRlciQubmV4dCgkZXZlbnQpXCJcbiAgICBjOHlQcm9kdWN0RXhwZXJpZW5jZVxuICAgIGluaGVyaXRcbiAgPjwvYzh5LXN0YXR1cy1maWx0ZXI+XG48L2M4eS1hY3Rpb24tYmFyLWl0ZW0+XG5cbjxjOHktYWN0aW9uLWJhci1pdGVtIFtwbGFjZW1lbnRdPVwiJ3JpZ2h0J1wiPlxuICA8Yzh5LXJlYWx0aW1lLWJ0biBbc2VydmljZV09XCJyZWFsdGltZVwiPjwvYzh5LXJlYWx0aW1lLWJ0bj5cbjwvYzh5LWFjdGlvbi1iYXItaXRlbT5cblxuPGM4eS1hY3Rpb24tYmFyLWl0ZW0gW3BsYWNlbWVudF09XCIncmlnaHQnXCI+XG4gIDxidXR0b25cbiAgICBjbGFzcz1cImJ0biBidG4tbGluayBkLWZsZXggYS1pLWNlbnRlclwiXG4gICAgdGl0bGU9XCJ7eyAnUmVsb2FkJyB8IHRyYW5zbGF0ZSB9fVwiXG4gICAgKGNsaWNrKT1cInJlbG9hZCQubmV4dCgpXCJcbiAgPlxuICAgIDxpXG4gICAgICBjbGFzcz1cIm0tci00XCJcbiAgICAgIGM4eUljb249XCJyZWZyZXNoXCJcbiAgICAgIFtuZ0NsYXNzXT1cInsgJ2ljb24tc3Bpbic6IHJlZnJlc2hMb2FkaW5nIH1cIlxuICAgID48L2k+XG4gICAgPHNwYW4gY2xhc3M9XCJ0ZXh0LXRydW5jYXRlXCI+XG4gICAgICB7eyAnUmVsb2FkJyB8IHRyYW5zbGF0ZSB9fVxuICAgIDwvc3Bhbj5cbiAgPC9idXR0b24+XG48L2M4eS1hY3Rpb24tYmFyLWl0ZW0+XG5cbjxuZy1jb250ZW50IHNlbGVjdD1cImM4eS1oZWxwXCI+XG4gIDxjOHktaGVscFxuICAgIHNyYz1cIi9kb2NzL2RldmljZS1tYW5hZ2VtZW50LWFwcGxpY2F0aW9uL21vbml0b3JpbmctYW5kLWNvbnRyb2xsaW5nLWRldmljZXMvI3RvLXZpZXctc2luZ2xlLW9wZXJhdGlvbnNcIlxuICA+PC9jOHktaGVscD5cbjwvbmctY29udGVudD5cblxuPCEtLSBFbXB0eSBzdGF0ZSAgLS0+XG48Yzh5LXVpLWVtcHR5LXN0YXRlXG4gIFtpY29uXT1cIidjOHktZW5lcmd5J1wiXG4gIFt0aXRsZV09XCInTm8gaXRlbXMgdG8gZGlzcGxheS4nIHwgdHJhbnNsYXRlXCJcbiAgW3N1YnRpdGxlXT1cIidPcGVyYXRpb25zIHdpbGwgYmUgZGlzcGxheWVkIGhlcmUuJyB8IHRyYW5zbGF0ZVwiXG4gICpuZ0lmPVwiKG9wZXJhdGlvbnMkIHwgYXN5bmMpPy5kYXRhLmxlbmd0aCA9PT0gMCAmJiAhKHN0YXR1c0ZpbHRlciQgfCBhc3luYylcIlxuPjwvYzh5LXVpLWVtcHR5LXN0YXRlPlxuPCEtLSBObyByZXN1bHRzIGVtcHR5IHN0YXRlIC0tPlxuPGM4eS11aS1lbXB0eS1zdGF0ZVxuICBbaWNvbl09XCInc2VhcmNoJ1wiXG4gIFt0aXRsZV09XCInTm8gcmVzdWx0cyB0byBkaXNwbGF5LicgfCB0cmFuc2xhdGVcIlxuICBbc3VidGl0bGVdPVwiJ0FkanVzdCBvciByZXNldCB0aGUgZmlsdGVyLicgfCB0cmFuc2xhdGVcIlxuICAqbmdJZj1cIihvcGVyYXRpb25zJCB8IGFzeW5jKT8uZGF0YS5sZW5ndGggPT09IDAgJiYgKHN0YXR1c0ZpbHRlciQgfCBhc3luYylcIlxuPlxuICA8YnV0dG9uXG4gICAgY2xhc3M9XCJidG4gYnRuLXByaW1hcnlcIlxuICAgIHRpdGxlPVwie3sgJ1Jlc2V0IGZpbHRlcicgfCB0cmFuc2xhdGUgfX1cIlxuICAgIHR5cGU9XCJidXR0b25cIlxuICAgIChjbGljayk9XCJzdGF0dXNGaWx0ZXIucmVzZXQoKVwiXG4gICAgdHJhbnNsYXRlXG4gID5cbiAgICBSZXNldCBmaWx0ZXJcbiAgPC9idXR0b24+XG48L2M4eS11aS1lbXB0eS1zdGF0ZT5cblxuPCEtLSBEZXRhaWxlZCBsaXN0IG9mIG9wZXJhdGlvbnMgKyBsb2FkIG1vcmUgYnV0dG9uIC0tPlxuPGM4eS1saXN0LWdyb3VwIGNsYXNzPVwibS1iLTI0XCI+XG4gIDxkaXZcbiAgICBjbGFzcz1cInBhZ2Utc3RpY2t5LWhlYWRlciBjOHktbGlzdF9faXRlbSBjOHktbGlzdF9faXRlbS0tZG91YmxlLWFjdGlvbnMgaGlkZGVuLXhzXCJcbiAgICAqbmdJZj1cIihvcGVyYXRpb25zJCB8IGFzeW5jKT8uZGF0YS5sZW5ndGhcIlxuICA+XG4gICAgPGRpdiBjbGFzcz1cImM4eS1saXN0X19pdGVtX19ibG9ja1wiPlxuICAgICAgPGRpdiBjbGFzcz1cImM4eS1saXN0X19pdGVtX19pY29uXCI+XG4gICAgICAgIDxpIGNsYXNzPVwicC1sLTI0XCI+PC9pPlxuICAgICAgPC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwiYzh5LWxpc3RfX2l0ZW1fX2JvZHkgdGV4dC10cnVuY2F0ZS13cmFwXCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJjb250ZW50LWZsZXgtNTdcIj5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiY29sLTVcIj5cbiAgICAgICAgICAgIHt7ICdPcGVyYXRpb24nIHwgdHJhbnNsYXRlIH19XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPGRpdlxuICAgICAgICAgICAgY2xhc3M9XCJmbGV4LWdyb3dcIlxuICAgICAgICAgICAgKm5nSWY9XCIhZGV2aWNlSWRcIlxuICAgICAgICAgID5cbiAgICAgICAgICAgIHt7ICdEZXZpY2UnIHwgdHJhbnNsYXRlIH19XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImNvbC00XCI+XG4gICAgICAgICAgICB7eyAnRGF0ZSBjcmVhdGVkJyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cImM4eS1saXN0X19pdGVtX19hY3Rpb25zXCI+PC9kaXY+XG4gICAgPC9kaXY+XG4gIDwvZGl2PlxuICA8ZGl2XG4gICAgY2xhc3M9XCJkLWNvbnRlbnRzXCJcbiAgICAqYzh5Rm9yPVwiXG4gICAgICBsZXQgb3Agb2Ygb3BlcmF0aW9ucyQgfCBhc3luYztcbiAgICAgIGxldCBpID0gaW5kZXg7XG4gICAgICByZWFsdGltZTogcmVhbHRpbWU7XG4gICAgICByZWFsdGltZU9wdGlvbnM6IHsgZW50aXR5T3JJZDogZGV2aWNlSWQsIHJlbW92ZU9uVXBkYXRlOiB0cnVlLCBpbnNlcnRPblVwZGF0ZTogdHJ1ZSB9O1xuICAgICAgY29tcGFyYXRvcjogY29tcGFyZU9wZXJhdGlvbnMuYmluZCh0aGlzKTtcbiAgICAgIGxvYWRNb3JlOiAnYXV0byc7XG4gICAgICBwaXBlOiBvcGVyYXRpb25zRmlsdGVyUGlwZVxuICAgIFwiXG4gID5cbiAgICA8Yzh5LW9wZXJhdGlvbnMtbGlzdC1pdGVtXG4gICAgICBjbGFzcz1cImQtY29udGVudHNcIlxuICAgICAgW29wZXJhdGlvbl09XCJvcFwiXG4gICAgICBbcmVhZE9ubHldPVwicmVhZE9ubHlJdGVtcygpXCJcbiAgICAgIFtpc1NtYXJ0UnVsZXNNaWNyb3NlcnZpY2VBdmFpbGFibGVdPVwiaXNTbWFydFJ1bGVzTWljcm9zZXJ2aWNlQXZhaWxhYmxlXCJcbiAgICAgIChyZWxvYWQpPVwicmVsb2FkJC5uZXh0KClcIlxuICAgICAgYzh5UHJvZHVjdEV4cGVyaWVuY2VcbiAgICAgIGluaGVyaXRcbiAgICA+PC9jOHktb3BlcmF0aW9ucy1saXN0LWl0ZW0+XG4gIDwvZGl2PlxuPC9jOHktbGlzdC1ncm91cD5cbiJdfQ==