From 5eb44c165cabdab7c9d938731db105b1d1f05bfe Mon Sep 17 00:00:00 2001 From: Pavlo Tkach <3469726+ptkach@users.noreply.github.com> Date: Thu, 14 Sep 2023 12:37:54 -0400 Subject: [PATCH] Add settings to console home page, update settings->security styles (#2144) --- console-webapp/src/app/app.module.ts | 38 ++++++++-------- .../src/app/header/header.component.html | 10 ++++- .../src/app/header/header.component.scss | 7 ++- .../src/app/home/home.component.html | 2 +- .../widgets/settings-widget.component.html | 38 ++++++++++++++++ .../home/widgets/settings-widget.component.ts | 23 ++++++++++ .../src/app/registrar/registrar.service.ts | 25 +++++++---- .../app/settings/contact/contact.component.ts | 13 ++++-- .../settings/security/security.component.html | 6 ++- .../settings/security/security.component.scss | 3 ++ .../settings/security/security.component.ts | 44 +++++++------------ .../app/settings/security/security.service.ts | 16 ++----- console-webapp/src/styles.scss | 6 ++- .../ui/server/console/RegistrarsAction.java | 2 +- 14 files changed, 156 insertions(+), 77 deletions(-) create mode 100644 console-webapp/src/app/home/widgets/settings-widget.component.html create mode 100644 console-webapp/src/app/home/widgets/settings-widget.component.ts diff --git a/console-webapp/src/app/app.module.ts b/console-webapp/src/app/app.module.ts index d6d4fa1e3..0029a9126 100644 --- a/console-webapp/src/app/app.module.ts +++ b/console-webapp/src/app/app.module.ts @@ -45,39 +45,41 @@ import { ResourcesWidgetComponent } from './home/widgets/resources-widget.compon import { EppWidgetComponent } from './home/widgets/epp-widget.component'; import { BillingWidgetComponent } from './home/widgets/billing-widget.component'; import { DomainsWidgetComponent } from './home/widgets/domains-widget.component'; +import { SettingsWidgetComponent } from './home/widgets/settings-widget.component'; @NgModule({ declarations: [ AppComponent, - HomeComponent, - TldsComponent, - HeaderComponent, - SettingsComponent, - SettingsContactComponent, + BillingWidgetComponent, ContactDetailsDialogComponent, - RegistrarComponent, - SecurityComponent, - EmptyRegistrar, - RegistrarSelectorComponent, ContactWidgetComponent, DomainsWidgetComponent, - PromotionsWidgetComponent, - TldsWidgetComponent, - ResourcesWidgetComponent, + EmptyRegistrar, EppWidgetComponent, - BillingWidgetComponent, + HeaderComponent, + HomeComponent, + PromotionsWidgetComponent, + RegistrarComponent, + RegistrarSelectorComponent, + ResourcesWidgetComponent, + SecurityComponent, + SettingsComponent, + SettingsContactComponent, + SettingsWidgetComponent, + TldsComponent, + TldsWidgetComponent, ], imports: [ - HttpClientModule, - FormsModule, - MaterialModule, - BrowserModule, AppRoutingModule, BrowserAnimationsModule, + BrowserModule, + FormsModule, + HttpClientModule, + MaterialModule, ], providers: [ - GlobalLoaderService, BackendService, + GlobalLoaderService, RegistrarGuard, { provide: MAT_FORM_FIELD_DEFAULT_OPTIONS, diff --git a/console-webapp/src/app/header/header.component.html b/console-webapp/src/app/header/header.component.html index c4c55736b..28468afa1 100644 --- a/console-webapp/src/app/header/header.component.html +++ b/console-webapp/src/app/header/header.component.html @@ -3,7 +3,15 @@ - Google Registry + + + +

Manage Primary, Technical, etc contacts.

+ +

+ Manage IP allow lists and SSL certificates. +

+ +

Reset your Nomulus password.

+ +

Create and manage console user accounts

+ +

Create and manage registrar accounts

+ + + + diff --git a/console-webapp/src/app/home/widgets/settings-widget.component.ts b/console-webapp/src/app/home/widgets/settings-widget.component.ts new file mode 100644 index 000000000..f87bd98e8 --- /dev/null +++ b/console-webapp/src/app/home/widgets/settings-widget.component.ts @@ -0,0 +1,23 @@ +// Copyright 2023 The Nomulus Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { Component } from '@angular/core'; + +@Component({ + selector: '[app-settings-widget]', + templateUrl: './settings-widget.component.html', +}) +export class SettingsWidgetComponent { + constructor() {} +} diff --git a/console-webapp/src/app/registrar/registrar.service.ts b/console-webapp/src/app/registrar/registrar.service.ts index 05c5b4843..17f72314c 100644 --- a/console-webapp/src/app/registrar/registrar.service.ts +++ b/console-webapp/src/app/registrar/registrar.service.ts @@ -14,7 +14,7 @@ import { Injectable } from '@angular/core'; import { BackendService } from '../shared/services/backend.service'; -import { Subject } from 'rxjs'; +import { Observable, Subject, tap } from 'rxjs'; import { GlobalLoader, GlobalLoaderService, @@ -54,24 +54,33 @@ export class RegistrarService implements GlobalLoader { private backend: BackendService, private globalLoader: GlobalLoaderService ) { - this.backend.getRegistrars().subscribe((r) => { + this.loadRegistrars().subscribe((r) => { this.globalLoader.stopGlobalLoader(this); - this.registrars = r; }); this.globalLoader.startGlobalLoader(this); } - public updateRegistrar(registrarId: string) { - this.activeRegistrarId = registrarId; - this.activeRegistrarIdChange.next(registrarId); - } - public get registrar(): Registrar { return this.registrars.filter( (r) => r.registrarId === this.activeRegistrarId )[0]; } + public updateRegistrar(registrarId: string) { + this.activeRegistrarId = registrarId; + this.activeRegistrarIdChange.next(registrarId); + } + + public loadRegistrars(): Observable { + return this.backend.getRegistrars().pipe( + tap((registrars) => { + if (registrars) { + this.registrars = registrars; + } + }) + ); + } + loadingTimeout() { // TODO: Decide what to do when timeout happens } diff --git a/console-webapp/src/app/settings/contact/contact.component.ts b/console-webapp/src/app/settings/contact/contact.component.ts index c40d43c20..f1e8bf704 100644 --- a/console-webapp/src/app/settings/contact/contact.component.ts +++ b/console-webapp/src/app/settings/contact/contact.component.ts @@ -129,7 +129,7 @@ export class ContactDetailsDialogComponent { operationObservable.subscribe({ complete: this.onCloseCallback.bind(this), error: (err: HttpErrorResponse) => { - this._snackBar.open(err.statusText, undefined, { + this._snackBar.open(err.error, undefined, { duration: 1500, }); }, @@ -148,7 +148,8 @@ export default class ContactComponent { private dialog: MatDialog, private bottomSheet: MatBottomSheet, private breakpointObserver: BreakpointObserver, - public contactService: ContactService + public contactService: ContactService, + private _snackBar: MatSnackBar ) { // TODO: Refactor to registrarId service this.loading = true; @@ -170,7 +171,13 @@ export default class ContactComponent { deleteContact(contact: Contact) { if (confirm(`Please confirm contact ${contact.name} delete`)) { - this.contactService.deleteContact(contact).subscribe(); + this.contactService.deleteContact(contact).subscribe({ + error: (err: HttpErrorResponse) => { + this._snackBar.open(err.error, undefined, { + duration: 1500, + }); + }, + }); } } diff --git a/console-webapp/src/app/settings/security/security.component.html b/console-webapp/src/app/settings/security/security.component.html index 62639465b..a517e8eb4 100644 --- a/console-webapp/src/app/settings/security/security.component.html +++ b/console-webapp/src/app/settings/security/security.component.html @@ -17,8 +17,10 @@ dataSource.ipAddressAllowList.length > 0 " > -
-
{{ item.value }}
+
{ - this.dataSource = this.securityService.securitySettings; - this.loading = false; - }, - error: (err: HttpErrorResponse) => { - this._snackBar.open(err.error, undefined, { - duration: 1500, - }); - this.loading = false; - }, - }); + this.dataSource = apiToUiConverter(this.registrarService.registrar); } enableEdit() { this.inEdit = true; - this.dataSource = JSON.parse( - JSON.stringify(this.securityService.securitySettings) - ); } - disableEdit() { + cancel() { this.inEdit = false; - this.dataSource = this.securityService.securitySettings; + this.resetDataSource(); } createIpEntry() { @@ -68,7 +59,7 @@ export default class SecurityComponent { this.securityService.saveChanges(this.dataSource).subscribe({ complete: () => { this.loading = false; - this.dataSource = this.securityService.securitySettings; + this.resetDataSource(); }, error: (err: HttpErrorResponse) => { this._snackBar.open(err.error, undefined, { @@ -76,16 +67,15 @@ export default class SecurityComponent { }); }, }); - this.disableEdit(); - } - - cancel() { - this.dataSource = this.securityService.securitySettings; - this.inEdit = false; + this.cancel(); } removeIpEntry(index: number) { this.dataSource.ipAddressAllowList = this.dataSource.ipAddressAllowList?.filter((_, i) => i != index); } + + resetDataSource() { + this.dataSource = apiToUiConverter(this.registrarService.registrar); + } } diff --git a/console-webapp/src/app/settings/security/security.service.ts b/console-webapp/src/app/settings/security/security.service.ts index ae19deb8e..b1ef83685 100644 --- a/console-webapp/src/app/settings/security/security.service.ts +++ b/console-webapp/src/app/settings/security/security.service.ts @@ -13,7 +13,7 @@ // limitations under the License. import { Injectable } from '@angular/core'; -import { tap } from 'rxjs'; +import { switchMap } from 'rxjs'; import { RegistrarService } from 'src/app/registrar/registrar.service'; import { BackendService } from 'src/app/shared/services/backend.service'; @@ -61,16 +61,6 @@ export class SecurityService { private registrarService: RegistrarService ) {} - fetchSecurityDetails() { - return this.backend - .getSecuritySettings(this.registrarService.activeRegistrarId) - .pipe( - tap((securitySettings: SecuritySettingsBackendModel) => { - this.securitySettings = apiToUiConverter(securitySettings); - }) - ); - } - saveChanges(newSecuritySettings: SecuritySettings) { return this.backend .postSecuritySettings( @@ -78,8 +68,8 @@ export class SecurityService { uiToApiConverter(newSecuritySettings) ) .pipe( - tap((_) => { - this.securitySettings = newSecuritySettings; + switchMap(() => { + return this.registrarService.loadRegistrars(); }) ); } diff --git a/console-webapp/src/styles.scss b/console-webapp/src/styles.scss index 59959cf8b..abd938ce5 100644 --- a/console-webapp/src/styles.scss +++ b/console-webapp/src/styles.scss @@ -44,7 +44,7 @@ body { &-link { padding: 0 !important; text-align: left; - margin-bottom: 0.5rem; + height: 20px !important; } &-title { color: var(--primary) !important; @@ -65,6 +65,10 @@ body { flex: 1; border-left: 1px solid var(--secondary); padding-left: 20px; + .secondary-text { + margin-bottom: 0.3rem; + font-size: 0.8rem; + } } } } diff --git a/core/src/main/java/google/registry/ui/server/console/RegistrarsAction.java b/core/src/main/java/google/registry/ui/server/console/RegistrarsAction.java index 93b2ac16f..51bcb1f48 100644 --- a/core/src/main/java/google/registry/ui/server/console/RegistrarsAction.java +++ b/core/src/main/java/google/registry/ui/server/console/RegistrarsAction.java @@ -93,7 +93,7 @@ public class RegistrarsAction implements JsonGetAction { return; } ImmutableList registrars = - Streams.stream(Registrar.loadAllCached()) + Streams.stream(Registrar.loadAll()) .filter(r -> r.getType() == Registrar.Type.REAL) .collect(ImmutableList.toImmutableList());