UNPKG

notify-dash

Version:

A modern, beautiful toast notification library for Angular

174 lines (168 loc) 33.7 kB
import { Component } from '@angular/core'; import * as i0 from "@angular/core"; import * as i1 from "./toast.service"; import * as i2 from "@angular/platform-browser"; import * as i3 from "@angular/common"; export class ToastComponent { constructor(toastService, sanitizer) { this.toastService = toastService; this.sanitizer = sanitizer; this.toasts = []; } dismissToast(id) { const toastElement = document.getElementById(`toast-${id}`); if (toastElement) { const progressBar = toastElement.querySelector('.progress-bar'); if (progressBar) { progressBar.style.animation = 'none'; } toastElement.classList.remove('toast-enter'); toastElement.classList.add('toast-exit'); // Clear the timeout to prevent duplicate dismissals const toast = this.toasts.find(t => t.id === id); if (toast && toast.timeoutId) { clearTimeout(toast.timeoutId); } setTimeout(() => { this.toastService.hide(id); }, 300); } } ngOnInit() { this.subscription = this.toastService.getToasts().subscribe(toasts => { // Filter out toasts that already have timeouts const newToasts = toasts.filter((toast) => !toast.timeoutId); // Set timeouts only for new toasts newToasts.forEach((toast) => { const timeoutId = setTimeout(() => { const toastElement = document.getElementById(`toast-${toast.id}`); if (toastElement) { toastElement.classList.remove('toast-enter'); toastElement.classList.add('toast-exit'); setTimeout(() => { this.toastService.hide(toast.id); }, 300); } }, 4700); toast.timeoutId = timeoutId; }); this.toasts = toasts; }); } ngOnDestroy() { // Clear all timeouts this.toasts.forEach((toast) => { if (toast.timeoutId) { clearTimeout(toast.timeoutId); } }); this.subscription?.unsubscribe(); } getUniquePositions() { return [...new Set(this.toasts.map(t => t.position || 'top-right'))]; } getPositionClasses(position) { return position; } getToastClasses(type) { return type; } getGlowClass(type) { return `glow-${type}`; } getIconContainerClasses(type) { return type; } getToastsByPosition(position) { return this.toasts.filter(t => (t.position || 'top-right') === position); } getIcon(type) { const icons = { success: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="currentColor"> <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"></path> </svg>`, error: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="currentColor"> <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clip-rule="evenodd"></path> </svg>`, warning: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="currentColor"> <path fill-rule="evenodd" d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z" clip-rule="evenodd"></path> </svg>`, info: `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="currentColor"> <path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2h-1V9z" clip-rule="evenodd"></path> </svg>` }; return this.sanitizer.bypassSecurityTrustHtml(icons[type] || icons.info); } getTitle(type) { const titles = { success: 'Success!', error: 'Error!', warning: 'Warning!', info: 'Information' }; return titles[type] || titles.info; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ToastComponent, deps: [{ token: i1.ToastService }, { token: i2.DomSanitizer }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: ToastComponent, selector: "notify-toast", ngImport: i0, template: ` <ng-container *ngFor="let position of getUniquePositions()"> <div class="toast-container" [ngClass]="getPositionClasses(position)"> <div *ngFor="let toast of getToastsByPosition(position)" class="toast" [id]="'toast-' + toast.id" [ngClass]="['toast-enter', 'toast-' + toast.type]"> <!-- Progress bar --> <div class="progress-bar" [ngClass]="'progress-' + toast.type"></div> <!-- Content --> <div class="toast-content"> <div class="icon-circle" [ngClass]="'icon-' + toast.type"> <div class="icon-core" [innerHTML]="getIcon(toast.type)"></div> </div> <div class="toast-text"> <h3 class="toast-title">{{getTitle(toast.type)}}</h3> <p class="toast-message">{{toast.message}}</p> </div> <!-- Close button --> <button (click)="dismissToast(toast.id)" class="toast-close"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor"> <path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd" /> </svg> </button> </div> </div> </div> </ng-container> `, isInline: true, styles: [":host{display:contents;font-family:inherit}.icon-core{display:flex;align-items:center;justify-content:center;width:20px;height:20px}.icon-core svg{width:100%;height:100%}.toast-container{position:fixed;z-index:50;display:flex;flex-direction:column;gap:.5rem;padding:.5rem;width:22rem}.toast-container.top-right{top:.5rem;right:.5rem}.toast-container.top-left{top:.5rem;left:.5rem}.toast-container.bottom-right{bottom:.5rem;right:.5rem}.toast-container.bottom-left{bottom:.5rem;left:.5rem}.toast{backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px);background:#ffffffa6;box-shadow:0 8px 32px #00000014;border-radius:.75rem;border:1px solid;display:flex;flex-direction:column;position:relative;overflow:hidden}.toast.toast-success{border-color:#d1fae5}.toast.toast-error{border-color:#fee2e2}.toast.toast-warning{border-color:#fef3c7}.toast.toast-info{border-color:#dbeafe}.toast-content{display:flex;align-items:flex-start;padding:1rem;gap:.75rem}.icon-circle{border-radius:9999px;width:2.5rem;height:2.5rem;display:flex;align-items:center;justify-content:center;flex-shrink:0;box-shadow:0 4px 12px -2px #0000001a,inset 0 -1px 4px #0000000d,inset 0 1px 4px #fff6}.icon-circle.icon-success{background-color:#10b9811a;color:#059669}.icon-circle.icon-error{background-color:#ef44441a;color:#dc2626}.icon-circle.icon-warning{background-color:#f59e0b1a;color:#d97706}.icon-circle.icon-info{background-color:#3b82f61a;color:#2563eb}.icon-circle svg{width:1.25rem;height:1.25rem}.toast-text{flex:1}.toast-title{font-weight:600;color:#1f2937;font-size:1rem;line-height:1.5;margin:0}.toast-message{color:#4b5563;font-size:.875rem;line-height:1.5;margin-top:.25rem;margin-bottom:0}.toast-close{color:#9ca3af;background:none;border:none;padding:.25rem;cursor:pointer;transition:color .2s}.toast-close:hover{color:#4b5563}.toast-close svg{width:1.25rem;height:1.25rem}.progress-bar{height:3px;width:100%;animation:progress 3.5s linear forwards}.progress-bar.progress-success{background:linear-gradient(90deg,#34d399,#a7f3d0)}.progress-bar.progress-error{background:linear-gradient(90deg,#f87171,#fecaca)}.progress-bar.progress-warning{background:linear-gradient(90deg,#fbbf24,#fde68a)}.progress-bar.progress-info{background:linear-gradient(90deg,#60a5fa,#bfdbfe)}@keyframes slideIn{0%{opacity:0;transform:translateY(20px) scale(.95)}to{opacity:1;transform:translateY(0) scale(1)}}@keyframes slideOut{0%{opacity:1;transform:translateY(0) scale(1)}to{opacity:0;transform:translateY(20px) scale(.95)}}@keyframes progress{0%{width:100%}to{width:0%}}.toast-enter{animation:slideIn .3s cubic-bezier(.175,.885,.32,1.275) forwards}.toast-exit{animation:slideOut .3s ease-out forwards}:host-context(.dark) .toast{background:#0f0f14d9}:host-context(.dark) .toast-title{color:#ffffffe6}:host-context(.dark) .toast-message{color:#9ca3afe6}:host-context(.dark) .toast-close:hover{color:#d1d5db}\n"], dependencies: [{ kind: "directive", type: i3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: ToastComponent, decorators: [{ type: Component, args: [{ selector: 'notify-toast', template: ` <ng-container *ngFor="let position of getUniquePositions()"> <div class="toast-container" [ngClass]="getPositionClasses(position)"> <div *ngFor="let toast of getToastsByPosition(position)" class="toast" [id]="'toast-' + toast.id" [ngClass]="['toast-enter', 'toast-' + toast.type]"> <!-- Progress bar --> <div class="progress-bar" [ngClass]="'progress-' + toast.type"></div> <!-- Content --> <div class="toast-content"> <div class="icon-circle" [ngClass]="'icon-' + toast.type"> <div class="icon-core" [innerHTML]="getIcon(toast.type)"></div> </div> <div class="toast-text"> <h3 class="toast-title">{{getTitle(toast.type)}}</h3> <p class="toast-message">{{toast.message}}</p> </div> <!-- Close button --> <button (click)="dismissToast(toast.id)" class="toast-close"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor"> <path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd" /> </svg> </button> </div> </div> </div> </ng-container> `, styles: [":host{display:contents;font-family:inherit}.icon-core{display:flex;align-items:center;justify-content:center;width:20px;height:20px}.icon-core svg{width:100%;height:100%}.toast-container{position:fixed;z-index:50;display:flex;flex-direction:column;gap:.5rem;padding:.5rem;width:22rem}.toast-container.top-right{top:.5rem;right:.5rem}.toast-container.top-left{top:.5rem;left:.5rem}.toast-container.bottom-right{bottom:.5rem;right:.5rem}.toast-container.bottom-left{bottom:.5rem;left:.5rem}.toast{backdrop-filter:blur(16px);-webkit-backdrop-filter:blur(16px);background:#ffffffa6;box-shadow:0 8px 32px #00000014;border-radius:.75rem;border:1px solid;display:flex;flex-direction:column;position:relative;overflow:hidden}.toast.toast-success{border-color:#d1fae5}.toast.toast-error{border-color:#fee2e2}.toast.toast-warning{border-color:#fef3c7}.toast.toast-info{border-color:#dbeafe}.toast-content{display:flex;align-items:flex-start;padding:1rem;gap:.75rem}.icon-circle{border-radius:9999px;width:2.5rem;height:2.5rem;display:flex;align-items:center;justify-content:center;flex-shrink:0;box-shadow:0 4px 12px -2px #0000001a,inset 0 -1px 4px #0000000d,inset 0 1px 4px #fff6}.icon-circle.icon-success{background-color:#10b9811a;color:#059669}.icon-circle.icon-error{background-color:#ef44441a;color:#dc2626}.icon-circle.icon-warning{background-color:#f59e0b1a;color:#d97706}.icon-circle.icon-info{background-color:#3b82f61a;color:#2563eb}.icon-circle svg{width:1.25rem;height:1.25rem}.toast-text{flex:1}.toast-title{font-weight:600;color:#1f2937;font-size:1rem;line-height:1.5;margin:0}.toast-message{color:#4b5563;font-size:.875rem;line-height:1.5;margin-top:.25rem;margin-bottom:0}.toast-close{color:#9ca3af;background:none;border:none;padding:.25rem;cursor:pointer;transition:color .2s}.toast-close:hover{color:#4b5563}.toast-close svg{width:1.25rem;height:1.25rem}.progress-bar{height:3px;width:100%;animation:progress 3.5s linear forwards}.progress-bar.progress-success{background:linear-gradient(90deg,#34d399,#a7f3d0)}.progress-bar.progress-error{background:linear-gradient(90deg,#f87171,#fecaca)}.progress-bar.progress-warning{background:linear-gradient(90deg,#fbbf24,#fde68a)}.progress-bar.progress-info{background:linear-gradient(90deg,#60a5fa,#bfdbfe)}@keyframes slideIn{0%{opacity:0;transform:translateY(20px) scale(.95)}to{opacity:1;transform:translateY(0) scale(1)}}@keyframes slideOut{0%{opacity:1;transform:translateY(0) scale(1)}to{opacity:0;transform:translateY(20px) scale(.95)}}@keyframes progress{0%{width:100%}to{width:0%}}.toast-enter{animation:slideIn .3s cubic-bezier(.175,.885,.32,1.275) forwards}.toast-exit{animation:slideOut .3s ease-out forwards}:host-context(.dark) .toast{background:#0f0f14d9}:host-context(.dark) .toast-title{color:#ffffffe6}:host-context(.dark) .toast-message{color:#9ca3afe6}:host-context(.dark) .toast-close:hover{color:#d1d5db}\n"] }] }], ctorParameters: function () { return [{ type: i1.ToastService }, { type: i2.DomSanitizer }]; } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9hc3QuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvdG9hc3Qvc3JjL2xpYi90b2FzdC5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBcUIsTUFBTSxlQUFlLENBQUM7Ozs7O0FBc1I3RCxNQUFNLE9BQU8sY0FBYztJQUl6QixZQUNVLFlBQTBCLEVBQzFCLFNBQXVCO1FBRHZCLGlCQUFZLEdBQVosWUFBWSxDQUFjO1FBQzFCLGNBQVMsR0FBVCxTQUFTLENBQWM7UUFMakMsV0FBTSxHQUFZLEVBQUUsQ0FBQztJQU1sQixDQUFDO0lBRUosWUFBWSxDQUFDLEVBQVU7UUFDckIsTUFBTSxZQUFZLEdBQUcsUUFBUSxDQUFDLGNBQWMsQ0FBQyxTQUFTLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDNUQsSUFBSSxZQUFZLEVBQUU7WUFDaEIsTUFBTSxXQUFXLEdBQUcsWUFBWSxDQUFDLGFBQWEsQ0FBQyxlQUFlLENBQUMsQ0FBQztZQUNoRSxJQUFJLFdBQVcsRUFBRTtnQkFDZCxXQUEyQixDQUFDLEtBQUssQ0FBQyxTQUFTLEdBQUcsTUFBTSxDQUFDO2FBQ3ZEO1lBQ0QsWUFBWSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLENBQUM7WUFDN0MsWUFBWSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLENBQUM7WUFFekMsb0RBQW9EO1lBQ3BELE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztZQUNqRCxJQUFJLEtBQUssSUFBSyxLQUFhLENBQUMsU0FBUyxFQUFFO2dCQUNyQyxZQUFZLENBQUUsS0FBYSxDQUFDLFNBQVMsQ0FBQyxDQUFDO2FBQ3hDO1lBRUQsVUFBVSxDQUFDLEdBQUcs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Q0FBQyxTQUFTLENBQUMsdUJBQXVCLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUMzRSxDQUFDO0lBRUQsUUFBUSxDQUFDLElBQVk7UUFDbkIsTUFBTSxNQUFNLEdBQVE7WUFDbEIsT0FBTyxFQUFFLFVBQVU7WUFDbkIsS0FBSyxFQUFFLFFBQVE7WUFDZixPQUFPLEVBQUUsVUFBVTtZQUNuQixJQUFJLEVBQUUsYUFBYTtTQUNwQixDQUFDO1FBQ0YsT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQztJQUNyQyxDQUFDOytHQW5IVSxjQUFjO21HQUFkLGNBQWMsb0RBL1FmOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBK0JUOzs0RkFnUFUsY0FBYztrQkFqUjFCLFNBQVM7K0JBQ0UsY0FBYyxZQUNkOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBK0JUIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBPbkluaXQsIE9uRGVzdHJveSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgVG9hc3RTZXJ2aWNlLCBUb2FzdCB9IGZyb20gJy4vdG9hc3Quc2VydmljZSc7XG5pbXBvcnQgeyBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IERvbVNhbml0aXplciwgU2FmZUh0bWwgfSBmcm9tICdAYW5ndWxhci9wbGF0Zm9ybS1icm93c2VyJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnbm90aWZ5LXRvYXN0JyxcbiAgdGVtcGxhdGU6IGBcbiAgICA8bmctY29udGFpbmVyICpuZ0Zvcj1cImxldCBwb3NpdGlvbiBvZiBnZXRVbmlxdWVQb3NpdGlvbnMoKVwiPlxuICAgICAgPGRpdiBjbGFzcz1cInRvYXN0LWNvbnRhaW5lclwiIFtuZ0NsYXNzXT1cImdldFBvc2l0aW9uQ2xhc3Nlcyhwb3NpdGlvbilcIj5cbiAgICAgICAgPGRpdiAqbmdGb3I9XCJsZXQgdG9hc3Qgb2YgZ2V0VG9hc3RzQnlQb3NpdGlvbihwb3NpdGlvbilcIlxuICAgICAgICAgICAgIGNsYXNzPVwidG9hc3RcIlxuICAgICAgICAgICAgIFtpZF09XCIndG9hc3QtJyArIHRvYXN0LmlkXCJcbiAgICAgICAgICAgICBbbmdDbGFzc109XCJbJ3RvYXN0LWVudGVyJywgJ3RvYXN0LScgKyB0b2FzdC50eXBlXVwiPlxuICAgICAgICAgIDwhLS0gUHJvZ3Jlc3MgYmFyIC0tPlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJwcm9ncmVzcy1iYXJcIiBbbmdDbGFzc109XCIncHJvZ3Jlc3MtJyArIHRvYXN0LnR5cGVcIj48L2Rpdj5cblxuICAgICAgICAgIDwhLS0gQ29udGVudCAtLT5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwidG9hc3QtY29udGVudFwiPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImljb24tY2lyY2xlXCIgW25nQ2xhc3NdPVwiJ2ljb24tJyArIHRvYXN0LnR5cGVcIj5cbiAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImljb24tY29yZVwiIFtpbm5lckhUTUxdPVwiZ2V0SWNvbih0b2FzdC50eXBlKVwiPjwvZGl2PlxuICAgICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJ0b2FzdC10ZXh0XCI+XG4gICAgICAgICAgICAgIDxoMyBjbGFzcz1cInRvYXN0LXRpdGxlXCI+e3tnZXRUaXRsZSh0b2FzdC50eXBlKX19PC9oMz5cbiAgICAgICAgICAgICAgPHAgY2xhc3M9XCJ0b2FzdC1tZXNzYWdlXCI+e3t0b2FzdC5tZXNzYWdlfX08L3A+XG4gICAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgICAgPCEtLSBDbG9zZSBidXR0b24gLS0+XG4gICAgICAgICAgICA8YnV0dG9uIChjbGljayk9XCJkaXNtaXNzVG9hc3QodG9hc3QuaWQpXCIgY2xhc3M9XCJ0b2FzdC1jbG9zZVwiPlxuICAgICAgICAgICAgICA8c3ZnIHhtbG5zPVwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIiB2aWV3Qm94PVwiMCAwIDIwIDIwXCIgZmlsbD1cImN1cnJlbnRDb2xvclwiPlxuICAgICAgICAgICAgICAgIDxwYXRoIGZpbGwtcnVsZT1cImV2ZW5vZGRcIiBkPVwiTTQuMjkzIDQuMjkzYTEgMSAwIDAxMS40MTQgMEwxMCA4LjU4Nmw0LjI5My00LjI5M2ExIDEgMCAxMTEuNDE0IDEuNDE0TDExLjQxNCAxMGw0LjI5MyA0LjI5M2ExIDEgMCAwMS0xLjQxNCAxLjQxNEwxMCAxMS40MTRsLTQuMjkzIDQuMjkzYTEgMSAwIDAxLTEuNDE0LTEuNDE0TDguNTg2IDEwIDQuMjkzIDUuNzA3YTEgMSAwIDAxMC0xLjQxNHpcIiBjbGlwLXJ1bGU9XCJldmVub2RkXCIgLz5cbiAgICAgICAgICAgICAgPC9zdmc+XG4gICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICA8L25nLWNvbnRhaW5lcj5cbiAgYCxcbiAgc3R5bGVzOiBbYFxuICAgIDpob3N0IHtcbiAgICAgIGRpc3BsYXk6IGNvbnRlbnRzO1xuICAgICAgZm9udC1mYW1pbHk6IGluaGVyaXQ7XG4gICAgfVxuXG4gICAgLmljb24tY29yZSB7XG4gICAgICBkaXNwbGF5OiBmbGV4O1xuICAgICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgICAgIGp1c3RpZnktY29udGVudDogY2VudGVyO1xuICAgICAgd2lkdGg6IDIwcHg7XG4gICAgICBoZWlnaHQ6IDIwcHg7XG4gICAgfVxuXG4gICAgLmljb24tY29yZSBzdmcge1xuICAgICAgd2lkdGg6IDEwMCU7XG4gICAgICBoZWlnaHQ6IDEwMCU7XG4gICAgfVxuXG4gICAgLnRvYXN0LWNvbnRhaW5lciB7XG4gICAgICBwb3NpdGlvbjogZml4ZWQ7XG4gICAgICB6LWluZGV4OiA1MDtcbiAgICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xuICAgICAgZ2FwOiAwLjVyZW07XG4gICAgICBwYWRkaW5nOiAwLjVyZW07XG4gICAgICB3aWR0aDogMjJyZW07XG4gICAgfVxuXG4gICAgLnRvYXN0LWNvbnRhaW5lci50b3AtcmlnaHQge1xuICAgICAgdG9wOiAwLjVyZW07XG4gICAgICByaWdodDogMC41cmVtO1xuICAgIH1cblxuICAgIC50b2FzdC1jb250YWluZXIudG9wLWxlZnQge1xuICAgICAgdG9wOiAwLjVyZW07XG4gICAgICBsZWZ0OiAwLjVyZW07XG4gICAgfVxuXG4gICAgLnRvYXN0LWNvbnRhaW5lci5ib3R0b20tcmlnaHQge1xuICAgICAgYm90dG9tOiAwLjVyZW07XG4gICAgICByaWdodDogMC41cmVtO1xuICAgIH1cblxuICAgIC50b2FzdC1jb250YWluZXIuYm90dG9tLWxlZnQge1xuICAgICAgYm90dG9tOiAwLjVyZW07XG4gICAgICBsZWZ0OiAwLjVyZW07XG4gICAgfVxuXG4gICAgLnRvYXN0IHtcbiAgICAgIGJhY2tkcm9wLWZpbHRlcjogYmx1cigxNnB4KTtcbiAgICAgIC13ZWJraXQtYmFja2Ryb3AtZmlsdGVyOiBibHVyKDE2cHgpO1xuICAgICAgYmFja2dyb3VuZDogcmdiYSgyNTUsIDI1NSwgMjU1LCAwLjY1KTtcbiAgICAgIGJveC1zaGFkb3c6IDAgOHB4IDMycHggcmdiYSgwLCAwLCAwLCAwLjA4KTtcbiAgICAgIGJvcmRlci1yYWRpdXM6IDAuNzVyZW07XG4gICAgICBib3JkZXI6IDFweCBzb2xpZDtcbiAgICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xuICAgICAgcG9zaXRpb246IHJlbGF0aXZlO1xuICAgICAgb3ZlcmZsb3c6IGhpZGRlbjtcbiAgICB9XG5cbiAgICAudG9hc3QudG9hc3Qtc3VjY2VzcyB7XG4gICAgICBib3JkZXItY29sb3I6ICNkMWZhZTU7XG4gICAgfVxuXG4gICAgLnRvYXN0LnRvYXN0LWVycm9yIHtcbiAgICAgIGJvcmRlci1jb2xvcjogI2ZlZTJlMjtcbiAgICB9XG5cbiAgICAudG9hc3QudG9hc3Qtd2FybmluZyB7XG4gICAgICBib3JkZXItY29sb3I6ICNmZWYzYzc7XG4gICAgfVxuXG4gICAgLnRvYXN0LnRvYXN0LWluZm8ge1xuICAgICAgYm9yZGVyLWNvbG9yOiAjZGJlYWZlO1xuICAgIH1cblxuICAgIC50b2FzdC1jb250ZW50IHtcbiAgICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgICBhbGlnbi1pdGVtczogZmxleC1zdGFydDtcbiAgICAgIHBhZGRpbmc6IDFyZW07XG4gICAgICBnYXA6IDAuNzVyZW07XG4gICAgfVxuXG4gICAgLmljb24tY2lyY2xlIHtcbiAgICAgIGJvcmRlci1yYWRpdXM6IDk5OTlweDtcbiAgICAgIHdpZHRoOiAyLjVyZW07XG4gICAgICBoZWlnaHQ6IDIuNXJlbTtcbiAgICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgICBhbGlnbi1pdGVtczogY2VudGVyO1xuICAgICAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XG4gICAgICBmbGV4LXNocmluazogMDtcbiAgICAgIGJveC1zaGFkb3c6IDAgNHB4IDEycHggLTJweCByZ2JhKDAsIDAsIDAsIDAuMSksXG4gICAgICAgICAgICAgICAgICBpbnNldCAwIC0xcHggNHB4IHJnYmEoMCwgMCwgMCwgMC4wNSksXG4gICAgICAgICAgICAgICAgICBpbnNldCAwIDFweCA0cHggcmdiYSgyNTUsIDI1NSwgMjU1LCAwLjQpO1xuICAgIH1cblxuICAgIC5pY29uLWNpcmNsZS5pY29uLXN1Y2Nlc3Mge1xuICAgICAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSgxNiwgMTg1LCAxMjksIDAuMSk7XG4gICAgICBjb2xvcjogIzA1OTY2OTtcbiAgICB9XG5cbiAgICAuaWNvbi1jaXJjbGUuaWNvbi1lcnJvciB7XG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDIzOSwgNjgsIDY4LCAwLjEpO1xuICAgICAgY29sb3I6ICNkYzI2MjY7XG4gICAgfVxuXG4gICAgLmljb24tY2lyY2xlLmljb24td2FybmluZyB7XG4gICAgICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDI0NSwgMTU4LCAxMSwgMC4xKTtcbiAgICAgIGNvbG9yOiAjZDk3NzA2O1xuICAgIH1cblxuICAgIC5pY29uLWNpcmNsZS5pY29uLWluZm8ge1xuICAgICAgYmFja2dyb3VuZC1jb2xvcjogcmdiYSg1OSwgMTMwLCAyNDYsIDAuMSk7XG4gICAgICBjb2xvcjogIzI1NjNlYjtcbiAgICB9XG5cbiAgICAuaWNvbi1jaXJjbGUgc3ZnIHtcbiAgICAgIHdpZHRoOiAxLjI1cmVtO1xuICAgICAgaGVpZ2h0OiAxLjI1cmVtO1xuICAgIH1cblxuICAgIC50b2FzdC10ZXh0IHtcbiAgICAgIGZsZXg6IDE7XG4gICAgfVxuXG4gICAgLnRvYXN0LXRpdGxlIHtcbiAgICAgIGZvbnQtd2VpZ2h0OiA2MDA7XG4gICAgICBjb2xvcjogIzFmMjkzNztcbiAgICAgIGZvbnQtc2l6ZTogMXJlbTtcbiAgICAgIGxpbmUtaGVpZ2h0OiAxLjU7XG4gICAgICBtYXJnaW46IDA7XG4gICAgfVxuXG4gICAgLnRvYXN0LW1lc3NhZ2Uge1xuICAgICAgY29sb3I6ICM0YjU1NjM7XG4gICAgICBmb250LXNpemU6IDAuODc1cmVtO1xuICAgICAgbGluZS1oZWlnaHQ6IDEuNTtcbiAgICAgIG1hcmdpbi10b3A6IDAuMjVyZW07XG4gICAgICBtYXJnaW4tYm90dG9tOiAwO1xuICAgIH1cblxuICAgIC50b2FzdC1jbG9zZSB7XG4gICAgICBjb2xvcjogIzljYTNhZjtcbiAgICAgIGJhY2tncm91bmQ6IG5vbmU7XG4gICAgICBib3JkZXI6IG5vbmU7XG4gICAgICBwYWRkaW5nOiAwLjI1cmVtO1xuICAgICAgY3Vyc29yOiBwb2ludGVyO1xuICAgICAgdHJhbnNpdGlvbjogY29sb3IgMC4ycztcbiAgICB9XG5cbiAgICAudG9hc3QtY2xvc2U6aG92ZXIge1xuICAgICAgY29sb3I6ICM0YjU1NjM7XG4gICAgfVxuXG4gICAgLnRvYXN0LWNsb3NlIHN2ZyB7XG4gICAgICB3aWR0aDogMS4yNXJlbTtcbiAgICAgIGhlaWdodDogMS4yNXJlbTtcbiAgICB9XG5cbiAgICAucHJvZ3Jlc3MtYmFyIHtcbiAgICAgIGhlaWdodDogM3B4O1xuICAgICAgd2lkdGg6IDEwMCU7XG4gICAgICBhbmltYXRpb246IHByb2dyZXNzIDMuNXMgbGluZWFyIGZvcndhcmRzO1xuICAgIH1cblxuICAgIC5wcm9ncmVzcy1iYXIucHJvZ3Jlc3Mtc3VjY2VzcyB7XG4gICAgICBiYWNrZ3JvdW5kOiBsaW5lYXItZ3JhZGllbnQoOTBkZWcsICMzNGQzOTksICNhN2YzZDApO1xuICAgIH1cblxuICAgIC5wcm9ncmVzcy1iYXIucHJvZ3Jlc3MtZXJyb3Ige1xuICAgICAgYmFja2dyb3VuZDogbGluZWFyLWdyYWRpZW50KDkwZGVnLCAjZjg3MTcxLCAjZmVjYWNhKTtcbiAgICB9XG5cbiAgICAucHJvZ3Jlc3MtYmFyLnByb2dyZXNzLXdhcm5pbmcge1xuICAgICAgYmFja2dyb3VuZDogbGluZWFyLWdyYWRpZW50KDkwZGVnLCAjZmJiZjI0LCAjZmRlNjhhKTtcbiAgICB9XG5cbiAgICAucHJvZ3Jlc3MtYmFyLnByb2dyZXNzLWluZm8ge1xuICAgICAgYmFja2dyb3VuZDogbGluZWFyLWdyYWRpZW50KDkwZGVnLCAjNjBhNWZhLCAjYmZkYmZlKTtcbiAgICB9XG5cbiAgICBAa2V5ZnJhbWVzIHNsaWRlSW4ge1xuICAgICAgMCUge1xuICAgICAgICBvcGFjaXR5OiAwO1xuICAgICAgICB0cmFuc2Zvcm06IHRyYW5zbGF0ZVkoMjBweCkgc2NhbGUoMC45NSk7XG4gICAgICB9XG4gICAgICAxMDAlIHtcbiAgICAgICAgb3BhY2l0eTogMTtcbiAgICAgICAgdHJhbnNmb3JtOiB0cmFuc2xhdGVZKDApIHNjYWxlKDEpO1xuICAgICAgfVxuICAgIH1cblxuICAgIEBrZXlmcmFtZXMgc2xpZGVPdXQge1xuICAgICAgMCUge1xuICAgICAgICBvcGFjaXR5OiAxO1xuICAgICAgICB0cmFuc2Zvcm06IHRyYW5zbGF0ZVkoMCkgc2NhbGUoMSk7XG4gICAgICB9XG4gICAgICAxMDAlIHtcbiAgICAgICAgb3BhY2l0eTogMDtcbiAgICAgICAgdHJhbnNmb3JtOiB0cmFuc2xhdGVZKDIwcHgpIHNjYWxlKDAuOTUpO1xuICAgICAgfVxuICAgIH1cblxuICAgIEBrZXlmcmFtZXMgcHJvZ3Jlc3Mge1xuICAgICAgMCUge1xuICAgICAgICB3aWR0aDogMTAwJTtcbiAgICAgIH1cbiAgICAgIDEwMCUge1xuICAgICAgICB3aWR0aDogMCU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLnRvYXN0LWVudGVyIHtcbiAgICAgIGFuaW1hdGlvbjogc2xpZGVJbiAwLjNzIGN1YmljLWJlemllcigwLjE3NSwgMC44ODUsIDAuMzIsIDEuMjc1KSBmb3J3YXJkcztcbiAgICB9XG5cbiAgICAudG9hc3QtZXhpdCB7XG4gICAgICBhbmltYXRpb246IHNsaWRlT3V0IDAuM3MgZWFzZS1vdXQgZm9yd2FyZHM7XG4gICAgfVxuXG4gICAgOmhvc3QtY29udGV4dCguZGFyaykgLnRvYXN0IHtcbiAgICAgIGJhY2tncm91bmQ6IHJnYmEoMTUsIDE1LCAyMCwgMC44NSk7XG4gICAgfVxuXG4gICAgOmhvc3QtY29udGV4dCguZGFyaykgLnRvYXN0LXRpdGxlIHtcbiAgICAgIGNvbG9yOiByZ2JhKDI1NSwgMjU1LCAyNTUsIDAuOSk7XG4gICAgfVxuXG4gICAgOmhvc3QtY29udGV4dCguZGFyaykgLnRvYXN0LW1lc3NhZ2Uge1xuICAgICAgY29sb3I6IHJnYmEoMTU2LCAxNjMsIDE3NSwgMC45KTtcbiAgICB9XG5cbiAgICA6aG9zdC1jb250ZXh0KC5kYXJrKSAudG9hc3QtY2xvc2U6aG92ZXIge1xuICAgICAgY29sb3I6IHJnYmEoMjA5LCAyMTMsIDIxOSwgMSk7XG4gICAgfVxuICBgXVxufSlcbmV4cG9ydCBjbGFzcyBUb2FzdENvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25EZXN0cm95IHtcbiAgdG9hc3RzOiBUb2FzdFtdID0gW107XG4gIHByaXZhdGUgc3Vic2NyaXB0aW9uPzogU3Vic2NyaXB0aW9uO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgdG9hc3RTZXJ2aWNlOiBUb2FzdFNlcnZpY2UsXG4gICAgcHJpdmF0ZSBzYW5pdGl6ZXI6IERvbVNhbml0aXplclxuICApIHt9XG5cbiAgZGlzbWlzc1RvYXN0KGlkOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCB0b2FzdEVsZW1lbnQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChgdG9hc3QtJHtpZH1gKTtcbiAgICBpZiAodG9hc3RFbGVtZW50KSB7XG4gICAgICBjb25zdCBwcm9ncmVzc0JhciA9IHRvYXN0RWxlbWVudC5xdWVyeVNlbGVjdG9yKCcucHJvZ3Jlc3MtYmFyJyk7XG4gICAgICBpZiAocHJvZ3Jlc3NCYXIpIHtcbiAgICAgICAgKHByb2dyZXNzQmFyIGFzIEhUTUxFbGVtZW50KS5zdHlsZS5hbmltYXRpb24gPSAnbm9uZSc7XG4gICAgICB9XG4gICAgICB0b2FzdEVsZW1lbnQuY2xhc3NMaXN0LnJlbW92ZSgndG9hc3QtZW50ZXInKTtcbiAgICAgIHRvYXN0RWxlbWVudC5jbGFzc0xpc3QuYWRkKCd0b2FzdC1leGl0Jyk7XG5cbiAgICAgIC8vIENsZWFyIHRoZSB0aW1lb3V0IHRvIHByZXZlbnQgZHVwbGljYXRlIGRpc21pc3NhbHNcbiAgICAgIGNvbnN0IHRvYXN0ID0gdGhpcy50b2FzdHMuZmluZCh0ID0+IHQuaWQgPT09IGlkKTtcbiAgICAgIGlmICh0b2FzdCAmJiAodG9hc3QgYXMgYW55KS50aW1lb3V0SWQpIHtcbiAgICAgICAgY2xlYXJUaW1lb3V0KCh0b2FzdCBhcyBhbnkpLnRpbWVvdXRJZCk7XG4gICAgICB9XG5cbiAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICB0aGlzLnRvYXN0U2VydmljZS5oaWRlKGlkKTtcbiAgICAgIH0sIDMwMCk7XG4gICAgfVxuICB9XG5cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgdGhpcy5zdWJzY3JpcHRpb24gPSB0aGlzLnRvYXN0U2VydmljZS5nZXRUb2FzdHMoKS5zdWJzY3JpYmUodG9hc3RzID0+IHtcbiAgICAgIC8vIEZpbHRlciBvdXQgdG9hc3RzIHRoYXQgYWxyZWFkeSBoYXZlIHRpbWVvdXRzXG4gICAgICBjb25zdCBuZXdUb2FzdHMgPSB0b2FzdHMuZmlsdGVyKCh0b2FzdCkgPT4gISh0b2FzdCBhcyBhbnkpLnRpbWVvdXRJZCk7XG5cbiAgICAgIC8vIFNldCB0aW1lb3V0cyBvbmx5IGZvciBuZXcgdG9hc3RzXG4gICAgICBuZXdUb2FzdHMuZm9yRWFjaCgodG9hc3QpID0+IHtcbiAgICAgICAgY29uc3QgdGltZW91dElkID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgY29uc3QgdG9hc3RFbGVtZW50ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoYHRvYXN0LSR7dG9hc3QuaWR9YCk7XG4gICAgICAgICAgaWYgKHRvYXN0RWxlbWVudCkge1xuICAgICAgICAgICAgdG9hc3RFbGVtZW50LmNsYXNzTGlzdC5yZW1vdmUoJ3RvYXN0LWVudGVyJyk7XG4gICAgICAgICAgICB0b2FzdEVsZW1lbnQuY2xhc3NMaXN0LmFkZCgndG9hc3QtZXhpdCcpO1xuICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICAgIHRoaXMudG9hc3RTZXJ2aWNlLmhpZGUodG9hc3QuaWQpO1xuICAgICAgICAgICAgfSwgMzAwKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0sIDQ3MDApO1xuICAgICAgICAodG9hc3QgYXMgYW55KS50aW1lb3V0SWQgPSB0aW1lb3V0SWQ7XG4gICAgICB9KTtcblxuICAgICAgdGhpcy50b2FzdHMgPSB0b2FzdHM7XG4gICAgfSk7XG4gIH1cblxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICAvLyBDbGVhciBhbGwgdGltZW91dHNcbiAgICB0aGlzLnRvYXN0cy5mb3JFYWNoKCh0b2FzdCkgPT4ge1xuICAgICAgaWYgKCh0b2FzdCBhcyBhbnkpLnRpbWVvdXRJZCkge1xuICAgICAgICBjbGVhclRpbWVvdXQoKHRvYXN0IGFzIGFueSkudGltZW91dElkKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICB0aGlzLnN1YnNjcmlwdGlvbj8udW5zdWJzY3JpYmUoKTtcbiAgfVxuXG4gIGdldFVuaXF1ZVBvc2l0aW9ucygpOiBzdHJpbmdbXSB7XG4gICAgcmV0dXJuIFsuLi5uZXcgU2V0KHRoaXMudG9hc3RzLm1hcCh0ID0+IHQucG9zaXRpb24gfHwgJ3RvcC1yaWdodCcpKV07XG4gIH1cblxuICBnZXRQb3NpdGlvbkNsYXNzZXMocG9zaXRpb246IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHBvc2l0aW9uO1xuICB9XG5cbiAgZ2V0VG9hc3RDbGFzc2VzKHR5cGU6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHR5cGU7XG4gIH1cblxuICBnZXRHbG93Q2xhc3ModHlwZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gYGdsb3ctJHt0eXBlfWA7XG4gIH1cblxuICBnZXRJY29uQ29udGFpbmVyQ2xhc3Nlcyh0eXBlOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiB0eXBlO1xuICB9XG5cbiAgZ2V0VG9hc3RzQnlQb3NpdGlvbihwb3NpdGlvbjogc3RyaW5nKTogVG9hc3RbXSB7XG4gICAgcmV0dXJuIHRoaXMudG9hc3RzLmZpbHRlcih0ID0+ICh0LnBvc2l0aW9uIHx8ICd0b3AtcmlnaHQnKSA9PT0gcG9zaXRpb24pO1xuICB9XG5cbiAgZ2V0SWNvbih0eXBlOiBzdHJpbmcpOiBTYWZlSHRtbCB7XG4gICAgY29uc3QgaWNvbnM6IGFueSA9IHtcbiAgICAgIHN1Y2Nlc3M6IGA8c3ZnIHhtbG5zPVwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIiB3aWR0aD1cIjIwXCIgaGVpZ2h0PVwiMjBcIiB2aWV3Qm94PVwiMCAwIDIwIDIwXCIgZmlsbD1cImN1cnJlbnRDb2xvclwiPlxuICAgICAgICAgICAgICAgICAgPHBhdGggZmlsbC1ydWxlPVwiZXZlbm9kZFwiIGQ9XCJNMTAgMThhOCA4IDAgMTAwLTE2IDggOCAwIDAwMCAxNnptMy43MDctOS4yOTNhMSAxIDAgMDAtMS40MTQtMS40MTRMOSAxMC41ODYgNy43MDcgOS4yOTNhMSAxIDAgMDAtMS40MTQgMS40MTRsMiAyYTEgMSAwIDAwMS40MTQgMGw0LTR6XCIgY2xpcC1ydWxlPVwiZXZlbm9kZFwiPjwvcGF0aD5cbiAgICAgICAgICAgICAgICA8L3N2Zz5gLFxuICAgICAgZXJyb3I6IGA8c3ZnIHhtbG5zPVwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIiB3aWR0aD1cIjIwXCIgaGVpZ2h0PVwiMjBcIiB2aWV3Qm94PVwiMCAwIDIwIDIwXCIgZmlsbD1cImN1cnJlbnRDb2xvclwiPlxuICAgICAgICAgICAgICAgIDxwYXRoIGZpbGwtcnVsZT1cImV2ZW5vZGRcIiBkPVwiTTEwIDE4YTggOCAwIDEwMC0xNiA4IDggMCAwMDAgMTZ6TTguNzA3IDcuMjkzYTEgMSAwIDAwLTEuNDE0IDEuNDE0TDguNTg2IDEwbC0xLjI5MyAxLjI5M2ExIDEgMCAxMDEuNDE0IDEuNDE0TDEwIDExLjQxNGwxLjI5MyAxLjI5M2ExIDEgMCAwMDEuNDE0LTEuNDE0TDExLjQxNCAxMGwxLjI5My0xLjI5M2ExIDEgMCAwMC0xLjQxNC0xLjQxNEwxMCA4LjU4NiA4LjcwNyA3LjI5M3pcIiBjbGlwLXJ1bGU9XCJldmVub2RkXCI+PC9wYXRoPlxuICAgICAgICAgICAgICA8L3N2Zz5gLFxuICAgICAgd2FybmluZzogYDxzdmcgeG1sbnM9XCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiIHdpZHRoPVwiMjBcIiBoZWlnaHQ9XCIyMFwiIHZpZXdCb3g9XCIwIDAgMjAgMjBcIiBmaWxsPVwiY3VycmVudENvbG9yXCI+XG4gICAgICAgICAgICAgICAgICA8cGF0aCBmaWxsLXJ1bGU9XCJldmVub2RkXCIgZD1cIk04LjI1NyAzLjA5OWMuNzY1LTEuMzYgMi43MjItMS4zNiAzLjQ4NiAwbDUuNTggOS45MmMuNzUgMS4zMzQtLjIxMyAyLjk4LTEuNzQyIDIuOThINC40MmMtMS41MyAwLTIuNDkzLTEuNjQ2LTEuNzQzLTIuOThsNS41OC05Ljkyek0xMSAxM2ExIDEgMCAxMS0yIDAgMSAxIDAgMDEyIDB6bS0xLThhMSAxIDAgMDAtMSAxdjNhMSAxIDAgMDAyIDBWNmExIDEgMCAwMC0xLTF6XCIgY2xpcC1ydWxlPVwiZXZlbm9kZFwiPjwvcGF0aD5cbiAgICAgICAgICAgICAgICA8L3N2Zz5gLFxuICAgICAgaW5mbzogYDxzdmcgeG1sbnM9XCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiIHdpZHRoPVwiMjBcIiBoZWlnaHQ9XCIyMFwiIHZpZXdCb3g9XCIwIDAgMjAgMjBcIiBmaWxsPVwiY3VycmVudENvbG9yXCI+XG4gICAgICAgICAgICAgIDxwYXRoIGZpbGwtcnVsZT1cImV2ZW5vZGRcIiBkPVwiTTE4IDEwYTggOCAwIDExLTE2IDAgOCA4IDAgMDExNiAwem0tNy00YTEgMSAwIDExLTIgMCAxIDEgMCAwMTIgMHpNOSA5YTEgMSAwIDAwMCAydjNhMSAxIDAgMDAxIDFoMWExIDEgMCAxMDAtMmgtMVY5elwiIGNsaXAtcnVsZT1cImV2ZW5vZGRcIj48L3BhdGg+XG4gICAgICAgICAgICA8L3N2Zz5gXG4gICAgfTtcbiAgICByZXR1cm4gdGhpcy5zYW5pdGl6ZXIuYnlwYXNzU2VjdXJpdHlUcnVzdEh0bWwoaWNvbnNbdHlwZV0gfHwgaWNvbnMuaW5mbyk7XG4gIH1cblxuICBnZXRUaXRsZSh0eXBlOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGNvbnN0IHRpdGxlczogYW55ID0ge1xuICAgICAgc3VjY2VzczogJ1N1Y2Nlc3MhJyxcbiAgICAgIGVycm9yOiAnRXJyb3IhJyxcbiAgICAgIHdhcm5pbmc6ICdXYXJuaW5nIScsXG4gICAgICBpbmZvOiAnSW5mb3JtYXRpb24nXG4gICAgfTtcbiAgICByZXR1cm4gdGl0bGVzW3R5cGVdIHx8IHRpdGxlcy5pbmZvO1xuICB9XG59XG4iXX0=