Add resources widget front-end (#2151)

This commit is contained in:
Pavlo Tkach 2023-09-21 13:59:40 -04:00 committed by GitHub
parent 759143535f
commit dded258864
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 151 additions and 29 deletions

View file

@ -24,6 +24,10 @@ import SettingsSecurityComponent from './settings/security/security.component';
import { RegistrarGuard } from './registrar/registrar.guard';
import { RegistrarComponent } from './registrar/registrarsTable.component';
import { EmptyRegistrar } from './registrar/emptyRegistrar.component';
import ContactComponent from './settings/contact/contact.component';
import WhoisComponent from './settings/whois/whois.component';
import SecurityComponent from './settings/security/security.component';
import UsersComponent from './settings/users/users.component';
const routes: Routes = [
{ path: '', redirectTo: '/home', pathMatch: 'full' },
@ -32,7 +36,7 @@ const routes: Routes = [
{ path: 'home', component: HomeComponent, canActivate: [RegistrarGuard] },
{ path: 'tlds', component: TldsComponent, canActivate: [RegistrarGuard] },
{
path: 'settings',
path: SettingsComponent.PATH,
component: SettingsComponent,
children: [
{
@ -41,32 +45,27 @@ const routes: Routes = [
pathMatch: 'full',
},
{
path: 'contact',
path: ContactComponent.PATH,
component: SettingsContactComponent,
canActivate: [RegistrarGuard],
},
{
path: 'whois',
path: WhoisComponent.PATH,
component: SettingsWhoisComponent,
canActivate: [RegistrarGuard],
},
{
path: 'security',
path: SecurityComponent.PATH,
component: SettingsSecurityComponent,
canActivate: [RegistrarGuard],
},
{
path: 'epp-password',
component: SettingsSecurityComponent,
canActivate: [RegistrarGuard],
},
{
path: 'users',
path: UsersComponent.PATH,
component: SettingsUsersComponent,
canActivate: [RegistrarGuard],
},
{
path: 'registrars',
path: RegistrarComponent.PATH,
component: RegistrarComponent,
},
],

View file

@ -14,6 +14,7 @@
import { Component } from '@angular/core';
import { RegistrarService } from './registrar/registrar.service';
import { UserDataService } from './shared/services/userData.service';
import { GlobalLoaderService } from './shared/services/globalLoader.service';
@Component({
@ -25,6 +26,7 @@ export class AppComponent {
renderRouter: boolean = true;
constructor(
protected registrarService: RegistrarService,
protected userDataService: UserDataService,
protected globalLoader: GlobalLoaderService
) {
registrarService.activeRegistrarIdChange.subscribe(() => {

View file

@ -46,6 +46,7 @@ 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';
import { UserDataService } from './shared/services/userData.service';
@NgModule({
declarations: [
@ -81,6 +82,7 @@ import { SettingsWidgetComponent } from './home/widgets/settings-widget.componen
BackendService,
GlobalLoaderService,
RegistrarGuard,
UserDataService,
{
provide: MAT_FORM_FIELD_DEFAULT_OPTIONS,
useValue: {

View file

@ -13,13 +13,13 @@
Give us a Call
</button>
<p class="secondary-text">
Call Google Registry support at +1 (404) 978 8419
Call Google Registry support at <b>+1 (404) 978 8419</b>
</p>
<button mat-button color="primary" class="console-app__widget-link">
Send us an Email
</button>
<p class="secondary-text">
Email Google Registry at support@google.com
Email Google Registry at <b>support@google.com</b>
</p>
</div>
</div>

View file

@ -1,13 +1,16 @@
<mat-card>
<mat-card-content>
<div class="console-app__widget">
<div class="console-app__widget_left">
<a
class="console-app__widget_left"
href="{{ userDataService.userData?.technicalDocsUrl }}"
>
<mat-icon class="console-app__widget-icon">menu_book</mat-icon>
<h1 class="console-app__widget-title">Resources</h1>
<h4 class="secondary-text text-center">
Use Google Drive to view onboarding FAQs, and technical documentation.
</h4>
</div>
</a>
</div>
</mat-card-content>
</mat-card>

View file

@ -13,11 +13,12 @@
// limitations under the License.
import { Component } from '@angular/core';
import { UserDataService } from 'src/app/shared/services/userData.service';
@Component({
selector: '[app-resources-widget]',
templateUrl: './resources-widget.component.html',
})
export class ResourcesWidgetComponent {
constructor() {}
constructor(public userDataService: UserDataService) {}
}

View file

@ -10,11 +10,21 @@
</h4>
</div>
<div class="console-app__widget_right">
<button mat-button color="primary" class="console-app__widget-link">
<button
mat-button
color="primary"
class="console-app__widget-link"
(click)="openContactsPage()"
>
Contact Information
</button>
<p class="secondary-text">Manage Primary, Technical, etc contacts.</p>
<button mat-button color="primary" class="console-app__widget-link">
<button
mat-button
color="primary"
class="console-app__widget-link"
(click)="openSecurityPage()"
>
Security
</button>
<p class="secondary-text">
@ -28,7 +38,12 @@
User Management
</button>
<p class="secondary-text">Create and manage console user accounts</p>
<button mat-button color="primary" class="console-app__widget-link">
<button
mat-button
color="primary"
class="console-app__widget-link"
(click)="openRegistrarsPage()"
>
Registrar Management
</button>
<p class="secondary-text">Create and manage registrar accounts</p>

View file

@ -13,11 +13,32 @@
// limitations under the License.
import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { RegistrarComponent } from 'src/app/registrar/registrarsTable.component';
import ContactComponent from 'src/app/settings/contact/contact.component';
import SecurityComponent from 'src/app/settings/security/security.component';
import { SettingsComponent } from 'src/app/settings/settings.component';
@Component({
selector: '[app-settings-widget]',
templateUrl: './settings-widget.component.html',
})
export class SettingsWidgetComponent {
constructor() {}
constructor(private router: Router) {}
openRegistrarsPage() {
this.navigate(RegistrarComponent.PATH);
}
openSecurityPage() {
this.navigate(SecurityComponent.PATH);
}
openContactsPage() {
this.navigate(ContactComponent.PATH);
}
private navigate(route: string) {
this.router.navigate([SettingsComponent.PATH, route]);
}
}

View file

@ -19,6 +19,7 @@ import {
GlobalLoader,
GlobalLoaderService,
} from '../shared/services/globalLoader.service';
import { MatSnackBar } from '@angular/material/snack-bar';
interface Address {
street?: string[];
@ -52,7 +53,8 @@ export class RegistrarService implements GlobalLoader {
constructor(
private backend: BackendService,
private globalLoader: GlobalLoaderService
private globalLoader: GlobalLoaderService,
private _snackBar: MatSnackBar
) {
this.loadRegistrars().subscribe((r) => {
this.globalLoader.stopGlobalLoader(this);
@ -82,6 +84,8 @@ export class RegistrarService implements GlobalLoader {
}
loadingTimeout() {
// TODO: Decide what to do when timeout happens
this._snackBar.open('Timeout loading registrars', undefined, {
duration: 1500,
});
}
}

View file

@ -21,6 +21,7 @@ import { Registrar, RegistrarService } from './registrar.service';
styleUrls: ['./registrarsTable.component.scss'],
})
export class RegistrarComponent {
public static PATH = 'registrars';
columns = [
{
columnDef: 'registrarId',

View file

@ -143,6 +143,8 @@ export class ContactDetailsDialogComponent {
styleUrls: ['./contact.component.scss'],
})
export default class ContactComponent {
public static PATH = 'contact';
loading: boolean = false;
constructor(
private dialog: MatDialog,

View file

@ -29,6 +29,8 @@ import { RegistrarService } from 'src/app/registrar/registrar.service';
providers: [SecurityService],
})
export default class SecurityComponent {
public static PATH = 'security';
loading: boolean = false;
inEdit: boolean = false;
dataSource: SecuritySettings = {};

View file

@ -20,4 +20,6 @@ import { Component, ViewEncapsulation } from '@angular/core';
styleUrls: ['./settings.component.scss'],
encapsulation: ViewEncapsulation.None,
})
export class SettingsComponent {}
export class SettingsComponent {
public static PATH = 'settings';
}

View file

@ -19,4 +19,6 @@ import { Component } from '@angular/core';
templateUrl: './users.component.html',
styleUrls: ['./users.component.scss'],
})
export default class UsersComponent {}
export default class UsersComponent {
public static PATH = 'users';
}

View file

@ -19,4 +19,6 @@ import { Component } from '@angular/core';
templateUrl: './whois.component.html',
styleUrls: ['./whois.component.scss'],
})
export default class WhoisComponent {}
export default class WhoisComponent {
public static PATH = 'whois';
}

View file

@ -19,6 +19,7 @@ import { SecuritySettingsBackendModel } from 'src/app/settings/security/security
import { Contact } from '../../settings/contact/contact.service';
import { Registrar } from '../../registrar/registrar.service';
import { UserData } from './userData.service';
@Injectable()
export class BackendService {
@ -90,4 +91,10 @@ export class BackendService {
securitySettings
);
}
getUserData(): Observable<UserData> {
return this.http
.get<UserData>(`/console-api/userdata`)
.pipe(catchError((err) => this.errorCatcher<UserData>(err)));
}
}

View file

@ -0,0 +1,56 @@
// 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 { Injectable } from '@angular/core';
import { Observable, tap } from 'rxjs';
import { BackendService } from './backend.service';
import { MatSnackBar } from '@angular/material/snack-bar';
import { GlobalLoader, GlobalLoaderService } from './globalLoader.service';
export interface UserData {
isAdmin: boolean;
globalRole: string;
technicalDocsUrl: string;
}
@Injectable({
providedIn: 'root',
})
export class UserDataService implements GlobalLoader {
public userData?: UserData;
constructor(
private backend: BackendService,
protected globalLoader: GlobalLoaderService,
private _snackBar: MatSnackBar
) {
this.getUserData().subscribe(() => {
this.globalLoader.stopGlobalLoader(this);
});
this.globalLoader.startGlobalLoader(this);
}
getUserData(): Observable<UserData> {
return this.backend.getUserData().pipe(
tap((userData: UserData) => {
this.userData = userData;
})
);
}
loadingTimeout() {
this._snackBar.open('Timeout loading user data', undefined, {
duration: 1500,
});
}
}

View file

@ -45,15 +45,16 @@ body {
padding: 0 !important;
text-align: left;
height: 20px !important;
min-width: auto !important;
}
&-title {
color: var(--primary) !important;
}
&-icon {
font-size: 4rem;
line-height: 4rem;
height: 4rem !important;
width: 4rem !important;
font-size: 5rem;
line-height: 5rem;
height: 5rem !important;
width: 5rem !important;
}
&_left {
flex: 1;