Handle sort in rss
This commit is contained in:
parent
cc1561f9f7
commit
7b87d2d514
|
@ -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)
|
||||||
|
|
|
@ -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'
|
||||||
|
|
|
@ -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 {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
if (params && params.keys().length !== 0) {
|
||||||
|
for (const feed of feeds) {
|
||||||
|
feed.url += '?' + params.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return feeds
|
return feeds
|
||||||
}
|
}
|
||||||
|
|
||||||
getVideoFeedUrls (filter?: VideoFilter) {
|
getVideoFeedUrls (sort: VideoSortField, filter?: VideoFilter) {
|
||||||
let params = this.restService.addRestGetParams(new HttpParams())
|
let params = this.restService.addRestGetParams(new HttpParams(), undefined, sort)
|
||||||
const feeds = this.buildBaseFeedUrls()
|
|
||||||
|
|
||||||
if (filter) params = params.set('filter', filter)
|
if (filter) params = params.set('filter', filter)
|
||||||
|
|
||||||
if (params.keys().length !== 0) {
|
return this.buildBaseFeedUrls(params)
|
||||||
for (let item of feeds) {
|
|
||||||
item.url += `?${params.toString()}`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return feeds
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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'
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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))
|
||||||
}
|
}
|
||||||
|
|
|
@ -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`
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue