@c8y/ngx-components
Version:
Angular modules for Cumulocity IoT applications
116 lines • 36.3 kB
JavaScript
import { Component, ViewChild } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Realtime } from '@c8y/client';
import { gettext } from '@c8y/ngx-components';
import { DeviceConfigurationOperation, RepositoryService } from '@c8y/ngx-components/repository/shared';
import { has } from 'lodash-es';
import { DeviceConfigurationService } from './device-configuration.service';
import { TextBasedConfigurationComponent } from './text-based-configuration.component';
import * as i0 from "@angular/core";
import * as i1 from "@angular/router";
import * as i2 from "./device-configuration.service";
import * as i3 from "@c8y/client";
import * as i4 from "@c8y/ngx-components/repository/shared";
import * as i5 from "@angular/common";
import * as i6 from "@c8y/ngx-components";
import * as i7 from "ngx-bootstrap/tabs";
import * as i8 from "./device-configuration-list.component";
import * as i9 from "./configuration-preview.component";
import * as i10 from "./text-based-configuration.component";
export class DeviceConfigurationComponent {
constructor(route, deviceConfigurationService, realtime, repositoryService) {
this.route = route;
this.deviceConfigurationService = deviceConfigurationService;
this.realtime = realtime;
this.repositoryService = repositoryService;
this.supportedConfigurations = [];
this.showBinaryBasedConfig = false;
this.configSnapshot = {};
this.reloading = false;
this.deviceConfigurationService.configurationsUpdated.subscribe(repositorySnapsOnly => {
this.updateSnapshots(repositorySnapsOnly);
});
}
ngOnInit() {
this.device = this.route.snapshot.parent.data.contextData;
if (this.device.c8y_SupportedConfigurations) {
this.supportedConfigurations = this.device.c8y_SupportedConfigurations.map(item => ({
name: item
}));
}
if (this.deviceConfigurationService.hasAnySupportedOperation(this.device, [
DeviceConfigurationOperation.DOWNLOAD_CONFIG,
DeviceConfigurationOperation.UPLOAD_CONFIG
])) {
this.supportedConfigurations.push({
name: gettext('Legacy configuration snapshot'),
isLegacy: true
});
}
if (this.supportedConfigurations.length > 0) {
this.showBinaryBasedConfig = true;
}
this.repositorySnapshotsEmptyState = {
icon: 'gears',
title: gettext('No configurations available.'),
text: gettext('Add configuration to configuration repository')
};
this.showTextBasedConfig =
this.deviceConfigurationService.hasAnySupportedOperation(this.device, [
DeviceConfigurationOperation.CONFIG,
DeviceConfigurationOperation.SEND_CONFIG
]) || has(this.device, 'c8y_Configuration');
}
async onConfigTypeSelected(config) {
this.configurationType = config.name;
this.isLegacy = config.isLegacy;
this.updateSnapshots();
}
async onRepositoryConfigSelected(config) {
this.repositorySnapshot = {
id: config.id,
time: config.creationTime,
name: config.name,
binaryUrl: config.url,
deviceType: config.deviceType,
configurationType: config.configurationType
};
if (config.url) {
try {
const binary = await this.repositoryService.getBinaryFile(config.url, {
allowExternal: false
});
if (binary) {
this.repositorySnapshot.binary = await binary.text();
}
}
catch (ex) {
// do nothing
}
}
}
async updateSnapshots(repositorySnapsOnly) {
this.reloading = true;
this.repositorySnapshot = undefined;
this.repositorySnapshots = await this.repositoryService.getSnapshotsFromRepository(this.device, this.configurationType);
if (!repositorySnapsOnly) {
this.configSnapshot = this.isLegacy
? await this.repositoryService.getLegacyConfigSnapshot(this.device)
: await this.repositoryService.getConfigSnapshot(this.device, this.configurationType);
}
if (this.showTextBasedConfig) {
await this.textBasedConfigurationComponent.load();
}
this.reloading = false;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DeviceConfigurationComponent, deps: [{ token: i1.ActivatedRoute }, { token: i2.DeviceConfigurationService }, { token: i3.Realtime }, { token: i4.RepositoryService }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: DeviceConfigurationComponent, selector: "c8y-device-configuration", viewQueries: [{ propertyName: "textBasedConfigurationComponent", first: true, predicate: TextBasedConfigurationComponent, descendants: true }], ngImport: i0, template: "<c8y-action-bar-item [placement]=\"'right'\">\n <button class=\"btn btn-link\" title=\"{{ 'Reload' | translate }}\" (click)=\"updateSnapshots()\">\n <i c8yIcon=\"refresh\" [ngClass]=\"{ 'icon-spin': reloading }\"></i>\n {{ 'Reload' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<div class=\"card content-fullpage card-has-tabs\">\n <tabset>\n <div class=\"card-header separator\" *ngIf=\"showBinaryBasedConfig && !showTextBasedConfig\">\n <div class=\"card-title\">{{ 'Configurations' | translate }}</div>\n </div>\n <div class=\"card-header separator\" *ngIf=\"!showBinaryBasedConfig && showTextBasedConfig\">\n <div class=\"card-title\">{{ 'Text-based configuration' | translate }}</div>\n </div>\n <tab heading=\"{{ 'Configurations' | translate }}\" *ngIf=\"showBinaryBasedConfig\">\n <div class=\"card--grid card grid__col--4-8--md grid__row--6-6--md m-b-0\">\n <!-- DEVICE SUPPORTED CONFIGURATIONS -->\n <div class=\"card--grid__inner-scroll bg-level-1\">\n <div class=\"p-l-16 p-r-16\">\n <h5 class=\"legend form-block\">\n <span translate>Device-supported configurations</span>\n </h5>\n </div>\n <c8y-device-configuration-list\n [items]=\"supportedConfigurations\"\n [itemIcon]=\"'gears'\"\n (configSelected)=\"onConfigTypeSelected($event)\"\n ></c8y-device-configuration-list>\n </div>\n\n <!-- CONFIGURATION PREVIEW -->\n <div class=\"card--grid__inner-scroll d-flex d-col flex-grow\">\n <div class=\"card-block d-flex d-col flex-grow\">\n <h5 class=\"legend form-block\"><span translate>Preview</span></h5>\n\n <!-- EMPTY STATE -->\n\n <c8y-ui-empty-state\n *ngIf=\"!configurationType\"\n [icon]=\"'file-text'\"\n [title]=\"'No configuration selected.' | translate\"\n [subtitle]=\"'Select a configuration to preview.' | translate\"\n [horizontal]=\"true\"\n ></c8y-ui-empty-state>\n\n <!-- PREVIEW AVAILABLE STATE -->\n <c8y-device-configuration-preview\n *ngIf=\"configurationType\"\n [device]=\"device\"\n [configurationType]=\"configurationType\"\n [configSnapshot]=\"configSnapshot\"\n [canSaveSnapshot]=\"true\"\n [operationToTrigger]=\"'c8y_UploadConfigFile'\"\n [actionButtonText]=\"'Get snapshot from device' | translate\"\n [actionButtonIcon]=\"'download'\"\n [isLegacy]=\"isLegacy\"\n class=\"d-flex d-col flex-grow\"\n ></c8y-device-configuration-preview>\n </div>\n </div>\n\n <!-- AVAILABLE SUPPORTED CONFIGURATIONS -->\n <div class=\"card--grid__inner-scroll bg-level-1\">\n <div class=\"p-l-16 p-r-16\">\n <h5 class=\"legend form-block\" translate>Available supported configurations</h5>\n </div>\n\n <!-- EMPTY STATE -->\n\n <c8y-ui-empty-state\n *ngIf=\"!configurationType\"\n [icon]=\"'gears'\"\n [title]=\"'No selection.' | translate\"\n [subtitle]=\"\n 'Select a configuration from the device-supported configuration list.' | translate\n \"\n [horizontal]=\"true\"\n ></c8y-ui-empty-state>\n\n <div class=\"p-r-16\" *ngIf=\"configurationType\">\n <c8y-device-configuration-list\n [items]=\"repositorySnapshots\"\n [itemIcon]=\"'file-text'\"\n [emptyState]=\"repositorySnapshotsEmptyState\"\n [isFilterEnabled]=\"true\"\n (configSelected)=\"onRepositoryConfigSelected($event)\"\n ></c8y-device-configuration-list>\n </div>\n </div>\n\n <!-- CONFIGURATION PREVIEW -->\n <div class=\"card--grid__inner-scroll d-flex d-col flex-grow\">\n <div class=\"card-block flex-grow d-flex d-col\">\n <h5 class=\"legend form-block\" translate>Preview</h5>\n\n <!-- EMPTY STATE -->\n <c8y-ui-empty-state\n *ngIf=\"!repositorySnapshot\"\n [icon]=\"'file-text'\"\n [title]=\"'No configuration selected.' | translate\"\n [subtitle]=\"'Select a configuration to preview.' | translate\"\n [horizontal]=\"true\"\n ></c8y-ui-empty-state>\n\n <!-- CONFIGURATION SELECTED STATE -->\n <c8y-device-configuration-preview\n *ngIf=\"repositorySnapshot\"\n [device]=\"device\"\n [configurationType]=\"configurationType\"\n [configSnapshot]=\"repositorySnapshot\"\n [operationToTrigger]=\"'c8y_DownloadConfigFile'\"\n [actionButtonText]=\"'Send configuration to device' | translate\"\n [actionButtonIcon]=\"'upload'\"\n [isLegacy]=\"isLegacy\"\n class=\"d-flex d-col flex-grow\"\n ></c8y-device-configuration-preview>\n </div>\n </div>\n </div>\n </tab>\n <tab heading=\"{{ 'Text-based configuration' | translate }}\" *ngIf=\"showTextBasedConfig\">\n <c8y-text-based-configuration></c8y-text-based-configuration>\n </tab>\n </tabset>\n</div>\n", dependencies: [{ kind: "directive", type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i6.ActionBarItemComponent, selector: "c8y-action-bar-item", inputs: ["placement", "priority", "itemClass", "injector", "groupId", "inGroupPriority"] }, { kind: "component", type: i6.EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "directive", type: i6.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: i6.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i6.TabsetAriaDirective, selector: "tabset" }, { kind: "directive", type: i7.TabDirective, selector: "tab, [tab]", inputs: ["heading", "id", "disabled", "removable", "customClass", "active"], outputs: ["selectTab", "deselect", "removed"], exportAs: ["tab"] }, { kind: "component", type: i7.TabsetComponent, selector: "tabset", inputs: ["vertical", "justified", "type"] }, { kind: "component", type: i8.DeviceConfigurationListComponent, selector: "c8y-device-configuration-list", inputs: ["items", "itemIcon", "emptyState", "isFilterEnabled"], outputs: ["configSelected"] }, { kind: "component", type: i9.ConfigurationPreviewComponent, selector: "c8y-device-configuration-preview", inputs: ["device", "configurationType", "configSnapshot", "canSaveSnapshot", "actionButtonText", "actionButtonIcon", "isLegacy", "operationToTrigger"] }, { kind: "component", type: i10.TextBasedConfigurationComponent, selector: "c8y-text-based-configuration" }, { kind: "pipe", type: i6.C8yTranslatePipe, name: "translate" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DeviceConfigurationComponent, decorators: [{
type: Component,
args: [{ selector: 'c8y-device-configuration', template: "<c8y-action-bar-item [placement]=\"'right'\">\n <button class=\"btn btn-link\" title=\"{{ 'Reload' | translate }}\" (click)=\"updateSnapshots()\">\n <i c8yIcon=\"refresh\" [ngClass]=\"{ 'icon-spin': reloading }\"></i>\n {{ 'Reload' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<div class=\"card content-fullpage card-has-tabs\">\n <tabset>\n <div class=\"card-header separator\" *ngIf=\"showBinaryBasedConfig && !showTextBasedConfig\">\n <div class=\"card-title\">{{ 'Configurations' | translate }}</div>\n </div>\n <div class=\"card-header separator\" *ngIf=\"!showBinaryBasedConfig && showTextBasedConfig\">\n <div class=\"card-title\">{{ 'Text-based configuration' | translate }}</div>\n </div>\n <tab heading=\"{{ 'Configurations' | translate }}\" *ngIf=\"showBinaryBasedConfig\">\n <div class=\"card--grid card grid__col--4-8--md grid__row--6-6--md m-b-0\">\n <!-- DEVICE SUPPORTED CONFIGURATIONS -->\n <div class=\"card--grid__inner-scroll bg-level-1\">\n <div class=\"p-l-16 p-r-16\">\n <h5 class=\"legend form-block\">\n <span translate>Device-supported configurations</span>\n </h5>\n </div>\n <c8y-device-configuration-list\n [items]=\"supportedConfigurations\"\n [itemIcon]=\"'gears'\"\n (configSelected)=\"onConfigTypeSelected($event)\"\n ></c8y-device-configuration-list>\n </div>\n\n <!-- CONFIGURATION PREVIEW -->\n <div class=\"card--grid__inner-scroll d-flex d-col flex-grow\">\n <div class=\"card-block d-flex d-col flex-grow\">\n <h5 class=\"legend form-block\"><span translate>Preview</span></h5>\n\n <!-- EMPTY STATE -->\n\n <c8y-ui-empty-state\n *ngIf=\"!configurationType\"\n [icon]=\"'file-text'\"\n [title]=\"'No configuration selected.' | translate\"\n [subtitle]=\"'Select a configuration to preview.' | translate\"\n [horizontal]=\"true\"\n ></c8y-ui-empty-state>\n\n <!-- PREVIEW AVAILABLE STATE -->\n <c8y-device-configuration-preview\n *ngIf=\"configurationType\"\n [device]=\"device\"\n [configurationType]=\"configurationType\"\n [configSnapshot]=\"configSnapshot\"\n [canSaveSnapshot]=\"true\"\n [operationToTrigger]=\"'c8y_UploadConfigFile'\"\n [actionButtonText]=\"'Get snapshot from device' | translate\"\n [actionButtonIcon]=\"'download'\"\n [isLegacy]=\"isLegacy\"\n class=\"d-flex d-col flex-grow\"\n ></c8y-device-configuration-preview>\n </div>\n </div>\n\n <!-- AVAILABLE SUPPORTED CONFIGURATIONS -->\n <div class=\"card--grid__inner-scroll bg-level-1\">\n <div class=\"p-l-16 p-r-16\">\n <h5 class=\"legend form-block\" translate>Available supported configurations</h5>\n </div>\n\n <!-- EMPTY STATE -->\n\n <c8y-ui-empty-state\n *ngIf=\"!configurationType\"\n [icon]=\"'gears'\"\n [title]=\"'No selection.' | translate\"\n [subtitle]=\"\n 'Select a configuration from the device-supported configuration list.' | translate\n \"\n [horizontal]=\"true\"\n ></c8y-ui-empty-state>\n\n <div class=\"p-r-16\" *ngIf=\"configurationType\">\n <c8y-device-configuration-list\n [items]=\"repositorySnapshots\"\n [itemIcon]=\"'file-text'\"\n [emptyState]=\"repositorySnapshotsEmptyState\"\n [isFilterEnabled]=\"true\"\n (configSelected)=\"onRepositoryConfigSelected($event)\"\n ></c8y-device-configuration-list>\n </div>\n </div>\n\n <!-- CONFIGURATION PREVIEW -->\n <div class=\"card--grid__inner-scroll d-flex d-col flex-grow\">\n <div class=\"card-block flex-grow d-flex d-col\">\n <h5 class=\"legend form-block\" translate>Preview</h5>\n\n <!-- EMPTY STATE -->\n <c8y-ui-empty-state\n *ngIf=\"!repositorySnapshot\"\n [icon]=\"'file-text'\"\n [title]=\"'No configuration selected.' | translate\"\n [subtitle]=\"'Select a configuration to preview.' | translate\"\n [horizontal]=\"true\"\n ></c8y-ui-empty-state>\n\n <!-- CONFIGURATION SELECTED STATE -->\n <c8y-device-configuration-preview\n *ngIf=\"repositorySnapshot\"\n [device]=\"device\"\n [configurationType]=\"configurationType\"\n [configSnapshot]=\"repositorySnapshot\"\n [operationToTrigger]=\"'c8y_DownloadConfigFile'\"\n [actionButtonText]=\"'Send configuration to device' | translate\"\n [actionButtonIcon]=\"'upload'\"\n [isLegacy]=\"isLegacy\"\n class=\"d-flex d-col flex-grow\"\n ></c8y-device-configuration-preview>\n </div>\n </div>\n </div>\n </tab>\n <tab heading=\"{{ 'Text-based configuration' | translate }}\" *ngIf=\"showTextBasedConfig\">\n <c8y-text-based-configuration></c8y-text-based-configuration>\n </tab>\n </tabset>\n</div>\n" }]
}], ctorParameters: () => [{ type: i1.ActivatedRoute }, { type: i2.DeviceConfigurationService }, { type: i3.Realtime }, { type: i4.RepositoryService }], propDecorators: { textBasedConfigurationComponent: [{
type: ViewChild,
args: [TextBasedConfigurationComponent]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGV2aWNlLWNvbmZpZ3VyYXRpb24uY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcmVwb3NpdG9yeS9jb25maWd1cmF0aW9uL2RldmljZS10YWIvZGV2aWNlLWNvbmZpZ3VyYXRpb24uY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vcmVwb3NpdG9yeS9jb25maWd1cmF0aW9uL2RldmljZS10YWIvZGV2aWNlLWNvbmZpZ3VyYXRpb24uY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBVSxTQUFTLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDN0QsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ2pELE9BQU8sRUFBa0IsUUFBUSxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ3ZELE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUM5QyxPQUFPLEVBR0wsNEJBQTRCLEVBQzVCLGlCQUFpQixFQUVsQixNQUFNLHVDQUF1QyxDQUFDO0FBQy9DLE9BQU8sRUFBRSxHQUFHLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDaEMsT0FBTyxFQUFFLDBCQUEwQixFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDNUUsT0FBTyxFQUFFLCtCQUErQixFQUFFLE1BQU0sc0NBQXNDLENBQUM7Ozs7Ozs7Ozs7OztBQU12RixNQUFNLE9BQU8sNEJBQTRCO0lBZ0J2QyxZQUNVLEtBQXFCLEVBQ3JCLDBCQUFzRCxFQUN0RCxRQUFrQixFQUNsQixpQkFBb0M7UUFIcEMsVUFBSyxHQUFMLEtBQUssQ0FBZ0I7UUFDckIsK0JBQTBCLEdBQTFCLDBCQUEwQixDQUE0QjtRQUN0RCxhQUFRLEdBQVIsUUFBUSxDQUFVO1FBQ2xCLHNCQUFpQixHQUFqQixpQkFBaUIsQ0FBbUI7UUFuQjlDLDRCQUF1QixHQUFpQyxFQUFFLENBQUM7UUFDM0QsMEJBQXFC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O21MQWlCcEMsK0JBQStCO3NCQUQ5QixTQUFTO3VCQUFDLCtCQUErQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgT25Jbml0LCBWaWV3Q2hpbGQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEFjdGl2YXRlZFJvdXRlIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7IElNYW5hZ2VkT2JqZWN0LCBSZWFsdGltZSB9IGZyb20gJ0BjOHkvY2xpZW50JztcbmltcG9ydCB7IGdldHRleHQgfSBmcm9tICdAYzh5L25neC1jb21wb25lbnRzJztcbmltcG9ydCB7XG4gIENvbmZpZ3VyYXRpb25TbmFwc2hvdCxcbiAgRGV2aWNlQ29uZmlndXJhdGlvbkxpc3RFbXB0eVN0YXRlLFxuICBEZXZpY2VDb25maWd1cmF0aW9uT3BlcmF0aW9uLFxuICBSZXBvc2l0b3J5U2VydmljZSxcbiAgU3VwcG9ydGVkQ29uZmlndXJhdGlvbkl0ZW1cbn0gZnJvbSAnQGM4eS9uZ3gtY29tcG9uZW50cy9yZXBvc2l0b3J5L3NoYXJlZCc7XG5pbXBvcnQgeyBoYXMgfSBmcm9tICdsb2Rhc2gtZXMnO1xuaW1wb3J0IHsgRGV2aWNlQ29uZmlndXJhdGlvblNlcnZpY2UgfSBmcm9tICcuL2RldmljZS1jb25maWd1cmF0aW9uLnNlcnZpY2UnO1xuaW1wb3J0IHsgVGV4dEJhc2VkQ29uZmlndXJhdGlvbkNvbXBvbmVudCB9IGZyb20gJy4vdGV4dC1iYXNlZC1jb25maWd1cmF0aW9uLmNvbXBvbmVudCc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2M4eS1kZXZpY2UtY29uZmlndXJhdGlvbicsXG4gIHRlbXBsYXRlVXJsOiAnLi9kZXZpY2UtY29uZmlndXJhdGlvbi5jb21wb25lbnQuaHRtbCdcbn0pXG5leHBvcnQgY2xhc3MgRGV2aWNlQ29uZmlndXJhdGlvbkNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCB7XG4gIHN1cHBvcnRlZENvbmZpZ3VyYXRpb25zOiBTdXBwb3J0ZWRDb25maWd1cmF0aW9uSXRlbVtdID0gW107XG4gIHNob3dCaW5hcnlCYXNlZENvbmZpZyA9IGZhbHNlO1xuICBjb25maWd1cmF0aW9uVHlwZTogc3RyaW5nO1xuICBjb25maWdTbmFwc2hvdDogUGFydGlhbDxDb25maWd1cmF0aW9uU25hcHNob3Q+ID0ge307XG4gIHJlcG9zaXRvcnlTbmFwc2hvdHM6IElNYW5hZ2VkT2JqZWN0W107XG4gIHJlcG9zaXRvcnlTbmFwc2hvdDogQ29uZmlndXJhdGlvblNuYXBzaG90O1xuICByZXBvc2l0b3J5U25hcHNob3RzRW1wdHlTdGF0ZTogRGV2aWNlQ29uZmlndXJhdGlvbkxpc3RFbXB0eVN0YXRlO1xuICBkZXZpY2U6IElNYW5hZ2VkT2JqZWN0O1xuICBpc0xlZ2FjeTogYm9vbGVhbjtcbiAgc2hvd1RleHRCYXNlZENvbmZpZzogYm9vbGVhbjtcbiAgcmVsb2FkaW5nID0gZmFsc2U7XG5cbiAgQFZpZXdDaGlsZChUZXh0QmFzZWRDb25maWd1cmF0aW9uQ29tcG9uZW50KVxuICB0ZXh0QmFzZWRDb25maWd1cmF0aW9uQ29tcG9uZW50OiBUZXh0QmFzZWRDb25maWd1cmF0aW9uQ29tcG9uZW50O1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgcm91dGU6IEFjdGl2YXRlZFJvdXRlLFxuICAgIHByaXZhdGUgZGV2aWNlQ29uZmlndXJhdGlvblNlcnZpY2U6IERldmljZUNvbmZpZ3VyYXRpb25TZXJ2aWNlLFxuICAgIHByaXZhdGUgcmVhbHRpbWU6IFJlYWx0aW1lLFxuICAgIHByaXZhdGUgcmVwb3NpdG9yeVNlcnZpY2U6IFJlcG9zaXRvcnlTZXJ2aWNlXG4gICkge1xuICAgIHRoaXMuZGV2aWNlQ29uZmlndXJhdGlvblNlcnZpY2UuY29uZmlndXJhdGlvbnNVcGRhdGVkLnN1YnNjcmliZShyZXBvc2l0b3J5U25hcHNPbmx5ID0+IHtcbiAgICAgIHRoaXMudXBkYXRlU25hcHNob3RzKHJlcG9zaXRvcnlTbmFwc09ubHkpO1xuICAgIH0pO1xuICB9XG5cbiAgbmdPbkluaXQoKSB7XG4gICAgdGhpcy5kZXZpY2UgPSB0aGlzLnJvdXRlLnNuYXBzaG90LnBhcmVudC5kYXRhLmNvbnRleHREYXRhO1xuICAgIGlmICh0aGlzLmRldmljZS5jOHlfU3VwcG9ydGVkQ29uZmlndXJhdGlvbnMpIHtcbiAgICAgIHRoaXMuc3VwcG9ydGVkQ29uZmlndXJhdGlvbnMgPSB0aGlzLmRldmljZS5jOHlfU3VwcG9ydGVkQ29uZmlndXJhdGlvbnMubWFwKGl0ZW0gPT4gKHtcbiAgICAgICAgbmFtZTogaXRlbVxuICAgICAgfSkpO1xuICAgIH1cblxuICAgIGlmIChcbiAgICAgIHRoaXMuZGV2aWNlQ29uZmlndXJhdGlvblNlcnZpY2UuaGFzQW55U3VwcG9ydGVkT3BlcmF0aW9uKHRoaXMuZGV2aWNlLCBbXG4gICAgICAgIERldmljZUNvbmZpZ3VyYXRpb25PcGVyYXRpb24uRE9XTkxPQURfQ09ORklHLFxuICAgICAgICBEZXZpY2VDb25maWd1cmF0aW9uT3BlcmF0aW9uLlVQTE9BRF9DT05GSUdcbiAgICAgIF0pXG4gICAgKSB7XG4gICAgICB0aGlzLnN1cHBvcnRlZENvbmZpZ3VyYXRpb25zLnB1c2goe1xuICAgICAgICBuYW1lOiBnZXR0ZXh0KCdMZWdhY3kgY29uZmlndXJhdGlvbiBzbmFwc2hvdCcpLFxuICAgICAgICBpc0xlZ2FjeTogdHJ1ZVxuICAgICAgfSk7XG4gICAgfVxuICAgIGlmICh0aGlzLnN1cHBvcnRlZENvbmZpZ3VyYXRpb25zLmxlbmd0aCA+IDApIHtcbiAgICAgIHRoaXMuc2hvd0JpbmFyeUJhc2VkQ29uZmlnID0gdHJ1ZTtcbiAgICB9XG5cbiAgICB0aGlzLnJlcG9zaXRvcnlTbmFwc2hvdHNFbXB0eVN0YXRlID0ge1xuICAgICAgaWNvbjogJ2dlYXJzJyxcbiAgICAgIHRpdGxlOiBnZXR0ZXh0KCdObyBjb25maWd1cmF0aW9ucyBhdmFpbGFibGUuJyksXG4gICAgICB0ZXh0OiBnZXR0ZXh0KCdBZGQgY29uZmlndXJhdGlvbiB0byBjb25maWd1cmF0aW9uIHJlcG9zaXRvcnknKVxuICAgIH07XG5cbiAgICB0aGlzLnNob3dUZXh0QmFzZWRDb25maWcgPVxuICAgICAgdGhpcy5kZXZpY2VDb25maWd1cmF0aW9uU2VydmljZS5oYXNBbnlTdXBwb3J0ZWRPcGVyYXRpb24odGhpcy5kZXZpY2UsIFtcbiAgICAgICAgRGV2aWNlQ29uZmlndXJhdGlvbk9wZXJhdGlvbi5DT05GSUcsXG4gICAgICAgIERldmljZUNvbmZpZ3VyYXRpb25PcGVyYXRpb24uU0VORF9DT05GSUdcbiAgICAgIF0pIHx8IGhhcyh0aGlzLmRldmljZSwgJ2M4eV9Db25maWd1cmF0aW9uJyk7XG4gIH1cblxuICBhc3luYyBvbkNvbmZpZ1R5cGVTZWxlY3RlZChjb25maWcpIHtcbiAgICB0aGlzLmNvbmZpZ3VyYXRpb25UeXBlID0gY29uZmlnLm5hbWU7XG4gICAgdGhpcy5pc0xlZ2FjeSA9IGNvbmZpZy5pc0xlZ2FjeTtcbiAgICB0aGlzLnVwZGF0ZVNuYXBzaG90cygpO1xuICB9XG5cbiAgYXN5bmMgb25SZXBvc2l0b3J5Q29uZmlnU2VsZWN0ZWQoY29uZmlnKSB7XG4gICAgdGhpcy5yZXBvc2l0b3J5U25hcHNob3QgPSB7XG4gICAgICBpZDogY29uZmlnLmlkLFxuICAgICAgdGltZTogY29uZmlnLmNyZWF0aW9uVGltZSxcbiAgICAgIG5hbWU6IGNvbmZpZy5uYW1lLFxuICAgICAgYmluYXJ5VXJsOiBjb25maWcudXJsLFxuICAgICAgZGV2aWNlVHlwZTogY29uZmlnLmRldmljZVR5cGUsXG4gICAgICBjb25maWd1cmF0aW9uVHlwZTogY29uZmlnLmNvbmZpZ3VyYXRpb25UeXBlXG4gICAgfTtcbiAgICBpZiAoY29uZmlnLnVybCkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgYmluYXJ5ID0gYXdhaXQgdGhpcy5yZXBvc2l0b3J5U2VydmljZS5nZXRCaW5hcnlGaWxlKGNvbmZpZy51cmwsIHtcbiAgICAgICAgICBhbGxvd0V4dGVybmFsOiBmYWxzZVxuICAgICAgICB9KTtcbiAgICAgICAgaWYgKGJpbmFyeSkge1xuICAgICAgICAgIHRoaXMucmVwb3NpdG9yeVNuYXBzaG90LmJpbmFyeSA9IGF3YWl0IChiaW5hcnkgYXMgYW55KS50ZXh0KCk7XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2ggKGV4KSB7XG4gICAgICAgIC8vIGRvIG5vdGhpbmdcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBhc3luYyB1cGRhdGVTbmFwc2hvdHMocmVwb3NpdG9yeVNuYXBzT25seT86IGJvb2xlYW4pIHtcbiAgICB0aGlzLnJlbG9hZGluZyA9IHRydWU7XG4gICAgdGhpcy5yZXBvc2l0b3J5U25hcHNob3QgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5yZXBvc2l0b3J5U25hcHNob3RzID0gYXdhaXQgdGhpcy5yZXBvc2l0b3J5U2VydmljZS5nZXRTbmFwc2hvdHNGcm9tUmVwb3NpdG9yeShcbiAgICAgIHRoaXMuZGV2aWNlLFxuICAgICAgdGhpcy5jb25maWd1cmF0aW9uVHlwZVxuICAgICk7XG4gICAgaWYgKCFyZXBvc2l0b3J5U25hcHNPbmx5KSB7XG4gICAgICB0aGlzLmNvbmZpZ1NuYXBzaG90ID0gdGhpcy5pc0xlZ2FjeVxuICAgICAgICA/IGF3YWl0IHRoaXMucmVwb3NpdG9yeVNlcnZpY2UuZ2V0TGVnYWN5Q29uZmlnU25hcHNob3QodGhpcy5kZXZpY2UpXG4gICAgICAgIDogYXdhaXQgdGhpcy5yZXBvc2l0b3J5U2VydmljZS5nZXRDb25maWdTbmFwc2hvdCh0aGlzLmRldmljZSwgdGhpcy5jb25maWd1cmF0aW9uVHlwZSk7XG4gICAgfVxuICAgIGlmICh0aGlzLnNob3dUZXh0QmFzZWRDb25maWcpIHtcbiAgICAgIGF3YWl0IHRoaXMudGV4dEJhc2VkQ29uZmlndXJhdGlvbkNvbXBvbmVudC5sb2FkKCk7XG4gICAgfVxuICAgIHRoaXMucmVsb2FkaW5nID0gZmFsc2U7XG4gIH1cbn1cbiIsIjxjOHktYWN0aW9uLWJhci1pdGVtIFtwbGFjZW1lbnRdPVwiJ3JpZ2h0J1wiPlxuICA8YnV0dG9uIGNsYXNzPVwiYnRuIGJ0bi1saW5rXCIgdGl0bGU9XCJ7eyAnUmVsb2FkJyB8IHRyYW5zbGF0ZSB9fVwiIChjbGljayk9XCJ1cGRhdGVTbmFwc2hvdHMoKVwiPlxuICAgIDxpIGM4eUljb249XCJyZWZyZXNoXCIgW25nQ2xhc3NdPVwieyAnaWNvbi1zcGluJzogcmVsb2FkaW5nIH1cIj48L2k+XG4gICAge3sgJ1JlbG9hZCcgfCB0cmFuc2xhdGUgfX1cbiAgPC9idXR0b24+XG48L2M4eS1hY3Rpb24tYmFyLWl0ZW0+XG5cbjxkaXYgY2xhc3M9XCJjYXJkIGNvbnRlbnQtZnVsbHBhZ2UgY2FyZC1oYXMtdGFic1wiPlxuICA8dGFic2V0PlxuICAgIDxkaXYgY2xhc3M9XCJjYXJkLWhlYWRlciBzZXBhcmF0b3JcIiAqbmdJZj1cInNob3dCaW5hcnlCYXNlZENvbmZpZyAmJiAhc2hvd1RleHRCYXNlZENvbmZpZ1wiPlxuICAgICAgPGRpdiBjbGFzcz1cImNhcmQtdGl0bGVcIj57eyAnQ29uZmlndXJhdGlvbnMnIHwgdHJhbnNsYXRlIH19PC9kaXY+XG4gICAgPC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cImNhcmQtaGVhZGVyIHNlcGFyYXRvclwiICpuZ0lmPVwiIXNob3dCaW5hcnlCYXNlZENvbmZpZyAmJiBzaG93VGV4dEJhc2VkQ29uZmlnXCI+XG4gICAgICA8ZGl2IGNsYXNzPVwiY2FyZC10aXRsZVwiPnt7ICdUZXh0LWJhc2VkIGNvbmZpZ3VyYXRpb24nIHwgdHJhbnNsYXRlIH19PC9kaXY+XG4gICAgPC9kaXY+XG4gICAgPHRhYiBoZWFkaW5nPVwie3sgJ0NvbmZpZ3VyYXRpb25zJyB8IHRyYW5zbGF0ZSB9fVwiICpuZ0lmPVwic2hvd0JpbmFyeUJhc2VkQ29uZmlnXCI+XG4gICAgICA8ZGl2IGNsYXNzPVwiY2FyZC0tZ3JpZCBjYXJkIGdyaWRfX2NvbC0tNC04LS1tZCBncmlkX19yb3ctLTYtNi0tbWQgbS1iLTBcIj5cbiAgICAgICAgPCEtLSBERVZJQ0UgU1VQUE9SVEVEIENPTkZJR1VSQVRJT05TIC0tPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiY2FyZC0tZ3JpZF9faW5uZXItc2Nyb2xsIGJnLWxldmVsLTFcIj5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwicC1sLTE2IHAtci0xNlwiPlxuICAgICAgICAgICAgPGg1IGNsYXNzPVwibGVnZW5kIGZvcm0tYmxvY2tcIj5cbiAgICAgICAgICAgICAgPHNwYW4gdHJhbnNsYXRlPkRldmljZS1zdXBwb3J0ZWQgY29uZmlndXJhdGlvbnM8L3NwYW4+XG4gICAgICAgICAgICA8L2g1PlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDxjOHktZGV2aWNlLWNvbmZpZ3VyYXRpb24tbGlzdFxuICAgICAgICAgICAgW2l0ZW1zXT1cInN1cHBvcnRlZENvbmZpZ3VyYXRpb25zXCJcbiAgICAgICAgICAgIFtpdGVtSWNvbl09XCInZ2VhcnMnXCJcbiAgICAgICAgICAgIChjb25maWdTZWxlY3RlZCk9XCJvbkNvbmZpZ1R5cGVTZWxlY3RlZCgkZXZlbnQpXCJcbiAgICAgICAgICA+PC9jOHktZGV2aWNlLWNvbmZpZ3VyYXRpb24tbGlzdD5cbiAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgPCEtLSBDT05GSUdVUkFUSU9OIFBSRVZJRVcgLS0+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJjYXJkLS1ncmlkX19pbm5lci1zY3JvbGwgZC1mbGV4IGQtY29sIGZsZXgtZ3Jvd1wiPlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJjYXJkLWJsb2NrIGQtZmxleCBkLWNvbCBmbGV4LWdyb3dcIj5cbiAgICAgICAgICAgIDxoNSBjbGFzcz1cImxlZ2VuZCBmb3JtLWJsb2NrXCI+PHNwYW4gdHJhbnNsYXRlPlByZXZpZXc8L3NwYW4+PC9oNT5cblxuICAgICAgICAgICAgPCEtLSBFTVBUWSBTVEFURSAtLT5cblxuICAgICAgICAgICAgPGM4eS11aS1lbXB0eS1zdGF0ZVxuICAgICAgICAgICAgICAqbmdJZj1cIiFjb25maWd1cmF0aW9uVHlwZVwiXG4gICAgICAgICAgICAgIFtpY29uXT1cIidmaWxlLXRleHQnXCJcbiAgICAgICAgICAgICAgW3RpdGxlXT1cIidObyBjb25maWd1cmF0aW9uIHNlbGVjdGVkLicgfCB0cmFuc2xhdGVcIlxuICAgICAgICAgICAgICBbc3VidGl0bGVdPVwiJ1NlbGVjdCBhIGNvbmZpZ3VyYXRpb24gdG8gcHJldmlldy4nIHwgdHJhbnNsYXRlXCJcbiAgICAgICAgICAgICAgW2hvcml6b250YWxdPVwidHJ1ZVwiXG4gICAgICAgICAgICA+PC9jOHktdWktZW1wdHktc3RhdGU+XG5cbiAgICAgICAgICAgIDwhLS0gUFJFVklFVyBBVkFJTEFCTEUgU1RBVEUgLS0+XG4gICAgICAgICAgICA8Yzh5LWRldmljZS1jb25maWd1cmF0aW9uLXByZXZpZXdcbiAgICAgICAgICAgICAgKm5nSWY9XCJjb25maWd1cmF0aW9uVHlwZVwiXG4gICAgICAgICAgICAgIFtkZXZpY2VdPVwiZGV2aWNlXCJcbiAgICAgICAgICAgICAgW2NvbmZpZ3VyYXRpb25UeXBlXT1cImNvbmZpZ3VyYXRpb25UeXBlXCJcbiAgICAgICAgICAgICAgW2NvbmZpZ1NuYXBzaG90XT1cImNvbmZpZ1NuYXBzaG90XCJcbiAgICAgICAgICAgICAgW2NhblNhdmVTbmFwc2hvdF09XCJ0cnVlXCJcbiAgICAgICAgICAgICAgW29wZXJhdGlvblRvVHJpZ2dlcl09XCInYzh5X1VwbG9hZENvbmZpZ0ZpbGUnXCJcbiAgICAgICAgICAgICAgW2FjdGlvbkJ1dHRvblRleHRdPVwiJ0dldCBzbmFwc2hvdCBmcm9tIGRldmljZScgfCB0cmFuc2xhdGVcIlxuICAgICAgICAgICAgICBbYWN0aW9uQnV0dG9uSWNvbl09XCInZG93bmxvYWQnXCJcbiAgICAgICAgICAgICAgW2lzTGVnYWN5XT1cImlzTGVnYWN5XCJcbiAgICAgICAgICAgICAgY2xhc3M9XCJkLWZsZXggZC1jb2wgZmxleC1ncm93XCJcbiAgICAgICAgICAgID48L2M4eS1kZXZpY2UtY29uZmlndXJhdGlvbi1wcmV2aWV3PlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cblxuICAgICAgICA8IS0tIEFWQUlMQUJMRSBTVVBQT1JURUQgQ09ORklHVVJBVElPTlMgLS0+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJjYXJkLS1ncmlkX19pbm5lci1zY3JvbGwgYmctbGV2ZWwtMVwiPlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJwLWwtMTYgcC1yLTE2XCI+XG4gICAgICAgICAgICA8aDUgY2xhc3M9XCJsZWdlbmQgZm9ybS1ibG9ja1wiIHRyYW5zbGF0ZT5BdmFpbGFibGUgc3VwcG9ydGVkIGNvbmZpZ3VyYXRpb25zPC9oNT5cbiAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgIDwhLS0gRU1QVFkgU1RBVEUgLS0+XG5cbiAgICAgICAgICA8Yzh5LXVpLWVtcHR5LXN0YXRlXG4gICAgICAgICAgICAqbmdJZj1cIiFjb25maWd1cmF0aW9uVHlwZVwiXG4gICAgICAgICAgICBbaWNvbl09XCInZ2VhcnMnXCJcbiAgICAgICAgICAgIFt0aXRsZV09XCInTm8gc2VsZWN0aW9uLicgfCB0cmFuc2xhdGVcIlxuICAgICAgICAgICAgW3N1YnRpdGxlXT1cIlxuICAgICAgICAgICAgICAnU2VsZWN0IGEgY29uZmlndXJhdGlvbiBmcm9tIHRoZSBkZXZpY2Utc3VwcG9ydGVkIGNvbmZpZ3VyYXRpb24gbGlzdC4nIHwgdHJhbnNsYXRlXG4gICAgICAgICAgICBcIlxuICAgICAgICAgICAgW2hvcml6b250YWxdPVwidHJ1ZVwiXG4gICAgICAgICAgPjwvYzh5LXVpLWVtcHR5LXN0YXRlPlxuXG4gICAgICAgICAgPGRpdiBjbGFzcz1cInAtci0xNlwiICpuZ0lmPVwiY29uZmlndXJhdGlvblR5cGVcIj5cbiAgICAgICAgICAgIDxjOHktZGV2aWNlLWNvbmZpZ3VyYXRpb24tbGlzdFxuICAgICAgICAgICAgICBbaXRlbXNdPVwicmVwb3NpdG9yeVNuYXBzaG90c1wiXG4gICAgICAgICAgICAgIFtpdGVtSWNvbl09XCInZmlsZS10ZXh0J1wiXG4gICAgICAgICAgICAgIFtlbXB0eVN0YXRlXT1cInJlcG9zaXRvcnlTbmFwc2hvdHNFbXB0eVN0YXRlXCJcbiAgICAgICAgICAgICAgW2lzRmlsdGVyRW5hYmxlZF09XCJ0cnVlXCJcbiAgICAgICAgICAgICAgKGNvbmZpZ1NlbGVjdGVkKT1cIm9uUmVwb3NpdG9yeUNvbmZpZ1NlbGVjdGVkKCRldmVudClcIlxuICAgICAgICAgICAgPjwvYzh5LWRldmljZS1jb25maWd1cmF0aW9uLWxpc3Q+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuXG4gICAgICAgIDwhLS0gQ09ORklHVVJBVElPTiBQUkVWSUVXIC0tPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiY2FyZC0tZ3JpZF9faW5uZXItc2Nyb2xsIGQtZmxleCBkLWNvbCBmbGV4LWdyb3dcIj5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiY2FyZC1ibG9jayBmbGV4LWdyb3cgZC1mbGV4IGQtY29sXCI+XG4gICAgICAgICAgICA8aDUgY2xhc3M9XCJsZWdlbmQgZm9ybS1ibG9ja1wiIHRyYW5zbGF0ZT5QcmV2aWV3PC9oNT5cblxuICAgICAgICAgICAgPCEtLSBFTVBUWSBTVEFURSAtLT5cbiAgICAgICAgICAgIDxjOHktdWktZW1wdHktc3RhdGVcbiAgICAgICAgICAgICAgKm5nSWY9XCIhcmVwb3NpdG9yeVNuYXBzaG90XCJcbiAgICAgICAgICAgICAgW2ljb25dPVwiJ2ZpbGUtdGV4dCdcIlxuICAgICAgICAgICAgICBbdGl0bGVdPVwiJ05vIGNvbmZpZ3VyYXRpb24gc2VsZWN0ZWQuJyB8IHRyYW5zbGF0ZVwiXG4gICAgICAgICAgICAgIFtzdWJ0aXRsZV09XCInU2VsZWN0IGEgY29uZmlndXJhdGlvbiB0byBwcmV2aWV3LicgfCB0cmFuc2xhdGVcIlxuICAgICAgICAgICAgICBbaG9yaXpvbnRhbF09XCJ0cnVlXCJcbiAgICAgICAgICAgID48L2M4eS11aS1lbXB0eS1zdGF0ZT5cblxuICAgICAgICAgICAgPCEtLSBDT05GSUdVUkFUSU9OIFNFTEVDVEVEIFNUQVRFIC0tPlxuICAgICAgICAgICAgPGM4eS1kZXZpY2UtY29uZmlndXJhdGlvbi1wcmV2aWV3XG4gICAgICAgICAgICAgICpuZ0lmPVwicmVwb3NpdG9yeVNuYXBzaG90XCJcbiAgICAgICAgICAgICAgW2RldmljZV09XCJkZXZpY2VcIlxuICAgICAgICAgICAgICBbY29uZmlndXJhdGlvblR5cGVdPVwiY29uZmlndXJhdGlvblR5cGVcIlxuICAgICAgICAgICAgICBbY29uZmlnU25hcHNob3RdPVwicmVwb3NpdG9yeVNuYXBzaG90XCJcbiAgICAgICAgICAgICAgW29wZXJhdGlvblRvVHJpZ2dlcl09XCInYzh5X0Rvd25sb2FkQ29uZmlnRmlsZSdcIlxuICAgICAgICAgICAgICBbYWN0aW9uQnV0dG9uVGV4dF09XCInU2VuZCBjb25maWd1cmF0aW9uIHRvIGRldmljZScgfCB0cmFuc2xhdGVcIlxuICAgICAgICAgICAgICBbYWN0aW9uQnV0dG9uSWNvbl09XCIndXBsb2FkJ1wiXG4gICAgICAgICAgICAgIFtpc0xlZ2FjeV09XCJpc0xlZ2FjeVwiXG4gICAgICAgICAgICAgIGNsYXNzPVwiZC1mbGV4IGQtY29sIGZsZXgtZ3Jvd1wiXG4gICAgICAgICAgICA+PC9jOHktZGV2aWNlLWNvbmZpZ3VyYXRpb24tcHJldmlldz5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICA8L3RhYj5cbiAgICA8dGFiIGhlYWRpbmc9XCJ7eyAnVGV4dC1iYXNlZCBjb25maWd1cmF0aW9uJyB8IHRyYW5zbGF0ZSB9fVwiICpuZ0lmPVwic2hvd1RleHRCYXNlZENvbmZpZ1wiPlxuICAgICAgPGM4eS10ZXh0LWJhc2VkLWNvbmZpZ3VyYXRpb24+PC9jOHktdGV4dC1iYXNlZC1jb25maWd1cmF0aW9uPlxuICAgIDwvdGFiPlxuICA8L3RhYnNldD5cbjwvZGl2PlxuIl19