@c8y/ngx-components
Version:
Angular modules for Cumulocity IoT applications
88 lines • 21.7 kB
JavaScript
import { DOCUMENT as Document } from '@angular/common';
import { Component, Inject } from '@angular/core';
import { Router } from '@angular/router';
import { AlertService, gettext, HeaderService } from '@c8y/ngx-components';
import { TranslateService } from '@ngx-translate/core';
import { cloneDeep } from 'lodash-es';
import { BsModalService } from 'ngx-bootstrap/modal';
import { BookmarkService } from './bookmarks.service';
import { EditBookmarksComponent } from './edit-bookmarks/edit-bookmarks.component';
import * as i0 from "@angular/core";
import * as i1 from "@ngx-translate/core";
import * as i2 from "./bookmarks.service";
import * as i3 from "@c8y/ngx-components";
import * as i4 from "ngx-bootstrap/modal";
import * as i5 from "@angular/router";
import * as i6 from "@angular/common";
import * as i7 from "ngx-bootstrap/tooltip";
export class BookmarksComponent {
constructor(document, translateService, bookmarksService, alertService, bookmarkService, bsModalService, router, headerService) {
this.document = document;
this.translateService = translateService;
this.bookmarksService = bookmarksService;
this.alertService = alertService;
this.bookmarkService = bookmarkService;
this.bsModalService = bsModalService;
this.router = router;
this.headerService = headerService;
this.emptyMessageHeader = this.translateService.instant(gettext('No bookmarks yet'));
this.emptyMessageBody = this.translateService.instant(gettext('Navigate to the desired page and click the "Add current page" button. Editing, deleting and reordering are possible by clicking on the cog wheel.'));
this.addButtonText = this.translateService.instant(gettext('Add current page'));
this.drawerOpen$ = this.headerService.rightDrawerOpen$;
}
async ngOnInit() {
this.bookmarks = await this.bookmarkService.getBookmarks();
}
async addBookmark() {
const currentHref = this.document.location.href;
if (this.bookmarks.some(bookmark => bookmark.url === currentHref)) {
this.alertService.warning(gettext('Bookmark with the same URL is already added.'));
return;
}
const linkObject = this.bookmarkService.convertBookmarkLinkToObject(this.document.title, currentHref, this.bookmarksService.getCurrentActiveNodeIcon(this.document));
this.bookmarks.push(linkObject);
await this.bookmarkService.updateBookmarksInStorage(this.bookmarks);
this.alertService.success(gettext('Bookmark added.'));
}
async editBookmarks() {
try {
const initialState = {
bookmarks: cloneDeep(this.bookmarks)
};
const modalRef = this.bsModalService.show(EditBookmarksComponent, {
class: 'modal-md',
ariaDescribedby: 'modal-body',
ariaLabelledBy: 'modal-title',
initialState: initialState,
ignoreBackdropClick: true
}).content;
this.bookmarks = await modalRef.result;
}
catch (err) {
return;
}
}
openUrl(url) {
const parsedUrl = new URL(url);
if (parsedUrl.hostname === location.hostname &&
parsedUrl.pathname.includes(location.pathname)) {
this.router.navigateByUrl(parsedUrl.hash.substring(1));
return;
}
// only possible if the external bookmark URL has been saved using the API
if (parsedUrl.hostname !== location.hostname) {
return;
}
window.open(url, '_self');
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: BookmarksComponent, deps: [{ token: Document }, { token: i1.TranslateService }, { token: i2.BookmarkService }, { token: i3.AlertService }, { token: i2.BookmarkService }, { token: i4.BsModalService }, { token: i5.Router }, { token: i3.HeaderService }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: BookmarksComponent, selector: "c8y-bookmarks", ngImport: i0, template: "<div class=\"separator-top p-t-8 m-t-auto c8y-right-drawer__item sticky-top\">\n <i c8yIcon=\"bookmark\"></i>\n <span class=\"text-bold\">{{ 'Bookmarks' | translate }}</span>\n <button\n class=\"btn-dot m-l-auto\"\n tooltip=\"{{ 'Edit bookmarks' | translate }}\"\n [attr.aria-label]=\"'Edit bookmarks' | translate\"\n container=\"body\"\n placement=\"left\"\n [adaptivePosition]=\"false\"\n [delay]=\"500\"\n (click)=\"editBookmarks()\"\n type=\"button\"\n [tabindex]=\"(drawerOpen$ | async) ? '0' : '-1'\"\n >\n <i c8yIcon=\"cog\" class=\"text-14 m-0\"></i>\n </button>\n</div>\n<div class=\"c8y-right-drawer__item p-t-0 p-b-8\" *ngIf=\"bookmarks?.length\">\n <button\n class=\"btn btn-default btn-sm\"\n (click)=\"addBookmark()\"\n type=\"button\"\n [tabindex]=\"(drawerOpen$ | async) ? '0' : '-1'\"\n >\n <i c8yIcon=\"plus-circle-o\" class=\"m-t-0 m-b-0 text-14\"></i>\n <span>{{ addButtonText }}</span>\n </button>\n</div>\n<ng-container *ngFor=\"let bookmark of bookmarks\">\n <button\n title=\"{{ bookmark.label }}\"\n type=\"button\"\n class=\"c8y-right-drawer__link\"\n (click)=\"openUrl(bookmark.url)\"\n [tabindex]=\"(drawerOpen$ | async) ? '0' : '-1'\"\n >\n <i [c8yIcon]=\"bookmark.icon\" *ngIf=\"bookmark.icon\"></i>\n <span class=\"text-truncate\">{{ bookmark.label }}</span>\n </button>\n</ng-container>\n<div class=\"p-t-8 p-b-8\">\n <ng-container *ngIf=\"!bookmarks?.length\">\n <span class=\"c8y-right-drawer__item text-muted text-bold text-14 p-b-0\">\n {{ emptyMessageHeader }}\n </span>\n <span class=\"c8y-right-drawer__item text-12 p-t-0\">\n <span class=\"text-muted\">{{ emptyMessageBody }}</span>\n </span>\n <div class=\"c8y-right-drawer__item\">\n <button\n class=\"btn btn-default btn-sm\"\n (click)=\"addBookmark()\"\n type=\"button\"\n [tabindex]=\"(drawerOpen$ | async) ? '0' : '-1'\"\n >\n <i c8yIcon=\"plus-circle-o\" class=\"m-t-0 m-b-0 text-14\"></i>\n <span>{{ addButtonText }}</span>\n </button>\n </div>\n </ng-container>\n</div>\n", dependencies: [{ kind: "directive", type: i3.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i7.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: "pipe", type: i3.C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: i6.AsyncPipe, name: "async" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: BookmarksComponent, decorators: [{
type: Component,
args: [{ selector: 'c8y-bookmarks', template: "<div class=\"separator-top p-t-8 m-t-auto c8y-right-drawer__item sticky-top\">\n <i c8yIcon=\"bookmark\"></i>\n <span class=\"text-bold\">{{ 'Bookmarks' | translate }}</span>\n <button\n class=\"btn-dot m-l-auto\"\n tooltip=\"{{ 'Edit bookmarks' | translate }}\"\n [attr.aria-label]=\"'Edit bookmarks' | translate\"\n container=\"body\"\n placement=\"left\"\n [adaptivePosition]=\"false\"\n [delay]=\"500\"\n (click)=\"editBookmarks()\"\n type=\"button\"\n [tabindex]=\"(drawerOpen$ | async) ? '0' : '-1'\"\n >\n <i c8yIcon=\"cog\" class=\"text-14 m-0\"></i>\n </button>\n</div>\n<div class=\"c8y-right-drawer__item p-t-0 p-b-8\" *ngIf=\"bookmarks?.length\">\n <button\n class=\"btn btn-default btn-sm\"\n (click)=\"addBookmark()\"\n type=\"button\"\n [tabindex]=\"(drawerOpen$ | async) ? '0' : '-1'\"\n >\n <i c8yIcon=\"plus-circle-o\" class=\"m-t-0 m-b-0 text-14\"></i>\n <span>{{ addButtonText }}</span>\n </button>\n</div>\n<ng-container *ngFor=\"let bookmark of bookmarks\">\n <button\n title=\"{{ bookmark.label }}\"\n type=\"button\"\n class=\"c8y-right-drawer__link\"\n (click)=\"openUrl(bookmark.url)\"\n [tabindex]=\"(drawerOpen$ | async) ? '0' : '-1'\"\n >\n <i [c8yIcon]=\"bookmark.icon\" *ngIf=\"bookmark.icon\"></i>\n <span class=\"text-truncate\">{{ bookmark.label }}</span>\n </button>\n</ng-container>\n<div class=\"p-t-8 p-b-8\">\n <ng-container *ngIf=\"!bookmarks?.length\">\n <span class=\"c8y-right-drawer__item text-muted text-bold text-14 p-b-0\">\n {{ emptyMessageHeader }}\n </span>\n <span class=\"c8y-right-drawer__item text-12 p-t-0\">\n <span class=\"text-muted\">{{ emptyMessageBody }}</span>\n </span>\n <div class=\"c8y-right-drawer__item\">\n <button\n class=\"btn btn-default btn-sm\"\n (click)=\"addBookmark()\"\n type=\"button\"\n [tabindex]=\"(drawerOpen$ | async) ? '0' : '-1'\"\n >\n <i c8yIcon=\"plus-circle-o\" class=\"m-t-0 m-b-0 text-14\"></i>\n <span>{{ addButtonText }}</span>\n </button>\n </div>\n </ng-container>\n</div>\n" }]
}], ctorParameters: () => [{ type: Document, decorators: [{
type: Inject,
args: [Document]
}] }, { type: i1.TranslateService }, { type: i2.BookmarkService }, { type: i3.AlertService }, { type: i2.BookmarkService }, { type: i4.BsModalService }, { type: i5.Router }, { type: i3.HeaderService }] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYm9va21hcmtzLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2Jvb2ttYXJrcy9ib29rbWFya3MuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vYm9va21hcmtzL2Jvb2ttYXJrcy5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsUUFBUSxJQUFJLFFBQVEsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ2xELE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUN6QyxPQUFPLEVBQUUsWUFBWSxFQUFFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUMzRSxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUN2RCxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQ3RDLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUdyRCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDdEQsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sMkNBQTJDLENBQUM7Ozs7Ozs7OztBQU1uRixNQUFNLE9BQU8sa0JBQWtCO0lBVzdCLFlBQzRCLFFBQWtCLEVBQ3BDLGdCQUFrQyxFQUNsQyxnQkFBaUMsRUFDakMsWUFBMEIsRUFDMUIsZUFBZ0MsRUFDaEMsY0FBOEIsRUFDOUIsTUFBYyxFQUNkLGFBQTRCO1FBUFYsYUFBUSxHQUFSLFFBQVEsQ0FBVTtRQUNwQyxxQkFBZ0IsR0FBaEIsZ0JBQWdCLENBQWtCO1FBQ2xDLHFCQUFnQixHQUFoQixnQkFBZ0IsQ0FBaUI7UUFDakMsaUJBQVksR0FBWixZQUFZLENBQWM7UUFDMUIsb0JBQWUsR0FBZixlQUFlLENBQWlCO1FBQ2hDLG1CQUFj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QUFDLENBQUM7WUFDdkQsT0FBTztRQUNULENBQUM7UUFFRCwwRUFBMEU7UUFDMUUsSUFBSSxTQUFTLENBQUMsUUFBUSxLQUFLLFFBQVEsQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUM3QyxPQUFPO1FBQ1QsQ0FBQztRQUVELE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQzVCLENBQUM7K0dBL0VVLGtCQUFrQixrQkFZbkIsUUFBUTttR0FaUCxrQkFBa0IscURDaEIvQiw4bEVBOERBOzs0RkQ5Q2Esa0JBQWtCO2tCQUo5QixTQUFTOytCQUNFLGVBQWU7OzBCQWV0QixNQUFNOzJCQUFDLFFBQVEiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBET0NVTUVOVCBhcyBEb2N1bWVudCB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBDb21wb25lbnQsIEluamVjdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgUm91dGVyIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7IEFsZXJ0U2VydmljZSwgZ2V0dGV4dCwgSGVhZGVyU2VydmljZSB9IGZyb20gJ0BjOHkvbmd4LWNvbXBvbmVudHMnO1xuaW1wb3J0IHsgVHJhbnNsYXRlU2VydmljZSB9IGZyb20gJ0BuZ3gtdHJhbnNsYXRlL2NvcmUnO1xuaW1wb3J0IHsgY2xvbmVEZWVwIH0gZnJvbSAnbG9kYXNoLWVzJztcbmltcG9ydCB7IEJzTW9kYWxTZXJ2aWNlIH0gZnJvbSAnbmd4LWJvb3RzdHJhcC9tb2RhbCc7XG5pbXBvcnQgeyBPYnNlcnZhYmxlIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBCb29rbWFyayB9IGZyb20gJy4vYm9va21hcmsubW9kZWwnO1xuaW1wb3J0IHsgQm9va21hcmtTZXJ2aWNlIH0gZnJvbSAnLi9ib29rbWFya3Muc2VydmljZSc7XG5pbXBvcnQgeyBFZGl0Qm9va21hcmtzQ29tcG9uZW50IH0gZnJvbSAnLi9lZGl0LWJvb2ttYXJrcy9lZGl0LWJvb2ttYXJrcy5jb21wb25lbnQnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdjOHktYm9va21hcmtzJyxcbiAgdGVtcGxhdGVVcmw6ICcuL2Jvb2ttYXJrcy5jb21wb25lbnQuaHRtbCdcbn0pXG5leHBvcnQgY2xhc3MgQm9va21hcmtzQ29tcG9uZW50IHtcbiAgZHJhd2VyT3BlbiQ6IE9ic2VydmFibGU8Ym9vbGVhbj47XG4gIGJvb2ttYXJrczogQm9va21hcmtbXTtcbiAgZW1wdHlNZXNzYWdlSGVhZGVyID0gdGhpcy50cmFuc2xhdGVTZXJ2aWNlLmluc3RhbnQoZ2V0dGV4dCgnTm8gYm9va21hcmtzIHlldCcpKTtcbiAgZW1wdHlNZXNzYWdlQm9keSA9IHRoaXMudHJhbnNsYXRlU2VydmljZS5pbnN0YW50KFxuICAgIGdldHRleHQoXG4gICAgICAnTmF2aWdhdGUgdG8gdGhlIGRlc2lyZWQgcGFnZSBhbmQgY2xpY2sgdGhlIFwiQWRkIGN1cnJlbnQgcGFnZVwiIGJ1dHRvbi4gRWRpdGluZywgZGVsZXRpbmcgYW5kIHJlb3JkZXJpbmcgYXJlIHBvc3NpYmxlIGJ5IGNsaWNraW5nIG9uIHRoZSBjb2cgd2hlZWwuJ1xuICAgIClcbiAgKTtcbiAgYWRkQnV0dG9uVGV4dCA9IHRoaXMudHJhbnNsYXRlU2VydmljZS5pbnN0YW50KGdldHRleHQoJ0FkZCBjdXJyZW50IHBhZ2UnKSk7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgQEluamVjdChEb2N1bWVudCkgcHJpdmF0ZSBkb2N1bWVudDogRG9jdW1lbnQsXG4gICAgcHJpdmF0ZSB0cmFuc2xhdGVTZXJ2aWNlOiBUcmFuc2xhdGVTZXJ2aWNlLFxuICAgIHByaXZhdGUgYm9va21hcmtzU2VydmljZTogQm9va21hcmtTZXJ2aWNlLFxuICAgIHByaXZhdGUgYWxlcnRTZXJ2aWNlOiBBbGVydFNlcnZpY2UsXG4gICAgcHJpdmF0ZSBib29rbWFya1NlcnZpY2U6IEJvb2ttYXJrU2VydmljZSxcbiAgICBwcml2YXRlIGJzTW9kYWxTZXJ2aWNlOiBCc01vZGFsU2VydmljZSxcbiAgICBwcml2YXRlIHJvdXRlcjogUm91dGVyLFxuICAgIHByaXZhdGUgaGVhZGVyU2VydmljZTogSGVhZGVyU2VydmljZVxuICApIHtcbiAgICB0aGlzLmRyYXdlck9wZW4kID0gdGhpcy5oZWFkZXJTZXJ2aWNlLnJpZ2h0RHJhd2VyT3BlbiQ7XG4gIH1cblxuICBhc3luYyBuZ09uSW5pdCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICB0aGlzLmJvb2ttYXJrcyA9IGF3YWl0IHRoaXMuYm9va21hcmtTZXJ2aWNlLmdldEJvb2ttYXJrcygpO1xuICB9XG5cbiAgYXN5bmMgYWRkQm9va21hcmsoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgY3VycmVudEhyZWYgPSB0aGlzLmRvY3VtZW50LmxvY2F0aW9uLmhyZWY7XG4gICAgaWYgKHRoaXMuYm9va21hcmtzLnNvbWUoYm9va21hcmsgPT4gYm9va21hcmsudXJsID09PSBjdXJyZW50SHJlZikpIHtcbiAgICAgIHRoaXMuYWxlcnRTZXJ2aWNlLndhcm5pbmcoZ2V0dGV4dCgnQm9va21hcmsgd2l0aCB0aGUgc2FtZSBVUkwgaXMgYWxyZWFkeSBhZGRlZC4nKSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGxpbmtPYmplY3QgPSB0aGlzLmJvb2ttYXJrU2VydmljZS5jb252ZXJ0Qm9va21hcmtMaW5rVG9PYmplY3QoXG4gICAgICB0aGlzLmRvY3VtZW50LnRpdGxlLFxuICAgICAgY3VycmVudEhyZWYsXG4gICAgICB0aGlzLmJvb2ttYXJrc1NlcnZpY2UuZ2V0Q3VycmVudEFjdGl2ZU5vZGVJY29uKHRoaXMuZG9jdW1lbnQpXG4gICAgKTtcbiAgICB0aGlzLmJvb2ttYXJrcy5wdXNoKGxpbmtPYmplY3QpO1xuICAgIGF3YWl0IHRoaXMuYm9va21hcmtTZXJ2aWNlLnVwZGF0ZUJvb2ttYXJrc0luU3RvcmFnZSh0aGlzLmJvb2ttYXJrcyk7XG4gICAgdGhpcy5hbGVydFNlcnZpY2Uuc3VjY2VzcyhnZXR0ZXh0KCdCb29rbWFyayBhZGRlZC4nKSk7XG4gIH1cblxuICBhc3luYyBlZGl0Qm9va21hcmtzKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBpbml0aWFsU3RhdGU6IFBpY2s8RWRpdEJvb2ttYXJrc0NvbXBvbmVudCwgJ2Jvb2ttYXJrcyc+ID0ge1xuICAgICAgICBib29rbWFya3M6IGNsb25lRGVlcCh0aGlzLmJvb2ttYXJrcylcbiAgICAgIH07XG4gICAgICBjb25zdCBtb2RhbFJlZiA9IHRoaXMuYnNNb2RhbFNlcnZpY2Uuc2hvdyhFZGl0Qm9va21hcmtzQ29tcG9uZW50LCB7XG4gICAgICAgIGNsYXNzOiAnbW9kYWwtbWQnLFxuICAgICAgICBhcmlhRGVzY3JpYmVkYnk6ICdtb2RhbC1ib2R5JyxcbiAgICAgICAgYXJpYUxhYmVsbGVkQnk6ICdtb2RhbC10aXRsZScsXG4gICAgICAgIGluaXRpYWxTdGF0ZTogaW5pdGlhbFN0YXRlLFxuICAgICAgICBpZ25vcmVCYWNrZHJvcENsaWNrOiB0cnVlXG4gICAgICB9KS5jb250ZW50IGFzIEVkaXRCb29rbWFya3NDb21wb25lbnQ7XG4gICAgICB0aGlzLmJvb2ttYXJrcyA9IGF3YWl0IG1vZGFsUmVmLnJlc3VsdDtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gIH1cblxuICBvcGVuVXJsKHVybDogc3RyaW5nKTogdm9pZCB7XG4gICAgY29uc3QgcGFyc2VkVXJsID0gbmV3IFVSTCh1cmwpO1xuXG4gICAgaWYgKFxuICAgICAgcGFyc2VkVXJsLmhvc3RuYW1lID09PSBsb2NhdGlvbi5ob3N0bmFtZSAmJlxuICAgICAgcGFyc2VkVXJsLnBhdGhuYW1lLmluY2x1ZGVzKGxvY2F0aW9uLnBhdGhuYW1lKVxuICAgICkge1xuICAgICAgdGhpcy5yb3V0ZXIubmF2aWdhdGVCeVVybChwYXJzZWRVcmwuaGFzaC5zdWJzdHJpbmcoMSkpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIG9ubHkgcG9zc2libGUgaWYgdGhlIGV4dGVybmFsIGJvb2ttYXJrIFVSTCBoYXMgYmVlbiBzYXZlZCB1c2luZyB0aGUgQVBJXG4gICAgaWYgKHBhcnNlZFVybC5ob3N0bmFtZSAhPT0gbG9jYXRpb24uaG9zdG5hbWUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB3aW5kb3cub3Blbih1cmwsICdfc2VsZicpO1xuICB9XG59XG4iLCI8ZGl2IGNsYXNzPVwic2VwYXJhdG9yLXRvcCBwLXQtOCBtLXQtYXV0byBjOHktcmlnaHQtZHJhd2VyX19pdGVtIHN0aWNreS10b3BcIj5cbiAgPGkgYzh5SWNvbj1cImJvb2ttYXJrXCI+PC9pPlxuICA8c3BhbiBjbGFzcz1cInRleHQtYm9sZFwiPnt7ICdCb29rbWFya3MnIHwgdHJhbnNsYXRlIH19PC9zcGFuPlxuICA8YnV0dG9uXG4gICAgY2xhc3M9XCJidG4tZG90IG0tbC1hdXRvXCJcbiAgICB0b29sdGlwPVwie3sgJ0VkaXQgYm9va21hcmtzJyB8IHRyYW5zbGF0ZSB9fVwiXG4gICAgW2F0dHIuYXJpYS1sYWJlbF09XCInRWRpdCBib29rbWFya3MnIHwgdHJhbnNsYXRlXCJcbiAgICBjb250YWluZXI9XCJib2R5XCJcbiAgICBwbGFjZW1lbnQ9XCJsZWZ0XCJcbiAgICBbYWRhcHRpdmVQb3NpdGlvbl09XCJmYWxzZVwiXG4gICAgW2RlbGF5XT1cIjUwMFwiXG4gICAgKGNsaWNrKT1cImVkaXRCb29rbWFya3MoKVwiXG4gICAgdHlwZT1cImJ1dHRvblwiXG4gICAgW3RhYmluZGV4XT1cIihkcmF3ZXJPcGVuJCB8IGFzeW5jKSA/ICcwJyA6ICctMSdcIlxuICA+XG4gICAgPGkgYzh5SWNvbj1cImNvZ1wiIGNsYXNzPVwidGV4dC0xNCBtLTBcIj48L2k+XG4gIDwvYnV0dG9uPlxuPC9kaXY+XG48ZGl2IGNsYXNzPVwiYzh5LXJpZ2h0LWRyYXdlcl9faXRlbSBwLXQtMCBwLWItOFwiICpuZ0lmPVwiYm9va21hcmtzPy5sZW5ndGhcIj5cbiAgPGJ1dHRvblxuICAgIGNsYXNzPVwiYnRuIGJ0bi1kZWZhdWx0IGJ0bi1zbVwiXG4gICAgKGNsaWNrKT1cImFkZEJvb2ttYXJrKClcIlxuICAgIHR5cGU9XCJidXR0b25cIlxuICAgIFt0YWJpbmRleF09XCIoZHJhd2VyT3BlbiQgfCBhc3luYykgPyAnMCcgOiAnLTEnXCJcbiAgPlxuICAgIDxpIGM4eUljb249XCJwbHVzLWNpcmNsZS1vXCIgY2xhc3M9XCJtLXQtMCBtLWItMCB0ZXh0LTE0XCI+PC9pPlxuICAgIDxzcGFuPnt7IGFkZEJ1dHRvblRleHQgfX08L3NwYW4+XG4gIDwvYnV0dG9uPlxuPC9kaXY+XG48bmctY29udGFpbmVyICpuZ0Zvcj1cImxldCBib29rbWFyayBvZiBib29rbWFya3NcIj5cbiAgPGJ1dHRvblxuICAgIHRpdGxlPVwie3sgYm9va21hcmsubGFiZWwgfX1cIlxuICAgIHR5cGU9XCJidXR0b25cIlxuICAgIGNsYXNzPVwiYzh5LXJpZ2h0LWRyYXdlcl9fbGlua1wiXG4gICAgKGNsaWNrKT1cIm9wZW5VcmwoYm9va21hcmsudXJsKVwiXG4gICAgW3RhYmluZGV4XT1cIihkcmF3ZXJPcGVuJCB8IGFzeW5jKSA/ICcwJyA6ICctMSdcIlxuICA+XG4gICAgPGkgW2M4eUljb25dPVwiYm9va21hcmsuaWNvblwiICpuZ0lmPVwiYm9va21hcmsuaWNvblwiPjwvaT5cbiAgICA8c3BhbiBjbGFzcz1cInRleHQtdHJ1bmNhdGVcIj57eyBib29rbWFyay5sYWJlbCB9fTwvc3Bhbj5cbiAgPC9idXR0b24+XG48L25nLWNvbnRhaW5lcj5cbjxkaXYgY2xhc3M9XCJwLXQtOCBwLWItOFwiPlxuICA8bmctY29udGFpbmVyICpuZ0lmPVwiIWJvb2ttYXJrcz8ubGVuZ3RoXCI+XG4gICAgPHNwYW4gY2xhc3M9XCJjOHktcmlnaHQtZHJhd2VyX19pdGVtIHRleHQtbXV0ZWQgdGV4dC1ib2xkIHRleHQtMTQgcC1iLTBcIj5cbiAgICAgIHt7IGVtcHR5TWVzc2FnZUhlYWRlciB9fVxuICAgIDwvc3Bhbj5cbiAgICA8c3BhbiBjbGFzcz1cImM4eS1yaWdodC1kcmF3ZXJfX2l0ZW0gdGV4dC0xMiBwLXQtMFwiPlxuICAgICAgPHNwYW4gY2xhc3M9XCJ0ZXh0LW11dGVkXCI+e3sgZW1wdHlNZXNzYWdlQm9keSB9fTwvc3Bhbj5cbiAgICA8L3NwYW4+XG4gICAgPGRpdiBjbGFzcz1cImM4eS1yaWdodC1kcmF3ZXJfX2l0ZW1cIj5cbiAgICAgIDxidXR0b25cbiAgICAgICAgY2xhc3M9XCJidG4gYnRuLWRlZmF1bHQgYnRuLXNtXCJcbiAgICAgICAgKGNsaWNrKT1cImFkZEJvb2ttYXJrKClcIlxuICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgW3RhYmluZGV4XT1cIihkcmF3ZXJPcGVuJCB8IGFzeW5jKSA/ICcwJyA6ICctMSdcIlxuICAgICAgPlxuICAgICAgICA8aSBjOHlJY29uPVwicGx1cy1jaXJjbGUtb1wiIGNsYXNzPVwibS10LTAgbS1iLTAgdGV4dC0xNFwiPjwvaT5cbiAgICAgICAgPHNwYW4+e3sgYWRkQnV0dG9uVGV4dCB9fTwvc3Bhbj5cbiAgICAgIDwvYnV0dG9uPlxuICAgIDwvZGl2PlxuICA8L25nLWNvbnRhaW5lcj5cbjwvZGl2PlxuIl19