Add ability to sort videos list
This commit is contained in:
parent
479f229198
commit
a877d5acc5
11 changed files with 173 additions and 9 deletions
|
@ -15,7 +15,9 @@ const oAuth2 = middlewares.oauth2
|
||||||
const pagination = middlewares.pagination
|
const pagination = middlewares.pagination
|
||||||
const reqValidator = middlewares.reqValidators
|
const reqValidator = middlewares.reqValidators
|
||||||
const reqValidatorPagination = reqValidator.pagination
|
const reqValidatorPagination = reqValidator.pagination
|
||||||
|
const reqValidatorSort = reqValidator.sort
|
||||||
const reqValidatorVideos = reqValidator.videos
|
const reqValidatorVideos = reqValidator.videos
|
||||||
|
const sort = middlewares.sort
|
||||||
const utils = require('../../../helpers/utils')
|
const utils = require('../../../helpers/utils')
|
||||||
const Videos = require('../../../models/videos') // model
|
const Videos = require('../../../models/videos') // model
|
||||||
const videos = require('../../../lib/videos')
|
const videos = require('../../../lib/videos')
|
||||||
|
@ -47,6 +49,8 @@ const thumbnailsDir = path.join(__dirname, '..', '..', '..', '..', config.get('s
|
||||||
|
|
||||||
router.get('/',
|
router.get('/',
|
||||||
reqValidatorPagination.pagination,
|
reqValidatorPagination.pagination,
|
||||||
|
reqValidatorSort.videosSort,
|
||||||
|
sort.setVideosSort,
|
||||||
pagination.setPagination,
|
pagination.setPagination,
|
||||||
listVideos
|
listVideos
|
||||||
)
|
)
|
||||||
|
@ -68,6 +72,8 @@ router.delete('/:id',
|
||||||
router.get('/search/:name',
|
router.get('/search/:name',
|
||||||
reqValidatorVideos.videosSearch,
|
reqValidatorVideos.videosSearch,
|
||||||
reqValidatorPagination.pagination,
|
reqValidatorPagination.pagination,
|
||||||
|
reqValidatorSort.videosSort,
|
||||||
|
sort.setVideosSort,
|
||||||
pagination.setPagination,
|
pagination.setPagination,
|
||||||
searchVideos
|
searchVideos
|
||||||
)
|
)
|
||||||
|
@ -173,7 +179,7 @@ function getVideos (req, res, next) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function listVideos (req, res, next) {
|
function listVideos (req, res, next) {
|
||||||
Videos.list(req.query.start, req.query.count, function (err, videosList) {
|
Videos.list(req.query.start, req.query.count, req.query.sort, function (err, videosList) {
|
||||||
if (err) return next(err)
|
if (err) return next(err)
|
||||||
|
|
||||||
res.json(getFormatedVideos(videosList))
|
res.json(getFormatedVideos(videosList))
|
||||||
|
@ -231,7 +237,7 @@ function removeVideo (req, res, next) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function searchVideos (req, res, next) {
|
function searchVideos (req, res, next) {
|
||||||
Videos.search(req.params.name, req.query.start, req.query.count, function (err, videosList) {
|
Videos.search(req.params.name, req.query.start, req.query.count, req.query.sort, function (err, videosList) {
|
||||||
if (err) return next(err)
|
if (err) return next(err)
|
||||||
|
|
||||||
res.json(getFormatedVideos(videosList))
|
res.json(getFormatedVideos(videosList))
|
||||||
|
|
|
@ -26,6 +26,11 @@ const PODS_SCORE = {
|
||||||
// Number of retries we make for the make retry requests (to friends...)
|
// Number of retries we make for the make retry requests (to friends...)
|
||||||
let REQUEST_RETRIES = 10
|
let REQUEST_RETRIES = 10
|
||||||
|
|
||||||
|
// Sortable columns per schema
|
||||||
|
const SORTABLE_COLUMNS = {
|
||||||
|
VIDEOS: [ 'name', '-name', 'duration', '-duration', 'createdDate', '-createdDate' ]
|
||||||
|
}
|
||||||
|
|
||||||
// Videos thumbnail size
|
// Videos thumbnail size
|
||||||
const THUMBNAILS_SIZE = '200x110'
|
const THUMBNAILS_SIZE = '200x110'
|
||||||
|
|
||||||
|
@ -51,6 +56,7 @@ module.exports = {
|
||||||
PAGINATION_COUNT_DEFAULT: PAGINATION_COUNT_DEFAULT,
|
PAGINATION_COUNT_DEFAULT: PAGINATION_COUNT_DEFAULT,
|
||||||
PODS_SCORE: PODS_SCORE,
|
PODS_SCORE: PODS_SCORE,
|
||||||
REQUEST_RETRIES: REQUEST_RETRIES,
|
REQUEST_RETRIES: REQUEST_RETRIES,
|
||||||
|
SORTABLE_COLUMNS: SORTABLE_COLUMNS,
|
||||||
THUMBNAILS_SIZE: THUMBNAILS_SIZE,
|
THUMBNAILS_SIZE: THUMBNAILS_SIZE,
|
||||||
THUMBNAILS_STATIC_PATH: THUMBNAILS_STATIC_PATH
|
THUMBNAILS_STATIC_PATH: THUMBNAILS_STATIC_PATH
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,12 +3,14 @@
|
||||||
const oauth2 = require('./oauth2')
|
const oauth2 = require('./oauth2')
|
||||||
const pagination = require('./pagination')
|
const pagination = require('./pagination')
|
||||||
const reqValidatorsMiddleware = require('./reqValidators')
|
const reqValidatorsMiddleware = require('./reqValidators')
|
||||||
|
const sort = require('./sort')
|
||||||
const secureMiddleware = require('./secure')
|
const secureMiddleware = require('./secure')
|
||||||
|
|
||||||
const middlewares = {
|
const middlewares = {
|
||||||
oauth2: oauth2,
|
oauth2: oauth2,
|
||||||
pagination: pagination,
|
pagination: pagination,
|
||||||
reqValidators: reqValidatorsMiddleware,
|
reqValidators: reqValidatorsMiddleware,
|
||||||
|
sort: sort,
|
||||||
secure: secureMiddleware
|
secure: secureMiddleware
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,12 +3,14 @@
|
||||||
const paginationReqValidators = require('./pagination')
|
const paginationReqValidators = require('./pagination')
|
||||||
const podsReqValidators = require('./pods')
|
const podsReqValidators = require('./pods')
|
||||||
const remoteReqValidators = require('./remote')
|
const remoteReqValidators = require('./remote')
|
||||||
|
const sortReqValidators = require('./sort')
|
||||||
const videosReqValidators = require('./videos')
|
const videosReqValidators = require('./videos')
|
||||||
|
|
||||||
const reqValidators = {
|
const reqValidators = {
|
||||||
pagination: paginationReqValidators,
|
pagination: paginationReqValidators,
|
||||||
pods: podsReqValidators,
|
pods: podsReqValidators,
|
||||||
remote: remoteReqValidators,
|
remote: remoteReqValidators,
|
||||||
|
sort: sortReqValidators,
|
||||||
videos: videosReqValidators
|
videos: videosReqValidators
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,10 +8,10 @@ const reqValidatorsPagination = {
|
||||||
}
|
}
|
||||||
|
|
||||||
function pagination (req, res, next) {
|
function pagination (req, res, next) {
|
||||||
req.checkParams('start', 'Should have a number start').optional().isInt()
|
req.checkQuery('start', 'Should have a number start').optional().isInt()
|
||||||
req.checkParams('count', 'Should have a number count').optional().isInt()
|
req.checkQuery('count', 'Should have a number count').optional().isInt()
|
||||||
|
|
||||||
logger.debug('Checking pagination parameters', { parameters: req.params })
|
logger.debug('Checking pagination parameters', { parameters: req.query })
|
||||||
|
|
||||||
checkErrors(req, res, next)
|
checkErrors(req, res, next)
|
||||||
}
|
}
|
||||||
|
|
23
server/middlewares/reqValidators/sort.js
Normal file
23
server/middlewares/reqValidators/sort.js
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const checkErrors = require('./utils').checkErrors
|
||||||
|
const constants = require('../../initializers/constants')
|
||||||
|
const logger = require('../../helpers/logger')
|
||||||
|
|
||||||
|
const reqValidatorsSort = {
|
||||||
|
videosSort: videosSort
|
||||||
|
}
|
||||||
|
|
||||||
|
function videosSort (req, res, next) {
|
||||||
|
const sortableColumns = constants.SORTABLE_COLUMNS.VIDEOS
|
||||||
|
|
||||||
|
req.checkQuery('sort', 'Should have correct sortable column').optional().isIn(sortableColumns)
|
||||||
|
|
||||||
|
logger.debug('Checking sort parameters', { parameters: req.query })
|
||||||
|
|
||||||
|
checkErrors(req, res, next)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
module.exports = reqValidatorsSort
|
15
server/middlewares/sort.js
Normal file
15
server/middlewares/sort.js
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const sortMiddleware = {
|
||||||
|
setVideosSort: setVideosSort
|
||||||
|
}
|
||||||
|
|
||||||
|
function setVideosSort (req, res, next) {
|
||||||
|
if (!req.query.sort) req.query.sort = '-createdDate'
|
||||||
|
|
||||||
|
return next()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
module.exports = sortMiddleware
|
|
@ -80,8 +80,9 @@ function get (id, callback) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function list (start, count, callback) {
|
function list (start, count, sort, callback) {
|
||||||
VideosDB.find({}).skip(start).limit(start + count).exec(function (err, videosList) {
|
VideosDB.find({}).skip(start).limit(start + count).sort(sort)
|
||||||
|
.exec(function (err, videosList) {
|
||||||
if (err) {
|
if (err) {
|
||||||
logger.error('Cannot get the list of the videos.')
|
logger.error('Cannot get the list of the videos.')
|
||||||
return callback(err)
|
return callback(err)
|
||||||
|
@ -129,8 +130,8 @@ function removeByIds (ids, callback) {
|
||||||
VideosDB.remove({ _id: { $in: ids } }, callback)
|
VideosDB.remove({ _id: { $in: ids } }, callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
function search (name, start, count, callback) {
|
function search (name, start, count, sort, callback) {
|
||||||
VideosDB.find({ name: new RegExp(name) }).skip(start).limit(start + count)
|
VideosDB.find({ name: new RegExp(name) }).skip(start).limit(start + count).sort(sort)
|
||||||
.exec(function (err, videos) {
|
.exec(function (err, videos) {
|
||||||
if (err) {
|
if (err) {
|
||||||
logger.error('Cannot search the videos.')
|
logger.error('Cannot search the videos.')
|
||||||
|
|
|
@ -130,6 +130,32 @@ describe('Test parameters validator', function () {
|
||||||
describe('Of the videos API', function () {
|
describe('Of the videos API', function () {
|
||||||
const path = '/api/v1/videos/'
|
const path = '/api/v1/videos/'
|
||||||
|
|
||||||
|
describe('When listing a video', function () {
|
||||||
|
it('Should fail with a bad start pagination', function (done) {
|
||||||
|
request(server.url)
|
||||||
|
.get(path)
|
||||||
|
.query({ start: 'hello' })
|
||||||
|
.set('Accept', 'application/json')
|
||||||
|
.expect(400, done)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should fail with a bad count pagination', function (done) {
|
||||||
|
request(server.url)
|
||||||
|
.get(path)
|
||||||
|
.query({ count: 'hello' })
|
||||||
|
.set('Accept', 'application/json')
|
||||||
|
.expect(400, done)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should fail with an incorrect sort', function (done) {
|
||||||
|
request(server.url)
|
||||||
|
.get(path)
|
||||||
|
.query({ sort: 'hello' })
|
||||||
|
.set('Accept', 'application/json')
|
||||||
|
.expect(400, done)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('When searching a video', function () {
|
describe('When searching a video', function () {
|
||||||
it('Should fail with nothing', function (done) {
|
it('Should fail with nothing', function (done) {
|
||||||
request(server.url)
|
request(server.url)
|
||||||
|
@ -137,6 +163,30 @@ describe('Test parameters validator', function () {
|
||||||
.set('Accept', 'application/json')
|
.set('Accept', 'application/json')
|
||||||
.expect(400, done)
|
.expect(400, done)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('Should fail with a bad start pagination', function (done) {
|
||||||
|
request(server.url)
|
||||||
|
.get(pathUtils.join(path, 'search', 'test'))
|
||||||
|
.query({ start: 'hello' })
|
||||||
|
.set('Accept', 'application/json')
|
||||||
|
.expect(400, done)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should fail with a bad count pagination', function (done) {
|
||||||
|
request(server.url)
|
||||||
|
.get(pathUtils.join(path, 'search', 'test'))
|
||||||
|
.query({ count: 'hello' })
|
||||||
|
.set('Accept', 'application/json')
|
||||||
|
.expect(400, done)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should fail with an incorrect sort', function (done) {
|
||||||
|
request(server.url)
|
||||||
|
.get(pathUtils.join(path, 'search', 'test'))
|
||||||
|
.query({ sort: 'hello' })
|
||||||
|
.set('Accept', 'application/json')
|
||||||
|
.expect(400, done)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('When adding a video', function () {
|
describe('When adding a video', function () {
|
||||||
|
|
|
@ -314,6 +314,39 @@ describe('Test a single pod', function () {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('Should list and sort by name in descending order', function (done) {
|
||||||
|
utils.getVideosListSort(server.url, '-name', function (err, res) {
|
||||||
|
if (err) throw err
|
||||||
|
|
||||||
|
const videos = res.body
|
||||||
|
expect(videos.length).to.equal(6)
|
||||||
|
expect(videos[5].name === 'video_short.mp4 name')
|
||||||
|
expect(videos[4].name === 'video_short.ogv name')
|
||||||
|
expect(videos[3].name === 'video_short.webm name')
|
||||||
|
expect(videos[2].name === 'video_short1.webm name')
|
||||||
|
expect(videos[1].name === 'video_short2.webm name')
|
||||||
|
expect(videos[0].name === 'video_short3.webm name')
|
||||||
|
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Should search and sort by name in ascending order', function (done) {
|
||||||
|
utils.searchVideoWithSort(server.url, 'webm', 'name', function (err, res) {
|
||||||
|
if (err) throw err
|
||||||
|
|
||||||
|
const videos = res.body
|
||||||
|
expect(videos.length).to.equal(4)
|
||||||
|
|
||||||
|
expect(videos[0].name === 'video_short.webm name')
|
||||||
|
expect(videos[1].name === 'video_short1.webm name')
|
||||||
|
expect(videos[2].name === 'video_short2.webm name')
|
||||||
|
expect(videos[3].name === 'video_short3.webm name')
|
||||||
|
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
after(function (done) {
|
after(function (done) {
|
||||||
process.kill(-server.app.pid)
|
process.kill(-server.app.pid)
|
||||||
process.kill(-webtorrent.app.pid)
|
process.kill(-webtorrent.app.pid)
|
||||||
|
|
|
@ -14,6 +14,7 @@ const testUtils = {
|
||||||
getVideo: getVideo,
|
getVideo: getVideo,
|
||||||
getVideosList: getVideosList,
|
getVideosList: getVideosList,
|
||||||
getVideosListPagination: getVideosListPagination,
|
getVideosListPagination: getVideosListPagination,
|
||||||
|
getVideosListSort: getVideosListSort,
|
||||||
login: login,
|
login: login,
|
||||||
loginAndGetAccessToken: loginAndGetAccessToken,
|
loginAndGetAccessToken: loginAndGetAccessToken,
|
||||||
makeFriends: makeFriends,
|
makeFriends: makeFriends,
|
||||||
|
@ -23,6 +24,7 @@ const testUtils = {
|
||||||
runServer: runServer,
|
runServer: runServer,
|
||||||
searchVideo: searchVideo,
|
searchVideo: searchVideo,
|
||||||
searchVideoWithPagination: searchVideoWithPagination,
|
searchVideoWithPagination: searchVideoWithPagination,
|
||||||
|
searchVideoWithSort: searchVideoWithSort,
|
||||||
testImage: testImage,
|
testImage: testImage,
|
||||||
uploadVideo: uploadVideo
|
uploadVideo: uploadVideo
|
||||||
}
|
}
|
||||||
|
@ -89,6 +91,18 @@ function getVideosListPagination (url, start, count, end) {
|
||||||
.end(end)
|
.end(end)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getVideosListSort (url, sort, end) {
|
||||||
|
const path = '/api/v1/videos'
|
||||||
|
|
||||||
|
request(url)
|
||||||
|
.get(path)
|
||||||
|
.query({ sort: sort })
|
||||||
|
.set('Accept', 'application/json')
|
||||||
|
.expect(200)
|
||||||
|
.expect('Content-Type', /json/)
|
||||||
|
.end(end)
|
||||||
|
}
|
||||||
|
|
||||||
function login (url, client, user, expectedStatus, end) {
|
function login (url, client, user, expectedStatus, end) {
|
||||||
if (!end) {
|
if (!end) {
|
||||||
end = expectedStatus
|
end = expectedStatus
|
||||||
|
@ -300,6 +314,18 @@ function searchVideoWithPagination (url, search, start, count, end) {
|
||||||
.end(end)
|
.end(end)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function searchVideoWithSort (url, search, sort, end) {
|
||||||
|
const path = '/api/v1/videos'
|
||||||
|
|
||||||
|
request(url)
|
||||||
|
.get(path + '/search/' + search)
|
||||||
|
.query({ sort: sort })
|
||||||
|
.set('Accept', 'application/json')
|
||||||
|
.expect(200)
|
||||||
|
.expect('Content-Type', /json/)
|
||||||
|
.end(end)
|
||||||
|
}
|
||||||
|
|
||||||
function testImage (url, videoName, imagePath, callback) {
|
function testImage (url, videoName, imagePath, callback) {
|
||||||
request(url)
|
request(url)
|
||||||
.get(imagePath)
|
.get(imagePath)
|
||||||
|
|
Loading…
Reference in a new issue