Improve console accessibility (#2649)
@@ -7,6 +7,11 @@
|
|||||||
></mat-progress-bar>
|
></mat-progress-bar>
|
||||||
</div>
|
</div>
|
||||||
<mat-sidenav-container class="console-app__container">
|
<mat-sidenav-container class="console-app__container">
|
||||||
|
<mat-sidenav-content class="console-app__content-wrapper">
|
||||||
|
<div class="console-app__content" role="main">
|
||||||
|
<router-outlet></router-outlet>
|
||||||
|
</div>
|
||||||
|
</mat-sidenav-content>
|
||||||
<mat-sidenav
|
<mat-sidenav
|
||||||
[mode]="breakpointObserver.isMobileView() ? 'over' : 'side'"
|
[mode]="breakpointObserver.isMobileView() ? 'over' : 'side'"
|
||||||
[opened]="!breakpointObserver.isMobileView()"
|
[opened]="!breakpointObserver.isMobileView()"
|
||||||
@@ -15,10 +20,5 @@
|
|||||||
>
|
>
|
||||||
<app-navigation />
|
<app-navigation />
|
||||||
</mat-sidenav>
|
</mat-sidenav>
|
||||||
<mat-sidenav-content class="console-app__content-wrapper">
|
|
||||||
<div class="console-app__content">
|
|
||||||
<router-outlet></router-outlet>
|
|
||||||
</div>
|
|
||||||
</mat-sidenav-content>
|
|
||||||
</mat-sidenav-container>
|
</mat-sidenav-container>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -20,12 +20,18 @@ import { AppComponent } from './app.component';
|
|||||||
import { MaterialModule } from './material.module';
|
import { MaterialModule } from './material.module';
|
||||||
import { BackendService } from './shared/services/backend.service';
|
import { BackendService } from './shared/services/backend.service';
|
||||||
import { AppRoutingModule } from './app-routing.module';
|
import { AppRoutingModule } from './app-routing.module';
|
||||||
|
import { AppModule } from './app.module';
|
||||||
|
|
||||||
describe('AppComponent', () => {
|
describe('AppComponent', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
declarations: [AppComponent],
|
declarations: [AppComponent],
|
||||||
imports: [MaterialModule, BrowserAnimationsModule, AppRoutingModule],
|
imports: [
|
||||||
|
MaterialModule,
|
||||||
|
BrowserAnimationsModule,
|
||||||
|
AppRoutingModule,
|
||||||
|
AppModule,
|
||||||
|
],
|
||||||
providers: [
|
providers: [
|
||||||
BackendService,
|
BackendService,
|
||||||
provideHttpClient(),
|
provideHttpClient(),
|
||||||
@@ -36,6 +42,7 @@ describe('AppComponent', () => {
|
|||||||
|
|
||||||
it('should create the app', () => {
|
it('should create the app', () => {
|
||||||
const fixture = TestBed.createComponent(AppComponent);
|
const fixture = TestBed.createComponent(AppComponent);
|
||||||
|
fixture.detectChanges();
|
||||||
const app = fixture.componentInstance;
|
const app = fixture.componentInstance;
|
||||||
expect(app).toBeTruthy();
|
expect(app).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import { MaterialModule } from '../material.module';
|
|||||||
import { BackendService } from '../shared/services/backend.service';
|
import { BackendService } from '../shared/services/backend.service';
|
||||||
import { DomainListComponent } from './domainList.component';
|
import { DomainListComponent } from './domainList.component';
|
||||||
import { FormsModule } from '@angular/forms';
|
import { FormsModule } from '@angular/forms';
|
||||||
|
import { AppModule } from '../app.module';
|
||||||
|
|
||||||
describe('DomainListComponent', () => {
|
describe('DomainListComponent', () => {
|
||||||
let component: DomainListComponent;
|
let component: DomainListComponent;
|
||||||
@@ -29,7 +30,12 @@ describe('DomainListComponent', () => {
|
|||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
declarations: [DomainListComponent],
|
declarations: [DomainListComponent],
|
||||||
imports: [MaterialModule, BrowserAnimationsModule, FormsModule],
|
imports: [
|
||||||
|
MaterialModule,
|
||||||
|
BrowserAnimationsModule,
|
||||||
|
FormsModule,
|
||||||
|
AppModule,
|
||||||
|
],
|
||||||
providers: [
|
providers: [
|
||||||
BackendService,
|
BackendService,
|
||||||
provideHttpClient(),
|
provideHttpClient(),
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
<a
|
<a
|
||||||
[routerLink]="'/home'"
|
[routerLink]="'/home'"
|
||||||
routerLinkActive="active"
|
routerLinkActive="active"
|
||||||
|
aria-label="Google Registry logo"
|
||||||
class="console-app__logo"
|
class="console-app__logo"
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
|
|||||||
@@ -17,6 +17,12 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|||||||
import { HeaderComponent } from './header.component';
|
import { HeaderComponent } from './header.component';
|
||||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { MaterialModule } from '../material.module';
|
import { MaterialModule } from '../material.module';
|
||||||
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
import { AppModule, SelectedRegistrarModule } from '../app.module';
|
||||||
|
import { AppRoutingModule } from '../app-routing.module';
|
||||||
|
import { BackendService } from '../shared/services/backend.service';
|
||||||
|
import { provideHttpClient } from '@angular/common/http';
|
||||||
|
import { provideHttpClientTesting } from '@angular/common/http/testing';
|
||||||
|
|
||||||
describe('HeaderComponent', () => {
|
describe('HeaderComponent', () => {
|
||||||
let component: HeaderComponent;
|
let component: HeaderComponent;
|
||||||
@@ -24,7 +30,19 @@ describe('HeaderComponent', () => {
|
|||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
imports: [MaterialModule, BrowserAnimationsModule],
|
imports: [
|
||||||
|
SelectedRegistrarModule,
|
||||||
|
MaterialModule,
|
||||||
|
BrowserAnimationsModule,
|
||||||
|
AppRoutingModule,
|
||||||
|
AppModule,
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
BackendService,
|
||||||
|
{ provide: ActivatedRoute, useValue: {} as ActivatedRoute },
|
||||||
|
provideHttpClient(),
|
||||||
|
provideHttpClientTesting(),
|
||||||
|
],
|
||||||
declarations: [HeaderComponent],
|
declarations: [HeaderComponent],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|||||||
|
|
||||||
import { HomeComponent } from './home.component';
|
import { HomeComponent } from './home.component';
|
||||||
import { MaterialModule } from '../material.module';
|
import { MaterialModule } from '../material.module';
|
||||||
|
import { AppModule } from '../app.module';
|
||||||
|
|
||||||
describe('HomeComponent', () => {
|
describe('HomeComponent', () => {
|
||||||
let component: HomeComponent;
|
let component: HomeComponent;
|
||||||
@@ -23,7 +24,7 @@ describe('HomeComponent', () => {
|
|||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
imports: [MaterialModule],
|
imports: [MaterialModule, AppModule],
|
||||||
declarations: [HomeComponent],
|
declarations: [HomeComponent],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,9 @@
|
|||||||
<mat-tree-node
|
<mat-tree-node
|
||||||
*matTreeNodeDef="let node"
|
*matTreeNodeDef="let node"
|
||||||
matTreeNodeToggle
|
matTreeNodeToggle
|
||||||
|
tabindex="0"
|
||||||
(click)="onClick(node)"
|
(click)="onClick(node)"
|
||||||
|
(keyup.enter)="onClick(node)"
|
||||||
[class.active]="router.url.includes(node.path)"
|
[class.active]="router.url.includes(node.path)"
|
||||||
[elementId]="getElementId(node)"
|
[elementId]="getElementId(node)"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
<div class="console-app__registrar-view">
|
<div
|
||||||
|
class="console-app__registrar-view"
|
||||||
|
cdkTrapFocus
|
||||||
|
[cdkTrapFocusAutoCapture]="true"
|
||||||
|
>
|
||||||
<h1 class="mat-headline-4">Registrars</h1>
|
<h1 class="mat-headline-4">Registrars</h1>
|
||||||
<mat-divider></mat-divider>
|
<mat-divider></mat-divider>
|
||||||
<div class="console-app__registrar-view-content">
|
<div class="console-app__registrar-view-content">
|
||||||
|
|||||||
@@ -59,6 +59,8 @@
|
|||||||
<mat-row
|
<mat-row
|
||||||
*matRowDef="let row; columns: displayedColumns"
|
*matRowDef="let row; columns: displayedColumns"
|
||||||
(click)="openDetails(row.registrarId)"
|
(click)="openDetails(row.registrarId)"
|
||||||
|
tabindex="0"
|
||||||
|
(keyup.enter)="openDetails(row.registrarId)"
|
||||||
></mat-row>
|
></mat-row>
|
||||||
</mat-table>
|
</mat-table>
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,9 @@
|
|||||||
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
|
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
|
||||||
<mat-row
|
<mat-row
|
||||||
*matRowDef="let row; columns: displayedColumns"
|
*matRowDef="let row; columns: displayedColumns"
|
||||||
|
tabindex="0"
|
||||||
(click)="openDetails(row)"
|
(click)="openDetails(row)"
|
||||||
|
(keyup.enter)="openDetails(row)"
|
||||||
></mat-row>
|
></mat-row>
|
||||||
</mat-table>
|
</mat-table>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,9 @@
|
|||||||
<div class="console-app__contact" *ngIf="contactService.contactInEdit">
|
<div
|
||||||
|
class="console-app__contact"
|
||||||
|
*ngIf="contactService.contactInEdit"
|
||||||
|
cdkTrapFocus
|
||||||
|
[cdkTrapFocusAutoCapture]="true"
|
||||||
|
>
|
||||||
<div class="console-app__contact-controls">
|
<div class="console-app__contact-controls">
|
||||||
<button
|
<button
|
||||||
mat-icon-button
|
mat-icon-button
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
<div class="settings-security__edit-password">
|
<div
|
||||||
|
class="settings-security__edit-password"
|
||||||
|
cdkTrapFocus
|
||||||
|
[cdkTrapFocusAutoCapture]="true"
|
||||||
|
>
|
||||||
<p>
|
<p>
|
||||||
<button
|
<button
|
||||||
mat-icon-button
|
mat-icon-button
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ describe('SecurityComponent', () => {
|
|||||||
fetchSecurityDetailsSpy =
|
fetchSecurityDetailsSpy =
|
||||||
securityServiceSpy.fetchSecurityDetails.and.returnValue(of());
|
securityServiceSpy.fetchSecurityDetails.and.returnValue(of());
|
||||||
|
|
||||||
saveSpy = securityServiceSpy.saveChanges;
|
saveSpy = securityServiceSpy.saveChanges.and.returnValue(of());
|
||||||
|
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
declarations: [SecurityEditComponent, SecurityComponent],
|
declarations: [SecurityEditComponent, SecurityComponent],
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
<div class="settings-security__edit">
|
<div
|
||||||
|
class="settings-security__edit"
|
||||||
|
cdkTrapFocus
|
||||||
|
[cdkTrapFocusAutoCapture]="true"
|
||||||
|
>
|
||||||
<h1>IP Allowlist</h1>
|
<h1>IP Allowlist</h1>
|
||||||
<p>
|
<p>
|
||||||
Restrict access to EPP production servers to the following IP/IPv6
|
Restrict access to EPP production servers to the following IP/IPv6
|
||||||
|
|||||||
@@ -10,22 +10,28 @@
|
|||||||
<a
|
<a
|
||||||
mat-tab-link
|
mat-tab-link
|
||||||
routerLink="contact"
|
routerLink="contact"
|
||||||
routerLinkActive="active-link"
|
routerLinkActive
|
||||||
queryParamsHandling="merge"
|
queryParamsHandling="merge"
|
||||||
|
#rla="routerLinkActive"
|
||||||
|
[active]="rla.isActive"
|
||||||
>Contacts</a
|
>Contacts</a
|
||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
mat-tab-link
|
mat-tab-link
|
||||||
routerLink="whois"
|
routerLink="whois"
|
||||||
routerLinkActive="active-link"
|
routerLinkActive
|
||||||
queryParamsHandling="merge"
|
queryParamsHandling="merge"
|
||||||
|
#rla2="routerLinkActive"
|
||||||
|
[active]="rla2.isActive"
|
||||||
>WHOIS Info</a
|
>WHOIS Info</a
|
||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
mat-tab-link
|
mat-tab-link
|
||||||
routerLink="security"
|
routerLink="security"
|
||||||
routerLinkActive="active-link"
|
routerLinkActive
|
||||||
queryParamsHandling="merge"
|
queryParamsHandling="merge"
|
||||||
|
#rla3="routerLinkActive"
|
||||||
|
[active]="rla3.isActive"
|
||||||
>Security</a
|
>Security</a
|
||||||
>
|
>
|
||||||
</nav>
|
</nav>
|
||||||
|
|||||||
@@ -13,14 +13,6 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
.console-settings {
|
.console-settings {
|
||||||
.mdc-tab {
|
|
||||||
&.active-link {
|
|
||||||
border-bottom: 2px solid var(--primary);
|
|
||||||
.mdc-tab__text-label {
|
|
||||||
color: var(--primary);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nav {
|
nav {
|
||||||
margin-bottom: 40px;
|
margin-bottom: 40px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,12 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|||||||
import { SettingsComponent } from './settings.component';
|
import { SettingsComponent } from './settings.component';
|
||||||
import { MaterialModule } from '../material.module';
|
import { MaterialModule } from '../material.module';
|
||||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
import { AppModule, SelectedRegistrarModule } from '../app.module';
|
||||||
|
import { BackendService } from '../shared/services/backend.service';
|
||||||
|
import { provideHttpClient } from '@angular/common/http';
|
||||||
|
import { provideHttpClientTesting } from '@angular/common/http/testing';
|
||||||
|
import { AppRoutingModule } from '../app-routing.module';
|
||||||
|
|
||||||
describe('SettingsComponent', () => {
|
describe('SettingsComponent', () => {
|
||||||
let component: SettingsComponent;
|
let component: SettingsComponent;
|
||||||
@@ -24,7 +30,19 @@ describe('SettingsComponent', () => {
|
|||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
imports: [MaterialModule, BrowserAnimationsModule],
|
imports: [
|
||||||
|
SelectedRegistrarModule,
|
||||||
|
MaterialModule,
|
||||||
|
BrowserAnimationsModule,
|
||||||
|
AppRoutingModule,
|
||||||
|
AppModule,
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
BackendService,
|
||||||
|
{ provide: ActivatedRoute, useValue: {} as ActivatedRoute },
|
||||||
|
provideHttpClient(),
|
||||||
|
provideHttpClientTesting(),
|
||||||
|
],
|
||||||
declarations: [SettingsComponent],
|
declarations: [SettingsComponent],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,9 @@
|
|||||||
<div class="console-app__whois-edit" *ngIf="registrarInEdit">
|
<div
|
||||||
|
class="console-app__whois-edit"
|
||||||
|
*ngIf="registrarInEdit"
|
||||||
|
cdkTrapFocus
|
||||||
|
[cdkTrapFocusAutoCapture]="true"
|
||||||
|
>
|
||||||
<button
|
<button
|
||||||
mat-icon-button
|
mat-icon-button
|
||||||
class="console-app__whois-edit-back"
|
class="console-app__whois-edit-back"
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
<div class="console-app__user-details">
|
<div
|
||||||
|
class="console-app__user-details"
|
||||||
|
cdkTrapFocus
|
||||||
|
[cdkTrapFocusAutoCapture]="true"
|
||||||
|
>
|
||||||
@if(isEditing) {
|
@if(isEditing) {
|
||||||
<h1 class="mat-headline-4">Editing {{ userDetails().emailAddress }}</h1>
|
<h1 class="mat-headline-4">Editing {{ userDetails().emailAddress }}</h1>
|
||||||
<mat-divider></mat-divider>
|
<mat-divider></mat-divider>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<app-selected-registrar-wrapper>
|
<app-selected-registrar-wrapper cdkTrapFocus [cdkTrapFocusAutoCapture]="true">
|
||||||
@if(isLoading) {
|
@if(isLoading) {
|
||||||
<div class="console-app__users-spinner">
|
<div class="console-app__users-spinner">
|
||||||
<mat-spinner />
|
<mat-spinner />
|
||||||
|
|||||||
@@ -19,6 +19,8 @@
|
|||||||
*matRowDef="let row; columns: displayedColumns"
|
*matRowDef="let row; columns: displayedColumns"
|
||||||
[class.rowSelected]="isRowSelected(row)"
|
[class.rowSelected]="isRowSelected(row)"
|
||||||
(click)="onClick(row)"
|
(click)="onClick(row)"
|
||||||
|
(keyup.enter)="onClick(row)"
|
||||||
|
tabindex="0"
|
||||||
></mat-row>
|
></mat-row>
|
||||||
</mat-table>
|
</mat-table>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ mat-row:hover {
|
|||||||
|
|
||||||
// Access and define a class with secondary color exposed
|
// Access and define a class with secondary color exposed
|
||||||
.secondary-text {
|
.secondary-text {
|
||||||
color: $secondary-color;
|
color: #575757;
|
||||||
}
|
}
|
||||||
|
|
||||||
.primary-text {
|
.primary-text {
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 69 KiB |
|
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 70 KiB |
|
Before Width: | Height: | Size: 73 KiB After Width: | Height: | Size: 72 KiB |