aboutsummaryrefslogtreecommitdiffhomepage
path: root/server
diff options
context:
space:
mode:
authorRigel Kent <sendmemail@rigelk.eu>2019-12-26 11:52:46 +0100
committerRigel Kent <sendmemail@rigelk.eu>2019-12-26 11:52:52 +0100
commitc06af5012ecc925ca924e6e20db3a1d909b1148e (patch)
tree88a3595bfd0a68e8f5314737a22f9516d9790c9b /server
parentdef2a70b7e5ee807d7b532df8c9d33d17d24ccbb (diff)
downloadPeerTube-c06af5012ecc925ca924e6e20db3a1d909b1148e.tar.gz
PeerTube-c06af5012ecc925ca924e6e20db3a1d909b1148e.tar.zst
PeerTube-c06af5012ecc925ca924e6e20db3a1d909b1148e.zip
Add playlist search option and search input for add-to-video-playlist dropdown
fixes #2138
Diffstat (limited to 'server')
-rw-r--r--server/controllers/api/accounts.ts7
-rw-r--r--server/middlewares/validators/videos/video-playlists.ts13
-rw-r--r--server/models/video/video-playlist.ts31
3 files changed, 45 insertions, 6 deletions
diff --git a/server/controllers/api/accounts.ts b/server/controllers/api/accounts.ts
index 5a1d652f2..c49da3c0a 100644
--- a/server/controllers/api/accounts.ts
+++ b/server/controllers/api/accounts.ts
@@ -27,7 +27,10 @@ import { VideoChannelModel } from '../../models/video/video-channel'
27import { JobQueue } from '../../lib/job-queue' 27import { JobQueue } from '../../lib/job-queue'
28import { logger } from '../../helpers/logger' 28import { logger } from '../../helpers/logger'
29import { VideoPlaylistModel } from '../../models/video/video-playlist' 29import { VideoPlaylistModel } from '../../models/video/video-playlist'
30import { commonVideoPlaylistFiltersValidator } from '../../middlewares/validators/videos/video-playlists' 30import {
31 commonVideoPlaylistFiltersValidator,
32 videoPlaylistsSearchValidator
33} from '../../middlewares/validators/videos/video-playlists'
31 34
32const accountsRouter = express.Router() 35const accountsRouter = express.Router()
33 36
@@ -72,6 +75,7 @@ accountsRouter.get('/:accountName/video-playlists',
72 setDefaultSort, 75 setDefaultSort,
73 setDefaultPagination, 76 setDefaultPagination,
74 commonVideoPlaylistFiltersValidator, 77 commonVideoPlaylistFiltersValidator,
78 videoPlaylistsSearchValidator,
75 asyncMiddleware(listAccountPlaylists) 79 asyncMiddleware(listAccountPlaylists)
76) 80)
77 81
@@ -135,6 +139,7 @@ async function listAccountPlaylists (req: express.Request, res: express.Response
135 } 139 }
136 140
137 const resultList = await VideoPlaylistModel.listForApi({ 141 const resultList = await VideoPlaylistModel.listForApi({
142 search: req.query.search,
138 followerActorId: serverActor.id, 143 followerActorId: serverActor.id,
139 start: req.query.start, 144 start: req.query.start,
140 count: req.query.count, 145 count: req.query.count,
diff --git a/server/middlewares/validators/videos/video-playlists.ts b/server/middlewares/validators/videos/video-playlists.ts
index 27ee62b1f..1d67e8666 100644
--- a/server/middlewares/validators/videos/video-playlists.ts
+++ b/server/middlewares/validators/videos/video-playlists.ts
@@ -166,6 +166,18 @@ const videoPlaylistsGetValidator = (fetchType: VideoPlaylistFetchType) => {
166 ] 166 ]
167} 167}
168 168
169const videoPlaylistsSearchValidator = [
170 query('search').optional().not().isEmpty().withMessage('Should have a valid search'),
171
172 (req: express.Request, res: express.Response, next: express.NextFunction) => {
173 logger.debug('Checking videoPlaylists search query', { parameters: req.query })
174
175 if (areValidationErrors(req, res)) return
176
177 return next()
178 }
179]
180
169const videoPlaylistsAddVideoValidator = [ 181const videoPlaylistsAddVideoValidator = [
170 param('playlistId') 182 param('playlistId')
171 .custom(isIdOrUUIDValid).withMessage('Should have a valid playlist id/uuid'), 183 .custom(isIdOrUUIDValid).withMessage('Should have a valid playlist id/uuid'),
@@ -354,6 +366,7 @@ export {
354 videoPlaylistsUpdateValidator, 366 videoPlaylistsUpdateValidator,
355 videoPlaylistsDeleteValidator, 367 videoPlaylistsDeleteValidator,
356 videoPlaylistsGetValidator, 368 videoPlaylistsGetValidator,
369 videoPlaylistsSearchValidator,
357 370
358 videoPlaylistsAddVideoValidator, 371 videoPlaylistsAddVideoValidator,
359 videoPlaylistsUpdateOrRemoveVideoValidator, 372 videoPlaylistsUpdateOrRemoveVideoValidator,
diff --git a/server/models/video/video-playlist.ts b/server/models/video/video-playlist.ts
index 278d80ac0..ef87a7ee9 100644
--- a/server/models/video/video-playlist.ts
+++ b/server/models/video/video-playlist.ts
@@ -13,10 +13,11 @@ import {
13 Model, 13 Model,
14 Scopes, 14 Scopes,
15 Table, 15 Table,
16 UpdatedAt 16 UpdatedAt,
17 Sequelize
17} from 'sequelize-typescript' 18} from 'sequelize-typescript'
18import { VideoPlaylistPrivacy } from '../../../shared/models/videos/playlist/video-playlist-privacy.model' 19import { VideoPlaylistPrivacy } from '../../../shared/models/videos/playlist/video-playlist-privacy.model'
19import { buildServerIdsFollowedBy, buildWhereIdOrUUID, getSort, isOutdated, throwIfNotValid } from '../utils' 20import { buildServerIdsFollowedBy, buildWhereIdOrUUID, getSort, isOutdated, throwIfNotValid, createSimilarityAttribute } from '../utils'
20import { 21import {
21 isVideoPlaylistDescriptionValid, 22 isVideoPlaylistDescriptionValid,
22 isVideoPlaylistNameValid, 23 isVideoPlaylistNameValid,
@@ -67,7 +68,8 @@ type AvailableForListOptions = {
67 type?: VideoPlaylistType 68 type?: VideoPlaylistType
68 accountId?: number 69 accountId?: number
69 videoChannelId?: number 70 videoChannelId?: number
70 privateAndUnlisted?: boolean 71 privateAndUnlisted?: boolean,
72 search?: string
71} 73}
72 74
73@Scopes(() => ({ 75@Scopes(() => ({
@@ -163,6 +165,23 @@ type AvailableForListOptions = {
163 }) 165 })
164 } 166 }
165 167
168 if (options.search) {
169 const escapedSearch = VideoPlaylistModel.sequelize.escape(options.search)
170 const escapedLikeSearch = VideoPlaylistModel.sequelize.escape('%' + options.search + '%')
171 whereAnd.push({
172 id: {
173 [ Op.in ]: Sequelize.literal(
174 '(' +
175 'SELECT "videoPlaylist"."id" FROM "videoPlaylist" ' +
176 'WHERE ' +
177 'lower(immutable_unaccent("videoPlaylist"."name")) % lower(immutable_unaccent(' + escapedSearch + ')) OR ' +
178 'lower(immutable_unaccent("videoPlaylist"."name")) LIKE lower(immutable_unaccent(' + escapedLikeSearch + '))' +
179 ')'
180 )
181 }
182 })
183 }
184
166 const where = { 185 const where = {
167 [Op.and]: whereAnd 186 [Op.and]: whereAnd
168 } 187 }
@@ -291,7 +310,8 @@ export class VideoPlaylistModel extends Model<VideoPlaylistModel> {
291 type?: VideoPlaylistType, 310 type?: VideoPlaylistType,
292 accountId?: number, 311 accountId?: number,
293 videoChannelId?: number, 312 videoChannelId?: number,
294 privateAndUnlisted?: boolean 313 privateAndUnlisted?: boolean,
314 search?: string
295 }) { 315 }) {
296 const query = { 316 const query = {
297 offset: options.start, 317 offset: options.start,
@@ -308,7 +328,8 @@ export class VideoPlaylistModel extends Model<VideoPlaylistModel> {
308 followerActorId: options.followerActorId, 328 followerActorId: options.followerActorId,
309 accountId: options.accountId, 329 accountId: options.accountId,
310 videoChannelId: options.videoChannelId, 330 videoChannelId: options.videoChannelId,
311 privateAndUnlisted: options.privateAndUnlisted 331 privateAndUnlisted: options.privateAndUnlisted,
332 search: options.search
312 } as AvailableForListOptions 333 } as AvailableForListOptions
313 ] 334 ]
314 }, 335 },