Handle sort in rss

This commit is contained in:
Chocobozzz 2018-04-17 10:56:27 +02:00
parent cc1561f9f7
commit 7b87d2d514
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
11 changed files with 60 additions and 65 deletions

View File

@ -9,7 +9,7 @@ import { fromEvent } from 'rxjs/observable/fromEvent'
import { Subscription } from 'rxjs/Subscription' import { Subscription } from 'rxjs/Subscription'
import { AuthService } from '../../core/auth' import { AuthService } from '../../core/auth'
import { ComponentPagination } from '../rest/component-pagination.model' import { ComponentPagination } from '../rest/component-pagination.model'
import { SortField } from './sort-field.type' import { VideoSortField } from './sort-field.type'
import { Video } from './video.model' import { Video } from './video.model'
export abstract class AbstractVideoList implements OnInit, OnDestroy { export abstract class AbstractVideoList implements OnInit, OnDestroy {
@ -23,8 +23,8 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy {
itemsPerPage: 10, itemsPerPage: 10,
totalItems: null totalItems: null
} }
sort: SortField = '-createdAt' sort: VideoSortField = '-createdAt'
defaultSort: SortField = '-createdAt' defaultSort: VideoSortField = '-createdAt'
syndicationItems = [] syndicationItems = []
loadOnInit = true loadOnInit = true
@ -154,7 +154,7 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy {
} }
protected loadRouteParams (routeParams: { [ key: string ]: any }) { protected loadRouteParams (routeParams: { [ key: string ]: any }) {
this.sort = routeParams['sort'] as SortField || this.defaultSort this.sort = routeParams['sort'] as VideoSortField || this.defaultSort
if (routeParams['page'] !== undefined) { if (routeParams['page'] !== undefined) {
this.pagination.currentPage = parseInt(routeParams['page'], 10) this.pagination.currentPage = parseInt(routeParams['page'], 10)

View File

@ -1,4 +1,4 @@
export type SortField = 'name' | '-name' export type VideoSortField = 'name' | '-name'
| 'duration' | '-duration' | 'duration' | '-duration'
| 'createdAt' | '-createdAt' | 'createdAt' | '-createdAt'
| 'views' | '-views' | 'views' | '-views'

View File

@ -16,7 +16,7 @@ import { ComponentPagination } from '../rest/component-pagination.model'
import { RestExtractor } from '../rest/rest-extractor.service' import { RestExtractor } from '../rest/rest-extractor.service'
import { RestService } from '../rest/rest.service' import { RestService } from '../rest/rest.service'
import { UserService } from '../users/user.service' import { UserService } from '../users/user.service'
import { SortField } from './sort-field.type' import { VideoSortField } from './sort-field.type'
import { VideoDetails } from './video-details.model' import { VideoDetails } from './video-details.model'
import { VideoEdit } from './video-edit.model' import { VideoEdit } from './video-edit.model'
import { Video } from './video.model' import { Video } from './video.model'
@ -86,7 +86,7 @@ export class VideoService {
.catch(this.restExtractor.handleError) .catch(this.restExtractor.handleError)
} }
getMyVideos (videoPagination: ComponentPagination, sort: SortField): Observable<{ videos: Video[], totalVideos: number}> { getMyVideos (videoPagination: ComponentPagination, sort: VideoSortField): Observable<{ videos: Video[], totalVideos: number}> {
const pagination = this.restService.componentPaginationToRestPagination(videoPagination) const pagination = this.restService.componentPaginationToRestPagination(videoPagination)
let params = new HttpParams() let params = new HttpParams()
@ -99,7 +99,7 @@ export class VideoService {
getVideos ( getVideos (
videoPagination: ComponentPagination, videoPagination: ComponentPagination,
sort: SortField, sort: VideoSortField,
filter?: VideoFilter filter?: VideoFilter
): Observable<{ videos: Video[], totalVideos: number}> { ): Observable<{ videos: Video[], totalVideos: number}> {
const pagination = this.restService.componentPaginationToRestPagination(videoPagination) const pagination = this.restService.componentPaginationToRestPagination(videoPagination)
@ -117,7 +117,7 @@ export class VideoService {
.catch((res) => this.restExtractor.handleError(res)) .catch((res) => this.restExtractor.handleError(res))
} }
buildBaseFeedUrls () { buildBaseFeedUrls (params: HttpParams) {
const feeds = [ const feeds = [
{ {
label: 'rss 2.0', label: 'rss 2.0',
@ -133,43 +133,34 @@ export class VideoService {
} }
] ]
return feeds if (params && params.keys().length !== 0) {
} for (const feed of feeds) {
feed.url += '?' + params.toString()
getVideoFeedUrls (filter?: VideoFilter) {
let params = this.restService.addRestGetParams(new HttpParams())
const feeds = this.buildBaseFeedUrls()
if (filter) params = params.set('filter', filter)
if (params.keys().length !== 0) {
for (let item of feeds) {
item.url += `?${params.toString()}`
} }
} }
return feeds return feeds
} }
getVideoFeedUrls (sort: VideoSortField, filter?: VideoFilter) {
let params = this.restService.addRestGetParams(new HttpParams(), undefined, sort)
if (filter) params = params.set('filter', filter)
return this.buildBaseFeedUrls(params)
}
getAccountFeedUrls (accountId: number) { getAccountFeedUrls (accountId: number) {
let params = this.restService.addRestGetParams(new HttpParams()) let params = this.restService.addRestGetParams(new HttpParams())
const feeds = this.buildBaseFeedUrls()
params = params.set('accountId', accountId.toString()) params = params.set('accountId', accountId.toString())
if (params.keys().length !== 0) { return this.buildBaseFeedUrls(params)
for (let item of feeds) {
item.url += `?${params.toString()}`
}
}
return feeds
} }
searchVideos ( searchVideos (
search: string, search: string,
videoPagination: ComponentPagination, videoPagination: ComponentPagination,
sort: SortField sort: VideoSortField
): Observable<{ videos: Video[], totalVideos: number}> { ): Observable<{ videos: Video[], totalVideos: number}> {
const url = VideoService.BASE_VIDEO_URL + 'search' const url = VideoService.BASE_VIDEO_URL + 'search'

View File

@ -14,7 +14,7 @@ import {
import { environment } from '../../../../environments/environment' import { environment } from '../../../../environments/environment'
import { RestExtractor, RestService } from '../../../shared/rest' import { RestExtractor, RestService } from '../../../shared/rest'
import { ComponentPagination } from '../../../shared/rest/component-pagination.model' import { ComponentPagination } from '../../../shared/rest/component-pagination.model'
import { SortField } from '../../../shared/video/sort-field.type' import { VideoSortField } from '../../../shared/video/sort-field.type'
import { VideoComment } from './video-comment.model' import { VideoComment } from './video-comment.model'
@Injectable() @Injectable()
@ -48,7 +48,7 @@ export class VideoCommentService {
getVideoCommentThreads ( getVideoCommentThreads (
videoId: number | string, videoId: number | string,
componentPagination: ComponentPagination, componentPagination: ComponentPagination,
sort: SortField sort: VideoSortField
): Observable<{ comments: VideoComment[], totalComments: number}> { ): Observable<{ comments: VideoComment[], totalComments: number}> {
const pagination = this.restService.componentPaginationToRestPagination(componentPagination) const pagination = this.restService.componentPaginationToRestPagination(componentPagination)

View File

@ -7,7 +7,7 @@ import { VideoCommentThreadTree } from '../../../../../../shared/models/videos/v
import { AuthService } from '../../../core/auth' import { AuthService } from '../../../core/auth'
import { ComponentPagination } from '../../../shared/rest/component-pagination.model' import { ComponentPagination } from '../../../shared/rest/component-pagination.model'
import { User } from '../../../shared/users' import { User } from '../../../shared/users'
import { SortField } from '../../../shared/video/sort-field.type' import { VideoSortField } from '../../../shared/video/sort-field.type'
import { VideoDetails } from '../../../shared/video/video-details.model' import { VideoDetails } from '../../../shared/video/video-details.model'
import { VideoComment } from './video-comment.model' import { VideoComment } from './video-comment.model'
import { VideoCommentService } from './video-comment.service' import { VideoCommentService } from './video-comment.service'
@ -23,7 +23,7 @@ export class VideoCommentsComponent implements OnInit, OnChanges, OnDestroy {
comments: VideoComment[] = [] comments: VideoComment[] = []
highlightedThread: VideoComment highlightedThread: VideoComment
sort: SortField = '-createdAt' sort: VideoSortField = '-createdAt'
componentPagination: ComponentPagination = { componentPagination: ComponentPagination = {
currentPage: 1, currentPage: 1,
itemsPerPage: 10, itemsPerPage: 10,

View File

@ -3,12 +3,10 @@ import { ActivatedRoute, Router } from '@angular/router'
import { immutableAssign } from '@app/shared/misc/utils' import { immutableAssign } from '@app/shared/misc/utils'
import { NotificationsService } from 'angular2-notifications' import { NotificationsService } from 'angular2-notifications'
import { AuthService } from '../../core/auth' import { AuthService } from '../../core/auth'
import { PopoverModule } from 'ngx-bootstrap/popover'
import { AbstractVideoList } from '../../shared/video/abstract-video-list' import { AbstractVideoList } from '../../shared/video/abstract-video-list'
import { SortField } from '../../shared/video/sort-field.type' import { VideoSortField } from '../../shared/video/sort-field.type'
import { VideoService } from '../../shared/video/video.service' import { VideoService } from '../../shared/video/video.service'
import { FeedFormat } from '../../../../../shared/models/feeds/feed-format.enum' import { VideoFilter } from '../../../../../shared/models/videos/video-query.type'
import * as url from 'url'
@Component({ @Component({
selector: 'my-videos-local', selector: 'my-videos-local',
@ -18,7 +16,8 @@ import * as url from 'url'
export class VideoLocalComponent extends AbstractVideoList implements OnInit, OnDestroy { export class VideoLocalComponent extends AbstractVideoList implements OnInit, OnDestroy {
titlePage = 'Local videos' titlePage = 'Local videos'
currentRoute = '/videos/local' currentRoute = '/videos/local'
sort = '-createdAt' as SortField sort = '-createdAt' as VideoSortField
filter: VideoFilter = 'local'
constructor (protected router: Router, constructor (protected router: Router,
protected route: ActivatedRoute, protected route: ActivatedRoute,
@ -41,10 +40,10 @@ export class VideoLocalComponent extends AbstractVideoList implements OnInit, On
getVideosObservable (page: number) { getVideosObservable (page: number) {
const newPagination = immutableAssign(this.pagination, { currentPage: page }) const newPagination = immutableAssign(this.pagination, { currentPage: page })
return this.videoService.getVideos(newPagination, this.sort, 'local') return this.videoService.getVideos(newPagination, this.sort, this.filter)
} }
generateSyndicationList () { generateSyndicationList () {
this.syndicationItems = this.videoService.getVideoFeedUrls('local') this.syndicationItems = this.videoService.getVideoFeedUrls(this.sort, this.filter)
} }
} }

View File

@ -4,10 +4,8 @@ import { immutableAssign } from '@app/shared/misc/utils'
import { NotificationsService } from 'angular2-notifications' import { NotificationsService } from 'angular2-notifications'
import { AuthService } from '../../core/auth' import { AuthService } from '../../core/auth'
import { AbstractVideoList } from '../../shared/video/abstract-video-list' import { AbstractVideoList } from '../../shared/video/abstract-video-list'
import { SortField } from '../../shared/video/sort-field.type' import { VideoSortField } from '../../shared/video/sort-field.type'
import { VideoService } from '../../shared/video/video.service' import { VideoService } from '../../shared/video/video.service'
import { FeedFormat } from '../../../../../shared/models/feeds/feed-format.enum'
import * as url from 'url'
@Component({ @Component({
selector: 'my-videos-recently-added', selector: 'my-videos-recently-added',
@ -17,7 +15,7 @@ import * as url from 'url'
export class VideoRecentlyAddedComponent extends AbstractVideoList implements OnInit, OnDestroy { export class VideoRecentlyAddedComponent extends AbstractVideoList implements OnInit, OnDestroy {
titlePage = 'Recently added' titlePage = 'Recently added'
currentRoute = '/videos/recently-added' currentRoute = '/videos/recently-added'
sort: SortField = '-createdAt' sort: VideoSortField = '-createdAt'
constructor (protected router: Router, constructor (protected router: Router,
protected route: ActivatedRoute, protected route: ActivatedRoute,
@ -44,6 +42,6 @@ export class VideoRecentlyAddedComponent extends AbstractVideoList implements On
} }
generateSyndicationList () { generateSyndicationList () {
this.syndicationItems = this.videoService.getVideoFeedUrls() this.syndicationItems = this.videoService.getVideoFeedUrls(this.sort)
} }
} }

View File

@ -4,7 +4,7 @@ import { immutableAssign } from '@app/shared/misc/utils'
import { NotificationsService } from 'angular2-notifications' import { NotificationsService } from 'angular2-notifications'
import { AuthService } from '../../core/auth' import { AuthService } from '../../core/auth'
import { AbstractVideoList } from '../../shared/video/abstract-video-list' import { AbstractVideoList } from '../../shared/video/abstract-video-list'
import { SortField } from '../../shared/video/sort-field.type' import { VideoSortField } from '../../shared/video/sort-field.type'
import { VideoService } from '../../shared/video/video.service' import { VideoService } from '../../shared/video/video.service'
@Component({ @Component({
@ -15,7 +15,7 @@ import { VideoService } from '../../shared/video/video.service'
export class VideoTrendingComponent extends AbstractVideoList implements OnInit, OnDestroy { export class VideoTrendingComponent extends AbstractVideoList implements OnInit, OnDestroy {
titlePage = 'Trending' titlePage = 'Trending'
currentRoute = '/videos/trending' currentRoute = '/videos/trending'
defaultSort: SortField = '-views' defaultSort: VideoSortField = '-views'
constructor (protected router: Router, constructor (protected router: Router,
protected route: ActivatedRoute, protected route: ActivatedRoute,
@ -41,6 +41,6 @@ export class VideoTrendingComponent extends AbstractVideoList implements OnInit,
} }
generateSyndicationList () { generateSyndicationList () {
this.syndicationItems = this.videoService.getVideoFeedUrls() this.syndicationItems = this.videoService.getVideoFeedUrls(this.sort)
} }
} }

View File

@ -161,7 +161,7 @@ export {
async function getUserVideos (req: express.Request, res: express.Response, next: express.NextFunction) { async function getUserVideos (req: express.Request, res: express.Response, next: express.NextFunction) {
const user = res.locals.oauth.token.User as UserModel const user = res.locals.oauth.token.User as UserModel
const resultList = await VideoModel.listUserVideosForApi(user.id ,req.query.start, req.query.count, req.query.sort) const resultList = await VideoModel.listAccountVideosForApi(user.Account.id ,req.query.start, req.query.count, req.query.sort)
return res.json(getFormattedObjects(resultList.data, resultList.total)) return res.json(getFormattedObjects(resultList.data, resultList.total))
} }

View File

@ -1,6 +1,12 @@
import * as express from 'express' import * as express from 'express'
import { CONFIG } from '../initializers' import { CONFIG } from '../initializers'
import { asyncMiddleware, feedsValidator } from '../middlewares' import {
asyncMiddleware,
feedsValidator,
setDefaultPagination,
setDefaultSort,
videosSortValidator
} from '../middlewares'
import { VideoModel } from '../models/video/video' import { VideoModel } from '../models/video/video'
import * as Feed from 'pfeed' import * as Feed from 'pfeed'
import { ResultList } from '../../shared/models' import { ResultList } from '../../shared/models'
@ -9,6 +15,8 @@ import { AccountModel } from '../models/account/account'
const feedsRouter = express.Router() const feedsRouter = express.Router()
feedsRouter.get('/feeds/videos.:format', feedsRouter.get('/feeds/videos.:format',
videosSortValidator,
setDefaultSort,
asyncMiddleware(feedsValidator), asyncMiddleware(feedsValidator),
asyncMiddleware(generateFeed) asyncMiddleware(generateFeed)
) )
@ -23,26 +31,25 @@ export {
async function generateFeed (req: express.Request, res: express.Response, next: express.NextFunction) { async function generateFeed (req: express.Request, res: express.Response, next: express.NextFunction) {
let feed = initFeed() let feed = initFeed()
let feedStart = 0 const paginationStart = 0
let feedCount = 10 const paginationCount = 20
let feedSort = '-createdAt'
let resultList: ResultList<VideoModel> let resultList: ResultList<VideoModel>
const account: AccountModel = res.locals.account const account: AccountModel = res.locals.account
if (account) { if (account) {
resultList = await VideoModel.listUserVideosForApi( resultList = await VideoModel.listAccountVideosForApi(
account.id, account.id,
feedStart, paginationStart,
feedCount, paginationCount,
feedSort, req.query.sort,
true true
) )
} else { } else {
resultList = await VideoModel.listForApi( resultList = await VideoModel.listForApi(
feedStart, paginationStart,
feedCount, paginationCount,
feedSort, req.query.sort,
req.query.filter, req.query.filter,
true true
) )
@ -100,7 +107,7 @@ function initFeed () {
rss: `${webserverUrl}/feeds/videos.xml` rss: `${webserverUrl}/feeds/videos.xml`
}, },
author: { author: {
name: 'instance admin of ' + CONFIG.INSTANCE.NAME, name: 'Instance admin of ' + CONFIG.INSTANCE.NAME,
email: CONFIG.ADMIN.EMAIL, email: CONFIG.ADMIN.EMAIL,
link: `${webserverUrl}/about` link: `${webserverUrl}/about`
} }

View File

@ -640,7 +640,7 @@ export class VideoModel extends Model<VideoModel> {
}) })
} }
static listUserVideosForApi (userId: number, start: number, count: number, sort: string, withFiles = false) { static listAccountVideosForApi (accountId: number, start: number, count: number, sort: string, withFiles = false) {
const query: IFindOptions<VideoModel> = { const query: IFindOptions<VideoModel> = {
offset: start, offset: start,
limit: count, limit: count,
@ -653,7 +653,7 @@ export class VideoModel extends Model<VideoModel> {
{ {
model: AccountModel, model: AccountModel,
where: { where: {
userId id: accountId
}, },
required: true required: true
} }