UNPKG

@iotize/ionic

Version:

Iotize specific building blocks on top of @ionic/angular.

89 lines 20.8 kB
import { ChangeDetectorRef, Component, EventEmitter, Input, Output, } from '@angular/core'; import { bufferToHexString } from '@iotize/common/byte-converter'; import * as i0 from "@angular/core"; import * as i1 from "@angular/common"; import * as i2 from "@ionic/angular"; export class TapDatalogTableComponent { constructor(changeRefDetector) { this.changeRefDetector = changeRefDetector; this.dataColumns = []; this.date = true; this.sync = true; this.onSyncEvent = new EventEmitter(); this.onRetrySync = new EventEmitter(); } set dataLogger(dataLogger) { if (dataLogger) { dataLogger.stream.subscribe((p) => { if (this.dataColumns.length === 0) { this.initColumnsFromPacket(p); } if (!this._packets) { this._packets = []; } this._packets.push(p); this.changeRefDetector.detectChanges(); }); } } set packets(packets) { this._packets = packets; if (packets && this.dataColumns.length === 0 && packets.length > 0) { this.initColumnsFromPacket(packets[0]); } } get packets() { return this._packets; } packetVariableValue(packet, key) { let value = packet.decodedData[key]; if (value instanceof Uint8Array) { value = `0x${bufferToHexString(value)}`; } return value; } packetId(packet) { return packet.meta.packetId; } packetDate(packet) { return packet.meta.logTime; } isPacketSync(packetInfo) { if (!('syncInfo' in packetInfo)) { return false; } return packetInfo.syncInfo && packetInfo.syncInfo.isSync; } syncPacket(packetInfo) { this.onRetrySync.emit(packetInfo); } initColumnsFromPacket(p) { this.dataColumns = Object.keys(p.decodedData).map((key) => { return { key: key, title: key, }; }); } } /** @nocollapse */ TapDatalogTableComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TapDatalogTableComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); /** @nocollapse */ TapDatalogTableComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: TapDatalogTableComponent, selector: "tap-datalog-table", inputs: { dataColumns: "dataColumns", date: "date", sync: "sync", dataLogger: "dataLogger", packets: "packets" }, outputs: { onSyncEvent: "onSyncEvent", onRetrySync: "onRetrySync" }, ngImport: i0, template: "<table *ngIf=\"dataColumns\" class=\"table\" mat-table>\n <thead>\n <th *ngIf=\"date\"><ion-icon name=\"time\"></ion-icon> Date</th>\n <th><ion-icon name=\"document\"></ion-icon> ID</th>\n <th *ngFor=\"let dataColumn of dataColumns\">\n <ion-icon name=\"analytics\"></ion-icon> {{ dataColumn.title }}\n </th>\n <th *ngIf=\"sync\"><ion-icon name=\"cloud\"></ion-icon> Cloud sync</th>\n </thead>\n <tbody>\n <tr *ngFor=\"let packet of packets\">\n <td *ngIf=\"date\">\n {{ packetDate(packet) | date: 'short' }}\n </td>\n <td>\n {{ packetId(packet) }}\n </td>\n <td *ngFor=\"let info of dataColumns\">\n {{ packetVariableValue(packet, info.key) }}\n </td>\n <td *ngIf=\"sync\">\n <ion-text *ngIf=\"isPacketSync(packet)\" color=\"success\">\n <ion-icon [name]=\"'checkmark'\"></ion-icon> &nbsp; Sync\n </ion-text>\n <ion-text *ngIf=\"!isPacketSync(packet)\" color=\"danger\">\n <ion-icon [name]=\"'alert'\"></ion-icon> &nbsp; Not sync &nbsp;\n <a (click)=\"syncPacket(packet)\"> retry </a>\n </ion-text>\n <!-- <ion-buttons slot=\"end\">\n <ion-button (click)=\"syncPacket(packet)\" [color]=\"isPacketSync(packet) ? 'success': ''\" [disabled]=\"isPacketSync(packet)\">\n <ion-icon [name]=\"isPacketSync(packet) ? 'checkmark' : 'sync'\"></ion-icon>\n Sync\n </ion-button>\n <ion-button (click)=\"decodePacket(syncInfo)\">\n <ion-icon name=\"sync\"></ion-icon>\n Decode\n </ion-button> \n <ion-button (click)=\"detail(syncInfo)\">\n <ion-icon name=\"more\"></ion-icon>\n Detail\n </ion-button> \n </ion-buttons>-->\n </td>\n </tr>\n </tbody>\n</table>\n", styles: ["table{width:100%;border-collapse:collapse}tr:nth-of-type(odd){background:#eee}th{background:#333;color:#fff;font-weight:700}td,th{padding:10px;text-align:left}@media only screen and (max-width: 760px),(min-device-width: 768px) and (max-device-width: 1024px){table,thead,tbody,th,td,tr{display:block}thead tr{position:absolute;top:-9999px;left:-9999px}tr{border:1px solid #ccc}td{border:none;border-bottom:1px solid #eee;position:relative;padding-left:50%}td:before{position:relative;top:0;left:6px;width:45%;padding-right:10px;white-space:nowrap}}@media only screen and (min-device-width: 320px) and (max-device-width: 480px){body{padding:0;margin:0;width:320px}}@media only screen and (min-device-width: 768px) and (max-device-width: 1024px){body{width:495px}}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i2.IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "pipe", type: i1.DatePipe, name: "date" }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TapDatalogTableComponent, decorators: [{ type: Component, args: [{ selector: 'tap-datalog-table', template: "<table *ngIf=\"dataColumns\" class=\"table\" mat-table>\n <thead>\n <th *ngIf=\"date\"><ion-icon name=\"time\"></ion-icon> Date</th>\n <th><ion-icon name=\"document\"></ion-icon> ID</th>\n <th *ngFor=\"let dataColumn of dataColumns\">\n <ion-icon name=\"analytics\"></ion-icon> {{ dataColumn.title }}\n </th>\n <th *ngIf=\"sync\"><ion-icon name=\"cloud\"></ion-icon> Cloud sync</th>\n </thead>\n <tbody>\n <tr *ngFor=\"let packet of packets\">\n <td *ngIf=\"date\">\n {{ packetDate(packet) | date: 'short' }}\n </td>\n <td>\n {{ packetId(packet) }}\n </td>\n <td *ngFor=\"let info of dataColumns\">\n {{ packetVariableValue(packet, info.key) }}\n </td>\n <td *ngIf=\"sync\">\n <ion-text *ngIf=\"isPacketSync(packet)\" color=\"success\">\n <ion-icon [name]=\"'checkmark'\"></ion-icon> &nbsp; Sync\n </ion-text>\n <ion-text *ngIf=\"!isPacketSync(packet)\" color=\"danger\">\n <ion-icon [name]=\"'alert'\"></ion-icon> &nbsp; Not sync &nbsp;\n <a (click)=\"syncPacket(packet)\"> retry </a>\n </ion-text>\n <!-- <ion-buttons slot=\"end\">\n <ion-button (click)=\"syncPacket(packet)\" [color]=\"isPacketSync(packet) ? 'success': ''\" [disabled]=\"isPacketSync(packet)\">\n <ion-icon [name]=\"isPacketSync(packet) ? 'checkmark' : 'sync'\"></ion-icon>\n Sync\n </ion-button>\n <ion-button (click)=\"decodePacket(syncInfo)\">\n <ion-icon name=\"sync\"></ion-icon>\n Decode\n </ion-button> \n <ion-button (click)=\"detail(syncInfo)\">\n <ion-icon name=\"more\"></ion-icon>\n Detail\n </ion-button> \n </ion-buttons>-->\n </td>\n </tr>\n </tbody>\n</table>\n", styles: ["table{width:100%;border-collapse:collapse}tr:nth-of-type(odd){background:#eee}th{background:#333;color:#fff;font-weight:700}td,th{padding:10px;text-align:left}@media only screen and (max-width: 760px),(min-device-width: 768px) and (max-device-width: 1024px){table,thead,tbody,th,td,tr{display:block}thead tr{position:absolute;top:-9999px;left:-9999px}tr{border:1px solid #ccc}td{border:none;border-bottom:1px solid #eee;position:relative;padding-left:50%}td:before{position:relative;top:0;left:6px;width:45%;padding-right:10px;white-space:nowrap}}@media only screen and (min-device-width: 320px) and (max-device-width: 480px){body{padding:0;margin:0;width:320px}}@media only screen and (min-device-width: 768px) and (max-device-width: 1024px){body{width:495px}}\n"] }] }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }]; }, propDecorators: { dataColumns: [{ type: Input }], date: [{ type: Input }], sync: [{ type: Input }], onSyncEvent: [{ type: Output }], dataLogger: [{ type: Input }], packets: [{ type: Input }], onRetrySync: [{ type: Output }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFwLWRhdGFsb2ctdGFibGUuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvaW90aXplLWlvbmljL21vbml0b3Jpbmcvc3JjL2xpYi91aS1jb21wb25lbnRzL3RhcC1kYXRhbG9nLXRhYmxlL3RhcC1kYXRhbG9nLXRhYmxlLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2lvdGl6ZS1pb25pYy9tb25pdG9yaW5nL3NyYy9saWIvdWktY29tcG9uZW50cy90YXAtZGF0YWxvZy10YWJsZS90YXAtZGF0YWxvZy10YWJsZS5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsaUJBQWlCLEVBQ2pCLFNBQVMsRUFDVCxZQUFZLEVBQ1osS0FBSyxFQUNMLE1BQU0sR0FDUCxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQzs7OztBQVFsRSxNQUFNLE9BQU8sd0JBQXdCO0lBV25DLFlBQXNCLGlCQUFvQztRQUFwQyxzQkFBaUIsR0FBakIsaUJBQWlCLENBQW1CO1FBUmpELGdCQUFXLEdBQXFDLEVBQUUsQ0FBQztRQUVuRCxTQUFJLEdBQUcsSUFBSSxDQUFDO1FBRVosU0FBSSxHQUFHLElBQUksQ0FBQztRQUVYLGdCQUFXLEdBQUcsSUFBSSxZQUFZLEVBQXlCLENBQUM7UUE0QnhELGdCQUFXLEdBQUcsSUFBSSxZQUFZLEVBQXlCLENBQUM7SUExQkwsQ0FBQztJQUU5RCxJQUFhLFVBQVUsQ0FBQyxVQUF1QztRQUM3RCxJQUFJLFVBQVUsRUFBRTtZQUNkLFVBQVUsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUN6QixDQUFDLENBQWtELEVBQUUsRUFBRTtnQkFDckQsSUFBSSxJQUFJLENBQUMsV0FBVyxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7b0JBQ2pDLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDLENBQUMsQ0FBQztpQkFDL0I7Z0JBQ0QsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUU7b0JBQ2xCLElBQUksQ0FBQyxRQUFRLEdBQUcsRUFBRSxDQUFDO2lCQUNwQjtnQkFDRCxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDdEIsSUFBSSxDQUFDLGlCQUFpQixDQUFDLGFBQWEsRUFBRSxDQUFDO1lBQ3pDLENBQUMsQ0FDRixDQUFDO1NBQ0g7SUFDSCxDQUFDO0lBRUQsSUFBYSxPQUFPLENBQUMsT0FBaUQ7UUFDcEUsSUFBSSxDQUFDLFFBQVEsR0FBRyxPQUFPLENBQUM7UUFDeEIsSUFBSSxPQUFPLElBQUksSUFBSSxDQUFDLFdBQVcsQ0FBQyxNQUFNLEtBQUssQ0FBQyxJQUFJLE9BQU8sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFO1lBQ2xFLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUN4QztJQUNILENBQUM7SUFJRCxJQUFJLE9BQU87UUFDVCxPQUFPLElBQUksQ0FBQyxRQUFRLENBQUM7SUFDdkIsQ0FBQztJQUVELG1CQUFtQixDQUFDLE1BQWtDLEVBQUUsR0FBVztRQUNqRSxJQUFJLEtBQUssR0FBRyxNQUFNLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ3BDLElBQUksS0FBSyxZQUFZLFVBQVUsRUFBRTtZQUMvQixLQUFLLEdBQUcsS0FBSyxpQkFBaUIsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1NBQ3pDO1FBQ0QsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0lBRUQsUUFBUSxDQUFDLE1BQWtDO1FBQ3pDLE9BQU8sTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUM7SUFDOUIsQ0FBQztJQUVELFVBQVUsQ0FBQyxNQUFrQztRQUMzQyxPQUFPLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDO0lBQzdCLENBQUM7SUFFRCxZQUFZLENBQUMsVUFBOEQ7UUFDekUsSUFBSSxDQUFDLENBQUMsVUFBVSxJQUFJLFVBQVUsQ0FBQyxFQUFFO1lBQy9CLE9BQU8sS0FBSyxDQUFDO1NBQ2Q7UUFDRCxPQUFPLFVBQVUsQ0FBQyxRQUFRLElBQUksVUFBVSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUM7SUFDM0QsQ0FBQztJQUVELFVBQVUsQ0FBQyxVQUFpQztRQUMxQyxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUNwQyxDQUFDO0lBRU8scUJBQXFCLENBQzNCLENBQWtEO1FBRWxELElBQUksQ0FBQyxXQUFXLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUU7WUFDeEQsT0FBTztnQkFDTCxHQUFHLEVBQUUsR0FBRztnQkFDUixLQUFLLEVBQUUsR0FBRzthQUNYLENBQUM7UUFDSixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7O3lJQS9FVSx3QkFBd0I7NkhBQXhCLHdCQUF3QixnUENmckMsbzVFQThDQTs0RkQvQmEsd0JBQXdCO2tCQUxwQyxTQUFTOytCQUNFLG1CQUFtQjt3R0FPcEIsV0FBVztzQkFBbkIsS0FBSztnQkFFRyxJQUFJO3NCQUFaLEtBQUs7Z0JBRUcsSUFBSTtzQkFBWixLQUFLO2dCQUVJLFdBQVc7c0JBQXBCLE1BQU07Z0JBSU0sVUFBVTtzQkFBdEIsS0FBSztnQkFpQk8sT0FBTztzQkFBbkIsS0FBSztnQkFPSSxXQUFXO3NCQUFwQixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gIENvbXBvbmVudCxcbiAgRXZlbnRFbWl0dGVyLFxuICBJbnB1dCxcbiAgT3V0cHV0LFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IGJ1ZmZlclRvSGV4U3RyaW5nIH0gZnJvbSAnQGlvdGl6ZS9jb21tb24vYnl0ZS1jb252ZXJ0ZXInO1xuaW1wb3J0IHsgSW9uaWNEYXRhTG9nZ2VyLCBTeW5jYWJsZURhdGFsb2dQYWNrZXQgfSBmcm9tICdAaW90aXplL2lvbmljJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAndGFwLWRhdGFsb2ctdGFibGUnLFxuICB0ZW1wbGF0ZVVybDogJy4vdGFwLWRhdGFsb2ctdGFibGUuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi90YXAtZGF0YWxvZy10YWJsZS5jb21wb25lbnQuc2NzcyddLFxufSlcbmV4cG9ydCBjbGFzcyBUYXBEYXRhbG9nVGFibGVDb21wb25lbnQge1xuICBfcGFja2V0cz86IElvbmljRGF0YUxvZ2dlci5QYWNrZXRJbmZvW107XG5cbiAgQElucHV0KCkgZGF0YUNvbHVtbnM6IHsga2V5OiBzdHJpbmc7IHRpdGxlOiBzdHJpbmcgfVtdID0gW107XG5cbiAgQElucHV0KCkgZGF0ZSA9IHRydWU7XG5cbiAgQElucHV0KCkgc3luYyA9IHRydWU7XG5cbiAgQE91dHB1dCgpIG9uU3luY0V2ZW50ID0gbmV3IEV2ZW50RW1pdHRlcjxTeW5jYWJsZURhdGFsb2dQYWNrZXQ+KCk7XG5cbiAgY29uc3RydWN0b3IocHJvdGVjdGVkIGNoYW5nZVJlZkRldGVjdG9yOiBDaGFuZ2VEZXRlY3RvclJlZikge31cblxuICBASW5wdXQoKSBzZXQgZGF0YUxvZ2dlcihkYXRhTG9nZ2VyOiBJb25pY0RhdGFMb2dnZXIgfCB1bmRlZmluZWQpIHtcbiAgICBpZiAoZGF0YUxvZ2dlcikge1xuICAgICAgZGF0YUxvZ2dlci5zdHJlYW0uc3Vic2NyaWJlKFxuICAgICAgICAocDogSW9uaWNEYXRhTG9nZ2VyLlBhY2tldEluZm88UmVjb3JkPHN0cmluZywgYW55Pj4pID0+IHtcbiAgICAgICAgICBpZiAodGhpcy5kYXRhQ29sdW1ucy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHRoaXMuaW5pdENvbHVtbnNGcm9tUGFja2V0KHApO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoIXRoaXMuX3BhY2tldHMpIHtcbiAgICAgICAgICAgIHRoaXMuX3BhY2tldHMgPSBbXTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhpcy5fcGFja2V0cy5wdXNoKHApO1xuICAgICAgICAgIHRoaXMuY2hhbmdlUmVmRGV0ZWN0b3IuZGV0ZWN0Q2hhbmdlcygpO1xuICAgICAgICB9XG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIEBJbnB1dCgpIHNldCBwYWNrZXRzKHBhY2tldHM6IElvbmljRGF0YUxvZ2dlci5QYWNrZXRJbmZvW10gfCB1bmRlZmluZWQpIHtcbiAgICB0aGlzLl9wYWNrZXRzID0gcGFja2V0cztcbiAgICBpZiAocGFja2V0cyAmJiB0aGlzLmRhdGFDb2x1bW5zLmxlbmd0aCA9PT0gMCAmJiBwYWNrZXRzLmxlbmd0aCA+IDApIHtcbiAgICAgIHRoaXMuaW5pdENvbHVtbnNGcm9tUGFja2V0KHBhY2tldHNbMF0pO1xuICAgIH1cbiAgfVxuXG4gIEBPdXRwdXQoKSBvblJldHJ5U3luYyA9IG5ldyBFdmVudEVtaXR0ZXI8U3luY2FibGVEYXRhbG9nUGFja2V0PigpO1xuXG4gIGdldCBwYWNrZXRzKCkge1xuICAgIHJldHVybiB0aGlzLl9wYWNrZXRzO1xuICB9XG5cbiAgcGFja2V0VmFyaWFibGVWYWx1ZShwYWNrZXQ6IElvbmljRGF0YUxvZ2dlci5QYWNrZXRJbmZvLCBrZXk6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgbGV0IHZhbHVlID0gcGFja2V0LmRlY29kZWREYXRhW2tleV07XG4gICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgVWludDhBcnJheSkge1xuICAgICAgdmFsdWUgPSBgMHgke2J1ZmZlclRvSGV4U3RyaW5nKHZhbHVlKX1gO1xuICAgIH1cbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwYWNrZXRJZChwYWNrZXQ6IElvbmljRGF0YUxvZ2dlci5QYWNrZXRJbmZvKTogbnVtYmVyIHtcbiAgICByZXR1cm4gcGFja2V0Lm1ldGEucGFja2V0SWQ7XG4gIH1cblxuICBwYWNrZXREYXRlKHBhY2tldDogSW9uaWNEYXRhTG9nZ2VyLlBhY2tldEluZm8pOiBEYXRlIHtcbiAgICByZXR1cm4gcGFja2V0Lm1ldGEubG9nVGltZTtcbiAgfVxuXG4gIGlzUGFja2V0U3luYyhwYWNrZXRJbmZvOiBTeW5jYWJsZURhdGFsb2dQYWNrZXQgfCBJb25pY0RhdGFMb2dnZXIuUGFja2V0SW5mbykge1xuICAgIGlmICghKCdzeW5jSW5mbycgaW4gcGFja2V0SW5mbykpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIHBhY2tldEluZm8uc3luY0luZm8gJiYgcGFja2V0SW5mby5zeW5jSW5mby5pc1N5bmM7XG4gIH1cblxuICBzeW5jUGFja2V0KHBhY2tldEluZm86IFN5bmNhYmxlRGF0YWxvZ1BhY2tldCkge1xuICAgIHRoaXMub25SZXRyeVN5bmMuZW1pdChwYWNrZXRJbmZvKTtcbiAgfVxuXG4gIHByaXZhdGUgaW5pdENvbHVtbnNGcm9tUGFja2V0KFxuICAgIHA6IElvbmljRGF0YUxvZ2dlci5QYWNrZXRJbmZvPFJlY29yZDxzdHJpbmcsIGFueT4+XG4gICkge1xuICAgIHRoaXMuZGF0YUNvbHVtbnMgPSBPYmplY3Qua2V5cyhwLmRlY29kZWREYXRhKS5tYXAoKGtleSkgPT4ge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAga2V5OiBrZXksXG4gICAgICAgIHRpdGxlOiBrZXksXG4gICAgICB9O1xuICAgIH0pO1xuICB9XG59XG4iLCI8dGFibGUgKm5nSWY9XCJkYXRhQ29sdW1uc1wiIGNsYXNzPVwidGFibGVcIiBtYXQtdGFibGU+XG4gIDx0aGVhZD5cbiAgICA8dGggKm5nSWY9XCJkYXRlXCI+PGlvbi1pY29uIG5hbWU9XCJ0aW1lXCI+PC9pb24taWNvbj4gRGF0ZTwvdGg+XG4gICAgPHRoPjxpb24taWNvbiBuYW1lPVwiZG9jdW1lbnRcIj48L2lvbi1pY29uPiBJRDwvdGg+XG4gICAgPHRoICpuZ0Zvcj1cImxldCBkYXRhQ29sdW1uIG9mIGRhdGFDb2x1bW5zXCI+XG4gICAgICA8aW9uLWljb24gbmFtZT1cImFuYWx5dGljc1wiPjwvaW9uLWljb24+IHt7IGRhdGFDb2x1bW4udGl0bGUgfX1cbiAgICA8L3RoPlxuICAgIDx0aCAqbmdJZj1cInN5bmNcIj48aW9uLWljb24gbmFtZT1cImNsb3VkXCI+PC9pb24taWNvbj4gQ2xvdWQgc3luYzwvdGg+XG4gIDwvdGhlYWQ+XG4gIDx0Ym9keT5cbiAgICA8dHIgKm5nRm9yPVwibGV0IHBhY2tldCBvZiBwYWNrZXRzXCI+XG4gICAgICA8dGQgKm5nSWY9XCJkYXRlXCI+XG4gICAgICAgIHt7IHBhY2tldERhdGUocGFja2V0KSB8IGRhdGU6ICdzaG9ydCcgfX1cbiAgICAgIDwvdGQ+XG4gICAgICA8dGQ+XG4gICAgICAgIHt7IHBhY2tldElkKHBhY2tldCkgfX1cbiAgICAgIDwvdGQ+XG4gICAgICA8dGQgKm5nRm9yPVwibGV0IGluZm8gb2YgZGF0YUNvbHVtbnNcIj5cbiAgICAgICAge3sgcGFja2V0VmFyaWFibGVWYWx1ZShwYWNrZXQsIGluZm8ua2V5KSB9fVxuICAgICAgPC90ZD5cbiAgICAgIDx0ZCAqbmdJZj1cInN5bmNcIj5cbiAgICAgICAgPGlvbi10ZXh0ICpuZ0lmPVwiaXNQYWNrZXRTeW5jKHBhY2tldClcIiBjb2xvcj1cInN1Y2Nlc3NcIj5cbiAgICAgICAgICA8aW9uLWljb24gW25hbWVdPVwiJ2NoZWNrbWFyaydcIj48L2lvbi1pY29uPiAmbmJzcDsgU3luY1xuICAgICAgICA8L2lvbi10ZXh0PlxuICAgICAgICA8aW9uLXRleHQgKm5nSWY9XCIhaXNQYWNrZXRTeW5jKHBhY2tldClcIiBjb2xvcj1cImRhbmdlclwiPlxuICAgICAgICAgIDxpb24taWNvbiBbbmFtZV09XCInYWxlcnQnXCI+PC9pb24taWNvbj4gJm5ic3A7IE5vdCBzeW5jICZuYnNwO1xuICAgICAgICAgIDxhIChjbGljayk9XCJzeW5jUGFja2V0KHBhY2tldClcIj4gcmV0cnkgPC9hPlxuICAgICAgICA8L2lvbi10ZXh0PlxuICAgICAgICA8IS0tICA8aW9uLWJ1dHRvbnMgc2xvdD1cImVuZFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlvbi1idXR0b24gKGNsaWNrKT1cInN5bmNQYWNrZXQocGFja2V0KVwiIFtjb2xvcl09XCJpc1BhY2tldFN5bmMocGFja2V0KSA/ICdzdWNjZXNzJzogJydcIiBbZGlzYWJsZWRdPVwiaXNQYWNrZXRTeW5jKHBhY2tldClcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW9uLWljb24gW25hbWVdPVwiaXNQYWNrZXRTeW5jKHBhY2tldCkgPyAnY2hlY2ttYXJrJyA6ICdzeW5jJ1wiPjwvaW9uLWljb24+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU3luY1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9pb24tYnV0dG9uPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlvbi1idXR0b24gKGNsaWNrKT1cImRlY29kZVBhY2tldChzeW5jSW5mbylcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxpb24taWNvbiBuYW1lPVwic3luY1wiPjwvaW9uLWljb24+XG4gICAgICAgICAgICAgICAgICAgICAgICBEZWNvZGVcbiAgICAgICAgICAgICAgICAgICAgPC9pb24tYnV0dG9uPiBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpb24tYnV0dG9uIChjbGljayk9XCJkZXRhaWwoc3luY0luZm8pXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlvbi1pY29uIG5hbWU9XCJtb3JlXCI+PC9pb24taWNvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBEZXRhaWxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2lvbi1idXR0b24+IFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2lvbi1idXR0b25zPi0tPlxuICAgICAgPC90ZD5cbiAgICA8L3RyPlxuICA8L3Rib2R5PlxuPC90YWJsZT5cbiJdfQ==