Skip to content

Commit 9a33fdd

Browse files
committed
UI: Add General Settings form.
1 parent b26b2f9 commit 9a33fdd

File tree

5 files changed

+194
-102
lines changed

5 files changed

+194
-102
lines changed

ui-ngx/src/app/modules/home/pages/settings/general-settings.component.html

Lines changed: 83 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -23,44 +23,32 @@
2323
</mat-card-header>
2424
<mat-card-content>
2525
<form [formGroup]="generalSettingsForm" (ngSubmit)="saveGeneralSettings()" class="tb-form-panel no-border no-padding">
26-
<fieldset class="fields-group">
27-
<legend class="group-title" translate>ws-client.ws-client</legend>
28-
<div class="container">
29-
<section class="flex flex-row items-center gap-2">
30-
<mat-slide-toggle formControlName="isLoggingEnabled">
31-
{{ 'ws-client.show-logs' | translate }}
32-
</mat-slide-toggle>
33-
<mat-icon class="tb-mat-20" style="color: rgba(0,0,0,0.18)"
34-
[matTooltip]="'ws-client.show-logs-hint' | translate"
35-
matTooltipPosition="right">
36-
info
37-
</mat-icon>
38-
</section>
39-
<section class="flex flex-row items-center gap-2">
40-
<mat-form-field class="flex flex-1">
41-
<mat-label translate>ws-client.messages.max-messages</mat-label>
42-
<input matInput type="number" min="1" formControlName="maxMessages" placeholder="1000"/>
43-
<mat-icon matSuffix [matTooltip]="'ws-client.messages.max-messages-hint' | translate">
44-
info
45-
</mat-icon>
46-
<mat-icon matSuffix
47-
matTooltipClass="tb-error-tooltip"
48-
matTooltip="{{ 'ws-client.messages.max-messages-required' | translate }}"
49-
[class.!hidden]="!(generalSettingsForm.get('maxMessages').hasError('required') && generalSettingsForm.get('maxMessages').touched)"
50-
class="tb-error">
51-
warning
52-
</mat-icon>
53-
<mat-icon matSuffix
54-
matTooltipClass="tb-error-tooltip"
55-
matTooltip="{{ 'ws-client.messages.max-messages-min' | translate }}"
56-
[class.!hidden]="!(generalSettingsForm.get('maxMessages').hasError('min') && generalSettingsForm.get('maxMessages').touched)"
57-
class="tb-error">
58-
warning
59-
</mat-icon>
60-
</mat-form-field>
61-
</section>
62-
</div>
63-
</fieldset>
26+
<div class="container">
27+
<mat-form-field class="flex flex-1" subscriptSizing="dynamic">
28+
<mat-label translate>admin.settings.base-url</mat-label>
29+
<input matInput formControlName="baseUrl"/>
30+
<mat-icon matSuffix [matTooltip]="'admin.settings.base-url-hint' | translate">
31+
info
32+
</mat-icon>
33+
<mat-icon matSuffix
34+
matTooltipClass="tb-error-tooltip"
35+
matTooltip="{{ 'admin.settings.base-url-required' | translate }}"
36+
[class.!hidden]="!(generalSettingsForm.get('baseUrl').hasError('required') && generalSettingsForm.get('baseUrl').touched)"
37+
class="tb-error">
38+
warning
39+
</mat-icon>
40+
</mat-form-field>
41+
<section class="flex flex-row items-center gap-2">
42+
<mat-slide-toggle formControlName="prohibitDifferentUrl">
43+
{{ 'admin.settings.prohibit-different-url' | translate }}
44+
</mat-slide-toggle>
45+
<mat-icon class="tb-mat-20" style="color: rgba(0,0,0,0.18)"
46+
[matTooltip]="'admin.settings.prohibit-different-url-hint' | translate"
47+
matTooltipPosition="right">
48+
info
49+
</mat-icon>
50+
</section>
51+
</div>
6452
<div class="layout-wrap flex flex-row items-center justify-end gap-2">
6553
<button mat-button color="primary"
6654
[disabled]="generalSettingsForm.pristine"
@@ -74,13 +62,69 @@
7462
</form>
7563
</mat-card-content>
7664
</mat-card>
65+
66+
<mat-card appearance="outlined" class="settings-card">
67+
<mat-card-header>
68+
<mat-card-title>
69+
<span class="mat-headline-5" translate>ws-client.ws-client-settings</span>
70+
</mat-card-title>
71+
</mat-card-header>
72+
<mat-card-content>
73+
<form [formGroup]="webSocketSettingsForm" (ngSubmit)="saveWebSocketSettings()" class="tb-form-panel no-border no-padding">
74+
<div class="container">
75+
<mat-form-field class="flex flex-1" subscriptSizing="dynamic">
76+
<mat-label translate>ws-client.messages.max-messages</mat-label>
77+
<input matInput type="number" min="1" formControlName="maxMessages" placeholder="1000"/>
78+
<mat-icon matSuffix [matTooltip]="'ws-client.messages.max-messages-hint' | translate">
79+
info
80+
</mat-icon>
81+
<mat-icon matSuffix
82+
matTooltipClass="tb-error-tooltip"
83+
matTooltip="{{ 'ws-client.messages.max-messages-required' | translate }}"
84+
[class.!hidden]="!(webSocketSettingsForm.get('maxMessages').hasError('required') && webSocketSettingsForm.get('maxMessages').touched)"
85+
class="tb-error">
86+
warning
87+
</mat-icon>
88+
<mat-icon matSuffix
89+
matTooltipClass="tb-error-tooltip"
90+
matTooltip="{{ 'ws-client.messages.max-messages-min' | translate }}"
91+
[class.!hidden]="!(webSocketSettingsForm.get('maxMessages').hasError('min') && webSocketSettingsForm.get('maxMessages').touched)"
92+
class="tb-error">
93+
warning
94+
</mat-icon>
95+
</mat-form-field>
96+
<section class="flex flex-row items-center gap-2">
97+
<mat-slide-toggle formControlName="isLoggingEnabled">
98+
{{ 'ws-client.show-logs' | translate }}
99+
</mat-slide-toggle>
100+
<mat-icon class="tb-mat-20" style="color: rgba(0,0,0,0.18)"
101+
[matTooltip]="'ws-client.show-logs-hint' | translate"
102+
matTooltipPosition="right">
103+
info
104+
</mat-icon>
105+
</section>
106+
</div>
107+
<div class="layout-wrap flex flex-row items-center justify-end gap-2">
108+
<button mat-button color="primary"
109+
[disabled]="webSocketSettingsForm.pristine"
110+
(click)="discardWebSocketSettings()"
111+
type="button">{{'action.undo' | translate}}
112+
</button>
113+
<button mat-button mat-raised-button color="primary" [disabled]="(isLoading$ | async) || webSocketSettingsForm.invalid || !webSocketSettingsForm.dirty"
114+
type="submit">{{'action.save' | translate}}
115+
</button>
116+
</div>
117+
</form>
118+
</mat-card-content>
119+
</mat-card>
120+
77121
<mat-card appearance="outlined" class="settings-card">
78122
<mat-card-header>
79123
<mat-card-title>
80124
<span class="mat-headline-5" translate>admin.settings.connectivity-settings</span>
81125
</mat-card-title>
82126
<span class="flex flex-1"></span>
83-
<mat-icon class="material-icons" style="color: rgba(0,0,0,0.18)"
127+
<mat-icon class="material-icons" style="color: rgba(0,0,0,0.54)"
84128
[matTooltip]="'admin.settings.connectivity-settings-hint' | translate">info
85129
</mat-icon>
86130
</mat-card-header>

