aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2018-04-25 16:56:13 +0200
committerChocobozzz <me@florianbigard.com>2018-04-25 16:56:13 +0200
commit170726f523ff48f89da45473fc53ca54784f43dd (patch)
treef9f783ebdfc934c6831396c2bf33f658d6640583
parentcc918ac3f45e32f031cce7b6e0473e5c2c34b8ae (diff)
downloadPeerTube-170726f523ff48f89da45473fc53ca54784f43dd.tar.gz
PeerTube-170726f523ff48f89da45473fc53ca54784f43dd.tar.zst
PeerTube-170726f523ff48f89da45473fc53ca54784f43dd.zip
Implement video channel views
-rw-r--r--client/src/app/+account/account.component.scss46
-rw-r--r--client/src/app/+account/index.ts3
-rw-r--r--client/src/app/+accounts/account-about/account-about.component.html (renamed from client/src/app/+account/account-about/account-about.component.html)0
-rw-r--r--client/src/app/+accounts/account-about/account-about.component.scss (renamed from client/src/app/+account/account-about/account-about.component.scss)0
-rw-r--r--client/src/app/+accounts/account-about/account-about.component.ts (renamed from client/src/app/+account/account-about/account-about.component.ts)0
-rw-r--r--client/src/app/+accounts/account-video-channels/account-video-channels.component.html (renamed from client/src/app/+account/account-video-channels/account-video-channels.component.html)0
-rw-r--r--client/src/app/+accounts/account-video-channels/account-video-channels.component.scss (renamed from client/src/app/+account/account-video-channels/account-video-channels.component.scss)0
-rw-r--r--client/src/app/+accounts/account-video-channels/account-video-channels.component.ts (renamed from client/src/app/+account/account-video-channels/account-video-channels.component.ts)2
-rw-r--r--client/src/app/+accounts/account-videos/account-videos.component.scss (renamed from client/src/app/+account/account-videos/account-videos.component.scss)0
-rw-r--r--client/src/app/+accounts/account-videos/account-videos.component.ts (renamed from client/src/app/+account/account-videos/account-videos.component.ts)0
-rw-r--r--client/src/app/+accounts/accounts-routing.module.ts (renamed from client/src/app/+account/account-routing.module.ts)10
-rw-r--r--client/src/app/+accounts/accounts.component.html (renamed from client/src/app/+account/account.component.html)8
-rw-r--r--client/src/app/+accounts/accounts.component.scss6
-rw-r--r--client/src/app/+accounts/accounts.component.ts (renamed from client/src/app/+account/account.component.ts)7
-rw-r--r--client/src/app/+accounts/accounts.module.ts (renamed from client/src/app/+account/account.module.ts)12
-rw-r--r--client/src/app/+accounts/index.ts3
-rw-r--r--client/src/app/+video-channels/index.ts3
-rw-r--r--client/src/app/+video-channels/video-channel-about/video-channel-about.component.html12
-rw-r--r--client/src/app/+video-channels/video-channel-about/video-channel-about.component.scss8
-rw-r--r--client/src/app/+video-channels/video-channel-about/video-channel-about.component.ts32
-rw-r--r--client/src/app/+video-channels/video-channel-videos/video-channel-videos.component.scss3
-rw-r--r--client/src/app/+video-channels/video-channel-videos/video-channel-videos.component.ts71
-rw-r--r--client/src/app/+video-channels/video-channels-routing.module.ts45
-rw-r--r--client/src/app/+video-channels/video-channels.component.html23
-rw-r--r--client/src/app/+video-channels/video-channels.component.scss6
-rw-r--r--client/src/app/+video-channels/video-channels.component.ts24
-rw-r--r--client/src/app/+video-channels/video-channels.module.ts26
-rw-r--r--client/src/app/app-routing.module.ts8
-rw-r--r--client/src/app/shared/video-channel/video-channel.service.ts15
-rw-r--r--client/src/app/shared/video/video-miniature.component.html4
-rw-r--r--client/src/app/shared/video/video.service.ts25
-rw-r--r--client/src/app/videos/+video-watch/video-watch.component.html2
-rw-r--r--client/src/sass/include/_mixins.scss44
-rw-r--r--server/tests/api/check-params/videos.ts2
-rw-r--r--server/tests/api/videos/multiple-servers.ts8
35 files changed, 375 insertions, 83 deletions
diff --git a/client/src/app/+account/account.component.scss b/client/src/app/+account/account.component.scss
deleted file mode 100644
index c7b8f038f..000000000
--- a/client/src/app/+account/account.component.scss
+++ /dev/null
@@ -1,46 +0,0 @@
1@import '_variables';
2@import '_mixins';
3
4.sub-menu {
5 height: 160px;
6 display: flex;
7 flex-direction: column;
8 align-items: start;
9
10 .account {
11 display: flex;
12 margin-top: 20px;
13 margin-bottom: 20px;
14
15 img {
16 @include avatar(80px);
17
18 margin-right: 20px;
19 }
20
21 .account-info {
22 display: flex;
23 flex-direction: column;
24 justify-content: center;
25
26 .account-display-name {
27 font-size: 23px;
28 font-weight: $font-bold;
29 }
30
31 .account-followers {
32 font-size: 15px;
33 }
34 }
35 }
36
37 .links {
38 margin-top: 0;
39 margin-bottom: 10px;
40
41 a {
42 margin-top: 0;
43 margin-bottom: 0;
44 }
45 }
46} \ No newline at end of file
diff --git a/client/src/app/+account/index.ts b/client/src/app/+account/index.ts
deleted file mode 100644
index dc56ffdbd..000000000
--- a/client/src/app/+account/index.ts
+++ /dev/null
@@ -1,3 +0,0 @@
1export * from './account-routing.module'
2export * from './account.component'
3export * from './account.module'
diff --git a/client/src/app/+account/account-about/account-about.component.html b/client/src/app/+accounts/account-about/account-about.component.html
index 003a8045e..003a8045e 100644
--- a/client/src/app/+account/account-about/account-about.component.html
+++ b/client/src/app/+accounts/account-about/account-about.component.html
diff --git a/client/src/app/+account/account-about/account-about.component.scss b/client/src/app/+accounts/account-about/account-about.component.scss
index b1be7d4ed..b1be7d4ed 100644
--- a/client/src/app/+account/account-about/account-about.component.scss
+++ b/client/src/app/+accounts/account-about/account-about.component.scss
diff --git a/client/src/app/+account/account-about/account-about.component.ts b/client/src/app/+accounts/account-about/account-about.component.ts
index 8746875cb..8746875cb 100644
--- a/client/src/app/+account/account-about/account-about.component.ts
+++ b/client/src/app/+accounts/account-about/account-about.component.ts
diff --git a/client/src/app/+account/account-video-channels/account-video-channels.component.html b/client/src/app/+accounts/account-video-channels/account-video-channels.component.html
index d20b40c60..d20b40c60 100644
--- a/client/src/app/+account/account-video-channels/account-video-channels.component.html
+++ b/client/src/app/+accounts/account-video-channels/account-video-channels.component.html
diff --git a/client/src/app/+account/account-video-channels/account-video-channels.component.scss b/client/src/app/+accounts/account-video-channels/account-video-channels.component.scss
index c9c7fa8eb..c9c7fa8eb 100644
--- a/client/src/app/+account/account-video-channels/account-video-channels.component.scss
+++ b/client/src/app/+accounts/account-video-channels/account-video-channels.component.scss
diff --git a/client/src/app/+account/account-video-channels/account-video-channels.component.ts b/client/src/app/+accounts/account-video-channels/account-video-channels.component.ts
index 8915eb622..4c5782f9d 100644
--- a/client/src/app/+account/account-video-channels/account-video-channels.component.ts
+++ b/client/src/app/+accounts/account-video-channels/account-video-channels.component.ts
@@ -26,7 +26,7 @@ export class AccountVideoChannelsComponent implements OnInit {
26 // Parent get the account for us 26 // Parent get the account for us
27 this.accountService.accountLoaded 27 this.accountService.accountLoaded
28 .do(account => this.account = account) 28 .do(account => this.account = account)
29 .flatMap(account => this.videoChannelService.getVideoChannels(account.id)) 29 .flatMap(account => this.videoChannelService.listAccountVideoChannels(account.id))
30 .map(res => res.data) 30 .map(res => res.data)
31 .subscribe(videoChannels => this.videoChannels = videoChannels) 31 .subscribe(videoChannels => this.videoChannels = videoChannels)
32 } 32 }
diff --git a/client/src/app/+account/account-videos/account-videos.component.scss b/client/src/app/+accounts/account-videos/account-videos.component.scss
index 2ba85c031..2ba85c031 100644
--- a/client/src/app/+account/account-videos/account-videos.component.scss
+++ b/client/src/app/+accounts/account-videos/account-videos.component.scss
diff --git a/client/src/app/+account/account-videos/account-videos.component.ts b/client/src/app/+accounts/account-videos/account-videos.component.ts
index 6c0f0bb52..6c0f0bb52 100644
--- a/client/src/app/+account/account-videos/account-videos.component.ts
+++ b/client/src/app/+accounts/account-videos/account-videos.component.ts
diff --git a/client/src/app/+account/account-routing.module.ts b/client/src/app/+accounts/accounts-routing.module.ts
index f72d8373f..ffe606b43 100644
--- a/client/src/app/+account/account-routing.module.ts
+++ b/client/src/app/+accounts/accounts-routing.module.ts
@@ -1,15 +1,15 @@
1import { NgModule } from '@angular/core' 1import { NgModule } from '@angular/core'
2import { RouterModule, Routes } from '@angular/router' 2import { RouterModule, Routes } from '@angular/router'
3import { MetaGuard } from '@ngx-meta/core' 3import { MetaGuard } from '@ngx-meta/core'
4import { AccountComponent } from './account.component' 4import { AccountsComponent } from './accounts.component'
5import { AccountVideosComponent } from './account-videos/account-videos.component' 5import { AccountVideosComponent } from './account-videos/account-videos.component'
6import { AccountAboutComponent } from './account-about/account-about.component' 6import { AccountAboutComponent } from './account-about/account-about.component'
7import { AccountVideoChannelsComponent } from './account-video-channels/account-video-channels.component' 7import { AccountVideoChannelsComponent } from './account-video-channels/account-video-channels.component'
8 8
9const accountRoutes: Routes = [ 9const accountsRoutes: Routes = [
10 { 10 {
11 path: ':accountId', 11 path: ':accountId',
12 component: AccountComponent, 12 component: AccountsComponent,
13 canActivateChild: [ MetaGuard ], 13 canActivateChild: [ MetaGuard ],
14 children: [ 14 children: [
15 { 15 {
@@ -49,7 +49,7 @@ const accountRoutes: Routes = [
49] 49]
50 50
51@NgModule({ 51@NgModule({
52 imports: [ RouterModule.forChild(accountRoutes) ], 52 imports: [ RouterModule.forChild(accountsRoutes) ],
53 exports: [ RouterModule ] 53 exports: [ RouterModule ]
54}) 54})
55export class AccountRoutingModule {} 55export class AccountsRoutingModule {}
diff --git a/client/src/app/+account/account.component.html b/client/src/app/+accounts/accounts.component.html
index d0e99edda..549676e5a 100644
--- a/client/src/app/+account/account.component.html
+++ b/client/src/app/+accounts/accounts.component.html
@@ -1,12 +1,12 @@
1<div *ngIf="account" class="row"> 1<div *ngIf="account" class="row">
2 <div class="sub-menu"> 2 <div class="sub-menu">
3 3
4 <div class="account"> 4 <div class="actor">
5 <img [src]="account.avatarUrl" alt="Avatar" /> 5 <img [src]="account.avatarUrl" alt="Avatar" />
6 6
7 <div class="account-info"> 7 <div class="actor-info">
8 <div class="account-display-name">{{ account.displayName }}</div> 8 <div class="actor-display-name">{{ account.displayName }}</div>
9 <div class="account-followers">{{ account.followersCount }} subscribers</div> 9 <div class="actor-followers">{{ account.followersCount }} subscribers</div>
10 </div> 10 </div>
11 </div> 11 </div>
12 12
diff --git a/client/src/app/+accounts/accounts.component.scss b/client/src/app/+accounts/accounts.component.scss
new file mode 100644
index 000000000..909b65bc7
--- /dev/null
+++ b/client/src/app/+accounts/accounts.component.scss
@@ -0,0 +1,6 @@
1@import '_variables';
2@import '_mixins';
3
4.sub-menu {
5 @include sub-menu-with-actor;
6} \ No newline at end of file
diff --git a/client/src/app/+account/account.component.ts b/client/src/app/+accounts/accounts.component.ts
index d936ce2fe..1298803c3 100644
--- a/client/src/app/+account/account.component.ts
+++ b/client/src/app/+accounts/accounts.component.ts
@@ -4,11 +4,10 @@ import { AccountService } from '@app/shared/account/account.service'
4import { Account } from '@app/shared/account/account.model' 4import { Account } from '@app/shared/account/account.model'
5 5
6@Component({ 6@Component({
7 selector: 'my-account', 7 templateUrl: './accounts.component.html',
8 templateUrl: './account.component.html', 8 styleUrls: [ './accounts.component.scss' ]
9 styleUrls: [ './account.component.scss' ]
10}) 9})
11export class AccountComponent implements OnInit { 10export class AccountsComponent implements OnInit {
12 account: Account 11 account: Account
13 12
14 constructor ( 13 constructor (
diff --git a/client/src/app/+account/account.module.ts b/client/src/app/+accounts/accounts.module.ts
index 82ef06e76..8e679822a 100644
--- a/client/src/app/+account/account.module.ts
+++ b/client/src/app/+accounts/accounts.module.ts
@@ -1,28 +1,28 @@
1import { NgModule } from '@angular/core' 1import { NgModule } from '@angular/core'
2import { SharedModule } from '../shared' 2import { SharedModule } from '../shared'
3import { AccountRoutingModule } from './account-routing.module' 3import { AccountsRoutingModule } from './accounts-routing.module'
4import { AccountComponent } from './account.component' 4import { AccountsComponent } from './accounts.component'
5import { AccountVideosComponent } from './account-videos/account-videos.component' 5import { AccountVideosComponent } from './account-videos/account-videos.component'
6import { AccountAboutComponent } from './account-about/account-about.component' 6import { AccountAboutComponent } from './account-about/account-about.component'
7import { AccountVideoChannelsComponent } from './account-video-channels/account-video-channels.component' 7import { AccountVideoChannelsComponent } from './account-video-channels/account-video-channels.component'
8 8
9@NgModule({ 9@NgModule({
10 imports: [ 10 imports: [
11 AccountRoutingModule, 11 AccountsRoutingModule,
12 SharedModule 12 SharedModule
13 ], 13 ],
14 14
15 declarations: [ 15 declarations: [
16 AccountComponent, 16 AccountsComponent,
17 AccountVideosComponent, 17 AccountVideosComponent,
18 AccountVideoChannelsComponent, 18 AccountVideoChannelsComponent,
19 AccountAboutComponent 19 AccountAboutComponent
20 ], 20 ],
21 21
22 exports: [ 22 exports: [
23 AccountComponent 23 AccountsComponent
24 ], 24 ],
25 25
26 providers: [] 26 providers: []
27}) 27})
28export class AccountModule { } 28export class AccountsModule { }
diff --git a/client/src/app/+accounts/index.ts b/client/src/app/+accounts/index.ts
new file mode 100644
index 000000000..4dfb6f586
--- /dev/null
+++ b/client/src/app/+accounts/index.ts
@@ -0,0 +1,3 @@
1export * from './accounts-routing.module'
2export * from './accounts.component'
3export * from './accounts.module'
diff --git a/client/src/app/+video-channels/index.ts b/client/src/app/+video-channels/index.ts
new file mode 100644
index 000000000..6683d1b12
--- /dev/null
+++ b/client/src/app/+video-channels/index.ts
@@ -0,0 +1,3 @@
1export * from './video-channels-routing.module'
2export * from './video-channels.component'
3export * from './video-channels.module'
diff --git a/client/src/app/+video-channels/video-channel-about/video-channel-about.component.html b/client/src/app/+video-channels/video-channel-about/video-channel-about.component.html
new file mode 100644
index 000000000..65ad6f541
--- /dev/null
+++ b/client/src/app/+video-channels/video-channel-about/video-channel-about.component.html
@@ -0,0 +1,12 @@
1<div *ngIf="videoChannel" class="row">
2 <div class="description col-md-6 col-sm-12">
3 <div class="small-title">Description</div>
4 <div class="content">{{ getVideoChannelDescription() }}</div>
5 </div>
6
7 <div class="stats col-md-6 col-sm-12">
8 <div class="small-title">Stats</div>
9
10 <div class="content">Created {{ videoChannel.createdAt | date }}</div>
11 </div>
12</div> \ No newline at end of file
diff --git a/client/src/app/+video-channels/video-channel-about/video-channel-about.component.scss b/client/src/app/+video-channels/video-channel-about/video-channel-about.component.scss
new file mode 100644
index 000000000..b1be7d4ed
--- /dev/null
+++ b/client/src/app/+video-channels/video-channel-about/video-channel-about.component.scss
@@ -0,0 +1,8 @@
1@import '_variables';
2@import '_mixins';
3
4.small-title {
5 @include in-content-small-title;
6
7 margin-bottom: 20px;
8}
diff --git a/client/src/app/+video-channels/video-channel-about/video-channel-about.component.ts b/client/src/app/+video-channels/video-channel-about/video-channel-about.component.ts
new file mode 100644
index 000000000..5d435708e
--- /dev/null
+++ b/client/src/app/+video-channels/video-channel-about/video-channel-about.component.ts
@@ -0,0 +1,32 @@
1import { Component, OnInit } from '@angular/core'
2import { ActivatedRoute } from '@angular/router'
3import 'rxjs/add/observable/from'
4import 'rxjs/add/operator/concatAll'
5import { VideoChannelService } from '@app/shared/video-channel/video-channel.service'
6import { VideoChannel } from '@app/shared/video-channel/video-channel.model'
7
8@Component({
9 selector: 'my-video-channel-about',
10 templateUrl: './video-channel-about.component.html',
11 styleUrls: [ './video-channel-about.component.scss' ]
12})
13export class VideoChannelAboutComponent implements OnInit {
14 videoChannel: VideoChannel
15
16 constructor (
17 protected route: ActivatedRoute,
18 private videoChannelService: VideoChannelService
19 ) { }
20
21 ngOnInit () {
22 // Parent get the video channel for us
23 this.videoChannelService.videoChannelLoaded
24 .subscribe(videoChannel => this.videoChannel = videoChannel)
25 }
26
27 getVideoChannelDescription () {
28 if (this.videoChannel.description) return this.videoChannel.description
29
30 return 'No description'
31 }
32}
diff --git a/client/src/app/+video-channels/video-channel-videos/video-channel-videos.component.scss b/client/src/app/+video-channels/video-channel-videos/video-channel-videos.component.scss
new file mode 100644
index 000000000..2ba85c031
--- /dev/null
+++ b/client/src/app/+video-channels/video-channel-videos/video-channel-videos.component.scss
@@ -0,0 +1,3 @@
1.title-page-single {
2 margin-top: 0;
3} \ No newline at end of file
diff --git a/client/src/app/+video-channels/video-channel-videos/video-channel-videos.component.ts b/client/src/app/+video-channels/video-channel-videos/video-channel-videos.component.ts
new file mode 100644
index 000000000..3cda630d3
--- /dev/null
+++ b/client/src/app/+video-channels/video-channel-videos/video-channel-videos.component.ts
@@ -0,0 +1,71 @@
1import { Component, OnDestroy, OnInit } from '@angular/core'
2import { ActivatedRoute, Router } from '@angular/router'
3import { Location } from '@angular/common'
4import { immutableAssign } from '@app/shared/misc/utils'
5import { NotificationsService } from 'angular2-notifications'
6import 'rxjs/add/observable/from'
7import 'rxjs/add/operator/concatAll'
8import { AuthService } from '../../core/auth'
9import { ConfirmService } from '../../core/confirm'
10import { AbstractVideoList } from '../../shared/video/abstract-video-list'
11import { VideoService } from '../../shared/video/video.service'
12import { VideoChannelService } from '@app/shared/video-channel/video-channel.service'
13import { VideoChannel } from '@app/shared/video-channel/video-channel.model'
14
15@Component({
16 selector: 'my-video-channel-videos',
17 templateUrl: '../../shared/video/abstract-video-list.html',
18 styleUrls: [
19 '../../shared/video/abstract-video-list.scss',
20 './video-channel-videos.component.scss'
21 ]
22})
23export class VideoChannelVideosComponent extends AbstractVideoList implements OnInit, OnDestroy {
24 titlePage = 'Published videos'
25 marginContent = false // Disable margin
26 currentRoute = '/video-channel/videos'
27 loadOnInit = false
28
29 private videoChannel: VideoChannel
30
31 constructor (
32 protected router: Router,
33 protected route: ActivatedRoute,
34 protected authService: AuthService,
35 protected notificationsService: NotificationsService,
36 protected confirmService: ConfirmService,
37 protected location: Location,
38 private videoChannelService: VideoChannelService,
39 private videoService: VideoService
40 ) {
41 super()
42 }
43
44 ngOnInit () {
45 super.ngOnInit()
46
47 // Parent get the video channel for us
48 this.videoChannelService.videoChannelLoaded
49 .subscribe(videoChannel => {
50 this.videoChannel = videoChannel
51 this.currentRoute = '/video-channel/' + this.videoChannel.uuid + '/videos'
52
53 this.loadMoreVideos(this.pagination.currentPage)
54 this.generateSyndicationList()
55 })
56 }
57
58 ngOnDestroy () {
59 super.ngOnDestroy()
60 }
61
62 getVideosObservable (page: number) {
63 const newPagination = immutableAssign(this.pagination, { currentPage: page })
64
65 return this.videoService.getVideoChannelVideos(this.videoChannel, newPagination, this.sort)
66 }
67
68 generateSyndicationList () {
69 this.syndicationItems = this.videoService.getVideoChannelFeedUrls(this.videoChannel.id)
70 }
71}
diff --git a/client/src/app/+video-channels/video-channels-routing.module.ts b/client/src/app/+video-channels/video-channels-routing.module.ts
new file mode 100644
index 000000000..935578d2a
--- /dev/null
+++ b/client/src/app/+video-channels/video-channels-routing.module.ts
@@ -0,0 +1,45 @@
1import { NgModule } from '@angular/core'
2import { RouterModule, Routes } from '@angular/router'
3import { MetaGuard } from '@ngx-meta/core'
4import { VideoChannelsComponent } from './video-channels.component'
5import { VideoChannelVideosComponent } from './video-channel-videos/video-channel-videos.component'
6import { VideoChannelAboutComponent } from './video-channel-about/video-channel-about.component'
7
8const videoChannelsRoutes: Routes = [
9 {
10 path: ':videoChannelId',
11 component: VideoChannelsComponent,
12 canActivateChild: [ MetaGuard ],
13 children: [
14 {
15 path: '',
16 redirectTo: 'videos',
17 pathMatch: 'full'
18 },
19 {
20 path: 'videos',
21 component: VideoChannelVideosComponent,
22 data: {
23 meta: {
24 title: 'Video channel videos'
25 }
26 }
27 },
28 {
29 path: 'about',
30 component: VideoChannelAboutComponent,
31 data: {
32 meta: {
33 title: 'About video channel'
34 }
35 }
36 }
37 ]
38 }
39]
40
41@NgModule({
42 imports: [ RouterModule.forChild(videoChannelsRoutes) ],
43 exports: [ RouterModule ]
44})
45export class VideoChannelsRoutingModule {}
diff --git a/client/src/app/+video-channels/video-channels.component.html b/client/src/app/+video-channels/video-channels.component.html
new file mode 100644
index 000000000..098e1eed4
--- /dev/null
+++ b/client/src/app/+video-channels/video-channels.component.html
@@ -0,0 +1,23 @@
1<div *ngIf="videoChannel" class="row">
2 <div class="sub-menu">
3
4 <div class="actor">
5 <img [src]="videoChannel.avatarUrl" alt="Avatar" />
6
7 <div class="actor-info">
8 <div class="actor-display-name">{{ videoChannel.displayName }}</div>
9 <div class="actor-followers">{{ videoChannel.followersCount }} subscribers</div>
10 </div>
11 </div>
12
13 <div class="links">
14 <a routerLink="videos" routerLinkActive="active" class="title-page">Videos</a>
15
16 <a routerLink="about" routerLinkActive="active" class="title-page">About</a>
17 </div>
18 </div>
19
20 <div class="margin-content">
21 <router-outlet></router-outlet>
22 </div>
23</div>
diff --git a/client/src/app/+video-channels/video-channels.component.scss b/client/src/app/+video-channels/video-channels.component.scss
new file mode 100644
index 000000000..909b65bc7
--- /dev/null
+++ b/client/src/app/+video-channels/video-channels.component.scss
@@ -0,0 +1,6 @@
1@import '_variables';
2@import '_mixins';
3
4.sub-menu {
5 @include sub-menu-with-actor;
6} \ No newline at end of file
diff --git a/client/src/app/+video-channels/video-channels.component.ts b/client/src/app/+video-channels/video-channels.component.ts
new file mode 100644
index 000000000..5eca64fb5
--- /dev/null
+++ b/client/src/app/+video-channels/video-channels.component.ts
@@ -0,0 +1,24 @@
1import { Component, OnInit } from '@angular/core'
2import { ActivatedRoute } from '@angular/router'
3import { VideoChannel } from '@app/shared/video-channel/video-channel.model'
4import { VideoChannelService } from '@app/shared/video-channel/video-channel.service'
5
6@Component({
7 templateUrl: './video-channels.component.html',
8 styleUrls: [ './video-channels.component.scss' ]
9})
10export class VideoChannelsComponent implements OnInit {
11 videoChannel: VideoChannel
12
13 constructor (
14 private route: ActivatedRoute,
15 private videoChannelService: VideoChannelService
16 ) {}
17
18 ngOnInit () {
19 const videoChannelId = this.route.snapshot.params['videoChannelId']
20
21 this.videoChannelService.getVideoChannel(videoChannelId)
22 .subscribe(videoChannel => this.videoChannel = videoChannel)
23 }
24}
diff --git a/client/src/app/+video-channels/video-channels.module.ts b/client/src/app/+video-channels/video-channels.module.ts
new file mode 100644
index 000000000..a09ea6f11
--- /dev/null
+++ b/client/src/app/+video-channels/video-channels.module.ts
@@ -0,0 +1,26 @@
1import { NgModule } from '@angular/core'
2import { SharedModule } from '../shared'
3import { VideoChannelsRoutingModule } from './video-channels-routing.module'
4import { VideoChannelsComponent } from './video-channels.component'
5import { VideoChannelVideosComponent } from './video-channel-videos/video-channel-videos.component'
6import { VideoChannelAboutComponent } from './video-channel-about/video-channel-about.component'
7
8@NgModule({
9 imports: [
10 VideoChannelsRoutingModule,
11 SharedModule
12 ],
13
14 declarations: [
15 VideoChannelsComponent,
16 VideoChannelVideosComponent,
17 VideoChannelAboutComponent
18 ],
19
20 exports: [
21 VideoChannelsComponent
22 ],
23
24 providers: []
25})
26export class VideoChannelsModule { }
diff --git a/client/src/app/app-routing.module.ts b/client/src/app/app-routing.module.ts
index 1d55b4cea..799748cfa 100644
--- a/client/src/app/app-routing.module.ts
+++ b/client/src/app/app-routing.module.ts
@@ -9,8 +9,12 @@ const routes: Routes = [
9 loadChildren: './+admin/admin.module#AdminModule' 9 loadChildren: './+admin/admin.module#AdminModule'
10 }, 10 },
11 { 11 {
12 path: 'account', 12 path: 'accounts',
13 loadChildren: './+account/account.module#AccountModule' 13 loadChildren: './+accounts/accounts.module#AccountsModule'
14 },
15 {
16 path: 'video-channels',
17 loadChildren: './+video-channels/video-channels.module#VideoChannelsModule'
14 } 18 }
15] 19]
16 20
diff --git a/client/src/app/shared/video-channel/video-channel.service.ts b/client/src/app/shared/video-channel/video-channel.service.ts
index 1f9088c38..d8efcc171 100644
--- a/client/src/app/shared/video-channel/video-channel.service.ts
+++ b/client/src/app/shared/video-channel/video-channel.service.ts
@@ -9,16 +9,29 @@ import { VideoChannel as VideoChannelServer } from '../../../../../shared/models
9import { AccountService } from '../account/account.service' 9import { AccountService } from '../account/account.service'
10import { ResultList } from '../../../../../shared' 10import { ResultList } from '../../../../../shared'
11import { VideoChannel } from './video-channel.model' 11import { VideoChannel } from './video-channel.model'
12import { ReplaySubject } from 'rxjs/ReplaySubject'
13import { environment } from '../../../environments/environment'
12 14
13@Injectable() 15@Injectable()
14export class VideoChannelService { 16export class VideoChannelService {
17 static BASE_VIDEO_CHANNEL_URL = environment.apiUrl + '/api/v1/video-channels/'
18
19 videoChannelLoaded = new ReplaySubject<VideoChannel>(1)
20
15 constructor ( 21 constructor (
16 private authHttp: HttpClient, 22 private authHttp: HttpClient,
17 private restExtractor: RestExtractor, 23 private restExtractor: RestExtractor,
18 private restService: RestService 24 private restService: RestService
19 ) {} 25 ) {}
20 26
21 getVideoChannels (accountId: number): Observable<ResultList<VideoChannel>> { 27 getVideoChannel (videoChannelUUID: string) {
28 return this.authHttp.get<VideoChannel>(VideoChannelService.BASE_VIDEO_CHANNEL_URL + videoChannelUUID)
29 .map(videoChannelHash => new VideoChannel(videoChannelHash))
30 .do(videoChannel => this.videoChannelLoaded.next(videoChannel))
31 .catch((res) => this.restExtractor.handleError(res))
32 }
33
34 listAccountVideoChannels (accountId: number): Observable<ResultList<VideoChannel>> {
22 return this.authHttp.get<ResultList<VideoChannelServer>>(AccountService.BASE_ACCOUNT_URL + accountId + '/video-channels') 35 return this.authHttp.get<ResultList<VideoChannelServer>>(AccountService.BASE_ACCOUNT_URL + accountId + '/video-channels')
23 .map(res => this.extractVideoChannels(res)) 36 .map(res => this.extractVideoChannels(res))
24 .catch((res) => this.restExtractor.handleError(res)) 37 .catch((res) => this.restExtractor.handleError(res))
diff --git a/client/src/app/shared/video/video-miniature.component.html b/client/src/app/shared/video/video-miniature.component.html
index d0b305509..e26cb058a 100644
--- a/client/src/app/shared/video/video-miniature.component.html
+++ b/client/src/app/shared/video/video-miniature.component.html
@@ -5,13 +5,13 @@
5 <span class="video-miniature-name"> 5 <span class="video-miniature-name">
6 <a 6 <a
7 class="video-miniature-name" 7 class="video-miniature-name"
8 [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() }"
9 > 9 >
10 {{ video.name }} 10 {{ video.name }}
11 </a> 11 </a>
12 </span> 12 </span>
13 13
14 <span class="video-miniature-created-at-views">{{ video.publishedAt | myFromNow }} - {{ video.views | myNumberFormatter }} views</span> 14 <span class="video-miniature-created-at-views">{{ video.publishedAt | myFromNow }} - {{ video.views | myNumberFormatter }} views</span>
15 <a class="video-miniature-account" [routerLink]="[ '/account', video.account.id ]">{{ video.by }}</a> 15 <a class="video-miniature-account" [routerLink]="[ '/accounts', video.account.id ]">{{ video.by }}</a>
16 </div> 16 </div>
17</div> 17</div>
diff --git a/client/src/app/shared/video/video.service.ts b/client/src/app/shared/video/video.service.ts
index f82aa7389..8870cbee4 100644
--- a/client/src/app/shared/video/video.service.ts
+++ b/client/src/app/shared/video/video.service.ts
@@ -23,6 +23,8 @@ import { Video } from './video.model'
23import { objectToFormData } from '@app/shared/misc/utils' 23import { objectToFormData } from '@app/shared/misc/utils'
24import { Account } from '@app/shared/account/account.model' 24import { Account } from '@app/shared/account/account.model'
25import { AccountService } from '@app/shared/account/account.service' 25import { AccountService } from '@app/shared/account/account.service'
26import { VideoChannel } from '../../../../../shared/models/videos'
27import { VideoChannelService } from '@app/shared/video-channel/video-channel.service'
26 28
27@Injectable() 29@Injectable()
28export class VideoService { 30export class VideoService {
@@ -115,6 +117,22 @@ export class VideoService {
115 .catch((res) => this.restExtractor.handleError(res)) 117 .catch((res) => this.restExtractor.handleError(res))
116 } 118 }
117 119
120 getVideoChannelVideos (
121 videoChannel: VideoChannel,
122 videoPagination: ComponentPagination,
123 sort: VideoSortField
124 ): Observable<{ videos: Video[], totalVideos: number}> {
125 const pagination = this.restService.componentPaginationToRestPagination(videoPagination)
126
127 let params = new HttpParams()
128 params = this.restService.addRestGetParams(params, pagination, sort)
129
130 return this.authHttp
131 .get(VideoChannelService.BASE_VIDEO_CHANNEL_URL + videoChannel.uuid + '/videos', { params })
132 .map(this.extractVideos)
133 .catch((res) => this.restExtractor.handleError(res))
134 }
135
118 getVideos ( 136 getVideos (
119 videoPagination: ComponentPagination, 137 videoPagination: ComponentPagination,
120 sort: VideoSortField, 138 sort: VideoSortField,
@@ -175,6 +193,13 @@ export class VideoService {
175 return this.buildBaseFeedUrls(params) 193 return this.buildBaseFeedUrls(params)
176 } 194 }
177 195
196 getVideoChannelFeedUrls (videoChannelId: number) {
197 let params = this.restService.addRestGetParams(new HttpParams())
198 params = params.set('videoChannelId', videoChannelId.toString())
199
200 return this.buildBaseFeedUrls(params)
201 }
202
178 searchVideos ( 203 searchVideos (
179 search: string, 204 search: string,
180 videoPagination: ComponentPagination, 205 videoPagination: ComponentPagination,
diff --git a/client/src/app/videos/+video-watch/video-watch.component.html b/client/src/app/videos/+video-watch/video-watch.component.html
index 5d3361561..f38e90927 100644
--- a/client/src/app/videos/+video-watch/video-watch.component.html
+++ b/client/src/app/videos/+video-watch/video-watch.component.html
@@ -22,7 +22,7 @@
22 </div> 22 </div>
23 23
24 <div class="video-info-by"> 24 <div class="video-info-by">
25 <a [routerLink]="[ '/account', video.account.id ]" title="Go the account page"> 25 <a [routerLink]="[ '/accounts', video.account.id ]" title="Go the account page">
26 <span>By {{ video.by }}</span> 26 <span>By {{ video.by }}</span>
27 <img [src]="video.accountAvatarUrl" alt="Account avatar" /> 27 <img [src]="video.accountAvatarUrl" alt="Account avatar" />
28 </a> 28 </a>
diff --git a/client/src/sass/include/_mixins.scss b/client/src/sass/include/_mixins.scss
index cbf9b566a..c43bd9803 100644
--- a/client/src/sass/include/_mixins.scss
+++ b/client/src/sass/include/_mixins.scss
@@ -320,4 +320,48 @@
320 color: $orange-color; 320 color: $orange-color;
321 font-weight: $font-bold; 321 font-weight: $font-bold;
322 font-size: 13px; 322 font-size: 13px;
323}
324
325@mixin sub-menu-with-actor {
326 height: 160px;
327 display: flex;
328 flex-direction: column;
329 align-items: start;
330
331 .actor {
332 display: flex;
333 margin-top: 20px;
334 margin-bottom: 20px;
335
336 img {
337 @include avatar(80px);
338
339 margin-right: 20px;
340 }
341
342 .actor-info {
343 display: flex;
344 flex-direction: column;
345 justify-content: center;
346
347 .actor-display-name {
348 font-size: 23px;
349 font-weight: $font-bold;
350 }
351
352 .actor-followers {
353 font-size: 15px;
354 }
355 }
356 }
357
358 .links {
359 margin-top: 0;
360 margin-bottom: 10px;
361
362 a {
363 margin-top: 0;
364 margin-bottom: 0;
365 }
366 }
323} \ No newline at end of file 367} \ No newline at end of file
diff --git a/server/tests/api/check-params/videos.ts b/server/tests/api/check-params/videos.ts
index 850ad12e0..499a4fc94 100644
--- a/server/tests/api/check-params/videos.ts
+++ b/server/tests/api/check-params/videos.ts
@@ -140,7 +140,7 @@ describe('Test videos API validator', function () {
140 let path: string 140 let path: string
141 141
142 before(async function () { 142 before(async function () {
143 path = '/api/v1/accounts/' + accountUUID + '/video-channels/' + channelUUID + '/videos' 143 path = '/api/v1/video-channels/' + channelUUID + '/videos'
144 }) 144 })
145 145
146 it('Should fail with a bad start pagination', async function () { 146 it('Should fail with a bad start pagination', async function () {
diff --git a/server/tests/api/videos/multiple-servers.ts b/server/tests/api/videos/multiple-servers.ts
index 6238cdc08..e462a2d47 100644
--- a/server/tests/api/videos/multiple-servers.ts
+++ b/server/tests/api/videos/multiple-servers.ts
@@ -47,7 +47,6 @@ describe('Test multiple servers', function () {
47 let servers: ServerInfo[] = [] 47 let servers: ServerInfo[] = []
48 const toRemove = [] 48 const toRemove = []
49 let videoUUID = '' 49 let videoUUID = ''
50 let accountId: number
51 let videoChannelId: number 50 let videoChannelId: number
52 51
53 before(async function () { 52 before(async function () {
@@ -59,16 +58,11 @@ describe('Test multiple servers', function () {
59 await setAccessTokensToServers(servers) 58 await setAccessTokensToServers(servers)
60 59
61 { 60 {
62 const res = await getAccountsList(servers[0].url)
63 accountId = res.body.data[0].id
64 }
65
66 {
67 const videoChannel = { 61 const videoChannel = {
68 name: 'my channel', 62 name: 'my channel',
69 description: 'super channel' 63 description: 'super channel'
70 } 64 }
71 await addVideoChannel(servers[ 0 ].url, servers[ 0 ].accessToken, accountId, videoChannel) 65 await addVideoChannel(servers[ 0 ].url, servers[ 0 ].accessToken, videoChannel)
72 const channelRes = await getVideoChannelsList(servers[ 0 ].url, 0, 1) 66 const channelRes = await getVideoChannelsList(servers[ 0 ].url, 0, 1)
73 videoChannelId = channelRes.body.data[ 0 ].id 67 videoChannelId = channelRes.body.data[ 0 ].id
74 } 68 }