aboutsummaryrefslogtreecommitdiffhomepage
path: root/client/src/app/videos
diff options
context:
space:
mode:
authorChocobozzz <florian.bigard@gmail.com>2017-12-01 18:56:26 +0100
committerChocobozzz <florian.bigard@gmail.com>2017-12-01 18:56:26 +0100
commit202f6b6c9dcc9b0aec4b0c1b15e455c22a7952a7 (patch)
tree605df063371b6be32ca0773bf2917b0c5d9163ae /client/src/app/videos
parentc30745f342480b59fb0856a059c8c2fbffbcfc6a (diff)
downloadPeerTube-202f6b6c9dcc9b0aec4b0c1b15e455c22a7952a7.tar.gz
PeerTube-202f6b6c9dcc9b0aec4b0c1b15e455c22a7952a7.tar.zst
PeerTube-202f6b6c9dcc9b0aec4b0c1b15e455c22a7952a7.zip
Begin videos of an account
Diffstat (limited to 'client/src/app/videos')
-rw-r--r--client/src/app/videos/+video-edit/shared/video-edit.module.ts3
-rw-r--r--client/src/app/videos/+video-edit/video-add.component.ts22
-rw-r--r--client/src/app/videos/+video-edit/video-update.component.ts19
-rw-r--r--client/src/app/videos/+video-watch/video-download.component.ts4
-rw-r--r--client/src/app/videos/+video-watch/video-report.component.ts8
-rw-r--r--client/src/app/videos/+video-watch/video-share.component.ts4
-rw-r--r--client/src/app/videos/+video-watch/video-watch.component.ts4
-rw-r--r--client/src/app/videos/+video-watch/video-watch.module.ts5
-rw-r--r--client/src/app/videos/shared/index.ts6
-rw-r--r--client/src/app/videos/shared/sort-field.type.ts5
-rw-r--r--client/src/app/videos/shared/video-details.model.ts84
-rw-r--r--client/src/app/videos/shared/video-edit.model.ts50
-rw-r--r--client/src/app/videos/shared/video-pagination.model.ts5
-rw-r--r--client/src/app/videos/shared/video.model.ts90
-rw-r--r--client/src/app/videos/shared/video.service.ts176
-rw-r--r--client/src/app/videos/video-list/shared/abstract-video-list.html19
-rw-r--r--client/src/app/videos/video-list/shared/abstract-video-list.scss0
-rw-r--r--client/src/app/videos/video-list/shared/abstract-video-list.ts121
-rw-r--r--client/src/app/videos/video-list/shared/index.ts1
-rw-r--r--client/src/app/videos/video-list/shared/video-miniature.component.html11
-rw-r--r--client/src/app/videos/video-list/shared/video-miniature.component.scss29
-rw-r--r--client/src/app/videos/video-list/shared/video-miniature.component.ts4
-rw-r--r--client/src/app/videos/video-list/video-recently-added.component.ts8
-rw-r--r--client/src/app/videos/video-list/video-trending.component.ts8
-rw-r--r--client/src/app/videos/videos.module.ts9
25 files changed, 43 insertions, 652 deletions
diff --git a/client/src/app/videos/+video-edit/shared/video-edit.module.ts b/client/src/app/videos/+video-edit/shared/video-edit.module.ts
index c64cea920..cdab694f9 100644
--- a/client/src/app/videos/+video-edit/shared/video-edit.module.ts
+++ b/client/src/app/videos/+video-edit/shared/video-edit.module.ts
@@ -3,7 +3,7 @@ import { NgModule } from '@angular/core'
3import { TagInputModule } from 'ngx-chips' 3import { TagInputModule } from 'ngx-chips'
4import { TabsModule } from 'ngx-bootstrap/tabs' 4import { TabsModule } from 'ngx-bootstrap/tabs'
5 5
6import { VideoService, MarkdownService, VideoDescriptionComponent } from '../../shared' 6import { MarkdownService, VideoDescriptionComponent } from '../../shared'
7import { SharedModule } from '../../../shared' 7import { SharedModule } from '../../../shared'
8 8
9@NgModule({ 9@NgModule({
@@ -26,7 +26,6 @@ import { SharedModule } from '../../../shared'
26 ], 26 ],
27 27
28 providers: [ 28 providers: [
29 VideoService,
30 MarkdownService 29 MarkdownService
31 ] 30 ]
32}) 31})
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 76bfbb515..989addbd7 100644
--- a/client/src/app/videos/+video-edit/video-add.component.ts
+++ b/client/src/app/videos/+video-edit/video-add.component.ts
@@ -1,25 +1,23 @@
1import { HttpEventType, HttpResponse } from '@angular/common/http'
1import { Component, OnInit, ViewChild } from '@angular/core' 2import { Component, OnInit, ViewChild } from '@angular/core'
2import { FormBuilder, FormGroup } from '@angular/forms' 3import { FormBuilder, FormGroup } from '@angular/forms'
3import { Router } from '@angular/router' 4import { Router } from '@angular/router'
4
5import { NotificationsService } from 'angular2-notifications' 5import { NotificationsService } from 'angular2-notifications'
6 6import { VideoService } from 'app/shared/video/video.service'
7import { VideoCreate } from '../../../../../shared'
8import { AuthService, ServerService } from '../../core'
7import { 9import {
8 FormReactive, 10 FormReactive,
9 VIDEO_NAME,
10 VIDEO_CATEGORY, 11 VIDEO_CATEGORY,
11 VIDEO_LICENCE,
12 VIDEO_LANGUAGE,
13 VIDEO_DESCRIPTION,
14 VIDEO_TAGS,
15 VIDEO_CHANNEL, 12 VIDEO_CHANNEL,
13 VIDEO_DESCRIPTION,
16 VIDEO_FILE, 14 VIDEO_FILE,
17 VIDEO_PRIVACY 15 VIDEO_LANGUAGE,
16 VIDEO_LICENCE,
17 VIDEO_NAME,
18 VIDEO_PRIVACY,
19 VIDEO_TAGS
18} from '../../shared' 20} from '../../shared'
19import { AuthService, ServerService } from '../../core'
20import { VideoService } from '../shared'
21import { VideoCreate } from '../../../../../shared'
22import { HttpEventType, HttpResponse } from '@angular/common/http'
23 21
24@Component({ 22@Component({
25 selector: 'my-videos-add', 23 selector: 'my-videos-add',
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 0e966cb50..017781866 100644
--- a/client/src/app/videos/+video-edit/video-update.component.ts
+++ b/client/src/app/videos/+video-edit/video-update.component.ts
@@ -1,23 +1,22 @@
1import { Component, OnInit } from '@angular/core' 1import { Component, OnInit } from '@angular/core'
2import { FormBuilder, FormGroup } from '@angular/forms' 2import { FormBuilder, FormGroup } from '@angular/forms'
3import { ActivatedRoute, Router } from '@angular/router' 3import { ActivatedRoute, Router } from '@angular/router'
4import 'rxjs/add/observable/forkJoin'
5
6import { NotificationsService } from 'angular2-notifications' 4import { NotificationsService } from 'angular2-notifications'
7 5import 'rxjs/add/observable/forkJoin'
6import { VideoPrivacy } from '../../../../../shared/models/videos/video-privacy.enum'
8import { ServerService } from '../../core' 7import { ServerService } from '../../core'
9import { 8import {
10 FormReactive, 9 FormReactive,
11 VIDEO_NAME,
12 VIDEO_CATEGORY, 10 VIDEO_CATEGORY,
13 VIDEO_LICENCE,
14 VIDEO_LANGUAGE,
15 VIDEO_DESCRIPTION, 11 VIDEO_DESCRIPTION,
16 VIDEO_TAGS, 12 VIDEO_LANGUAGE,
17 VIDEO_PRIVACY 13 VIDEO_LICENCE,
14 VIDEO_NAME,
15 VIDEO_PRIVACY,
16 VIDEO_TAGS
18} from '../../shared' 17} from '../../shared'
19import { VideoEdit, VideoService } from '../shared' 18import { VideoService } from '../../shared/video/video.service'
20import { VideoPrivacy } from '../../../../../shared/models/videos/video-privacy.enum' 19import { VideoEdit } from '../../shared/video/video-edit.model'
21 20
22@Component({ 21@Component({
23 selector: 'my-videos-update', 22 selector: 'my-videos-update',
diff --git a/client/src/app/videos/+video-watch/video-download.component.ts b/client/src/app/videos/+video-watch/video-download.component.ts
index c32f8d586..010a246cd 100644
--- a/client/src/app/videos/+video-watch/video-download.component.ts
+++ b/client/src/app/videos/+video-watch/video-download.component.ts
@@ -1,8 +1,6 @@
1import { Component, Input, ViewChild } from '@angular/core' 1import { Component, Input, ViewChild } from '@angular/core'
2
3import { ModalDirective } from 'ngx-bootstrap/modal' 2import { ModalDirective } from 'ngx-bootstrap/modal'
4 3import { VideoDetails } from '../../shared/video/video-details.model'
5import { VideoDetails } from '../shared'
6 4
7@Component({ 5@Component({
8 selector: 'my-video-download', 6 selector: 'my-video-download',
diff --git a/client/src/app/videos/+video-watch/video-report.component.ts b/client/src/app/videos/+video-watch/video-report.component.ts
index fc9b5a9d4..b94e4144e 100644
--- a/client/src/app/videos/+video-watch/video-report.component.ts
+++ b/client/src/app/videos/+video-watch/video-report.component.ts
@@ -1,11 +1,9 @@
1import { Component, Input, OnInit, ViewChild } from '@angular/core' 1import { Component, Input, OnInit, ViewChild } from '@angular/core'
2import { FormBuilder, FormGroup } from '@angular/forms' 2import { FormBuilder, FormGroup } from '@angular/forms'
3
4import { ModalDirective } from 'ngx-bootstrap/modal'
5import { NotificationsService } from 'angular2-notifications' 3import { NotificationsService } from 'angular2-notifications'
6 4import { ModalDirective } from 'ngx-bootstrap/modal'
7import { FormReactive, VideoAbuseService, VIDEO_ABUSE_REASON } from '../../shared' 5import { FormReactive, VIDEO_ABUSE_REASON, VideoAbuseService } from '../../shared'
8import { VideoDetails, VideoService } from '../shared' 6import { VideoDetails } from '../../shared/video/video-details.model'
9 7
10@Component({ 8@Component({
11 selector: 'my-video-report', 9 selector: 'my-video-report',
diff --git a/client/src/app/videos/+video-watch/video-share.component.ts b/client/src/app/videos/+video-watch/video-share.component.ts
index aeef65ecf..4df9adf29 100644
--- a/client/src/app/videos/+video-watch/video-share.component.ts
+++ b/client/src/app/videos/+video-watch/video-share.component.ts
@@ -1,8 +1,6 @@
1import { Component, Input, ViewChild } from '@angular/core' 1import { Component, Input, ViewChild } from '@angular/core'
2
3import { ModalDirective } from 'ngx-bootstrap/modal' 2import { ModalDirective } from 'ngx-bootstrap/modal'
4 3import { VideoDetails } from '../../shared/video/video-details.model'
5import { VideoDetails } from '../shared'
6 4
7@Component({ 5@Component({
8 selector: 'my-video-share', 6 selector: 'my-video-share',
diff --git a/client/src/app/videos/+video-watch/video-watch.component.ts b/client/src/app/videos/+video-watch/video-watch.component.ts
index b26f3092f..eac676be8 100644
--- a/client/src/app/videos/+video-watch/video-watch.component.ts
+++ b/client/src/app/videos/+video-watch/video-watch.component.ts
@@ -2,6 +2,7 @@ import { Component, ElementRef, OnDestroy, OnInit, ViewChild } from '@angular/co
2import { ActivatedRoute, Router } from '@angular/router' 2import { ActivatedRoute, Router } from '@angular/router'
3import { MetaService } from '@ngx-meta/core' 3import { MetaService } from '@ngx-meta/core'
4import { NotificationsService } from 'angular2-notifications' 4import { NotificationsService } from 'angular2-notifications'
5import { VideoService } from 'app/shared/video/video.service'
5import { Observable } from 'rxjs/Observable' 6import { Observable } from 'rxjs/Observable'
6import { Subscription } from 'rxjs/Subscription' 7import { Subscription } from 'rxjs/Subscription'
7import videojs from 'video.js' 8import videojs from 'video.js'
@@ -9,10 +10,11 @@ import { UserVideoRateType, VideoRateType } from '../../../../../shared'
9import '../../../assets/player/peertube-videojs-plugin' 10import '../../../assets/player/peertube-videojs-plugin'
10import { AuthService, ConfirmService } from '../../core' 11import { AuthService, ConfirmService } from '../../core'
11import { VideoBlacklistService } from '../../shared' 12import { VideoBlacklistService } from '../../shared'
12import { MarkdownService, VideoDetails, VideoService } from '../shared' 13import { MarkdownService } from '../shared'
13import { VideoDownloadComponent } from './video-download.component' 14import { VideoDownloadComponent } from './video-download.component'
14import { VideoReportComponent } from './video-report.component' 15import { VideoReportComponent } from './video-report.component'
15import { VideoShareComponent } from './video-share.component' 16import { VideoShareComponent } from './video-share.component'
17import { VideoDetails } from '../../shared/video/video-details.model'
16 18
17@Component({ 19@Component({
18 selector: 'my-video-watch', 20 selector: 'my-video-watch',
diff --git a/client/src/app/videos/+video-watch/video-watch.module.ts b/client/src/app/videos/+video-watch/video-watch.module.ts
index 1b983200d..0b1dd5c15 100644
--- a/client/src/app/videos/+video-watch/video-watch.module.ts
+++ b/client/src/app/videos/+video-watch/video-watch.module.ts
@@ -1,7 +1,7 @@
1import { NgModule } from '@angular/core' 1import { NgModule } from '@angular/core'
2 2
3import { VideoWatchRoutingModule } from './video-watch-routing.module' 3import { VideoWatchRoutingModule } from './video-watch-routing.module'
4import { VideoService, MarkdownService } from '../shared' 4import { MarkdownService } from '../shared'
5import { SharedModule } from '../../shared' 5import { SharedModule } from '../../shared'
6 6
7import { VideoWatchComponent } from './video-watch.component' 7import { VideoWatchComponent } from './video-watch.component'
@@ -28,8 +28,7 @@ import { VideoDownloadComponent } from './video-download.component'
28 ], 28 ],
29 29
30 providers: [ 30 providers: [
31 MarkdownService, 31 MarkdownService
32 VideoService
33 ] 32 ]
34}) 33})
35export class VideoWatchModule { } 34export class VideoWatchModule { }
diff --git a/client/src/app/videos/shared/index.ts b/client/src/app/videos/shared/index.ts
index 3f1458088..3c72ed895 100644
--- a/client/src/app/videos/shared/index.ts
+++ b/client/src/app/videos/shared/index.ts
@@ -1,8 +1,2 @@
1export * from './sort-field.type'
2export * from './markdown.service' 1export * from './markdown.service'
3export * from './video.model'
4export * from './video-details.model'
5export * from './video-edit.model'
6export * from './video.service'
7export * from './video-description.component' 2export * from './video-description.component'
8export * from './video-pagination.model'
diff --git a/client/src/app/videos/shared/sort-field.type.ts b/client/src/app/videos/shared/sort-field.type.ts
deleted file mode 100644
index 776f360f8..000000000
--- a/client/src/app/videos/shared/sort-field.type.ts
+++ /dev/null
@@ -1,5 +0,0 @@
1export type SortField = 'name' | '-name'
2 | 'duration' | '-duration'
3 | 'createdAt' | '-createdAt'
4 | 'views' | '-views'
5 | 'likes' | '-likes'
diff --git a/client/src/app/videos/shared/video-details.model.ts b/client/src/app/videos/shared/video-details.model.ts
deleted file mode 100644
index 64cb4f847..000000000
--- a/client/src/app/videos/shared/video-details.model.ts
+++ /dev/null
@@ -1,84 +0,0 @@
1import { Video } from './video.model'
2import { AuthUser } from '../../core'
3import {
4 VideoDetails as VideoDetailsServerModel,
5 VideoFile,
6 VideoChannel,
7 VideoResolution,
8 UserRight,
9 VideoPrivacy
10} from '../../../../../shared'
11
12export class VideoDetails extends Video implements VideoDetailsServerModel {
13 account: string
14 by: string
15 createdAt: Date
16 updatedAt: Date
17 categoryLabel: string
18 category: number
19 licenceLabel: string
20 licence: number
21 languageLabel: string
22 language: number
23 description: string
24 duration: number
25 durationLabel: string
26 id: number
27 uuid: string
28 isLocal: boolean
29 name: string
30 serverHost: string
31 tags: string[]
32 thumbnailPath: string
33 thumbnailUrl: string
34 previewPath: string
35 previewUrl: string
36 embedPath: string
37 embedUrl: string
38 views: number
39 likes: number
40 dislikes: number
41 nsfw: boolean
42 descriptionPath: string
43 files: VideoFile[]
44 channel: VideoChannel
45 privacy: VideoPrivacy
46 privacyLabel: string
47
48 constructor (hash: VideoDetailsServerModel) {
49 super(hash)
50
51 this.privacy = hash.privacy
52 this.privacyLabel = hash.privacyLabel
53 this.descriptionPath = hash.descriptionPath
54 this.files = hash.files
55 this.channel = hash.channel
56 }
57
58 getAppropriateMagnetUri (actualDownloadSpeed = 0) {
59 if (this.files === undefined || this.files.length === 0) return ''
60 if (this.files.length === 1) return this.files[0].magnetUri
61
62 // Find first video that is good for our download speed (remember they are sorted)
63 let betterResolutionFile = this.files.find(f => actualDownloadSpeed > (f.size / this.duration))
64
65 // If the download speed is too bad, return the lowest resolution we have
66 if (betterResolutionFile === undefined) {
67 betterResolutionFile = this.files.find(f => f.resolution === VideoResolution.H_240P)
68 }
69
70 return betterResolutionFile.magnetUri
71 }
72
73 isRemovableBy (user: AuthUser) {
74 return user && this.isLocal === true && (this.account === user.username || user.hasRight(UserRight.REMOVE_ANY_VIDEO))
75 }
76
77 isBlackistableBy (user: AuthUser) {
78 return user && user.hasRight(UserRight.MANAGE_VIDEO_BLACKLIST) === true && this.isLocal === false
79 }
80
81 isUpdatableBy (user: AuthUser) {
82 return user && this.isLocal === true && user.username === this.account
83 }
84}
diff --git a/client/src/app/videos/shared/video-edit.model.ts b/client/src/app/videos/shared/video-edit.model.ts
deleted file mode 100644
index 88d23a59f..000000000
--- a/client/src/app/videos/shared/video-edit.model.ts
+++ /dev/null
@@ -1,50 +0,0 @@
1import { VideoDetails } from './video-details.model'
2import { VideoPrivacy } from '../../../../../shared/models/videos/video-privacy.enum'
3
4export class VideoEdit {
5 category: number
6 licence: number
7 language: number
8 description: string
9 name: string
10 tags: string[]
11 nsfw: boolean
12 channel: number
13 privacy: VideoPrivacy
14 uuid?: string
15 id?: number
16
17 constructor (videoDetails: VideoDetails) {
18 this.id = videoDetails.id
19 this.uuid = videoDetails.uuid
20 this.category = videoDetails.category
21 this.licence = videoDetails.licence
22 this.language = videoDetails.language
23 this.description = videoDetails.description
24 this.name = videoDetails.name
25 this.tags = videoDetails.tags
26 this.nsfw = videoDetails.nsfw
27 this.channel = videoDetails.channel.id
28 this.privacy = videoDetails.privacy
29 }
30
31 patch (values: Object) {
32 Object.keys(values).forEach((key) => {
33 this[key] = values[key]
34 })
35 }
36
37 toJSON () {
38 return {
39 category: this.category,
40 licence: this.licence,
41 language: this.language,
42 description: this.description,
43 name: this.name,
44 tags: this.tags,
45 nsfw: this.nsfw,
46 channel: this.channel,
47 privacy: this.privacy
48 }
49 }
50}
diff --git a/client/src/app/videos/shared/video-pagination.model.ts b/client/src/app/videos/shared/video-pagination.model.ts
deleted file mode 100644
index 9e71769cb..000000000
--- a/client/src/app/videos/shared/video-pagination.model.ts
+++ /dev/null
@@ -1,5 +0,0 @@
1export interface VideoPagination {
2 currentPage: number
3 itemsPerPage: number
4 totalItems: number
5}
diff --git a/client/src/app/videos/shared/video.model.ts b/client/src/app/videos/shared/video.model.ts
deleted file mode 100644
index 0dd41d71b..000000000
--- a/client/src/app/videos/shared/video.model.ts
+++ /dev/null
@@ -1,90 +0,0 @@
1import { Video as VideoServerModel } from '../../../../../shared'
2import { User } from '../../shared'
3
4export class Video implements VideoServerModel {
5 account: string
6 by: string
7 createdAt: Date
8 updatedAt: Date
9 categoryLabel: string
10 category: number
11 licenceLabel: string
12 licence: number
13 languageLabel: string
14 language: number
15 description: string
16 duration: number
17 durationLabel: string
18 id: number
19 uuid: string
20 isLocal: boolean
21 name: string
22 serverHost: string
23 tags: string[]
24 thumbnailPath: string
25 thumbnailUrl: string
26 previewPath: string
27 previewUrl: string
28 embedPath: string
29 embedUrl: string
30 views: number
31 likes: number
32 dislikes: number
33 nsfw: boolean
34
35 private static createByString (account: string, serverHost: string) {
36 return account + '@' + serverHost
37 }
38
39 private static createDurationString (duration: number) {
40 const minutes = Math.floor(duration / 60)
41 const seconds = duration % 60
42 const minutesPadding = minutes >= 10 ? '' : '0'
43 const secondsPadding = seconds >= 10 ? '' : '0'
44
45 return minutesPadding + minutes.toString() + ':' + secondsPadding + seconds.toString()
46 }
47
48 constructor (hash: VideoServerModel) {
49 let absoluteAPIUrl = API_URL
50 if (!absoluteAPIUrl) {
51 // The API is on the same domain
52 absoluteAPIUrl = window.location.origin
53 }
54
55 this.account = hash.account
56 this.createdAt = new Date(hash.createdAt.toString())
57 this.categoryLabel = hash.categoryLabel
58 this.category = hash.category
59 this.licenceLabel = hash.licenceLabel
60 this.licence = hash.licence
61 this.languageLabel = hash.languageLabel
62 this.language = hash.language
63 this.description = hash.description
64 this.duration = hash.duration
65 this.durationLabel = Video.createDurationString(hash.duration)
66 this.id = hash.id
67 this.uuid = hash.uuid
68 this.isLocal = hash.isLocal
69 this.name = hash.name
70 this.serverHost = hash.serverHost
71 this.tags = hash.tags
72 this.thumbnailPath = hash.thumbnailPath
73 this.thumbnailUrl = absoluteAPIUrl + hash.thumbnailPath
74 this.previewPath = hash.previewPath
75 this.previewUrl = absoluteAPIUrl + hash.previewPath
76 this.embedPath = hash.embedPath
77 this.embedUrl = absoluteAPIUrl + hash.embedPath
78 this.views = hash.views
79 this.likes = hash.likes
80 this.dislikes = hash.dislikes
81 this.nsfw = hash.nsfw
82
83 this.by = Video.createByString(hash.account, hash.serverHost)
84 }
85
86 isVideoNSFWForUser (user: User) {
87 // If the video is NSFW and the user is not logged in, or the user does not want to display NSFW videos...
88 return (this.nsfw && (!user || user.displayNSFW === false))
89 }
90}
diff --git a/client/src/app/videos/shared/video.service.ts b/client/src/app/videos/shared/video.service.ts
deleted file mode 100644
index 5d25a26d4..000000000
--- a/client/src/app/videos/shared/video.service.ts
+++ /dev/null
@@ -1,176 +0,0 @@
1import { Injectable } from '@angular/core'
2import { Observable } from 'rxjs/Observable'
3import { HttpClient, HttpParams, HttpRequest } from '@angular/common/http'
4import 'rxjs/add/operator/catch'
5import 'rxjs/add/operator/map'
6
7import { SortField } from './sort-field.type'
8import {
9 RestExtractor,
10 RestService,
11 UserService,
12 Search
13} from '../../shared'
14import { Video } from './video.model'
15import { VideoDetails } from './video-details.model'
16import { VideoEdit } from './video-edit.model'
17import { VideoPagination } from './video-pagination.model'
18import {
19 UserVideoRate,
20 VideoRateType,
21 VideoUpdate,
22 UserVideoRateUpdate,
23 Video as VideoServerModel,
24 VideoDetails as VideoDetailsServerModel,
25 ResultList
26} from '../../../../../shared'
27
28@Injectable()
29export class VideoService {
30 private static BASE_VIDEO_URL = API_URL + '/api/v1/videos/'
31
32 constructor (
33 private authHttp: HttpClient,
34 private restExtractor: RestExtractor,
35 private restService: RestService
36 ) {}
37
38 getVideo (uuid: string): Observable<VideoDetails> {
39 return this.authHttp.get<VideoDetailsServerModel>(VideoService.BASE_VIDEO_URL + uuid)
40 .map(videoHash => new VideoDetails(videoHash))
41 .catch((res) => this.restExtractor.handleError(res))
42 }
43
44 viewVideo (uuid: string): Observable<VideoDetails> {
45 return this.authHttp.post(VideoService.BASE_VIDEO_URL + uuid + '/views', {})
46 .map(this.restExtractor.extractDataBool)
47 .catch(this.restExtractor.handleError)
48 }
49
50 updateVideo (video: VideoEdit) {
51 const language = video.language ? video.language : null
52
53 const body: VideoUpdate = {
54 name: video.name,
55 category: video.category,
56 licence: video.licence,
57 language,
58 description: video.description,
59 privacy: video.privacy,
60 tags: video.tags,
61 nsfw: video.nsfw
62 }
63
64 return this.authHttp.put(VideoService.BASE_VIDEO_URL + video.id, body)
65 .map(this.restExtractor.extractDataBool)
66 .catch(this.restExtractor.handleError)
67 }
68
69 uploadVideo (video: FormData) {
70 const req = new HttpRequest('POST', VideoService.BASE_VIDEO_URL + 'upload', video, { reportProgress: true })
71
72 return this.authHttp
73 .request(req)
74 .catch(this.restExtractor.handleError)
75 }
76
77 getMyVideos (videoPagination: VideoPagination, sort: SortField): Observable<{ videos: Video[], totalVideos: number}> {
78 const pagination = this.videoPaginationToRestPagination(videoPagination)
79
80 let params = new HttpParams()
81 params = this.restService.addRestGetParams(params, pagination, sort)
82
83 return this.authHttp.get(UserService.BASE_USERS_URL + '/me/videos', { params })
84 .map(this.extractVideos)
85 .catch((res) => this.restExtractor.handleError(res))
86 }
87
88 getVideos (videoPagination: VideoPagination, sort: SortField): Observable<{ videos: Video[], totalVideos: number}> {
89 const pagination = this.videoPaginationToRestPagination(videoPagination)
90
91 let params = new HttpParams()
92 params = this.restService.addRestGetParams(params, pagination, sort)
93
94 return this.authHttp
95 .get(VideoService.BASE_VIDEO_URL, { params })
96 .map(this.extractVideos)
97 .catch((res) => this.restExtractor.handleError(res))
98 }
99
100 searchVideos (search: Search, videoPagination: VideoPagination, sort: SortField): Observable<{ videos: Video[], totalVideos: number}> {
101 const url = VideoService.BASE_VIDEO_URL + 'search/' + encodeURIComponent(search.value)
102
103 const pagination = this.videoPaginationToRestPagination(videoPagination)
104
105 let params = new HttpParams()
106 params = this.restService.addRestGetParams(params, pagination, sort)
107
108 if (search.field) params.set('field', search.field)
109
110 return this.authHttp
111 .get<ResultList<VideoServerModel>>(url, { params })
112 .map(this.extractVideos)
113 .catch((res) => this.restExtractor.handleError(res))
114 }
115
116 removeVideo (id: number) {
117 return this.authHttp
118 .delete(VideoService.BASE_VIDEO_URL + id)
119 .map(this.restExtractor.extractDataBool)
120 .catch((res) => this.restExtractor.handleError(res))
121 }
122
123 loadCompleteDescription (descriptionPath: string) {
124 return this.authHttp
125 .get(API_URL + descriptionPath)
126 .map(res => res['description'])
127 .catch((res) => this.restExtractor.handleError(res))
128 }
129
130 setVideoLike (id: number) {
131 return this.setVideoRate(id, 'like')
132 }
133
134 setVideoDislike (id: number) {
135 return this.setVideoRate(id, 'dislike')
136 }
137
138 getUserVideoRating (id: number): Observable<UserVideoRate> {
139 const url = UserService.BASE_USERS_URL + 'me/videos/' + id + '/rating'
140
141 return this.authHttp
142 .get(url)
143 .catch(res => this.restExtractor.handleError(res))
144 }
145
146 private videoPaginationToRestPagination (videoPagination: VideoPagination) {
147 const start: number = (videoPagination.currentPage - 1) * videoPagination.itemsPerPage
148 const count: number = videoPagination.itemsPerPage
149
150 return { start, count }
151 }
152
153 private setVideoRate (id: number, rateType: VideoRateType) {
154 const url = VideoService.BASE_VIDEO_URL + id + '/rate'
155 const body: UserVideoRateUpdate = {
156 rating: rateType
157 }
158
159 return this.authHttp
160 .put(url, body)
161 .map(this.restExtractor.extractDataBool)
162 .catch(res => this.restExtractor.handleError(res))
163 }
164
165 private extractVideos (result: ResultList<VideoServerModel>) {
166 const videosJson = result.data
167 const totalVideos = result.total
168 const videos = []
169
170 for (const videoJson of videosJson) {
171 videos.push(new Video(videoJson))
172 }
173
174 return { videos, totalVideos }
175 }
176}
diff --git a/client/src/app/videos/video-list/shared/abstract-video-list.html b/client/src/app/videos/video-list/shared/abstract-video-list.html
deleted file mode 100644
index bd4f6b1f8..000000000
--- a/client/src/app/videos/video-list/shared/abstract-video-list.html
+++ /dev/null
@@ -1,19 +0,0 @@
1<div class="margin-content">
2 <div class="title-page title-page-single">
3 {{ titlePage }}
4 </div>
5
6 <div
7 infiniteScroll
8 [infiniteScrollUpDistance]="1.5"
9 [infiniteScrollDistance]="0.5"
10 (scrolled)="onNearOfBottom()"
11 (scrolledUp)="onNearOfTop()"
12 >
13 <my-video-miniature
14 class="ng-animate"
15 *ngFor="let video of videos" [video]="video" [user]="user" [currentSort]="sort"
16 >
17 </my-video-miniature>
18 </div>
19</div>
diff --git a/client/src/app/videos/video-list/shared/abstract-video-list.scss b/client/src/app/videos/video-list/shared/abstract-video-list.scss
deleted file mode 100644
index e69de29bb..000000000
--- a/client/src/app/videos/video-list/shared/abstract-video-list.scss
+++ /dev/null
diff --git a/client/src/app/videos/video-list/shared/abstract-video-list.ts b/client/src/app/videos/video-list/shared/abstract-video-list.ts
deleted file mode 100644
index a684ffef4..000000000
--- a/client/src/app/videos/video-list/shared/abstract-video-list.ts
+++ /dev/null
@@ -1,121 +0,0 @@
1import { OnDestroy, OnInit } from '@angular/core'
2import { ActivatedRoute, Router } from '@angular/router'
3
4import { NotificationsService } from 'angular2-notifications'
5import { Observable } from 'rxjs/Observable'
6import { Subscription } from 'rxjs/Subscription'
7
8import { SortField, Video, VideoPagination } from '../../shared'
9
10export abstract class AbstractVideoList implements OnInit, OnDestroy {
11 pagination: VideoPagination = {
12 currentPage: 1,
13 itemsPerPage: 25,
14 totalItems: null
15 }
16 sort: SortField = '-createdAt'
17 videos: Video[] = []
18
19 protected notificationsService: NotificationsService
20 protected router: Router
21 protected route: ActivatedRoute
22 protected subActivatedRoute: Subscription
23
24 protected abstract currentRoute: string
25
26 abstract titlePage: string
27 private loadedPages: { [ id: number ]: boolean } = {}
28
29 abstract getVideosObservable (): Observable<{ videos: Video[], totalVideos: number}>
30
31 ngOnInit () {
32 // Subscribe to route changes
33 const routeParams = this.route.snapshot.params
34 this.loadRouteParams(routeParams)
35 this.loadMoreVideos('after')
36 }
37
38 ngOnDestroy () {
39 if (this.subActivatedRoute) {
40 this.subActivatedRoute.unsubscribe()
41 }
42 }
43
44 onNearOfTop () {
45 if (this.pagination.currentPage > 1) {
46 this.previousPage()
47 }
48 }
49
50 onNearOfBottom () {
51 if (this.hasMoreVideos()) {
52 this.nextPage()
53 }
54 }
55
56 loadMoreVideos (where: 'before' | 'after') {
57 if (this.loadedPages[this.pagination.currentPage] === true) return
58
59 const observable = this.getVideosObservable()
60
61 observable.subscribe(
62 ({ videos, totalVideos }) => {
63 this.loadedPages[this.pagination.currentPage] = true
64 this.pagination.totalItems = totalVideos
65
66 if (where === 'before') {
67 this.videos = videos.concat(this.videos)
68 } else {
69 this.videos = this.videos.concat(videos)
70 }
71 },
72 error => this.notificationsService.error('Error', error.text)
73 )
74 }
75
76 protected hasMoreVideos () {
77 if (!this.pagination.totalItems) return true
78
79 const maxPage = this.pagination.totalItems/this.pagination.itemsPerPage
80 return maxPage > this.pagination.currentPage
81 }
82
83 protected previousPage () {
84 this.pagination.currentPage--
85
86 this.setNewRouteParams()
87 this.loadMoreVideos('before')
88 }
89
90 protected nextPage () {
91 this.pagination.currentPage++
92
93 this.setNewRouteParams()
94 this.loadMoreVideos('after')
95 }
96
97 protected buildRouteParams () {
98 // There is always a sort and a current page
99 const params = {
100 sort: this.sort,
101 page: this.pagination.currentPage
102 }
103
104 return params
105 }
106
107 protected loadRouteParams (routeParams: { [ key: string ]: any }) {
108 this.sort = routeParams['sort'] as SortField || '-createdAt'
109
110 if (routeParams['page'] !== undefined) {
111 this.pagination.currentPage = parseInt(routeParams['page'], 10)
112 } else {
113 this.pagination.currentPage = 1
114 }
115 }
116
117 protected setNewRouteParams () {
118 const routeParams = this.buildRouteParams()
119 this.router.navigate([ this.currentRoute, routeParams ])
120 }
121}
diff --git a/client/src/app/videos/video-list/shared/index.ts b/client/src/app/videos/video-list/shared/index.ts
index 170ca4832..2778f2d9e 100644
--- a/client/src/app/videos/video-list/shared/index.ts
+++ b/client/src/app/videos/video-list/shared/index.ts
@@ -1,2 +1 @@
1export * from './abstract-video-list'
2export * from './video-miniature.component' export * from './video-miniature.component'
diff --git a/client/src/app/videos/video-list/shared/video-miniature.component.html b/client/src/app/videos/video-list/shared/video-miniature.component.html
index aea85b6c6..f2756ca3d 100644
--- a/client/src/app/videos/video-list/shared/video-miniature.component.html
+++ b/client/src/app/videos/video-list/shared/video-miniature.component.html
@@ -1,14 +1,5 @@
1<div class="video-miniature"> 1<div class="video-miniature">
2 <a 2 <my-video-thumbnail [video]="video" [nsfw]="isVideoNSFWForThisUser()"></my-video-thumbnail>
3 [routerLink]="['/videos/watch', video.uuid]" [attr.title]="video.description"
4 class="video-miniature-thumbnail"
5 >
6 <img [attr.src]="video.thumbnailUrl" alt="video thumbnail" [ngClass]="{ 'blur-filter': isVideoNSFWForThisUser() }" />
7
8 <div class="video-miniature-thumbnail-overlay">
9 {{ video.durationLabel }}
10 </div>
11 </a>
12 3
13 <div class="video-miniature-information"> 4 <div class="video-miniature-information">
14 <span class="video-miniature-name"> 5 <span class="video-miniature-name">
diff --git a/client/src/app/videos/video-list/shared/video-miniature.component.scss b/client/src/app/videos/video-list/shared/video-miniature.component.scss
index ed15864d9..658d7af9d 100644
--- a/client/src/app/videos/video-list/shared/video-miniature.component.scss
+++ b/client/src/app/videos/video-list/shared/video-miniature.component.scss
@@ -5,35 +5,6 @@
5 height: 175px; 5 height: 175px;
6 vertical-align: top; 6 vertical-align: top;
7 7
8 .video-miniature-thumbnail {
9 display: inline-block;
10 position: relative;
11 border-radius: 4px;
12 overflow: hidden;
13
14 &:hover {
15 text-decoration: none !important;
16 }
17
18 img.blur-filter {
19 filter: blur(5px);
20 transform : scale(1.03);
21 }
22
23 .video-miniature-thumbnail-overlay {
24 position: absolute;
25 right: 5px;
26 bottom: 5px;
27 display: inline-block;
28 background-color: rgba(0, 0, 0, 0.7);
29 color: #fff;
30 font-size: 12px;
31 font-weight: $font-bold;
32 border-radius: 3px;
33 padding: 0 5px;
34 }
35 }
36
37 .video-miniature-information { 8 .video-miniature-information {
38 width: 200px; 9 width: 200px;
39 margin-top: 2px; 10 margin-top: 2px;
diff --git a/client/src/app/videos/video-list/shared/video-miniature.component.ts b/client/src/app/videos/video-list/shared/video-miniature.component.ts
index e5a87907b..e8fc8e911 100644
--- a/client/src/app/videos/video-list/shared/video-miniature.component.ts
+++ b/client/src/app/videos/video-list/shared/video-miniature.component.ts
@@ -1,7 +1,7 @@
1import { Component, Input } from '@angular/core' 1import { Component, Input } from '@angular/core'
2
3import { SortField, Video } from '../../shared'
4import { User } from '../../../shared' 2import { User } from '../../../shared'
3import { SortField } from '../../../shared/video/sort-field.type'
4import { Video } from '../../../shared/video/video.model'
5 5
6@Component({ 6@Component({
7 selector: 'my-video-miniature', 7 selector: 'my-video-miniature',
diff --git a/client/src/app/videos/video-list/video-recently-added.component.ts b/client/src/app/videos/video-list/video-recently-added.component.ts
index 9bf69bd78..d48804414 100644
--- a/client/src/app/videos/video-list/video-recently-added.component.ts
+++ b/client/src/app/videos/video-list/video-recently-added.component.ts
@@ -1,13 +1,13 @@
1import { Component, OnDestroy, OnInit } from '@angular/core' 1import { Component, OnDestroy, OnInit } from '@angular/core'
2import { ActivatedRoute, Router } from '@angular/router' 2import { ActivatedRoute, Router } from '@angular/router'
3import { NotificationsService } from 'angular2-notifications' 3import { NotificationsService } from 'angular2-notifications'
4import { VideoService } from '../shared' 4import { VideoService } from '../../shared/video/video.service'
5import { AbstractVideoList } from './shared' 5import { AbstractVideoList } from '../../shared/video/abstract-video-list'
6 6
7@Component({ 7@Component({
8 selector: 'my-videos-recently-added', 8 selector: 'my-videos-recently-added',
9 styleUrls: [ './shared/abstract-video-list.scss' ], 9 styleUrls: [ '../../shared/video/abstract-video-list.scss' ],
10 templateUrl: './shared/abstract-video-list.html' 10 templateUrl: '../../shared/video/abstract-video-list.html'
11}) 11})
12export class VideoRecentlyAddedComponent extends AbstractVideoList implements OnInit, OnDestroy { 12export class VideoRecentlyAddedComponent extends AbstractVideoList implements OnInit, OnDestroy {
13 titlePage = 'Recently added' 13 titlePage = 'Recently added'
diff --git a/client/src/app/videos/video-list/video-trending.component.ts b/client/src/app/videos/video-list/video-trending.component.ts
index a1df68711..9108289c9 100644
--- a/client/src/app/videos/video-list/video-trending.component.ts
+++ b/client/src/app/videos/video-list/video-trending.component.ts
@@ -1,13 +1,13 @@
1import { Component, OnDestroy, OnInit } from '@angular/core' 1import { Component, OnDestroy, OnInit } from '@angular/core'
2import { ActivatedRoute, Router } from '@angular/router' 2import { ActivatedRoute, Router } from '@angular/router'
3import { NotificationsService } from 'angular2-notifications' 3import { NotificationsService } from 'angular2-notifications'
4import { VideoService } from '../shared' 4import { VideoService } from '../../shared/video/video.service'
5import { AbstractVideoList } from './shared' 5import { AbstractVideoList } from 'app/shared/video/abstract-video-list'
6 6
7@Component({ 7@Component({
8 selector: 'my-videos-trending', 8 selector: 'my-videos-trending',
9 styleUrls: [ './shared/abstract-video-list.scss' ], 9 styleUrls: [ '../../shared/video/abstract-video-list.scss' ],
10 templateUrl: './shared/abstract-video-list.html' 10 templateUrl: '../../shared/video/abstract-video-list.html'
11}) 11})
12export class VideoTrendingComponent extends AbstractVideoList implements OnInit, OnDestroy { 12export class VideoTrendingComponent extends AbstractVideoList implements OnInit, OnDestroy {
13 titlePage = 'Trending' 13 titlePage = 'Trending'
diff --git a/client/src/app/videos/videos.module.ts b/client/src/app/videos/videos.module.ts
index 1d6194158..6d846fd3b 100644
--- a/client/src/app/videos/videos.module.ts
+++ b/client/src/app/videos/videos.module.ts
@@ -1,7 +1,5 @@
1import { NgModule } from '@angular/core' 1import { NgModule } from '@angular/core'
2import { InfiniteScrollModule } from 'ngx-infinite-scroll'
3import { SharedModule } from '../shared' 2import { SharedModule } from '../shared'
4import { VideoService } from './shared'
5import { VideoMiniatureComponent } from './video-list' 3import { VideoMiniatureComponent } from './video-list'
6import { VideoRecentlyAddedComponent } from './video-list/video-recently-added.component' 4import { VideoRecentlyAddedComponent } from './video-list/video-recently-added.component'
7import { VideoTrendingComponent } from './video-list/video-trending.component' 5import { VideoTrendingComponent } from './video-list/video-trending.component'
@@ -11,8 +9,7 @@ import { VideosComponent } from './videos.component'
11@NgModule({ 9@NgModule({
12 imports: [ 10 imports: [
13 VideosRoutingModule, 11 VideosRoutingModule,
14 SharedModule, 12 SharedModule
15 InfiniteScrollModule
16 ], 13 ],
17 14
18 declarations: [ 15 declarations: [
@@ -27,8 +24,6 @@ import { VideosComponent } from './videos.component'
27 VideosComponent 24 VideosComponent
28 ], 25 ],
29 26
30 providers: [ 27 providers: []
31 VideoService
32 ]
33}) 28})
34export class VideosModule { } 29export class VideosModule { }