UNPKG

@c8y/ngx-components

Version:

Angular modules for Cumulocity IoT applications

196 lines 35.7 kB
import { Component, Input } from '@angular/core'; import { DocsService } from '../docs/docs.service'; import { HelpService } from './help.service'; import * as i0 from "@angular/core"; import * as i1 from "../docs/docs.service"; import * as i2 from "./help.service"; import * as i3 from "../common/icon.directive"; import * as i4 from "../i18n/c8y-translate.directive"; import * as i5 from "@angular/common"; import * as i6 from "../common/loading.component"; import * as i7 from "ngx-bootstrap/collapse"; import * as i8 from "ngx-bootstrap/tooltip"; import * as i9 from "../action-bar/action-bar-item.component"; import * as i10 from "../product-experience/product-experience.directive"; import * as i11 from "../i18n/c8y-translate.pipe"; /** * A component which shows a context help in * the action bar. * * ```html * <c8y-help src="/docs/cockpit/working-with-dashboards/#working-with-dashboards"></c8y-help> * ``` */ export class HelpComponent { /** * @ignore Only private DI */ constructor(docsService, helpService) { this.docsService = docsService; this.helpService = helpService; /** * The source of the documentation. Used to link to the documentation as well as * to parse the source to display. */ this.src = ''; /** * Indicates if the help dialog is collapsed. */ this.isCollapsed = true; /** * The priority where the help icon should be shown in the action bar. "-Infinity" value means that priority * of this item is the lowest possible, so it will be placed at the right edge of action bar. */ this.priority = -Infinity; /** * A title. Set in open by passing the source. */ this.title = ''; /** * The section heading in the doc which is going to be displayed. */ this.sectionHeading = ''; /** * The section content in the doc which is going to be displayed. */ this.sectionContent = ''; /** * Indicates if the component is loading. */ this.isLoading = true; /** * Indicates if the component failed loading the source. */ this.hasError = false; /** * Indicates if a warning should be shown. */ this.showLangWarning = false; /** * @ignore */ this.isInit = false; } /** * The component is shown by default and therefore breaks e2e test. This is * to prevent the visibility on first navigation. * @ignore */ onCollapsed() { this.isInit = true; } /** * Builds the URL based on the src. The Base URL can be set in the application options docBaseUrl. * @param src The source of the help on the guide. * @param index This flag is used to call the index.json content of a guide. For example, "https://cumulocity.com/docs/cockpit/data-explorer/index.json". */ getUrl(src = '', index = false) { let docsUrl; try { docsUrl = typeof this.helpService.contextHelp.value === 'string' ? new URL(this.docsService.getUrlWithDocsVersion(this.helpService.contextHelp.value)) : new URL(this.docsService.getBaseUrl()); } catch (error) { docsUrl = new URL(this.docsService.getBaseUrl()); console.warn(error); } const [url, hashFragment] = src.split('#'); this.sectionHeading = hashFragment; if (index) { src = `${url}index.json`; docsUrl.pathname += src; } else { docsUrl.pathname += url; if (hashFragment) { docsUrl.hash = hashFragment; } } docsUrl.pathname = docsUrl.pathname.replace(/\/+/g, '/'); return docsUrl.href; } /** * Toggles the visibility of the help dialog. */ toggle() { if (this.isCollapsed) { this.open(); return; } this.close(); } /** * Closes the help dialog. */ close() { this.isCollapsed = true; this.clean(); } /** * Opens the help dialog. */ open() { this.isCollapsed = false; this.isLoading = true; this.requestContent(); if (!this.icon) { this.icon = this.resolveIcon(); } } requestContent() { const req = new XMLHttpRequest(); req.onreadystatechange = () => this.render(req); req.addEventListener('load', () => this.render(req)); req.open('GET', this.getUrl(this.src, true)); req.responseType = 'json'; req.setRequestHeader('Accept', 'text/html'); req.send(); } clean() { this.title = ''; this.hasError = false; this.sectionContent = ''; } resolveIcon() { try { const icon = Array.from(document.querySelector('nav .active i').classList).find(classes => classes.startsWith('c8y-icon-') || classes.startsWith('dlt-c8y-icon-')); return icon.replace('dlt-c8y-icon-', '').replace('c8y-icon-', 'c8y-'); } catch (ex) { return 'life-saver'; } } render(req) { if (req.readyState === 4) { this.isLoading = false; if (req.status === 200) { this.hasError = false; const sectionData = req.response[this.sectionHeading]; if (sectionData) { this.title = sectionData.title; this.sectionContent = sectionData.helpcontent; } } else { this.hasError = true; } } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: HelpComponent, deps: [{ token: i1.DocsService }, { token: i2.HelpService }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: HelpComponent, selector: "c8y-help", inputs: { src: "src", isCollapsed: "isCollapsed", priority: "priority", icon: "icon" }, ngImport: i0, template: "<c8y-action-bar-item\n [placement]=\"'right'\"\n itemClass=\"pull-right m-l-md-8\"\n [priority]=\"priority\"\n *ngIf=\"!!(helpService.contextHelp | async)\"\n>\n <button\n class=\"btn-help hidden-xs\"\n [attr.aria-label]=\"'About this page' | translate\"\n tooltip=\"{{ 'About this page' | translate }}\"\n placement=\"left\"\n container=\"body\"\n aria-controls=\"collapseHelp\"\n [attr.aria-expanded]=\"!isCollapsed\"\n type=\"button\"\n data-cy=\"help--help-btn\"\n [delay]=\"750\"\n (click)=\"toggle()\"\n c8yProductExperience\n [actionName]=\"isCollapsed ? 'helpOpened' : 'helpClosed'\"\n [actionData]=\"{ src: src }\"\n ></button>\n <button\n class=\"btn btn-link visible-xs\"\n title=\"{{ 'About this page' | translate }}\"\n aria-controls=\"collapseHelp\"\n [attr.aria-expanded]=\"!isCollapsed\"\n type=\"button\"\n (click)=\"toggle()\"\n c8yProductExperience\n [actionName]=\"isCollapsed ? 'helpOpened' : 'helpClosed'\"\n [actionData]=\"{ src: src }\"\n >\n <i c8yIcon=\"help-outline\" class=\"text-info\"></i>\n {{ 'About this page' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<div\n class=\"c8y-help-drawer\"\n id=\"collapseHelp\"\n [collapse]=\"isCollapsed\"\n [isAnimated]=\"true\"\n (collapsed)=\"onCollapsed()\"\n>\n <div\n [ngClass]=\"{ 'c8y-help-drawer-block': isInit }\"\n #docOutlet\n data-cy=\"c8y-help--c8y-help-drawer-block\"\n >\n <div *ngIf=\"isLoading\">\n <c8y-loading></c8y-loading>\n </div>\n\n <div *ngIf=\"!isLoading\">\n <div class=\"d-flex\">\n <i\n class=\"c8y-icon-duocolor icon-48\"\n [c8yIcon]=\"!hasError ? icon : 'unlink'\"\n [ngClass]=\"{ 'text-warning': hasError, 'text-muted': !hasError }\"\n ></i>\n <div\n class=\"p-l-16 flex-grow\"\n *ngIf=\"!hasError\"\n >\n <div\n class=\"alert alert-info m-b-16\"\n *ngIf=\"\n !helpService.isSupportedLanguage() &&\n !showLangWarning &&\n !helpService.isWarningAlertViewed\n \"\n >\n <button\n class=\"close\"\n [attr.aria-label]=\"'Close' | translate\"\n type=\"button\"\n (click)=\"\n showLangWarning = !showLangWarning;\n helpService.isWarningAlertViewed = !helpService.isWarningAlertViewed\n \"\n >\n <span aria-hidden=\"true\">\u00D7</span>\n <span class=\"sr-only\">Close</span>\n </button>\n <p>\n {{ 'Help content is only available in English.' | translate }}\n </p>\n </div>\n <h4 class=\"text-bold text-primary p-t-16 m-b-16\">\n {{ title }}\n </h4>\n <div\n class=\"help-content\"\n id=\"helpContent\"\n [innerHTML]=\"sectionContent\"\n data-cy=\"help--c8y-help-content\"\n ></div>\n </div>\n\n <div\n class=\"p-l-16 p-t-16 flex-grow\"\n *ngIf=\"hasError\"\n >\n <h4\n class=\"text-bold m-b-16\"\n translate\n >\n Content couldn't be loaded.\n </h4>\n <div class=\"help-content\">\n <p translate>Check internet connection or reload page.</p>\n </div>\n </div>\n </div>\n </div>\n </div>\n <div\n class=\"c8y-help-drawer-footer animated fadeIn\"\n style=\"animation-delay: 0.35s\"\n *ngIf=\"!isLoading && !hasError\"\n data-cy=\"c8y-help--c8y-help-drawer-footer\"\n >\n <button\n class=\"btn btn-default\"\n [title]=\"'Close help' | translate\"\n aria-controls=\"collapseHelp\"\n [attr.aria-expanded]=\"!isCollapsed\"\n type=\"button\"\n (click)=\"toggle()\"\n translate\n >\n Close\n </button>\n <a\n class=\"btn btn-primary\"\n href=\"{{ hasError ? getUrl() : getUrl(src) }}\"\n target=\"_blank\"\n data-cy=\"c8y-help--user-guide\"\n rel=\"noopener noreferrer\"\n >\n <span\n translate\n *ngIf=\"!hasError\"\n >\n Open the\n <span>user documentation</span>\n </span>\n <span\n translate\n *ngIf=\"hasError\"\n >\n Check the\n <span>user documentation</span>\n </span>\n </a>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: i3.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: i4.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { 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.LoadingComponent, selector: "c8y-loading", inputs: ["layout", "progress", "message"] }, { kind: "directive", type: i7.CollapseDirective, selector: "[collapse]", inputs: ["display", "isAnimated", "collapse"], outputs: ["collapsed", "collapses", "expanded", "expands"], exportAs: ["bs-collapse"] }, { kind: "directive", type: i8.TooltipDirective, selector: "[tooltip], [tooltipHtml]", inputs: ["adaptivePosition", "tooltip", "placement", "triggers", "container", "containerClass", "boundariesElement", "isOpen", "isDisabled", "delay", "tooltipHtml", "tooltipPlacement", "tooltipIsOpen", "tooltipEnable", "tooltipAppendToBody", "tooltipAnimation", "tooltipClass", "tooltipContext", "tooltipPopupDelay", "tooltipFadeDuration", "tooltipTrigger"], outputs: ["tooltipChange", "onShown", "onHidden", "tooltipStateChanged"], exportAs: ["bs-tooltip"] }, { kind: "component", type: i9.ActionBarItemComponent, selector: "c8y-action-bar-item", inputs: ["placement", "priority", "itemClass", "injector", "groupId", "inGroupPriority"] }, { kind: "directive", type: i10.ProductExperienceDirective, selector: "[c8yProductExperience]", inputs: ["actionName", "actionData", "inherit", "suppressDataOverriding"] }, { kind: "pipe", type: i11.C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: HelpComponent, decorators: [{ type: Component, args: [{ selector: 'c8y-help', template: "<c8y-action-bar-item\n [placement]=\"'right'\"\n itemClass=\"pull-right m-l-md-8\"\n [priority]=\"priority\"\n *ngIf=\"!!(helpService.contextHelp | async)\"\n>\n <button\n class=\"btn-help hidden-xs\"\n [attr.aria-label]=\"'About this page' | translate\"\n tooltip=\"{{ 'About this page' | translate }}\"\n placement=\"left\"\n container=\"body\"\n aria-controls=\"collapseHelp\"\n [attr.aria-expanded]=\"!isCollapsed\"\n type=\"button\"\n data-cy=\"help--help-btn\"\n [delay]=\"750\"\n (click)=\"toggle()\"\n c8yProductExperience\n [actionName]=\"isCollapsed ? 'helpOpened' : 'helpClosed'\"\n [actionData]=\"{ src: src }\"\n ></button>\n <button\n class=\"btn btn-link visible-xs\"\n title=\"{{ 'About this page' | translate }}\"\n aria-controls=\"collapseHelp\"\n [attr.aria-expanded]=\"!isCollapsed\"\n type=\"button\"\n (click)=\"toggle()\"\n c8yProductExperience\n [actionName]=\"isCollapsed ? 'helpOpened' : 'helpClosed'\"\n [actionData]=\"{ src: src }\"\n >\n <i c8yIcon=\"help-outline\" class=\"text-info\"></i>\n {{ 'About this page' | translate }}\n </button>\n</c8y-action-bar-item>\n\n<div\n class=\"c8y-help-drawer\"\n id=\"collapseHelp\"\n [collapse]=\"isCollapsed\"\n [isAnimated]=\"true\"\n (collapsed)=\"onCollapsed()\"\n>\n <div\n [ngClass]=\"{ 'c8y-help-drawer-block': isInit }\"\n #docOutlet\n data-cy=\"c8y-help--c8y-help-drawer-block\"\n >\n <div *ngIf=\"isLoading\">\n <c8y-loading></c8y-loading>\n </div>\n\n <div *ngIf=\"!isLoading\">\n <div class=\"d-flex\">\n <i\n class=\"c8y-icon-duocolor icon-48\"\n [c8yIcon]=\"!hasError ? icon : 'unlink'\"\n [ngClass]=\"{ 'text-warning': hasError, 'text-muted': !hasError }\"\n ></i>\n <div\n class=\"p-l-16 flex-grow\"\n *ngIf=\"!hasError\"\n >\n <div\n class=\"alert alert-info m-b-16\"\n *ngIf=\"\n !helpService.isSupportedLanguage() &&\n !showLangWarning &&\n !helpService.isWarningAlertViewed\n \"\n >\n <button\n class=\"close\"\n [attr.aria-label]=\"'Close' | translate\"\n type=\"button\"\n (click)=\"\n showLangWarning = !showLangWarning;\n helpService.isWarningAlertViewed = !helpService.isWarningAlertViewed\n \"\n >\n <span aria-hidden=\"true\">\u00D7</span>\n <span class=\"sr-only\">Close</span>\n </button>\n <p>\n {{ 'Help content is only available in English.' | translate }}\n </p>\n </div>\n <h4 class=\"text-bold text-primary p-t-16 m-b-16\">\n {{ title }}\n </h4>\n <div\n class=\"help-content\"\n id=\"helpContent\"\n [innerHTML]=\"sectionContent\"\n data-cy=\"help--c8y-help-content\"\n ></div>\n </div>\n\n <div\n class=\"p-l-16 p-t-16 flex-grow\"\n *ngIf=\"hasError\"\n >\n <h4\n class=\"text-bold m-b-16\"\n translate\n >\n Content couldn't be loaded.\n </h4>\n <div class=\"help-content\">\n <p translate>Check internet connection or reload page.</p>\n </div>\n </div>\n </div>\n </div>\n </div>\n <div\n class=\"c8y-help-drawer-footer animated fadeIn\"\n style=\"animation-delay: 0.35s\"\n *ngIf=\"!isLoading && !hasError\"\n data-cy=\"c8y-help--c8y-help-drawer-footer\"\n >\n <button\n class=\"btn btn-default\"\n [title]=\"'Close help' | translate\"\n aria-controls=\"collapseHelp\"\n [attr.aria-expanded]=\"!isCollapsed\"\n type=\"button\"\n (click)=\"toggle()\"\n translate\n >\n Close\n </button>\n <a\n class=\"btn btn-primary\"\n href=\"{{ hasError ? getUrl() : getUrl(src) }}\"\n target=\"_blank\"\n data-cy=\"c8y-help--user-guide\"\n rel=\"noopener noreferrer\"\n >\n <span\n translate\n *ngIf=\"!hasError\"\n >\n Open the\n <span>user documentation</span>\n </span>\n <span\n translate\n *ngIf=\"hasError\"\n >\n Check the\n <span>user documentation</span>\n </span>\n </a>\n </div>\n</div>\n" }] }], ctorParameters: () => [{ type: i1.DocsService }, { type: i2.HelpService }], propDecorators: { src: [{ type: Input }], isCollapsed: [{ type: Input }], priority: [{ type: Input }], icon: [{ type: Input }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGVscC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9jb3JlL2hlbHAvaGVscC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi9jb3JlL2hlbHAvaGVscC5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNqRCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDbkQsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLGdCQUFnQixDQUFDOzs7Ozs7Ozs7Ozs7O0FBRTdDOzs7Ozs7O0dBT0c7QUFLSCxNQUFNLE9BQU8sYUFBYTtJQThEeEI7O09BRUc7SUFDSCxZQUNVLFdBQXdCLEVBQ3pCLFdBQXdCO1FBRHZCLGdCQUFXLEdBQVgsV0FBVyxDQUFhO1FBQ3pCLGdCQUFXLEdBQVgsV0FBVyxDQUFhO1FBbEVqQzs7O1dBR0c7UUFFSCxRQUFHLEdBQUcsRUFBRSxDQUFDO1FBRVQ7O1dBRUc7UUFFSCxnQkFBVyxHQUFHLElBQUksQ0FBQztRQUVuQjs7O1dBR0c7UUFFSCxhQUFRLEdBQUcsQ0FBQyxRQUFRLENBQUM7UUFRckI7O1dBRUc7UUFDSCxVQUFLLEdBQUcsRUFBRSxDQUFDO1FBRVg7O1dBRUc7UUFDSCxtQkFBYyxHQUFHLEVBQUUsQ0FBQztRQUVwQjs7V0FFRztRQUNILG1CQUFjLEdBQUcsRUFBRSxDQUFDO1FBRXBCOztXQUVHO1FBQ0gsY0FBUyxHQUFHLElBQUksQ0FBQztRQUVqQjs7V0FFRztRQUNILGFBQVEsR0FBRyxLQUFLLENBQUM7UUFFakI7O1dBRUc7UUFDSCxvQkFBZSxHQUFHLEtBQUssQ0FBQztRQUV4Qjs7V0FFRztRQUNILFdBQU0sR0FBRyxLQUFLLENBQUM7SUFRWixDQUFDO0lBRUo7Ozs7T0FJRztJQUNILFdBQVc7UUFDVCxJQUFJLENBQUMsTUFBTSxHQUFHLElBQUks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LFdBQVcsRUFBRSxDQUFDO29CQUNoQixJQUFJLENBQUMsS0FBSyxHQUFHLFdBQVcsQ0FBQyxLQUFLLENBQUM7b0JBQy9CLElBQUksQ0FBQyxjQUFjLEdBQUcsV0FBVyxDQUFDLFdBQVcsQ0FBQztnQkFDaEQsQ0FBQztZQUNILENBQUM7aUJBQU0sQ0FBQztnQkFDTixJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQztZQUN2QixDQUFDO1FBQ0gsQ0FBQztJQUNILENBQUM7K0dBMUxVLGFBQWE7bUdBQWIsYUFBYSx3SUNoQjFCLGk1SUE4SkE7OzRGRDlJYSxhQUFhO2tCQUp6QixTQUFTOytCQUNFLFVBQVU7MEdBU3BCLEdBQUc7c0JBREYsS0FBSztnQkFPTixXQUFXO3NCQURWLEtBQUs7Z0JBUU4sUUFBUTtzQkFEUCxLQUFLO2dCQU9OLElBQUk7c0JBREgsS0FBSyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgSW5wdXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IERvY3NTZXJ2aWNlIH0gZnJvbSAnLi4vZG9jcy9kb2NzLnNlcnZpY2UnO1xuaW1wb3J0IHsgSGVscFNlcnZpY2UgfSBmcm9tICcuL2hlbHAuc2VydmljZSc7XG5cbi8qKlxuICogQSBjb21wb25lbnQgd2hpY2ggc2hvd3MgYSBjb250ZXh0IGhlbHAgaW5cbiAqIHRoZSBhY3Rpb24gYmFyLlxuICpcbiAqIGBgYGh0bWxcbiAqIDxjOHktaGVscCBzcmM9XCIvZG9jcy9jb2NrcGl0L3dvcmtpbmctd2l0aC1kYXNoYm9hcmRzLyN3b3JraW5nLXdpdGgtZGFzaGJvYXJkc1wiPjwvYzh5LWhlbHA+XG4gKiBgYGBcbiAqL1xuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnYzh5LWhlbHAnLFxuICB0ZW1wbGF0ZVVybDogJy4vaGVscC5jb21wb25lbnQuaHRtbCdcbn0pXG5leHBvcnQgY2xhc3MgSGVscENvbXBvbmVudCB7XG4gIC8qKlxuICAgKiBUaGUgc291cmNlIG9mIHRoZSBkb2N1bWVudGF0aW9uLiBVc2VkIHRvIGxpbmsgdG8gdGhlIGRvY3VtZW50YXRpb24gYXMgd2VsbCBhc1xuICAgKiB0byBwYXJzZSB0aGUgc291cmNlIHRvIGRpc3BsYXkuXG4gICAqL1xuICBASW5wdXQoKVxuICBzcmMgPSAnJztcblxuICAvKipcbiAgICogSW5kaWNhdGVzIGlmIHRoZSBoZWxwIGRpYWxvZyBpcyBjb2xsYXBzZWQuXG4gICAqL1xuICBASW5wdXQoKVxuICBpc0NvbGxhcHNlZCA9IHRydWU7XG5cbiAgLyoqXG4gICAqIFRoZSBwcmlvcml0eSB3aGVyZSB0aGUgaGVscCBpY29uIHNob3VsZCBiZSBzaG93biBpbiB0aGUgYWN0aW9uIGJhci4gXCItSW5maW5pdHlcIiB2YWx1ZSBtZWFucyB0aGF0IHByaW9yaXR5XG4gICAqIG9mIHRoaXMgaXRlbSBpcyB0aGUgbG93ZXN0IHBvc3NpYmxlLCBzbyBpdCB3aWxsIGJlIHBsYWNlZCBhdCB0aGUgcmlnaHQgZWRnZSBvZiBhY3Rpb24gYmFyLlxuICAgKi9cbiAgQElucHV0KClcbiAgcHJpb3JpdHkgPSAtSW5maW5pdHk7XG5cbiAgLyoqXG4gICAqIEEgY3VzdG9tIGljb24uIElmIG5vdCBzZXQsIHRoZSBuYXZpZ2F0b3IgaWNvbiBpcyByZXNvbHZlZFxuICAgKi9cbiAgQElucHV0KClcbiAgaWNvbjtcblxuICAvKipcbiAgICogQSB0aXRsZS4gU2V0IGluIG9wZW4gYnkgcGFzc2luZyB0aGUgc291cmNlLlxuICAgKi9cbiAgdGl0bGUgPSAnJztcblxuICAvKipcbiAgICogVGhlIHNlY3Rpb24gaGVhZGluZyBpbiB0aGUgZG9jIHdoaWNoIGlzIGdvaW5nIHRvIGJlIGRpc3BsYXllZC5cbiAgICovXG4gIHNlY3Rpb25IZWFkaW5nID0gJyc7XG5cbiAgLyoqXG4gICAqIFRoZSBzZWN0aW9uIGNvbnRlbnQgaW4gdGhlIGRvYyB3aGljaCBpcyBnb2luZyB0byBiZSBkaXNwbGF5ZWQuXG4gICAqL1xuICBzZWN0aW9uQ29udGVudCA9ICcnO1xuXG4gIC8qKlxuICAgKiBJbmRpY2F0ZXMgaWYgdGhlIGNvbXBvbmVudCBpcyBsb2FkaW5nLlxuICAgKi9cbiAgaXNMb2FkaW5nID0gdHJ1ZTtcblxuICAvKipcbiAgICogSW5kaWNhdGVzIGlmIHRoZSBjb21wb25lbnQgZmFpbGVkIGxvYWRpbmcgdGhlIHNvdXJjZS5cbiAgICovXG4gIGhhc0Vycm9yID0gZmFsc2U7XG5cbiAgLyoqXG4gICAqIEluZGljYXRlcyBpZiBhIHdhcm5pbmcgc2hvdWxkIGJlIHNob3duLlxuICAgKi9cbiAgc2hvd0xhbmdXYXJuaW5nID0gZmFsc2U7XG5cbiAgLyoqXG4gICAqIEBpZ25vcmVcbiAgICovXG4gIGlzSW5pdCA9IGZhbHNlO1xuXG4gIC8qKlxuICAgKiBAaWdub3JlIE9ubHkgcHJpdmF0ZSBESVxuICAgKi9cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBkb2NzU2VydmljZTogRG9jc1NlcnZpY2UsXG4gICAgcHVibGljIGhlbHBTZXJ2aWNlOiBIZWxwU2VydmljZVxuICApIHt9XG5cbiAgLyoqXG4gICAqIFRoZSBjb21wb25lbnQgaXMgc2hvd24gYnkgZGVmYXVsdCBhbmQgdGhlcmVmb3JlIGJyZWFrcyBlMmUgdGVzdC4gVGhpcyBpc1xuICAgKiB0byBwcmV2ZW50IHRoZSB2aXNpYmlsaXR5IG9uIGZpcnN0IG5hdmlnYXRpb24uXG4gICAqIEBpZ25vcmVcbiAgICovXG4gIG9uQ29sbGFwc2VkKCkge1xuICAgIHRoaXMuaXNJbml0ID0gdHJ1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBCdWlsZHMgdGhlIFVSTCBiYXNlZCBvbiB0aGUgc3JjLiBUaGUgQmFzZSBVUkwgY2FuIGJlIHNldCBpbiB0aGUgYXBwbGljYXRpb24gb3B0aW9ucyBkb2NCYXNlVXJsLlxuICAgKiBAcGFyYW0gc3JjIFRoZSBzb3VyY2Ugb2YgdGhlIGhlbHAgb24gdGhlIGd1aWRlLlxuICAgKiBAcGFyYW0gaW5kZXggVGhpcyBmbGFnIGlzIHVzZWQgdG8gY2FsbCB0aGUgaW5kZXguanNvbiBjb250ZW50IG9mIGEgZ3VpZGUuIEZvciBleGFtcGxlLCBcImh0dHBzOi8vY3VtdWxvY2l0eS5jb20vZG9jcy9jb2NrcGl0L2RhdGEtZXhwbG9yZXIvaW5kZXguanNvblwiLlxuICAgKi9cbiAgZ2V0VXJsKHNyYyA9ICcnLCBpbmRleCA9IGZhbHNlKTogc3RyaW5nIHtcbiAgICBsZXQgZG9jc1VybDogVVJMO1xuXG4gICAgdHJ5IHtcbiAgICAgIGRvY3NVcmwgPVxuICAgICAgICB0eXBlb2YgdGhpcy5oZWxwU2VydmljZS5jb250ZXh0SGVscC52YWx1ZSA9PT0gJ3N0cmluZydcbiAgICAgICAgICA/IG5ldyBVUkwodGhpcy5kb2NzU2VydmljZS5nZXRVcmxXaXRoRG9jc1ZlcnNpb24odGhpcy5oZWxwU2VydmljZS5jb250ZXh0SGVscC52YWx1ZSkpXG4gICAgICAgICAgOiBuZXcgVVJMKHRoaXMuZG9jc1NlcnZpY2UuZ2V0QmFzZVVybCgpKTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgZG9jc1VybCA9IG5ldyBVUkwodGhpcy5kb2NzU2VydmljZS5nZXRCYXNlVXJsKCkpO1xuICAgICAgY29uc29sZS53YXJuKGVycm9yKTtcbiAgICB9XG5cbiAgICBjb25zdCBbdXJsLCBoYXNoRnJhZ21lbnRdID0gc3JjLnNwbGl0KCcjJyk7XG4gICAgdGhpcy5zZWN0aW9uSGVhZGluZyA9IGhhc2hGcmFnbWVudDtcblxuICAgIGlmIChpbmRleCkge1xuICAgICAgc3JjID0gYCR7dXJsfWluZGV4Lmpzb25gO1xuICAgICAgZG9jc1VybC5wYXRobmFtZSArPSBzcmM7XG4gICAgfSBlbHNlIHtcbiAgICAgIGRvY3NVcmwucGF0aG5hbWUgKz0gdXJsO1xuICAgICAgaWYgKGhhc2hGcmFnbWVudCkge1xuICAgICAgICBkb2NzVXJsLmhhc2ggPSBoYXNoRnJhZ21lbnQ7XG4gICAgICB9XG4gICAgfVxuXG4gICAgZG9jc1VybC5wYXRobmFtZSA9IGRvY3NVcmwucGF0aG5hbWUucmVwbGFjZSgvXFwvKy9nLCAnLycpO1xuICAgIHJldHVybiBkb2NzVXJsLmhyZWY7XG4gIH1cblxuICAvKipcbiAgICogVG9nZ2xlcyB0aGUgdmlzaWJpbGl0eSBvZiB0aGUgaGVscCBkaWFsb2cuXG4gICAqL1xuICB0b2dnbGUoKSB7XG4gICAgaWYgKHRoaXMuaXNDb2xsYXBzZWQpIHtcbiAgICAgIHRoaXMub3BlbigpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLmNsb3NlKCk7XG4gIH1cblxuICAvKipcbiAgICogQ2xvc2VzIHRoZSBoZWxwIGRpYWxvZy5cbiAgICovXG4gIGNsb3NlKCkge1xuICAgIHRoaXMuaXNDb2xsYXBzZWQgPSB0cnVlO1xuICAgIHRoaXMuY2xlYW4oKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBPcGVucyB0aGUgaGVscCBkaWFsb2cuXG4gICAqL1xuICBvcGVuKCkge1xuICAgIHRoaXMuaXNDb2xsYXBzZWQgPSBmYWxzZTtcbiAgICB0aGlzLmlzTG9hZGluZyA9IHRydWU7XG4gICAgdGhpcy5yZXF1ZXN0Q29udGVudCgpO1xuICAgIGlmICghdGhpcy5pY29uKSB7XG4gICAgICB0aGlzLmljb24gPSB0aGlzLnJlc29sdmVJY29uKCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSByZXF1ZXN0Q29udGVudCgpIHtcbiAgICBjb25zdCByZXEgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTtcbiAgICByZXEub25yZWFkeXN0YXRlY2hhbmdlID0gKCkgPT4gdGhpcy5yZW5kZXIocmVxKTtcbiAgICByZXEuYWRkRXZlbnRMaXN0ZW5lcignbG9hZCcsICgpID0+IHRoaXMucmVuZGVyKHJlcSkpO1xuICAgIHJlcS5vcGVuKCdHRVQnLCB0aGlzLmdldFVybCh0aGlzLnNyYywgdHJ1ZSkpO1xuICAgIHJlcS5yZXNwb25zZVR5cGUgPSAnanNvbic7XG4gICAgcmVxLnNldFJlcXVlc3RIZWFkZXIoJ0FjY2VwdCcsICd0ZXh0L2h0bWwnKTtcbiAgICByZXEuc2VuZCgpO1xuICB9XG5cbiAgcHJpdmF0ZSBjbGVhbigpIHtcbiAgICB0aGlzLnRpdGxlID0gJyc7XG4gICAgdGhpcy5oYXNFcnJvciA9IGZhbHNlO1xuICAgIHRoaXMuc2VjdGlvbkNvbnRlbnQgPSAnJztcbiAgfVxuXG4gIHByaXZhdGUgcmVzb2x2ZUljb24oKSB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGljb24gPSBBcnJheS5mcm9tKGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJ25hdiAuYWN0aXZlIGknKS5jbGFzc0xpc3QpLmZpbmQoXG4gICAgICAgIGNsYXNzZXMgPT4gY2xhc3Nlcy5zdGFydHNXaXRoKCdjOHktaWNvbi0nKSB8fCBjbGFzc2VzLnN0YXJ0c1dpdGgoJ2RsdC1jOHktaWNvbi0nKVxuICAgICAgKTtcbiAgICAgIHJldHVybiBpY29uLnJlcGxhY2UoJ2RsdC1jOHktaWNvbi0nLCAnJykucmVwbGFjZSgnYzh5LWljb24tJywgJ2M4eS0nKTtcbiAgICB9IGNhdGNoIChleCkge1xuICAgICAgcmV0dXJuICdsaWZlLXNhdmVyJztcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHJlbmRlcihyZXE6IFhNTEh0dHBSZXF1ZXN0KSB7XG4gICAgaWYgKHJlcS5yZWFkeVN0YXRlID09PSA0KSB7XG4gICAgICB0aGlzLmlzTG9hZGluZyA9IGZhbHNlO1xuICAgICAgaWYgKHJlcS5zdGF0dXMgPT09IDIwMCkge1xuICAgICAgICB0aGlzLmhhc0Vycm9yID0gZmFsc2U7XG4gICAgICAgIGNvbnN0IHNlY3Rpb25EYXRhID0gcmVxLnJlc3BvbnNlW3RoaXMuc2VjdGlvbkhlYWRpbmddO1xuICAgICAgICBpZiAoc2VjdGlvbkRhdGEpIHtcbiAgICAgICAgICB0aGlzLnRpdGxlID0gc2VjdGlvbkRhdGEudGl0bGU7XG4gICAgICAgICAgdGhpcy5zZWN0aW9uQ29udGVudCA9IHNlY3Rpb25EYXRhLmhlbHBjb250ZW50O1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLmhhc0Vycm9yID0gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cbiIsIjxjOHktYWN0aW9uLWJhci1pdGVtXG4gIFtwbGFjZW1lbnRdPVwiJ3JpZ2h0J1wiXG4gIGl0ZW1DbGFzcz1cInB1bGwtcmlnaHQgbS1sLW1kLThcIlxuICBbcHJpb3JpdHldPVwicHJpb3JpdHlcIlxuICAqbmdJZj1cIiEhKGhlbHBTZXJ2aWNlLmNvbnRleHRIZWxwIHwgYXN5bmMpXCJcbj5cbiAgPGJ1dHRvblxuICAgIGNsYXNzPVwiYnRuLWhlbHAgaGlkZGVuLXhzXCJcbiAgICBbYXR0ci5hcmlhLWxhYmVsXT1cIidBYm91dCB0aGlzIHBhZ2UnIHwgdHJhbnNsYXRlXCJcbiAgICB0b29sdGlwPVwie3sgJ0Fib3V0IHRoaXMgcGFnZScgfCB0cmFuc2xhdGUgfX1cIlxuICAgIHBsYWNlbWVudD1cImxlZnRcIlxuICAgIGNvbnRhaW5lcj1cImJvZHlcIlxuICAgIGFyaWEtY29udHJvbHM9XCJjb2xsYXBzZUhlbHBcIlxuICAgIFthdHRyLmFyaWEtZXhwYW5kZWRdPVwiIWlzQ29sbGFwc2VkXCJcbiAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICBkYXRhLWN5PVwiaGVscC0taGVscC1idG5cIlxuICAgIFtkZWxheV09XCI3NTBcIlxuICAgIChjbGljayk9XCJ0b2dnbGUoKVwiXG4gICAgYzh5UHJvZHVjdEV4cGVyaWVuY2VcbiAgICBbYWN0aW9uTmFtZV09XCJpc0NvbGxhcHNlZCA/ICdoZWxwT3BlbmVkJyA6ICdoZWxwQ2xvc2VkJ1wiXG4gICAgW2FjdGlvbkRhdGFdPVwieyBzcmM6IHNyYyB9XCJcbiAgPjwvYnV0dG9uPlxuICA8YnV0dG9uXG4gICAgY2xhc3M9XCJidG4gYnRuLWxpbmsgdmlzaWJsZS14c1wiXG4gICAgdGl0bGU9XCJ7eyAnQWJvdXQgdGhpcyBwYWdlJyB8IHRyYW5zbGF0ZSB9fVwiXG4gICAgYXJpYS1jb250cm9scz1cImNvbGxhcHNlSGVscFwiXG4gICAgW2F0dHIuYXJpYS1leHBhbmRlZF09XCIhaXNDb2xsYXBzZWRcIlxuICAgIHR5cGU9XCJidXR0b25cIlxuICAgIChjbGljayk9XCJ0b2dnbGUoKVwiXG4gICAgYzh5UHJvZHVjdEV4cGVyaWVuY2VcbiAgICBbYWN0aW9uTmFtZV09XCJpc0NvbGxhcHNlZCA/ICdoZWxwT3BlbmVkJyA6ICdoZWxwQ2xvc2VkJ1wiXG4gICAgW2FjdGlvbkRhdGFdPVwieyBzcmM6IHNyYyB9XCJcbiAgPlxuICAgIDxpIGM4eUljb249XCJoZWxwLW91dGxpbmVcIiBjbGFzcz1cInRleHQtaW5mb1wiPjwvaT5cbiAgICB7eyAnQWJvdXQgdGhpcyBwYWdlJyB8IHRyYW5zbGF0ZSB9fVxuICA8L2J1dHRvbj5cbjwvYzh5LWFjdGlvbi1iYXItaXRlbT5cblxuPGRpdlxuICBjbGFzcz1cImM4eS1oZWxwLWRyYXdlclwiXG4gIGlkPVwiY29sbGFwc2VIZWxwXCJcbiAgW2NvbGxhcHNlXT1cImlzQ29sbGFwc2VkXCJcbiAgW2lzQW5pbWF0ZWRdPVwidHJ1ZVwiXG4gIChjb2xsYXBzZWQpPVwib25Db2xsYXBzZWQoKVwiXG4+XG4gIDxkaXZcbiAgICBbbmdDbGFzc109XCJ7ICdjOHktaGVscC1kcmF3ZXItYmxvY2snOiBpc0luaXQgfVwiXG4gICAgI2RvY091dGxldFxuICAgIGRhdGEtY3k9XCJjOHktaGVscC0tYzh5LWhlbHAtZHJhd2VyLWJsb2NrXCJcbiAgPlxuICAgIDxkaXYgKm5nSWY9XCJpc0xvYWRpbmdcIj5cbiAgICAgIDxjOHktbG9hZGluZz48L2M4eS1sb2FkaW5nPlxuICAgIDwvZGl2PlxuXG4gICAgPGRpdiAqbmdJZj1cIiFpc0xvYWRpbmdcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJkLWZsZXhcIj5cbiAgICAgICAgPGlcbiAgICAgICAgICBjbGFzcz1cImM4eS1pY29uLWR1b2NvbG9yIGljb24tNDhcIlxuICAgICAgICAgIFtjOHlJY29uXT1cIiFoYXNFcnJvciA/IGljb24gOiAndW5saW5rJ1wiXG4gICAgICAgICAgW25nQ2xhc3NdPVwieyAndGV4dC13YXJuaW5nJzogaGFzRXJyb3IsICd0ZXh0LW11dGVkJzogIWhhc0Vycm9yIH1cIlxuICAgICAgICA+PC9pPlxuICAgICAgICA8ZGl2XG4gICAgICAgICAgY2xhc3M9XCJwLWwtMTYgZmxleC1ncm93XCJcbiAgICAgICAgICAqbmdJZj1cIiFoYXNFcnJvclwiXG4gICAgICAgID5cbiAgICAgICAgICA8ZGl2XG4gICAgICAgICAgICBjbGFzcz1cImFsZXJ0IGFsZXJ0LWluZm8gbS1iLTE2XCJcbiAgICAgICAgICAgICpuZ0lmPVwiXG4gICAgICAgICAgICAgICFoZWxwU2VydmljZS5pc1N1cHBvcnRlZExhbmd1YWdlKCkgJiZcbiAgICAgICAgICAgICAgIXNob3dMYW5nV2FybmluZyAmJlxuICAgICAgICAgICAgICAhaGVscFNlcnZpY2UuaXNXYXJuaW5nQWxlcnRWaWV3ZWRcbiAgICAgICAgICAgIFwiXG4gICAgICAgICAgPlxuICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICBjbGFzcz1cImNsb3NlXCJcbiAgICAgICAgICAgICAgW2F0dHIuYXJpYS1sYWJlbF09XCInQ2xvc2UnIHwgdHJhbnNsYXRlXCJcbiAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAgIChjbGljayk9XCJcbiAgICAgICAgICAgICAgICBzaG93TGFuZ1dhcm5pbmcgPSAhc2hvd0xhbmdXYXJuaW5nO1xuICAgICAgICAgICAgICAgIGhlbHBTZXJ2aWNlLmlzV2FybmluZ0FsZXJ0Vmlld2VkID0gIWhlbHBTZXJ2aWNlLmlzV2FybmluZ0FsZXJ0Vmlld2VkXG4gICAgICAgICAgICAgIFwiXG4gICAgICAgICAgICA+XG4gICAgICAgICAgICAgIDxzcGFuIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPsOXPC9zcGFuPlxuICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cInNyLW9ubHlcIj5DbG9zZTwvc3Bhbj5cbiAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgPHA+XG4gICAgICAgICAgICAgIHt7ICdIZWxwIGNvbnRlbnQgaXMgb25seSBhdmFpbGFibGUgaW4gRW5nbGlzaC4nIHwgdHJhbnNsYXRlIH19XG4gICAgICAgICAgICA8L3A+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPGg0IGNsYXNzPVwidGV4dC1ib2xkIHRleHQtcHJpbWFyeSBwLXQtMTYgbS1iLTE2XCI+XG4gICAgICAgICAgICB7eyB0aXRsZSB9fVxuICAgICAgICAgIDwvaDQ+XG4gICAgICAgICAgPGRpdlxuICAgICAgICAgICAgY2xhc3M9XCJoZWxwLWNvbnRlbnRcIlxuICAgICAgICAgICAgaWQ9XCJoZWxwQ29udGVudFwiXG4gICAgICAgICAgICBbaW5uZXJIVE1MXT1cInNlY3Rpb25Db250ZW50XCJcbiAgICAgICAgICAgIGRhdGEtY3k9XCJoZWxwLS1jOHktaGVscC1jb250ZW50XCJcbiAgICAgICAgICA+PC9kaXY+XG4gICAgICAgIDwvZGl2PlxuXG4gICAgICAgIDxkaXZcbiAgICAgICAgICBjbGFzcz1cInAtbC0xNiBwLXQtMTYgZmxleC1ncm93XCJcbiAgICAgICAgICAqbmdJZj1cImhhc0Vycm9yXCJcbiAgICAgICAgPlxuICAgICAgICAgIDxoNFxuICAgICAgICAgICAgY2xhc3M9XCJ0ZXh0LWJvbGQgbS1iLTE2XCJcbiAgICAgICAgICAgIHRyYW5zbGF0ZVxuICAgICAgICAgID5cbiAgICAgICAgICAgIENvbnRlbnQgY291bGRuJ3QgYmUgbG9hZGVkLlxuICAgICAgICAgIDwvaDQ+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImhlbHAtY29udGVudFwiPlxuICAgICAgICAgICAgPHAgdHJhbnNsYXRlPkNoZWNrIGludGVybmV0IGNvbm5lY3Rpb24gb3IgcmVsb2FkIHBhZ2UuPC9wPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuICA8L2Rpdj5cbiAgPGRpdlxuICAgIGNsYXNzPVwiYzh5LWhlbHAtZHJhd2VyLWZvb3RlciBhbmltYXRlZCBmYWRlSW5cIlxuICAgIHN0eWxlPVwiYW5pbWF0aW9uLWRlbGF5OiAwLjM1c1wiXG4gICAgKm5nSWY9XCIhaXNMb2FkaW5nICYmICFoYXNFcnJvclwiXG4gICAgZGF0YS1jeT1cImM4eS1oZWxwLS1jOHktaGVscC1kcmF3ZXItZm9vdGVyXCJcbiAgPlxuICAgIDxidXR0b25cbiAgICAgIGNsYXNzPVwiYnRuIGJ0bi1kZWZhdWx0XCJcbiAgICAgIFt0aXRsZV09XCInQ2xvc2UgaGVscCcgfCB0cmFuc2xhdGVcIlxuICAgICAgYXJpYS1jb250cm9scz1cImNvbGxhcHNlSGVscFwiXG4gICAgICBbYXR0ci5hcmlhLWV4cGFuZGVkXT1cIiFpc0NvbGxhcHNlZFwiXG4gICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgIChjbGljayk9XCJ0b2dnbGUoKVwiXG4gICAgICB0cmFuc2xhdGVcbiAgICA+XG4gICAgICBDbG9zZVxuICAgIDwvYnV0dG9uPlxuICAgIDxhXG4gICAgICBjbGFzcz1cImJ0biBidG4tcHJpbWFyeVwiXG4gICAgICBocmVmPVwie3sgaGFzRXJyb3IgPyBnZXRVcmwoKSA6IGdldFVybChzcmMpIH19XCJcbiAgICAgIHRhcmdldD1cIl9ibGFua1wiXG4gICAgICBkYXRhLWN5PVwiYzh5LWhlbHAtLXVzZXItZ3VpZGVcIlxuICAgICAgcmVsPVwibm9vcGVuZXIgbm9yZWZlcnJlclwiXG4gICAgPlxuICAgICAgPHNwYW5cbiAgICAgICAgdHJhbnNsYXRlXG4gICAgICAgICpuZ0lmPVwiIWhhc0Vycm9yXCJcbiAgICAgID5cbiAgICAgICAgT3BlbiB0aGVcbiAgICAgICAgPHNwYW4+dXNlciBkb2N1bWVudGF0aW9uPC9zcGFuPlxuICAgICAgPC9zcGFuPlxuICAgICAgPHNwYW5cbiAgICAgICAgdHJhbnNsYXRlXG4gICAgICAgICpuZ0lmPVwiaGFzRXJyb3JcIlxuICAgICAgPlxuICAgICAgICBDaGVjayB0aGVcbiAgICAgICAgPHNwYW4+dXNlciBkb2N1bWVudGF0aW9uPC9zcGFuPlxuICAgICAgPC9zcGFuPlxuICAgIDwvYT5cbiAgPC9kaXY+XG48L2Rpdj5cbiJdfQ==