aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRigel Kent <sendmemail@rigelk.eu>2020-01-10 19:50:48 +0100
committerChocobozzz <chocobozzz@cpy.re>2020-01-21 10:08:10 +0100
commit7738273b808f0ff1494f18c4cc13553505e6ac6d (patch)
treee751a2282ffb9d5f1f4e556ca865e06ed4426710
parentaa0f19635ae4632e286de1599fc24f95f32a108c (diff)
downloadPeerTube-7738273b808f0ff1494f18c4cc13553505e6ac6d.tar.gz
PeerTube-7738273b808f0ff1494f18c4cc13553505e6ac6d.tar.zst
PeerTube-7738273b808f0ff1494f18c4cc13553505e6ac6d.zip
Accessibility fixes for #2149
-rw-r--r--client/src/app/+admin/users/user-edit/user-edit.component.html2
-rw-r--r--client/src/app/+my-account/my-account-settings/my-account-change-email/my-account-change-email.component.html2
-rw-r--r--client/src/app/+my-account/my-account-settings/my-account-change-password/my-account-change-password.component.html6
-rw-r--r--client/src/app/+signup/+register/register-step-user.component.html2
-rw-r--r--client/src/app/+video-channels/video-channel-videos/video-channel-videos.component.ts2
-rw-r--r--client/src/app/+video-channels/video-channels.component.html2
-rw-r--r--client/src/app/header/header.component.html2
-rw-r--r--client/src/app/header/header.component.ts7
-rw-r--r--client/src/app/login/login.component.html2
-rw-r--r--client/src/app/reset-password/reset-password.component.html4
-rw-r--r--client/src/app/shared/images/global-icon.component.ts4
-rw-r--r--client/src/app/shared/video/video-thumbnail.component.html4
-rw-r--r--client/src/sass/primeng-custom.scss1
-rw-r--r--server/lib/client-html.ts11
14 files changed, 32 insertions, 19 deletions
diff --git a/client/src/app/+admin/users/user-edit/user-edit.component.html b/client/src/app/+admin/users/user-edit/user-edit.component.html
index 6282d48a4..4ff4d0d12 100644
--- a/client/src/app/+admin/users/user-edit/user-edit.component.html
+++ b/client/src/app/+admin/users/user-edit/user-edit.component.html
@@ -30,7 +30,7 @@
30 <div class="form-group" *ngIf="isCreation()"> 30 <div class="form-group" *ngIf="isCreation()">
31 <label i18n for="password">Password</label> 31 <label i18n for="password">Password</label>
32 <input 32 <input
33 type="password" id="password" 33 type="password" id="password" autocomplete="new-password"
34 formControlName="password" [ngClass]="{ 'input-error': formErrors['password'] }" 34 formControlName="password" [ngClass]="{ 'input-error': formErrors['password'] }"
35 > 35 >
36 <div *ngIf="formErrors.password" class="form-error"> 36 <div *ngIf="formErrors.password" class="form-error">
diff --git a/client/src/app/+my-account/my-account-settings/my-account-change-email/my-account-change-email.component.html b/client/src/app/+my-account/my-account-settings/my-account-change-email/my-account-change-email.component.html
index 5492cdf22..76886c73e 100644
--- a/client/src/app/+my-account/my-account-settings/my-account-change-email/my-account-change-email.component.html
+++ b/client/src/app/+my-account/my-account-settings/my-account-change-email/my-account-change-email.component.html
@@ -24,7 +24,7 @@
24 24
25 <div class="form-group"> 25 <div class="form-group">
26 <input 26 <input
27 type="password" id="password" i18n-placeholder placeholder="Your password" 27 type="password" id="password" i18n-placeholder placeholder="Your password" autocomplete="off"
28 formControlName="password" [ngClass]="{ 'input-error': formErrors['password'] }" 28 formControlName="password" [ngClass]="{ 'input-error': formErrors['password'] }"
29 > 29 >
30 <div *ngIf="formErrors['password']" class="form-error"> 30 <div *ngIf="formErrors['password']" class="form-error">
diff --git a/client/src/app/+my-account/my-account-settings/my-account-change-password/my-account-change-password.component.html b/client/src/app/+my-account/my-account-settings/my-account-change-password/my-account-change-password.component.html
index a39061ee3..cec70c6b5 100644
--- a/client/src/app/+my-account/my-account-settings/my-account-change-password/my-account-change-password.component.html
+++ b/client/src/app/+my-account/my-account-settings/my-account-change-password/my-account-change-password.component.html
@@ -4,7 +4,7 @@
4 4
5 <label i18n for="current-password">Change password</label> 5 <label i18n for="current-password">Change password</label>
6 <input 6 <input
7 type="password" id="current-password" i18n-placeholder placeholder="Current password" 7 type="password" id="current-password" i18n-placeholder placeholder="Current password" autocomplete="current-password"
8 formControlName="current-password" [ngClass]="{ 'input-error': formErrors['current-password'] }" 8 formControlName="current-password" [ngClass]="{ 'input-error': formErrors['current-password'] }"
9 > 9 >
10 <div *ngIf="formErrors['current-password']" class="form-error"> 10 <div *ngIf="formErrors['current-password']" class="form-error">
@@ -12,7 +12,7 @@
12 </div> 12 </div>
13 13
14 <input 14 <input
15 type="password" id="new-password" i18n-placeholder placeholder="New password" 15 type="password" id="new-password" i18n-placeholder placeholder="New password" autocomplete="new-password"
16 formControlName="new-password" [ngClass]="{ 'input-error': formErrors['new-password'] }" 16 formControlName="new-password" [ngClass]="{ 'input-error': formErrors['new-password'] }"
17 > 17 >
18 <div *ngIf="formErrors['new-password']" class="form-error"> 18 <div *ngIf="formErrors['new-password']" class="form-error">
@@ -20,7 +20,7 @@
20 </div> 20 </div>
21 21
22 <input 22 <input
23 type="password" id="new-confirmed-password" i18n-placeholder placeholder="Confirm new password" 23 type="password" id="new-confirmed-password" i18n-placeholder placeholder="Confirm new password" autocomplete="new-password"
24 formControlName="new-confirmed-password" 24 formControlName="new-confirmed-password"
25 > 25 >
26 <div *ngIf="formErrors['new-confirmed-password']" class="form-error"> 26 <div *ngIf="formErrors['new-confirmed-password']" class="form-error">
diff --git a/client/src/app/+signup/+register/register-step-user.component.html b/client/src/app/+signup/+register/register-step-user.component.html
index 4381702ae..a2a657660 100644
--- a/client/src/app/+signup/+register/register-step-user.component.html
+++ b/client/src/app/+signup/+register/register-step-user.component.html
@@ -51,7 +51,7 @@
51 <div class="form-group"> 51 <div class="form-group">
52 <label for="password" i18n>Password</label> 52 <label for="password" i18n>Password</label>
53 <input 53 <input
54 type="password" id="password" i18n-placeholder placeholder="Password" 54 type="password" id="password" i18n-placeholder placeholder="Password" autocomplete="new-password"
55 formControlName="password" [ngClass]="{ 'input-error': formErrors['password'] }" 55 formControlName="password" [ngClass]="{ 'input-error': formErrors['password'] }"
56 > 56 >
57 <div *ngIf="formErrors.password" class="form-error"> 57 <div *ngIf="formErrors.password" class="form-error">
diff --git a/client/src/app/+video-channels/video-channel-videos/video-channel-videos.component.ts b/client/src/app/+video-channels/video-channel-videos/video-channel-videos.component.ts
index c1dc25aaf..f4fe14662 100644
--- a/client/src/app/+video-channels/video-channel-videos/video-channel-videos.component.ts
+++ b/client/src/app/+video-channels/video-channel-videos/video-channel-videos.component.ts
@@ -72,7 +72,7 @@ export class VideoChannelVideosComponent extends AbstractVideoList implements On
72 .getVideoChannelVideos(this.videoChannel, newPagination, this.sort) 72 .getVideoChannelVideos(this.videoChannel, newPagination, this.sort)
73 .pipe( 73 .pipe(
74 tap(({ total }) => { 74 tap(({ total }) => {
75 this.titlePage = this.i18n('Published {{total}} videos', { total }) 75 this.titlePage = this.i18n(`{total, plural, =1 {Published 1 video} other {Published ${total} videos}}`, { total })
76 }) 76 })
77 ) 77 )
78 } 78 }
diff --git a/client/src/app/+video-channels/video-channels.component.html b/client/src/app/+video-channels/video-channels.component.html
index 8ab79526d..065fc2c04 100644
--- a/client/src/app/+video-channels/video-channels.component.html
+++ b/client/src/app/+video-channels/video-channels.component.html
@@ -20,7 +20,7 @@
20 <my-subscribe-button #subscribeButton [videoChannels]="[videoChannel]"></my-subscribe-button> 20 <my-subscribe-button #subscribeButton [videoChannels]="[videoChannel]"></my-subscribe-button>
21 </div> 21 </div>
22 </div> 22 </div>
23 <div i18n class="actor-followers">{{ videoChannel.followersCount }} subscribers</div> 23 <div class="actor-followers" i18n>{videoChannel.followersCount, plural, =1 {1 subscriber} other {{{ videoChannel.followersCount }} subscribers}}</div>
24 24
25 <a [routerLink]="[ '/accounts', videoChannel.ownerBy ]" i18n-title title="Go the owner account page" class="actor-owner"> 25 <a [routerLink]="[ '/accounts', videoChannel.ownerBy ]" i18n-title title="Go the owner account page" class="actor-owner">
26 <span i18n>Created by {{ videoChannel.ownerBy }}</span> 26 <span i18n>Created by {{ videoChannel.ownerBy }}</span>
diff --git a/client/src/app/header/header.component.html b/client/src/app/header/header.component.html
index 599861817..1bdfe9858 100644
--- a/client/src/app/header/header.component.html
+++ b/client/src/app/header/header.component.html
@@ -1,5 +1,5 @@
1<input 1<input
2 type="text" id="search-video" name="search-video" i18n-placeholder placeholder="Search videos, channels…" 2 type="text" id="search-video" name="search-video" [attr.aria-label]="ariaLabelTextForSearch" i18n-placeholder placeholder="Search videos, channels…"
3 [(ngModel)]="searchValue" (keyup.enter)="doSearch()" 3 [(ngModel)]="searchValue" (keyup.enter)="doSearch()"
4> 4>
5<span (click)="doSearch()" class="icon icon-search"></span> 5<span (click)="doSearch()" class="icon icon-search"></span>
diff --git a/client/src/app/header/header.component.ts b/client/src/app/header/header.component.ts
index 580535669..5fd122930 100644
--- a/client/src/app/header/header.component.ts
+++ b/client/src/app/header/header.component.ts
@@ -5,6 +5,7 @@ import { getParameterByName } from '../shared/misc/utils'
5import { AuthService, ServerService, Notifier } from '@app/core' 5import { AuthService, ServerService, Notifier } from '@app/core'
6import { of } from 'rxjs' 6import { of } from 'rxjs'
7import { ServerConfig } from '@shared/models' 7import { ServerConfig } from '@shared/models'
8import { I18n } from '@ngx-translate/i18n-polyfill'
8 9
9@Component({ 10@Component({
10 selector: 'my-header', 11 selector: 'my-header',
@@ -14,6 +15,7 @@ import { ServerConfig } from '@shared/models'
14 15
15export class HeaderComponent implements OnInit { 16export class HeaderComponent implements OnInit {
16 searchValue = '' 17 searchValue = ''
18 ariaLabelTextForSearch = ''
17 19
18 private serverConfig: ServerConfig 20 private serverConfig: ServerConfig
19 21
@@ -23,10 +25,13 @@ export class HeaderComponent implements OnInit {
23 private auth: AuthService, 25 private auth: AuthService,
24 private serverService: ServerService, 26 private serverService: ServerService,
25 private authService: AuthService, 27 private authService: AuthService,
26 private notifier: Notifier 28 private notifier: Notifier,
29 private i18n: I18n
27 ) {} 30 ) {}
28 31
29 ngOnInit () { 32 ngOnInit () {
33 this.ariaLabelTextForSearch = this.i18n('Search videos, channels')
34
30 this.router.events 35 this.router.events
31 .pipe( 36 .pipe(
32 filter(e => e instanceof NavigationEnd), 37 filter(e => e instanceof NavigationEnd),
diff --git a/client/src/app/login/login.component.html b/client/src/app/login/login.component.html
index 162f44ded..6c6a41c4a 100644
--- a/client/src/app/login/login.component.html
+++ b/client/src/app/login/login.component.html
@@ -51,7 +51,7 @@
51 <label i18n for="password">Password</label> 51 <label i18n for="password">Password</label>
52 <div> 52 <div>
53 <input 53 <input
54 type="password" name="password" id="password" i18n-placeholder placeholder="Password" required tabindex="2" 54 type="password" name="password" id="password" i18n-placeholder placeholder="Password" required tabindex="2" autocomplete="current-password"
55 formControlName="password" [ngClass]="{ 'input-error': formErrors['password'] }" 55 formControlName="password" [ngClass]="{ 'input-error': formErrors['password'] }"
56 > 56 >
57 <a i18n class="forgot-password-button" (click)="openForgotPasswordModal()" title="Click here to reset your password">I forgot my password</a> 57 <a i18n class="forgot-password-button" (click)="openForgotPasswordModal()" title="Click here to reset your password">I forgot my password</a>
diff --git a/client/src/app/reset-password/reset-password.component.html b/client/src/app/reset-password/reset-password.component.html
index 8398be091..af30af4a0 100644
--- a/client/src/app/reset-password/reset-password.component.html
+++ b/client/src/app/reset-password/reset-password.component.html
@@ -7,7 +7,7 @@
7 <div class="form-group"> 7 <div class="form-group">
8 <label i18n for="password">Password</label> 8 <label i18n for="password">Password</label>
9 <input 9 <input
10 type="password" name="password" id="password" i18n-placeholder placeholder="Password" required 10 type="password" name="password" id="password" i18n-placeholder placeholder="Password" required autocomplete="new-password"
11 formControlName="password" [ngClass]="{ 'input-error': formErrors['password'] }" 11 formControlName="password" [ngClass]="{ 'input-error': formErrors['password'] }"
12 > 12 >
13 <div *ngIf="formErrors.password" class="form-error"> 13 <div *ngIf="formErrors.password" class="form-error">
@@ -18,7 +18,7 @@
18 <div class="form-group"> 18 <div class="form-group">
19 <label i18n for="password-confirm">Confirm password</label> 19 <label i18n for="password-confirm">Confirm password</label>
20 <input 20 <input
21 type="password" name="password-confirm" id="password-confirm" i18n-placeholder placeholder="Confirmed password" required 21 type="password" name="password-confirm" id="password-confirm" i18n-placeholder placeholder="Confirmed password" required autocomplete="new-password"
22 formControlName="password-confirm" [ngClass]="{ 'input-error': formErrors['password-confirm'] }" 22 formControlName="password-confirm" [ngClass]="{ 'input-error': formErrors['password-confirm'] }"
23 > 23 >
24 <div *ngIf="formErrors['password-confirm']" class="form-error"> 24 <div *ngIf="formErrors['password-confirm']" class="form-error">
diff --git a/client/src/app/shared/images/global-icon.component.ts b/client/src/app/shared/images/global-icon.component.ts
index 17186cff4..806aca347 100644
--- a/client/src/app/shared/images/global-icon.component.ts
+++ b/client/src/app/shared/images/global-icon.component.ts
@@ -1,5 +1,6 @@
1import { ChangeDetectionStrategy, Component, ElementRef, Input, OnInit } from '@angular/core' 1import { ChangeDetectionStrategy, Component, ElementRef, Input, OnInit } from '@angular/core'
2import { HooksService } from '@app/core/plugins/hooks.service' 2import { HooksService } from '@app/core/plugins/hooks.service'
3import { I18n } from '@ngx-translate/i18n-polyfill'
3 4
4const icons = { 5const icons = {
5 'add': require('!!raw-loader?!../../../assets/images/global/add.svg'), 6 'add': require('!!raw-loader?!../../../assets/images/global/add.svg'),
@@ -70,8 +71,7 @@ export class GlobalIconComponent implements OnInit {
70 ) { } 71 ) { }
71 72
72 async ngOnInit () { 73 async ngOnInit () {
73 const nativeElement = this.el.nativeElement 74 const nativeElement = this.el.nativeElement as HTMLElement
74
75 nativeElement.innerHTML = await this.hooks.wrapFun( 75 nativeElement.innerHTML = await this.hooks.wrapFun(
76 this.getSVGContent.bind(this), 76 this.getSVGContent.bind(this),
77 { name: this.iconName }, 77 { name: this.iconName },
diff --git a/client/src/app/shared/video/video-thumbnail.component.html b/client/src/app/shared/video/video-thumbnail.component.html
index 7e71a390b..b63085b81 100644
--- a/client/src/app/shared/video/video-thumbnail.component.html
+++ b/client/src/app/shared/video/video-thumbnail.component.html
@@ -1,8 +1,8 @@
1<a 1<a
2 [routerLink]="getVideoRouterLink()" [queryParams]="queryParams" [attr.title]="video.name" 2 [routerLink]="getVideoRouterLink()" [queryParams]="queryParams" [title]="video.name"
3 class="video-thumbnail" 3 class="video-thumbnail"
4> 4>
5 <img alt="" [attr.aria-labelledby]="video.name" [attr.src]="getImageUrl()" [ngClass]="{ 'blur-filter': nsfw }" /> 5 <img alt="" [attr.aria-label]="video.name" [attr.src]="getImageUrl()" [ngClass]="{ 'blur-filter': nsfw }" />
6 6
7 <div *ngIf="displayWatchLaterPlaylist" class="video-thumbnail-actions-overlay"> 7 <div *ngIf="displayWatchLaterPlaylist" class="video-thumbnail-actions-overlay">
8 <ng-container *ngIf="inWatchLaterPlaylist !== true"> 8 <ng-container *ngIf="inWatchLaterPlaylist !== true">
diff --git a/client/src/sass/primeng-custom.scss b/client/src/sass/primeng-custom.scss
index 9aa4d980c..238cb8454 100644
--- a/client/src/sass/primeng-custom.scss
+++ b/client/src/sass/primeng-custom.scss
@@ -8,6 +8,7 @@
8 font-family: 'Glyphicons Halflings'; 8 font-family: 'Glyphicons Halflings';
9 text-decoration: none !important; 9 text-decoration: none !important;
10 color: var(--mainForegroundColor) !important; 10 color: var(--mainForegroundColor) !important;
11 font-display: swap;
11} 12}
12 13
13my-edit-button, 14my-edit-button,
diff --git a/server/lib/client-html.ts b/server/lib/client-html.ts
index e59505614..1d8a08ed0 100644
--- a/server/lib/client-html.ts
+++ b/server/lib/client-html.ts
@@ -26,7 +26,9 @@ export class ClientHtml {
26 } 26 }
27 27
28 static async getDefaultHTMLPage (req: express.Request, res: express.Response, paramLang?: string) { 28 static async getDefaultHTMLPage (req: express.Request, res: express.Response, paramLang?: string) {
29 const html = await ClientHtml.getIndexHTML(req, res, paramLang) 29 const html = paramLang
30 ? await ClientHtml.getIndexHTML(req, res, paramLang)
31 : await ClientHtml.getIndexHTML(req, res)
30 32
31 let customHtml = ClientHtml.addTitleTag(html) 33 let customHtml = ClientHtml.addTitleTag(html)
32 customHtml = ClientHtml.addDescriptionTag(customHtml) 34 customHtml = ClientHtml.addDescriptionTag(customHtml)
@@ -98,6 +100,7 @@ export class ClientHtml {
98 100
99 let html = buffer.toString() 101 let html = buffer.toString()
100 102
103 if (paramLang) html = ClientHtml.addHtmlLang(html, paramLang)
101 html = ClientHtml.addCustomCSS(html) 104 html = ClientHtml.addCustomCSS(html)
102 html = await ClientHtml.addAsyncPluginCSS(html) 105 html = await ClientHtml.addAsyncPluginCSS(html)
103 106
@@ -106,7 +109,7 @@ export class ClientHtml {
106 return html 109 return html
107 } 110 }
108 111
109 private static getIndexPath (req: express.Request, res: express.Response, paramLang?: string) { 112 private static getIndexPath (req: express.Request, res: express.Response, paramLang: string) {
110 let lang: string 113 let lang: string
111 114
112 // Check param lang validity 115 // Check param lang validity
@@ -129,6 +132,10 @@ export class ClientHtml {
129 return join(__dirname, '../../../client/dist/' + buildFileLocale(lang) + '/index.html') 132 return join(__dirname, '../../../client/dist/' + buildFileLocale(lang) + '/index.html')
130 } 133 }
131 134
135 private static addHtmlLang (htmlStringPage: string, paramLang: string) {
136 return htmlStringPage.replace('<html>', `<html lang="${paramLang}">`)
137 }
138
132 private static addTitleTag (htmlStringPage: string, title?: string) { 139 private static addTitleTag (htmlStringPage: string, title?: string) {
133 let text = title || CONFIG.INSTANCE.NAME 140 let text = title || CONFIG.INSTANCE.NAME
134 if (title) text += ` - ${CONFIG.INSTANCE.NAME}` 141 if (title) text += ` - ${CONFIG.INSTANCE.NAME}`