ui-ngx/src/app/modules/home/pages/settings/general-settings.component.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
display: flex;
4141
flex-direction: column;
4242
gap: 16px;
43-
padding-top: 8px;
43+
padding: 8px 0 8px;
4444
}
4545

4646
.fields-group {

ui-ngx/src/app/modules/home/pages/settings/general-settings.component.ts

Lines changed: 97 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,12 @@ import {
2525
ConnectivityProtocol,
2626
ConnectivitySettings,
2727
connectivitySettingsKey,
28+
generalSettingsKey,
29+
GeneralSettings,
2830
WebSocketSettings,
29-
webSocketSettingsKey
3031
} from '@shared/models/settings.models';
3132
import { SettingsService } from '@core/http/settings.service';
3233
import { takeUntil } from 'rxjs/operators';
33-
import { isUndefined } from '@core/utils';
3434
import { MqttJsClientService } from '@core/http/mqtt-js-client.service';
3535
import { MatCard, MatCardHeader, MatCardTitle, MatCardContent } from '@angular/material/card';
3636
import { TranslateModule } from '@ngx-translate/core';
@@ -54,21 +54,24 @@ import { HasConfirmForm } from '@core/guards/confirm-on-exit.guard';
5454
export class GeneralSettingsComponent extends PageComponent implements OnDestroy, HasConfirmForm {
5555

5656
generalSettingsForm: UntypedFormGroup;
57+
webSocketSettingsForm: UntypedFormGroup;
5758
connectivitySettingsForm: UntypedFormGroup;
59+
5860
protocol = 'mqtt';
5961
listenerPortMap = new Map<ConnectivityProtocol, number>();
6062

63+
private generalSettings: AdminSettings<GeneralSettings>;
64+
private webSocketSettings: AdminSettings<WebSocketSettings>;
6165
private connectivitySettings: AdminSettings<ConnectivitySettings>;
62-
private generalSettings: AdminSettings<WebSocketSettings>;
66+
6367
private destroy$ = new Subject<void>();
6468

6569
constructor(protected store: Store<AppState>,
6670
private settingsService: SettingsService,
6771
private mqttJsClientService: MqttJsClientService,
6872
public fb: UntypedFormBuilder) {
6973
super(store);
70-
this.buildConnectivitySettingsForm();
71-
this.buildWebSocketSettingsForm();
74+
this.buildForms();
7275
this.getSettings();
7376
}
7477

@@ -77,57 +80,22 @@ export class GeneralSettingsComponent extends PageComponent implements OnDestroy
7780
super.ngOnDestroy();
7881
}
7982

80-
private buildConnectivitySettingsForm() {
81-
this.connectivitySettingsForm = this.fb.group({
82-
ws: this.buildConnectivityInfoForm('ws'),
83-
wss: this.buildConnectivityInfoForm('wss'),
84-
mqtt: this.buildConnectivityInfoForm('mqtt'),
85-
mqtts: this.buildConnectivityInfoForm('mqtts'),
86-
});
87-
}
88-
89-
private buildConnectivityInfoForm(protocol: ConnectivityProtocol): UntypedFormGroup {
90-
const formGroup = this.fb.group({
91-
enabled: [false, []],
92-
host: [{value: '', disabled: true}, [Validators.required]],
93-
port: [{value: null, disabled: true}, [Validators.min(1), Validators.max(65535), Validators.pattern('[0-9]*'), Validators.required]]
94-
});
95-
formGroup.get('enabled').valueChanges.pipe(
96-
takeUntil(this.destroy$)
97-
).subscribe(value => {
98-
if (value) {
99-
formGroup.get('host').enable({emitEvent: false});
100-
formGroup.get('port').enable({emitEvent: false});
101-
this.settingsService.getListenerPort(protocol).subscribe(value => this.listenerPortMap.set(protocol, value));
102-
} else {
103-
formGroup.get('host').disable({emitEvent: false});
104-
formGroup.get('port').disable({emitEvent: false});
105-
this.listenerPortMap.delete(protocol);
106-
}
107-
});
108-
return formGroup;
109-
}
110-
111-
private buildWebSocketSettingsForm() {
112-
this.generalSettingsForm = this.fb.group({
113-
isLoggingEnabled: [null, []],
114-
maxMessages: [null, [Validators.required]]
115-
});
116-
}
117-
11883
saveGeneralSettings() {
119-
let generalSettings: AdminSettings<WebSocketSettings> = JSON.parse(JSON.stringify(this.generalSettings));
120-
const maxMessagesChanged = this.generalSettings.jsonValue.maxMessages !== this.generalSettingsForm.value.maxMessages;
121-
if (isUndefined(this.generalSettings)) {
122-
generalSettings = {
123-
key: webSocketSettingsKey,
124-
jsonValue: this.generalSettingsForm.value
125-
};
126-
}
84+
const generalSettings: AdminSettings<GeneralSettings> = JSON.parse(JSON.stringify(this.generalSettings));
12785
generalSettings.jsonValue = {...generalSettings.jsonValue, ...this.generalSettingsForm.value};
12886
this.settingsService.saveAdminSettings(generalSettings)
12987
.subscribe(settings => {
13088
this.processGeneralSettings(settings);
89+
});
90+
}
91+
92+
saveWebSocketSettings() {
93+
const webSocketSettings: AdminSettings<WebSocketSettings> = JSON.parse(JSON.stringify(this.webSocketSettings));
94+
const maxMessagesChanged = this.webSocketSettings.jsonValue.maxMessages !== this.webSocketSettingsForm.value.maxMessages;
95+
webSocketSettings.jsonValue = {...webSocketSettings.jsonValue, ...this.webSocketSettingsForm.value};
96+
this.settingsService.saveAdminSettings(webSocketSettings)
97+
.subscribe(settings => {
98+
this.processWebSocketSettings(settings);
13199
if (maxMessagesChanged) {
132100
this.mqttJsClientService.clearAllMessages();
133101
}
@@ -156,6 +124,11 @@ export class GeneralSettingsComponent extends PageComponent implements OnDestroy
156124
this.generalSettingsForm.reset(generalSettings);
157125
}
158126

127+
discardWebSocketSettings(): void {
128+
const webSocketSettings = this.webSocketSettings.jsonValue;
129+
this.webSocketSettingsForm.reset(webSocketSettings);
130+
}
131+
159132
discardConnectivitySettings(): void {
160133
this.connectivitySettingsForm.reset(this.connectivitySettings.jsonValue);
161134
}
@@ -179,33 +152,96 @@ export class GeneralSettingsComponent extends PageComponent implements OnDestroy
179152
}
180153
}
181154

182-
private processConnectivitySettings(settings: AdminSettings<ConnectivitySettings>): void {
183-
this.connectivitySettings = settings;
184-
this.connectivitySettingsForm.reset(this.connectivitySettings.jsonValue);
155+
confirmForm(): UntypedFormGroup {
156+
if (this.generalSettingsForm.dirty) {
157+
return this.generalSettingsForm;
158+
} else if (this.webSocketSettingsForm.dirty) {
159+
return this.webSocketSettingsForm;
160+
}
161+
return this.connectivitySettingsForm;
185162
}
186163

187-
private processGeneralSettings(settings: AdminSettings<WebSocketSettings>): void {
164+
private buildForms() {
165+
this.buildGeneralSettingsForm();
166+
this.buildWebSocketSettingsForm();
167+
this.buildConnectivitySettingsForm();
168+
}
169+
170+
private buildGeneralSettingsForm() {
171+
this.generalSettingsForm = this.fb.group({
172+
baseUrl: [null, [Validators.required]],
173+
prohibitDifferentUrl: [null, []],
174+
});
175+
}
176+
177+
private buildWebSocketSettingsForm() {
178+
this.webSocketSettingsForm = this.fb.group({
179+
isLoggingEnabled: [null, []],
180+
maxMessages: [null, [Validators.required]],
181+
});
182+
}
183+
184+
private buildConnectivitySettingsForm() {
185+
this.connectivitySettingsForm = this.fb.group({
186+
ws: this.buildConnectivityInfoForm('ws'),
187+
wss: this.buildConnectivityInfoForm('wss'),
188+
mqtt: this.buildConnectivityInfoForm('mqtt'),
189+
mqtts: this.buildConnectivityInfoForm('mqtts'),
190+
});
191+
}
192+
193+
private buildConnectivityInfoForm(protocol: ConnectivityProtocol): UntypedFormGroup {
194+
const formGroup = this.fb.group({
195+
enabled: [false, []],
196+
host: [{value: '', disabled: true}, [Validators.required]],
197+
port: [{value: null, disabled: true}, [Validators.min(1), Validators.max(65535), Validators.pattern('[0-9]*'), Validators.required]]
198+
});
199+
formGroup.get('enabled').valueChanges.pipe(
200+
takeUntil(this.destroy$)
201+
).subscribe(value => {
202+
if (value) {
203+
formGroup.get('host').enable({emitEvent: false});
204+
formGroup.get('port').enable({emitEvent: false});
205+
this.settingsService.getListenerPort(protocol).subscribe(value => this.listenerPortMap.set(protocol, value));
206+
} else {
207+
formGroup.get('host').disable({emitEvent: false});
208+
formGroup.get('port').disable({emitEvent: false});
209+
this.listenerPortMap.delete(protocol);
210+
}
211+
});
212+
return formGroup;
213+
}
214+
215+
private processGeneralSettings(settings: AdminSettings<GeneralSettings>): void {
188216
this.generalSettings = settings;
189217
this.generalSettingsForm.reset(this.generalSettings.jsonValue);
190218
}
191219

220+
private processWebSocketSettings(settings: AdminSettings<WebSocketSettings>): void {
221+
this.webSocketSettings = settings;
222+
this.webSocketSettingsForm.reset(this.webSocketSettings.jsonValue);
223+
}
224+
225+
private processConnectivitySettings(settings: AdminSettings<ConnectivitySettings>): void {
226+
this.connectivitySettings = settings;
227+
this.connectivitySettingsForm.reset(this.connectivitySettings.jsonValue);
228+
}
229+
192230
private getSettings() {
193231
this.getConnectivitySettings();
194232
this.getWebSocketGeneralSettings();
233+
this.getGeneralSettings();
195234
}
196235

197236
private getConnectivitySettings() {
198237
this.settingsService.getAdminSettings<ConnectivitySettings>(connectivitySettingsKey).subscribe(settings => this.processConnectivitySettings(settings));
199238
}
200239

201240
private getWebSocketGeneralSettings() {
202-
this.settingsService.getWebSocketSettings().subscribe(settings => this.processGeneralSettings(settings));
241+
this.settingsService.getWebSocketSettings().subscribe(settings => this.processWebSocketSettings(settings));
203242
}
204243

205-
confirmForm(): UntypedFormGroup {
206-
if (this.generalSettingsForm.dirty) {
207-
return this.generalSettingsForm;
208-
}
209-
return this.connectivitySettingsForm;
244+
private getGeneralSettings() {
245+
this.settingsService.getAdminSettings<GeneralSettings>(generalSettingsKey).subscribe(settings => this.processGeneralSettings(settings));
210246
}
211247
}

0 commit comments

Comments
 (0)