From ba5d4a849c7d7ba05f093480ae12286c4af61556 Mon Sep 17 00:00:00 2001 From: Rigel Kent Date: Wed, 27 Jan 2021 17:15:21 +0100 Subject: move from trending routes to alg param --- .../src/app/+videos/video-list/trending/index.ts | 4 +- .../video-list/trending/video-hot.component.ts | 85 ---------------- .../trending/video-most-liked.component.ts | 81 --------------- .../trending/video-most-viewed.component.ts | 99 ------------------ .../trending/video-trending-header.component.html | 10 +- .../trending/video-trending-header.component.ts | 67 ++++++++----- .../trending/video-trending.component.ts | 111 +++++++++++++++++++++ client/src/app/+videos/videos-routing.module.ts | 42 +------- client/src/app/+videos/videos.module.ts | 10 +- 9 files changed, 169 insertions(+), 340 deletions(-) delete mode 100644 client/src/app/+videos/video-list/trending/video-hot.component.ts delete mode 100644 client/src/app/+videos/video-list/trending/video-most-liked.component.ts delete mode 100644 client/src/app/+videos/video-list/trending/video-most-viewed.component.ts create mode 100644 client/src/app/+videos/video-list/trending/video-trending.component.ts (limited to 'client/src/app/+videos') diff --git a/client/src/app/+videos/video-list/trending/index.ts b/client/src/app/+videos/video-list/trending/index.ts index 93f4b1df6..70835885a 100644 --- a/client/src/app/+videos/video-list/trending/index.ts +++ b/client/src/app/+videos/video-list/trending/index.ts @@ -1,4 +1,2 @@ export * from './video-trending-header.component' -export * from './video-hot.component' -export * from './video-most-viewed.component' -export * from './video-most-liked.component' +export * from './video-trending.component' diff --git a/client/src/app/+videos/video-list/trending/video-hot.component.ts b/client/src/app/+videos/video-list/trending/video-hot.component.ts deleted file mode 100644 index 1617eb21e..000000000 --- a/client/src/app/+videos/video-list/trending/video-hot.component.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { Component, ComponentFactoryResolver, Injector, OnDestroy, OnInit } from '@angular/core' -import { ActivatedRoute, Router } from '@angular/router' -import { AuthService, LocalStorageService, Notifier, ScreenService, ServerService, UserService } from '@app/core' -import { HooksService } from '@app/core/plugins/hooks.service' -import { immutableAssign } from '@app/helpers' -import { VideoService } from '@app/shared/shared-main' -import { AbstractVideoList } from '@app/shared/shared-video-miniature' -import { VideoSortField } from '@shared/models' -import { VideoTrendingHeaderComponent } from './video-trending-header.component' - -@Component({ - selector: 'my-videos-hot', - styleUrls: [ '../../../shared/shared-video-miniature/abstract-video-list.scss' ], - templateUrl: '../../../shared/shared-video-miniature/abstract-video-list.html' -}) -export class VideoHotComponent extends AbstractVideoList implements OnInit, OnDestroy { - HeaderComponent = VideoTrendingHeaderComponent - titlePage: string - defaultSort: VideoSortField = '-hot' - - useUserVideoPreferences = true - - constructor ( - protected router: Router, - protected serverService: ServerService, - protected route: ActivatedRoute, - protected notifier: Notifier, - protected authService: AuthService, - protected userService: UserService, - protected screenService: ScreenService, - protected storageService: LocalStorageService, - protected cfr: ComponentFactoryResolver, - private videoService: VideoService, - private hooks: HooksService - ) { - super() - - this.headerComponentInjector = this.getInjector() - } - - ngOnInit () { - super.ngOnInit() - - this.generateSyndicationList() - } - - ngOnDestroy () { - super.ngOnDestroy() - } - - getVideosObservable (page: number) { - const newPagination = immutableAssign(this.pagination, { currentPage: page }) - const params = { - videoPagination: newPagination, - sort: this.sort, - categoryOneOf: this.categoryOneOf, - languageOneOf: this.languageOneOf, - nsfwPolicy: this.nsfwPolicy, - skipCount: true - } - - return this.hooks.wrapObsFun( - this.videoService.getVideos.bind(this.videoService), - params, - 'common', - 'filter:api.trending-videos.videos.list.params', - 'filter:api.trending-videos.videos.list.result' - ) - } - - generateSyndicationList () { - this.syndicationItems = this.videoService.getVideoFeedUrls(this.sort, undefined, this.categoryOneOf) - } - - getInjector () { - return Injector.create({ - providers: [{ - provide: 'data', - useValue: { - model: this.defaultSort - } - }] - }) - } -} diff --git a/client/src/app/+videos/video-list/trending/video-most-liked.component.ts b/client/src/app/+videos/video-list/trending/video-most-liked.component.ts deleted file mode 100644 index 1781cc6aa..000000000 --- a/client/src/app/+videos/video-list/trending/video-most-liked.component.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { Component, ComponentFactoryResolver, Injector, OnInit } from '@angular/core' -import { ActivatedRoute, Router } from '@angular/router' -import { AuthService, LocalStorageService, Notifier, ScreenService, ServerService, UserService } from '@app/core' -import { HooksService } from '@app/core/plugins/hooks.service' -import { immutableAssign } from '@app/helpers' -import { VideoService } from '@app/shared/shared-main' -import { AbstractVideoList } from '@app/shared/shared-video-miniature' -import { VideoSortField } from '@shared/models' -import { VideoTrendingHeaderComponent } from './video-trending-header.component' - -@Component({ - selector: 'my-videos-most-liked', - styleUrls: [ '../../../shared/shared-video-miniature/abstract-video-list.scss' ], - templateUrl: '../../../shared/shared-video-miniature/abstract-video-list.html' -}) -export class VideoMostLikedComponent extends AbstractVideoList implements OnInit { - HeaderComponent = VideoTrendingHeaderComponent - titlePage: string - defaultSort: VideoSortField = '-likes' - - useUserVideoPreferences = true - - constructor ( - protected router: Router, - protected serverService: ServerService, - protected route: ActivatedRoute, - protected notifier: Notifier, - protected authService: AuthService, - protected userService: UserService, - protected screenService: ScreenService, - protected storageService: LocalStorageService, - protected cfr: ComponentFactoryResolver, - private videoService: VideoService, - private hooks: HooksService - ) { - super() - - this.headerComponentInjector = this.getInjector() - } - - ngOnInit () { - super.ngOnInit() - - this.generateSyndicationList() - } - - getVideosObservable (page: number) { - const newPagination = immutableAssign(this.pagination, { currentPage: page }) - const params = { - videoPagination: newPagination, - sort: this.sort, - categoryOneOf: this.categoryOneOf, - languageOneOf: this.languageOneOf, - nsfwPolicy: this.nsfwPolicy, - skipCount: true - } - - return this.hooks.wrapObsFun( - this.videoService.getVideos.bind(this.videoService), - params, - 'common', - 'filter:api.most-liked-videos.videos.list.params', - 'filter:api.most-liked-videos.videos.list.result' - ) - } - - generateSyndicationList () { - this.syndicationItems = this.videoService.getVideoFeedUrls(this.sort, undefined, this.categoryOneOf) - } - - getInjector () { - return Injector.create({ - providers: [{ - provide: 'data', - useValue: { - model: this.defaultSort - } - }] - }) - } -} diff --git a/client/src/app/+videos/video-list/trending/video-most-viewed.component.ts b/client/src/app/+videos/video-list/trending/video-most-viewed.component.ts deleted file mode 100644 index 98ced42d6..000000000 --- a/client/src/app/+videos/video-list/trending/video-most-viewed.component.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { Component, ComponentFactoryResolver, Injector, OnDestroy, OnInit } from '@angular/core' -import { ActivatedRoute, Router } from '@angular/router' -import { AuthService, LocalStorageService, Notifier, ScreenService, ServerService, UserService } from '@app/core' -import { HooksService } from '@app/core/plugins/hooks.service' -import { immutableAssign } from '@app/helpers' -import { VideoService } from '@app/shared/shared-main' -import { AbstractVideoList } from '@app/shared/shared-video-miniature' -import { VideoSortField } from '@shared/models' -import { VideoTrendingHeaderComponent } from './video-trending-header.component' - -@Component({ - selector: 'my-videos-most-viewed', - styleUrls: [ '../../../shared/shared-video-miniature/abstract-video-list.scss' ], - templateUrl: '../../../shared/shared-video-miniature/abstract-video-list.html' -}) -export class VideoMostViewedComponent extends AbstractVideoList implements OnInit, OnDestroy { - HeaderComponent = VideoTrendingHeaderComponent - titlePage: string - defaultSort: VideoSortField = '-trending' - - useUserVideoPreferences = true - - constructor ( - protected router: Router, - protected serverService: ServerService, - protected route: ActivatedRoute, - protected notifier: Notifier, - protected authService: AuthService, - protected userService: UserService, - protected screenService: ScreenService, - protected storageService: LocalStorageService, - protected cfr: ComponentFactoryResolver, - private videoService: VideoService, - private hooks: HooksService - ) { - super() - - this.headerComponentInjector = this.getInjector() - } - - ngOnInit () { - super.ngOnInit() - - this.generateSyndicationList() - - this.serverService.getConfig().subscribe( - config => { - const trendingDays = config.trending.videos.intervalDays - - if (trendingDays === 1) { - this.titleTooltip = $localize`Trending videos are those totalizing the greatest number of views during the last 24 hours` - } else { - this.titleTooltip = $localize`Trending videos are those totalizing the greatest number of views during the last ${trendingDays} days` - } - - this.headerComponentInjector = this.getInjector() - this.setHeader() - }) - } - - ngOnDestroy () { - super.ngOnDestroy() - } - - getVideosObservable (page: number) { - const newPagination = immutableAssign(this.pagination, { currentPage: page }) - const params = { - videoPagination: newPagination, - sort: this.sort, - categoryOneOf: this.categoryOneOf, - languageOneOf: this.languageOneOf, - nsfwPolicy: this.nsfwPolicy, - skipCount: true - } - - return this.hooks.wrapObsFun( - this.videoService.getVideos.bind(this.videoService), - params, - 'common', - 'filter:api.trending-videos.videos.list.params', - 'filter:api.trending-videos.videos.list.result' - ) - } - - generateSyndicationList () { - this.syndicationItems = this.videoService.getVideoFeedUrls(this.sort, undefined, this.categoryOneOf) - } - - getInjector () { - return Injector.create({ - providers: [{ - provide: 'data', - useValue: { - model: this.defaultSort - } - }] - }) - } -} diff --git a/client/src/app/+videos/video-list/trending/video-trending-header.component.html b/client/src/app/+videos/video-list/trending/video-trending-header.component.html index a025bf1a2..7eb1e4f95 100644 --- a/client/src/app/+videos/video-list/trending/video-trending-header.component.html +++ b/client/src/app/+videos/video-list/trending/video-trending-header.component.html @@ -1,6 +1,8 @@
- + + +
\ No newline at end of file diff --git a/client/src/app/+videos/video-list/trending/video-trending-header.component.ts b/client/src/app/+videos/video-list/trending/video-trending-header.component.ts index e49b61c68..33eaa2c1e 100644 --- a/client/src/app/+videos/video-list/trending/video-trending-header.component.ts +++ b/client/src/app/+videos/video-list/trending/video-trending-header.component.ts @@ -1,30 +1,34 @@ -import { Component, Inject, OnInit } from '@angular/core' -import { Router } from '@angular/router' +import { Component, HostBinding, Inject, OnDestroy, OnInit } from '@angular/core' +import { ActivatedRoute, Router } from '@angular/router' import { VideoListHeaderComponent } from '@app/shared/shared-video-miniature' import { GlobalIconName } from '@app/shared/shared-icons' -import { VideoSortField } from '@shared/models' import { ServerService } from '@app/core/server/server.service' +import { Subscription } from 'rxjs' +import { RedirectService } from '@app/core' interface VideoTrendingHeaderItem { label: string iconName: GlobalIconName - value: VideoSortField - path: string + value: string tooltip?: string hidden?: boolean } @Component({ selector: 'video-trending-title-page', - host: { 'class': 'title-page title-page-single' }, styleUrls: [ './video-trending-header.component.scss' ], templateUrl: './video-trending-header.component.html' }) -export class VideoTrendingHeaderComponent extends VideoListHeaderComponent implements OnInit { +export class VideoTrendingHeaderComponent extends VideoListHeaderComponent implements OnInit, OnDestroy { + @HostBinding('class') class = 'title-page title-page-single' + buttons: VideoTrendingHeaderItem[] + private algorithmChangeSub: Subscription + constructor ( @Inject('data') public data: any, + private route: ActivatedRoute, private router: Router, private serverService: ServerService ) { @@ -34,23 +38,20 @@ export class VideoTrendingHeaderComponent extends VideoListHeaderComponent imple { label: $localize`:A variant of Trending videos based on the number of recent interactions:Hot`, iconName: 'flame', - value: '-hot', - path: 'hot', + value: 'hot', tooltip: $localize`Videos totalizing the most interactions for recent videos`, hidden: true }, { label: $localize`:Main variant of Trending videos based on number of recent views:Views`, iconName: 'trending', - value: '-trending', - path: 'most-viewed', - tooltip: $localize`Videos totalizing the most views during the last 24 hours`, + value: 'most-viewed', + tooltip: $localize`Videos totalizing the most views during the last 24 hours` }, { label: $localize`:A variant of Trending videos based on the number of likes:Likes`, iconName: 'like', - value: '-likes', - path: 'most-liked', + value: 'most-liked', tooltip: $localize`Videos that have the most likes` } ] @@ -59,20 +60,40 @@ export class VideoTrendingHeaderComponent extends VideoListHeaderComponent imple ngOnInit () { this.serverService.getConfig() .subscribe(config => { - // don't filter if auto-blacklist is not enabled as this will be the only list - if (config.instance.pages.hot.enabled) { - const index = this.buttons.findIndex(b => b.path === 'hot') - this.buttons[index].hidden = false - } + this.buttons = this.buttons.map(b => { + b.hidden = !config.trending.videos.algorithms.enabled.includes(b.value) + return b + }) }) + + this.algorithmChangeSub = this.route.queryParams.subscribe( + queryParams => { + const algorithm = queryParams['alg'] + if (algorithm) { + this.data.model = algorithm + } else { + this.data.model = RedirectService.DEFAULT_TRENDING_ALGORITHM + } + } + ) } - get visibleButtons () { - return this.buttons.filter(b => !b.hidden) + ngOnDestroy () { + if (this.algorithmChangeSub) this.algorithmChangeSub.unsubscribe() } setSort () { - const path = this.buttons.find(b => b.value === this.data.model).path - this.router.navigate([ `/videos/${path}` ]) + const alg = this.data.model !== RedirectService.DEFAULT_TRENDING_ALGORITHM + ? this.data.model + : undefined + + this.router.navigate( + [], + { + relativeTo: this.route, + queryParams: { alg }, + queryParamsHandling: 'merge' + } + ) } } diff --git a/client/src/app/+videos/video-list/trending/video-trending.component.ts b/client/src/app/+videos/video-list/trending/video-trending.component.ts new file mode 100644 index 000000000..6128c4acd --- /dev/null +++ b/client/src/app/+videos/video-list/trending/video-trending.component.ts @@ -0,0 +1,111 @@ +import { Component, ComponentFactoryResolver, Injector, OnDestroy, OnInit } from '@angular/core' +import { ActivatedRoute, Router } from '@angular/router' +import { AuthService, LocalStorageService, Notifier, RedirectService, ScreenService, ServerService, UserService } from '@app/core' +import { HooksService } from '@app/core/plugins/hooks.service' +import { immutableAssign } from '@app/helpers' +import { VideoService } from '@app/shared/shared-main' +import { AbstractVideoList } from '@app/shared/shared-video-miniature' +import { VideoSortField } from '@shared/models' +import { Subscription } from 'rxjs' +import { VideoTrendingHeaderComponent } from './video-trending-header.component' + +@Component({ + selector: 'my-videos-hot', + styleUrls: [ '../../../shared/shared-video-miniature/abstract-video-list.scss' ], + templateUrl: '../../../shared/shared-video-miniature/abstract-video-list.html' +}) +export class VideoTrendingComponent extends AbstractVideoList implements OnInit, OnDestroy { + HeaderComponent = VideoTrendingHeaderComponent + titlePage: string + defaultSort: VideoSortField = '-trending' + + useUserVideoPreferences = true + + private algorithmChangeSub: Subscription + + constructor ( + protected router: Router, + protected serverService: ServerService, + protected route: ActivatedRoute, + protected notifier: Notifier, + protected authService: AuthService, + protected userService: UserService, + protected screenService: ScreenService, + protected storageService: LocalStorageService, + protected cfr: ComponentFactoryResolver, + private videoService: VideoService, + private hooks: HooksService + ) { + super() + + this.defaultSort = this.parseAlgorithm(RedirectService.DEFAULT_TRENDING_ALGORITHM) + + this.headerComponentInjector = this.getInjector() + } + + ngOnInit () { + super.ngOnInit() + + this.generateSyndicationList() + + this.algorithmChangeSub = this.route.queryParams.subscribe( + queryParams => { + const algorithm = queryParams['alg'] || RedirectService.DEFAULT_TRENDING_ALGORITHM + + this.sort = this.parseAlgorithm(algorithm) + this.reloadVideos() + } + ) + } + + ngOnDestroy () { + super.ngOnDestroy() + if (this.algorithmChangeSub) this.algorithmChangeSub.unsubscribe() + } + + getVideosObservable (page: number) { + const newPagination = immutableAssign(this.pagination, { currentPage: page }) + const params = { + videoPagination: newPagination, + sort: this.sort, + categoryOneOf: this.categoryOneOf, + languageOneOf: this.languageOneOf, + nsfwPolicy: this.nsfwPolicy, + skipCount: true + } + + return this.hooks.wrapObsFun( + this.videoService.getVideos.bind(this.videoService), + params, + 'common', + 'filter:api.trending-videos.videos.list.params', + 'filter:api.trending-videos.videos.list.result' + ) + } + + generateSyndicationList () { + this.syndicationItems = this.videoService.getVideoFeedUrls(this.sort, undefined, this.categoryOneOf) + } + + getInjector () { + return Injector.create({ + providers: [{ + provide: 'data', + useValue: { + model: this.defaultSort + } + }] + }) + } + + private parseAlgorithm (algorithm: string): VideoSortField { + switch (algorithm) { + case 'most-viewed': + return '-trending' + case 'most-liked': + return '-likes' + default: + return '-' + algorithm as VideoSortField + } + } +} diff --git a/client/src/app/+videos/videos-routing.module.ts b/client/src/app/+videos/videos-routing.module.ts index 973935af8..16e3b9bb2 100644 --- a/client/src/app/+videos/videos-routing.module.ts +++ b/client/src/app/+videos/videos-routing.module.ts @@ -1,11 +1,9 @@ import { NgModule } from '@angular/core' import { RouterModule, Routes } from '@angular/router' -import { LoginGuard, TrendingGuard } from '@app/core' +import { LoginGuard } from '@app/core' import { MetaGuard } from '@ngx-meta/core' +import { VideoTrendingComponent } from './video-list' import { VideoOverviewComponent } from './video-list/overview/video-overview.component' -import { VideoHotComponent } from './video-list/trending/video-hot.component' -import { VideoMostLikedComponent } from './video-list/trending/video-most-liked.component' -import { VideoMostViewedComponent } from './video-list/trending/video-most-viewed.component' import { VideoLocalComponent } from './video-list/video-local.component' import { VideoRecentlyAddedComponent } from './video-list/video-recently-added.component' import { VideoUserSubscriptionsComponent } from './video-list/video-user-subscriptions.component' @@ -28,46 +26,16 @@ const videosRoutes: Routes = [ }, { path: 'trending', - canActivate: [ TrendingGuard ] - }, - { - path: 'hot', - component: VideoHotComponent, + component: VideoTrendingComponent, data: { meta: { - title: $localize`Hot videos` - }, - reuse: { - enabled: true, - key: 'hot-videos-list' - } - } - }, - { - path: 'most-viewed', - component: VideoMostViewedComponent, - data: { - meta: { - title: $localize`Most viewed videos` - }, - reuse: { - enabled: true, - key: 'most-viewed-videos-list' + title: $localize`Trending videos` } } }, { path: 'most-liked', - component: VideoMostLikedComponent, - data: { - meta: { - title: $localize`Most liked videos` - }, - reuse: { - enabled: true, - key: 'most-liked-videos-list' - } - } + redirectTo: 'trending?alg=most-liked' }, { path: 'recently-added', diff --git a/client/src/app/+videos/videos.module.ts b/client/src/app/+videos/videos.module.ts index ae9c680eb..61d012d63 100644 --- a/client/src/app/+videos/videos.module.ts +++ b/client/src/app/+videos/videos.module.ts @@ -1,16 +1,12 @@ -import { CommonModule } from '@angular/common' import { NgModule } from '@angular/core' import { SharedFormModule } from '@app/shared/shared-forms' import { SharedGlobalIconModule } from '@app/shared/shared-icons' import { SharedMainModule } from '@app/shared/shared-main' import { SharedUserSubscriptionModule } from '@app/shared/shared-user-subscription' import { SharedVideoMiniatureModule } from '@app/shared/shared-video-miniature' -import { OverviewService } from './video-list' +import { OverviewService, VideoTrendingComponent } from './video-list' import { VideoOverviewComponent } from './video-list/overview/video-overview.component' import { VideoTrendingHeaderComponent } from './video-list/trending/video-trending-header.component' -import { VideoHotComponent } from './video-list/trending/video-hot.component' -import { VideoMostViewedComponent } from './video-list/trending/video-most-viewed.component' -import { VideoMostLikedComponent } from './video-list/trending/video-most-liked.component' import { VideoLocalComponent } from './video-list/video-local.component' import { VideoRecentlyAddedComponent } from './video-list/video-recently-added.component' import { VideoUserSubscriptionsComponent } from './video-list/video-user-subscriptions.component' @@ -32,9 +28,7 @@ import { VideosComponent } from './videos.component' VideosComponent, VideoTrendingHeaderComponent, - VideoMostViewedComponent, - VideoHotComponent, - VideoMostLikedComponent, + VideoTrendingComponent, VideoRecentlyAddedComponent, VideoLocalComponent, VideoUserSubscriptionsComponent, -- cgit v1.2.3