aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--client/package.json3
-rw-r--r--client/src/app/app.component.html2
-rw-r--r--client/src/app/app.module.ts1
-rw-r--r--client/src/app/menu/menu.component.html4
-rw-r--r--client/src/app/menu/menu.component.scss3
-rw-r--r--client/src/app/search/search.component.html4
-rw-r--r--client/src/app/shared/video/video-miniature.component.html5
-rw-r--r--client/src/app/shared/video/video-thumbnail.component.scss5
-rw-r--r--client/src/app/videos/video-list/video-overview.component.scss5
-rw-r--r--client/src/sass/include/_mixins.scss4
-rw-r--r--client/yarn.lock72
-rw-r--r--server/helpers/custom-validators/videos.ts4
12 files changed, 32 insertions, 80 deletions
diff --git a/client/package.json b/client/package.json
index 3a4605b56..4454e9a39 100644
--- a/client/package.json
+++ b/client/package.json
@@ -159,6 +159,7 @@
159 "webpack-cli": "^3.0.8", 159 "webpack-cli": "^3.0.8",
160 "webtorrent": "^0.102.1", 160 "webtorrent": "^0.102.1",
161 "whatwg-fetch": "^2.0.4", 161 "whatwg-fetch": "^2.0.4",
162 "zone.js": "~0.8.5" 162 "zone.js": "~0.8.5",
163 "focus-visible": "^4.1.5"
163 } 164 }
164} 165}
diff --git a/client/src/app/app.component.html b/client/src/app/app.component.html
index 20e573de1..23ed04c2d 100644
--- a/client/src/app/app.component.html
+++ b/client/src/app/app.component.html
@@ -22,7 +22,7 @@
22 <div class="sub-header-container"> 22 <div class="sub-header-container">
23 <my-menu *ngIf="isMenuDisplayed"></my-menu> 23 <my-menu *ngIf="isMenuDisplayed"></my-menu>
24 24
25 <div id="right-container" class="main-col container-fluid" [ngClass]="{ expanded: isMenuDisplayed === false }"> 25 <div id="content" tabindex="-1" class="main-col container-fluid" [ngClass]="{ expanded: isMenuDisplayed === false }">
26 26
27 <div class="main-row"> 27 <div class="main-row">
28 <router-outlet></router-outlet> 28 <router-outlet></router-outlet>
diff --git a/client/src/app/app.module.ts b/client/src/app/app.module.ts
index b484a89e8..ba16c072e 100644
--- a/client/src/app/app.module.ts
+++ b/client/src/app/app.module.ts
@@ -6,6 +6,7 @@ import { ResetPasswordModule } from '@app/reset-password'
6import { MetaLoader, MetaModule, MetaStaticLoader, PageTitlePositioning } from '@ngx-meta/core' 6import { MetaLoader, MetaModule, MetaStaticLoader, PageTitlePositioning } from '@ngx-meta/core'
7import { ClipboardModule } from 'ngx-clipboard' 7import { ClipboardModule } from 'ngx-clipboard'
8import { HotkeyModule, IHotkeyOptions } from 'angular2-hotkeys' 8import { HotkeyModule, IHotkeyOptions } from 'angular2-hotkeys'
9import 'focus-visible'
9 10
10import { AppRoutingModule } from './app-routing.module' 11import { AppRoutingModule } from './app-routing.module'
11import { AppComponent } from './app.component' 12import { AppComponent } from './app.component'
diff --git a/client/src/app/menu/menu.component.html b/client/src/app/menu/menu.component.html
index 63ff4a86f..139664534 100644
--- a/client/src/app/menu/menu.component.html
+++ b/client/src/app/menu/menu.component.html
@@ -85,10 +85,10 @@
85 85
86 <div class="footer d-flex justify-content-between"> 86 <div class="footer d-flex justify-content-between">
87 <span class="language"> 87 <span class="language">
88 <span (click)="openLanguageChooser()" i18n-title title="Change the language" class="icon icon-language"></span> 88 <span tabindex="0" (keyup.enter)="openLanguageChooser()" (click)="openLanguageChooser()" i18n-title title="Change the language" class="icon icon-language"></span>
89 </span> 89 </span>
90 <span class="color-palette"> 90 <span class="color-palette">
91 <span (click)="toggleDarkTheme()" i18n-title title="Toggle dark interface" class="icon icon-moonsun"></span> 91 <span tabindex="0" (keyup.enter)="toggleDarkTheme()" (click)="toggleDarkTheme()" i18n-title title="Toggle dark interface" class="icon icon-moonsun"></span>
92 </span> 92 </span>
93 </div> 93 </div>
94 </menu> 94 </menu>
diff --git a/client/src/app/menu/menu.component.scss b/client/src/app/menu/menu.component.scss
index 592860e12..f1b0a284f 100644
--- a/client/src/app/menu/menu.component.scss
+++ b/client/src/app/menu/menu.component.scss
@@ -130,7 +130,7 @@ menu {
130 transition: background-color .1s ease-in-out; 130 transition: background-color .1s ease-in-out;
131 @include disable-default-a-behaviour; 131 @include disable-default-a-behaviour;
132 132
133 &:hover { 133 &:hover, &.focus-visible {
134 background-color: rgba(255, 255, 255, 0.15); 134 background-color: rgba(255, 255, 255, 0.15);
135 } 135 }
136 136
@@ -202,6 +202,7 @@ menu {
202 font-weight: $font-semibold; 202 font-weight: $font-semibold;
203 203
204 .icon { 204 .icon {
205 @include disable-outline;
205 @include icon(28px); 206 @include icon(28px);
206 opacity: 0.9; 207 opacity: 0.9;
207 208
diff --git a/client/src/app/search/search.component.html b/client/src/app/search/search.component.html
index a258d4edd..c4072b291 100644
--- a/client/src/app/search/search.component.html
+++ b/client/src/app/search/search.component.html
@@ -48,9 +48,9 @@
48 <my-video-thumbnail [video]="result"></my-video-thumbnail> 48 <my-video-thumbnail [video]="result"></my-video-thumbnail>
49 49
50 <div class="video-info"> 50 <div class="video-info">
51 <a class="video-info-name" [routerLink]="['/videos/watch', result.uuid]" [attr.title]="result.name">{{ result.name }}</a> 51 <a tabindex="-1" class="video-info-name" [routerLink]="['/videos/watch', result.uuid]" [attr.title]="result.name">{{ result.name }}</a>
52 <span i18n class="video-info-date-views">{{ result.publishedAt | myFromNow }} - {{ result.views | myNumberFormatter }} views</span> 52 <span i18n class="video-info-date-views">{{ result.publishedAt | myFromNow }} - {{ result.views | myNumberFormatter }} views</span>
53 <a class="video-info-account" [routerLink]="[ '/accounts', result.byAccount ]">{{ result.byAccount }}</a> 53 <a tabindex="-1" class="video-info-account" [routerLink]="[ '/accounts', result.byAccount ]">{{ result.byAccount }}</a>
54 </div> 54 </div>
55 </div> 55 </div>
56 </ng-container> 56 </ng-container>
diff --git a/client/src/app/shared/video/video-miniature.component.html b/client/src/app/shared/video/video-miniature.component.html
index de84bccf9..9cf3fb321 100644
--- a/client/src/app/shared/video/video-miniature.component.html
+++ b/client/src/app/shared/video/video-miniature.component.html
@@ -3,6 +3,7 @@
3 3
4 <div class="video-miniature-information"> 4 <div class="video-miniature-information">
5 <a 5 <a
6 tabindex="-1"
6 class="video-miniature-name" 7 class="video-miniature-name"
7 [routerLink]="[ '/videos/watch', video.uuid ]" [attr.title]="video.name" [ngClass]="{ 'blur-filter': isVideoBlur() }" 8 [routerLink]="[ '/videos/watch', video.uuid ]" [attr.title]="video.name" [ngClass]="{ 'blur-filter': isVideoBlur() }"
8 > 9 >
@@ -11,10 +12,10 @@
11 12
12 <span i18n class="video-miniature-created-at-views">{{ video.publishedAt | myFromNow }} - {{ video.views | myNumberFormatter }} views</span> 13 <span i18n class="video-miniature-created-at-views">{{ video.publishedAt | myFromNow }} - {{ video.views | myNumberFormatter }} views</span>
13 14
14 <a *ngIf="displayOwnerAccount()" class="video-miniature-account" [routerLink]="[ '/accounts', video.byAccount ]"> 15 <a tabindex="-1" *ngIf="displayOwnerAccount()" class="video-miniature-account" [routerLink]="[ '/accounts', video.byAccount ]">
15 {{ video.byAccount }} 16 {{ video.byAccount }}
16 </a> 17 </a>
17 <a *ngIf="displayOwnerVideoChannel()" class="video-miniature-channel" [routerLink]="[ '/video-channels', video.byVideoChannel ]"> 18 <a tabindex="-1" *ngIf="displayOwnerVideoChannel()" class="video-miniature-channel" [routerLink]="[ '/video-channels', video.byVideoChannel ]">
18 {{ video.byVideoChannel }} 19 {{ video.byVideoChannel }}
19 </a> 20 </a>
20 </div> 21 </div>
diff --git a/client/src/app/shared/video/video-thumbnail.component.scss b/client/src/app/shared/video/video-thumbnail.component.scss
index c3cb1ec75..1dd8e5338 100644
--- a/client/src/app/shared/video/video-thumbnail.component.scss
+++ b/client/src/app/shared/video/video-thumbnail.component.scss
@@ -14,6 +14,11 @@
14 text-decoration: none !important; 14 text-decoration: none !important;
15 } 15 }
16 16
17 @include disable-outline;
18 &.focus-visible {
19 box-shadow: 0 0 0 2px var(--mainColor);
20 }
21
17 img { 22 img {
18 width: $video-thumbnail-width; 23 width: $video-thumbnail-width;
19 height: $video-thumbnail-height; 24 height: $video-thumbnail-height;
diff --git a/client/src/app/videos/video-list/video-overview.component.scss b/client/src/app/videos/video-list/video-overview.component.scss
index f5508cf61..eca8b230f 100644
--- a/client/src/app/videos/video-list/video-overview.component.scss
+++ b/client/src/app/videos/video-list/video-overview.component.scss
@@ -19,7 +19,10 @@
19 margin-bottom: 20px; 19 margin-bottom: 20px;
20 20
21 a { 21 a {
22 @include disable-default-a-behaviour; 22 &:hover, &:focus:not(.focus-visible), &:active {
23 text-decoration: none;
24 outline: none;
25 }
23 26
24 color: var(--mainForegroundColor); 27 color: var(--mainForegroundColor);
25 } 28 }
diff --git a/client/src/sass/include/_mixins.scss b/client/src/sass/include/_mixins.scss
index 03cb337c2..d755e7df3 100644
--- a/client/src/sass/include/_mixins.scss
+++ b/client/src/sass/include/_mixins.scss
@@ -8,7 +8,9 @@
8} 8}
9 9
10@mixin disable-outline { 10@mixin disable-outline {
11 outline: none; 11 &:focus:not(.focus-visible) {
12 outline: none;
13 }
12 14
13 &::-moz-focus-inner { 15 &::-moz-focus-inner {
14 border: 0; 16 border: 0;
diff --git a/client/yarn.lock b/client/yarn.lock
index dcd37c80d..6ecf26393 100644
--- a/client/yarn.lock
+++ b/client/yarn.lock
@@ -189,46 +189,12 @@
189 version "2.1.3" 189 version "2.1.3"
190 resolved "https://registry.yarnpkg.com/@angularclass/hmr/-/hmr-2.1.3.tgz#34e658ed3da37f23b0a200e2da5a89be92bb209f" 190 resolved "https://registry.yarnpkg.com/@angularclass/hmr/-/hmr-2.1.3.tgz#34e658ed3da37f23b0a200e2da5a89be92bb209f"
191 191
192"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.0.0-beta.35": 192"@babel/code-frame@^7.0.0-beta.35":
193 version "7.0.0" 193 version "7.0.0"
194 resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0.tgz#06e2ab19bdb535385559aabb5ba59729482800f8" 194 resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0.tgz#06e2ab19bdb535385559aabb5ba59729482800f8"
195 dependencies: 195 dependencies:
196 "@babel/highlight" "^7.0.0" 196 "@babel/highlight" "^7.0.0"
197 197
198"@babel/helper-module-imports@^7.0.0":
199 version "7.0.0"
200 resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz#96081b7111e486da4d2cd971ad1a4fe216cc2e3d"
201 dependencies:
202 "@babel/types" "^7.0.0"
203
204"@babel/helper-module-transforms@^7.0.0":
205 version "7.0.0"
206 resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.0.0.tgz#b01ee7d543e81e8c3fc404b19c9f26acb6e4cf4c"
207 dependencies:
208 "@babel/helper-module-imports" "^7.0.0"
209 "@babel/helper-simple-access" "^7.0.0"
210 "@babel/helper-split-export-declaration" "^7.0.0"
211 "@babel/template" "^7.0.0"
212 "@babel/types" "^7.0.0"
213 lodash "^4.17.10"
214
215"@babel/helper-plugin-utils@^7.0.0":
216 version "7.0.0"
217 resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz#bbb3fbee98661c569034237cc03967ba99b4f250"
218
219"@babel/helper-simple-access@^7.0.0":
220 version "7.0.0"
221 resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.0.0.tgz#ff36a27983ae4c27122da2f7f294dced80ecbd08"
222 dependencies:
223 "@babel/template" "^7.0.0"
224 "@babel/types" "^7.0.0"
225
226"@babel/helper-split-export-declaration@^7.0.0":
227 version "7.0.0"
228 resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0.tgz#3aae285c0311c2ab095d997b8c9a94cad547d813"
229 dependencies:
230 "@babel/types" "^7.0.0"
231
232"@babel/highlight@^7.0.0": 198"@babel/highlight@^7.0.0":
233 version "7.0.0" 199 version "7.0.0"
234 resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0.tgz#f710c38c8d458e6dd9a201afb637fcb781ce99e4" 200 resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0.tgz#f710c38c8d458e6dd9a201afb637fcb781ce99e4"
@@ -237,34 +203,6 @@
237 esutils "^2.0.2" 203 esutils "^2.0.2"
238 js-tokens "^4.0.0" 204 js-tokens "^4.0.0"
239 205
240"@babel/parser@^7.0.0":
241 version "7.0.0"
242 resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.0.0.tgz#697655183394facffb063437ddf52c0277698775"
243
244"@babel/plugin-transform-modules-commonjs@^7.0.0":
245 version "7.0.0"
246 resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.0.0.tgz#20b906e5ab130dd8e456b694a94d9575da0fd41f"
247 dependencies:
248 "@babel/helper-module-transforms" "^7.0.0"
249 "@babel/helper-plugin-utils" "^7.0.0"
250 "@babel/helper-simple-access" "^7.0.0"
251
252"@babel/template@^7.0.0":
253 version "7.0.0"
254 resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.0.0.tgz#c2bc9870405959c89a9c814376a2ecb247838c80"
255 dependencies:
256 "@babel/code-frame" "^7.0.0"
257 "@babel/parser" "^7.0.0"
258 "@babel/types" "^7.0.0"
259
260"@babel/types@^7.0.0":
261 version "7.0.0"
262 resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.0.0.tgz#6e191793d3c854d19c6749989e3bc55f0e962118"
263 dependencies:
264 esutils "^2.0.2"
265 lodash "^4.17.10"
266 to-fast-properties "^2.0.0"
267
268"@neos21/bootstrap3-glyphicons@^1.0.1": 206"@neos21/bootstrap3-glyphicons@^1.0.1":
269 version "1.0.1" 207 version "1.0.1"
270 resolved "https://registry.yarnpkg.com/@neos21/bootstrap3-glyphicons/-/bootstrap3-glyphicons-1.0.1.tgz#e5eeec43e0153d4b51effd9ecb58cdf7029924d7" 208 resolved "https://registry.yarnpkg.com/@neos21/bootstrap3-glyphicons/-/bootstrap3-glyphicons-1.0.1.tgz#e5eeec43e0153d4b51effd9ecb58cdf7029924d7"
@@ -3299,6 +3237,10 @@ flush-write-stream@^1.0.0:
3299 inherits "^2.0.1" 3237 inherits "^2.0.1"
3300 readable-stream "^2.0.4" 3238 readable-stream "^2.0.4"
3301 3239
3240focus-visible@^4.1.5:
3241 version "4.1.5"
3242 resolved "https://registry.yarnpkg.com/focus-visible/-/focus-visible-4.1.5.tgz#50b44e2e84c24b831ceca3cce84d57c2b311c855"
3243
3302follow-redirects@^1.0.0: 3244follow-redirects@^1.0.0:
3303 version "1.5.1" 3245 version "1.5.1"
3304 resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.1.tgz#67a8f14f5a1f67f962c2c46469c79eaec0a90291" 3246 resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.1.tgz#67a8f14f5a1f67f962c2c46469c79eaec0a90291"
@@ -8217,10 +8159,6 @@ to-fast-properties@^1.0.3:
8217 version "1.0.3" 8159 version "1.0.3"
8218 resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" 8160 resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47"
8219 8161
8220to-fast-properties@^2.0.0:
8221 version "2.0.0"
8222 resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
8223
8224to-object-path@^0.3.0: 8162to-object-path@^0.3.0:
8225 version "0.3.0" 8163 version "0.3.0"
8226 resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" 8164 resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af"
diff --git a/server/helpers/custom-validators/videos.ts b/server/helpers/custom-validators/videos.ts
index 4b1f6c069..edafba6e2 100644
--- a/server/helpers/custom-validators/videos.ts
+++ b/server/helpers/custom-validators/videos.ts
@@ -178,7 +178,7 @@ async function isVideoChannelOfAccountExist (channelId: number, user: UserModel,
178 const videoChannel = await VideoChannelModel.loadAndPopulateAccount(channelId) 178 const videoChannel = await VideoChannelModel.loadAndPopulateAccount(channelId)
179 if (videoChannel === null) { 179 if (videoChannel === null) {
180 res.status(400) 180 res.status(400)
181 .json({ error: 'Unknown video video channel on this instance.' }) 181 .json({ error: 'Unknown video `video channel` on this instance.' })
182 .end() 182 .end()
183 183
184 return false 184 return false
@@ -191,7 +191,7 @@ async function isVideoChannelOfAccountExist (channelId: number, user: UserModel,
191 const videoChannel = await VideoChannelModel.loadByIdAndAccount(channelId, user.Account.id) 191 const videoChannel = await VideoChannelModel.loadByIdAndAccount(channelId, user.Account.id)
192 if (videoChannel === null) { 192 if (videoChannel === null) {
193 res.status(400) 193 res.status(400)
194 .json({ error: 'Unknown video video channel for this account.' }) 194 .json({ error: 'Unknown video `video channel` for this account.' })
195 .end() 195 .end()
196 196
197 return false 197 return false