UNPKG

@c8y/ngx-components

Version:

Angular modules for Cumulocity IoT applications

214 lines 59.8 kB
import { Component, Inject, Input, ViewChild } from '@angular/core'; import { CommonModule as NgCommonModule } from '@angular/common'; import { FormsModule as NgFormsModule } from '@angular/forms'; import { ControlContainer, NgForm } from '@angular/forms'; import { AlertService, AssetLinkPipe, CommonModule, FormsModule, gettext } from '@c8y/ngx-components'; import { MAP_DEFAULT_CONFIG, MapComponent, MapModule, MapService } from '@c8y/ngx-components/map'; import { TranslateService } from '@ngx-translate/core'; import { Observable, Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; import { IconSelectorModule } from '@c8y/ngx-components/icon-selector'; import { TooltipModule } from 'ngx-bootstrap/tooltip'; import * as i0 from "@angular/core"; import * as i1 from "@c8y/ngx-components/map"; import * as i2 from "@c8y/ngx-components"; import * as i3 from "@ngx-translate/core"; import * as i4 from "@angular/common"; import * as i5 from "@angular/forms"; import * as i6 from "@c8y/ngx-components/icon-selector"; import * as i7 from "ngx-bootstrap/tooltip"; import * as i8 from "rxjs"; export class MapWidgetConfigComponent { constructor(mapService, alertService, translateService, defaultMapConfig) { this.mapService = mapService; this.alertService = alertService; this.translateService = translateService; this.defaultMapConfig = defaultMapConfig; this.config = { mapConfig: undefined }; this.canAutoCenter = true; this.isPositionedDevice = false; this.refreshOption = 'none'; this.destroyed$ = new Subject(); // JS precision for floating point number is 15 for 64-bit and because of this provided to leaflet are recalculated // to values almost-like provided (e.g. 0 is recalculated to 1.46e-14; for 180 it's 180.00000000000003). // To ensure provided value has no floating point error, number needs to be rounded to fixed point 13. this.FIXED_POINT_DIGITS = 13; } ngOnDestroy() { this.destroyed$.next(); } ngOnInit() { this.defaultMapConfig.pipe(takeUntil(this.destroyed$)).subscribe(defaultConfig => { this.formConfig = { zoomLevel: defaultConfig.zoomLevel, center: defaultConfig.center }; this.initForm(); }); } async initForm() { if (!this.config.mapConfig) { this.config.mapConfig = this.formConfig; } this.formConfig = { ...this.formConfig, ...this.config.mapConfig, disablePan: false }; await this.updateAsset(); } async ngOnChanges(changes) { if (changes.config.currentValue !== changes.config.previousValue && !changes.config.firstChange) { await this.updateAsset(); } } previewMapInit(leaflet) { this.leaflet = leaflet; this.addCenterIcon(this.formConfig.center[0], this.formConfig.center[1]); } onBeforeSave() { this.config.mapConfig = this.formConfig; return true; } zoomLevelChanged() { this.config.mapConfig = { ...this.config.mapConfig, zoomLevel: this.formConfig.zoomLevel }; } changeCenter() { if (this.centerIcon) { this.centerIcon.remove(); } this.config.mapConfig = { ...this.formConfig, center: [...this.formConfig.center] }; this.addCenterIcon(this.formConfig.center[0], this.formConfig.center[1]); } changeCenterOnEnterKey(event) { event.preventDefault(); this.changeCenter(); } onPreviewZoomStart() { this.centerIcon.remove(); } onPreviewZoomEnd(event) { this.formConfig.zoomLevel = Math.floor(event.target.getZoom()); } onPreviewMapMove(event) { if (this.centerIcon) { this.centerIcon.remove(); } const { lat, lng } = event.target.getCenter(); const fixedLat = +lat.toFixed(this.FIXED_POINT_DIGITS); const fixedLng = +lng.toFixed(this.FIXED_POINT_DIGITS); this.addCenterIcon(fixedLat, fixedLng); this.formConfig.center = [fixedLat, fixedLng]; } useOwnPosition() { navigator.geolocation.getCurrentPosition(({ coords }) => { this.formConfig.center = [coords.latitude, coords.longitude]; this.changeCenter(); }); } centerToAsset() { this.formConfig.center = [ this.config.device.c8y_Position.lat, this.config.device.c8y_Position.lng ]; this.changeCenter(); } updateRefreshOption() { this.formConfig.realtime = this.refreshOption === 'realtime'; this.config.widgetInstanceGlobalAutoRefreshContext = this.refreshOption === 'dashboard-auto-refresh-context'; this.formConfig.widgetInstanceGlobalAutoRefreshContext = this.refreshOption === 'dashboard-auto-refresh-context'; if (this.refreshOption === 'interval') { this.formConfig.refreshInterval ??= 5000; } else { this.formConfig.refreshInterval = null; } if (!this.formConfig.realtime) { this.formConfig.follow = false; } this.config.widgetInstanceGlobalTimeContext = this.refreshOption === 'dashboard-realtime-context'; if (this.config.widgetInstanceGlobalTimeContext) { this.formConfig.realtime = null; } } selectIcon(icon) { this.formConfig.icon = icon; this.config.mapConfig.icon = icon; this.previewMap.refreshMarkers(); } async updateAsset() { this.canAutoCenter = this.mapService.hasPosition(this.config.device); this.isPositionedDevice = this.mapService.isPositionedDevice(this.config.device); this.refreshOption = this.getRefreshOption(); this.updateRefreshOption(); const { data, paging } = await this.mapService.getAllPositionMOs(this.config.device); this.assets = data; if (paging.totalPages > 1) { this.alertService.danger(gettext('It might be possible that assets are not shown in the preview, as the current selection has more than 500 assets and the preview only supports a maximum of 500 assets.')); } } getRefreshOption() { let option = 'none'; if (this.formConfig.realtime) { option = 'realtime'; } else if (this.formConfig.refreshInterval) { option = 'interval'; } else if (this.config.widgetInstanceGlobalTimeContext) { option = 'dashboard-realtime-context'; } else if (this.config.widgetInstanceGlobalAutoRefreshContext || this.formConfig.widgetInstanceGlobalAutoRefreshContext) { option = 'dashboard-auto-refresh-context'; } const isNotAllowedOption = (!this.isPositionedDevice && option === 'dashboard-realtime-context') || (!this.isPositionedDevice && option === 'realtime') || (this.isPositionedDevice && option === 'interval'); option = isNotAllowedOption ? 'none' : option; return option; } addCenterIcon(lat, lng) { const titleText = this.translateService.instant(gettext('Map center')); const icon = this.leaflet.divIcon({ html: `<i style="pointer-events: none" class="c8y-map-marker-icon text-muted dlt-c8y-icon-target icon-2x" title="${titleText}" />` }); this.centerIcon = this.leaflet.marker([lat, lng], { icon }); this.previewMap.addMarkerToMap(this.centerIcon); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: MapWidgetConfigComponent, deps: [{ token: i1.MapService }, { token: i2.AlertService }, { token: i3.TranslateService }, { token: MAP_DEFAULT_CONFIG }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: MapWidgetConfigComponent, isStandalone: true, selector: "c8y-map-widget-config", inputs: { config: "config" }, viewQueries: [{ propertyName: "previewMap", first: true, predicate: MapComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div\n class=\"row p-t-16\"\n *ngIf=\"formConfig\"\n>\n <div class=\"col-xs-2\">\n <c8y-form-group class=\"m-b-0 text-center form-group-sm\">\n <label translate>Marker icon</label>\n <c8y-icon-selector-wrapper\n [canRemoveIcon]=\"true\"\n [selectedIcon]=\"formConfig.icon\"\n (onSelect)=\"selectIcon($event)\"\n ></c8y-icon-selector-wrapper>\n </c8y-form-group>\n </div>\n <div class=\"col-xs-10\">\n <div class=\"row tight-grid separator-bottom\">\n <div class=\"col-xs-4\">\n <div class=\"form-group form-group-sm\">\n <label translate>Zoom level</label>\n <c8y-range\n class=\"label-bottom\"\n name=\"zoomLevel\"\n #range\n [(ngModel)]=\"formConfig.zoomLevel\"\n (change)=\"zoomLevelChanged()\"\n >\n <input\n type=\"range\"\n min=\"2\"\n max=\"18\"\n step=\"1\"\n />\n </c8y-range>\n </div>\n </div>\n <div class=\"col-xs-8\">\n <c8y-form-group class=\"form-group-sm m-b-8\">\n <label translate>Center bound</label>\n <div class=\"input-group input-group-sm\">\n <input\n class=\"form-control\"\n placeholder=\"{{ 'lat.`latitude`' | translate }}\"\n name=\"centerLat\"\n type=\"number\"\n required\n [(ngModel)]=\"formConfig.center[0]\"\n (change)=\"changeCenter()\"\n (keydown.enter)=\"changeCenterOnEnterKey($event)\"\n min=\"-90\"\n max=\"90\"\n step=\"0.1\"\n />\n <input\n class=\"form-control\"\n placeholder=\"{{ 'lng.`longitude`' | translate }}\"\n name=\"centerLng\"\n type=\"number\"\n required\n min=\"-180\"\n max=\"180\"\n [(ngModel)]=\"formConfig.center[1]\"\n (change)=\"changeCenter()\"\n (keydown.enter)=\"changeCenterOnEnterKey($event)\"\n min=\"-180\"\n max=\"180\"\n step=\"0.1\"\n />\n <div class=\"input-group-btn\">\n <button\n class=\"btn btn-default\"\n [attr.aria-label]=\"'Use your location' | translate\"\n [tooltip]=\"'Use your location' | translate\"\n placement=\"top\"\n container=\"body\"\n (click)=\"useOwnPosition()\"\n >\n <i\n class=\"icon-14\"\n c8yIcon=\"location-arrow\"\n ></i>\n </button>\n </div>\n <div\n class=\"input-group-btn\"\n *ngIf=\"canAutoCenter\"\n >\n <button\n class=\"btn btn-default\"\n [attr.aria-label]=\"'Use selected asset location' | translate\"\n [tooltip]=\"'Use selected asset location' | translate\"\n placement=\"top\"\n container=\"body\"\n (click)=\"centerToAsset()\"\n >\n <i\n class=\"icon-14\"\n c8yIcon=\"location\"\n ></i>\n </button>\n </div>\n </div>\n <c8y-messages\n [helpMessage]=\"'Drag the map to the desired position' | translate\"\n ></c8y-messages>\n </c8y-form-group>\n </div>\n </div>\n\n <div class=\"row tight-grid p-t-8 d-flex a-i-center\">\n <div class=\"col-xs-6\">\n <c8y-form-group class=\"m-b-0 form-group-sm\">\n <div class=\"c8y-select-wrapper\">\n <select\n class=\"form-control\"\n title=\"{{ 'Refresh options`options for refreshing a view`' | translate }}\"\n id=\"selectExample\"\n name=\"refreshSelection\"\n [(ngModel)]=\"refreshOption\"\n (change)=\"updateRefreshOption()\"\n >\n <option\n [title]=\"'Only refreshing on interaction' | translate\"\n value=\"none\"\n translate\n >\n No automatic refresh\n </option>\n <option\n [title]=\"'Refreshing after the given interval and on interaction' | translate\"\n value=\"interval\"\n *ngIf=\"!isPositionedDevice\"\n translate\n >\n Use refresh interval\n </option>\n <option\n [title]=\"\n 'Refreshing after the given interval and on interaction, synchronized globally'\n | translate\n \"\n value=\"dashboard-auto-refresh-context\"\n *ngIf=\"!isPositionedDevice\"\n translate\n >\n Use global refresh interval\n </option>\n <option\n [title]=\"'Live updating on each position change' | translate\"\n value=\"realtime\"\n *ngIf=\"isPositionedDevice\"\n translate\n >\n Realtime\n </option>\n <option\n [title]=\"'Bind widget to dashboard realtime context' | translate\"\n value=\"dashboard-realtime-context\"\n *ngIf=\"isPositionedDevice\"\n translate\n >\n Dashboard realtime context\n </option>\n </select>\n </div>\n </c8y-form-group>\n </div>\n <div class=\"col-xs-8\">\n <div class=\"form-group form-group-sm m-b-0\">\n <c8y-range\n class=\"label-bottom\"\n name=\"refreshInterval\"\n #intervalRange\n *ngIf=\"refreshOption === 'interval'\"\n [(ngModel)]=\"formConfig.refreshInterval\"\n >\n <ng-template #c8yRangeValue>\n <div>\n <span\n [translateParams]=\"{ intervalInSeconds: intervalRange.value * 0.001 }\"\n translate\n ngNonBindable\n >\n {{ intervalInSeconds }} s\n </span>\n </div>\n </ng-template>\n <input\n type=\"range\"\n min=\"5000\"\n max=\"100000\"\n step=\"1000\"\n />\n </c8y-range>\n </div>\n <label\n class=\"c8y-switch c8y-switch--inline\"\n *ngIf=\"refreshOption === 'realtime' || refreshOption === 'dashboard-realtime-context'\"\n >\n <input\n name=\"follow\"\n type=\"checkbox\"\n [(ngModel)]=\"formConfig.follow\"\n />\n <span></span>\n <span\n class=\"text-12\"\n translate\n >\n Follow selected\n </span>\n </label>\n </div>\n </div>\n </div>\n</div>\n\n<div\n class=\"p-t-16 p-b-16\"\n style=\"width: 100%; height: 240px\"\n>\n <c8y-map\n *ngIf=\"config.mapConfig\"\n [assets]=\"assets\"\n [config]=\"config.mapConfig\"\n (onMove)=\"onPreviewMapMove($event)\"\n (onZoomStart)=\"onPreviewZoomStart()\"\n (onZoomEnd)=\"onPreviewZoomEnd($event)\"\n (onInit)=\"previewMapInit($event)\"\n ></c8y-map>\n</div>\n", dependencies: [{ kind: "ngmodule", type: NgCommonModule }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: NgFormsModule }, { kind: "directive", type: i5.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i5.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i5.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i5.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i5.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i5.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i5.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i5.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "pipe", type: i2.C8yTranslatePipe, name: "translate" }, { kind: "directive", type: i2.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.MinValidationDirective, selector: "[min]", inputs: ["min"] }, { kind: "directive", type: i2.MaxValidationDirective, selector: "[max]", inputs: ["max"] }, { kind: "component", type: i2.FormGroupComponent, selector: "c8y-form-group", inputs: ["hasError", "hasWarning", "hasSuccess", "novalidation", "status"] }, { kind: "component", type: i2.MessagesComponent, selector: "c8y-messages", inputs: ["show", "defaults", "helpMessage"] }, { kind: "directive", type: i2.RequiredInputPlaceholderDirective, selector: "input[required], input[formControlName]" }, { kind: "directive", type: i2.RangeDirective, selector: "input[type=\"range\"]" }, { kind: "component", type: i2.RangeComponent, selector: "c8y-range", inputs: ["valueDisplayMode"] }, { kind: "ngmodule", type: IconSelectorModule }, { kind: "component", type: i6.IconSelectorWrapperComponent, selector: "c8y-icon-selector-wrapper", inputs: ["canRemoveIcon", "selectedIcon", "iconSize"], outputs: ["onSelect"] }, { kind: "ngmodule", type: MapModule }, { kind: "component", type: i1.MapComponent, selector: "c8y-map", inputs: ["config", "assets", "polyline$", "polylineOptions"], outputs: ["onRealtimeUpdate", "onMove", "onMoveEnd", "onZoomStart", "onZoomEnd", "onMap", "onInit"] }, { kind: "ngmodule", type: TooltipModule }, { 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"] }], viewProviders: [{ provide: ControlContainer, useExisting: NgForm }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: MapWidgetConfigComponent, decorators: [{ type: Component, args: [{ selector: 'c8y-map-widget-config', viewProviders: [{ provide: ControlContainer, useExisting: NgForm }], standalone: true, imports: [ NgCommonModule, NgFormsModule, CommonModule, FormsModule, IconSelectorModule, MapModule, AssetLinkPipe, TooltipModule ], template: "<div\n class=\"row p-t-16\"\n *ngIf=\"formConfig\"\n>\n <div class=\"col-xs-2\">\n <c8y-form-group class=\"m-b-0 text-center form-group-sm\">\n <label translate>Marker icon</label>\n <c8y-icon-selector-wrapper\n [canRemoveIcon]=\"true\"\n [selectedIcon]=\"formConfig.icon\"\n (onSelect)=\"selectIcon($event)\"\n ></c8y-icon-selector-wrapper>\n </c8y-form-group>\n </div>\n <div class=\"col-xs-10\">\n <div class=\"row tight-grid separator-bottom\">\n <div class=\"col-xs-4\">\n <div class=\"form-group form-group-sm\">\n <label translate>Zoom level</label>\n <c8y-range\n class=\"label-bottom\"\n name=\"zoomLevel\"\n #range\n [(ngModel)]=\"formConfig.zoomLevel\"\n (change)=\"zoomLevelChanged()\"\n >\n <input\n type=\"range\"\n min=\"2\"\n max=\"18\"\n step=\"1\"\n />\n </c8y-range>\n </div>\n </div>\n <div class=\"col-xs-8\">\n <c8y-form-group class=\"form-group-sm m-b-8\">\n <label translate>Center bound</label>\n <div class=\"input-group input-group-sm\">\n <input\n class=\"form-control\"\n placeholder=\"{{ 'lat.`latitude`' | translate }}\"\n name=\"centerLat\"\n type=\"number\"\n required\n [(ngModel)]=\"formConfig.center[0]\"\n (change)=\"changeCenter()\"\n (keydown.enter)=\"changeCenterOnEnterKey($event)\"\n min=\"-90\"\n max=\"90\"\n step=\"0.1\"\n />\n <input\n class=\"form-control\"\n placeholder=\"{{ 'lng.`longitude`' | translate }}\"\n name=\"centerLng\"\n type=\"number\"\n required\n min=\"-180\"\n max=\"180\"\n [(ngModel)]=\"formConfig.center[1]\"\n (change)=\"changeCenter()\"\n (keydown.enter)=\"changeCenterOnEnterKey($event)\"\n min=\"-180\"\n max=\"180\"\n step=\"0.1\"\n />\n <div class=\"input-group-btn\">\n <button\n class=\"btn btn-default\"\n [attr.aria-label]=\"'Use your location' | translate\"\n [tooltip]=\"'Use your location' | translate\"\n placement=\"top\"\n container=\"body\"\n (click)=\"useOwnPosition()\"\n >\n <i\n class=\"icon-14\"\n c8yIcon=\"location-arrow\"\n ></i>\n </button>\n </div>\n <div\n class=\"input-group-btn\"\n *ngIf=\"canAutoCenter\"\n >\n <button\n class=\"btn btn-default\"\n [attr.aria-label]=\"'Use selected asset location' | translate\"\n [tooltip]=\"'Use selected asset location' | translate\"\n placement=\"top\"\n container=\"body\"\n (click)=\"centerToAsset()\"\n >\n <i\n class=\"icon-14\"\n c8yIcon=\"location\"\n ></i>\n </button>\n </div>\n </div>\n <c8y-messages\n [helpMessage]=\"'Drag the map to the desired position' | translate\"\n ></c8y-messages>\n </c8y-form-group>\n </div>\n </div>\n\n <div class=\"row tight-grid p-t-8 d-flex a-i-center\">\n <div class=\"col-xs-6\">\n <c8y-form-group class=\"m-b-0 form-group-sm\">\n <div class=\"c8y-select-wrapper\">\n <select\n class=\"form-control\"\n title=\"{{ 'Refresh options`options for refreshing a view`' | translate }}\"\n id=\"selectExample\"\n name=\"refreshSelection\"\n [(ngModel)]=\"refreshOption\"\n (change)=\"updateRefreshOption()\"\n >\n <option\n [title]=\"'Only refreshing on interaction' | translate\"\n value=\"none\"\n translate\n >\n No automatic refresh\n </option>\n <option\n [title]=\"'Refreshing after the given interval and on interaction' | translate\"\n value=\"interval\"\n *ngIf=\"!isPositionedDevice\"\n translate\n >\n Use refresh interval\n </option>\n <option\n [title]=\"\n 'Refreshing after the given interval and on interaction, synchronized globally'\n | translate\n \"\n value=\"dashboard-auto-refresh-context\"\n *ngIf=\"!isPositionedDevice\"\n translate\n >\n Use global refresh interval\n </option>\n <option\n [title]=\"'Live updating on each position change' | translate\"\n value=\"realtime\"\n *ngIf=\"isPositionedDevice\"\n translate\n >\n Realtime\n </option>\n <option\n [title]=\"'Bind widget to dashboard realtime context' | translate\"\n value=\"dashboard-realtime-context\"\n *ngIf=\"isPositionedDevice\"\n translate\n >\n Dashboard realtime context\n </option>\n </select>\n </div>\n </c8y-form-group>\n </div>\n <div class=\"col-xs-8\">\n <div class=\"form-group form-group-sm m-b-0\">\n <c8y-range\n class=\"label-bottom\"\n name=\"refreshInterval\"\n #intervalRange\n *ngIf=\"refreshOption === 'interval'\"\n [(ngModel)]=\"formConfig.refreshInterval\"\n >\n <ng-template #c8yRangeValue>\n <div>\n <span\n [translateParams]=\"{ intervalInSeconds: intervalRange.value * 0.001 }\"\n translate\n ngNonBindable\n >\n {{ intervalInSeconds }} s\n </span>\n </div>\n </ng-template>\n <input\n type=\"range\"\n min=\"5000\"\n max=\"100000\"\n step=\"1000\"\n />\n </c8y-range>\n </div>\n <label\n class=\"c8y-switch c8y-switch--inline\"\n *ngIf=\"refreshOption === 'realtime' || refreshOption === 'dashboard-realtime-context'\"\n >\n <input\n name=\"follow\"\n type=\"checkbox\"\n [(ngModel)]=\"formConfig.follow\"\n />\n <span></span>\n <span\n class=\"text-12\"\n translate\n >\n Follow selected\n </span>\n </label>\n </div>\n </div>\n </div>\n</div>\n\n<div\n class=\"p-t-16 p-b-16\"\n style=\"width: 100%; height: 240px\"\n>\n <c8y-map\n *ngIf=\"config.mapConfig\"\n [assets]=\"assets\"\n [config]=\"config.mapConfig\"\n (onMove)=\"onPreviewMapMove($event)\"\n (onZoomStart)=\"onPreviewZoomStart()\"\n (onZoomEnd)=\"onPreviewZoomEnd($event)\"\n (onInit)=\"previewMapInit($event)\"\n ></c8y-map>\n</div>\n" }] }], ctorParameters: () => [{ type: i1.MapService }, { type: i2.AlertService }, { type: i3.TranslateService }, { type: i8.Observable, decorators: [{ type: Inject, args: [MAP_DEFAULT_CONFIG] }] }], propDecorators: { config: [{ type: Input }], previewMap: [{ type: ViewChild, args: [MapComponent] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFwLXdpZGdldC1jb25maWcuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vd2lkZ2V0cy9pbXBsZW1lbnRhdGlvbnMvbWFwL21hcC13aWRnZXQtY29uZmlnLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3dpZGdldHMvaW1wbGVtZW50YXRpb25zL21hcC9tYXAtd2lkZ2V0LWNvbmZpZy5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsU0FBUyxFQUNULE1BQU0sRUFDTixLQUFLLEVBS0wsU0FBUyxFQUNWLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxZQUFZLElBQUksY0FBYyxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDakUsT0FBTyxFQUFFLFdBQVcsSUFBSSxhQUFhLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUM5RCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDMUQsT0FBTyxFQUNMLFlBQVksRUFDWixhQUFhLEVBQ2IsWUFBWSxFQUNaLFdBQVcsRUFDWCxPQUFPLEVBQ1IsTUFBTSxxQkFBcUIsQ0FBQztBQUU3QixPQUFPLEVBRUwsa0JBQWtCLEVBQ2xCLFlBQVksRUFDWixTQUFTLEVBQ1QsVUFBVSxFQUVYLE1BQU0seUJBQXlCLENBQUM7QUFDakMsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFFdkQsT0FBTyxFQUFFLFVBQVUsRUFBRSxPQUFPLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDM0MsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRTNDLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLG1DQUFtQyxDQUFDO0FBQ3ZFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQzs7Ozs7Ozs7OztBQWtCdEQsTUFBTSxPQUFP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cnQge1xuICBDb21wb25lbnQsXG4gIEluamVjdCxcbiAgSW5wdXQsXG4gIE9uQ2hhbmdlcyxcbiAgT25EZXN0cm95LFxuICBPbkluaXQsXG4gIFNpbXBsZUNoYW5nZXMsXG4gIFZpZXdDaGlsZFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IENvbW1vbk1vZHVsZSBhcyBOZ0NvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBGb3Jtc01vZHVsZSBhcyBOZ0Zvcm1zTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgQ29udHJvbENvbnRhaW5lciwgTmdGb3JtIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHtcbiAgQWxlcnRTZXJ2aWNlLFxuICBBc3NldExpbmtQaXBlLFxuICBDb21tb25Nb2R1bGUsXG4gIEZvcm1zTW9kdWxlLFxuICBnZXR0ZXh0XG59IGZyb20gJ0BjOHkvbmd4LWNvbXBvbmVudHMnO1xuaW1wb3J0IHR5cGUgeyBNYXBEZWZhdWx0Q29uZmlnIH0gZnJvbSAnQGM4eS9vcHRpb25zJztcbmltcG9ydCB7XG4gIENsdXN0ZXJNYXBDb25maWcsXG4gIE1BUF9ERUZBVUxUX0NPTkZJRyxcbiAgTWFwQ29tcG9uZW50LFxuICBNYXBNb2R1bGUsXG4gIE1hcFNlcnZpY2UsXG4gIFBvc2l0aW9uTWFuYWdlZE9iamVjdFxufSBmcm9tICdAYzh5L25neC1jb21wb25lbnRzL21hcCc7XG5pbXBvcnQgeyBUcmFuc2xhdGVTZXJ2aWNlIH0gZnJvbSAnQG5neC10cmFuc2xhdGUvY29yZSc7XG5pbXBvcnQgdHlwZSBMIGZyb20gJ2xlYWZsZXQnO1xuaW1wb3J0IHsgT2JzZXJ2YWJsZSwgU3ViamVjdCB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgdGFrZVVudGlsIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgTWFwV2lkZ2V0Q29uZmlnLCBNYXBSZWZyZXNoT3B0aW9uIH0gZnJvbSAnLi9tYXAtd2lkZ2V0Lm1vZGVsJztcbmltcG9ydCB7IEljb25TZWxlY3Rvck1vZHVsZSB9IGZyb20gJ0BjOHkvbmd4LWNvbXBvbmVudHMvaWNvbi1zZWxlY3Rvcic7XG5pbXBvcnQgeyBUb29sdGlwTW9kdWxlIH0gZnJvbSAnbmd4LWJvb3RzdHJhcC90b29sdGlwJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnYzh5LW1hcC13aWRnZXQtY29uZmlnJyxcbiAgdGVtcGxhdGVVcmw6ICcuL21hcC13aWRnZXQtY29uZmlnLmNvbXBvbmVudC5odG1sJyxcbiAgdmlld1Byb3ZpZGVyczogW3sgcHJvdmlkZTogQ29udHJvbENvbnRhaW5lciwgdXNlRXhpc3Rpbmc6IE5nRm9ybSB9XSxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW1xuICAgIE5nQ29tbW9uTW9kdWxlLFxuICAgIE5nRm9ybXNNb2R1bGUsXG4gICAgQ29tbW9uTW9kdWxlLFxuICAgIEZvcm1zTW9kdWxlLFxuICAgIEljb25TZWxlY3Rvck1vZHVsZSxcbiAgICBNYXBNb2R1bGUsXG4gICAgQXNzZXRMaW5rUGlwZSxcbiAgICBUb29sdGlwTW9kdWxlXG4gIF1cbn0pXG5leHBvcnQgY2xhc3MgTWFwV2lkZ2V0Q29uZmlnQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkNoYW5nZXMsIE9uRGVzdHJveSB7XG4gIEBJbnB1dCgpIGNvbmZpZzogTWFwV2lkZ2V0Q29uZmlnID0ge1xuICAgIG1hcENvbmZpZzogdW5kZWZpbmVkXG4gIH07XG5cbiAgZm9ybUNvbmZpZzogQ2x1c3Rlck1hcENvbmZpZztcblxuICBjYW5BdXRvQ2VudGVyID0gdHJ1ZTtcbiAgaXNQb3NpdGlvbmVkRGV2aWNlID0gZmFsc2U7XG4gIGFzc2V0czogUG9zaXRpb25NYW5hZ2VkT2JqZWN0W107XG4gIHJlZnJlc2hPcHRpb246IE1hcFJlZnJlc2hPcHRpb24gPSAnbm9uZSc7XG5cbiAgcHJpdmF0ZSBkZXN0cm95ZWQkID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcbiAgcHJpdmF0ZSBsZWFmbGV0OiB0eXBlb2YgTDtcbiAgcHJpdmF0ZSBjZW50ZXJJY29uOiBMLk1hcmtlcjtcbiAgLy8gSlMgcHJlY2lzaW9uIGZvciBmbG9hdGluZyBwb2ludCBudW1iZXIgaXMgMTUgZm9yIDY0LWJpdCBhbmQgYmVjYXVzZSBvZiB0aGlzIHByb3ZpZGVkIHRvIGxlYWZsZXQgYXJlIHJlY2FsY3VsYXRlZFxuICAvLyB0byB2YWx1ZXMgYWxtb3N0LWxpa2UgcHJvdmlkZWQgKGUuZy4gMCBpcyByZWNhbGN1bGF0ZWQgdG8gMS40NmUtMTQ7IGZvciAxODAgaXQncyAxODAuMDAwMDAwMDAwMDAwMDMpLlxuICAvLyBUbyBlbnN1cmUgcHJvdmlkZWQgdmFsdWUgaGFzIG5vIGZsb2F0aW5nIHBvaW50IGVycm9yLCBudW1iZXIgbmVlZHMgdG8gYmUgcm91bmRlZCB0byBmaXhlZCBwb2ludCAxMy5cbiAgcHJpdmF0ZSByZWFkb25seSBGSVhFRF9QT0lOVF9ESUdJVFMgPSAxMztcblxuICBAVmlld0NoaWxkKE1hcENvbXBvbmVudClcbiAgcHJldmlld01hcDogTWFwQ29tcG9uZW50O1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgbWFwU2VydmljZTogTWFwU2VydmljZSxcbiAgICBwcml2YXRlIGFsZXJ0U2VydmljZTogQWxlcnRTZXJ2aWNlLFxuICAgIHByaXZhdGUgdHJhbnNsYXRlU2VydmljZTogVHJhbnNsYXRlU2VydmljZSxcbiAgICBASW5qZWN0KE1BUF9ERUZBVUxUX0NPTkZJRykgcHJpdmF0ZSBkZWZhdWx0TWFwQ29uZmlnOiBPYnNlcnZhYmxlPE1hcERlZmF1bHRDb25maWc+XG4gICkge31cblxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICB0aGlzLmRlc3Ryb3llZCQubmV4dCgpO1xuICB9XG5cbiAgbmdPbkluaXQoKSB7XG4gICAgdGhpcy5kZWZhdWx0TWFwQ29uZmlnLnBpcGUodGFrZVVudGlsKHRoaXMuZGVzdHJveWVkJCkpLnN1YnNjcmliZShkZWZhdWx0Q29uZmlnID0+IHtcbiAgICAgIHRoaXMuZm9ybUNvbmZpZyA9IHtcbiAgICAgICAgem9vbUxldmVsOiBkZWZhdWx0Q29uZmlnLnpvb21MZXZlbCxcbiAgICAgICAgY2VudGVyOiBkZWZhdWx0Q29uZmlnLmNlbnRlclxuICAgICAgfTtcbiAgICAgIHRoaXMuaW5pdEZvcm0oKTtcbiAgICB9KTtcbiAgfVxuXG4gIGFzeW5jIGluaXRGb3JtKCkge1xuICAgIGlmICghdGhpcy5jb25maWcubWFwQ29uZmlnKSB7XG4gICAgICB0aGlzLmNvbmZpZy5tYXBDb25maWcgPSB0aGlzLmZvcm1Db25maWc7XG4gICAgfVxuICAgIHRoaXMuZm9ybUNvbmZpZyA9IHtcbiAgICAgIC4uLnRoaXMuZm9ybUNvbmZpZyxcbiAgICAgIC4uLnRoaXMuY29uZmlnLm1hcENvbmZpZyxcbiAgICAgIGRpc2FibGVQYW46IGZhbHNlXG4gICAgfTtcbiAgICBhd2FpdCB0aGlzLnVwZGF0ZUFzc2V0KCk7XG4gIH1cblxuICBhc3luYyBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKSB7XG4gICAgaWYgKFxuICAgICAgY2hhbmdlcy5jb25maWcuY3VycmVudFZhbHVlICE9PSBjaGFuZ2VzLmNvbmZpZy5wcmV2aW91c1ZhbHVlICYmXG4gICAgICAhY2hhbmdlcy5jb25maWcuZmlyc3RDaGFuZ2VcbiAgICApIHtcbiAgICAgIGF3YWl0IHRoaXMudXBkYXRlQXNzZXQoKTtcbiAgICB9XG4gIH1cblxuICBwcmV2aWV3TWFwSW5pdChsZWFmbGV0OiB0eXBlb2YgTCk6IHZvaWQge1xuICAgIHRoaXMubGVhZmxldCA9IGxlYWZsZXQ7XG4gICAgdGhpcy5hZGRDZW50ZXJJY29uKHRoaXMuZm9ybUNvbmZpZy5jZW50ZXJbMF0sIHRoaXMuZm9ybUNvbmZpZy5jZW50ZXJbMV0pO1xuICB9XG5cbiAgb25CZWZvcmVTYXZlKCkge1xuICAgIHRoaXMuY29uZmlnLm1hcENvbmZpZyA9IHRoaXMuZm9ybUNvbmZpZztcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIHpvb21MZXZlbENoYW5nZWQoKSB7XG4gICAgdGhpcy5jb25maWcubWFwQ29uZmlnID0ge1xuICAgICAgLi4udGhpcy5jb25maWcubWFwQ29uZmlnLFxuICAgICAgem9vbUxldmVsOiB0aGlzLmZvcm1Db25maWcuem9vbUxldmVsXG4gICAgfTtcbiAgfVxuXG4gIGNoYW5nZUNlbnRlcigpIHtcbiAgICBpZiAodGhpcy5jZW50ZXJJY29uKSB7XG4gICAgICB0aGlzLmNlbnRlckljb24ucmVtb3ZlKCk7XG4gICAgfVxuICAgIHRoaXMuY29uZmlnLm1hcENvbmZpZyA9IHsgLi4udGhpcy5mb3JtQ29uZmlnLCBjZW50ZXI6IFsuLi50aGlzLmZvcm1Db25maWcuY2VudGVyXSB9O1xuICAgIHRoaXMuYWRkQ2VudGVySWNvbih0aGlzLmZvcm1Db25maWcuY2VudGVyWzBdLCB0aGlzLmZvcm1Db25maWcuY2VudGVyWzFdKTtcbiAgfVxuXG4gIGNoYW5nZUNlbnRlck9uRW50ZXJLZXkoZXZlbnQ6IEtleWJvYXJkRXZlbnQpOiB2b2lkIHtcbiAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIHRoaXMuY2hhbmdlQ2VudGVyKCk7XG4gIH1cblxuICBvblByZXZpZXdab29tU3RhcnQoKSB7XG4gICAgdGhpcy5jZW50ZXJJY29uLnJlbW92ZSgpO1xuICB9XG5cbiAgb25QcmV2aWV3Wm9vbUVuZChldmVudDogTC5MZWFmbGV0RXZlbnQpIHtcbiAgICB0aGlzLmZvcm1Db25maWcuem9vbUxldmVsID0gTWF0aC5mbG9vcihldmVudC50YXJnZXQuZ2V0Wm9vbSgpKTtcbiAgfVxuXG4gIG9uUHJldmlld01hcE1vdmUoZXZlbnQ6IEwuTGVhZmxldEV2ZW50KSB7XG4gICAgaWYgKHRoaXMuY2VudGVySWNvbikge1xuICAgICAgdGhpcy5jZW50ZXJJY29uLnJlbW92ZSgpO1xuICAgIH1cbiAgICBjb25zdCB7IGxhdCwgbG5nIH0gPSBldmVudC50YXJnZXQuZ2V0Q2VudGVyKCk7XG4gICAgY29uc3QgZml4ZWRMYXQgPSArbGF0LnRvRml4ZWQodGhpcy5GSVhFRF9QT0lOVF9ESUdJVFMpO1xuICAgIGNvbnN0IGZpeGVkTG5nID0gK2xuZy50b0ZpeGVkKHRoaXMuRklYRURfUE9JTlRfRElHSVRTKTtcbiAgICB0aGlzLmFkZENlbnRlckljb24oZml4ZWRMYXQsIGZpeGVkTG5nKTtcbiAgICB0aGlzLmZvcm1Db25maWcuY2VudGVyID0gW2ZpeGVkTGF0LCBmaXhlZExuZ107XG4gIH1cblxuICB1c2VPd25Qb3NpdGlvbigpIHtcbiAgICBuYXZpZ2F0b3IuZ2VvbG9jYXRpb24uZ2V0Q3VycmVudFBvc2l0aW9uKCh7IGNvb3JkcyB9KSA9PiB7XG4gICAgICB0aGlzLmZvcm1Db25maWcuY2VudGVyID0gW2Nvb3Jkcy5sYXRpdHVkZSwgY29vcmRzLmxvbmdpdHVkZV07XG4gICAgICB0aGlzLmNoYW5nZUNlbnRlcigpO1xuICAgIH0pO1xuICB9XG5cbiAgY2VudGVyVG9Bc3NldCgpIHtcbiAgICB0aGlzLmZvcm1Db25maWcuY2VudGVyID0gW1xuICAgICAgdGhpcy5jb25maWcuZGV2aWNlLmM4eV9Qb3NpdGlvbi5sYXQsXG4gICAgICB0aGlzLmNvbmZpZy5kZXZpY2UuYzh5X1Bvc2l0aW9uLmxuZ1xuICAgIF07XG4gICAgdGhpcy5jaGFuZ2VDZW50ZXIoKTtcbiAgfVxuXG4gIHVwZGF0ZVJlZnJlc2hPcHRpb24oKSB7XG4gICAgdGhpcy5mb3JtQ29uZmlnLnJlYWx0aW1lID0gdGhpcy5yZWZyZXNoT3B0aW9uID09PSAncmVhbHRpbWUnO1xuICAgIHRoaXMuY29uZmlnLndpZGdldEluc3RhbmNlR2xvYmFsQXV0b1JlZnJlc2hDb250ZXh0ID1cbiAgICAgIHRoaXMucmVmcmVzaE9wdGlvbiA9PT0gJ2Rhc2hib2FyZC1hdXRvLXJlZnJlc2gtY29udGV4dCc7XG4gICAgdGhpcy5mb3JtQ29uZmlnLndpZGdldEluc3RhbmNlR2xvYmFsQXV0b1JlZnJlc2hDb250ZXh0ID1cbiAgICAgIHRoaXMucmVmcmVzaE9wdGlvbiA9PT0gJ2Rhc2hib2FyZC1hdXRvLXJlZnJlc2gtY29udGV4dCc7XG4gICAgaWYgKHRoaXMucmVmcmVzaE9wdGlvbiA9PT0gJ2ludGVydmFsJykge1xuICAgICAgdGhpcy5mb3JtQ29uZmlnLnJlZnJlc2hJbnRlcnZhbCA/Pz0gNTAwMDtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5mb3JtQ29uZmlnLnJlZnJlc2hJbnRlcnZhbCA9IG51bGw7XG4gICAgfVxuICAgIGlmICghdGhpcy5mb3JtQ29uZmlnLnJlYWx0aW1lKSB7XG4gICAgICB0aGlzLmZvcm1Db25maWcuZm9sbG93ID0gZmFsc2U7XG4gICAgfVxuICAgIHRoaXMuY29uZmlnLndpZGdldEluc3RhbmNlR2xvYmFsVGltZUNvbnRleHQgPVxuICAgICAgdGhpcy5yZWZyZXNoT3B0aW9uID09PSAnZGFzaGJvYXJkLXJlYWx0aW1lLWNvbnRleHQnO1xuICAgIGlmICh0aGlzLmNvbmZpZy53aWRnZXRJbnN0YW5jZUdsb2JhbFRpbWVDb250ZXh0KSB7XG4gICAgICB0aGlzLmZvcm1Db25maWcucmVhbHRpbWUgPSBudWxsO1xuICAgIH1cbiAgfVxuXG4gIHNlbGVjdEljb24oaWNvbjogc3RyaW5nKSB7XG4gICAgdGhpcy5mb3JtQ29uZmlnLmljb24gPSBpY29uO1xuICAgIHRoaXMuY29uZmlnLm1hcENvbmZpZy5pY29uID0gaWNvbjtcbiAgICB0aGlzLnByZXZpZXdNYXAucmVmcmVzaE1hcmtlcnMoKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgdXBkYXRlQXNzZXQoKSB7XG4gICAgdGhpcy5jYW5BdXRvQ2VudGVyID0gdGhpcy5tYXBTZXJ2aWNlLmhhc1Bvc2l0aW9uKHRoaXMuY29uZmlnLmRldmljZSk7XG4gICAgdGhpcy5pc1Bvc2l0aW9uZWREZXZpY2UgPSB0aGlzLm1hcFNlcnZpY2UuaXNQb3NpdGlvbmVkRGV2aWNlKHRoaXMuY29uZmlnLmRldmljZSk7XG4gICAgdGhpcy5yZWZyZXNoT3B0aW9uID0gdGhpcy5nZXRSZWZyZXNoT3B0aW9uKCk7XG4gICAgdGhpcy51cGRhdGVSZWZyZXNoT3B0aW9uKCk7XG5cbiAgICBjb25zdCB7IGRhdGEsIHBhZ2luZyB9ID0gYXdhaXQgdGhpcy5tYXBTZXJ2aWNlLmdldEFsbFBvc2l0aW9uTU9zKHRoaXMuY29uZmlnLmRldmljZSk7XG4gICAgdGhpcy5hc3NldHMgPSBkYXRhO1xuICAgIGlmIChwYWdpbmcudG90YWxQYWdlcyA+IDEpIHtcbiAgICAgIHRoaXMuYWxlcnRTZXJ2aWNlLmRhbmdlcihcbiAgICAgICAgZ2V0dGV4dChcbiAgICAgICAgICAnSXQgbWlnaHQgYmUgcG9zc2libGUgdGhhdCBhc3NldHMgYXJlIG5vdCBzaG93biBpbiB0aGUgcHJldmlldywgYXMgdGhlIGN1cnJlbnQgc2VsZWN0aW9uIGhhcyBtb3JlIHRoYW4gNTAwIGFzc2V0cyBhbmQgdGhlIHByZXZpZXcgb25seSBzdXBwb3J0cyBhIG1heGltdW0gb2YgNTAwIGFzc2V0cy4nXG4gICAgICAgIClcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBnZXRSZWZyZXNoT3B0aW9uKCk6IE1hcFJlZnJlc2hPcHRpb24ge1xuICAgIGxldCBvcHRpb246IE1hcFJlZnJlc2hPcHRpb24gPSAnbm9uZSc7XG4gICAgaWYgKHRoaXMuZm9ybUNvbmZpZy5yZWFsdGltZSkge1xuICAgICAgb3B0aW9uID0gJ3JlYWx0aW1lJztcbiAgICB9IGVsc2UgaWYgKHRoaXMuZm9ybUNvbmZpZy5yZWZyZXNoSW50ZXJ2YWwpIHtcbiAgICAgIG9wdGlvbiA9ICdpbnRlcnZhbCc7XG4gICAgfSBlbHNlIGlmICh0aGlzLmNvbmZpZy53aWRnZXRJbnN0YW5jZUdsb2JhbFRpbWVDb250ZXh0KSB7XG4gICAgICBvcHRpb24gPSAnZGFzaGJvYXJkLXJlYWx0aW1lLWNvbnRleHQnO1xuICAgIH0gZWxzZSBpZiAoXG4gICAgICB0aGlzLmNvbmZpZy53aWRnZXRJbnN0YW5jZUdsb2JhbEF1dG9SZWZyZXNoQ29udGV4dCB8fFxuICAgICAgdGhpcy5mb3JtQ29uZmlnLndpZGdldEluc3RhbmNlR2xvYmFsQXV0b1JlZnJlc2hDb250ZXh0XG4gICAgKSB7XG4gICAgICBvcHRpb24gPSAnZGFzaGJvYXJkLWF1dG8tcmVmcmVzaC1jb250ZXh0JztcbiAgICB9XG4gICAgY29uc3QgaXNOb3RBbGxvd2VkT3B0aW9uID1cbiAgICAgICghdGhpcy5pc1Bvc2l0aW9uZWREZXZpY2UgJiYgb3B0aW9uID09PSAnZGFzaGJvYXJkLXJlYWx0aW1lLWNvbnRleHQnKSB8fFxuICAgICAgKCF0aGlzLmlzUG9zaXRpb25lZERldmljZSAmJiBvcHRpb24gPT09ICdyZWFsdGltZScpIHx8XG4gICAgICAodGhpcy5pc1Bvc2l0aW9uZWREZXZpY2UgJiYgb3B0aW9uID09PSAnaW50ZXJ2YWwnKTtcbiAgICBvcHRpb24gPSBpc05vdEFsbG93ZWRPcHRpb24gPyAnbm9uZScgOiBvcHRpb247XG4gICAgcmV0dXJuIG9wdGlvbjtcbiAgfVxuXG4gIHByaXZhdGUgYWRkQ2VudGVySWNvbihsYXQ6IG51bWJlciwgbG5nOiBudW1iZXIpIHtcbiAgICBjb25zdCB0aXRsZVRleHQgPSB0aGlzLnRyYW5zbGF0ZVNlcnZpY2UuaW5zdGFudChnZXR0ZXh0KCdNYXAgY2VudGVyJykpO1xuICAgIGNvbnN0IGljb24gPSB0aGlzLmxlYWZsZXQuZGl2SWNvbih7XG4gICAgICBodG1sOiBgPGkgc3R5bGU9XCJwb2ludGVyLWV2ZW50czogbm9uZVwiIGNsYXNzPVwiYzh5LW1hcC1tYXJrZXItaWNvbiB0ZXh0LW11dGVkIGRsdC1jOHktaWNvbi10YXJnZXQgaWNvbi0yeFwiIHRpdGxlPVwiJHt0aXRsZVRleHR9XCIgLz5gXG4gICAgfSk7XG4gICAgdGhpcy5jZW50ZXJJY29uID0gdGhpcy5sZWFmbGV0Lm1hcmtlcihbbGF0LCBsbmddLCB7XG4gICAgICBpY29uXG4gICAgfSk7XG4gICAgdGhpcy5wcmV2aWV3TWFwLmFkZE1hcmtlclRvTWFwKHRoaXMuY2VudGVySWNvbik7XG4gIH1cbn1cbiIsIjxkaXZcbiAgY2xhc3M9XCJyb3cgcC10LTE2XCJcbiAgKm5nSWY9XCJmb3JtQ29uZmlnXCJcbj5cbiAgPGRpdiBjbGFzcz1cImNvbC14cy0yXCI+XG4gICAgPGM4eS1mb3JtLWdyb3VwIGNsYXNzPVwibS1iLTAgdGV4dC1jZW50ZXIgZm9ybS1ncm91cC1zbVwiPlxuICAgICAgPGxhYmVsIHRyYW5zbGF0ZT5NYXJrZXIgaWNvbjwvbGFiZWw+XG4gICAgICA8Yzh5LWljb24tc2VsZWN0b3Itd3JhcHBlclxuICAgICAgICBbY2FuUmVtb3ZlSWNvbl09XCJ0cnVlXCJcbiAgICAgICAgW3NlbGVjdGVkSWNvbl09XCJmb3JtQ29uZmlnLmljb25cIlxuICAg