diff options
author | Chocobozzz <me@florianbigard.com> | 2018-01-08 12:53:09 +0100 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2018-01-08 12:53:09 +0100 |
commit | ce5496d6a31b9617aba67970f5dc135e73335234 (patch) | |
tree | b5d2578f4618b71632e92838c3ceae36aa102798 /client | |
parent | 108af66140713c4beec681a71d360ab788226528 (diff) | |
download | PeerTube-ce5496d6a31b9617aba67970f5dc135e73335234.tar.gz PeerTube-ce5496d6a31b9617aba67970f5dc135e73335234.tar.zst PeerTube-ce5496d6a31b9617aba67970f5dc135e73335234.zip |
Support video quota on client
Diffstat (limited to 'client')
10 files changed, 53 insertions, 32 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 77aa613a1..a69ffee77 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 | |||
@@ -64,7 +64,7 @@ | |||
64 | 64 | ||
65 | <div class="transcoding-information" *ngIf="isTranscodingInformationDisplayed()"> | 65 | <div class="transcoding-information" *ngIf="isTranscodingInformationDisplayed()"> |
66 | Transcoding is enabled on server. The video quota only take in account <strong>original</strong> video. <br /> | 66 | Transcoding is enabled on server. The video quota only take in account <strong>original</strong> video. <br /> |
67 | In maximum, this user could use ~ {{ computeQuotaWithTranscoding() | bytes }}. | 67 | In maximum, this user could use ~ {{ computeQuotaWithTranscoding() | bytes: 0 }}. |
68 | </div> | 68 | </div> |
69 | </div> | 69 | </div> |
70 | 70 | ||
diff --git a/client/src/app/account/account-settings/account-settings.component.html b/client/src/app/account/account-settings/account-settings.component.html index 0d1637c40..2f41b5ecf 100644 --- a/client/src/app/account/account-settings/account-settings.component.html +++ b/client/src/app/account/account-settings/account-settings.component.html | |||
@@ -13,8 +13,12 @@ | |||
13 | </div> | 13 | </div> |
14 | <div class="file-max-size">(extensions: {{ avatarExtensions }}, max size: {{ maxAvatarSize | bytes }})</div> | 14 | <div class="file-max-size">(extensions: {{ avatarExtensions }}, max size: {{ maxAvatarSize | bytes }})</div> |
15 | 15 | ||
16 | <div class="user-quota"> | ||
17 | <span class="user-quota-label">Video quota:</span> {{ userVideoQuotaUsed | bytes: 0 }} / {{ user.videoQuota | bytes: 0 }} | ||
18 | </div> | ||
19 | |||
16 | <div class="account-title">Account settings</div> | 20 | <div class="account-title">Account settings</div> |
17 | <my-account-change-password></my-account-change-password> | 21 | <my-account-change-password></my-account-change-password> |
18 | 22 | ||
19 | <div class="account-title">Videos</div> | 23 | <div class="account-title">Video settings</div> |
20 | <my-account-details [user]="user"></my-account-details> | 24 | <my-account-details [user]="user"></my-account-details> |
diff --git a/client/src/app/account/account-settings/account-settings.component.scss b/client/src/app/account/account-settings/account-settings.component.scss index fbd1cb9f0..aaf9d79f0 100644 --- a/client/src/app/account/account-settings/account-settings.component.scss +++ b/client/src/app/account/account-settings/account-settings.component.scss | |||
@@ -36,6 +36,15 @@ | |||
36 | top: -10px; | 36 | top: -10px; |
37 | } | 37 | } |
38 | 38 | ||
39 | .user-quota { | ||
40 | font-size: 15px; | ||
41 | margin-top: 20px; | ||
42 | |||
43 | .user-quota-label { | ||
44 | font-weight: $font-semibold; | ||
45 | } | ||
46 | } | ||
47 | |||
39 | .account-title { | 48 | .account-title { |
40 | text-transform: uppercase; | 49 | text-transform: uppercase; |
41 | color: $orange-color; | 50 | color: $orange-color; |
diff --git a/client/src/app/account/account-settings/account-settings.component.ts b/client/src/app/account/account-settings/account-settings.component.ts index d5f5ff30f..a375072a0 100644 --- a/client/src/app/account/account-settings/account-settings.component.ts +++ b/client/src/app/account/account-settings/account-settings.component.ts | |||
@@ -14,6 +14,7 @@ export class AccountSettingsComponent implements OnInit { | |||
14 | @ViewChild('avatarfileInput') avatarfileInput | 14 | @ViewChild('avatarfileInput') avatarfileInput |
15 | 15 | ||
16 | user: User = null | 16 | user: User = null |
17 | userVideoQuotaUsed = 0 | ||
17 | 18 | ||
18 | constructor ( | 19 | constructor ( |
19 | private userService: UserService, | 20 | private userService: UserService, |
@@ -24,6 +25,9 @@ export class AccountSettingsComponent implements OnInit { | |||
24 | 25 | ||
25 | ngOnInit () { | 26 | ngOnInit () { |
26 | this.user = this.authService.getUser() | 27 | this.user = this.authService.getUser() |
28 | |||
29 | this.userService.getMyVideoQuotaUsed() | ||
30 | .subscribe(data => this.userVideoQuotaUsed = data.videoQuotaUsed) | ||
27 | } | 31 | } |
28 | 32 | ||
29 | getAvatarUrl () { | 33 | getAvatarUrl () { |
diff --git a/client/src/app/core/auth/auth.service.ts b/client/src/app/core/auth/auth.service.ts index 8a2ba77d6..8700e8c74 100644 --- a/client/src/app/core/auth/auth.service.ts +++ b/client/src/app/core/auth/auth.service.ts | |||
@@ -14,7 +14,6 @@ import { User } from '../../../../../shared/models/users' | |||
14 | import { UserLogin } from '../../../../../shared/models/users/user-login.model' | 14 | import { UserLogin } from '../../../../../shared/models/users/user-login.model' |
15 | import { environment } from '../../../environments/environment' | 15 | import { environment } from '../../../environments/environment' |
16 | import { RestExtractor } from '../../shared/rest' | 16 | import { RestExtractor } from '../../shared/rest' |
17 | import { UserConstructorHash } from '../../shared/users/user.model' | ||
18 | import { AuthStatus } from './auth-status.model' | 17 | import { AuthStatus } from './auth-status.model' |
19 | import { AuthUser } from './auth-user.model' | 18 | import { AuthUser } from './auth-user.model' |
20 | 19 | ||
@@ -178,12 +177,7 @@ export class AuthService { | |||
178 | this.mergeUserInformation(obj) | 177 | this.mergeUserInformation(obj) |
179 | .subscribe( | 178 | .subscribe( |
180 | res => { | 179 | res => { |
181 | this.user.displayNSFW = res.displayNSFW | 180 | this.user.patch(res) |
182 | this.user.autoPlayVideo = res.autoPlayVideo | ||
183 | this.user.role = res.role | ||
184 | this.user.videoChannels = res.videoChannels | ||
185 | this.user.account = res.account | ||
186 | |||
187 | this.user.save() | 181 | this.user.save() |
188 | 182 | ||
189 | this.userInformationLoaded.next(true) | 183 | this.userInformationLoaded.next(true) |
@@ -200,24 +194,13 @@ export class AuthService { | |||
200 | } | 194 | } |
201 | 195 | ||
202 | private handleLogin (obj: UserLoginWithUserInformation) { | 196 | private handleLogin (obj: UserLoginWithUserInformation) { |
203 | const hashUser: UserConstructorHash = { | ||
204 | id: obj.id, | ||
205 | username: obj.username, | ||
206 | role: obj.role, | ||
207 | email: obj.email, | ||
208 | displayNSFW: obj.displayNSFW, | ||
209 | autoPlayVideo: obj.autoPlayVideo, | ||
210 | videoQuota: obj.videoQuota, | ||
211 | videoChannels: obj.videoChannels, | ||
212 | account: obj.account | ||
213 | } | ||
214 | const hashTokens = { | 197 | const hashTokens = { |
215 | accessToken: obj.access_token, | 198 | accessToken: obj.access_token, |
216 | tokenType: obj.token_type, | 199 | tokenType: obj.token_type, |
217 | refreshToken: obj.refresh_token | 200 | refreshToken: obj.refresh_token |
218 | } | 201 | } |
219 | 202 | ||
220 | this.user = new AuthUser(hashUser, hashTokens) | 203 | this.user = new AuthUser(obj, hashTokens) |
221 | this.user.save() | 204 | this.user.save() |
222 | 205 | ||
223 | this.setStatus(AuthStatus.LoggedIn) | 206 | this.setStatus(AuthStatus.LoggedIn) |
diff --git a/client/src/app/shared/users/user.model.ts b/client/src/app/shared/users/user.model.ts index 83aae4463..4a94b032d 100644 --- a/client/src/app/shared/users/user.model.ts +++ b/client/src/app/shared/users/user.model.ts | |||
@@ -60,4 +60,10 @@ export class User implements UserServerModel { | |||
60 | getAvatarUrl () { | 60 | getAvatarUrl () { |
61 | return Account.GET_ACCOUNT_AVATAR_URL(this.account) | 61 | return Account.GET_ACCOUNT_AVATAR_URL(this.account) |
62 | } | 62 | } |
63 | |||
64 | patch (obj: UserServerModel) { | ||
65 | for (const key of Object.keys(obj)) { | ||
66 | this[key] = obj[key] | ||
67 | } | ||
68 | } | ||
63 | } | 69 | } |
diff --git a/client/src/app/shared/users/user.service.ts b/client/src/app/shared/users/user.service.ts index 58ddaa5ee..742fb0728 100644 --- a/client/src/app/shared/users/user.service.ts +++ b/client/src/app/shared/users/user.service.ts | |||
@@ -48,11 +48,10 @@ export class UserService { | |||
48 | .catch(res => this.restExtractor.handleError(res)) | 48 | .catch(res => this.restExtractor.handleError(res)) |
49 | } | 49 | } |
50 | 50 | ||
51 | getMyInformation () { | 51 | getMyVideoQuotaUsed () { |
52 | const url = UserService.BASE_USERS_URL + 'me' | 52 | const url = UserService.BASE_USERS_URL + '/me/video-quota-used' |
53 | 53 | ||
54 | return this.authHttp.get(url) | 54 | return this.authHttp.get(url) |
55 | .map((userHash: any) => new User(userHash)) | ||
56 | .catch(res => this.restExtractor.handleError(res)) | 55 | .catch(res => this.restExtractor.handleError(res)) |
57 | } | 56 | } |
58 | } | 57 | } |
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 193cc55ee..2040ff9d4 100644 --- a/client/src/app/videos/+video-edit/video-add.component.html +++ b/client/src/app/videos/+video-edit/video-add.component.html | |||
@@ -3,8 +3,6 @@ | |||
3 | Upload your video | 3 | Upload your video |
4 | </div> | 4 | </div> |
5 | 5 | ||
6 | <div *ngIf="error" class="alert alert-danger">{{ error }}</div> | ||
7 | |||
8 | <div *ngIf="!isUploadingVideo" class="upload-video-container"> | 6 | <div *ngIf="!isUploadingVideo" class="upload-video-container"> |
9 | <div class="upload-video"> | 7 | <div class="upload-video"> |
10 | <div class="icon icon-upload"></div> | 8 | <div class="icon icon-upload"></div> |
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 066f945fc..a86d9d3c2 100644 --- a/client/src/app/videos/+video-edit/video-add.component.ts +++ b/client/src/app/videos/+video-edit/video-add.component.ts | |||
@@ -2,7 +2,9 @@ import { HttpEventType, HttpResponse } from '@angular/common/http' | |||
2 | import { Component, OnInit, ViewChild } from '@angular/core' | 2 | import { Component, OnInit, ViewChild } from '@angular/core' |
3 | import { FormBuilder, FormGroup } from '@angular/forms' | 3 | import { FormBuilder, FormGroup } from '@angular/forms' |
4 | import { Router } from '@angular/router' | 4 | import { Router } from '@angular/router' |
5 | import { UserService } from '@app/shared' | ||
5 | import { NotificationsService } from 'angular2-notifications' | 6 | import { NotificationsService } from 'angular2-notifications' |
7 | import { BytesPipe } from 'ngx-pipes' | ||
6 | import { VideoPrivacy } from '../../../../../shared/models/videos' | 8 | import { VideoPrivacy } from '../../../../../shared/models/videos' |
7 | import { AuthService, ServerService } from '../../core' | 9 | import { AuthService, ServerService } from '../../core' |
8 | import { FormReactive } from '../../shared' | 10 | import { FormReactive } from '../../shared' |
@@ -31,12 +33,12 @@ export class VideoAddComponent extends FormReactive implements OnInit { | |||
31 | uuid: '' | 33 | uuid: '' |
32 | } | 34 | } |
33 | 35 | ||
34 | error: string = null | ||
35 | form: FormGroup | 36 | form: FormGroup |
36 | formErrors: { [ id: string ]: string } = {} | 37 | formErrors: { [ id: string ]: string } = {} |
37 | validationMessages: ValidatorMessage = {} | 38 | validationMessages: ValidatorMessage = {} |
38 | 39 | ||
39 | userVideoChannels = [] | 40 | userVideoChannels = [] |
41 | userVideoQuotaUsed = 0 | ||
40 | videoPrivacies = [] | 42 | videoPrivacies = [] |
41 | firstStepPrivacyId = 0 | 43 | firstStepPrivacyId = 0 |
42 | firstStepChannelId = 0 | 44 | firstStepChannelId = 0 |
@@ -46,6 +48,7 @@ export class VideoAddComponent extends FormReactive implements OnInit { | |||
46 | private router: Router, | 48 | private router: Router, |
47 | private notificationsService: NotificationsService, | 49 | private notificationsService: NotificationsService, |
48 | private authService: AuthService, | 50 | private authService: AuthService, |
51 | private userService: UserService, | ||
49 | private serverService: ServerService, | 52 | private serverService: ServerService, |
50 | private videoService: VideoService | 53 | private videoService: VideoService |
51 | ) { | 54 | ) { |
@@ -67,6 +70,9 @@ export class VideoAddComponent extends FormReactive implements OnInit { | |||
67 | populateAsyncUserVideoChannels(this.authService, this.userVideoChannels) | 70 | populateAsyncUserVideoChannels(this.authService, this.userVideoChannels) |
68 | .then(() => this.firstStepChannelId = this.userVideoChannels[0].id) | 71 | .then(() => this.firstStepChannelId = this.userVideoChannels[0].id) |
69 | 72 | ||
73 | this.userService.getMyVideoQuotaUsed() | ||
74 | .subscribe(data => this.userVideoQuotaUsed = data.videoQuotaUsed) | ||
75 | |||
70 | this.serverService.videoPrivaciesLoaded | 76 | this.serverService.videoPrivaciesLoaded |
71 | .subscribe( | 77 | .subscribe( |
72 | () => { | 78 | () => { |
@@ -89,6 +95,18 @@ export class VideoAddComponent extends FormReactive implements OnInit { | |||
89 | 95 | ||
90 | uploadFirstStep () { | 96 | uploadFirstStep () { |
91 | const videofile = this.videofileInput.nativeElement.files[0] | 97 | const videofile = this.videofileInput.nativeElement.files[0] |
98 | const videoQuota = this.authService.getUser().videoQuota | ||
99 | if ((this.userVideoQuotaUsed + videofile.size) > videoQuota) { | ||
100 | const bytePipes = new BytesPipe() | ||
101 | |||
102 | const msg = 'Your video quota is exceeded with this video ' + | ||
103 | `(video size: ${bytePipes.transform(videofile.size, 0)}, ` + | ||
104 | `used: ${bytePipes.transform(this.userVideoQuotaUsed, 0)}, ` + | ||
105 | `quota: ${bytePipes.transform(videoQuota, 0)})` | ||
106 | this.notificationsService.error('Error', msg) | ||
107 | return | ||
108 | } | ||
109 | |||
92 | const name = videofile.name.replace(/\.[^/.]+$/, '') | 110 | const name = videofile.name.replace(/\.[^/.]+$/, '') |
93 | const privacy = this.firstStepPrivacyId.toString() | 111 | const privacy = this.firstStepPrivacyId.toString() |
94 | const nsfw = false | 112 | const nsfw = false |
@@ -127,8 +145,9 @@ export class VideoAddComponent extends FormReactive implements OnInit { | |||
127 | 145 | ||
128 | err => { | 146 | err => { |
129 | // Reset progress | 147 | // Reset progress |
148 | this.isUploadingVideo = false | ||
130 | this.videoUploadPercents = 0 | 149 | this.videoUploadPercents = 0 |
131 | this.error = err.message | 150 | this.notificationsService.error('Error', err.message) |
132 | } | 151 | } |
133 | ) | 152 | ) |
134 | } | 153 | } |
@@ -152,7 +171,7 @@ export class VideoAddComponent extends FormReactive implements OnInit { | |||
152 | }, | 171 | }, |
153 | 172 | ||
154 | err => { | 173 | err => { |
155 | this.error = 'Cannot update the video.' | 174 | this.notificationsService.error('Error', err.message) |
156 | console.error(err) | 175 | console.error(err) |
157 | } | 176 | } |
158 | ) | 177 | ) |
diff --git a/client/src/app/videos/+video-edit/video-update.component.ts b/client/src/app/videos/+video-edit/video-update.component.ts index 941ef2478..7f41b56d8 100644 --- a/client/src/app/videos/+video-edit/video-update.component.ts +++ b/client/src/app/videos/+video-edit/video-update.component.ts | |||
@@ -21,7 +21,6 @@ import { VideoService } from '../../shared/video/video.service' | |||
21 | export class VideoUpdateComponent extends FormReactive implements OnInit { | 21 | export class VideoUpdateComponent extends FormReactive implements OnInit { |
22 | video: VideoEdit | 22 | video: VideoEdit |
23 | 23 | ||
24 | error: string = null | ||
25 | form: FormGroup | 24 | form: FormGroup |
26 | formErrors: { [ id: string ]: string } = {} | 25 | formErrors: { [ id: string ]: string } = {} |
27 | validationMessages: ValidatorMessage = {} | 26 | validationMessages: ValidatorMessage = {} |
@@ -82,7 +81,7 @@ export class VideoUpdateComponent extends FormReactive implements OnInit { | |||
82 | 81 | ||
83 | err => { | 82 | err => { |
84 | console.error(err) | 83 | console.error(err) |
85 | this.error = 'Cannot fetch video.' | 84 | this.notificationsService.error('Error', err.message) |
86 | } | 85 | } |
87 | ) | 86 | ) |
88 | } | 87 | } |
@@ -108,7 +107,7 @@ export class VideoUpdateComponent extends FormReactive implements OnInit { | |||
108 | }, | 107 | }, |
109 | 108 | ||
110 | err => { | 109 | err => { |
111 | this.error = 'Cannot update the video.' | 110 | this.notificationsService.error('Error', err.message) |
112 | console.error(err) | 111 | console.error(err) |
113 | } | 112 | } |
114 | ) | 113 | ) |