From bce47964f6241ae56f61089d144b29eb9b5da6d3 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Thu, 14 Mar 2019 14:05:36 +0100 Subject: [PATCH] Add video channel view --- .../+my-account/my-account-routing.module.ts | 12 ++-- ...unt-video-playlist-elements.component.html | 31 ++++++--- ...unt-video-playlist-elements.component.scss | 11 +++ ...count-video-playlist-elements.component.ts | 6 +- .../my-account-video-playlists.component.html | 3 +- .../my-account-video-playlists.component.scss | 3 +- .../my-account-videos.component.html | 2 +- .../my-account-videos.component.scss | 4 +- .../video-channel-playlists.component.html | 11 +++ .../video-channel-playlists.component.scss | 9 +++ .../video-channel-playlists.component.ts | 67 +++++++++++++++++++ .../video-channels-routing.module.ts | 10 +++ .../video-channels.component.html | 1 + .../+video-channels/video-channels.module.ts | 4 +- ...-playlist-element-miniature.component.html | 2 +- ...-playlist-element-miniature.component.scss | 4 +- ...eo-playlist-element-miniature.component.ts | 16 ++++- .../video-playlist-miniature.component.html | 18 ++++- .../video-playlist-miniature.component.scss | 36 +++++++++- .../video-playlist-miniature.component.ts | 3 + .../video/infinite-scroller.directive.ts | 23 +++++-- .../+video-watch/video-watch.component.html | 6 +- .../+video-watch/video-watch.component.scss | 3 +- .../+video-watch/video-watch.component.ts | 4 +- client/src/sass/application.scss | 2 +- client/src/sass/include/_variables.scss | 2 + 26 files changed, 248 insertions(+), 45 deletions(-) create mode 100644 client/src/app/+video-channels/video-channel-playlists/video-channel-playlists.component.html create mode 100644 client/src/app/+video-channels/video-channel-playlists/video-channel-playlists.component.scss create mode 100644 client/src/app/+video-channels/video-channel-playlists/video-channel-playlists.component.ts diff --git a/client/src/app/+my-account/my-account-routing.module.ts b/client/src/app/+my-account/my-account-routing.module.ts index 3f921b13f..07557a029 100644 --- a/client/src/app/+my-account/my-account-routing.module.ts +++ b/client/src/app/+my-account/my-account-routing.module.ts @@ -85,20 +85,20 @@ const myAccountRoutes: Routes = [ } }, { - path: 'video-playlists/:videoPlaylistId', - component: MyAccountVideoPlaylistElementsComponent, + path: 'video-playlists/create', + component: MyAccountVideoPlaylistCreateComponent, data: { meta: { - title: 'Playlist elements' + title: 'Create new playlist' } } }, { - path: 'video-playlists/create', - component: MyAccountVideoPlaylistCreateComponent, + path: 'video-playlists/:videoPlaylistId', + component: MyAccountVideoPlaylistElementsComponent, data: { meta: { - title: 'Create new playlist' + title: 'Playlist elements' } } }, diff --git a/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlist-elements.component.html b/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlist-elements.component.html index bc26e198e..95d4519fa 100644 --- a/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlist-elements.component.html +++ b/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlist-elements.component.html @@ -1,11 +1,26 @@ -
No videos in this playlist.
+
-
-
- - +
+ +
+ +
+
No videos in this playlist.
+ +
+
+ + +
+
diff --git a/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlist-elements.component.scss b/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlist-elements.component.scss index b05af0490..900669827 100644 --- a/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlist-elements.component.scss +++ b/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlist-elements.component.scss @@ -2,6 +2,17 @@ @import '_mixins'; @import '_miniature'; +.playlist-info { + background-color: var(--submenuColor); + margin-left: -15px; + margin-top: -$sub-menu-margin-bottom; + + padding: $sub-menu-margin-bottom 0; + + display: flex; + justify-content: center; +} + // Thanks Angular CDK <3 https://material.angular.io/cdk/drag-drop/examples .cdk-drag-preview { box-sizing: border-box; diff --git a/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlist-elements.component.ts b/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlist-elements.component.ts index dcf470be3..25d51d2cb 100644 --- a/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlist-elements.component.ts +++ b/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlist-elements.component.ts @@ -24,7 +24,7 @@ export class MyAccountVideoPlaylistElementsComponent implements OnInit, OnDestro pagination: ComponentPagination = { currentPage: 1, - itemsPerPage: 10, + itemsPerPage: 30, totalItems: null } @@ -123,6 +123,10 @@ export class MyAccountVideoPlaylistElementsComponent implements OnInit, OnDestro this.loadElements() } + trackByFn (index: number, elem: Video) { + return elem.id + } + private loadElements () { this.videoService.getPlaylistVideos(this.videoPlaylistId, this.pagination) .subscribe(({ totalVideos, videos }) => { diff --git a/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlists.component.html b/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlists.component.html index 7d1bed12a..322560673 100644 --- a/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlists.component.html +++ b/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlists.component.html @@ -8,7 +8,8 @@
- +
diff --git a/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlists.component.scss b/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlists.component.scss index 88fba5b05..f648c33e4 100644 --- a/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlists.component.scss +++ b/client/src/app/+my-account/my-account-video-playlists/my-account-video-playlists.component.scss @@ -20,8 +20,9 @@ /deep/ .miniature { display: flex; - .miniature-bottom { + .miniature-info { margin-left: 10px; + width: auto; } } } diff --git a/client/src/app/+my-account/my-account-videos/my-account-videos.component.html b/client/src/app/+my-account/my-account-videos/my-account-videos.component.html index 69748ef37..b09e845ac 100644 --- a/client/src/app/+my-account/my-account-videos/my-account-videos.component.html +++ b/client/src/app/+my-account/my-account-videos/my-account-videos.component.html @@ -17,7 +17,7 @@
{{ video.name }} {{ video.createdAt | myFromNow }} - {{ video.views | myNumberFormatter }} views -
{{ video.privacy.label }}{{ getStateLabel(video) }}
+
{{ video.privacy.label }}{{ getStateLabel(video) }}
Blacklisted {{ video.blacklistedReason }} diff --git a/client/src/app/+my-account/my-account-videos/my-account-videos.component.scss b/client/src/app/+my-account/my-account-videos/my-account-videos.component.scss index 39d0cf2f7..f6b5faa45 100644 --- a/client/src/app/+my-account/my-account-videos/my-account-videos.component.scss +++ b/client/src/app/+my-account/my-account-videos/my-account-videos.component.scss @@ -64,11 +64,11 @@ } .video-info-date-views, - .video-info-private, + .video-info-privacy, .video-info-blacklisted { font-size: 13px; - &.video-info-private, + &.video-info-privacy, &.video-info-blacklisted .blacklisted-label { font-weight: $font-semibold; } diff --git a/client/src/app/+video-channels/video-channel-playlists/video-channel-playlists.component.html b/client/src/app/+video-channels/video-channel-playlists/video-channel-playlists.component.html new file mode 100644 index 000000000..0d9fba375 --- /dev/null +++ b/client/src/app/+video-channels/video-channel-playlists/video-channel-playlists.component.html @@ -0,0 +1,11 @@ +
+ Created {{pagination.totalItems}} playlists +
+ +
This channel does not have playlists.
+ +
+
+ +
+
diff --git a/client/src/app/+video-channels/video-channel-playlists/video-channel-playlists.component.scss b/client/src/app/+video-channels/video-channel-playlists/video-channel-playlists.component.scss new file mode 100644 index 000000000..fe9104794 --- /dev/null +++ b/client/src/app/+video-channels/video-channel-playlists/video-channel-playlists.component.scss @@ -0,0 +1,9 @@ +.video-playlist { + display: flex; + justify-content: center; + + my-video-playlist-miniature { + margin-right: 15px; + margin-bottom: 30px; + } +} diff --git a/client/src/app/+video-channels/video-channel-playlists/video-channel-playlists.component.ts b/client/src/app/+video-channels/video-channel-playlists/video-channel-playlists.component.ts new file mode 100644 index 000000000..f878a5a24 --- /dev/null +++ b/client/src/app/+video-channels/video-channel-playlists/video-channel-playlists.component.ts @@ -0,0 +1,67 @@ +import { Component, OnDestroy, OnInit } from '@angular/core' +import { AuthService } from '../../core/auth' +import { ConfirmService } from '../../core/confirm' +import { VideoChannelService } from '@app/shared/video-channel/video-channel.service' +import { VideoChannel } from '@app/shared/video-channel/video-channel.model' +import { flatMap } from 'rxjs/operators' +import { Subscription } from 'rxjs' +import { Notifier } from '@app/core' +import { VideoPlaylist } from '@app/shared/video-playlist/video-playlist.model' +import { ComponentPagination } from '@app/shared/rest/component-pagination.model' +import { VideoPlaylistService } from '@app/shared/video-playlist/video-playlist.service' + +@Component({ + selector: 'my-video-channel-playlists', + templateUrl: './video-channel-playlists.component.html', + styleUrls: [ './video-channel-playlists.component.scss' ] +}) +export class VideoChannelPlaylistsComponent implements OnInit, OnDestroy { + videoPlaylists: VideoPlaylist[] = [] + + pagination: ComponentPagination = { + currentPage: 1, + itemsPerPage: 20, + totalItems: null + } + + private videoChannelSub: Subscription + private videoChannel: VideoChannel + + constructor ( + private authService: AuthService, + private notifier: Notifier, + private confirmService: ConfirmService, + private videoPlaylistService: VideoPlaylistService, + private videoChannelService: VideoChannelService + ) {} + + ngOnInit () { + // Parent get the video channel for us + this.videoChannelSub = this.videoChannelService.videoChannelLoaded + .subscribe(videoChannel => { + this.videoChannel = videoChannel + this.loadVideoPlaylists() + }) + } + + ngOnDestroy () { + if (this.videoChannelSub) this.videoChannelSub.unsubscribe() + } + + onNearOfBottom () { + // Last page + if (this.pagination.totalItems <= (this.pagination.currentPage * this.pagination.itemsPerPage)) return + + this.pagination.currentPage += 1 + this.loadVideoPlaylists() + } + + private loadVideoPlaylists () { + this.authService.userInformationLoaded + .pipe(flatMap(() => this.videoPlaylistService.listChannelPlaylists(this.videoChannel))) + .subscribe(res => { + this.videoPlaylists = this.videoPlaylists.concat(res.data) + this.pagination.totalItems = res.total + }) + } +} diff --git a/client/src/app/+video-channels/video-channels-routing.module.ts b/client/src/app/+video-channels/video-channels-routing.module.ts index 3ac3533d9..cedd07d39 100644 --- a/client/src/app/+video-channels/video-channels-routing.module.ts +++ b/client/src/app/+video-channels/video-channels-routing.module.ts @@ -4,6 +4,7 @@ import { MetaGuard } from '@ngx-meta/core' import { VideoChannelsComponent } from './video-channels.component' import { VideoChannelVideosComponent } from './video-channel-videos/video-channel-videos.component' import { VideoChannelAboutComponent } from './video-channel-about/video-channel-about.component' +import { VideoChannelPlaylistsComponent } from '@app/+video-channels/video-channel-playlists/video-channel-playlists.component' const videoChannelsRoutes: Routes = [ { @@ -25,6 +26,15 @@ const videoChannelsRoutes: Routes = [ } } }, + { + path: 'video-playlists', + component: VideoChannelPlaylistsComponent, + data: { + meta: { + title: 'Video channel playlists' + } + } + }, { path: 'about', component: VideoChannelAboutComponent, diff --git a/client/src/app/+video-channels/video-channels.component.html b/client/src/app/+video-channels/video-channels.component.html index c65b5713d..600b7a365 100644 --- a/client/src/app/+video-channels/video-channels.component.html +++ b/client/src/app/+video-channels/video-channels.component.html @@ -22,6 +22,7 @@
diff --git a/client/src/app/+video-channels/video-channels.module.ts b/client/src/app/+video-channels/video-channels.module.ts index a09ea6f11..6975d05b2 100644 --- a/client/src/app/+video-channels/video-channels.module.ts +++ b/client/src/app/+video-channels/video-channels.module.ts @@ -4,6 +4,7 @@ import { VideoChannelsRoutingModule } from './video-channels-routing.module' import { VideoChannelsComponent } from './video-channels.component' import { VideoChannelVideosComponent } from './video-channel-videos/video-channel-videos.component' import { VideoChannelAboutComponent } from './video-channel-about/video-channel-about.component' +import { VideoChannelPlaylistsComponent } from '@app/+video-channels/video-channel-playlists/video-channel-playlists.component' @NgModule({ imports: [ @@ -14,7 +15,8 @@ import { VideoChannelAboutComponent } from './video-channel-about/video-channel- declarations: [ VideoChannelsComponent, VideoChannelVideosComponent, - VideoChannelAboutComponent + VideoChannelAboutComponent, + VideoChannelPlaylistsComponent ], exports: [ diff --git a/client/src/app/shared/video-playlist/video-playlist-element-miniature.component.html b/client/src/app/shared/video-playlist/video-playlist-element-miniature.component.html index 1f178675f..4764fc0e1 100644 --- a/client/src/app/shared/video-playlist/video-playlist-element-miniature.component.html +++ b/client/src/app/shared/video-playlist/video-playlist-element-miniature.component.html @@ -2,7 +2,7 @@
- {{ video.playlistElement.position }} + {{ position }}
() @@ -44,7 +46,8 @@ export class VideoPlaylistElementMiniatureComponent { private route: ActivatedRoute, private i18n: I18n, private videoService: VideoService, - private videoPlaylistService: VideoPlaylistService + private videoPlaylistService: VideoPlaylistService, + private cdr: ChangeDetectorRef ) {} buildRouterLink () { @@ -95,6 +98,8 @@ export class VideoPlaylistElementMiniatureComponent { video.playlistElement.startTimestamp = body.startTimestamp video.playlistElement.stopTimestamp = body.stopTimestamp + + this.cdr.detectChanges() }, err => this.notifier.error(err.message) @@ -145,5 +150,10 @@ export class VideoPlaylistElementMiniatureComponent { this.timestampOptions.stopTimestamp = video.playlistElement.stopTimestamp } } + + // FIXME: why do we have to use setTimeout here? + setTimeout(() => { + this.cdr.detectChanges() + }) } } diff --git a/client/src/app/shared/video-playlist/video-playlist-miniature.component.html b/client/src/app/shared/video-playlist/video-playlist-miniature.component.html index a136f9233..c01c73012 100644 --- a/client/src/app/shared/video-playlist/video-playlist-miniature.component.html +++ b/client/src/app/shared/video-playlist/video-playlist-miniature.component.html @@ -1,6 +1,6 @@
-
- +
+ {{ playlist.displayName }} + +
{{ playlist.privacy.label }}
+ +
+ + {{ playlist.videoChannelBy }} + + +
Updated {{ playlist.updatedAt | myFromNow }}
+
+ +
{{ playlist.description }}
diff --git a/client/src/app/shared/video-playlist/video-playlist-miniature.component.scss b/client/src/app/shared/video-playlist/video-playlist-miniature.component.scss index 72158eb10..94edd1177 100644 --- a/client/src/app/shared/video-playlist/video-playlist-miniature.component.scss +++ b/client/src/app/shared/video-playlist/video-playlist-miniature.component.scss @@ -11,9 +11,11 @@ } } - &.to-manage .play-overlay, + &.to-manage, &.no-videos { - display: none; + .play-overlay { + display: none; + } } .miniature-thumbnail { @@ -34,7 +36,7 @@ } } - .miniature-bottom { + .miniature-info { width: 200px; margin-top: 2px; line-height: normal; @@ -42,5 +44,33 @@ .miniature-name { @include miniature-name; } + + .video-info-by-date { + display: flex; + font-size: 13px; + margin: 5px 0; + + .by { + @include disable-default-a-behaviour; + + display: block; + color: var(--mainForegroundColor); + + &::after { + content: '-'; + margin: 0 3px; + } + } + } + + .video-info-privacy { + font-size: 13px; + font-weight: $font-semibold; + } + + .video-info-description { + margin-top: 10px; + color: $grey-foreground-color; + } } } diff --git a/client/src/app/shared/video-playlist/video-playlist-miniature.component.ts b/client/src/app/shared/video-playlist/video-playlist-miniature.component.ts index cb5803400..523e96f2a 100644 --- a/client/src/app/shared/video-playlist/video-playlist-miniature.component.ts +++ b/client/src/app/shared/video-playlist/video-playlist-miniature.component.ts @@ -9,6 +9,9 @@ import { VideoPlaylist } from '@app/shared/video-playlist/video-playlist.model' export class VideoPlaylistMiniatureComponent { @Input() playlist: VideoPlaylist @Input() toManage = false + @Input() displayChannel = false + @Input() displayDescription = false + @Input() displayPrivacy = false getPlaylistUrl () { if (this.toManage) return [ '/my-account/video-playlists', this.playlist.uuid ] diff --git a/client/src/app/shared/video/infinite-scroller.directive.ts b/client/src/app/shared/video/infinite-scroller.directive.ts index 186597a3a..a9e75007c 100644 --- a/client/src/app/shared/video/infinite-scroller.directive.ts +++ b/client/src/app/shared/video/infinite-scroller.directive.ts @@ -1,5 +1,5 @@ import { distinct, distinctUntilChanged, filter, map, share, startWith, throttleTime } from 'rxjs/operators' -import { Directive, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core' +import { Directive, ElementRef, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core' import { fromEvent, Subscription } from 'rxjs' @Directive({ @@ -11,7 +11,7 @@ export class InfiniteScrollerDirective implements OnInit, OnDestroy { @Input() firstLoadedPage = 1 @Input() percentLimit = 70 @Input() autoInit = false - @Input() container = document.body + @Input() onItself = false @Output() nearOfBottom = new EventEmitter() @Output() nearOfTop = new EventEmitter() @@ -24,8 +24,9 @@ export class InfiniteScrollerDirective implements OnInit, OnDestroy { private scrollUpSub: Subscription private pageChangeSub: Subscription private middleScreen: number + private container: HTMLElement - constructor () { + constructor (private el: ElementRef) { this.decimalLimit = this.percentLimit / 100 } @@ -40,16 +41,20 @@ export class InfiniteScrollerDirective implements OnInit, OnDestroy { } initialize () { + if (this.onItself) { + this.container = this.el.nativeElement + } + this.middleScreen = window.innerHeight / 2 // Emit the last value const throttleOptions = { leading: true, trailing: true } - const scrollObservable = fromEvent(window, 'scroll') + const scrollObservable = fromEvent(this.container || window, 'scroll') .pipe( startWith(null), throttleTime(200, undefined, throttleOptions), - map(() => ({ current: window.scrollY, maximumScroll: this.container.clientHeight - window.innerHeight })), + map(() => this.getScrollInfo()), distinctUntilChanged((o1, o2) => o1.current === o2.current), share() ) @@ -102,4 +107,12 @@ export class InfiniteScrollerDirective implements OnInit, OnDestroy { // Offset page return page + (this.firstLoadedPage - 1) } + + private getScrollInfo () { + if (this.container) { + return { current: this.container.scrollTop, maximumScroll: this.container.scrollHeight } + } + + return { current: window.scrollY, maximumScroll: document.body.clientHeight - window.innerHeight } + } } 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 7f3d1cc2e..3df5b7b19 100644 --- a/client/src/app/videos/+video-watch/video-watch.component.html +++ b/client/src/app/videos/+video-watch/video-watch.component.html @@ -9,7 +9,7 @@
-
+
{{ playlist.displayName }} @@ -27,10 +27,10 @@
-
+
diff --git a/client/src/app/videos/+video-watch/video-watch.component.scss b/client/src/app/videos/+video-watch/video-watch.component.scss index e1cb249ef..281b9240b 100644 --- a/client/src/app/videos/+video-watch/video-watch.component.scss +++ b/client/src/app/videos/+video-watch/video-watch.component.scss @@ -43,11 +43,12 @@ $other-videos-width: 260px; .playlist { width: 400px; height: 66vh; - background-color: #e4e4e4; + background-color: var(--mainBackgroundColor); overflow-y: auto; .playlist-info { padding: 5px 30px; + background-color: #e4e4e4; .playlist-display-name { font-size: 18px; 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 ddd0f1766..adb728aba 100644 --- a/client/src/app/videos/+video-watch/video-watch.component.ts +++ b/client/src/app/videos/+video-watch/video-watch.component.ts @@ -58,7 +58,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy { playlistVideos: Video[] = [] playlistPagination: ComponentPagination = { currentPage: 1, - itemsPerPage: 10, + itemsPerPage: 30, totalItems: null } noPlaylistVideos = false @@ -401,7 +401,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy { } private loadPlaylistElements (redirectToFirst = false) { - this.videoService.getPlaylistVideos(this.playlist.id, this.playlistPagination) + this.videoService.getPlaylistVideos(this.playlist.uuid, this.playlistPagination) .subscribe(({ totalVideos, videos }) => { this.playlistVideos = this.playlistVideos.concat(videos) this.playlistPagination.totalItems = totalVideos diff --git a/client/src/sass/application.scss b/client/src/sass/application.scss index 478737a43..28b466c01 100644 --- a/client/src/sass/application.scss +++ b/client/src/sass/application.scss @@ -104,7 +104,7 @@ label { background-color: var(--submenuColor); width: 100%; height: 81px; - margin-bottom: 30px; + margin-bottom: $sub-menu-margin-bottom; display: flex; align-items: center; padding-left: $not-expanded-horizontal-margins; diff --git a/client/src/sass/include/_variables.scss b/client/src/sass/include/_variables.scss index deabbf6d4..b8eb06f2c 100644 --- a/client/src/sass/include/_variables.scss +++ b/client/src/sass/include/_variables.scss @@ -54,6 +54,8 @@ $theater-bottom-space: 115px; $input-background-color: $bg-color; $input-placeholder-color: #898989; +$sub-menu-margin-bottom: 30px; + /*** map theme ***/ // pass variables into a sass map, -- 2.41.0