Add channels to upload form
authorChocobozzz <florian.bigard@gmail.com>
Wed, 25 Oct 2017 15:31:11 +0000 (17:31 +0200)
committerChocobozzz <florian.bigard@gmail.com>
Thu, 26 Oct 2017 07:11:38 +0000 (09:11 +0200)
client/src/app/app.component.ts
client/src/app/core/auth/auth-user.model.ts
client/src/app/core/auth/auth.service.ts
client/src/app/shared/forms/form-validators/video.ts
client/src/app/shared/users/user.service.ts
client/src/app/videos/+video-edit/video-add.component.html
client/src/app/videos/+video-edit/video-add.component.ts
client/src/app/videos/video-list/video-list.component.ts
server/tests/api/friends-advanced.ts

index 7d890e72aa37eaf40b332237c2d28365bf542786..984470d69257fe8056266a86438b26081990af18 100644 (file)
@@ -37,7 +37,7 @@ export class AppComponent implements OnInit {
 
     if (this.authService.isLoggedIn()) {
       // The service will automatically redirect to the login page if the token is not valid anymore
-      this.userService.checkTokenValidity()
+      this.authService.refreshUserInformation()
     }
 
     // Load custom data from server
index 4155aea1927a1f131e5208d6a583378d049dd365..81bff99a040bdee257799ac007d09797352b6a47 100644 (file)
@@ -1,6 +1,6 @@
 // Do not use the barrel (dependency loop)
 import { UserRole } from '../../../../../shared/models/users/user-role.type'
-import { User } from '../../shared/users/user.model'
+import { User, UserConstructorHash } from '../../shared/users/user.model'
 
 export type TokenOptions = {
   accessToken: string
@@ -100,13 +100,7 @@ export class AuthUser extends User {
     Tokens.flush()
   }
 
-  constructor (userHash: {
-    id: number,
-    username: string,
-    role: UserRole,
-    email: string,
-    displayNSFW: boolean
-  }, hashTokens: TokenOptions) {
+  constructor (userHash: UserConstructorHash, hashTokens: TokenOptions) {
     super(userHash)
     this.tokens = new Tokens(hashTokens)
   }
index 4a8814c4e4c5dc6e077952606380fe1f911cd73c..9ac9ba7bb1fcd7a20b2f168af4253d779db998d4 100644 (file)
@@ -11,11 +11,17 @@ import { NotificationsService } from 'angular2-notifications'
 
 import { AuthStatus } from './auth-status.model'
 import { AuthUser } from './auth-user.model'
-import { OAuthClientLocal, UserRole, UserRefreshToken } from '../../../../../shared'
+import {
+  OAuthClientLocal,
+  UserRole,
+  UserRefreshToken,
+  VideoChannel,
+  User as UserServerModel
+} from '../../../../../shared'
 // Do not use the barrel (dependency loop)
 import { RestExtractor } from '../../shared/rest'
 import { UserLogin } from '../../../../../shared/models/users/user-login.model'
-import { User } from '../../shared/users/user.model'
+import { User, UserConstructorHash } from '../../shared/users/user.model'
 
 interface UserLoginWithUsername extends UserLogin {
   access_token: string
@@ -33,6 +39,12 @@ interface UserLoginWithUserInformation extends UserLogin {
   role: UserRole
   displayNSFW: boolean
   email: string
+  videoQuota: number
+  author: {
+    id: number
+    uuid: string
+  }
+  videoChannels: VideoChannel[]
 }
 
 @Injectable()
@@ -197,6 +209,8 @@ export class AuthService {
           res => {
             this.user.displayNSFW = res.displayNSFW
             this.user.role = res.role
+            this.user.videoChannels = res.videoChannels
+            this.user.author = res.author
 
             this.user.save()
           }
@@ -207,13 +221,16 @@ export class AuthService {
     // User is not loaded yet, set manually auth header
     const headers = new HttpHeaders().set('Authorization', `${obj.token_type} ${obj.access_token}`)
 
-    return this.http.get<User>(AuthService.BASE_USER_INFORMATION_URL, { headers })
+    return this.http.get<UserServerModel>(AuthService.BASE_USER_INFORMATION_URL, { headers })
                     .map(res => {
                       const newProperties = {
-                        id: res.id as number,
-                        role: res.role as UserRole,
-                        displayNSFW: res.displayNSFW as boolean,
-                        email: res.email as string
+                        id: res.id,
+                        role: res.role,
+                        displayNSFW: res.displayNSFW,
+                        email: res.email,
+                        videoQuota: res.videoQuota,
+                        author: res.author,
+                        videoChannels: res.videoChannels
                       }
 
                       return Object.assign(obj, newProperties)
@@ -222,18 +239,23 @@ export class AuthService {
   }
 
   private handleLogin (obj: UserLoginWithUserInformation) {
-    const id = obj.id
-    const username = obj.username
-    const role = obj.role
-    const email = obj.email
-    const displayNSFW = obj.displayNSFW
+    const hashUser: UserConstructorHash = {
+      id: obj.id,
+      username: obj.username,
+      role: obj.role,
+      email: obj.email,
+      displayNSFW: obj.displayNSFW,
+      videoQuota: obj.videoQuota,
+      videoChannels: obj.videoChannels,
+      author: obj.author
+    }
     const hashTokens = {
       accessToken: obj.access_token,
       tokenType: obj.token_type,
       refreshToken: obj.refresh_token
     }
 
-    this.user = new AuthUser({ id, username, role, displayNSFW, email }, hashTokens)
+    this.user = new AuthUser(hashUser, hashTokens)
     this.user.save()
 
     this.setStatus(AuthStatus.LoggedIn)
index 32b1f1c2ebf0fb8fc02dffa9f852450a2383caf0..213ab15db2caa82d0a70c2ab1d7b9d5eef73b979 100644 (file)
@@ -28,6 +28,13 @@ export const VIDEO_LANGUAGE = {
   MESSAGES: {}
 }
 
+export const VIDEO_CHANNEL = {
+  VALIDATORS: [ Validators.required ],
+  MESSAGES: {
+    'required': 'Video channel is required.'
+  }
+}
+
 export const VIDEO_DESCRIPTION = {
   VALIDATORS: [ Validators.required, Validators.minLength(3), Validators.maxLength(250) ],
   MESSAGES: {
index 5c089d221a3b6d8cf0f57c4f872bc989c22facc1..6d1017fc9b0fc85ca364adb2e9fe45df6dc553b8 100644 (file)
@@ -15,13 +15,6 @@ export class UserService {
     private restExtractor: RestExtractor
   ) {}
 
-  checkTokenValidity () {
-    const url = UserService.BASE_USERS_URL + 'me'
-
-    // AuthHttp will redirect us to the login page if the token is not valid anymore
-    this.authHttp.get(url).subscribe()
-  }
-
   changePassword (newPassword: string) {
     const url = UserService.BASE_USERS_URL + 'me'
     const body: UserUpdateMe = {
index 698152ff9ee9da3382175bc7950f43135a4a69d2..7946c0879d7294887809921729b1e4b8b535cacb 100644 (file)
         >
       </div>
 
+      <div class="form-group">
+        <label for="category">Channel</label>
+        <select class="form-control" id="channelId" formControlName="channelId">
+          <option></option>
+          <option *ngFor="let channel of userVideoChannels" [value]="channel.id">{{ channel.label }}</option>
+        </select>
+
+        <div *ngIf="formErrors.channelId" class="alert alert-danger">
+          {{ formErrors.channelId }}
+        </div>
+      </div>
+
       <div class="form-group">
         <label for="category">Category</label>
         <select class="form-control" id="category" formControlName="category">
index 8043bb41c88cb0c689a0570019535b27b53d253f..92b03e8c96cae9c6898aa871929a3e139ef38f0d 100644 (file)
@@ -12,9 +12,10 @@ import {
   VIDEO_LANGUAGE,
   VIDEO_DESCRIPTION,
   VIDEO_TAGS,
+  VIDEO_CHANNEL,
   VIDEO_FILE
 } from '../../shared'
-import { ServerService } from '../../core'
+import { AuthService, ServerService } from '../../core'
 import { VideoService } from '../shared'
 import { VideoCreate } from '../../../../../shared'
 import { HttpEventType, HttpResponse } from '@angular/common/http'
@@ -33,6 +34,7 @@ export class VideoAddComponent extends FormReactive implements OnInit {
   videoCategories = []
   videoLicences = []
   videoLanguages = []
+  userVideoChannels = []
 
   tagValidators = VIDEO_TAGS.VALIDATORS
   tagValidatorsMessages = VIDEO_TAGS.MESSAGES
@@ -44,6 +46,7 @@ export class VideoAddComponent extends FormReactive implements OnInit {
     category: '',
     licence: '',
     language: '',
+    channelId: '',
     description: '',
     videofile: ''
   }
@@ -52,6 +55,7 @@ export class VideoAddComponent extends FormReactive implements OnInit {
     category: VIDEO_CATEGORY.MESSAGES,
     licence: VIDEO_LICENCE.MESSAGES,
     language: VIDEO_LANGUAGE.MESSAGES,
+    channelId: VIDEO_CHANNEL.MESSAGES,
     description: VIDEO_DESCRIPTION.MESSAGES,
     videofile: VIDEO_FILE.MESSAGES
   }
@@ -60,6 +64,7 @@ export class VideoAddComponent extends FormReactive implements OnInit {
     private formBuilder: FormBuilder,
     private router: Router,
     private notificationsService: NotificationsService,
+    private authService: AuthService,
     private serverService: ServerService,
     private videoService: VideoService
   ) {
@@ -77,6 +82,7 @@ export class VideoAddComponent extends FormReactive implements OnInit {
       category: [ '', VIDEO_CATEGORY.VALIDATORS ],
       licence: [ '', VIDEO_LICENCE.VALIDATORS ],
       language: [ '', VIDEO_LANGUAGE.VALIDATORS ],
+      channelId: [ this.userVideoChannels[0].id, VIDEO_CHANNEL.VALIDATORS ],
       description: [ '', VIDEO_DESCRIPTION.VALIDATORS ],
       videofile: [ '', VIDEO_FILE.VALIDATORS ],
       tags: [ '' ]
@@ -90,6 +96,9 @@ export class VideoAddComponent extends FormReactive implements OnInit {
     this.videoLicences = this.serverService.getVideoLicences()
     this.videoLanguages = this.serverService.getVideoLanguages()
 
+    const user = this.authService.getUser()
+    this.userVideoChannels = user.videoChannels.map(v => ({ id: v.id, label: v.name }))
+
     this.buildForm()
   }
 
@@ -122,6 +131,7 @@ export class VideoAddComponent extends FormReactive implements OnInit {
     const category = formValue.category
     const licence = formValue.licence
     const language = formValue.language
+    const channelId = formValue.channelId
     const description = formValue.description
     const tags = formValue.tags
     const videofile = this.videofileInput.nativeElement.files[0]
@@ -131,6 +141,7 @@ export class VideoAddComponent extends FormReactive implements OnInit {
     formData.append('category', '' + category)
     formData.append('nsfw', '' + nsfw)
     formData.append('licence', '' + licence)
+    formData.append('channelId', '' + channelId)
     formData.append('videofile', videofile)
 
     // Language is optional
index 4714ce01eb690c77cd50d9c4536569fb1d15d6f2..d2f0ae0450ef4d19d7ebbc2a9f6cdc646653ccd7 100644 (file)
@@ -1,4 +1,4 @@
-import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core'
+import { Component, OnDestroy, OnInit } from '@angular/core'
 import { ActivatedRoute, Router } from '@angular/router'
 import { Subscription } from 'rxjs/Subscription'
 import { BehaviorSubject } from 'rxjs/BehaviorSubject'
@@ -11,7 +11,6 @@ import {
   VideoService,
   VideoPagination
 } from '../shared'
-import { AuthService, AuthUser } from '../../core'
 import { Search, SearchField, SearchService } from '../../shared'
 
 @Component({
@@ -27,7 +26,6 @@ export class VideoListComponent implements OnInit, OnDestroy {
     totalItems: null
   }
   sort: SortField
-  user: AuthUser = null
   videos: Video[] = []
 
   private search: Search
@@ -36,8 +34,6 @@ export class VideoListComponent implements OnInit, OnDestroy {
 
   constructor (
     private notificationsService: NotificationsService,
-    private authService: AuthService,
-    private changeDetector: ChangeDetectorRef,
     private router: Router,
     private route: ActivatedRoute,
     private videoService: VideoService,
@@ -45,10 +41,6 @@ export class VideoListComponent implements OnInit, OnDestroy {
   ) {}
 
   ngOnInit () {
-    if (this.authService.isLoggedIn()) {
-      this.user = AuthUser.load()
-    }
-
     // Subscribe to route changes
     this.subActivatedRoute = this.route.params.subscribe(routeParams => {
       this.loadRouteParams(routeParams)
index fbfdf227e3c6de913acd026bea8604f648ba548c..139019398f7b940963c4a2c0bb4453ece692b200 100644 (file)
@@ -221,11 +221,11 @@ describe('Test advanced friends', function () {
   // Pod 4 is friend with : 2 3
   // Pod 6 is friend with : 2 3
   it('Should make friends between pod 1, 2, 3 and 6 and exchange their videos', async function () {
-    this.timeout(20000)
+    this.timeout(30000)
 
     await makeFriendsWrapper(1)
 
-    await wait(11000)
+    await wait(22000)
 
     const res = await getVideosWrapper(1)
     const videos = res.body.data