@iotize/ionic
Version:
Iotize specific building blocks on top of @ionic/angular.
91 lines • 20.8 kB
JavaScript
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 {
changeRefDetector;
_packets;
dataColumns = [];
date = true;
sync = true;
onSyncEvent = new EventEmitter();
constructor(changeRefDetector) {
this.changeRefDetector = changeRefDetector;
}
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]);
}
}
onRetrySync = new EventEmitter();
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 */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TapDatalogTableComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
/** @nocollapse */ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", 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> Sync\n </ion-text>\n <ion-text *ngIf=\"!isPacketSync(packet)\" color=\"danger\">\n <ion-icon [name]=\"'alert'\"></ion-icon> Not sync \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: "18.2.14", 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> Sync\n </ion-text>\n <ion-text *ngIf=\"!isPacketSync(packet)\" color=\"danger\">\n <ion-icon [name]=\"'alert'\"></ion-icon> Not sync \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: () => [{ 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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFwLWRhdGFsb2ctdGFibGUuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvaW90aXplLWlvbmljL21vbml0b3Jpbmcvc3JjL2xpYi91aS1jb21wb25lbnRzL3RhcC1kYXRhbG9nLXRhYmxlL3RhcC1kYXRhbG9nLXRhYmxlLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2lvdGl6ZS1pb25pYy9tb25pdG9yaW5nL3NyYy9saWIvdWktY29tcG9uZW50cy90YXAtZGF0YWxvZy10YWJsZS90YXAtZGF0YWxvZy10YWJsZS5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsaUJBQWlCLEVBQ2pCLFNBQVMsRUFDVCxZQUFZLEVBQ1osS0FBSyxFQUNMLE1BQU0sR0FDUCxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQzs7OztBQVFsRSxNQUFNLE9BQU8sd0JBQXdCO0lBV2I7SUFWdEIsUUFBUSxDQUFnQztJQUUvQixXQUFXLEdBQXFDLEVBQUUsQ0FBQztJQUVuRCxJQUFJLEdBQUcsSUFBSSxDQUFDO0lBRVosSUFBSSxHQUFHLElBQUksQ0FBQztJQUVYLFdBQVcsR0FBRyxJQUFJLFlBQVksRUFBeUIsQ0FBQztJQUVsRSxZQUFzQixpQkFBb0M7UUFBcEMsc0JBQWlCLEdBQWpCLGlCQUFpQixDQUFtQjtJQUFHLENBQUM7SUFFOUQsSUFBYSxVQUFVLENBQUMsVUFBdUM7UUFDN0QsSUFBSSxVQUFVLEVBQUUsQ0FBQztZQUNmLFVBQVUsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUN6QixDQUFDLENBQWtELEVBQUUsRUFBRTtnQkFDckQsSUFBSSxJQUFJLENBQUMsV0FBVyxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUUsQ0FBQztvQkFDbEMsSUFBSSxDQUFDLHFCQUFxQixDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUNoQyxDQUFDO2dCQUNELElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7b0JBQ25CLElBQUksQ0FBQyxRQUFRLEdBQUcsRUFBRSxDQUFDO2dCQUNyQixDQUFDO2dCQUNELElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUN0QixJQUFJLENBQUMsaUJBQWlCLENBQUMsYUFBYSxFQUFFLENBQUM7WUFDekMsQ0FBQyxDQUNGLENBQUM7UUFDSixDQUFDO0lBQ0gsQ0FBQztJQUVELElBQWEsT0FBTyxDQUFDLE9BQWlEO1FBQ3BFLElBQUksQ0FBQyxRQUFRLEdBQUcsT0FBTyxDQUFDO1FBQ3hCLElBQUksT0FBTyxJQUFJLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxLQUFLLENBQUMsSUFBSSxPQUFPLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ25FLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN6QyxDQUFDO0lBQ0gsQ0FBQztJQUVTLFdBQVcsR0FBRyxJQUFJLFlBQVksRUFBeUIsQ0FBQztJQUVsRSxJQUFJLE9BQU87UUFDVCxPQUFPLElBQUksQ0FBQyxRQUFRLENBQUM7SUFDdkIsQ0FBQztJQUVELG1CQUFtQixDQUFDLE1BQWtDLEVBQUUsR0FBVztRQUNqRSxJQUFJLEtBQUssR0FBRyxNQUFNLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ3BDLElBQUksS0FBSyxZQUFZLFVBQVUsRUFBRSxDQUFDO1lBQ2hDLEtBQUssR0FBRyxLQUFLLGlCQUFpQixDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7UUFDMUMsQ0FBQztRQUNELE9BQU8sS0FBSyxDQUFDO0lBQ2YsQ0FBQztJQUVELFFBQVEsQ0FBQyxNQUFrQztRQUN6QyxPQUFPLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDO0lBQzlCLENBQUM7SUFFRCxVQUFVLENBQUMsTUFBa0M7UUFDM0MsT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQztJQUM3QixDQUFDO0lBRUQsWUFBWSxDQUFDLFVBQThEO1FBQ3pFLElBQUksQ0FBQyxDQUFDLFVBQVUsSUFBSSxVQUFVLENBQUMsRUFBRSxDQUFDO1lBQ2hDLE9BQU8sS0FBSyxDQUFDO1FBQ2YsQ0FBQztRQUNELE9BQU8sVUFBVSxDQUFDLFFBQVEsSUFBSSxVQUFVLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQztJQUMzRCxDQUFDO0lBRUQsVUFBVSxDQUFDLFVBQWlDO1FBQzFDLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQ3BDLENBQUM7SUFFTyxxQkFBcUIsQ0FDM0IsQ0FBa0Q7UUFFbEQsSUFBSSxDQUFDLFdBQVcsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRTtZQUN4RCxPQUFPO2dCQUNMLEdBQUcsRUFBRSxHQUFHO2dCQUNSLEtBQUssRUFBRSxHQUFHO2FBQ1gsQ0FBQztRQUNKLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQzsySEEvRVUsd0JBQXdCOytHQUF4Qix3QkFBd0IsZ1BDZnJDLG81RUE4Q0E7OzRGRC9CYSx3QkFBd0I7a0JBTHBDLFNBQVM7K0JBQ0UsbUJBQW1CO3NGQU9wQixXQUFXO3NCQUFuQixLQUFLO2dCQUVHLElBQUk7c0JBQVosS0FBSztnQkFFRyxJQUFJO3NCQUFaLEtBQUs7Z0JBRUksV0FBVztzQkFBcEIsTUFBTTtnQkFJTSxVQUFVO3NCQUF0QixLQUFLO2dCQWlCTyxPQUFPO3NCQUFuQixLQUFLO2dCQU9JLFdBQVc7c0JBQXBCLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBDaGFuZ2VEZXRlY3RvclJlZixcbiAgQ29tcG9uZW50LFxuICBFdmVudEVtaXR0ZXIsXG4gIElucHV0LFxuICBPdXRwdXQsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgYnVmZmVyVG9IZXhTdHJpbmcgfSBmcm9tICdAaW90aXplL2NvbW1vbi9ieXRlLWNvbnZlcnRlcic7XG5pbXBvcnQgeyBJb25pY0RhdGFMb2dnZXIsIFN5bmNhYmxlRGF0YWxvZ1BhY2tldCB9IGZyb20gJ0Bpb3RpemUvaW9uaWMnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICd0YXAtZGF0YWxvZy10YWJsZScsXG4gIHRlbXBsYXRlVXJsOiAnLi90YXAtZGF0YWxvZy10YWJsZS5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL3RhcC1kYXRhbG9nLXRhYmxlLmNvbXBvbmVudC5zY3NzJ10sXG59KVxuZXhwb3J0IGNsYXNzIFRhcERhdGFsb2dUYWJsZUNvbXBvbmVudCB7XG4gIF9wYWNrZXRzPzogSW9uaWNEYXRhTG9nZ2VyLlBhY2tldEluZm9bXTtcblxuICBASW5wdXQoKSBkYXRhQ29sdW1uczogeyBrZXk6IHN0cmluZzsgdGl0bGU6IHN0cmluZyB9W10gPSBbXTtcblxuICBASW5wdXQoKSBkYXRlID0gdHJ1ZTtcblxuICBASW5wdXQoKSBzeW5jID0gdHJ1ZTtcblxuICBAT3V0cHV0KCkgb25TeW5jRXZlbnQgPSBuZXcgRXZlbnRFbWl0dGVyPFN5bmNhYmxlRGF0YWxvZ1BhY2tldD4oKTtcblxuICBjb25zdHJ1Y3Rvcihwcm90ZWN0ZWQgY2hhbmdlUmVmRGV0ZWN0b3I6IENoYW5nZURldGVjdG9yUmVmKSB7fVxuXG4gIEBJbnB1dCgpIHNldCBkYXRhTG9nZ2VyKGRhdGFMb2dnZXI6IElvbmljRGF0YUxvZ2dlciB8IHVuZGVmaW5lZCkge1xuICAgIGlmIChkYXRhTG9nZ2VyKSB7XG4gICAgICBkYXRhTG9nZ2VyLnN0cmVhbS5zdWJzY3JpYmUoXG4gICAgICAgIChwOiBJb25pY0RhdGFMb2dnZXIuUGFja2V0SW5mbzxSZWNvcmQ8c3RyaW5nLCBhbnk+PikgPT4ge1xuICAgICAgICAgIGlmICh0aGlzLmRhdGFDb2x1bW5zLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgdGhpcy5pbml0Q29sdW1uc0Zyb21QYWNrZXQocCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICghdGhpcy5fcGFja2V0cykge1xuICAgICAgICAgICAgdGhpcy5fcGFja2V0cyA9IFtdO1xuICAgICAgICAgIH1cbiAgICAgICAgICB0aGlzLl9wYWNrZXRzLnB1c2gocCk7XG4gICAgICAgICAgdGhpcy5jaGFuZ2VSZWZEZXRlY3Rvci5kZXRlY3RDaGFuZ2VzKCk7XG4gICAgICAgIH1cbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgQElucHV0KCkgc2V0IHBhY2tldHMocGFja2V0czogSW9uaWNEYXRhTG9nZ2VyLlBhY2tldEluZm9bXSB8IHVuZGVmaW5lZCkge1xuICAgIHRoaXMuX3BhY2tldHMgPSBwYWNrZXRzO1xuICAgIGlmIChwYWNrZXRzICYmIHRoaXMuZGF0YUNvbHVtbnMubGVuZ3RoID09PSAwICYmIHBhY2tldHMubGVuZ3RoID4gMCkge1xuICAgICAgdGhpcy5pbml0Q29sdW1uc0Zyb21QYWNrZXQocGFja2V0c1swXSk7XG4gICAgfVxuICB9XG5cbiAgQE91dHB1dCgpIG9uUmV0cnlTeW5jID0gbmV3IEV2ZW50RW1pdHRlcjxTeW5jYWJsZURhdGFsb2dQYWNrZXQ+KCk7XG5cbiAgZ2V0IHBhY2tldHMoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3BhY2tldHM7XG4gIH1cblxuICBwYWNrZXRWYXJpYWJsZVZhbHVlKHBhY2tldDogSW9uaWNEYXRhTG9nZ2VyLlBhY2tldEluZm8sIGtleTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBsZXQgdmFsdWUgPSBwYWNrZXQuZGVjb2RlZERhdGFba2V5XTtcbiAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBVaW50OEFycmF5KSB7XG4gICAgICB2YWx1ZSA9IGAweCR7YnVmZmVyVG9IZXhTdHJpbmcodmFsdWUpfWA7XG4gICAgfVxuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHBhY2tldElkKHBhY2tldDogSW9uaWNEYXRhTG9nZ2VyLlBhY2tldEluZm8pOiBudW1iZXIge1xuICAgIHJldHVybiBwYWNrZXQubWV0YS5wYWNrZXRJZDtcbiAgfVxuXG4gIHBhY2tldERhdGUocGFja2V0OiBJb25pY0RhdGFMb2dnZXIuUGFja2V0SW5mbyk6IERhdGUge1xuICAgIHJldHVybiBwYWNrZXQubWV0YS5sb2dUaW1lO1xuICB9XG5cbiAgaXNQYWNrZXRTeW5jKHBhY2tldEluZm86IFN5bmNhYmxlRGF0YWxvZ1BhY2tldCB8IElvbmljRGF0YUxvZ2dlci5QYWNrZXRJbmZvKSB7XG4gICAgaWYgKCEoJ3N5bmNJbmZvJyBpbiBwYWNrZXRJbmZvKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gcGFja2V0SW5mby5zeW5jSW5mbyAmJiBwYWNrZXRJbmZvLnN5bmNJbmZvLmlzU3luYztcbiAgfVxuXG4gIHN5bmNQYWNrZXQocGFja2V0SW5mbzogU3luY2FibGVEYXRhbG9nUGFja2V0KSB7XG4gICAgdGhpcy5vblJldHJ5U3luYy5lbWl0KHBhY2tldEluZm8pO1xuICB9XG5cbiAgcHJpdmF0ZSBpbml0Q29sdW1uc0Zyb21QYWNrZXQoXG4gICAgcDogSW9uaWNEYXRhTG9nZ2VyLlBhY2tldEluZm88UmVjb3JkPHN0cmluZywgYW55Pj5cbiAgKSB7XG4gICAgdGhpcy5kYXRhQ29sdW1ucyA9IE9iamVjdC5rZXlzKHAuZGVjb2RlZERhdGEpLm1hcCgoa2V5KSA9PiB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBrZXk6IGtleSxcbiAgICAgICAgdGl0bGU6IGtleSxcbiAgICAgIH07XG4gICAgfSk7XG4gIH1cbn1cbiIsIjx0YWJsZSAqbmdJZj1cImRhdGFDb2x1bW5zXCIgY2xhc3M9XCJ0YWJsZVwiIG1hdC10YWJsZT5cbiAgPHRoZWFkPlxuICAgIDx0aCAqbmdJZj1cImRhdGVcIj48aW9uLWljb24gbmFtZT1cInRpbWVcIj48L2lvbi1pY29uPiBEYXRlPC90aD5cbiAgICA8dGg+PGlvbi1pY29uIG5hbWU9XCJkb2N1bWVudFwiPjwvaW9uLWljb24+IElEPC90aD5cbiAgICA8dGggKm5nRm9yPVwibGV0IGRhdGFDb2x1bW4gb2YgZGF0YUNvbHVtbnNcIj5cbiAgICAgIDxpb24taWNvbiBuYW1lPVwiYW5hbHl0aWNzXCI+PC9pb24taWNvbj4ge3sgZGF0YUNvbHVtbi50aXRsZSB9fVxuICAgIDwvdGg+XG4gICAgPHRoICpuZ0lmPVwic3luY1wiPjxpb24taWNvbiBuYW1lPVwiY2xvdWRcIj48L2lvbi1pY29uPiBDbG91ZCBzeW5jPC90aD5cbiAgPC90aGVhZD5cbiAgPHRib2R5PlxuICAgIDx0ciAqbmdGb3I9XCJsZXQgcGFja2V0IG9mIHBhY2tldHNcIj5cbiAgICAgIDx0ZCAqbmdJZj1cImRhdGVcIj5cbiAgICAgICAge3sgcGFja2V0RGF0ZShwYWNrZXQpIHwgZGF0ZTogJ3Nob3J0JyB9fVxuICAgICAgPC90ZD5cbiAgICAgIDx0ZD5cbiAgICAgICAge3sgcGFja2V0SWQocGFja2V0KSB9fVxuICAgICAgPC90ZD5cbiAgICAgIDx0ZCAqbmdGb3I9XCJsZXQgaW5mbyBvZiBkYXRhQ29sdW1uc1wiPlxuICAgICAgICB7eyBwYWNrZXRWYXJpYWJsZVZhbHVlKHBhY2tldCwgaW5mby5rZXkpIH19XG4gICAgICA8L3RkPlxuICAgICAgPHRkICpuZ0lmPVwic3luY1wiPlxuICAgICAgICA8aW9uLXRleHQgKm5nSWY9XCJpc1BhY2tldFN5bmMocGFja2V0KVwiIGNvbG9yPVwic3VjY2Vzc1wiPlxuICAgICAgICAgIDxpb24taWNvbiBbbmFtZV09XCInY2hlY2ttYXJrJ1wiPjwvaW9uLWljb24+ICZuYnNwOyBTeW5jXG4gICAgICAgIDwvaW9uLXRleHQ+XG4gICAgICAgIDxpb24tdGV4dCAqbmdJZj1cIiFpc1BhY2tldFN5bmMocGFja2V0KVwiIGNvbG9yPVwiZGFuZ2VyXCI+XG4gICAgICAgICAgPGlvbi1pY29uIFtuYW1lXT1cIidhbGVydCdcIj48L2lvbi1pY29uPiAmbmJzcDsgTm90IHN5bmMgJm5ic3A7XG4gICAgICAgICAgPGEgKGNsaWNrKT1cInN5bmNQYWNrZXQocGFja2V0KVwiPiByZXRyeSA8L2E+XG4gICAgICAgIDwvaW9uLXRleHQ+XG4gICAgICAgIDwhLS0gIDxpb24tYnV0dG9ucyBzbG90PVwiZW5kXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW9uLWJ1dHRvbiAoY2xpY2spPVwic3luY1BhY2tldChwYWNrZXQpXCIgW2NvbG9yXT1cImlzUGFja2V0U3luYyhwYWNrZXQpID8gJ3N1Y2Nlc3MnOiAnJ1wiIFtkaXNhYmxlZF09XCJpc1BhY2tldFN5bmMocGFja2V0KVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpb24taWNvbiBbbmFtZV09XCJpc1BhY2tldFN5bmMocGFja2V0KSA/ICdjaGVja21hcmsnIDogJ3N5bmMnXCI+PC9pb24taWNvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBTeW5jXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2lvbi1idXR0b24+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW9uLWJ1dHRvbiAoY2xpY2spPVwiZGVjb2RlUGFja2V0KHN5bmNJbmZvKVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPGlvbi1pY29uIG5hbWU9XCJzeW5jXCI+PC9pb24taWNvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgIERlY29kZVxuICAgICAgICAgICAgICAgICAgICA8L2lvbi1idXR0b24+IFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlvbi1idXR0b24gKGNsaWNrKT1cImRldGFpbChzeW5jSW5mbylcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW9uLWljb24gbmFtZT1cIm1vcmVcIj48L2lvbi1pY29uPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIERldGFpbFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvaW9uLWJ1dHRvbj4gXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvaW9uLWJ1dHRvbnM+LS0+XG4gICAgICA8L3RkPlxuICAgIDwvdHI+XG4gIDwvdGJvZHk+XG48L3RhYmxlPlxuIl19