Add ability to filter by host

This commit is contained in:
Chocobozzz 2021-07-28 11:22:42 +02:00
parent 4543d255b6
commit e5a2e7a442
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
10 changed files with 85 additions and 6 deletions

@ -1 +1 @@
Subproject commit cffa06fd28bbfb03980bc7d151cfd93130c3daaf Subproject commit 28be9d1d3ee92db7c9fd84c82e4ea20900eab0f5

View File

@ -1,6 +1,7 @@
export interface SearchUrl { export interface SearchUrl {
search?: string search?: string
nsfw?: string nsfw?: string
host?: string
publishedDateRange?: string publishedDateRange?: string
durationRange?: string durationRange?: string
categoryOneOf?: number[] categoryOneOf?: number[]

View File

@ -1,6 +1,8 @@
@import "_variables"; @import "_variables";
@import "./progress"; @import "./progress";
$border-input-color: #C6C6C6;
* { * {
box-sizing: border-box; box-sizing: border-box;
} }
@ -94,7 +96,7 @@ body {
select { select {
padding: 0 35px 0 12px; padding: 0 35px 0 12px;
position: relative; position: relative;
border: 1px solid #C6C6C6; border: 1px solid $border-input-color;
background: transparent none; background: transparent none;
appearance: none; appearance: none;
cursor: pointer; cursor: pointer;
@ -117,6 +119,15 @@ body {
} }
} }
.classic-input-text {
display: block;
min-height: 30px;
width: 100%;
border: 1px solid $border-input-color;
padding: 0 35px 0 12px;
outline: 0;
}
.results { .results {
.root-result { .root-result {
display: flex; display: flex;

View File

@ -1,11 +1,10 @@
import axios from 'axios' import axios from 'axios'
import { VideoPlaylistsSearchQuery } from '../../../PeerTube/shared/models' import { ResultList, VideoPlaylistsSearchQuery } from '../../../PeerTube/shared/models'
import { ResultList } from '../../../PeerTube/shared/models/result-list.model'
import { VideoChannelsSearchQuery } from '../../../PeerTube/shared/models/search/video-channels-search-query.model' import { VideoChannelsSearchQuery } from '../../../PeerTube/shared/models/search/video-channels-search-query.model'
import { VideosSearchQuery } from '../../../PeerTube/shared/models/search/videos-search-query.model' import { VideosSearchQuery } from '../../../PeerTube/shared/models/search/videos-search-query.model'
import { EnhancedVideoChannel } from '../../../server/types/channel.model' import { EnhancedVideoChannel } from '../../../server/types/channel.model'
import { EnhancedVideo } from '../../../server/types/video.model'
import { EnhancedPlaylist } from '../../../server/types/playlist.model' import { EnhancedPlaylist } from '../../../server/types/playlist.model'
import { EnhancedVideo } from '../../../server/types/video.model'
import { buildApiUrl } from './utils' import { buildApiUrl } from './utils'
const baseVideosPath = '/api/v1/search/videos' const baseVideosPath = '/api/v1/search/videos'

View File

@ -160,6 +160,12 @@
</div> </div>
</div> </div>
<div class="form-group">
<label v-translate for="host">Host</label>
<input type="text" id="host" name="host" v-model="formHost" class="classic-input-text" />
</div>
<div class="form-group"> <div class="form-group">
<label v-translate for="tagsAllOf">All of these tags</label> <label v-translate for="tagsAllOf">All of these tags</label>
<button v-translate class="reset-button" v-on:click="resetField('tagsAllOf')" v-if="formTagsAllOf.length !== 0"> <button v-translate class="reset-button" v-on:click="resetField('tagsAllOf')" v-if="formTagsAllOf.length !== 0">
@ -500,6 +506,7 @@
formSort: '-match', formSort: '-match',
formNSFW: undefined, formNSFW: undefined,
formHost: '',
formPublishedDateRange: undefined, formPublishedDateRange: undefined,
formDurationRange: undefined, formDurationRange: undefined,
formCategoryOneOf: undefined, formCategoryOneOf: undefined,
@ -785,6 +792,7 @@
search: this.formSearch, search: this.formSearch,
sort: this.formSort, sort: this.formSort,
nsfw: this.formNSFW, nsfw: this.formNSFW,
host: this.formHost,
isLive: this.formIsLive, isLive: this.formIsLive,
publishedDateRange: this.formPublishedDateRange, publishedDateRange: this.formPublishedDateRange,
durationRange: this.formDurationRange, durationRange: this.formDurationRange,
@ -835,6 +843,9 @@
if (query.isLive) this.formIsLive = query.isLive if (query.isLive) this.formIsLive = query.isLive
else this.formIsLive = undefined else this.formIsLive = undefined
if (query.host) this.formHost = query.host
else this.formHost = ''
if (query.page && this.currentPage !== query.page) { if (query.page && this.currentPage !== query.page) {
this.currentPage = parseInt(query.page + '') this.currentPage = parseInt(query.page + '')
} else { } else {
@ -871,6 +882,8 @@
isLive: this.formIsLive !== undefined ? this.formIsLive : undefined, isLive: this.formIsLive !== undefined ? this.formIsLive : undefined,
host: this.formHost || undefined,
start, start,
count, count,
sort: this.formSort sort: this.formSort
@ -887,6 +900,7 @@
return { return {
search: this.formSearch, search: this.formSearch,
host: this.formHost || undefined,
start, start,
sort, sort,
count count
@ -903,6 +917,7 @@
return { return {
search: this.formSearch, search: this.formSearch,
host: this.formHost || undefined,
start, start,
sort, sort,
count count
@ -1011,6 +1026,7 @@
else if (field === 'isLive') this.formIsLive = undefined else if (field === 'isLive') this.formIsLive = undefined
else if (field === 'tagsAllOf') this.formTagsAllOf = [] else if (field === 'tagsAllOf') this.formTagsAllOf = []
else if (field === 'tagsOneOf') this.formTagsOneOf = [] else if (field === 'tagsOneOf') this.formTagsOneOf = []
else if (field === 'host') this.formHost = ''
}, },
simpleFormReset (searchDone = true) { simpleFormReset (searchDone = true) {
@ -1022,6 +1038,7 @@
let count = 0 let count = 0
if (this.formNSFW) count++ if (this.formNSFW) count++
if (this.formHost) count++
if (this.formPublishedDateRange) count++ if (this.formPublishedDateRange) count++
if (this.formDurationRange) count++ if (this.formDurationRange) count++
if (this.formCategoryOneOf) count++ if (this.formCategoryOneOf) count++
@ -1035,6 +1052,9 @@
}, },
isChannelOrPlaylistSearchDisabled () { isChannelOrPlaylistSearchDisabled () {
// We can search against host for playlists and channels
if (this.formHost) return this.countActiveFilters() > 1
return this.countActiveFilters() > 0 return this.countActiveFilters() > 0
}, },

View File

@ -1,5 +1,5 @@
import * as express from 'express' import * as express from 'express'
import { ResultList } from '../../PeerTube/shared/models/result-list.model' import { ResultList } from '../../PeerTube/shared/models/common/result-list.model'
function badRequest (req: express.Request, res: express.Response) { function badRequest (req: express.Request, res: express.Response) {
return res.type('json').status(400).end() return res.type('json').status(400).end()

View File

@ -11,6 +11,7 @@ import { formatAvatarForAPI, formatAvatarForDB } from './shared/elastic-search-a
async function queryChannels (search: ChannelsSearchQuery) { async function queryChannels (search: ChannelsSearchQuery) {
const bool: any = {} const bool: any = {}
const mustNot: any[] = [] const mustNot: any[] = []
const filter: any[] = []
if (search.search) { if (search.search) {
Object.assign(bool, { Object.assign(bool, {
@ -42,6 +43,18 @@ async function queryChannels (search: ChannelsSearchQuery) {
}) })
} }
if (search.host) {
filter.push({
term: {
host: search.host
}
})
}
if (filter.length !== 0) {
Object.assign(bool, { filter })
}
if (mustNot.length !== 0) { if (mustNot.length !== 0) {
Object.assign(bool, { must_not: mustNot }) Object.assign(bool, { must_not: mustNot })
} }

View File

@ -10,6 +10,7 @@ import { buildChannelOrAccountSummaryMapping, formatActorForDB, formatActorSumma
async function queryPlaylists (search: PlaylistsSearchQuery) { async function queryPlaylists (search: PlaylistsSearchQuery) {
const bool: any = {} const bool: any = {}
const mustNot: any[] = [] const mustNot: any[] = []
const filter: any[] = []
if (search.search) { if (search.search) {
Object.assign(bool, { Object.assign(bool, {
@ -41,6 +42,18 @@ async function queryPlaylists (search: PlaylistsSearchQuery) {
}) })
} }
if (search.host) {
filter.push({
term: {
'ownerAccount.host': search.host
}
})
}
if (filter.length !== 0) {
Object.assign(bool, { filter })
}
if (mustNot.length !== 0) { if (mustNot.length !== 0) {
Object.assign(bool, { must_not: mustNot }) Object.assign(bool, { must_not: mustNot })
} }
@ -66,6 +79,7 @@ function formatPlaylistForAPI (p: DBPlaylist, fromHost?: string): EnhancedPlayli
return { return {
id: p.id, id: p.id,
uuid: p.uuid, uuid: p.uuid,
shortUUID: p.shortUUID,
score: p.score, score: p.score,
@ -106,6 +120,7 @@ function formatPlaylistForDB (p: IndexablePlaylist): DBPlaylist {
return { return {
id: p.id, id: p.id,
uuid: p.uuid, uuid: p.uuid,
shortUUID: p.shortUUID,
indexedAt: new Date(), indexedAt: new Date(),
createdAt: p.createdAt, createdAt: p.createdAt,
@ -145,6 +160,9 @@ function buildPlaylistsMapping () {
uuid: { uuid: {
type: 'keyword' type: 'keyword'
}, },
shortUUID: {
type: 'keyword'
},
createdAt: { createdAt: {
type: 'date', type: 'date',
format: 'date_optional_time' format: 'date_optional_time'

View File

@ -162,6 +162,14 @@ async function queryVideos (search: VideosSearchQuery) {
}) })
} }
if (exists(search.host)) {
filter.push({
term: {
'account.host': search.host
}
})
}
Object.assign(bool, { filter }) Object.assign(bool, { filter })
if (mustNot.length !== 0) { if (mustNot.length !== 0) {
@ -231,6 +239,9 @@ function buildVideosMapping () {
uuid: { uuid: {
type: 'keyword' type: 'keyword'
}, },
shortUUID: {
type: 'keyword'
},
createdAt: { createdAt: {
type: 'date', type: 'date',
format: 'date_optional_time' format: 'date_optional_time'
@ -366,6 +377,7 @@ function formatVideoForDB (v: IndexableVideo | IndexableVideoDetails): DBVideo |
return { return {
id: v.id, id: v.id,
uuid: v.uuid, uuid: v.uuid,
shortUUID: v.shortUUID,
indexedAt: new Date(), indexedAt: new Date(),
createdAt: v.createdAt, createdAt: v.createdAt,
@ -418,6 +430,7 @@ function formatVideoForAPI (v: DBVideoDetails, fromHost?: string): EnhancedVideo
return { return {
id: v.id, id: v.id,
uuid: v.uuid, uuid: v.uuid,
shortUUID: v.shortUUID,
score: v.score, score: v.score,

View File

@ -62,6 +62,8 @@ const commonVideosFiltersValidator = [
const videosSearchValidator = [ const videosSearchValidator = [
check('search').optional().not().isEmpty().withMessage('Should have a valid search'), check('search').optional().not().isEmpty().withMessage('Should have a valid search'),
check('host').optional().not().isEmpty().withMessage('Should have a valid host'),
check('startDate').optional().custom(isDateValid).withMessage('Should have a valid start date'), check('startDate').optional().custom(isDateValid).withMessage('Should have a valid start date'),
check('endDate').optional().custom(isDateValid).withMessage('Should have a valid end date'), check('endDate').optional().custom(isDateValid).withMessage('Should have a valid end date'),
@ -87,6 +89,7 @@ const videosSearchValidator = [
const videoChannelsSearchValidator = [ const videoChannelsSearchValidator = [
check('search').not().isEmpty().withMessage('Should have a valid search'), check('search').not().isEmpty().withMessage('Should have a valid search'),
check('host').optional().not().isEmpty().withMessage('Should have a valid host'),
(req: express.Request, res: express.Response, next: express.NextFunction) => { (req: express.Request, res: express.Response, next: express.NextFunction) => {
logger.debug({ query: req.query, body: req.body }, 'Checking video channels search query') logger.debug({ query: req.query, body: req.body }, 'Checking video channels search query')
@ -99,6 +102,7 @@ const videoChannelsSearchValidator = [
const videoPlaylistsSearchValidator = [ const videoPlaylistsSearchValidator = [
check('search').not().isEmpty().withMessage('Should have a valid search'), check('search').not().isEmpty().withMessage('Should have a valid search'),
check('host').optional().not().isEmpty().withMessage('Should have a valid host'),
(req: express.Request, res: express.Response, next: express.NextFunction) => { (req: express.Request, res: express.Response, next: express.NextFunction) => {
logger.debug({ query: req.query, body: req.body }, 'Checking video playlists search query') logger.debug({ query: req.query, body: req.body }, 'Checking video playlists search query')