mirror of
https://github.com/google/nomulus.git
synced 2025-07-23 19:20:44 +02:00
Replace less with scss, add homepage widgets, add registrars selector and registrars page (#2114)
* Replace less compiler with scss * Replace less with scss, add homepage widgets, add registrars selector and registrars page
This commit is contained in:
parent
6b5ec36eed
commit
1929654f8c
62 changed files with 11927 additions and 730 deletions
|
@ -7,7 +7,7 @@
|
||||||
"projectType": "application",
|
"projectType": "application",
|
||||||
"schematics": {
|
"schematics": {
|
||||||
"@schematics/angular:component": {
|
"@schematics/angular:component": {
|
||||||
"style": "less"
|
"style": "scss"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"root": "",
|
"root": "",
|
||||||
|
@ -22,15 +22,18 @@
|
||||||
"main": "src/main.ts",
|
"main": "src/main.ts",
|
||||||
"polyfills": "src/polyfills.ts",
|
"polyfills": "src/polyfills.ts",
|
||||||
"tsConfig": "tsconfig.app.json",
|
"tsConfig": "tsconfig.app.json",
|
||||||
"inlineStyleLanguage": "less",
|
"inlineStyleLanguage": "scss",
|
||||||
"assets": [
|
"assets": [
|
||||||
"src/favicon.ico",
|
"src/favicon.ico",
|
||||||
"src/assets"
|
"src/assets"
|
||||||
],
|
],
|
||||||
"styles": [
|
"styles": [
|
||||||
"./node_modules/@angular/material/prebuilt-themes/indigo-pink.css",
|
"src/theme.scss",
|
||||||
"src/styles.less"
|
"src/styles.scss"
|
||||||
],
|
],
|
||||||
|
"stylePreprocessorOptions": {
|
||||||
|
"includePaths": ["node_modules/"]
|
||||||
|
},
|
||||||
"scripts": []
|
"scripts": []
|
||||||
},
|
},
|
||||||
"configurations": {
|
"configurations": {
|
||||||
|
@ -91,15 +94,18 @@
|
||||||
"polyfills": "src/polyfills.ts",
|
"polyfills": "src/polyfills.ts",
|
||||||
"tsConfig": "tsconfig.spec.json",
|
"tsConfig": "tsconfig.spec.json",
|
||||||
"karmaConfig": "karma.conf.js",
|
"karmaConfig": "karma.conf.js",
|
||||||
"inlineStyleLanguage": "less",
|
"inlineStyleLanguage": "scss",
|
||||||
"assets": [
|
"assets": [
|
||||||
"src/favicon.ico",
|
"src/favicon.ico",
|
||||||
"src/assets"
|
"src/assets"
|
||||||
],
|
],
|
||||||
"styles": [
|
"styles": [
|
||||||
"./node_modules/@angular/material/prebuilt-themes/indigo-pink.css",
|
"src/theme.scss",
|
||||||
"src/styles.less"
|
"src/styles.scss"
|
||||||
],
|
],
|
||||||
|
"stylePreprocessorOptions": {
|
||||||
|
"includePaths": ["node_modules/"]
|
||||||
|
},
|
||||||
"scripts": []
|
"scripts": []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
11444
console-webapp/package-lock.json
generated
11444
console-webapp/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -18,51 +18,56 @@ import { TldsComponent } from './tlds/tlds.component';
|
||||||
import { HomeComponent } from './home/home.component';
|
import { HomeComponent } from './home/home.component';
|
||||||
import { SettingsComponent } from './settings/settings.component';
|
import { SettingsComponent } from './settings/settings.component';
|
||||||
import SettingsContactComponent from './settings/contact/contact.component';
|
import SettingsContactComponent from './settings/contact/contact.component';
|
||||||
import SettingsRegistrarsComponent from './settings/registrars/registrars.component';
|
|
||||||
import SettingsWhoisComponent from './settings/whois/whois.component';
|
import SettingsWhoisComponent from './settings/whois/whois.component';
|
||||||
import SettingsUsersComponent from './settings/users/users.component';
|
import SettingsUsersComponent from './settings/users/users.component';
|
||||||
import SettingsSecurityComponent from './settings/security/security.component';
|
import SettingsSecurityComponent from './settings/security/security.component';
|
||||||
import { RegistrarGuard } from './registrar/registrar.guard';
|
import { RegistrarGuard } from './registrar/registrar.guard';
|
||||||
import { RegistrarComponent } from './registrar/registrar.component';
|
import { RegistrarComponent } from './registrar/registrarsTable.component';
|
||||||
|
import { EmptyRegistrar } from './registrar/emptyRegistrar.component';
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{ path: '', redirectTo: '/home', pathMatch: 'full' },
|
{ path: '', redirectTo: '/home', pathMatch: 'full' },
|
||||||
{ path: 'registrars', component: RegistrarComponent },
|
{ path: 'registrars', component: RegistrarComponent },
|
||||||
|
{ path: 'empty-registrar', component: EmptyRegistrar },
|
||||||
{ path: 'home', component: HomeComponent, canActivate: [RegistrarGuard] },
|
{ path: 'home', component: HomeComponent, canActivate: [RegistrarGuard] },
|
||||||
{ path: 'tlds', component: TldsComponent, canActivate: [RegistrarGuard] },
|
{ path: 'tlds', component: TldsComponent, canActivate: [RegistrarGuard] },
|
||||||
{
|
{
|
||||||
path: 'settings',
|
path: 'settings',
|
||||||
component: SettingsComponent,
|
component: SettingsComponent,
|
||||||
canActivate: [RegistrarGuard],
|
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
redirectTo: 'contact',
|
redirectTo: 'registrars',
|
||||||
pathMatch: 'full',
|
pathMatch: 'full',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'contact',
|
path: 'contact',
|
||||||
component: SettingsContactComponent,
|
component: SettingsContactComponent,
|
||||||
|
canActivate: [RegistrarGuard],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'whois',
|
path: 'whois',
|
||||||
component: SettingsWhoisComponent,
|
component: SettingsWhoisComponent,
|
||||||
|
canActivate: [RegistrarGuard],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'security',
|
path: 'security',
|
||||||
component: SettingsSecurityComponent,
|
component: SettingsSecurityComponent,
|
||||||
|
canActivate: [RegistrarGuard],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'epp-password',
|
path: 'epp-password',
|
||||||
component: SettingsSecurityComponent,
|
component: SettingsSecurityComponent,
|
||||||
|
canActivate: [RegistrarGuard],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'users',
|
path: 'users',
|
||||||
component: SettingsUsersComponent,
|
component: SettingsUsersComponent,
|
||||||
|
canActivate: [RegistrarGuard],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'registrars',
|
path: 'registrars',
|
||||||
component: SettingsRegistrarsComponent,
|
component: RegistrarComponent,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
|
@ -12,13 +12,13 @@
|
||||||
<a mat-list-item [routerLink]="'/settings'" routerLinkActive="active">
|
<a mat-list-item [routerLink]="'/settings'" routerLinkActive="active">
|
||||||
Settings
|
Settings
|
||||||
</a>
|
</a>
|
||||||
<a mat-list-item [routerLink]="'/registrars'" routerLinkActive="active">
|
|
||||||
Select Registrar
|
|
||||||
</a>
|
|
||||||
</mat-nav-list>
|
</mat-nav-list>
|
||||||
</mat-sidenav>
|
</mat-sidenav>
|
||||||
<mat-sidenav-content class="console-app__content-wrapper">
|
<mat-sidenav-content class="console-app__content-wrapper">
|
||||||
<div class="console-app__content">
|
<div *ngIf="globalLoader.isLoading" class="console-app__global-spinner">
|
||||||
|
<mat-progress-bar mode="indeterminate"></mat-progress-bar>
|
||||||
|
</div>
|
||||||
|
<div class="console-app__content" *ngIf="renderRouter">
|
||||||
<router-outlet></router-outlet>
|
<router-outlet></router-outlet>
|
||||||
</div>
|
</div>
|
||||||
</mat-sidenav-content>
|
</mat-sidenav-content>
|
||||||
|
|
|
@ -13,8 +13,8 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
:host {
|
:host {
|
||||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica,
|
font-family: Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji",
|
||||||
Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
"Segoe UI Emoji", "Segoe UI Symbol" !important;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: #333;
|
color: #333;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
@ -47,4 +47,7 @@
|
||||||
max-width: 1340px;
|
max-width: 1340px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
&__global-spinner {
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -13,10 +13,25 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
|
import { RegistrarService } from './registrar/registrar.service';
|
||||||
|
import { GlobalLoaderService } from './shared/services/globalLoader.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
templateUrl: './app.component.html',
|
templateUrl: './app.component.html',
|
||||||
styleUrls: ['./app.component.less'],
|
styleUrls: ['./app.component.scss'],
|
||||||
})
|
})
|
||||||
export class AppComponent {}
|
export class AppComponent {
|
||||||
|
renderRouter: boolean = true;
|
||||||
|
constructor(
|
||||||
|
protected registrarService: RegistrarService,
|
||||||
|
protected globalLoader: GlobalLoaderService
|
||||||
|
) {
|
||||||
|
registrarService.activeRegistrarIdChange.subscribe(() => {
|
||||||
|
this.renderRouter = false;
|
||||||
|
setTimeout(() => {
|
||||||
|
this.renderRouter = true;
|
||||||
|
}, 400);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -31,9 +31,20 @@ import SettingsContactComponent, {
|
||||||
ContactDetailsDialogComponent,
|
ContactDetailsDialogComponent,
|
||||||
} from './settings/contact/contact.component';
|
} from './settings/contact/contact.component';
|
||||||
import { HttpClientModule } from '@angular/common/http';
|
import { HttpClientModule } from '@angular/common/http';
|
||||||
import { RegistrarComponent } from './registrar/registrar.component';
|
import { RegistrarComponent } from './registrar/registrarsTable.component';
|
||||||
import { RegistrarGuard } from './registrar/registrar.guard';
|
import { RegistrarGuard } from './registrar/registrar.guard';
|
||||||
import SecurityComponent from './settings/security/security.component';
|
import SecurityComponent from './settings/security/security.component';
|
||||||
|
import { MAT_FORM_FIELD_DEFAULT_OPTIONS } from '@angular/material/form-field';
|
||||||
|
import { EmptyRegistrar } from './registrar/emptyRegistrar.component';
|
||||||
|
import { RegistrarSelectorComponent } from './registrar/registrar-selector.component';
|
||||||
|
import { GlobalLoaderService } from './shared/services/globalLoader.service';
|
||||||
|
import { ContactWidgetComponent } from './home/widgets/contact-widget.component';
|
||||||
|
import { PromotionsWidgetComponent } from './home/widgets/promotions-widget.component';
|
||||||
|
import { TldsWidgetComponent } from './home/widgets/tlds-widget.component';
|
||||||
|
import { ResourcesWidgetComponent } from './home/widgets/resources-widget.component';
|
||||||
|
import { EppWidgetComponent } from './home/widgets/epp-widget.component';
|
||||||
|
import { BillingWidgetComponent } from './home/widgets/billing-widget.component';
|
||||||
|
import { DomainsWidgetComponent } from './home/widgets/domains-widget.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
|
@ -46,6 +57,15 @@ import SecurityComponent from './settings/security/security.component';
|
||||||
ContactDetailsDialogComponent,
|
ContactDetailsDialogComponent,
|
||||||
RegistrarComponent,
|
RegistrarComponent,
|
||||||
SecurityComponent,
|
SecurityComponent,
|
||||||
|
EmptyRegistrar,
|
||||||
|
RegistrarSelectorComponent,
|
||||||
|
ContactWidgetComponent,
|
||||||
|
DomainsWidgetComponent,
|
||||||
|
PromotionsWidgetComponent,
|
||||||
|
TldsWidgetComponent,
|
||||||
|
ResourcesWidgetComponent,
|
||||||
|
EppWidgetComponent,
|
||||||
|
BillingWidgetComponent,
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
HttpClientModule,
|
HttpClientModule,
|
||||||
|
@ -55,7 +75,17 @@ import SecurityComponent from './settings/security/security.component';
|
||||||
AppRoutingModule,
|
AppRoutingModule,
|
||||||
BrowserAnimationsModule,
|
BrowserAnimationsModule,
|
||||||
],
|
],
|
||||||
providers: [BackendService, RegistrarGuard],
|
providers: [
|
||||||
|
GlobalLoaderService,
|
||||||
|
BackendService,
|
||||||
|
RegistrarGuard,
|
||||||
|
{
|
||||||
|
provide: MAT_FORM_FIELD_DEFAULT_OPTIONS,
|
||||||
|
useValue: {
|
||||||
|
subscriptSizing: 'dynamic',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
bootstrap: [AppComponent],
|
bootstrap: [AppComponent],
|
||||||
})
|
})
|
||||||
export class AppModule {}
|
export class AppModule {}
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
</button>
|
</button>
|
||||||
<span>Google Registry</span>
|
<span>Google Registry</span>
|
||||||
<span class="spacer"></span>
|
<span class="spacer"></span>
|
||||||
|
<app-registrar-selector />
|
||||||
<button mat-icon-button aria-label="Open FAQ">
|
<button mat-icon-button aria-label="Open FAQ">
|
||||||
<mat-icon>question_mark</mat-icon>
|
<mat-icon>question_mark</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
|
|
|
@ -12,6 +12,9 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
|
.console-app__header {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
.spacer {
|
.spacer {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
|
@ -17,7 +17,7 @@ import { Component, EventEmitter, Output } from '@angular/core';
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-header',
|
selector: 'app-header',
|
||||||
templateUrl: './header.component.html',
|
templateUrl: './header.component.html',
|
||||||
styleUrls: ['./header.component.less'],
|
styleUrls: ['./header.component.scss'],
|
||||||
})
|
})
|
||||||
export class HeaderComponent {
|
export class HeaderComponent {
|
||||||
private isNavOpen = false;
|
private isNavOpen = false;
|
||||||
|
|
|
@ -1,21 +1,13 @@
|
||||||
<h3>Recent Activity</h3>
|
<div class="console-app__home">
|
||||||
<table
|
<h1>Welcome to the Google Registry Console</h1>
|
||||||
mat-table
|
<div class="console-app__home-widgets">
|
||||||
[dataSource]="dataSource"
|
<div app-domains-widget class="console-app__widget-wrapper__wide"></div>
|
||||||
class="mat-elevation-z8 console-home__activity"
|
<div app-contact-widget class="console-app__widget-wrapper__wide"></div>
|
||||||
>
|
<div app-tlds-widget></div>
|
||||||
<ng-container
|
<div app-promotions-widget class="console-app__widget-wrapper__wide"></div>
|
||||||
*ngFor="let column of columns"
|
<div app-promotions-widget class="console-app__widget-wrapper__wide"></div>
|
||||||
[matColumnDef]="column.columnDef"
|
<div app-resources-widget></div>
|
||||||
>
|
<div app-billing-widget></div>
|
||||||
<th mat-header-cell *matHeaderCellDef>
|
<div app-epp-widget></div>
|
||||||
{{ column.header }}
|
</div>
|
||||||
</th>
|
</div>
|
||||||
<td mat-cell *matCellDef="let row">
|
|
||||||
{{ column.cell(row) }}
|
|
||||||
</td>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
|
||||||
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
|
|
||||||
</table>
|
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
// Copyright 2022 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.
|
|
|
@ -12,11 +12,20 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
html,
|
.console-app {
|
||||||
body {
|
&__home {
|
||||||
height: 100%;
|
margin-top: 1rem;
|
||||||
}
|
}
|
||||||
body {
|
&__home-widgets {
|
||||||
margin: 0;
|
display: grid;
|
||||||
font-family: Roboto, "Helvetica Neue", sans-serif;
|
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
|
||||||
|
grid-gap: 20px;
|
||||||
|
|
||||||
|
mat-card {
|
||||||
|
height: 100%;
|
||||||
|
h1 {
|
||||||
|
margin-top: 1rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -12,220 +12,12 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { Component } from '@angular/core';
|
import { Component, ViewEncapsulation } from '@angular/core';
|
||||||
|
|
||||||
export interface ActivityRecord {
|
|
||||||
eventType: string;
|
|
||||||
userName: string;
|
|
||||||
registrarName: string;
|
|
||||||
timestamp: string;
|
|
||||||
details: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const MOCK_DATA: ActivityRecord[] = [
|
|
||||||
{
|
|
||||||
eventType: 'Export DUMS',
|
|
||||||
userName: 'user3',
|
|
||||||
registrarName: 'registrar1',
|
|
||||||
timestamp: '2022-03-15T19:46:39.007',
|
|
||||||
details: 'All Domains under management exported as .csv file',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventType: 'Update Contact',
|
|
||||||
userName: 'user3',
|
|
||||||
registrarName: 'registrar1',
|
|
||||||
timestamp: '2022-03-15T19:46:39.007',
|
|
||||||
details: 'All Domains under management exported as .csv file',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventType: 'Delete Domain',
|
|
||||||
userName: 'user3',
|
|
||||||
registrarName: 'registrar1',
|
|
||||||
timestamp: '2022-03-15T19:46:39.007',
|
|
||||||
details: 'All Domains under management exported as .csv file',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventType: 'Export DUMS',
|
|
||||||
userName: 'user3',
|
|
||||||
registrarName: 'registrar1',
|
|
||||||
timestamp: '2022-03-15T19:46:39.007',
|
|
||||||
details: 'All Domains under management exported as .csv file',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventType: 'Update Contact',
|
|
||||||
userName: 'user3',
|
|
||||||
registrarName: 'registrar1',
|
|
||||||
timestamp: '2022-03-15T19:46:39.007',
|
|
||||||
details: 'All Domains under management exported as .csv file',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventType: 'Delete Domain',
|
|
||||||
userName: 'user3',
|
|
||||||
registrarName: 'registrar1',
|
|
||||||
timestamp: '2022-03-15T19:46:39.007',
|
|
||||||
details: 'All Domains under management exported as .csv file',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventType: 'Export DUMS',
|
|
||||||
userName: 'user3',
|
|
||||||
registrarName: 'registrar1',
|
|
||||||
timestamp: '2022-03-15T19:46:39.007',
|
|
||||||
details: 'All Domains under management exported as .csv file',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventType: 'Update Contact',
|
|
||||||
userName: 'user3',
|
|
||||||
registrarName: 'registrar1',
|
|
||||||
timestamp: '2022-03-15T19:46:39.007',
|
|
||||||
details: 'All Domains under management exported as .csv file',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventType: 'Delete Domain',
|
|
||||||
userName: 'user3',
|
|
||||||
registrarName: 'registrar1',
|
|
||||||
timestamp: '2022-03-15T19:46:39.007',
|
|
||||||
details: 'All Domains under management exported as .csv file',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventType: 'Export DUMS',
|
|
||||||
userName: 'user3',
|
|
||||||
registrarName: 'registrar1',
|
|
||||||
timestamp: '2022-03-15T19:46:39.007',
|
|
||||||
details: 'All Domains under management exported as .csv file',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventType: 'Update Contact',
|
|
||||||
userName: 'user3',
|
|
||||||
registrarName: 'registrar1',
|
|
||||||
timestamp: '2022-03-15T19:46:39.007',
|
|
||||||
details: 'All Domains under management exported as .csv file',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventType: 'Delete Domain',
|
|
||||||
userName: 'user3',
|
|
||||||
registrarName: 'registrar1',
|
|
||||||
timestamp: '2022-03-15T19:46:39.007',
|
|
||||||
details: 'All Domains under management exported as .csv file',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventType: 'Export DUMS',
|
|
||||||
userName: 'user3',
|
|
||||||
registrarName: 'registrar1',
|
|
||||||
timestamp: '2022-03-15T19:46:39.007',
|
|
||||||
details: 'All Domains under management exported as .csv file',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventType: 'Update Contact',
|
|
||||||
userName: 'user3',
|
|
||||||
registrarName: 'registrar1',
|
|
||||||
timestamp: '2022-03-15T19:46:39.007',
|
|
||||||
details: 'All Domains under management exported as .csv file',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventType: 'Delete Domain',
|
|
||||||
userName: 'user3',
|
|
||||||
registrarName: 'registrar1',
|
|
||||||
timestamp: '2022-03-15T19:46:39.007',
|
|
||||||
details: 'All Domains under management exported as .csv file',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventType: 'Export DUMS',
|
|
||||||
userName: 'user3',
|
|
||||||
registrarName: 'registrar1',
|
|
||||||
timestamp: '2022-03-15T19:46:39.007',
|
|
||||||
details: 'All Domains under management exported as .csv file',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventType: 'Update Contact',
|
|
||||||
userName: 'user3',
|
|
||||||
registrarName: 'registrar1',
|
|
||||||
timestamp: '2022-03-15T19:46:39.007',
|
|
||||||
details: 'All Domains under management exported as .csv file',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventType: 'Delete Domain',
|
|
||||||
userName: 'user3',
|
|
||||||
registrarName: 'registrar1',
|
|
||||||
timestamp: '2022-03-15T19:46:39.007',
|
|
||||||
details: 'All Domains under management exported as .csv file',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventType: 'Export DUMS',
|
|
||||||
userName: 'user3',
|
|
||||||
registrarName: 'registrar1',
|
|
||||||
timestamp: '2022-03-15T19:46:39.007',
|
|
||||||
details: 'All Domains under management exported as .csv file',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventType: 'Update Contact',
|
|
||||||
userName: 'user3',
|
|
||||||
registrarName: 'registrar1',
|
|
||||||
timestamp: '2022-03-15T19:46:39.007',
|
|
||||||
details: 'All Domains under management exported as .csv file',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventType: 'Delete Domain',
|
|
||||||
userName: 'user3',
|
|
||||||
registrarName: 'registrar1',
|
|
||||||
timestamp: '2022-03-15T19:46:39.007',
|
|
||||||
details: 'All Domains under management exported as .csv file',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventType: 'Export DUMS',
|
|
||||||
userName: 'user3',
|
|
||||||
registrarName: 'registrar1',
|
|
||||||
timestamp: '2022-03-15T19:46:39.007',
|
|
||||||
details: 'All Domains under management exported as .csv file',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventType: 'Update Contact',
|
|
||||||
userName: 'user3',
|
|
||||||
registrarName: 'registrar1',
|
|
||||||
timestamp: '2022-03-15T19:46:39.007',
|
|
||||||
details: 'All Domains under management exported as .csv file',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
eventType: 'Delete Domain',
|
|
||||||
userName: 'user3',
|
|
||||||
registrarName: 'registrar1',
|
|
||||||
timestamp: '2022-03-15T19:46:39.007',
|
|
||||||
details: 'All Domains under management exported as .csv file',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-home',
|
selector: 'app-home',
|
||||||
templateUrl: './home.component.html',
|
templateUrl: './home.component.html',
|
||||||
styleUrls: ['./home.component.less'],
|
styleUrls: ['./home.component.scss'],
|
||||||
|
encapsulation: ViewEncapsulation.None,
|
||||||
})
|
})
|
||||||
export class HomeComponent {
|
export class HomeComponent {}
|
||||||
columns = [
|
|
||||||
{
|
|
||||||
columnDef: 'eventType',
|
|
||||||
header: 'Event Type',
|
|
||||||
cell: (record: ActivityRecord) => `${record.eventType}`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
columnDef: 'userName',
|
|
||||||
header: 'User',
|
|
||||||
cell: (record: ActivityRecord) => `${record.userName}`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
columnDef: 'registrarName',
|
|
||||||
header: 'Registrar',
|
|
||||||
cell: (record: ActivityRecord) => `${record.registrarName}`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
columnDef: 'timestamp',
|
|
||||||
header: 'Timestamp',
|
|
||||||
cell: (record: ActivityRecord) => `${record.timestamp}`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
columnDef: 'details',
|
|
||||||
header: 'Details',
|
|
||||||
cell: (record: ActivityRecord) => `${record.details}`,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
dataSource = MOCK_DATA;
|
|
||||||
displayedColumns = this.columns.map((c) => c.columnDef);
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
<mat-card>
|
||||||
|
<mat-card-content>
|
||||||
|
<div class="console-app__widget">
|
||||||
|
<div class="console-app__widget_left">
|
||||||
|
<mat-icon class="console-app__widget-icon">account_balance</mat-icon>
|
||||||
|
<h1 class="console-app__widget-title">Billing Info</h1>
|
||||||
|
<h4 class="secondary-text text-center">
|
||||||
|
View important billing and payments information.
|
||||||
|
</h4>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
|
@ -15,8 +15,9 @@
|
||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-registrars',
|
selector: '[app-billing-widget]',
|
||||||
templateUrl: './registrars.component.html',
|
templateUrl: './billing-widget.component.html',
|
||||||
styleUrls: ['./registrars.component.less'],
|
|
||||||
})
|
})
|
||||||
export default class RegistrarsComponent {}
|
export class BillingWidgetComponent {
|
||||||
|
constructor() {}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
<mat-card>
|
||||||
|
<mat-card-content>
|
||||||
|
<div class="console-app__widget">
|
||||||
|
<div class="console-app__widget_left">
|
||||||
|
<mat-icon class="console-app__widget-icon">call</mat-icon>
|
||||||
|
<h1 class="console-app__widget-title">Contact Support</h1>
|
||||||
|
<h4 class="secondary-text text-center">
|
||||||
|
View Google Registry support email and phone information
|
||||||
|
</h4>
|
||||||
|
</div>
|
||||||
|
<div class="console-app__widget_right">
|
||||||
|
<button mat-button color="primary" class="console-app__widget-link">
|
||||||
|
Give us a Call
|
||||||
|
</button>
|
||||||
|
<p class="secondary-text">
|
||||||
|
Call Google Registry support at +1 (404) 978 8419
|
||||||
|
</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
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
|
@ -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-contact-widget]',
|
||||||
|
templateUrl: './contact-widget.component.html',
|
||||||
|
})
|
||||||
|
export class ContactWidgetComponent {
|
||||||
|
constructor() {}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
<mat-card>
|
||||||
|
<mat-card-content>
|
||||||
|
<div class="console-app__widget">
|
||||||
|
<div class="console-app__widget_left">
|
||||||
|
<mat-icon class="console-app__widget-icon">view_list</mat-icon>
|
||||||
|
<h1 class="console-app__widget-title">Domains</h1>
|
||||||
|
<h4 class="secondary-text text-center">
|
||||||
|
Manage domain names and registry lock settings.
|
||||||
|
</h4>
|
||||||
|
</div>
|
||||||
|
<div class="console-app__widget_right">
|
||||||
|
<button mat-button color="primary" class="console-app__widget-link">
|
||||||
|
Create a Domain
|
||||||
|
</button>
|
||||||
|
<p class="secondary-text">Register a new domain name</p>
|
||||||
|
<button mat-button color="primary" class="console-app__widget-link">
|
||||||
|
View DUMs
|
||||||
|
</button>
|
||||||
|
<p class="secondary-text">
|
||||||
|
Download a csv of all domains under management
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
|
@ -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-domains-widget]',
|
||||||
|
templateUrl: './domains-widget.component.html',
|
||||||
|
})
|
||||||
|
export class DomainsWidgetComponent {
|
||||||
|
constructor() {}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
<mat-card>
|
||||||
|
<mat-card-content>
|
||||||
|
<div class="console-app__widget">
|
||||||
|
<div class="console-app__widget_left">
|
||||||
|
<mat-icon class="console-app__widget-icon">computer</mat-icon>
|
||||||
|
<h1 class="console-app__widget-title">EPP Console</h1>
|
||||||
|
<h4 class="secondary-text text-center">
|
||||||
|
Test run and execute EPP commands using XML files.
|
||||||
|
</h4>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
|
@ -11,3 +11,13 @@
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: '[app-epp-widget]',
|
||||||
|
templateUrl: './epp-widget.component.html',
|
||||||
|
})
|
||||||
|
export class EppWidgetComponent {
|
||||||
|
constructor() {}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
<mat-card class="console-app__widget-wrapper__wide">
|
||||||
|
<mat-card-content>
|
||||||
|
<div class="console-app__widget">
|
||||||
|
<div class="console-app__widget_left">
|
||||||
|
<mat-icon class="console-app__widget-icon">subject</mat-icon>
|
||||||
|
<h1 class="console-app__widget-title">Promotions</h1>
|
||||||
|
<h4 class="secondary-text text-center">
|
||||||
|
Manage Google Registry promotions and view onboarding process.
|
||||||
|
</h4>
|
||||||
|
</div>
|
||||||
|
<div class="console-app__widget_right">
|
||||||
|
<button mat-button color="primary" class="console-app__widget-link">
|
||||||
|
Manage Preferred Partner Program
|
||||||
|
</button>
|
||||||
|
<p class="secondary-text">
|
||||||
|
Onboard or view current preferred partner status
|
||||||
|
</p>
|
||||||
|
<button mat-button color="primary" class="console-app__widget-link">
|
||||||
|
Manage Registry Lock Program
|
||||||
|
</button>
|
||||||
|
<p class="secondary-text">
|
||||||
|
Onboard or view current registry lock status
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
|
@ -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-promotions-widget]',
|
||||||
|
templateUrl: './promotions-widget.component.html',
|
||||||
|
})
|
||||||
|
export class PromotionsWidgetComponent {
|
||||||
|
constructor() {}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
<mat-card>
|
||||||
|
<mat-card-content>
|
||||||
|
<div class="console-app__widget">
|
||||||
|
<div class="console-app__widget_left">
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
|
@ -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-resources-widget]',
|
||||||
|
templateUrl: './resources-widget.component.html',
|
||||||
|
})
|
||||||
|
export class ResourcesWidgetComponent {
|
||||||
|
constructor() {}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
<mat-card>
|
||||||
|
<mat-card-content>
|
||||||
|
<div class="console-app__widget">
|
||||||
|
<div class="console-app__widget_left">
|
||||||
|
<mat-icon class="console-app__widget-icon">list_alt</mat-icon>
|
||||||
|
<h1 class="console-app__widget-title">TLDs</h1>
|
||||||
|
<h4 class="secondary-text text-center">
|
||||||
|
View launch phase information for all onboarded and available TLDs.
|
||||||
|
</h4>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</mat-card-content>
|
||||||
|
</mat-card>
|
23
console-webapp/src/app/home/widgets/tlds-widget.component.ts
Normal file
23
console-webapp/src/app/home/widgets/tlds-widget.component.ts
Normal file
|
@ -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-tlds-widget]',
|
||||||
|
templateUrl: './tlds-widget.component.html',
|
||||||
|
})
|
||||||
|
export class TldsWidgetComponent {
|
||||||
|
constructor() {}
|
||||||
|
}
|
|
@ -44,6 +44,7 @@ import { CdkMenuModule } from '@angular/cdk/menu';
|
||||||
import { DialogModule } from '@angular/cdk/dialog';
|
import { DialogModule } from '@angular/cdk/dialog';
|
||||||
import { MatSidenavModule } from '@angular/material/sidenav';
|
import { MatSidenavModule } from '@angular/material/sidenav';
|
||||||
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
||||||
|
import { MatPaginatorModule } from '@angular/material/paginator';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
exports: [
|
exports: [
|
||||||
|
@ -79,6 +80,7 @@ import { MatSnackBarModule } from '@angular/material/snack-bar';
|
||||||
OverlayModule,
|
OverlayModule,
|
||||||
DialogModule,
|
DialogModule,
|
||||||
MatSnackBarModule,
|
MatSnackBarModule,
|
||||||
|
MatPaginatorModule,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class MaterialModule {}
|
export class MaterialModule {}
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
<div class="console-app__emty-registrar">
|
||||||
|
<h1>
|
||||||
|
<mat-icon class="console-app__emty-registrar-icon">block</mat-icon>
|
||||||
|
</h1>
|
||||||
|
<h1>No registrar selected</h1>
|
||||||
|
<h4 class="mat-body-2">Please select a registrar</h4>
|
||||||
|
</div>
|
|
@ -0,0 +1,17 @@
|
||||||
|
.console-app {
|
||||||
|
&__emty-registrar {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
top: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
|
||||||
|
&-icon {
|
||||||
|
transform: scale(3);
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,33 +13,32 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { RegistrarService } from './registrar.service';
|
|
||||||
import { ActivatedRoute, Router } from '@angular/router';
|
import { ActivatedRoute, Router } from '@angular/router';
|
||||||
|
import { RegistrarService } from './registrar.service';
|
||||||
|
import { Subscription } from 'rxjs';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-registrar',
|
selector: 'app-empty-registrar',
|
||||||
templateUrl: './registrar.component.html',
|
templateUrl: './emptyRegistrar.component.html',
|
||||||
styleUrls: ['./registrar.component.less'],
|
styleUrls: ['./emptyRegistrar.component.scss'],
|
||||||
})
|
})
|
||||||
export class RegistrarComponent {
|
export class EmptyRegistrar {
|
||||||
private lastActiveRegistrarId: string;
|
private registrarIdChangeSubscription?: Subscription;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
protected registrarService: RegistrarService,
|
protected registrarService: RegistrarService,
|
||||||
private router: Router
|
private router: Router
|
||||||
) {
|
) {
|
||||||
this.lastActiveRegistrarId = registrarService.activeRegistrarId;
|
this.registrarIdChangeSubscription =
|
||||||
|
registrarService.activeRegistrarIdChange.subscribe((newRegistrarId) => {
|
||||||
|
if (newRegistrarId) {
|
||||||
|
this.router.navigate([this.route.snapshot.paramMap.get('nextUrl')]);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ngDoCheck() {
|
ngOnDestroy() {
|
||||||
if (
|
this.registrarIdChangeSubscription?.unsubscribe();
|
||||||
this.registrarService.activeRegistrarId &&
|
|
||||||
this.registrarService.activeRegistrarId !== this.lastActiveRegistrarId &&
|
|
||||||
this.route.snapshot.paramMap.get('nextUrl')
|
|
||||||
) {
|
|
||||||
this.lastActiveRegistrarId = this.registrarService.activeRegistrarId;
|
|
||||||
this.router.navigate([this.route.snapshot.paramMap.get('nextUrl')]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
<div class="console-app__registrar">
|
||||||
|
<div>
|
||||||
|
<mat-form-field class="mat-form-field-density-5" appearance="fill">
|
||||||
|
<mat-label>Registrar</mat-label>
|
||||||
|
<mat-select
|
||||||
|
[ngModel]="registrarService.activeRegistrarId"
|
||||||
|
(selectionChange)="registrarService.updateRegistrar($event.value)"
|
||||||
|
>
|
||||||
|
<mat-option
|
||||||
|
*ngFor="let registrar of registrarService.registrars"
|
||||||
|
[value]="registrar.registrarName"
|
||||||
|
>
|
||||||
|
{{ registrar.registrarName }}
|
||||||
|
</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -0,0 +1,18 @@
|
||||||
|
.console-app {
|
||||||
|
&__registrar {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: baseline;
|
||||||
|
// Fix for angular v15 label issue
|
||||||
|
// https://github.com/angular/components/issues/26579
|
||||||
|
.mat-mdc-floating-label {
|
||||||
|
display: inline !important;
|
||||||
|
}
|
||||||
|
.mat-mdc-select-arrow-wrapper {
|
||||||
|
transform: translateY(0) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&__title {
|
||||||
|
margin-right: 1rem;
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,18 +14,18 @@
|
||||||
|
|
||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
import RegistrarsComponent from './registrars.component';
|
import { RegistrarSelectorComponent } from './registrar-selector.component';
|
||||||
|
|
||||||
describe('RegistrarsComponent', () => {
|
describe('RegistrarSelectorComponent', () => {
|
||||||
let component: RegistrarsComponent;
|
let component: RegistrarSelectorComponent;
|
||||||
let fixture: ComponentFixture<RegistrarsComponent>;
|
let fixture: ComponentFixture<RegistrarSelectorComponent>;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
declarations: [RegistrarsComponent],
|
declarations: [RegistrarSelectorComponent],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
|
|
||||||
fixture = TestBed.createComponent(RegistrarsComponent);
|
fixture = TestBed.createComponent(RegistrarSelectorComponent);
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance;
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
});
|
});
|
|
@ -0,0 +1,25 @@
|
||||||
|
// 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';
|
||||||
|
import { RegistrarService } from './registrar.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-registrar-selector',
|
||||||
|
templateUrl: './registrar-selector.component.html',
|
||||||
|
styleUrls: ['./registrar-selector.component.scss'],
|
||||||
|
})
|
||||||
|
export class RegistrarSelectorComponent {
|
||||||
|
constructor(protected registrarService: RegistrarService) {}
|
||||||
|
}
|
|
@ -1,17 +0,0 @@
|
||||||
<div class="console-app__registrar">
|
|
||||||
<h4 class="console-app__title">
|
|
||||||
{{ registrarService.activeRegistrarId === "" ? "Select" : "Switch" }}
|
|
||||||
registrar:
|
|
||||||
</h4>
|
|
||||||
<mat-form-field>
|
|
||||||
<mat-label>Registrar</mat-label>
|
|
||||||
<mat-select [(ngModel)]="registrarService.activeRegistrarId">
|
|
||||||
<mat-option
|
|
||||||
*ngFor="let registrar of registrarService.registrars"
|
|
||||||
[value]="registrar"
|
|
||||||
>
|
|
||||||
{{ registrar }}
|
|
||||||
</mat-option>
|
|
||||||
</mat-select>
|
|
||||||
</mat-form-field>
|
|
||||||
</div>
|
|
|
@ -1,11 +0,0 @@
|
||||||
.console-app {
|
|
||||||
&__registrar {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
margin-top: 1rem;
|
|
||||||
}
|
|
||||||
&__title {
|
|
||||||
margin-right: 1rem;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -29,6 +29,6 @@ export class RegistrarGuard {
|
||||||
if (this.registrarService.activeRegistrarId) {
|
if (this.registrarService.activeRegistrarId) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return this.router.navigate([`/registrars`, { nextUrl: state.url }]);
|
return this.router.navigate([`/empty-registrar`, { nextUrl: state.url }]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,16 +14,59 @@
|
||||||
|
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { BackendService } from '../shared/services/backend.service';
|
import { BackendService } from '../shared/services/backend.service';
|
||||||
|
import { Subject } from 'rxjs';
|
||||||
|
import {
|
||||||
|
GlobalLoader,
|
||||||
|
GlobalLoaderService,
|
||||||
|
} from '../shared/services/globalLoader.service';
|
||||||
|
|
||||||
|
interface Address {
|
||||||
|
street?: string[];
|
||||||
|
city?: string;
|
||||||
|
countryCode?: string;
|
||||||
|
zip?: string;
|
||||||
|
state?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Registrar {
|
||||||
|
allowedTlds?: string[];
|
||||||
|
ipAddressAllowList?: string[];
|
||||||
|
emailAddress?: string;
|
||||||
|
billingAccountMap?: object;
|
||||||
|
driveFolderId?: string;
|
||||||
|
ianaIdentifier?: number;
|
||||||
|
icannReferralEmail?: string;
|
||||||
|
localizedAddress?: Address;
|
||||||
|
registrarId: string;
|
||||||
|
registrarName: string;
|
||||||
|
registryLockAllowed?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root',
|
providedIn: 'root',
|
||||||
})
|
})
|
||||||
export class RegistrarService {
|
export class RegistrarService implements GlobalLoader {
|
||||||
activeRegistrarId: string = '';
|
activeRegistrarId: string = '';
|
||||||
registrars: string[] = [];
|
registrars: Registrar[] = [];
|
||||||
constructor(private backend: BackendService) {
|
activeRegistrarIdChange: Subject<string> = new Subject<string>();
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private backend: BackendService,
|
||||||
|
private globalLoader: GlobalLoaderService
|
||||||
|
) {
|
||||||
this.backend.getRegistrars().subscribe((r) => {
|
this.backend.getRegistrars().subscribe((r) => {
|
||||||
|
this.globalLoader.stopGlobalLoader(this);
|
||||||
this.registrars = r;
|
this.registrars = r;
|
||||||
});
|
});
|
||||||
|
this.globalLoader.startGlobalLoader(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public updateRegistrar(registrarId: string) {
|
||||||
|
this.activeRegistrarId = registrarId;
|
||||||
|
this.activeRegistrarIdChange.next(registrarId);
|
||||||
|
}
|
||||||
|
|
||||||
|
loadingTimeout() {
|
||||||
|
// TODO: Decide what to do when timeout happens
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
<div class="console-app__registrars">
|
||||||
|
<table
|
||||||
|
mat-table
|
||||||
|
[dataSource]="registrarService.registrars"
|
||||||
|
class="mat-elevation-z8"
|
||||||
|
>
|
||||||
|
<ng-container
|
||||||
|
*ngFor="let column of columns"
|
||||||
|
[matColumnDef]="column.columnDef"
|
||||||
|
>
|
||||||
|
<th mat-header-cell *matHeaderCellDef>
|
||||||
|
{{ column.header }}
|
||||||
|
</th>
|
||||||
|
<td mat-cell *matCellDef="let row" [innerHTML]="column.cell(row)"></td>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||||
|
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
|
||||||
|
</table>
|
||||||
|
<mat-paginator
|
||||||
|
class="mat-elevation-z8"
|
||||||
|
[pageSizeOptions]="[5, 10, 20]"
|
||||||
|
showFirstLastButtons
|
||||||
|
></mat-paginator>
|
||||||
|
</div>
|
|
@ -0,0 +1,5 @@
|
||||||
|
.console-app {
|
||||||
|
&__registrars {
|
||||||
|
margin-top: 1.5rem;
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
import { RegistrarComponent } from './registrar.component';
|
import { RegistrarComponent } from './registrarsTable.component';
|
||||||
import { BackendService } from '../shared/services/backend.service';
|
import { BackendService } from '../shared/services/backend.service';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
import { HttpClientTestingModule } from '@angular/common/http/testing';
|
import { HttpClientTestingModule } from '@angular/common/http/testing';
|
|
@ -0,0 +1,75 @@
|
||||||
|
// 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';
|
||||||
|
import { Registrar, RegistrarService } from './registrar.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-registrar',
|
||||||
|
templateUrl: './registrarsTable.component.html',
|
||||||
|
styleUrls: ['./registrarsTable.component.scss'],
|
||||||
|
})
|
||||||
|
export class RegistrarComponent {
|
||||||
|
columns = [
|
||||||
|
{
|
||||||
|
columnDef: 'registrarId',
|
||||||
|
header: 'Registrar Id',
|
||||||
|
cell: (record: Registrar) => `${record.registrarId || ''}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
columnDef: 'registrarName',
|
||||||
|
header: 'Name',
|
||||||
|
cell: (record: Registrar) => `${record.registrarName || ''}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
columnDef: 'allowedTlds',
|
||||||
|
header: 'TLDs',
|
||||||
|
cell: (record: Registrar) => `${(record.allowedTlds || []).join(', ')}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
columnDef: 'emailAddress',
|
||||||
|
header: 'Username',
|
||||||
|
cell: (record: Registrar) => `${record.emailAddress || ''}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
columnDef: 'ianaIdentifier',
|
||||||
|
header: 'IANA ID',
|
||||||
|
cell: (record: Registrar) => `${record.ianaIdentifier || ''}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
columnDef: 'billingAccountMap',
|
||||||
|
header: 'Billing Accounts',
|
||||||
|
cell: (record: Registrar) =>
|
||||||
|
// @ts-ignore - completely legit line, but TS keeps complaining
|
||||||
|
`${Object.entries(record.billingAccountMap).reduce(
|
||||||
|
(acc, [key, val]) => {
|
||||||
|
return `${acc}${key}=${val}<br/>`;
|
||||||
|
},
|
||||||
|
''
|
||||||
|
)}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
columnDef: 'registryLockAllowed',
|
||||||
|
header: 'Registry Lock',
|
||||||
|
cell: (record: Registrar) => `${record.registryLockAllowed}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
columnDef: 'driveId',
|
||||||
|
header: 'Drive ID',
|
||||||
|
cell: (record: Registrar) => `${record.driveFolderId || ''}`,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
displayedColumns = this.columns.map((c) => c.columnDef);
|
||||||
|
constructor(protected registrarService: RegistrarService) {}
|
||||||
|
}
|
|
@ -2,6 +2,15 @@
|
||||||
<mat-progress-bar mode="indeterminate"></mat-progress-bar>
|
<mat-progress-bar mode="indeterminate"></mat-progress-bar>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="!loading">
|
<div *ngIf="!loading">
|
||||||
|
<div
|
||||||
|
class="contact__empty-contacts"
|
||||||
|
*ngIf="contactService.contacts.length === 0"
|
||||||
|
>
|
||||||
|
<mat-icon class="contact__empty-contacts-icon secondary-text"
|
||||||
|
>apps_outage</mat-icon
|
||||||
|
>
|
||||||
|
<h1>No contacts found</h1>
|
||||||
|
</div>
|
||||||
<div *ngFor="let group of groupedData">
|
<div *ngFor="let group of groupedData">
|
||||||
<div class="contact__cards-wrapper" *ngIf="group.contacts.length">
|
<div class="contact__cards-wrapper" *ngIf="group.contacts.length">
|
||||||
<h3>{{ group.label }}s</h3>
|
<h3>{{ group.label }}s</h3>
|
||||||
|
|
|
@ -37,6 +37,18 @@
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
margin: 2rem 0;
|
margin: 2rem 0;
|
||||||
}
|
}
|
||||||
|
&__empty-contacts {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
&__empty-contacts-icon {
|
||||||
|
width: 4rem;
|
||||||
|
height: 4rem;
|
||||||
|
font-size: 4rem;
|
||||||
|
margin-top: 1.5rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.contact-details {
|
.contact-details {
|
||||||
&__input {
|
&__input {
|
|
@ -77,7 +77,7 @@ class ContactDetailsEventsResponder {
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-contact-details-dialog',
|
selector: 'app-contact-details-dialog',
|
||||||
templateUrl: 'contact-details.component.html',
|
templateUrl: 'contact-details.component.html',
|
||||||
styleUrls: ['./contact.component.less'],
|
styleUrls: ['./contact.component.scss'],
|
||||||
})
|
})
|
||||||
export class ContactDetailsDialogComponent {
|
export class ContactDetailsDialogComponent {
|
||||||
contact: Contact;
|
contact: Contact;
|
||||||
|
@ -140,7 +140,7 @@ export class ContactDetailsDialogComponent {
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-contact',
|
selector: 'app-contact',
|
||||||
templateUrl: './contact.component.html',
|
templateUrl: './contact.component.html',
|
||||||
styleUrls: ['./contact.component.less'],
|
styleUrls: ['./contact.component.scss'],
|
||||||
})
|
})
|
||||||
export default class ContactComponent {
|
export default class ContactComponent {
|
||||||
loading: boolean = false;
|
loading: boolean = false;
|
||||||
|
@ -158,7 +158,7 @@ export default class ContactComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
public get groupedData() {
|
public get groupedData() {
|
||||||
return this.contactService.contacts.reduce((acc, contact) => {
|
return this.contactService.contacts?.reduce((acc, contact) => {
|
||||||
contact.types.forEach((type) => {
|
contact.types.forEach((type) => {
|
||||||
acc
|
acc
|
||||||
.find((group: GroupedContacts) => group.value === type)
|
.find((group: GroupedContacts) => group.value === type)
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
<p>registrars component works!</p>
|
|
|
@ -20,7 +20,7 @@ import { MatSnackBar } from '@angular/material/snack-bar';
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-security',
|
selector: 'app-security',
|
||||||
templateUrl: './security.component.html',
|
templateUrl: './security.component.html',
|
||||||
styleUrls: ['./security.component.less'],
|
styleUrls: ['./security.component.scss'],
|
||||||
providers: [SecurityService],
|
providers: [SecurityService],
|
||||||
})
|
})
|
||||||
export default class SecurityComponent {
|
export default class SecurityComponent {
|
||||||
|
|
|
@ -17,7 +17,7 @@ import { Component, ViewEncapsulation } from '@angular/core';
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-settings',
|
selector: 'app-settings',
|
||||||
templateUrl: './settings.component.html',
|
templateUrl: './settings.component.html',
|
||||||
styleUrls: ['./settings.component.less'],
|
styleUrls: ['./settings.component.scss'],
|
||||||
encapsulation: ViewEncapsulation.None,
|
encapsulation: ViewEncapsulation.None,
|
||||||
})
|
})
|
||||||
export class SettingsComponent {}
|
export class SettingsComponent {}
|
||||||
|
|
|
@ -17,6 +17,6 @@ import { Component } from '@angular/core';
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-users',
|
selector: 'app-users',
|
||||||
templateUrl: './users.component.html',
|
templateUrl: './users.component.html',
|
||||||
styleUrls: ['./users.component.less'],
|
styleUrls: ['./users.component.scss'],
|
||||||
})
|
})
|
||||||
export default class UsersComponent {}
|
export default class UsersComponent {}
|
||||||
|
|
|
@ -17,6 +17,6 @@ import { Component } from '@angular/core';
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-whois',
|
selector: 'app-whois',
|
||||||
templateUrl: './whois.component.html',
|
templateUrl: './whois.component.html',
|
||||||
styleUrls: ['./whois.component.less'],
|
styleUrls: ['./whois.component.scss'],
|
||||||
})
|
})
|
||||||
export default class WhoisComponent {}
|
export default class WhoisComponent {}
|
||||||
|
|
|
@ -18,6 +18,7 @@ import { catchError, Observable, of } from 'rxjs';
|
||||||
import { SecuritySettingsBackendModel } from 'src/app/settings/security/security.service';
|
import { SecuritySettingsBackendModel } from 'src/app/settings/security/security.service';
|
||||||
|
|
||||||
import { Contact } from '../../settings/contact/contact.service';
|
import { Contact } from '../../settings/contact/contact.service';
|
||||||
|
import { Registrar } from '../../registrar/registrar.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class BackendService {
|
export class BackendService {
|
||||||
|
@ -60,10 +61,10 @@ export class BackendService {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getRegistrars(): Observable<string[]> {
|
getRegistrars(): Observable<Registrar[]> {
|
||||||
return this.http
|
return this.http
|
||||||
.get<string[]>('/console-api/registrars')
|
.get<Registrar[]>('/console-api/registrars')
|
||||||
.pipe(catchError((err) => this.errorCatcher<string[]>(err)));
|
.pipe(catchError((err) => this.errorCatcher<Registrar[]>(err)));
|
||||||
}
|
}
|
||||||
|
|
||||||
getSecuritySettings(
|
getSecuritySettings(
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
// 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, Subscription, timeout } from 'rxjs';
|
||||||
|
|
||||||
|
export interface GlobalLoader {
|
||||||
|
loadingTimeout: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class responsible for global application loading indicator
|
||||||
|
*
|
||||||
|
* <p>Only to be used for when the activity should indicate that the entire application is busy
|
||||||
|
* For instance - when initial user information is loading, which is crucial for any subsequent
|
||||||
|
* interaction with the application
|
||||||
|
*/
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root',
|
||||||
|
})
|
||||||
|
export class GlobalLoaderService {
|
||||||
|
private static readonly TIMEOUT_MS = 3000;
|
||||||
|
private loaders = new Map<GlobalLoader, Subscription>();
|
||||||
|
public isLoading: boolean = false;
|
||||||
|
|
||||||
|
private syncLoading() {
|
||||||
|
this.isLoading = this.loaders.size > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
startGlobalLoader(c: GlobalLoader) {
|
||||||
|
const subscription = new Observable(() => {})
|
||||||
|
.pipe(timeout(GlobalLoaderService.TIMEOUT_MS))
|
||||||
|
.subscribe({
|
||||||
|
error: () => {
|
||||||
|
this.loaders.delete(c);
|
||||||
|
c.loadingTimeout();
|
||||||
|
this.syncLoading();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
this.loaders.set(c, subscription);
|
||||||
|
this.syncLoading();
|
||||||
|
}
|
||||||
|
|
||||||
|
stopGlobalLoader(c: GlobalLoader) {
|
||||||
|
this.loaders.get(c)?.unsubscribe();
|
||||||
|
this.loaders.delete(c);
|
||||||
|
this.syncLoading();
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,6 +17,6 @@ import { Component } from '@angular/core';
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-tlds',
|
selector: 'app-tlds',
|
||||||
templateUrl: './tlds.component.html',
|
templateUrl: './tlds.component.html',
|
||||||
styleUrls: ['./tlds.component.less'],
|
styleUrls: ['./tlds.component.scss'],
|
||||||
})
|
})
|
||||||
export class TldsComponent {}
|
export class TldsComponent {}
|
||||||
|
|
63
console-webapp/src/styles.scss
Normal file
63
console-webapp/src/styles.scss
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
// Copyright 2022 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.
|
||||||
|
@use "@angular/material" as mat;
|
||||||
|
@import "app/registrar/registrar-selector.component.scss";
|
||||||
|
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
font-family: Roboto, "Helvetica Neue", sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.console-app {
|
||||||
|
&__widget {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
&-wrapper__wide {
|
||||||
|
grid-column: span 2;
|
||||||
|
}
|
||||||
|
&-link {
|
||||||
|
padding: 0 !important;
|
||||||
|
text-align: left;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
&-title {
|
||||||
|
color: var(--primary) !important;
|
||||||
|
}
|
||||||
|
&-icon {
|
||||||
|
font-size: 4rem;
|
||||||
|
line-height: 4rem;
|
||||||
|
height: 4rem !important;
|
||||||
|
width: 4rem !important;
|
||||||
|
}
|
||||||
|
&_left {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
&_right {
|
||||||
|
flex: 1;
|
||||||
|
border-left: 1px solid var(--secondary);
|
||||||
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
69
console-webapp/src/theme.scss
Normal file
69
console-webapp/src/theme.scss
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
@use "sass:map";
|
||||||
|
@use "@angular/material" as mat;
|
||||||
|
|
||||||
|
/** Copied from docs section **/
|
||||||
|
|
||||||
|
// Include the common styles for Angular Material. We include this here so that you only
|
||||||
|
// have to load a single css file for Angular Material in your app.
|
||||||
|
// Be sure that you only ever include this mixin once!
|
||||||
|
@include mat.core();
|
||||||
|
|
||||||
|
// Define the palettes for your theme using the Material Design palettes available in palette.scss
|
||||||
|
// (imported above). For each palette, you can optionally specify a default, lighter, and darker
|
||||||
|
// hue. Available color palettes: https://material.io/design/color/
|
||||||
|
$theme-primary: mat.define-palette(mat.$indigo-palette);
|
||||||
|
$theme-accent: mat.define-palette(mat.$pink-palette, A200, A100, A400);
|
||||||
|
|
||||||
|
// The warn palette is optional (defaults to red).
|
||||||
|
$theme-warn: mat.define-palette(mat.$red-palette);
|
||||||
|
|
||||||
|
// Create the theme object. A theme consists of configurations for individual
|
||||||
|
// theming systems such as "color" or "typography".
|
||||||
|
$theme: mat.define-light-theme(
|
||||||
|
(
|
||||||
|
color: (
|
||||||
|
primary: $theme-primary,
|
||||||
|
accent: $theme-accent,
|
||||||
|
warn: $theme-warn,
|
||||||
|
),
|
||||||
|
density: 0,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
/** Application specific section **/
|
||||||
|
|
||||||
|
@mixin form-field-density($density) {
|
||||||
|
$field-typography: mat.define-typography-config(
|
||||||
|
$body-1: mat.define-typography-level(12px, 24px, 400),
|
||||||
|
);
|
||||||
|
@include mat.typography-level($field-typography, "body-1");
|
||||||
|
@include mat.form-field-density($density);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define lowest possible density class to be used in application
|
||||||
|
// In the same manner -1...-5 classes can be defined
|
||||||
|
.mat-form-field-density-5 {
|
||||||
|
@include form-field-density(-5);
|
||||||
|
}
|
||||||
|
|
||||||
|
$foreground: map.merge($theme, mat.$light-theme-foreground-palette);
|
||||||
|
|
||||||
|
// Access and define a class with secondary color exposed
|
||||||
|
.secondary-text {
|
||||||
|
color: map.get($foreground, "secondary-text");
|
||||||
|
}
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--primary: #{mat.get-color-from-palette($theme-primary, 500)};
|
||||||
|
--secondary: #{map.get($foreground, "secondary-text")};
|
||||||
|
}
|
||||||
|
|
||||||
|
@include mat.all-component-themes($theme);
|
||||||
|
@import "@angular/material/theming";
|
||||||
|
|
||||||
|
// Define application specific typography settings, font-family, etc
|
||||||
|
$typography-configuration: mat-typography-config(
|
||||||
|
$font-family: 'Roboto, "Helvetica Neue", sans-serif',
|
||||||
|
);
|
||||||
|
|
||||||
|
@include angular-material-typography($typography-configuration);
|
Loading…
Add table
Add a link
Reference in a new issue