@c8y/ngx-components
Version:
Angular modules for Cumulocity IoT applications
135 lines • 35.8 kB
JavaScript
import { Component, ContentChildren, EventEmitter, Input, Output, QueryList, ViewChild } from '@angular/core';
import { AlertService, C8yStepper, gettext, ModalService, Status } from '@c8y/ngx-components';
import { BulkOperationsService } from '@c8y/ngx-components/operations/bulk-operations-service';
import { CreateBulkOperationDetailsComponent } from '@c8y/ngx-components/operations/create-bulk-operation-details';
import { BULK_OPERATION_EVENT } from '@c8y/ngx-components/operations/product-experience';
import { get } from 'lodash-es';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { CustomStep } from './custom-step.directive';
import * as i0 from "@angular/core";
import * as i1 from "@c8y/ngx-components/operations/bulk-operations-service";
import * as i2 from "@c8y/ngx-components";
import * as i3 from "@angular/common";
import * as i4 from "@angular/cdk/stepper";
import * as i5 from "@c8y/ngx-components/operations/device-selector";
import * as i6 from "@c8y/ngx-components/operations/create-bulk-operation-details";
import * as i7 from "@c8y/ngx-components/operations/operation-summary";
export class BulkOperationStepper {
constructor(bulkOperationService, modal, alert) {
this.bulkOperationService = bulkOperationService;
this.modal = modal;
this.alert = alert;
this.BULK_OPERATION_EVENT = BULK_OPERATION_EVENT;
this.selectionChange = new EventEmitter();
this.steps = [];
this.showStepper = false;
this.showButtons = false;
this.stepperButtonsLabels = { custom: gettext('Schedule') };
this.deviceTypesSubject$ = new Subject();
this.endSubscriptions = new Subject();
this.deviceTypes$ = this.deviceTypesSubject$.asObservable();
}
ngAfterViewInit() {
setTimeout(() => {
// wait for the next event loop turn as `steps` has already been checked in this CD cycle
this.steps = this.customSteps.toArray();
this.showStepper = true;
setTimeout(() => {
// postpone rendering of buttons for custom steps to the point where custom steps have already been rendered
this.showButtons = true;
if (this.stepper) {
this.stepper.selectionChange.pipe(takeUntil(this.endSubscriptions)).subscribe(event => {
this.selectionChange.next(event);
});
this.operationDetailsForm =
this.createBulkOperationDetailsComponent.fgOperationDescription;
}
});
});
}
changeDeviceTypes(deviceTypes) {
if (deviceTypes) {
this.deviceTypesSubject$.next(Array.isArray(deviceTypes) ? deviceTypes : [deviceTypes]);
}
else {
this.deviceTypesSubject$.next([]);
}
}
async confirmDeviceSelection($event) {
if (!this.deviceQueryString) {
try {
await this.modal.confirm(gettext('All devices selected'), gettext('You are about to schedule the bulk operation to be executed for all devices. Do you want to proceed?'), Status.WARNING, { ok: gettext('Schedule for all devices'), cancel: gettext('Cancel and select devices') });
$event.step.completed = true;
$event.stepper.next();
this.operationDetails = this.retrieveOperationDetails
? await this.retrieveOperationDetails()
: undefined;
}
catch (ex) {
// Intentionally empty
}
}
else {
$event.step.completed = true;
$event.stepper.next();
this.operationDetails = this.retrieveOperationDetails
? await this.retrieveOperationDetails()
: undefined;
}
this.bulkOperationType = this.bulkOperationService.retrieveBulkOperationType(get(this.operationDetails, 'prototype'));
if (this.operationDetailsForm &&
get(this.operationDetailsForm, 'controls.description.pristine') &&
this.operationDetails) {
this.operationDetailsForm.patchValue({
description: get(this.operationDetails, 'prototype.description')
});
}
}
cancel() {
this.close();
}
async scheduleBulkOperation() {
this.pendingStatus = true;
try {
this.operationDetails.prototype.description = get(this.operationDetailsForm, 'controls.description.value');
this.operationDetails.note = get(this.operationDetailsForm, 'controls.note.value');
this.operationDetails.schedule = get(this.operationDetailsForm, 'controls.schedule.value');
await this.bulkOperationService.scheduleBulkOperation(this.deviceQueryString, this.operationDetails);
this.alert.success(gettext('New bulk operation scheduled.'));
this.close();
}
catch (ex) {
this.alert.addServerFailure(ex);
}
this.pendingStatus = false;
}
ngOnDestroy() {
this.endSubscriptions.next();
this.endSubscriptions.complete();
}
close() {
this.stepper.reset();
this.bulkOperationService.returnToBulkOperationOverview();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: BulkOperationStepper, deps: [{ token: i1.BulkOperationsService }, { token: i2.ModalService }, { token: i2.AlertService }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: BulkOperationStepper, selector: "c8y-bulk-operation-stepper", inputs: { type: "type" }, outputs: { selectionChange: "selectionChange" }, queries: [{ propertyName: "customSteps", predicate: CustomStep }], viewQueries: [{ propertyName: "stepper", first: true, predicate: C8yStepper, descendants: true }, { propertyName: "createBulkOperationDetailsComponent", first: true, predicate: CreateBulkOperationDetailsComponent, descendants: true }], ngImport: i0, template: "<div class=\"fit-h\">\n <c8y-stepper\n class=\"d-col no-align-items fit-h c8y-stepper--no-btns a-i-center\"\n linear\n [disableDefaultIcons]=\"{ edit: true, done: false }\"\n [customClasses]=\"['col-xs-10', 'col-sm-8', 'm-t-24', 'm-b-40', 'p-0', 'flex-no-shrink']\"\n *ngIf=\"showStepper\"\n c8yProductExperience\n [actionName]=\"BULK_OPERATION_EVENT\"\n [actionData]=\"{ bulkOperationType: type }\"\n >\n <!-- CUSTOM STEPS 1 to N-2 -->\n <cdk-step\n *ngFor=\"let step of steps\"\n [label]=\"step.label | translate\"\n [completed]=\"step.completed\"\n >\n <ng-container *ngTemplateOutlet=\"step.templateRef\"></ng-container>\n <c8y-stepper-buttons\n class=\"d-block card-footer p-24 separator fit-w sticky-bottom bg-level-0\"\n *ngIf=\"showButtons\"\n [disabled]=\"step.buttonsDisabled\"\n (onNext)=\"step.onNext($event)\"\n (onCancel)=\"cancel()\"\n ></c8y-stepper-buttons>\n </cdk-step>\n <!-- STEP N-1 - Data-grid -->\n <cdk-step [label]=\"'Filter target devices' | translate\">\n <div class=\"card-block p-b-0 p-t-0 flex-no-shrink separator-bottom col-xs-12\">\n <div class=\"d-flex j-c-center p-b-8 p-t-4\">\n <div class=\"col-xs-12 col-sm-6\">\n <h4 class=\"text-center text-normal m-b-16\">\n {{ 'Filter target devices' | translate }}\n </h4>\n </div>\n </div>\n </div>\n\n <div class=\"col-xs-12 flex-grow no-gutter\">\n <c8y-device-selector\n [deviceTypes]=\"deviceTypes$\"\n (onDeviceQueryStringChange)=\"deviceQueryString = $event\"\n ></c8y-device-selector>\n </div>\n <c8y-stepper-buttons\n class=\"d-block card-footer p-24 separator fit-w sticky-bottom bg-level-0\"\n *ngIf=\"showButtons\"\n (onNext)=\"confirmDeviceSelection($event)\"\n (onCancel)=\"cancel()\"\n ></c8y-stepper-buttons>\n </cdk-step>\n\n <!-- STEP N - Scheduler -->\n <cdk-step [label]=\"'Confirm and schedule bulk operation' | translate\">\n <div class=\"card-block flex-no-shrink p-b-0 p-t-0 separator-bottom col-xs-12\">\n <div class=\"d-flex j-c-center p-b-8 p-t-4\">\n <div class=\"col-xs-12 col-sm-6\">\n <h4 class=\"text-center text-normal m-b-16\">\n {{ 'Confirm and schedule bulk operation' | translate }}\n </h4>\n </div>\n </div>\n </div>\n\n <div class=\"col-xs-12 flex-grow no-gutter\">\n <div class=\"card-inner-scroll fit-h\">\n <div class=\"card-block p-b-0\">\n <div class=\"d-flex j-c-center p-t-8 p-b-8\">\n <div class=\"col-xs-12 col-sm-6\">\n <c8y-operation-summary\n [name]=\"operationDetails?.name | translate\"\n [description]=\"operationDetails?.description | translate\"\n [deviceQueryString]=\"deviceQueryString\"\n ></c8y-operation-summary>\n </div>\n </div>\n <div class=\"d-flex j-c-center\">\n <div class=\"col-xs-12 col-sm-6\">\n <c8y-create-bulk-operation-details\n [bulkOperationType]=\"bulkOperationType\"\n ></c8y-create-bulk-operation-details>\n </div>\n </div>\n </div>\n </div>\n </div>\n <c8y-stepper-buttons\n class=\"d-block card-footer p-24 separator fit-w sticky-bottom bg-level-0\"\n *ngIf=\"showButtons\"\n [labels]=\"stepperButtonsLabels\"\n [pending]=\"pendingStatus\"\n [disabled]=\"operationDetailsForm?.invalid\"\n (onCancel)=\"cancel()\"\n (onCustom)=\"scheduleBulkOperation()\"\n ></c8y-stepper-buttons>\n </cdk-step>\n </c8y-stepper>\n</div>\n", dependencies: [{ kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i2.C8yStepper, selector: "c8y-stepper", inputs: ["disableDefaultIcons", "disableProgressButtons", "customClasses", "hideStepProgress", "useStepLabelsAsTitlesOnly"], outputs: ["onStepChange"] }, { kind: "component", type: i4.CdkStep, selector: "cdk-step", inputs: ["stepControl", "label", "errorMessage", "aria-label", "aria-labelledby", "state", "editable", "optional", "completed", "hasError"], outputs: ["interacted"], exportAs: ["cdkStep"] }, { kind: "component", type: i2.C8yStepperButtons, selector: "c8y-stepper-buttons", inputs: ["labels", "pending", "disabled", "showButtons"], outputs: ["onCancel", "onNext", "onBack", "onCustom"] }, { kind: "directive", type: i2.ProductExperienceDirective, selector: "[c8yProductExperience]", inputs: ["actionName", "actionData", "inherit", "suppressDataOverriding"] }, { kind: "component", type: i5.DeviceSelectorComponent, selector: "c8y-device-selector", inputs: ["deviceTypes"], outputs: ["onDeviceQueryStringChange"] }, { kind: "component", type: i6.CreateBulkOperationDetailsComponent, selector: "c8y-create-bulk-operation-details", inputs: ["bulkOperationType"] }, { kind: "component", type: i7.OperationSummaryComponent, selector: "c8y-operation-summary", inputs: ["name", "description", "deviceQueryString"] }, { kind: "pipe", type: i2.C8yTranslatePipe, name: "translate" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: BulkOperationStepper, decorators: [{
type: Component,
args: [{ selector: 'c8y-bulk-operation-stepper', template: "<div class=\"fit-h\">\n <c8y-stepper\n class=\"d-col no-align-items fit-h c8y-stepper--no-btns a-i-center\"\n linear\n [disableDefaultIcons]=\"{ edit: true, done: false }\"\n [customClasses]=\"['col-xs-10', 'col-sm-8', 'm-t-24', 'm-b-40', 'p-0', 'flex-no-shrink']\"\n *ngIf=\"showStepper\"\n c8yProductExperience\n [actionName]=\"BULK_OPERATION_EVENT\"\n [actionData]=\"{ bulkOperationType: type }\"\n >\n <!-- CUSTOM STEPS 1 to N-2 -->\n <cdk-step\n *ngFor=\"let step of steps\"\n [label]=\"step.label | translate\"\n [completed]=\"step.completed\"\n >\n <ng-container *ngTemplateOutlet=\"step.templateRef\"></ng-container>\n <c8y-stepper-buttons\n class=\"d-block card-footer p-24 separator fit-w sticky-bottom bg-level-0\"\n *ngIf=\"showButtons\"\n [disabled]=\"step.buttonsDisabled\"\n (onNext)=\"step.onNext($event)\"\n (onCancel)=\"cancel()\"\n ></c8y-stepper-buttons>\n </cdk-step>\n <!-- STEP N-1 - Data-grid -->\n <cdk-step [label]=\"'Filter target devices' | translate\">\n <div class=\"card-block p-b-0 p-t-0 flex-no-shrink separator-bottom col-xs-12\">\n <div class=\"d-flex j-c-center p-b-8 p-t-4\">\n <div class=\"col-xs-12 col-sm-6\">\n <h4 class=\"text-center text-normal m-b-16\">\n {{ 'Filter target devices' | translate }}\n </h4>\n </div>\n </div>\n </div>\n\n <div class=\"col-xs-12 flex-grow no-gutter\">\n <c8y-device-selector\n [deviceTypes]=\"deviceTypes$\"\n (onDeviceQueryStringChange)=\"deviceQueryString = $event\"\n ></c8y-device-selector>\n </div>\n <c8y-stepper-buttons\n class=\"d-block card-footer p-24 separator fit-w sticky-bottom bg-level-0\"\n *ngIf=\"showButtons\"\n (onNext)=\"confirmDeviceSelection($event)\"\n (onCancel)=\"cancel()\"\n ></c8y-stepper-buttons>\n </cdk-step>\n\n <!-- STEP N - Scheduler -->\n <cdk-step [label]=\"'Confirm and schedule bulk operation' | translate\">\n <div class=\"card-block flex-no-shrink p-b-0 p-t-0 separator-bottom col-xs-12\">\n <div class=\"d-flex j-c-center p-b-8 p-t-4\">\n <div class=\"col-xs-12 col-sm-6\">\n <h4 class=\"text-center text-normal m-b-16\">\n {{ 'Confirm and schedule bulk operation' | translate }}\n </h4>\n </div>\n </div>\n </div>\n\n <div class=\"col-xs-12 flex-grow no-gutter\">\n <div class=\"card-inner-scroll fit-h\">\n <div class=\"card-block p-b-0\">\n <div class=\"d-flex j-c-center p-t-8 p-b-8\">\n <div class=\"col-xs-12 col-sm-6\">\n <c8y-operation-summary\n [name]=\"operationDetails?.name | translate\"\n [description]=\"operationDetails?.description | translate\"\n [deviceQueryString]=\"deviceQueryString\"\n ></c8y-operation-summary>\n </div>\n </div>\n <div class=\"d-flex j-c-center\">\n <div class=\"col-xs-12 col-sm-6\">\n <c8y-create-bulk-operation-details\n [bulkOperationType]=\"bulkOperationType\"\n ></c8y-create-bulk-operation-details>\n </div>\n </div>\n </div>\n </div>\n </div>\n <c8y-stepper-buttons\n class=\"d-block card-footer p-24 separator fit-w sticky-bottom bg-level-0\"\n *ngIf=\"showButtons\"\n [labels]=\"stepperButtonsLabels\"\n [pending]=\"pendingStatus\"\n [disabled]=\"operationDetailsForm?.invalid\"\n (onCancel)=\"cancel()\"\n (onCustom)=\"scheduleBulkOperation()\"\n ></c8y-stepper-buttons>\n </cdk-step>\n </c8y-stepper>\n</div>\n" }]
}], ctorParameters: () => [{ type: i1.BulkOperationsService }, { type: i2.ModalService }, { type: i2.AlertService }], propDecorators: { type: [{
type: Input
}], selectionChange: [{
type: Output
}], customSteps: [{
type: ContentChildren,
args: [CustomStep]
}], stepper: [{
type: ViewChild,
args: [C8yStepper, { static: false }]
}], createBulkOperationDetailsComponent: [{
type: ViewChild,
args: [CreateBulkOperationDetailsComponent, { static: false }]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnVsay1vcGVyYXRpb24tc3RlcHBlci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9vcGVyYXRpb25zL2J1bGstb3BlcmF0aW9uLXN0ZXBwZXIvYnVsay1vcGVyYXRpb24tc3RlcHBlci5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi9vcGVyYXRpb25zL2J1bGstb3BlcmF0aW9uLXN0ZXBwZXIvYnVsay1vcGVyYXRpb24tc3RlcHBlci5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQ0wsU0FBUyxFQUNULGVBQWUsRUFDZixZQUFZLEVBQ1osS0FBSyxFQUVMLE1BQU0sRUFDTixTQUFTLEVBQ1QsU0FBUyxFQUNWLE1BQU0sZUFBZSxDQUFDO0FBRXZCLE9BQU8sRUFBRSxZQUFZLEVBQUUsVUFBVSxFQUFFLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFFOUYsT0FBTyxFQUNMLHFCQUFxQixFQUd0QixNQUFNLHdEQUF3RCxDQUFDO0FBQ2hFLE9BQU8sRUFBRSxtQ0FBbUMsRUFBRSxNQUFNLDhEQUE4RCxDQUFDO0FBQ25ILE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLG1EQUFtRCxDQUFDO0FBQ3pGLE9BQU8sRUFBRSxHQUFHLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDaEMsT0FBTyxFQUFjLE9BQU8sRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUMzQyxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDM0MsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLHlCQUF5QixDQUFDOzs7Ozs7Ozs7QUFNckQsTUFBTSxPQUFPLG9CQUFvQjtJQTJCL0IsWUFDVSxvQkFBMkMsRUFDM0MsS0FBbUIsRUFDbkIsS0FBbUI7UUFGbkIseUJBQW9CLEdBQXBCLG9CQUFvQixDQUF1QjtRQUMzQyxVQUFLLEdBQUwsS0FBSyxDQUFjO1FB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O2dCQUd4QyxtQ0FBbUM7c0JBRGxDLFNBQVM7dUJBQUMsbUNBQW1DLEVBQUUsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ2RrU3RlcCwgU3RlcHBlclNlbGVjdGlvbkV2ZW50IH0gZnJvbSAnQGFuZ3VsYXIvY2RrL3N0ZXBwZXInO1xuaW1wb3J0IHtcbiAgQ29tcG9uZW50LFxuICBDb250ZW50Q2hpbGRyZW4sXG4gIEV2ZW50RW1pdHRlcixcbiAgSW5wdXQsXG4gIE9uRGVzdHJveSxcbiAgT3V0cHV0LFxuICBRdWVyeUxpc3QsXG4gIFZpZXdDaGlsZFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEZvcm1Hcm91cCB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IEFsZXJ0U2VydmljZSwgQzh5U3RlcHBlciwgZ2V0dGV4dCwgTW9kYWxTZXJ2aWNlLCBTdGF0dXMgfSBmcm9tICdAYzh5L25neC1jb21wb25lbnRzJztcbmltcG9ydCB7IE9wZXJhdGlvblNjaGVkdWxlIH0gZnJvbSAnQGM4eS9uZ3gtY29tcG9uZW50cy9vcGVyYXRpb25zL2J1bGstb3BlcmF0aW9uLXNjaGVkdWxlcic7XG5pbXBvcnQge1xuICBCdWxrT3BlcmF0aW9uc1NlcnZpY2UsXG4gIEJ1bGtPcGVyYXRpb25UeXBlLFxuICBPcGVyYXRpb25EZXRhaWxzXG59IGZyb20gJ0BjOHkvbmd4LWNvbXBvbmVudHMvb3BlcmF0aW9ucy9idWxrLW9wZXJhdGlvbnMtc2VydmljZSc7XG5pbXBvcnQgeyBDcmVhdGVCdWxrT3BlcmF0aW9uRGV0YWlsc0NvbXBvbmVudCB9IGZyb20gJ0BjOHkvbmd4LWNvbXBvbmVudHMvb3BlcmF0aW9ucy9jcmVhdGUtYnVsay1vcGVyYXRpb24tZGV0YWlscyc7XG5pbXBvcnQgeyBCVUxLX09QRVJBVElPTl9FVkVOVCB9IGZyb20gJ0BjOHkvbmd4LWNvbXBvbmVudHMvb3BlcmF0aW9ucy9wcm9kdWN0LWV4cGVyaWVuY2UnO1xuaW1wb3J0IHsgZ2V0IH0gZnJvbSAnbG9kYXNoLWVzJztcbmltcG9ydCB7IE9ic2VydmFibGUsIFN1YmplY3QgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IHRha2VVbnRpbCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IEN1c3RvbVN0ZXAgfSBmcm9tICcuL2N1c3RvbS1zdGVwLmRpcmVjdGl2ZSc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2M4eS1idWxrLW9wZXJhdGlvbi1zdGVwcGVyJyxcbiAgdGVtcGxhdGVVcmw6ICdidWxrLW9wZXJhdGlvbi1zdGVwcGVyLmNvbXBvbmVudC5odG1sJ1xufSlcbmV4cG9ydCBjbGFzcyBCdWxrT3BlcmF0aW9uU3RlcHBlciBpbXBsZW1lbnRzIE9uRGVzdHJveSB7XG4gIEJVTEtfT1BFUkFUSU9OX0VWRU5UID0gQlVMS19PUEVSQVRJT05fRVZFTlQ7XG5cbiAgQElucHV0KCkgdHlwZTogQnVsa09wZXJhdGlvblR5cGUgfCBzdHJpbmc7XG4gIEBPdXRwdXQoKSBzZWxlY3Rpb25DaGFuZ2U6IEV2ZW50RW1pdHRlcjxTdGVwcGVyU2VsZWN0aW9uRXZlbnQ+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICBAQ29udGVudENoaWxkcmVuKEN1c3RvbVN0ZXApIGN1c3RvbVN0ZXBzOiBRdWVyeUxpc3Q8Q3VzdG9tU3RlcD47XG4gIEBWaWV3Q2hpbGQoQzh5U3RlcHBlciwgeyBzdGF0aWM6IGZhbHNlIH0pXG4gIHN0ZXBwZXI6IEM4eVN0ZXBwZXI7XG4gIEBWaWV3Q2hpbGQoQ3JlYXRlQnVsa09wZXJhdGlvbkRldGFpbHNDb21wb25lbnQsIHsgc3RhdGljOiBmYWxzZSB9KVxuICBjcmVhdGVCdWxrT3BlcmF0aW9uRGV0YWlsc0NvbXBvbmVudDogQ3JlYXRlQnVsa09wZXJhdGlvbkRldGFpbHNDb21wb25lbnQ7XG5cbiAgc3RlcHM6IEN1c3RvbVN0ZXBbXSA9IFtdO1xuICBzaG93U3RlcHBlciA9IGZhbHNlO1xuICBzaG93QnV0dG9ucyA9IGZhbHNlO1xuICBwZW5kaW5nU3RhdHVzOiBib29sZWFuO1xuICBzdGVwcGVyQnV0dG9uc0xhYmVscyA9IHsgY3VzdG9tOiBnZXR0ZXh0KCdTY2hlZHVsZScpIH07XG4gIGRldmljZVR5cGVzJDogT2JzZXJ2YWJsZTxzdHJpbmdbXT47XG4gIGRldmljZVF1ZXJ5U3RyaW5nOiBzdHJpbmc7XG4gIGJ1bGtPcGVyYXRpb25UeXBlOiBCdWxrT3BlcmF0aW9uVHlwZTtcbiAgc2NoZWR1bGVEYXRhOiBPcGVyYXRpb25TY2hlZHVsZTtcbiAgb3BlcmF0aW9uRGV0YWlsc0Zvcm06IEZvcm1Hcm91cDtcbiAgb3BlcmF0aW9uRGV0YWlsczogT3BlcmF0aW9uRGV0YWlscztcbiAgcmV0cmlldmVPcGVyYXRpb25EZXRhaWxzOiAoKSA9PiBPcGVyYXRpb25EZXRhaWxzIHwgUHJvbWlzZTxPcGVyYXRpb25EZXRhaWxzPjtcblxuICBwcml2YXRlIGRldmljZVR5cGVzU3ViamVjdCQ6IFN1YmplY3Q8c3RyaW5nW10+ID0gbmV3IFN1YmplY3QoKTtcbiAgcHJpdmF0ZSBlbmRTdWJzY3JpcHRpb25zOiBTdWJqZWN0PHZvaWQ+ID0gbmV3IFN1YmplY3QoKTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIGJ1bGtPcGVyYXRpb25TZXJ2aWNlOiBCdWxrT3BlcmF0aW9uc1NlcnZpY2UsXG4gICAgcHJpdmF0ZSBtb2RhbDogTW9kYWxTZXJ2aWNlLFxuICAgIHByaXZhdGUgYWxlcnQ6IEFsZXJ0U2VydmljZVxuICApIHtcbiAgICB0aGlzLmRldmljZVR5cGVzJCA9IHRoaXMuZGV2aWNlVHlwZXNTdWJqZWN0JC5hc09ic2VydmFibGUoKTtcbiAgfVxuXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpOiB2b2lkIHtcbiAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIC8vIHdhaXQgZm9yIHRoZSBuZXh0IGV2ZW50IGxvb3AgdHVybiBhcyBgc3RlcHNgIGhhcyBhbHJlYWR5IGJlZW4gY2hlY2tlZCBpbiB0aGlzIENEIGN5Y2xlXG4gICAgICB0aGlzLnN0ZXBzID0gdGhpcy5jdXN0b21TdGVwcy50b0FycmF5KCk7XG4gICAgICB0aGlzLnNob3dTdGVwcGVyID0gdHJ1ZTtcbiAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAvLyBwb3N0cG9uZSByZW5kZXJpbmcgb2YgYnV0dG9ucyBmb3IgY3VzdG9tIHN0ZXBzIHRvIHRoZSBwb2ludCB3aGVyZSBjdXN0b20gc3RlcHMgaGF2ZSBhbHJlYWR5IGJlZW4gcmVuZGVyZWRcbiAgICAgICAgdGhpcy5zaG93QnV0dG9ucyA9IHRydWU7XG4gICAgICAgIGlmICh0aGlzLnN0ZXBwZXIpIHtcbiAgICAgICAgICB0aGlzLnN0ZXBwZXIuc2VsZWN0aW9uQ2hhbmdlLnBpcGUodGFrZVVudGlsKHRoaXMuZW5kU3Vic2NyaXB0aW9ucykpLnN1YnNjcmliZShldmVudCA9PiB7XG4gICAgICAgICAgICB0aGlzLnNlbGVjdGlvbkNoYW5nZS5uZXh0KGV2ZW50KTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgICB0aGlzLm9wZXJhdGlvbkRldGFpbHNGb3JtID1cbiAgICAgICAgICAgIHRoaXMuY3JlYXRlQnVsa09wZXJhdGlvbkRldGFpbHNDb21wb25lbnQuZmdPcGVyYXRpb25EZXNjcmlwdGlvbjtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICBjaGFuZ2VEZXZpY2VUeXBlcyhkZXZpY2VUeXBlczogc3RyaW5nIHwgc3RyaW5nW10pIHtcbiAgICBpZiAoZGV2aWNlVHlwZXMpIHtcbiAgICAgIHRoaXMuZGV2aWNlVHlwZXNTdWJqZWN0JC5uZXh0KEFycmF5LmlzQXJyYXkoZGV2aWNlVHlwZXMpID8gZGV2aWNlVHlwZXMgOiBbZGV2aWNlVHlwZXNdKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5kZXZpY2VUeXBlc1N1YmplY3QkLm5leHQoW10pO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIGNvbmZpcm1EZXZpY2VTZWxlY3Rpb24oJGV2ZW50OiB7IHN0ZXBwZXI6IEM4eVN0ZXBwZXI7IHN0ZXA6IENka1N0ZXAgfSkge1xuICAgIGlmICghdGhpcy5kZXZpY2VRdWVyeVN0cmluZykge1xuICAgICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgdGhpcy5tb2RhbC5jb25maXJtKFxuICAgICAgICAgIGdldHRleHQoJ0FsbCBkZXZpY2VzIHNlbGVjdGVkJyksXG4gICAgICAgICAgZ2V0dGV4dChcbiAgICAgICAgICAgICdZb3UgYXJlIGFib3V0IHRvIHNjaGVkdWxlIHRoZSBidWxrIG9wZXJhdGlvbiB0byBiZSBleGVjdXRlZCBmb3IgYWxsIGRldmljZXMuIERvIHlvdSB3YW50IHRvIHByb2NlZWQ/J1xuICAgICAgICAgICksXG4gICAgICAgICAgU3RhdHVzLldBUk5JTkcsXG4gICAgICAgICAgeyBvazogZ2V0dGV4dCgnU2NoZWR1bGUgZm9yIGFsbCBkZXZpY2VzJyksIGNhbmNlbDogZ2V0dGV4dCgnQ2FuY2VsIGFuZCBzZWxlY3QgZGV2aWNlcycpIH1cbiAgICAgICAgKTtcbiAgICAgICAgJGV2ZW50LnN0ZXAuY29tcGxldGVkID0gdHJ1ZTtcbiAgICAgICAgJGV2ZW50LnN0ZXBwZXIubmV4dCgpO1xuICAgICAgICB0aGlzLm9wZXJhdGlvbkRldGFpbHMgPSB0aGlzLnJldHJpZXZlT3BlcmF0aW9uRGV0YWlsc1xuICAgICAgICAgID8gYXdhaXQgdGhpcy5yZXRyaWV2ZU9wZXJhdGlvbkRldGFpbHMoKVxuICAgICAgICAgIDogdW5kZWZpbmVkO1xuICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgLy8gSW50ZW50aW9uYWxseSBlbXB0eVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAkZXZlbnQuc3RlcC5jb21wbGV0ZWQgPSB0cnVlO1xuICAgICAgJGV2ZW50LnN0ZXBwZXIubmV4dCgpO1xuICAgICAgdGhpcy5vcGVyYXRpb25EZXRhaWxzID0gdGhpcy5yZXRyaWV2ZU9wZXJhdGlvbkRldGFpbHNcbiAgICAgICAgPyBhd2FpdCB0aGlzLnJldHJpZXZlT3BlcmF0aW9uRGV0YWlscygpXG4gICAgICAgIDogdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIHRoaXMuYnVsa09wZXJhdGlvblR5cGUgPSB0aGlzLmJ1bGtPcGVyYXRpb25TZXJ2aWNlLnJldHJpZXZlQnVsa09wZXJhdGlvblR5cGUoXG4gICAgICBnZXQodGhpcy5vcGVyYXRpb25EZXRhaWxzLCAncHJvdG90eXBlJylcbiAgICApO1xuICAgIGlmIChcbiAgICAgIHRoaXMub3BlcmF0aW9uRGV0YWlsc0Zvcm0gJiZcbiAgICAgIGdldCh0aGlzLm9wZXJhdGlvbkRldGFpbHNGb3JtLCAnY29udHJvbHMuZGVzY3JpcHRpb24ucHJpc3RpbmUnKSAmJlxuICAgICAgdGhpcy5vcGVyYXRpb25EZXRhaWxzXG4gICAgKSB7XG4gICAgICB0aGlzLm9wZXJhdGlvbkRldGFpbHNGb3JtLnBhdGNoVmFsdWUoe1xuICAgICAgICBkZXNjcmlwdGlvbjogZ2V0KHRoaXMub3BlcmF0aW9uRGV0YWlscywgJ3Byb3RvdHlwZS5kZXNjcmlwdGlvbicpXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBjYW5jZWwoKSB7XG4gICAgdGhpcy5jbG9zZSgpO1xuICB9XG5cbiAgYXN5bmMgc2NoZWR1bGVCdWxrT3BlcmF0aW9uKCkge1xuICAgIHRoaXMucGVuZGluZ1N0YXR1cyA9IHRydWU7XG5cbiAgICB0cnkge1xuICAgICAgdGhpcy5vcGVyYXRpb25EZXRhaWxzLnByb3RvdHlwZS5kZXNjcmlwdGlvbiA9IGdldChcbiAgICAgICAgdGhpcy5vcGVyYXRpb25EZXRhaWxzRm9ybSxcbiAgICAgICAgJ2NvbnRyb2xzLmRlc2NyaXB0aW9uLnZhbHVlJ1xuICAgICAgKTtcbiAgICAgIHRoaXMub3BlcmF0aW9uRGV0YWlscy5ub3RlID0gZ2V0KHRoaXMub3BlcmF0aW9uRGV0YWlsc0Zvcm0sICdjb250cm9scy5ub3RlLnZhbHVlJyk7XG4gICAgICB0aGlzLm9wZXJhdGlvbkRldGFpbHMuc2NoZWR1bGUgPSBnZXQodGhpcy5vcGVyYXRpb25EZXRhaWxzRm9ybSwgJ2NvbnRyb2xzLnNjaGVkdWxlLnZhbHVlJyk7XG5cbiAgICAgIGF3YWl0IHRoaXMuYnVsa09wZXJhdGlvblNlcnZpY2Uuc2NoZWR1bGVCdWxrT3BlcmF0aW9uKFxuICAgICAgICB0aGlzLmRldmljZVF1ZXJ5U3RyaW5nLFxuICAgICAgICB0aGlzLm9wZXJhdGlvbkRldGFpbHNcbiAgICAgICk7XG4gICAgICB0aGlzLmFsZXJ0LnN1Y2Nlc3MoZ2V0dGV4dCgnTmV3IGJ1bGsgb3BlcmF0aW9uIHNjaGVkdWxlZC4nKSk7XG4gICAgICB0aGlzLmNsb3NlKCk7XG4gICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgIHRoaXMuYWxlcnQuYWRkU2VydmVyRmFpbHVyZShleCk7XG4gICAgfVxuXG4gICAgdGhpcy5wZW5kaW5nU3RhdHVzID0gZmFsc2U7XG4gIH1cblxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICB0aGlzLmVuZFN1YnNjcmlwdGlvbnMubmV4dCgpO1xuICAgIHRoaXMuZW5kU3Vic2NyaXB0aW9ucy5jb21wbGV0ZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBjbG9zZSgpIHtcbiAgICB0aGlzLnN0ZXBwZXIucmVzZXQoKTtcbiAgICB0aGlzLmJ1bGtPcGVyYXRpb25TZXJ2aWNlLnJldHVyblRvQnVsa09wZXJhdGlvbk92ZXJ2aWV3KCk7XG4gIH1cbn1cbiIsIjxkaXYgY2xhc3M9XCJmaXQtaFwiPlxuICA8Yzh5LXN0ZXBwZXJcbiAgICBjbGFzcz1cImQtY29sIG5vLWFsaWduLWl0ZW1zIGZpdC1oIGM4eS1zdGVwcGVyLS1uby1idG5zIGEtaS1jZW50ZXJcIlxuICAgIGxpbmVhclxuICAgIFtkaXNhYmxlRGVmYXVsdEljb25zXT1cInsgZWRpdDogdHJ1ZSwgZG9uZTogZmFsc2UgfVwiXG4gICAgW2N1c3RvbUNsYXNzZXNdPVwiWydjb2wteHMtMTAnLCAnY29sLXNtLTgnLCAnbS10LTI0JywgJ20tYi00MCcsICdwLTAnLCAnZmxleC1uby1zaHJpbmsnXVwiXG4gICAgKm5nSWY9XCJzaG93U3RlcHBlclwiXG4gICAgYzh5UHJvZHVjdEV4cGVyaWVuY2VcbiAgICBbYWN0aW9uTmFtZV09XCJCVUxLX09QRVJBVElPTl9FVkVOVFwiXG4gICAgW2FjdGlvbkRhdGFdPVwieyBidWxrT3BlcmF0aW9uVHlwZTogdHlwZSB9XCJcbiAgPlxuICAgIDwhLS0gQ1VTVE9NIFNURVBTIDEgdG8gTi0yIC0tPlxuICAgIDxjZGstc3RlcFxuICAgICAgKm5nRm9yPVwibGV0IHN0ZXAgb2Ygc3RlcHNcIlxuICAgICAgW2xhYmVsXT1cInN0ZXAubGFiZWwgfCB0cmFuc2xhdGVcIlxuICAgICAgW2NvbXBsZXRlZF09XCJzdGVwLmNvbXBsZXRlZFwiXG4gICAgPlxuICAgICAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cInN0ZXAudGVtcGxhdGVSZWZcIj48L25nLWNvbnRhaW5lcj5cbiAgICAgIDxjOHktc3RlcHBlci1idXR0b25zXG4gICAgICAgIGNsYXNzPVwiZC1ibG9jayBjYXJkLWZvb3RlciBwLTI0IHNlcGFyYXRvciBmaXQtdyBzdGlja3ktYm90dG9tIGJnLWxldmVsLTBcIlxuICAgICAgICAqbmdJZj1cInNob3dCdXR0b25zXCJcbiAgICAgICAgW2Rpc2FibGVkXT1cInN0ZXAuYnV0dG9uc0Rpc2FibGVkXCJcbiAgICAgICAgKG9uTmV4dCk9XCJzdGVwLm9uTmV4dCgkZXZlbnQpXCJcbiAgICAgICAgKG9uQ2FuY2VsKT1cImNhbmNlbCgpXCJcbiAgICAgID48L2M4eS1zdGVwcGVyLWJ1dHRvbnM+XG4gICAgPC9jZGstc3RlcD5cbiAgICA8IS0tIFNURVAgTi0xIC0gRGF0YS1ncmlkIC0tPlxuICAgIDxjZGstc3RlcCBbbGFiZWxdPVwiJ0ZpbHRlciB0YXJnZXQgZGV2aWNlcycgfCB0cmFuc2xhdGVcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJjYXJkLWJsb2NrIHAtYi0wIHAtdC0wIGZsZXgtbm8tc2hyaW5rIHNlcGFyYXRvci1ib3R0b20gY29sLXhzLTEyXCI+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJkLWZsZXggai1jLWNlbnRlciBwLWItOCBwLXQtNFwiPlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJjb2wteHMtMTIgY29sLXNtLTZcIj5cbiAgICAgICAgICAgIDxoNCBjbGFzcz1cInRleHQtY2VudGVyIHRleHQtbm9ybWFsIG0tYi0xNlwiPlxuICAgICAgICAgICAgICB7eyAnRmlsdGVyIHRhcmdldCBkZXZpY2VzJyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICAgICAgPC9oND5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cblxuICAgICAgPGRpdiBjbGFzcz1cImNvbC14cy0xMiBmbGV4LWdyb3cgbm8tZ3V0dGVyXCI+XG4gICAgICAgIDxjOHktZGV2aWNlLXNlbGVjdG9yXG4gICAgICAgICAgW2RldmljZVR5cGVzXT1cImRldmljZVR5cGVzJFwiXG4gICAgICAgICAgKG9uRGV2aWNlUXVlcnlTdHJpbmdDaGFuZ2UpPVwiZGV2aWNlUXVlcnlTdHJpbmcgPSAkZXZlbnRcIlxuICAgICAgICA+PC9jOHktZGV2aWNlLXNlbGVjdG9yPlxuICAgICAgPC9kaXY+XG4gICAgICA8Yzh5LXN0ZXBwZXItYnV0dG9uc1xuICAgICAgICBjbGFzcz1cImQtYmxvY2sgY2FyZC1mb290ZXIgcC0yNCBzZXBhcmF0b3IgZml0LXcgc3RpY2t5LWJvdHRvbSBiZy1sZXZlbC0wXCJcbiAgICAgICAgKm5nSWY9XCJzaG93QnV0dG9uc1wiXG4gICAgICAgIChvbk5leHQpPVwiY29uZmlybURldmljZVNlbGVjdGlvbigkZXZlbnQpXCJcbiAgICAgICAgKG9uQ2FuY2VsKT1cImNhbmNlbCgpXCJcbiAgICAgID48L2M4eS1zdGVwcGVyLWJ1dHRvbnM+XG4gICAgPC9jZGstc3RlcD5cblxuICAgIDwhLS0gU1RFUCBOIC0gU2NoZWR1bGVyIC0tPlxuICAgIDxjZGstc3RlcCBbbGFiZWxdPVwiJ0NvbmZpcm0gYW5kIHNjaGVkdWxlIGJ1bGsgb3BlcmF0aW9uJyB8IHRyYW5zbGF0ZVwiPlxuICAgICAgPGRpdiBjbGFzcz1cImNhcmQtYmxvY2sgZmxleC1uby1zaHJpbmsgcC1iLTAgcC10LTAgc2VwYXJhdG9yLWJvdHRvbSBjb2wteHMtMTJcIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImQtZmxleCBqLWMtY2VudGVyIHAtYi04IHAtdC00XCI+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImNvbC14cy0xMiBjb2wtc20tNlwiPlxuICAgICAgICAgICAgPGg0IGNsYXNzPVwidGV4dC1jZW50ZXIgdGV4dC1ub3JtYWwgbS1iLTE2XCI+XG4gICAgICAgICAgICAgIHt7ICdDb25maXJtIGFuZCBzY2hlZHVsZSBidWxrIG9wZXJhdGlvbicgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgICAgIDwvaDQ+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG5cbiAgICAgIDxkaXYgY2xhc3M9XCJjb2wteHMtMTIgZmxleC1ncm93IG5vLWd1dHRlclwiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiY2FyZC1pbm5lci1zY3JvbGwgZml0LWhcIj5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiY2FyZC1ibG9jayBwLWItMFwiPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImQtZmxleCBqLWMtY2VudGVyIHAtdC04IHAtYi04XCI+XG4gICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJjb2wteHMtMTIgY29sLXNtLTZcIj5cbiAgICAgICAgICAgICAgICA8Yzh5LW9wZXJhdGlvbi1zdW1tYXJ5XG4gICAgICAgICAgICAgICAgICBbbmFtZV09XCJvcGVyYXRpb25EZXRhaWxzPy5uYW1lIHwgdHJhbnNsYXRlXCJcbiAgICAgICAgICAgICAgICAgIFtkZXNjcmlwdGlvbl09XCJvcGVyYXRpb25EZXRhaWxzPy5kZXNjcmlwdGlvbiB8IHRyYW5zbGF0ZVwiXG4gICAgICAgICAgICAgICAgICBbZGV2aWNlUXVlcnlTdHJpbmddPVwiZGV2aWNlUXVlcnlTdHJpbmdcIlxuICAgICAgICAgICAgICAgID48L2M4eS1vcGVyYXRpb24tc3VtbWFyeT5cbiAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJkLWZsZXggai1jLWNlbnRlclwiPlxuICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiY29sLXhzLTEyIGNvbC1zbS02XCI+XG4gICAgICAgICAgICAgICAgPGM4eS1jcmVhdGUtYnVsay1vcGVyYXRpb24tZGV0YWlsc1xuICAgICAgICAgICAgICAgICAgW2J1bGtPcGVyYXRpb25UeXBlXT1cImJ1bGtPcGVyYXRpb25UeXBlXCJcbiAgICAgICAgICAgICAgICA+PC9jOHktY3JlYXRlLWJ1bGstb3BlcmF0aW9uLWRldGFpbHM+XG4gICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgICA8Yzh5LXN0ZXBwZXItYnV0dG9uc1xuICAgICAgICBjbGFzcz1cImQtYmxvY2sgY2FyZC1mb290ZXIgcC0yNCBzZXBhcmF0b3IgZml0LXcgc3RpY2t5LWJvdHRvbSBiZy1sZXZlbC0wXCJcbiAgICAgICAgKm5nSWY9XCJzaG93QnV0dG9uc1wiXG4gICAgICAgIFtsYWJlbHNdPVwic3RlcHBlckJ1dHRvbnNMYWJlbHNcIlxuICAgICAgICBbcGVuZGluZ109XCJwZW5kaW5nU3RhdHVzXCJcbiAgICAgICAgW2Rpc2FibGVkXT1cIm9wZXJhdGlvbkRldGFpbHNGb3JtPy5pbnZhbGlkXCJcbiAgICAgICAgKG9uQ2FuY2VsKT1cImNhbmNlbCgpXCJcbiAgICAgICAgKG9uQ3VzdG9tKT1cInNjaGVkdWxlQnVsa09wZXJhdGlvbigpXCJcbiAgICAgID48L2M4eS1zdGVwcGVyLWJ1dHRvbnM+XG4gICAgPC9jZGstc3RlcD5cbiAgPC9jOHktc3RlcHBlcj5cbjwvZGl2PlxuIl19