+
Please restart Homebridge for the changes to apply.
diff --git a/ui/src/app/core/manage-plugins/custom-plugins/custom-plugins.component.ts b/ui/src/app/core/manage-plugins/custom-plugins/custom-plugins.component.ts
index 65a21d3a1..5a1337f3d 100644
--- a/ui/src/app/core/manage-plugins/custom-plugins/custom-plugins.component.ts
+++ b/ui/src/app/core/manage-plugins/custom-plugins/custom-plugins.component.ts
@@ -52,9 +52,9 @@ export class CustomPluginsComponent implements OnInit, OnDestroy {
public schemaFormUpdatedSubject = new Subject();
// other forms
- public formId;
- public formSchema;
- public formData;
+ public formId: string;
+ public formSchema: any;
+ public formData: any;
public formSubmitButtonLabel: string;
public formCancelButtonLabel: string;
public formValid = true;
diff --git a/ui/src/app/core/manage-plugins/settings-plugins-modal/settings-plugins-modal.component.html b/ui/src/app/core/manage-plugins/settings-plugins-modal/settings-plugins-modal.component.html
index f08093aa6..1d3c273ff 100644
--- a/ui/src/app/core/manage-plugins/settings-plugins-modal/settings-plugins-modal.component.html
+++ b/ui/src/app/core/manage-plugins/settings-plugins-modal/settings-plugins-modal.component.html
@@ -8,7 +8,7 @@
×
+
@@ -54,7 +54,27 @@
{{ block.name }}
*ngIf="schema.footerDisplay">
-
diff --git a/ui/src/app/core/manage-plugins/settings-plugins-modal/settings-plugins-modal.component.ts b/ui/src/app/core/manage-plugins/settings-plugins-modal/settings-plugins-modal.component.ts
index 182710103..b9decf77a 100644
--- a/ui/src/app/core/manage-plugins/settings-plugins-modal/settings-plugins-modal.component.ts
+++ b/ui/src/app/core/manage-plugins/settings-plugins-modal/settings-plugins-modal.component.ts
@@ -1,4 +1,5 @@
import { Component, Input, OnInit } from '@angular/core';
+import { Router } from '@angular/router';
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
import { TranslateService } from '@ngx-translate/core';
import { ToastrService } from 'ngx-toastr';
@@ -29,12 +30,16 @@ export class SettingsPluginsModalComponent implements OnInit {
public form: any = {};
public show = '';
public saveInProgress: boolean;
+ public justSavedAndExited = false;
+
+ public childBridges: any[] = [];
constructor(
public activeModal: NgbActiveModal,
private $api: ApiService,
private $settings: SettingsService,
private $notification: NotificationService,
+ private $router: Router,
private $toastr: ToastrService,
private translate: TranslateService,
) { }
@@ -84,17 +89,20 @@ export class SettingsPluginsModalComponent implements OnInit {
try {
await this.$api.post(`/config-editor/plugin/${encodeURIComponent(this.plugin.name)}`, configBlocks)
.toPromise();
- this.$toastr.success(
- this.translate.instant('plugins.settings.toast_restart_required'),
- this.translate.instant('plugins.settings.toast_plugin_config_saved'));
-
- this.activeModal.close(configBlocks.length ? this.schema : null);
- this.$notification.configUpdated.next(undefined);
+ // this.$toastr.success(
+ // this.translate.instant('plugins.settings.toast_restart_required'),
+ // this.translate.instant('plugins.settings.toast_plugin_config_saved'));
+ //
+ // this.activeModal.close(configBlocks.length ? this.schema : null);
+ // this.$notification.configUpdated.next(undefined);
// reload app settings if the config was changed for Homebridge UI
if (this.plugin.name === 'homebridge-config-ui-x') {
this.$settings.getAppSettings().catch();
}
+
+ this.getChildBridges();
+ this.justSavedAndExited = true;
} catch (err) {
this.$toastr.error(
this.translate.instant('config.toast_failed_to_save_config') + ': ' + err.error?.message,
@@ -131,6 +139,47 @@ export class SettingsPluginsModalComponent implements OnInit {
this.pluginConfig.splice(pluginConfigIndex, 1);
}
+ getChildBridges(): any[] {
+ try {
+ this.$api.get('/status/homebridge/child-bridges').subscribe((data: any[]) => {
+ data.forEach((bridge) => {
+ if (this.plugin.name === bridge.plugin) {
+ this.childBridges.push(bridge);
+ }
+ });
+ });
+ return this.childBridges;
+ } catch (err) {
+ this.$toastr.error(err.message, this.translate.instant('toast.title_error'));
+ return [];
+ }
+ }
+
+ public onRestartHomebridgeClick() {
+ this.$router.navigate(['/restart']);
+ this.activeModal.close();
+ }
+
+ public async onRestartChildBridgeClick() {
+ try {
+ for (const bridge of this.childBridges) {
+ await this.$api.put(`/server/restart/${bridge.username}`, {}).toPromise();
+ }
+ this.$toastr.success(
+ this.translate.instant('plugins.manage.child_bridge_restart_success'),
+ this.translate.instant('toast.title_success'),
+ );
+ } catch (err) {
+ this.$notification.configUpdated.next(undefined); // highlight the restart icon in the navbar
+ this.$toastr.error(
+ this.translate.instant('plugins.manage.child_bridge_restart_failed'),
+ this.translate.instant('toast.title_error'),
+ );
+ } finally {
+ this.activeModal.close();
+ }
+ }
+
/**
* Homebridge Hue - ensure users object is preserved
*/
diff --git a/ui/src/app/core/mobile-detect.service.ts b/ui/src/app/core/mobile-detect.service.ts
index fcfae9299..49f281098 100644
--- a/ui/src/app/core/mobile-detect.service.ts
+++ b/ui/src/app/core/mobile-detect.service.ts
@@ -9,7 +9,7 @@ const preventDefault = (e) => {
providedIn: 'root',
})
export class MobileDetectService {
- public detect;
+ public detect: MobileDetect;
public isTouchMoveLocked = false;
constructor() {
diff --git a/ui/src/app/core/settings.service.ts b/ui/src/app/core/settings.service.ts
index e2c446d4d..43ff55608 100644
--- a/ui/src/app/core/settings.service.ts
+++ b/ui/src/app/core/settings.service.ts
@@ -33,13 +33,6 @@ interface EnvInterface {
recommendChildBridges: boolean;
}
-interface AppSettingsInterface {
- env: EnvInterface;
- formAuth: boolean;
- theme: string;
- serverTimestamp: string;
-}
-
@Injectable({
providedIn: 'root',
})
@@ -67,19 +60,17 @@ export class SettingsService {
this.getAppSettings();
}
- getAppSettings() {
- return this.$api.get('/auth/settings').toPromise()
- .then((data: AppSettingsInterface) => {
- this.formAuth = data.formAuth;
- this.env = data.env;
- this.setTheme(data.theme || 'auto');
- this.setTitle(this.env.homebridgeInstanceName);
- this.checkServerTime(data.serverTimestamp);
- this.setUiVersion(data.env.packageVersion);
- this.setLang(this.env.lang);
- this.settingsLoaded = true;
- this.settingsLoadedSubject.next(undefined);
- });
+ async getAppSettings() {
+ const data = await this.$api.get('/auth/settings').toPromise();
+ this.formAuth = data.formAuth;
+ this.env = data.env;
+ this.setTheme(data.theme || 'auto');
+ this.setTitle(this.env.homebridgeInstanceName);
+ this.checkServerTime(data.serverTimestamp);
+ this.setUiVersion(data.env.packageVersion);
+ this.setLang(this.env.lang);
+ this.settingsLoaded = true;
+ this.settingsLoadedSubject.next(undefined);
}
setTheme(theme: string) {
@@ -112,7 +103,7 @@ export class SettingsService {
this.$title.setTitle(title || 'Homebridge');
}
- setUiVersion(version) {
+ setUiVersion(version: string) {
if (!this.uiVersion) {
this.uiVersion = version;
}
diff --git a/ui/src/app/core/terminal.service.ts b/ui/src/app/core/terminal.service.ts
index 0c4fd7c69..808a8c5d9 100644
--- a/ui/src/app/core/terminal.service.ts
+++ b/ui/src/app/core/terminal.service.ts
@@ -1,5 +1,5 @@
import { ElementRef, Injectable } from '@angular/core';
-import { Subject, Subscription } from 'rxjs';
+import { Subject } from 'rxjs';
import { debounceTime } from 'rxjs/operators';
import { ITerminalOptions, Terminal } from 'xterm';
import { FitAddon } from 'xterm-addon-fit';
@@ -79,7 +79,7 @@ export class TerminalService {
});
// subscribe to incoming data events from server to client
- this.io.socket.on('stdout', data => {
+ this.io.socket.on('stdout', (data: string) => {
this.term.write(data);
});
diff --git a/ui/src/app/core/ws.service.ts b/ui/src/app/core/ws.service.ts
index c0d260727..f637f7084 100644
--- a/ui/src/app/core/ws.service.ts
+++ b/ui/src/app/core/ws.service.ts
@@ -33,7 +33,7 @@ export class WsService {
const io: IoNamespace = this.namespaceConnectionCache[namespace];
io.connected = new Subject();
- // broadcast to sbuscribers that the connection is ready
+ // broadcast to subscribers that the connection is ready
setTimeout(() => {
if (io.socket.connected) {
io.connected.next(undefined);
@@ -58,7 +58,7 @@ export class WsService {
const io = this.establishConnectionToNamespace(namespace);
io.connected = new Subject();
- // wait for the connection and broadcase when ready
+ // wait for the connection and broadcast when ready
io.socket.on('connect', () => {
io.connected.next(undefined);
});
@@ -92,8 +92,8 @@ export class WsService {
},
});
- const request = (resource, payload): Observable
=> new Observable((observer) => {
- socket.emit(resource, payload, (resp) => {
+ const request = (resource: string, payload: any): Observable => new Observable((observer) => {
+ socket.emit(resource, payload, (resp: any) => {
if (typeof resp === 'object' && resp.error) {
observer.error(resp);
} else {