diff --git a/package-lock.json b/package-lock.json
index a3e200a60..6eebd0b27 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -3896,9 +3896,9 @@
}
},
"node_modules/caniuse-lite": {
- "version": "1.0.30001566",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001566.tgz",
- "integrity": "sha512-ggIhCsTxmITBAMmK8yZjEhCO5/47jKXPu6Dha/wuCS4JePVL+3uiDEBuhu2aIoT+bqTOR8L76Ip1ARL9xYsEJA==",
+ "version": "1.0.30001568",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001568.tgz",
+ "integrity": "sha512-vSUkH84HontZJ88MiNrOau1EBrCqEQYgkC5gIySiDlpsm8sGVrhU7Kx4V6h0tnqaHzIHZv08HlJIwPbL4XL9+A==",
"dev": true,
"funding": [
{
diff --git a/ui/package-lock.json b/ui/package-lock.json
index 9a773ba2a..d8cf493e1 100644
--- a/ui/package-lock.json
+++ b/ui/package-lock.json
@@ -5421,9 +5421,9 @@
}
},
"node_modules/caniuse-lite": {
- "version": "1.0.30001566",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001566.tgz",
- "integrity": "sha512-ggIhCsTxmITBAMmK8yZjEhCO5/47jKXPu6Dha/wuCS4JePVL+3uiDEBuhu2aIoT+bqTOR8L76Ip1ARL9xYsEJA==",
+ "version": "1.0.30001568",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001568.tgz",
+ "integrity": "sha512-vSUkH84HontZJ88MiNrOau1EBrCqEQYgkC5gIySiDlpsm8sGVrhU7Kx4V6h0tnqaHzIHZv08HlJIwPbL4XL9+A==",
"funding": [
{
"type": "opencollective",
diff --git a/ui/src/app/core/manage-plugins/plugin-log-modal/plugin-log-modal.component.html b/ui/src/app/core/manage-plugins/plugin-log-modal/plugin-log-modal.component.html
index 7f4d501f8..5592d1af4 100644
--- a/ui/src/app/core/manage-plugins/plugin-log-modal/plugin-log-modal.component.html
+++ b/ui/src/app/core/manage-plugins/plugin-log-modal/plugin-log-modal.component.html
@@ -10,12 +10,16 @@
Logs: {{ plugin.displayName || plugin.name }}
diff --git a/ui/src/app/core/manage-plugins/plugin-log-modal/plugin-log-modal.component.ts b/ui/src/app/core/manage-plugins/plugin-log-modal/plugin-log-modal.component.ts
index bc05173f9..380bbf75c 100644
--- a/ui/src/app/core/manage-plugins/plugin-log-modal/plugin-log-modal.component.ts
+++ b/ui/src/app/core/manage-plugins/plugin-log-modal/plugin-log-modal.component.ts
@@ -1,3 +1,4 @@
+import { HttpErrorResponse, HttpResponse } from '@angular/common/http';
import {
Component,
ElementRef,
@@ -7,11 +8,13 @@ import {
OnInit,
ViewChild,
} from '@angular/core';
-import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
+import { NgbActiveModal, NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { TranslateService } from '@ngx-translate/core';
+import { saveAs } from 'file-saver';
import { ToastrService } from 'ngx-toastr';
import { Subject } from 'rxjs';
import { ApiService } from '@/app/core/api.service';
+import { ConfirmComponent } from '@/app/core/components/confirm/confirm.component';
import { LogService } from '@/app/core/log.service';
@Component({
@@ -28,6 +31,7 @@ export class PluginLogModalComponent implements OnInit, OnDestroy {
public activeModal: NgbActiveModal,
private $api: ApiService,
private $log: LogService,
+ private $modal: NgbModal,
private $toastr: ToastrService,
private $translate: TranslateService,
) { }
@@ -43,7 +47,6 @@ export class PluginLogModalComponent implements OnInit, OnDestroy {
getPluginLog() {
// Get the plugin name as configured in the config file
- console.log(this.plugin);
this.$api.get(`/config-editor/plugin/${encodeURIComponent(this.plugin.name)}`).subscribe(
(result) => {
const logAlias = this.plugin.name === 'homebridge-config-ui-x' ? 'Homebridge UI' : (result[0]?.name || this.plugin.name);
@@ -56,6 +59,57 @@ export class PluginLogModalComponent implements OnInit, OnDestroy {
);
}
+ downloadLogFile() {
+ const ref = this.$modal.open(ConfirmComponent);
+ ref.componentInstance.title = this.$translate.instant('logs.title_download_log_file');
+ ref.componentInstance.message = this.$translate.instant('logs.message_download_warning');
+ ref.componentInstance.confirmButtonLabel = this.$translate.instant('logs.label_download');
+ ref.componentInstance.faIconClass = 'fas fa-fw fa-user-secret primary-text';
+
+ ref.result.then(() => {
+ this.$api.get('/platform-tools/hb-service/log/download?colour=yes', { observe: 'response', responseType: 'text' })
+ .subscribe(
+ (res: HttpResponse) => {
+ if (!res.body) {
+ return;
+ }
+ const lines = res.body.split('\n');
+ let finalOutput = '';
+ let includeNextLine = false;
+
+ lines.forEach((line: string) => {
+ if (includeNextLine) {
+ if (line.match(/36m\[.*?]/)) {
+ includeNextLine = false;
+ } else {
+ finalOutput += line + '\r\n';
+ return;
+ }
+ }
+
+ if (line.includes(`36m[${this.plugin.name}]`)) {
+ finalOutput += line + '\r\n';
+ includeNextLine = true;
+ }
+ });
+
+ saveAs(new Blob([finalOutput], { type: 'text/plain;charset=utf-8' }), `${this.plugin.name}.log.txt`);
+ },
+ async (err: HttpErrorResponse) => {
+ let message: string;
+ try {
+ message = JSON.parse(await err.error.text()).message;
+ } catch (e) {
+ // do nothing
+ }
+ this.$toastr.error(message || 'Failed to download log file', this.$translate.instant('toast.title_error'));
+ },
+ );
+ }).catch(() => {
+ // do nothing
+ });
+ }
+
ngOnDestroy() {
this.$log.destroyTerminal();
}
diff --git a/ui/src/app/modules/status/widgets/homebridge-status-widget/homebridge-status-widget.component.html b/ui/src/app/modules/status/widgets/homebridge-status-widget/homebridge-status-widget.component.html
index c30d3571e..f4280db68 100644
--- a/ui/src/app/modules/status/widgets/homebridge-status-widget/homebridge-status-widget.component.html
+++ b/ui/src/app/modules/status/widgets/homebridge-status-widget/homebridge-status-widget.component.html
@@ -1,7 +1,7 @@