aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorKim <1877318+kimsible@users.noreply.github.com>2020-07-24 08:53:25 +0200
committerGitHub <noreply@github.com>2020-07-24 08:53:25 +0200
commit2e7f262724dd64a209e0bad5930ba29bb4f801c3 (patch)
treeae722bf8df3331442a5f9eaa34eb5c12db21f6cf
parentb40a219338fed042072decea203838ca5e2b265f (diff)
downloadPeerTube-2e7f262724dd64a209e0bad5930ba29bb4f801c3.tar.gz
PeerTube-2e7f262724dd64a209e0bad5930ba29bb4f801c3.tar.zst
PeerTube-2e7f262724dd64a209e0bad5930ba29bb4f801c3.zip
Display user quota progress bars above upload form (#2981)
* Move user-quota to my-user-quota shared component * Add user-quota to upload form * Increase progress bar height and make it focusable * Correct syntax parenthesis * Add explicit title to user-quota bars + tooltip with quota values * Hide user-quota in second upload step * Customize focus styles on user-quota Co-authored-by: kimsible <kimsible@users.noreply.github.com>
-rw-r--r--client/src/app/+my-account/my-account-settings/my-account-settings.component.html16
-rw-r--r--client/src/app/+my-account/my-account-settings/my-account-settings.component.scss21
-rw-r--r--client/src/app/+my-account/my-account-settings/my-account-settings.component.ts38
-rw-r--r--client/src/app/+videos/+video-edit/video-add.component.html2
-rw-r--r--client/src/app/+videos/+video-edit/video-add.component.scss6
-rw-r--r--client/src/app/+videos/+video-edit/video-add.component.ts10
-rw-r--r--client/src/app/shared/shared-main/shared-main.module.ts4
-rw-r--r--client/src/app/shared/shared-main/users/index.ts1
-rw-r--r--client/src/app/shared/shared-main/users/user-quota.component.html21
-rw-r--r--client/src/app/shared/shared-main/users/user-quota.component.scss31
-rw-r--r--client/src/app/shared/shared-main/users/user-quota.component.ts68
11 files changed, 141 insertions, 77 deletions
diff --git a/client/src/app/+my-account/my-account-settings/my-account-settings.component.html b/client/src/app/+my-account/my-account-settings/my-account-settings.component.html
index eb7bb0d6f..2ad014f01 100644
--- a/client/src/app/+my-account/my-account-settings/my-account-settings.component.html
+++ b/client/src/app/+my-account/my-account-settings/my-account-settings.component.html
@@ -14,21 +14,7 @@
14 14
15 <div class="form-group form-group-right col-12 col-lg-8 col-xl-9"> 15 <div class="form-group form-group-right col-12 col-lg-8 col-xl-9">
16 16
17 <div class="user-quota mb-3"> 17 <my-user-quota [user]="user" [userInformationLoaded]="userInformationLoaded"></my-user-quota>
18 <div>
19 <div class="progress" i18n-title title="Total video quota">
20 <div class="progress-bar" role="progressbar" [style]="{ width: userVideoQuotaPercentage + '%' }" [attr.aria-valuenow]="userVideoQuotaUsed" aria-valuemin="0" [attr.aria-valuemax]="user.videoQuota">{{ userVideoQuotaUsed | bytes: 0 }}</div>
21 <span class="ml-auto mr-2">{{ userVideoQuota }}</span>
22 </div>
23 </div>
24
25 <div *ngIf="hasDailyQuota()" class="mt-3">
26 <div class="progress" i18n-title title="Daily video quota">
27 <div class="progress-bar secondary" role="progressbar" [style]="{ width: userVideoQuotaDailyPercentage + '%' }" [attr.aria-valuenow]="userVideoQuotaUsedDaily" aria-valuemin="0" [attr.aria-valuemax]="user.videoQuotaDaily">{{ userVideoQuotaUsedDaily | bytes: 0 }}</div>
28 <span class="ml-auto mr-2">{{ userVideoQuotaDaily }}</span>
29 </div>
30 </div>
31 </div>
32 18
33 <my-account-profile [user]="user" [userInformationLoaded]="userInformationLoaded"></my-account-profile> 19 <my-account-profile [user]="user" [userInformationLoaded]="userInformationLoaded"></my-account-profile>
34 </div> 20 </div>
diff --git a/client/src/app/+my-account/my-account-settings/my-account-settings.component.scss b/client/src/app/+my-account/my-account-settings/my-account-settings.component.scss
index 1cdb1fab4..d17cd931e 100644
--- a/client/src/app/+my-account/my-account-settings/my-account-settings.component.scss
+++ b/client/src/app/+my-account/my-account-settings/my-account-settings.component.scss
@@ -1,15 +1,6 @@
1@import '_variables'; 1@import '_variables';
2@import '_mixins'; 2@import '_mixins';
3 3
4.user-quota {
5 font-size: 15px;
6 margin-top: 20px;
7
8 label {
9 margin-right: 5px;
10 }
11}
12
13.account-title { 4.account-title {
14 @include settings-big-title; 5 @include settings-big-title;
15 6
@@ -18,14 +9,6 @@
18 } 9 }
19} 10}
20 11
21.progress { 12.form-group {
22 @include progressbar; 13 max-width: 500px;
23 width: 500px;
24 max-width: 100%;
25}
26
27@media screen and (max-width: $small-view) {
28 .progress {
29 width: 100%;
30 }
31} 14}
diff --git a/client/src/app/+my-account/my-account-settings/my-account-settings.component.ts b/client/src/app/+my-account/my-account-settings/my-account-settings.component.ts
index a9a150e21..a3a8ff1f1 100644
--- a/client/src/app/+my-account/my-account-settings/my-account-settings.component.ts
+++ b/client/src/app/+my-account/my-account-settings/my-account-settings.component.ts
@@ -1,4 +1,3 @@
1import { BytesPipe } from 'ngx-pipes'
2import { ViewportScroller } from '@angular/common' 1import { ViewportScroller } from '@angular/common'
3import { AfterViewChecked, Component, OnInit } from '@angular/core' 2import { AfterViewChecked, Component, OnInit } from '@angular/core'
4import { AuthService, Notifier, User, UserService } from '@app/core' 3import { AuthService, Notifier, User, UserService } from '@app/core'
@@ -12,14 +11,6 @@ import { I18n } from '@ngx-translate/i18n-polyfill'
12export class MyAccountSettingsComponent implements OnInit, AfterViewChecked { 11export class MyAccountSettingsComponent implements OnInit, AfterViewChecked {
13 user: User = null 12 user: User = null
14 13
15 userVideoQuota = '0'
16 userVideoQuotaUsed = 0
17 userVideoQuotaPercentage = 15
18
19 userVideoQuotaDaily = '0'
20 userVideoQuotaUsedDaily = 0
21 userVideoQuotaDailyPercentage = 15
22
23 private lastScrollHash: string 14 private lastScrollHash: string
24 15
25 constructor ( 16 constructor (
@@ -36,31 +27,6 @@ export class MyAccountSettingsComponent implements OnInit, AfterViewChecked {
36 27
37 ngOnInit () { 28 ngOnInit () {
38 this.user = this.authService.getUser() 29 this.user = this.authService.getUser()
39
40 this.authService.userInformationLoaded.subscribe(
41 () => {
42 if (this.user.videoQuota !== -1) {
43 this.userVideoQuota = new BytesPipe().transform(this.user.videoQuota, 0).toString()
44 } else {
45 this.userVideoQuota = this.i18n('Unlimited')
46 }
47
48 if (this.user.videoQuotaDaily !== -1) {
49 this.userVideoQuotaDaily = new BytesPipe().transform(this.user.videoQuotaDaily, 0).toString()
50 } else {
51 this.userVideoQuotaDaily = this.i18n('Unlimited')
52 }
53 }
54 )
55
56 this.userService.getMyVideoQuotaUsed()
57 .subscribe(data => {
58 this.userVideoQuotaUsed = data.videoQuotaUsed
59 this.userVideoQuotaPercentage = this.userVideoQuotaUsed * 100 / this.user.videoQuota
60
61 this.userVideoQuotaUsedDaily = data.videoQuotaUsedDaily
62 this.userVideoQuotaDailyPercentage = this.userVideoQuotaUsedDaily * 100 / this.user.videoQuotaDaily
63 })
64 } 30 }
65 31
66 ngAfterViewChecked () { 32 ngAfterViewChecked () {
@@ -83,8 +49,4 @@ export class MyAccountSettingsComponent implements OnInit, AfterViewChecked {
83 err => this.notifier.error(err.message) 49 err => this.notifier.error(err.message)
84 ) 50 )
85 } 51 }
86
87 hasDailyQuota () {
88 return this.user.videoQuotaDaily !== -1
89 }
90} 52}
diff --git a/client/src/app/+videos/+video-edit/video-add.component.html b/client/src/app/+videos/+video-edit/video-add.component.html
index 79bfc6e5c..5690ac37f 100644
--- a/client/src/app/+videos/+video-edit/video-add.component.html
+++ b/client/src/app/+videos/+video-edit/video-add.component.html
@@ -5,6 +5,8 @@
5 Instead, <a routerLink="/admin/users">create a dedicated account</a> to upload your videos. 5 Instead, <a routerLink="/admin/users">create a dedicated account</a> to upload your videos.
6 </div> 6 </div>
7 7
8 <my-user-quota *ngIf="!isInSecondStep()" [user]="user" [userInformationLoaded]="userInformationLoaded"></my-user-quota>
9
8 <div class="title-page title-page-single" *ngIf="isInSecondStep()"> 10 <div class="title-page title-page-single" *ngIf="isInSecondStep()">
9 <ng-container *ngIf="secondStepType === 'import-url' || secondStepType === 'import-torrent'" i18n>Import {{ videoName }}</ng-container> 11 <ng-container *ngIf="secondStepType === 'import-url' || secondStepType === 'import-torrent'" i18n>Import {{ videoName }}</ng-container>
10 <ng-container *ngIf="secondStepType === 'upload'" i18n>Upload {{ videoName }}</ng-container> 12 <ng-container *ngIf="secondStepType === 'upload'" i18n>Upload {{ videoName }}</ng-container>
diff --git a/client/src/app/+videos/+video-edit/video-add.component.scss b/client/src/app/+videos/+video-edit/video-add.component.scss
index b9fef9fce..f9977bda0 100644
--- a/client/src/app/+videos/+video-edit/video-add.component.scss
+++ b/client/src/app/+videos/+video-edit/video-add.component.scss
@@ -7,7 +7,7 @@ $border-color: #EAEAEA;
7$nav-link-height: 40px; 7$nav-link-height: 40px;
8 8
9.margin-content { 9.margin-content {
10 padding-top: 50px; 10 padding-top: 20px;
11} 11}
12 12
13.alert { 13.alert {
@@ -16,7 +16,7 @@ $nav-link-height: 40px;
16 16
17::ng-deep .video-add-nav { 17::ng-deep .video-add-nav {
18 border-bottom: $border-width $border-type $border-color; 18 border-bottom: $border-width $border-type $border-color;
19 margin: 50px 0 0 0 !important; 19 margin: 20px 0 0 0 !important;
20 20
21 &.hide-nav { 21 &.hide-nav {
22 display: none !important; 22 display: none !important;
@@ -64,7 +64,7 @@ $nav-link-height: 40px;
64 padding-bottom: 20px; 64 padding-bottom: 20px;
65 display: flex; 65 display: flex;
66 justify-content: center; 66 justify-content: center;
67 align-items: center; 67 padding-top: 20px;
68 68
69 &.dragover { 69 &.dragover {
70 border: 3px dashed pvar(--mainColor); 70 border: 3px dashed pvar(--mainColor);
diff --git a/client/src/app/+videos/+video-edit/video-add.component.ts b/client/src/app/+videos/+video-edit/video-add.component.ts
index 5bd768809..016791d59 100644
--- a/client/src/app/+videos/+video-edit/video-add.component.ts
+++ b/client/src/app/+videos/+video-edit/video-add.component.ts
@@ -1,5 +1,5 @@
1import { Component, HostListener, OnInit, ViewChild } from '@angular/core' 1import { Component, HostListener, OnInit, ViewChild } from '@angular/core'
2import { AuthService, CanComponentDeactivate, ServerService } from '@app/core' 2import { AuthService, CanComponentDeactivate, ServerService, User } from '@app/core'
3import { ServerConfig } from '@shared/models' 3import { ServerConfig } from '@shared/models'
4import { VideoImportTorrentComponent } from './video-add-components/video-import-torrent.component' 4import { VideoImportTorrentComponent } from './video-add-components/video-import-torrent.component'
5import { VideoImportUrlComponent } from './video-add-components/video-import-url.component' 5import { VideoImportUrlComponent } from './video-add-components/video-import-url.component'
@@ -15,6 +15,8 @@ export class VideoAddComponent implements OnInit, CanComponentDeactivate {
15 @ViewChild('videoImportUrl') videoImportUrl: VideoImportUrlComponent 15 @ViewChild('videoImportUrl') videoImportUrl: VideoImportUrlComponent
16 @ViewChild('videoImportTorrent') videoImportTorrent: VideoImportTorrentComponent 16 @ViewChild('videoImportTorrent') videoImportTorrent: VideoImportTorrentComponent
17 17
18 user: User = null
19
18 secondStepType: 'upload' | 'import-url' | 'import-torrent' 20 secondStepType: 'upload' | 'import-url' | 'import-torrent'
19 videoName: string 21 videoName: string
20 serverConfig: ServerConfig 22 serverConfig: ServerConfig
@@ -24,7 +26,13 @@ export class VideoAddComponent implements OnInit, CanComponentDeactivate {
24 private serverService: ServerService 26 private serverService: ServerService
25 ) {} 27 ) {}
26 28
29 get userInformationLoaded () {
30 return this.auth.userInformationLoaded
31 }
32
27 ngOnInit () { 33 ngOnInit () {
34 this.user = this.auth.getUser()
35
28 this.serverConfig = this.serverService.getTmpConfig() 36 this.serverConfig = this.serverService.getTmpConfig()
29 37
30 this.serverService.getConfig() 38 this.serverService.getConfig()
diff --git a/client/src/app/shared/shared-main/shared-main.module.ts b/client/src/app/shared/shared-main/shared-main.module.ts
index 732914e34..22a207e51 100644
--- a/client/src/app/shared/shared-main/shared-main.module.ts
+++ b/client/src/app/shared/shared-main/shared-main.module.ts
@@ -26,7 +26,7 @@ import { DateToggleComponent } from './date'
26import { FeedComponent } from './feeds' 26import { FeedComponent } from './feeds'
27import { LoaderComponent, SmallLoaderComponent } from './loaders' 27import { LoaderComponent, SmallLoaderComponent } from './loaders'
28import { HelpComponent, ListOverflowComponent, TopMenuDropdownComponent } from './misc' 28import { HelpComponent, ListOverflowComponent, TopMenuDropdownComponent } from './misc'
29import { UserHistoryService, UserNotificationsComponent, UserNotificationService } from './users' 29import { UserHistoryService, UserNotificationsComponent, UserNotificationService, UserQuotaComponent } from './users'
30import { RedundancyService, VideoImportService, VideoOwnershipService, VideoService } from './video' 30import { RedundancyService, VideoImportService, VideoOwnershipService, VideoService } from './video'
31import { VideoCaptionService } from './video-caption' 31import { VideoCaptionService } from './video-caption'
32import { VideoChannelService } from './video-channel' 32import { VideoChannelService } from './video-channel'
@@ -83,6 +83,7 @@ import { AUTH_INTERCEPTOR_PROVIDER } from './auth'
83 ListOverflowComponent, 83 ListOverflowComponent,
84 TopMenuDropdownComponent, 84 TopMenuDropdownComponent,
85 85
86 UserQuotaComponent,
86 UserNotificationsComponent 87 UserNotificationsComponent
87 ], 88 ],
88 89
@@ -132,6 +133,7 @@ import { AUTH_INTERCEPTOR_PROVIDER } from './auth'
132 ListOverflowComponent, 133 ListOverflowComponent,
133 TopMenuDropdownComponent, 134 TopMenuDropdownComponent,
134 135
136 UserQuotaComponent,
135 UserNotificationsComponent 137 UserNotificationsComponent
136 ], 138 ],
137 139
diff --git a/client/src/app/shared/shared-main/users/index.ts b/client/src/app/shared/shared-main/users/index.ts
index 83401ab52..130082af6 100644
--- a/client/src/app/shared/shared-main/users/index.ts
+++ b/client/src/app/shared/shared-main/users/index.ts
@@ -2,3 +2,4 @@ export * from './user-history.service'
2export * from './user-notification.model' 2export * from './user-notification.model'
3export * from './user-notification.service' 3export * from './user-notification.service'
4export * from './user-notifications.component' 4export * from './user-notifications.component'
5export * from './user-quota.component'
diff --git a/client/src/app/shared/shared-main/users/user-quota.component.html b/client/src/app/shared/shared-main/users/user-quota.component.html
new file mode 100644
index 000000000..f9fb32133
--- /dev/null
+++ b/client/src/app/shared/shared-main/users/user-quota.component.html
@@ -0,0 +1,21 @@
1<div class="user-quota mb-3">
2 <div>
3 <strong class="user-quota-title" tabindex="0" i18n>Total video quota</strong>
4 <div class="progress" tabindex="0" [ngbTooltip]="titleVideoQuota()">
5 <div class="progress-bar" tabindex="0" role="progressbar" [style]="{ width: userVideoQuotaPercentage + '%' }"
6 [attr.aria-valuenow]="userVideoQuotaUsed" aria-valuemin="0" [attr.aria-valuemax]="user.videoQuota">
7 {{ userVideoQuotaUsed | bytes: 0 }}</div>
8 <span class="ml-auto mr-2">{{ userVideoQuota }}</span>
9 </div>
10 </div>
11
12 <div *ngIf="hasDailyQuota()" class="mt-3">
13 <strong class="user-quota-title" tabindex="0" i18n>Daily video quota</strong>
14 <div class="progress" tabindex="0" [ngbTooltip]="titleVideoQuotaDaily()">
15 <div class="progress-bar secondary" role="progressbar" [style]="{ width: userVideoQuotaDailyPercentage + '%' }"
16 [attr.aria-valuenow]="userVideoQuotaUsedDaily" aria-valuemin="0" [attr.aria-valuemax]="user.videoQuotaDaily">
17 {{ userVideoQuotaUsedDaily | bytes: 0 }}</div>
18 <span class="ml-auto mr-2">{{ userVideoQuotaDaily }}</span>
19 </div>
20 </div>
21</div> \ No newline at end of file
diff --git a/client/src/app/shared/shared-main/users/user-quota.component.scss b/client/src/app/shared/shared-main/users/user-quota.component.scss
new file mode 100644
index 000000000..904add0f4
--- /dev/null
+++ b/client/src/app/shared/shared-main/users/user-quota.component.scss
@@ -0,0 +1,31 @@
1@import '_variables';
2@import '_mixins';
3
4.user-quota {
5 font-size: 15px;
6 margin-top: 20px;
7
8 label {
9 margin-right: 5px;
10 }
11
12 &, .progress {
13 width: 100% !important;
14 }
15
16 .user-quota-title, .progress {
17 @include disable-outline;
18 @include button-focus(pvar(--mainColorLightest));
19 }
20
21 .progress {
22 @include progressbar;
23
24 height: 2rem;
25
26 span {
27 align-self: center;
28 }
29 }
30}
31
diff --git a/client/src/app/shared/shared-main/users/user-quota.component.ts b/client/src/app/shared/shared-main/users/user-quota.component.ts
new file mode 100644
index 000000000..a8f56e4d6
--- /dev/null
+++ b/client/src/app/shared/shared-main/users/user-quota.component.ts
@@ -0,0 +1,68 @@
1import { Subject } from 'rxjs'
2import { BytesPipe } from 'ngx-pipes'
3import { Component, Input, OnInit } from '@angular/core'
4import { User, UserService } from '@app/core'
5import { I18n } from '@ngx-translate/i18n-polyfill'
6
7@Component({
8 selector: 'my-user-quota',
9 templateUrl: './user-quota.component.html',
10 styleUrls: ['./user-quota.component.scss']
11})
12
13export class UserQuotaComponent implements OnInit {
14 @Input() user: User = null
15 @Input() userInformationLoaded: Subject<any>
16
17 userVideoQuota = '0'
18 userVideoQuotaUsed = 0
19 userVideoQuotaPercentage = 15
20
21 userVideoQuotaDaily = '0'
22 userVideoQuotaUsedDaily = 0
23 userVideoQuotaDailyPercentage = 15
24
25 constructor (
26 private userService: UserService,
27 private i18n: I18n
28 ) { }
29
30 ngOnInit () {
31 this.userInformationLoaded.subscribe(
32 () => {
33 if (this.user.videoQuota !== -1) {
34 this.userVideoQuota = new BytesPipe().transform(this.user.videoQuota, 0).toString()
35 } else {
36 this.userVideoQuota = this.i18n('Unlimited')
37 }
38
39 if (this.user.videoQuotaDaily !== -1) {
40 this.userVideoQuotaDaily = new BytesPipe().transform(this.user.videoQuotaDaily, 0).toString()
41 } else {
42 this.userVideoQuotaDaily = this.i18n('Unlimited')
43 }
44 }
45 )
46
47 this.userService.getMyVideoQuotaUsed()
48 .subscribe(data => {
49 this.userVideoQuotaUsed = data.videoQuotaUsed
50 this.userVideoQuotaPercentage = this.userVideoQuotaUsed * 100 / this.user.videoQuota
51
52 this.userVideoQuotaUsedDaily = data.videoQuotaUsedDaily
53 this.userVideoQuotaDailyPercentage = this.userVideoQuotaUsedDaily * 100 / this.user.videoQuotaDaily
54 })
55 }
56
57 hasDailyQuota () {
58 return this.user.videoQuotaDaily !== -1
59 }
60
61 titleVideoQuota () {
62 return `${new BytesPipe().transform(this.userVideoQuotaUsed, 0).toString()} / ${this.userVideoQuota}`
63 }
64
65 titleVideoQuotaDaily () {
66 return `${new BytesPipe().transform(this.userVideoQuotaUsedDaily, 0).toString()} / ${this.userVideoQuotaDaily}`
67 }
68}