UNPKG

@c8y/ngx-components

Version:

Angular modules for Cumulocity IoT applications

67 lines 19.2 kB
import { CommonModule as NgCommonModule } from '@angular/common'; import { Component, computed, inject, input, signal } from '@angular/core'; import { FormsModule as NgFormsModule } from '@angular/forms'; import { InventoryService } from '@c8y/client'; import { AlertService, AppStateService, CommonModule, CoreModule, DatePipe, FormsModule, gettext } from '@c8y/ngx-components'; import * as i0 from "@angular/core"; import * as i1 from "@c8y/ngx-components"; import * as i2 from "@angular/common"; import * as i3 from "@angular/forms"; export class AssetNotesWidgetComponent { constructor() { this.inventory = inject(InventoryService); this.appState = inject(AppStateService); this.alertService = inject(AlertService); this.datePipe = inject(DatePipe); this.config = input(); this.notes = signal(null); this.editable = signal(false); this.isLoading = computed(() => this.notes()?.htmlContent === undefined); this.FRAGMENT = 'c8y_ComponentConfig!assetNotes'; this.ngNonBindableTranslate = computed(() => ({ lastUpdated: this.datePipe.transform(this.notes()?.lastUpdated), user: this.notes()?.user })); } async ngOnInit() { await this.loadNotes(); } toggleEdit() { this.editable.set(!this.editable()); } async save() { try { const updatedNotes = { ...this.notes(), user: this.appState.currentUser.value.id, lastUpdated: new Date().toISOString() }; await this.inventory.update({ id: this.config().device.id, [this.FRAGMENT]: updatedNotes }); this.notes.set(updatedNotes); this.editable.set(false); this.alertService.success(gettext('Notes saved.')); } catch (error) { this.alertService.addServerFailure(error); } } async loadNotes() { try { const device = await this.inventory.detail(this.config().device.id); this.notes.set(device.data[this.FRAGMENT] || { htmlContent: '' }); } catch (error) { this.alertService.addServerFailure(error); } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AssetNotesWidgetComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: AssetNotesWidgetComponent, isStandalone: true, selector: "c8y-asset-notes", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div class=\"fit-h d-flex flex-wrap a-i-stretch\">\n <i\n class=\"c8y-icon c8y-icon-duocolor asset-notes-icon\"\n [c8yIcon]=\"'c8y-notification'\"\n ></i>\n\n @if (!editable()) {\n <div class=\"asset-notes-content\">\n <c8y-loading *ngIf=\"isLoading()\"></c8y-loading>\n <div class=\"text-break-word asset-notes-body\">\n @if (notes()?.htmlContent && !isLoading()) {\n <span\n class=\"markdown-content d-inline-block\"\n [innerHTML]=\"notes()?.htmlContent | markdownToHtml | async\"\n ></span>\n } @else if (!notes()?.htmlContent) {\n <span>\n {{ 'No notes yet.' | translate }}\n </span>\n }\n\n <button\n class=\"btn btn-link btn-sm\"\n title=\"{{ 'Edit' | translate }}\"\n type=\"button\"\n (click)=\"toggleEdit()\"\n >\n <i c8yIcon=\"pencil\"></i>\n {{ 'Edit' | translate }}\n </button>\n </div>\n </div>\n <div class=\"asset-notes-footer m-t-8\">\n <small class=\"text-muted\">\n <em\n *ngIf=\"notes()?.lastUpdated\"\n ngNonBindable\n translate\n [translateParams]=\"ngNonBindableTranslate()\"\n >\n {{ lastUpdated }} by {{ user }}\n </em>\n </small>\n </div>\n } @else {\n <div class=\"fit-h flex-grow\">\n <div class=\"d-flex a-i-stretch fit-h\">\n <textarea\n class=\"form-control fit-h text-monospace\"\n [attr.aria-label]=\"'Notes' | translate\"\n rows=\"5\"\n [(ngModel)]=\"notes().htmlContent\"\n c8y-code-editor\n ></textarea>\n <div class=\"input-group-btn a-s-center\">\n <button\n class=\"btn btn-dot\"\n title=\"{{ 'Save' | translate }}\"\n type=\"button\"\n (click)=\"save()\"\n >\n <i c8yIcon=\"check\"></i>\n </button>\n </div>\n <div class=\"input-group-btn a-s-center\">\n <button\n class=\"btn btn-dot\"\n title=\"{{ 'Cancel' | translate }}\"\n type=\"button\"\n (click)=\"toggleEdit()\"\n >\n <i c8yIcon=\"times\"></i>\n </button>\n </div>\n </div>\n </div>\n }\n</div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "pipe", type: i1.C8yTranslatePipe, name: "translate" }, { kind: "directive", type: i1.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }, { kind: "component", type: i1.LoadingComponent, selector: "c8y-loading", inputs: ["layout", "progress", "message"] }, { kind: "pipe", type: i1.MarkdownToHtmlPipe, name: "markdownToHtml" }, { kind: "ngmodule", type: NgCommonModule }, { kind: "ngmodule", type: CoreModule }, { kind: "directive", type: i3.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: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: NgFormsModule }, { kind: "ngmodule", type: FormsModule }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AssetNotesWidgetComponent, decorators: [{ type: Component, args: [{ selector: 'c8y-asset-notes', standalone: true, imports: [CommonModule, NgCommonModule, CoreModule, NgFormsModule, FormsModule, DatePipe], template: "<div class=\"fit-h d-flex flex-wrap a-i-stretch\">\n <i\n class=\"c8y-icon c8y-icon-duocolor asset-notes-icon\"\n [c8yIcon]=\"'c8y-notification'\"\n ></i>\n\n @if (!editable()) {\n <div class=\"asset-notes-content\">\n <c8y-loading *ngIf=\"isLoading()\"></c8y-loading>\n <div class=\"text-break-word asset-notes-body\">\n @if (notes()?.htmlContent && !isLoading()) {\n <span\n class=\"markdown-content d-inline-block\"\n [innerHTML]=\"notes()?.htmlContent | markdownToHtml | async\"\n ></span>\n } @else if (!notes()?.htmlContent) {\n <span>\n {{ 'No notes yet.' | translate }}\n </span>\n }\n\n <button\n class=\"btn btn-link btn-sm\"\n title=\"{{ 'Edit' | translate }}\"\n type=\"button\"\n (click)=\"toggleEdit()\"\n >\n <i c8yIcon=\"pencil\"></i>\n {{ 'Edit' | translate }}\n </button>\n </div>\n </div>\n <div class=\"asset-notes-footer m-t-8\">\n <small class=\"text-muted\">\n <em\n *ngIf=\"notes()?.lastUpdated\"\n ngNonBindable\n translate\n [translateParams]=\"ngNonBindableTranslate()\"\n >\n {{ lastUpdated }} by {{ user }}\n </em>\n </small>\n </div>\n } @else {\n <div class=\"fit-h flex-grow\">\n <div class=\"d-flex a-i-stretch fit-h\">\n <textarea\n class=\"form-control fit-h text-monospace\"\n [attr.aria-label]=\"'Notes' | translate\"\n rows=\"5\"\n [(ngModel)]=\"notes().htmlContent\"\n c8y-code-editor\n ></textarea>\n <div class=\"input-group-btn a-s-center\">\n <button\n class=\"btn btn-dot\"\n title=\"{{ 'Save' | translate }}\"\n type=\"button\"\n (click)=\"save()\"\n >\n <i c8yIcon=\"check\"></i>\n </button>\n </div>\n <div class=\"input-group-btn a-s-center\">\n <button\n class=\"btn btn-dot\"\n title=\"{{ 'Cancel' | translate }}\"\n type=\"button\"\n (click)=\"toggleEdit()\"\n >\n <i c8yIcon=\"times\"></i>\n </button>\n </div>\n </div>\n </div>\n }\n</div>\n" }] }] }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXNzZXQtbm90ZXMtd2lkZ2V0LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3dpZGdldHMvaW1wbGVtZW50YXRpb25zL2Fzc2V0LW5vdGVzL2Fzc2V0LW5vdGVzLXdpZGdldC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi93aWRnZXRzL2ltcGxlbWVudGF0aW9ucy9hc3NldC1ub3Rlcy9hc3NldC1ub3Rlcy13aWRnZXQuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFlBQVksSUFBSSxjQUFjLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNqRSxPQUFPLEVBQUUsU0FBUyxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUF1QixNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDaEcsT0FBTyxFQUFFLFdBQVcsSUFBSSxhQUFhLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUM5RCxPQUFPLEVBQWtCLGdCQUFnQixFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQy9ELE9BQU8sRUFDTCxZQUFZLEVBQ1osZUFBZSxFQUNmLFlBQVksRUFDWixVQUFVLEVBQ1YsUUFBUSxFQUNSLFdBQVcsRUFDWCxPQUFPLEVBQ1IsTUFBTSxxQkFBcUIsQ0FBQzs7Ozs7QUFnQjdCLE1BQU0sT0FBTyx5QkFBeUI7SUFOdEM7UUFPVSxjQUFTLEdBQUcsTUFBTSxDQUFDLGdCQUFnQixDQUFDLENBQUM7UUFDckMsYUFBUSxHQUFHLE1BQU0sQ0FBQyxlQUFlLENBQUMsQ0FBQztRQUNuQyxpQkFBWSxHQUFHLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUNwQyxhQUFRLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBRXBDLFdBQU0sR0FBa0MsS0FBSyxFQUFFLENBQUM7UUFFaEQsVUFBSyxHQUFHLE1BQU0sQ0FBb0IsSUFBSSxDQUFDLENBQUM7UUFDeEMsYUFBUSxHQUFH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bmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBDb21wb25lbnQsIGNvbXB1dGVkLCBpbmplY3QsIGlucHV0LCBJbnB1dFNpZ25hbCwgT25Jbml0LCBzaWduYWwgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEZvcm1zTW9kdWxlIGFzIE5nRm9ybXNNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBJTWFuYWdlZE9iamVjdCwgSW52ZW50b3J5U2VydmljZSB9IGZyb20gJ0BjOHkvY2xpZW50JztcbmltcG9ydCB7XG4gIEFsZXJ0U2VydmljZSxcbiAgQXBwU3RhdGVTZXJ2aWNlLFxuICBDb21tb25Nb2R1bGUsXG4gIENvcmVNb2R1bGUsXG4gIERhdGVQaXBlLFxuICBGb3Jtc01vZHVsZSxcbiAgZ2V0dGV4dFxufSBmcm9tICdAYzh5L25neC1jb21wb25lbnRzJztcblxuaW50ZXJmYWNlIEFzc2V0Tm90ZXMge1xuICB1c2VyOiBzdHJpbmc7XG4gIGxhc3RVcGRhdGVkOiBzdHJpbmc7XG4gIGh0bWxDb250ZW50OiBzdHJpbmc7XG59XG5cbmV4cG9ydCB0eXBlIEFzc2V0Tm90ZXNDb25maWcgPSB7IGRldmljZTogUGFydGlhbDxJTWFuYWdlZE9iamVjdD4gfTtcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnYzh5LWFzc2V0LW5vdGVzJyxcbiAgdGVtcGxhdGVVcmw6ICcuL2Fzc2V0LW5vdGVzLXdpZGdldC5jb21wb25lbnQuaHRtbCcsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtDb21tb25Nb2R1bGUsIE5nQ29tbW9uTW9kdWxlLCBDb3JlTW9kdWxlLCBOZ0Zvcm1zTW9kdWxlLCBGb3Jtc01vZHVsZSwgRGF0ZVBpcGVdXG59KVxuZXhwb3J0IGNsYXNzIEFzc2V0Tm90ZXNXaWRnZXRDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQge1xuICBwcml2YXRlIGludmVudG9yeSA9IGluamVjdChJbnZlbnRvcnlTZXJ2aWNlKTtcbiAgcHJpdmF0ZSBhcHBTdGF0ZSA9IGluamVjdChBcHBTdGF0ZVNlcnZpY2UpO1xuICBwcml2YXRlIGFsZXJ0U2VydmljZSA9IGluamVjdChBbGVydFNlcnZpY2UpO1xuICBwcml2YXRlIGRhdGVQaXBlID0gaW5qZWN0KERhdGVQaXBlKTtcblxuICBjb25maWc6IElucHV0U2lnbmFsPEFzc2V0Tm90ZXNDb25maWc+ID0gaW5wdXQoKTtcblxuICBub3RlcyA9IHNpZ25hbDxBc3NldE5vdGVzIHwgbnVsbD4obnVsbCk7XG4gIGVkaXRhYmxlID0gc2lnbmFsKGZhbHNlKTtcbiAgaXNMb2FkaW5nID0gY29tcHV0ZWQoKCkgPT4gdGhpcy5ub3RlcygpPy5odG1sQ29udGVudCA9PT0gdW5kZWZpbmVkKTtcblxuICBwcml2YXRlIHJlYWRvbmx5IEZSQUdNRU5UID0gJ2M4eV9Db21wb25lbnRDb25maWchYXNzZXROb3Rlcyc7XG4gIG5nTm9uQmluZGFibGVUcmFuc2xhdGUgPSBjb21wdXRlZCgoKSA9PiAoe1xuICAgIGxhc3RVcGRhdGVkOiB0aGlzLmRhdGVQaXBlLnRyYW5zZm9ybSh0aGlzLm5vdGVzKCk/Lmxhc3RVcGRhdGVkKSxcbiAgICB1c2VyOiB0aGlzLm5vdGVzKCk/LnVzZXJcbiAgfSkpO1xuXG4gIGFzeW5jIG5nT25Jbml0KCkge1xuICAgIGF3YWl0IHRoaXMubG9hZE5vdGVzKCk7XG4gIH1cblxuICB0b2dnbGVFZGl0KCkge1xuICAgIHRoaXMuZWRpdGFibGUuc2V0KCF0aGlzLmVkaXRhYmxlKCkpO1xuICB9XG5cbiAgYXN5bmMgc2F2ZSgpIHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgdXBkYXRlZE5vdGVzID0ge1xuICAgICAgICAuLi50aGlzLm5vdGVzKCksXG4gICAgICAgIHVzZXI6IHRoaXMuYXBwU3RhdGUuY3VycmVudFVzZXIudmFsdWUuaWQsXG4gICAgICAgIGxhc3RVcGRhdGVkOiBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKClcbiAgICAgIH07XG5cbiAgICAgIGF3YWl0IHRoaXMuaW52ZW50b3J5LnVwZGF0ZSh7XG4gICAgICAgIGlkOiB0aGlzLmNvbmZpZygpLmRldmljZS5pZCxcbiAgICAgICAgW3RoaXMuRlJBR01FTlRdOiB1cGRhdGVkTm90ZXNcbiAgICAgIH0pO1xuXG4gICAgICB0aGlzLm5vdGVzLnNldCh1cGRhdGVkTm90ZXMpO1xuICAgICAgdGhpcy5lZGl0YWJsZS5zZXQoZmFsc2UpO1xuICAgICAgdGhpcy5hbGVydFNlcnZpY2Uuc3VjY2VzcyhnZXR0ZXh0KCdOb3RlcyBzYXZlZC4nKSk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHRoaXMuYWxlcnRTZXJ2aWNlLmFkZFNlcnZlckZhaWx1cmUoZXJyb3IpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgbG9hZE5vdGVzKCkge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBkZXZpY2UgPSBhd2FpdCB0aGlzLmludmVudG9yeS5kZXRhaWwodGhpcy5jb25maWcoKS5kZXZpY2UuaWQpO1xuICAgICAgdGhpcy5ub3Rlcy5zZXQoZGV2aWNlLmRhdGFbdGhpcy5GUkFHTUVOVF0gfHwgeyBodG1sQ29udGVudDogJycgfSk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHRoaXMuYWxlcnRTZXJ2aWNlLmFkZFNlcnZlckZhaWx1cmUoZXJyb3IpO1xuICAgIH1cbiAgfVxufVxuIiwiPGRpdiBjbGFzcz1cImZpdC1oIGQtZmxleCBmbGV4LXdyYXAgYS1pLXN0cmV0Y2hcIj5cbiAgPGlcbiAgICBjbGFzcz1cImM4eS1pY29uIGM4eS1pY29uLWR1b2NvbG9yIGFzc2V0LW5vdGVzLWljb25cIlxuICAgIFtjOHlJY29uXT1cIidjOHktbm90aWZpY2F0aW9uJ1wiXG4gID48L2k+XG5cbiAgQGlmICghZWRpdGFibGUoKSkge1xuICAgIDxkaXYgY2xhc3M9XCJhc3NldC1ub3Rlcy1jb250ZW50XCI+XG4gICAgICA8Yzh5LWxvYWRpbmcgKm5nSWY9XCJpc0xvYWRpbmcoKVwiPjwvYzh5LWxvYWRpbmc+XG4gICAgICA8ZGl2IGNsYXNzPVwidGV4dC1icmVhay13b3JkIGFzc2V0LW5vdGVzLWJvZHlcIj5cbiAgICAgICAgQGlmIChub3RlcygpPy5odG1sQ29udGVudCAmJiAhaXNMb2FkaW5nKCkpIHtcbiAgICAgICAgICA8c3BhblxuICAgICAgICAgICAgY2xhc3M9XCJtYXJrZG93bi1jb250ZW50IGQtaW5saW5lLWJsb2NrXCJcbiAgICAgICAgICAgIFtpbm5lckhUTUxdPVwibm90ZXMoKT8uaHRtbENvbnRlbnQgfCBtYXJrZG93blRvSHRtbCB8IGFzeW5jXCJcbiAgICAgICAgICA+PC9zcGFuPlxuICAgICAgICB9IEBlbHNlIGlmICghbm90ZXMoKT8uaHRtbENvbnRlbnQpIHtcbiAgICAgICAgICA8c3Bhbj5cbiAgICAgICAgICAgIHt7ICdObyBub3RlcyB5ZXQuJyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgfVxuXG4gICAgICAgIDxidXR0b25cbiAgICAgICAgICBjbGFzcz1cImJ0biBidG4tbGluayBidG4tc21cIlxuICAgICAgICAgIHRpdGxlPVwie3sgJ0VkaXQnIHwgdHJhbnNsYXRlIH19XCJcbiAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAoY2xpY2spPVwidG9nZ2xlRWRpdCgpXCJcbiAgICAgICAgPlxuICAgICAgICAgIDxpIGM4eUljb249XCJwZW5jaWxcIj48L2k+XG4gICAgICAgICAge3sgJ0VkaXQnIHwgdHJhbnNsYXRlIH19XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cImFzc2V0LW5vdGVzLWZvb3RlciBtLXQtOFwiPlxuICAgICAgPHNtYWxsIGNsYXNzPVwidGV4dC1tdXRlZFwiPlxuICAgICAgICA8ZW1cbiAgICAgICAgICAqbmdJZj1cIm5vdGVzKCk/Lmxhc3RVcGRhdGVkXCJcbiAgICAgICAgICBuZ05vbkJpbmRhYmxlXG4gICAgICAgICAgdHJhbnNsYXRlXG4gICAgICAgICAgW3RyYW5zbGF0ZVBhcmFtc109XCJuZ05vbkJpbmRhYmxlVHJhbnNsYXRlKClcIlxuICAgICAgICA+XG4gICAgICAgICAge3sgbGFzdFVwZGF0ZWQgfX0gYnkge3sgdXNlciB9fVxuICAgICAgICA8L2VtPlxuICAgICAgPC9zbWFsbD5cbiAgICA8L2Rpdj5cbiAgfSBAZWxzZSB7XG4gICAgPGRpdiBjbGFzcz1cImZpdC1oIGZsZXgtZ3Jvd1wiPlxuICAgICAgPGRpdiBjbGFzcz1cImQtZmxleCBhLWktc3RyZXRjaCBmaXQtaFwiPlxuICAgICAgICA8dGV4dGFyZWFcbiAgICAgICAgICBjbGFzcz1cImZvcm0tY29udHJvbCBmaXQtaCB0ZXh0LW1vbm9zcGFjZVwiXG4gICAgICAgICAgW2F0dHIuYXJpYS1sYWJlbF09XCInTm90ZXMnIHwgdHJhbnNsYXRlXCJcbiAgICAgICAgICByb3dzPVwiNVwiXG4gICAgICAgICAgWyhuZ01vZGVsKV09XCJub3RlcygpLmh0bWxDb250ZW50XCJcbiAgICAgICAgICBjOHktY29kZS1lZGl0b3JcbiAgICAgICAgPjwvdGV4dGFyZWE+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJpbnB1dC1ncm91cC1idG4gYS1zLWNlbnRlclwiPlxuICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgIGNsYXNzPVwiYnRuIGJ0bi1kb3RcIlxuICAgICAgICAgICAgdGl0bGU9XCJ7eyAnU2F2ZScgfCB0cmFuc2xhdGUgfX1cIlxuICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAoY2xpY2spPVwic2F2ZSgpXCJcbiAgICAgICAgICA+XG4gICAgICAgICAgICA8aSBjOHlJY29uPVwiY2hlY2tcIj48L2k+XG4gICAgICAgICAgPC9idXR0b24+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8ZGl2IGNsYXNzPVwiaW5wdXQtZ3JvdXAtYnRuIGEtcy1jZW50ZXJcIj5cbiAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICBjbGFzcz1cImJ0biBidG4tZG90XCJcbiAgICAgICAgICAgIHRpdGxlPVwie3sgJ0NhbmNlbCcgfCB0cmFuc2xhdGUgfX1cIlxuICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAoY2xpY2spPVwidG9nZ2xlRWRpdCgpXCJcbiAgICAgICAgICA+XG4gICAgICAgICAgICA8aSBjOHlJY29uPVwidGltZXNcIj48L2k+XG4gICAgICAgICAgPC9idXR0b24+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG4gIH1cbjwvZGl2PlxuIl19