UNPKG

@data-cafe/datagrid

Version:

A very generic datagrid component for data-café applications

103 lines 19.4 kB
import { __decorate } from "tslib"; /* * data·café * Copyright (c) 2021-2022 Data Terrae * This program is under the terms of the GNU Affero General Public License version 3 * The full license information can be found in LICENSE in the root directory of this project. */ import { Component, EventEmitter, Input, Output } from '@angular/core'; import { ClrLoadingState } from '@clr/angular'; import { UntilDestroy } from '@ngneat/until-destroy'; import { initialUI, Type } from '../model'; import * as i0 from "@angular/core"; import * as i1 from "@clr/angular"; import * as i2 from "../cell-editable/cell-editable.component"; import * as i3 from "@angular/common"; let DatagridComponent = class DatagridComponent { constructor() { this.NO_ITEMS = []; this.NO_COLS = []; this.ClrLoadingState = ClrLoadingState; this.ui = initialUI(); /** * Dispatch everytime an item is updated in the datagrid. * * @see editable */ this.edit = new EventEmitter(); } /** * Set the data to be displayed. * @param value */ set items(value) { this.updateUI(value ?? undefined); } /** * Transform the grid editable. * * @param something * * @see edit */ set editable(something) { this.ui.editable = something != null && `${something}` !== "false"; } onEdit(item, property, modification) { this.edit.emit({ previous: { ...item }, updated: { ...item, [property]: modification, }, updatedProperties: [property], }); } // -- Helper methods --------------------------------------------------------- updateUI(items) { if (items?.length) { // Generate structure const cols = Object .keys(items[0]) .map(property => ({ property, title: property, type: Type.TEXT, })); // Build data this.data = { items, cols, }; // Update UI this.ui.loading = false; } else { // Clear data this.data = undefined; // Update UI this.ui.loading = true; } } }; DatagridComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: DatagridComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); DatagridComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.1", type: DatagridComponent, selector: "dt-datagrid", inputs: { texts: "texts", actions: "actions", items: "items", editable: "editable" }, outputs: { edit: "edit" }, ngImport: i0, template: "<!--\n ~ data\u00B7caf\u00E9\n ~ Copyright (c) 2021-2022 Data Terrae\n ~ This program is under the terms of the GNU Affero General Public License version 3\n ~ The full license information can be found in LICENSE in the root directory of this project.\n -->\n\n<h1 *ngIf=\"texts?.h1\" [innerText]=\"texts!.h1\"></h1>\n<h2 *ngIf=\"texts?.h2\" [innerText]=\"texts!.h2\"></h2>\n<h3 *ngIf=\"texts?.h3\" [innerText]=\"texts!.h3\"></h3>\n<p *ngIf=\"texts?.top\" [innerText]=\"texts!.top\"></p>\n\n<clr-datagrid [clrLoading]=\"ui.loading\">\n\n <!-- Actions -->\n <clr-dg-action-bar *ngIf=\"actions?.length\">\n <div *ngFor=\"let action of actions\" class=\"btn-group\">\n <button (click)=\"action.callback($event)\"\n [clrLoading]=\"action.loading ?? ClrLoadingState.DEFAULT\"\n class=\"btn btn-sm btn-secondary\"\n type=\"button\">\n <cds-icon *ngIf=\"action.icon\" [attr.shape]=\"action.icon\"></cds-icon>\n {{ action.label }}\n </button>\n </div>\n </clr-dg-action-bar>\n\n <!-- Placeholder -->\n <clr-dg-placeholder *ngIf=\"texts?.placeholder\">{{ texts!.placeholder }}</clr-dg-placeholder>\n\n <!-- Columns -->\n <clr-dg-column *ngFor=\"let col of data?.cols ?? NO_COLS\">{{ col.title }}</clr-dg-column>\n\n <!-- Rows -->\n <clr-dg-row *ngFor=\"let item of data?.items ?? NO_ITEMS\" [clrDgItem]=\"item\">\n <clr-dg-cell *ngFor=\"let col of data?.cols ?? NO_COLS\">\n\n <dt-cell-editable (save)=\"onEdit(item, col.property, $event.current)\"\n [enable]=\"ui.editable\"\n [fallbackLabel]=\"col.fallbackLabel ?? texts?.fallbackLabel ?? undefined\"\n [item]=\"item[col.property]\"></dt-cell-editable>\n </clr-dg-cell>\n </clr-dg-row>\n\n <clr-dg-footer *ngIf=\"data && texts?.counter\">\n {{ texts!.counter!(data!.items.length) }}\n </clr-dg-footer>\n</clr-datagrid>\n\n<p *ngIf=\"texts?.bottom\" [innerText]=\"texts!.bottom\"></p>\n", styles: ["@charset \"UTF-8\";/*!\n * data\u00B7caf\u00E9\n * Copyright (c) 2021-2022 Data Terrae\n * This program is under the terms of the GNU Affero General Public License version 3\n * The full license information can be found in LICENSE in the root directory of this project.\n */\n"], components: [{ type: i1.ClrDatagrid, selector: "clr-datagrid", inputs: ["clrDgSingleSelectionAriaLabel", "clrDgSingleActionableAriaLabel", "clrDetailExpandableAriaLabel", "clrDgDisablePageFocus", "clrDgLoading", "clrDgSelected", "clrDgSingleSelected", "clrDgPreserveSelection", "clrDgRowSelection"], outputs: ["clrDgRefresh", "clrDgSelectedChange", "clrDgSingleSelectedChange"] }, { type: i1.ClrDatagridActionBar, selector: "clr-dg-action-bar" }, { type: i1.ClrLoadingButton, selector: "button[clrLoading]", inputs: ["disabled"], outputs: ["clrLoadingChange"] }, { type: i1.ClrDatagridPlaceholder, selector: "clr-dg-placeholder" }, { type: i1.ClrDatagridColumn, selector: "clr-dg-column", inputs: ["clrDgColType", "clrDgField", "clrFilterValue", "clrDgSortBy", "clrDgSorted", "clrDgSortOrder"], outputs: ["clrDgSortedChange", "clrDgSortOrderChange", "clrFilterValueChange"] }, { type: i1.ClrDatagridRow, selector: "clr-dg-row", inputs: ["clrDgSelected", "clrDgSelectable", "clrDgExpanded", "clrDgDetailOpenLabel", "clrDgDetailCloseLabel", "clrDgItem"], outputs: ["clrDgSelectedChange", "clrDgExpandedChange"] }, { type: i1.ClrDatagridCell, selector: "clr-dg-cell" }, { type: i2.CellEditableComponent, selector: "dt-cell-editable", inputs: ["item", "fallbackLabel", "altValues", "itemToLabel", "enable", "validators"], outputs: ["save", "editing$"] }, { type: i1.ClrDatagridFooter, selector: "clr-dg-footer" }], directives: [{ type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1.ÇlrDatagridMainRenderer, selector: "clr-datagrid" }, { type: i1.ÇlrDatagridWillyWonka, selector: "clr-datagrid" }, { type: i1.ÇlrActionableOompaLoompa, selector: "clr-datagrid, clr-dg-row" }, { type: i1.ÇlrExpandableOompaLoompa, selector: "clr-datagrid, clr-dg-row" }, { type: i1.ClrLoading, selector: "[clrLoading]", inputs: ["clrLoading"] }, { type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i1.CdsIconCustomTag, selector: "cds-icon" }, { type: i1.ÇlrDatagridHeaderRenderer, selector: "clr-dg-column", outputs: ["clrDgColumnResize"] }, { type: i1.ÇlrDatagridRowRenderer, selector: "clr-dg-row, clr-dg-row-detail" }, { type: i1.ÇlrDatagridCellRenderer, selector: "clr-dg-cell" }] }); DatagridComponent = __decorate([ UntilDestroy() ], DatagridComponent); export { DatagridComponent }; i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: DatagridComponent, decorators: [{ type: Component, args: [{ selector: 'dt-datagrid', template: "<!--\n ~ data\u00B7caf\u00E9\n ~ Copyright (c) 2021-2022 Data Terrae\n ~ This program is under the terms of the GNU Affero General Public License version 3\n ~ The full license information can be found in LICENSE in the root directory of this project.\n -->\n\n<h1 *ngIf=\"texts?.h1\" [innerText]=\"texts!.h1\"></h1>\n<h2 *ngIf=\"texts?.h2\" [innerText]=\"texts!.h2\"></h2>\n<h3 *ngIf=\"texts?.h3\" [innerText]=\"texts!.h3\"></h3>\n<p *ngIf=\"texts?.top\" [innerText]=\"texts!.top\"></p>\n\n<clr-datagrid [clrLoading]=\"ui.loading\">\n\n <!-- Actions -->\n <clr-dg-action-bar *ngIf=\"actions?.length\">\n <div *ngFor=\"let action of actions\" class=\"btn-group\">\n <button (click)=\"action.callback($event)\"\n [clrLoading]=\"action.loading ?? ClrLoadingState.DEFAULT\"\n class=\"btn btn-sm btn-secondary\"\n type=\"button\">\n <cds-icon *ngIf=\"action.icon\" [attr.shape]=\"action.icon\"></cds-icon>\n {{ action.label }}\n </button>\n </div>\n </clr-dg-action-bar>\n\n <!-- Placeholder -->\n <clr-dg-placeholder *ngIf=\"texts?.placeholder\">{{ texts!.placeholder }}</clr-dg-placeholder>\n\n <!-- Columns -->\n <clr-dg-column *ngFor=\"let col of data?.cols ?? NO_COLS\">{{ col.title }}</clr-dg-column>\n\n <!-- Rows -->\n <clr-dg-row *ngFor=\"let item of data?.items ?? NO_ITEMS\" [clrDgItem]=\"item\">\n <clr-dg-cell *ngFor=\"let col of data?.cols ?? NO_COLS\">\n\n <dt-cell-editable (save)=\"onEdit(item, col.property, $event.current)\"\n [enable]=\"ui.editable\"\n [fallbackLabel]=\"col.fallbackLabel ?? texts?.fallbackLabel ?? undefined\"\n [item]=\"item[col.property]\"></dt-cell-editable>\n </clr-dg-cell>\n </clr-dg-row>\n\n <clr-dg-footer *ngIf=\"data && texts?.counter\">\n {{ texts!.counter!(data!.items.length) }}\n </clr-dg-footer>\n</clr-datagrid>\n\n<p *ngIf=\"texts?.bottom\" [innerText]=\"texts!.bottom\"></p>\n", styles: ["@charset \"UTF-8\";/*!\n * data\u00B7caf\u00E9\n * Copyright (c) 2021-2022 Data Terrae\n * This program is under the terms of the GNU Affero General Public License version 3\n * The full license information can be found in LICENSE in the root directory of this project.\n */\n"] }] }], ctorParameters: function () { return []; }, propDecorators: { texts: [{ type: Input }], actions: [{ type: Input }], edit: [{ type: Output }], items: [{ type: Input }], editable: [{ type: Input }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0YWdyaWQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvZGF0YWdyaWQvc3JjL2xpYi9kYXRhZ3JpZC9kYXRhZ3JpZC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9kYXRhZ3JpZC9zcmMvbGliL2RhdGFncmlkL2RhdGFncmlkLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7R0FLRztBQUVILE9BQU8sRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDdkUsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUMvQyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFHckQsT0FBTyxFQUFnQixTQUFTLEVBQVEsSUFBSSxFQUFNLE1BQU0sVUFBVSxDQUFDOzs7OztJQVF0RCxpQkFBaUIsU0FBakIsaUJBQWlCO0lBMkI1QjtRQTFCUyxhQUFRLEdBQWEsRUFBRSxDQUFDO1FBQ3hCLFlBQU8sR0FBa0IsRUFBRSxDQUFDO1FBQzVCLG9CQUFlLEdBQUcsZUFBZSxDQUFDO1FBRzNDLE9BQUUsR0FBTyxTQUFTLEVBQUUsQ0FBQztRQWNyQjs7OztXQUlHO1FBQ08sU0FBSSxHQUFHLElBQUksWUFBWSxFQUFpQixDQUFDO0lBR25ELENBQUM7SUFFRDs7O09BR0c7SUFDSCxJQUFhLEtBQUssQ0FBQyxLQUF1QztRQUN4RCxJQUFJLENBQUMsUUFBUSxDQUFDLEtBQUssSUFBSSxTQUFTLENBQUMsQ0FBQztJQUNwQyxDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0gsSUFBYSxRQUFRLENBQUMsU0FBa0I7UUFDdEMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxRQUFRLEdBQUcsU0FBUyxJQUFJLElBQUksSUFBSSxHQUFHLFNBQVMsRUFBRSxLQUFLLE9BQU8sQ0FBQztJQUNyRSxDQUFDO0lBRUQsTUFBTSxDQUFDLElBQU8sRUFBRSxRQUFnQixFQUFFLFlBQWlCO1FBQ2pELElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDO1lBQ2IsUUFBUSxFQUFFLEVBQUUsR0FBRyxJQUFJLEVBQUU7WUFDckIsT0FBTyxFQUFFO2dCQUNQLEdBQUcsSUFBSTtnQkFDUCxDQUFDLFFBQVEsQ0FBQyxFQUFFLFlBQVk7YUFDekI7WUFDRCxpQkFBaUIsRUFBRSxDQUFDLFFBQVEsQ0FBQztTQUM5QixDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsOEVBQThFO0lBRXRFLFFBQVEsQ0FBQyxLQUFnQjtRQUMvQixJQUFJLEtBQUssRUFBRSxNQUFNLEVBQUU7WUFDakIscUJBQXFCO1lBQ3JCLE1BQU0sSUFBSSxHQUFhLE1BQU07aUJBQzFCLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7aUJBQ2QsR0FBRyxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsQ0FBUztnQkFDeEIsUUFBUTtnQkFDUixLQUFLLEVBQUUsUUFBUTtnQkFDZixJQUFJLEVBQUUsSUFBSSxDQUFDLElBQUk7YUFDZixDQUFBLENBQUMsQ0FBQztZQUVOLGFBQWE7WUFDYixJQUFJLENBQUMsSUFBSSxHQUFHO2dCQUNWLEtBQUs7Z0JBQ0wsSUFBSTthQUNMLENBQUM7WUFFRixZQUFZO1lBQ1osSUFBSSxDQUFDLEVBQUUsQ0FBQyxPQUFPLEdBQUcsS0FBSyxDQUFDO1NBRXpCO2FBQU07WUFDTCxhQUFhO1lBQ2IsSUFBSSxDQUFDLElBQUksR0FBRyxTQUFTLENBQUM7WUFFdEIsWUFBWTtZQUNaLElBQUksQ0FBQyxFQUFFLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQztTQUN4QjtJQUNILENBQUM7Q0FDRixDQUFBOzhHQTFGWSxpQkFBaUI7a0dBQWpCLGlCQUFpQixvS0NwQjlCLCs4REFrREE7QUQ5QmEsaUJBQWlCO0lBTjdCLFlBQVksRUFBRTtHQU1GLGlCQUFpQixDQTBGN0I7U0ExRlksaUJBQWlCOzJGQUFqQixpQkFBaUI7a0JBTDdCLFNBQVM7K0JBQ0UsYUFBYTswRUFpQmQsS0FBSztzQkFBYixLQUFLO2dCQUtHLE9BQU87c0JBQWYsS0FBSztnQkFPSSxJQUFJO3NCQUFiLE1BQU07Z0JBU00sS0FBSztzQkFBakIsS0FBSztnQkFXTyxRQUFRO3NCQUFwQixLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIGRhdGHCt2NhZsOpXG4gKiBDb3B5cmlnaHQgKGMpIDIwMjEtMjAyMiBEYXRhIFRlcnJhZVxuICogVGhpcyBwcm9ncmFtIGlzIHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIHZlcnNpb24gM1xuICogVGhlIGZ1bGwgbGljZW5zZSBpbmZvcm1hdGlvbiBjYW4gYmUgZm91bmQgaW4gTElDRU5TRSBpbiB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhpcyBwcm9qZWN0LlxuICovXG5cbmltcG9ydCB7IENvbXBvbmVudCwgRXZlbnRFbWl0dGVyLCBJbnB1dCwgT3V0cHV0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBDbHJMb2FkaW5nU3RhdGUgfSBmcm9tICdAY2xyL2FuZ3VsYXInO1xuaW1wb3J0IHsgVW50aWxEZXN0cm95IH0gZnJvbSAnQG5nbmVhdC91bnRpbC1kZXN0cm95JztcbmltcG9ydCB7IEFjdGlvbnNJbnB1dCwgSXRlbXNJbnB1dCwgVGV4dHNJbnB1dCB9IGZyb20gJy4uL2lvJztcbmltcG9ydCB7IEVkaXRPdXRwdXQgfSBmcm9tICcuLi9pby9lZGl0Lm91dHB1dCc7XG5pbXBvcnQgeyBDb2x1bW4sIERhdGEsIGluaXRpYWxVSSwgSXRlbSwgVHlwZSwgVUkgfSBmcm9tICcuLi9tb2RlbCc7XG5cbkBVbnRpbERlc3Ryb3koKVxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnZHQtZGF0YWdyaWQnLFxuICB0ZW1wbGF0ZVVybDogJy4vZGF0YWdyaWQuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9kYXRhZ3JpZC5jb21wb25lbnQuc2NzcyddLFxufSlcbmV4cG9ydCBjbGFzcyBEYXRhZ3JpZENvbXBvbmVudDxJIGV4dGVuZHMgSXRlbT4ge1xuICByZWFkb25seSBOT19JVEVNUzogQXJyYXk8ST4gPSBbXTtcbiAgcmVhZG9ubHkgTk9fQ09MUzogQXJyYXk8Q29sdW1uPiA9IFtdO1xuICByZWFkb25seSBDbHJMb2FkaW5nU3RhdGUgPSBDbHJMb2FkaW5nU3RhdGU7XG5cbiAgZGF0YT86IERhdGE8ST47XG4gIHVpOiBVSSA9IGluaXRpYWxVSSgpO1xuXG4gIC8vIC0tIExpZmVjeWNsZSAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4gIC8qKlxuICAgKiBDdXN0b21pemUgYWxsIHRleHRzIGluIGNvbXBvbmVudCBmb3IgaTE4biBwdXJwb3Nlcy5cbiAgICovXG4gIEBJbnB1dCgpIHRleHRzPzogVGV4dHNJbnB1dDtcblxuICAvKipcbiAgICogRGVmaW5lIGN1c3RvbSBhY3Rpb24gYnV0dG9ucy5cbiAgICovXG4gIEBJbnB1dCgpIGFjdGlvbnM/OiBBY3Rpb25zSW5wdXQ7XG5cbiAgLyoqXG4gICAqIERpc3BhdGNoIGV2ZXJ5dGltZSBhbiBpdGVtIGlzIHVwZGF0ZWQgaW4gdGhlIGRhdGFncmlkLlxuICAgKlxuICAgKiBAc2VlIGVkaXRhYmxlXG4gICAqL1xuICBAT3V0cHV0KCkgZWRpdCA9IG5ldyBFdmVudEVtaXR0ZXI8RWRpdE91dHB1dDxJPj4oKTtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXQgdGhlIGRhdGEgdG8gYmUgZGlzcGxheWVkLlxuICAgKiBAcGFyYW0gdmFsdWVcbiAgICovXG4gIEBJbnB1dCgpIHNldCBpdGVtcyh2YWx1ZTogSXRlbXNJbnB1dDxJPiB8IHVuZGVmaW5lZCB8IG51bGwpIHtcbiAgICB0aGlzLnVwZGF0ZVVJKHZhbHVlID8/IHVuZGVmaW5lZCk7XG4gIH1cblxuICAvKipcbiAgICogVHJhbnNmb3JtIHRoZSBncmlkIGVkaXRhYmxlLlxuICAgKlxuICAgKiBAcGFyYW0gc29tZXRoaW5nXG4gICAqXG4gICAqIEBzZWUgZWRpdFxuICAgKi9cbiAgQElucHV0KCkgc2V0IGVkaXRhYmxlKHNvbWV0aGluZzogdW5rbm93bikge1xuICAgIHRoaXMudWkuZWRpdGFibGUgPSBzb21ldGhpbmcgIT0gbnVsbCAmJiBgJHtzb21ldGhpbmd9YCAhPT0gXCJmYWxzZVwiO1xuICB9XG5cbiAgb25FZGl0KGl0ZW06IEksIHByb3BlcnR5OiBzdHJpbmcsIG1vZGlmaWNhdGlvbjogYW55KTogdm9pZCB7XG4gICAgdGhpcy5lZGl0LmVtaXQoe1xuICAgICAgcHJldmlvdXM6IHsgLi4uaXRlbSB9LFxuICAgICAgdXBkYXRlZDoge1xuICAgICAgICAuLi5pdGVtLFxuICAgICAgICBbcHJvcGVydHldOiBtb2RpZmljYXRpb24sXG4gICAgICB9LFxuICAgICAgdXBkYXRlZFByb3BlcnRpZXM6IFtwcm9wZXJ0eV0sXG4gICAgfSk7XG4gIH1cblxuICAvLyAtLSBIZWxwZXIgbWV0aG9kcyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuICBwcml2YXRlIHVwZGF0ZVVJKGl0ZW1zPzogQXJyYXk8ST4pIHtcbiAgICBpZiAoaXRlbXM/Lmxlbmd0aCkge1xuICAgICAgLy8gR2VuZXJhdGUgc3RydWN0dXJlXG4gICAgICBjb25zdCBjb2xzOiBDb2x1bW5bXSA9IE9iamVjdFxuICAgICAgICAua2V5cyhpdGVtc1swXSlcbiAgICAgICAgLm1hcChwcm9wZXJ0eSA9PiAoPENvbHVtbj57XG4gICAgICAgICAgcHJvcGVydHksXG4gICAgICAgICAgdGl0bGU6IHByb3BlcnR5LCAvLyBUT0RPOiBDYXBpdGFsaXplIGZpcnN0IGxldHRlclxuICAgICAgICAgIHR5cGU6IFR5cGUuVEVYVCxcbiAgICAgICAgfSkpO1xuXG4gICAgICAvLyBCdWlsZCBkYXRhXG4gICAgICB0aGlzLmRhdGEgPSB7XG4gICAgICAgIGl0ZW1zLFxuICAgICAgICBjb2xzLFxuICAgICAgfTtcblxuICAgICAgLy8gVXBkYXRlIFVJXG4gICAgICB0aGlzLnVpLmxvYWRpbmcgPSBmYWxzZTtcblxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBDbGVhciBkYXRhXG4gICAgICB0aGlzLmRhdGEgPSB1bmRlZmluZWQ7XG5cbiAgICAgIC8vIFVwZGF0ZSBVSVxuICAgICAgdGhpcy51aS5sb2FkaW5nID0gdHJ1ZTtcbiAgICB9XG4gIH1cbn1cbiIsIjwhLS1cbiAgfiBkYXRhwrdjYWbDqVxuICB+IENvcHlyaWdodCAoYykgMjAyMS0yMDIyIERhdGEgVGVycmFlXG4gIH4gVGhpcyBwcm9ncmFtIGlzIHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIHZlcnNpb24gM1xuICB+IFRoZSBmdWxsIGxpY2Vuc2UgaW5mb3JtYXRpb24gY2FuIGJlIGZvdW5kIGluIExJQ0VOU0UgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgcHJvamVjdC5cbiAgLS0+XG5cbjxoMSAqbmdJZj1cInRleHRzPy5oMVwiIFtpbm5lclRleHRdPVwidGV4dHMhLmgxXCI+PC9oMT5cbjxoMiAqbmdJZj1cInRleHRzPy5oMlwiIFtpbm5lclRleHRdPVwidGV4dHMhLmgyXCI+PC9oMj5cbjxoMyAqbmdJZj1cInRleHRzPy5oM1wiIFtpbm5lclRleHRdPVwidGV4dHMhLmgzXCI+PC9oMz5cbjxwICpuZ0lmPVwidGV4dHM/LnRvcFwiIFtpbm5lclRleHRdPVwidGV4dHMhLnRvcFwiPjwvcD5cblxuPGNsci1kYXRhZ3JpZCBbY2xyTG9hZGluZ109XCJ1aS5sb2FkaW5nXCI+XG5cbiAgPCEtLSBBY3Rpb25zIC0tPlxuICA8Y2xyLWRnLWFjdGlvbi1iYXIgKm5nSWY9XCJhY3Rpb25zPy5sZW5ndGhcIj5cbiAgICA8ZGl2ICpuZ0Zvcj1cImxldCBhY3Rpb24gb2YgYWN0aW9uc1wiIGNsYXNzPVwiYnRuLWdyb3VwXCI+XG4gICAgICA8YnV0dG9uIChjbGljayk9XCJhY3Rpb24uY2FsbGJhY2soJGV2ZW50KVwiXG4gICAgICAgICAgICAgIFtjbHJMb2FkaW5nXT1cImFjdGlvbi5sb2FkaW5nID8/IENsckxvYWRpbmdTdGF0ZS5ERUZBVUxUXCJcbiAgICAgICAgICAgICAgY2xhc3M9XCJidG4gYnRuLXNtIGJ0bi1zZWNvbmRhcnlcIlxuICAgICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCI+XG4gICAgICAgIDxjZHMtaWNvbiAqbmdJZj1cImFjdGlvbi5pY29uXCIgW2F0dHIuc2hhcGVdPVwiYWN0aW9uLmljb25cIj48L2Nkcy1pY29uPlxuICAgICAgICB7eyBhY3Rpb24ubGFiZWwgfX1cbiAgICAgIDwvYnV0dG9uPlxuICAgIDwvZGl2PlxuICA8L2Nsci1kZy1hY3Rpb24tYmFyPlxuXG4gIDwhLS0gUGxhY2Vob2xkZXIgLS0+XG4gIDxjbHItZGctcGxhY2Vob2xkZXIgKm5nSWY9XCJ0ZXh0cz8ucGxhY2Vob2xkZXJcIj57eyB0ZXh0cyEucGxhY2Vob2xkZXIgfX08L2Nsci1kZy1wbGFjZWhvbGRlcj5cblxuICA8IS0tIENvbHVtbnMgLS0+XG4gIDxjbHItZGctY29sdW1uICpuZ0Zvcj1cImxldCBjb2wgb2YgZGF0YT8uY29scyA/PyBOT19DT0xTXCI+e3sgY29sLnRpdGxlIH19PC9jbHItZGctY29sdW1uPlxuXG4gIDwhLS0gUm93cyAtLT5cbiAgPGNsci1kZy1yb3cgKm5nRm9yPVwibGV0IGl0ZW0gb2YgZGF0YT8uaXRlbXMgPz8gTk9fSVRFTVNcIiBbY2xyRGdJdGVtXT1cIml0ZW1cIj5cbiAgICA8Y2xyLWRnLWNlbGwgKm5nRm9yPVwibGV0IGNvbCBvZiBkYXRhPy5jb2xzID8/IE5PX0NPTFNcIj5cblxuICAgICAgPGR0LWNlbGwtZWRpdGFibGUgKHNhdmUpPVwib25FZGl0KGl0ZW0sIGNvbC5wcm9wZXJ0eSwgJGV2ZW50LmN1cnJlbnQpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIFtlbmFibGVdPVwidWkuZWRpdGFibGVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgW2ZhbGxiYWNrTGFiZWxdPVwiY29sLmZhbGxiYWNrTGFiZWwgPz8gdGV4dHM/LmZhbGxiYWNrTGFiZWwgPz8gdW5kZWZpbmVkXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIFtpdGVtXT1cIml0ZW1bY29sLnByb3BlcnR5XVwiPjwvZHQtY2VsbC1lZGl0YWJsZT5cbiAgICA8L2Nsci1kZy1jZWxsPlxuICA8L2Nsci1kZy1yb3c+XG5cbiAgPGNsci1kZy1mb290ZXIgKm5nSWY9XCJkYXRhICYmIHRleHRzPy5jb3VudGVyXCI+XG4gICAge3sgdGV4dHMhLmNvdW50ZXIhKGRhdGEhLml0ZW1zLmxlbmd0aCkgfX1cbiAgPC9jbHItZGctZm9vdGVyPlxuPC9jbHItZGF0YWdyaWQ+XG5cbjxwICpuZ0lmPVwidGV4dHM/LmJvdHRvbVwiIFtpbm5lclRleHRdPVwidGV4dHMhLmJvdHRvbVwiPjwvcD5cbiJdfQ==