sepia-search-motore-di-rice.../client/src/components/Filters.vue

459 lines
15 KiB
Vue

<template>
<div class="filters-content">
<div class="form-group small-height">
<div class="radio-label label-container">
<label>{{ $gettext('Display sensitive content') }}</label>
<button v-if="formNSFW !== undefined" class="reset-button" @click="resetField('nsfw')">
{{ $gettext('Reset') }}
</button>
</div>
<div class="peertube-radio-container">
<input id="sensitiveContentYes" v-model="formNSFW" type="radio" name="sensitiveContent" value="both">
<label for="sensitiveContentYes" class="radio">{{ $gettext('Yes') }}</label>
</div>
<div class="peertube-radio-container">
<input id="sensitiveContentNo" v-model="formNSFW" type="radio" name="sensitiveContent" value="false">
<label for="sensitiveContentNo" class="radio">{{ $gettext('No') }}</label>
</div>
</div>
<div class="form-group small-height">
<div class="radio-label label-container">
<label>{{ $gettext('Display only') }}</label>
<button v-if="formIsLive !== undefined" class="reset-button" @click="resetField('isLive')">{{ $gettext('Reset') }}</button>
</div>
<div class="peertube-radio-container">
<input id="isLiveYes" v-model="formIsLive" type="radio" name="isLive" value="both">
<label for="isLiveYes" class="radio">{{ $gettext('Live videos') }}</label>
</div>
<div class="peertube-radio-container">
<input id="isLiveNo" v-model="formIsLive" type="radio" name="isLive" value="false">
<label for="isLiveNo" class="radio">{{ $gettext('VOD videos') }}</label>
</div>
</div>
<div class="form-group">
<div class="radio-label label-container">
<label>{{ $gettext('Published date') }}</label>
<button v-if="formPublishedDateRange !== undefined" class="reset-button" @click="resetField('publishedDateRange')">
{{ $gettext('Reset') }}
</button>
</div>
<div v-for="date in publishedDateRanges" :key="date.id" class="peertube-radio-container">
<input :id="date.id" v-model="formPublishedDateRange" type="radio" name="publishedDateRange" :value="date.id">
<label :for="date.id" class="radio">{{ date.label }}</label>
</div>
</div>
<div class="form-group">
<div class="radio-label label-container">
<label>{{ $gettext('Duration') }}</label>
<button v-if="formDurationRange !== undefined" class="reset-button" @click="resetField('durationRange')">
{{ $gettext('Reset') }}
</button>
</div>
<div v-for="duration in durationRanges" :key="duration.id" class="peertube-radio-container">
<input :id="duration.id" v-model="formDurationRange" type="radio" name="durationRange" :value="duration.id">
<label :for="duration.id" class="radio">{{ duration.label }}</label>
</div>
</div>
<div class="form-group">
<label for="category">{{ $gettext('Category') }}</label>
<button v-if="formCategoryOneOf !== undefined" class="reset-button" @click="resetField('categoryOneOf')">
{{ $gettext('Reset') }}
</button>
<div class="select-container">
<select id="category" v-model="formCategoryOneOf" name="category">
<option :value="undefined">
{{ $gettext('Display all categories') }}
</option>
<option v-for="category in videoCategories" :key="category.id" :value="category.id">
{{ category.label }}
</option>
</select>
</div>
</div>
<div class="form-group">
<label for="licence">{{ $gettext('Licence') }}</label>
<button v-if="formLicenceOneOf !== undefined" class="reset-button" @click="resetField('licenceOneOf')">
{{ $gettext('Reset') }}
</button>
<div class="select-container">
<select id="licence" v-model="formLicenceOneOf" name="licence">
<option :value="undefined">
{{ $gettext('Display all licenses') }}
</option>
<option v-for="licence in videoLicences" :key="licence.id" :value="licence.id">
{{ licence.label }}
</option>
</select>
</div>
</div>
<div class="form-group">
<label for="language">{{ $gettext('Language') }}</label>
<button v-if="formLanguageOneOf !== undefined" class="reset-button" @click="resetField('languageOneOf')">
{{ $gettext('Reset') }}
</button>
<div class="select-container">
<select id="language" v-model="formLanguageOneOf" name="language">
<option :value="undefined">
{{ $gettext('Display all languages') }}
</option>
<option v-for="language in videoLanguages" :key="language.id" :value="language.id">
{{ language.label }}
</option>
</select>
</div>
</div>
<div class="form-group">
<label for="host">{{ $gettext('PeerTube instance') }}</label>
<input id="host" v-model="formHost" type="text" name="host" class="classic-input-text" />
</div>
<div class="form-group">
<label for="tagsAllOf">{{ $gettext('All of these tags') }}</label>
<button v-if="formTagsAllOf.length !== 0" class="reset-button" @click="resetField('tagsAllOf')">
{{ $gettext('Reset') }}
</button>
<vue-tags-input
v-model="formTagAllOf" :placeholder="tagsPlaceholder" :tags="formTagsAllOf"
@tags-changed="newTags => formTagsAllOf = newTags"
/>
</div>
<div class="form-group">
<label for="tagsOneOf">{{ $gettext('One of these tags') }}</label>
<button v-if="formTagsOneOf.length !== 0" class="reset-button" @click="resetField('tagsOneOf')">
{{ $gettext('Reset') }}
</button>
<vue-tags-input
v-model="formTagOneOf" :placeholder="tagsPlaceholder" :tags="formTagsOneOf"
@tags-changed="newTags => formTagsOneOf = newTags"
/>
</div>
<div class="button-block mt-3">
<router-link class="peertube-button peertube-button-link peertube-primary-button" :to="{ path: '/search', query: { ...getUrlQuery() } }">
{{ applyFiltersLabel }}
</router-link>
</div>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import VueTagsInput from '@sipec/vue3-tags-input'
import { SearchUrl } from '@/models/search-url.model'
import { extractTagsFromQuery } from '@/shared/utils'
export default defineComponent({
components: {
'vue-tags-input': VueTagsInput,
},
data () {
return {
formNSFW: undefined,
formHost: '',
formPublishedDateRange: undefined,
formDurationRange: undefined,
formCategoryOneOf: undefined,
formLicenceOneOf: undefined,
formLanguageOneOf: undefined,
formTagAllOf: '',
formTagOneOf: '',
formTagsAllOf: [],
formTagsOneOf: [],
formIsLive: undefined,
activeFilters: 0
}
},
computed: {
applyFiltersLabel (): string {
return this.$gettext('Apply filters')
},
inputPlaceholder (): string {
return this.$gettext('Keyword, channel, video, playlist, etc.')
},
tagsPlaceholder (): string {
return this.$gettext('Add tag')
},
publishedDateRanges (): { id: string, label: string }[] {
return [
{
id: 'any_published_date',
label: this.$gettext('Any')
},
{
id: 'today',
label: this.$gettext('Today')
},
{
id: 'last_7days',
label: this.$gettext('Last 7 days')
},
{
id: 'last_30days',
label: this.$gettext('Last 30 days')
},
{
id: 'last_365days',
label: this.$gettext('Last 365 days')
}
]
},
durationRanges (): { id: string, label: string }[] {
return [
{
id: 'any_duration',
label: this.$gettext('Any')
},
{
id: 'short',
label: this.$gettext('Short (< 4 min)')
},
{
id: 'medium',
label: this.$gettext('Medium (4-10 min)')
},
{
id: 'long',
label: this.$gettext('Long (> 10 min)')
}
]
},
videoCategories (): { id: string, label: string }[] {
return [
{ id: '1', label: this.$gettext('Music') },
{ id: '2', label: this.$gettext('Films') },
{ id: '3', label: this.$gettext('Vehicles') },
{ id: '4', label: this.$gettext('Art') },
{ id: '5', label: this.$gettext('Sports') },
{ id: '6', label: this.$gettext('Travels') },
{ id: '7', label: this.$gettext('Gaming') },
{ id: '8', label: this.$gettext('People') },
{ id: '9', label: this.$gettext('Comedy') },
{ id: '10', label: this.$gettext('Entertainment') },
{ id: '11', label: this.$gettext('News & Politics') },
{ id: '12', label: this.$gettext('How To') },
{ id: '13', label: this.$gettext('Education') },
{ id: '14', label: this.$gettext('Activism') },
{ id: '15', label: this.$gettext('Science & Technology') },
{ id: '16', label: this.$gettext('Animals') },
{ id: '17', label: this.$gettext('Kids') },
{ id: '18', label: this.$gettext('Food') }
]
},
videoLicences (): { id: string, label: string }[] {
return [
{ id: '1', label: this.$gettext('Attribution') },
{ id: '2', label: this.$gettext('Attribution - Share Alike') },
{ id: '3', label: this.$gettext('Attribution - No Derivatives') },
{ id: '4', label: this.$gettext('Attribution - Non Commercial') },
{ id: '5', label: this.$gettext('Attribution - Non Commercial - Share Alike') },
{ id: '6', label: this.$gettext('Attribution - Non Commercial - No Derivatives') },
{ id: '7', label: this.$gettext('Public Domain Dedication') }
]
},
videoLanguages (): { id: string, label: string }[] {
return [
{ id: 'en', label: this.$gettext('English') },
{ id: 'fr', label: this.$gettext('Français') },
{ id: 'ja', label: this.$gettext('日本語') },
{ id: 'eu', label: this.$gettext('Euskara') },
{ id: 'ca', label: this.$gettext('Català') },
{ id: 'cs', label: this.$gettext('Čeština') },
{ id: 'eo', label: this.$gettext('Esperanto') },
{ id: 'el', label: this.$gettext('ελληνικά') },
{ id: 'de', label: this.$gettext('Deutsch') },
{ id: 'it', label: this.$gettext('Italiano') },
{ id: 'nl', label: this.$gettext('Nederlands') },
{ id: 'es', label: this.$gettext('Español') },
{ id: 'oc', label: this.$gettext('Occitan') },
{ id: 'gd', label: this.$gettext('Gàidhlig') },
{ id: 'zh', label: this.$gettext('简体中文(中国)') },
{ id: 'pt', label: this.$gettext('Português (Portugal)') },
{ id: 'sv', label: this.$gettext('svenska') },
{ id: 'pl', label: this.$gettext('Polski') },
{ id: 'fi', label: this.$gettext('suomi') },
{ id: 'ru', label: this.$gettext('русский') }
]
}
},
mounted () {
this.loadUrl()
},
methods: {
getUrlQuery (): SearchUrl {
return {
...this.$route.query,
nsfw: this.formNSFW,
host: this.formHost || undefined,
isLive: this.formIsLive,
publishedDateRange: this.formPublishedDateRange,
durationRange: this.formDurationRange,
categoryOneOf: this.formCategoryOneOf,
licenceOneOf: this.formLicenceOneOf,
languageOneOf: this.formLanguageOneOf,
tagsAllOf: this.formTagsAllOf.map(t => t.text),
tagsOneOf: this.formTagsOneOf.map(t => t.text)
}
},
loadUrl () {
const query = this.$route.query as SearchUrl
if (query.nsfw) this.formNSFW = query.nsfw
else this.formNSFW = undefined
if (query.publishedDateRange) this.formPublishedDateRange = query.publishedDateRange
else this.formPublishedDateRange = undefined
if (query.durationRange) this.formDurationRange = query.durationRange
else this.formDurationRange = undefined
if (query.categoryOneOf) this.formCategoryOneOf = query.categoryOneOf
else this.formCategoryOneOf = undefined
if (query.licenceOneOf) this.formLicenceOneOf = query.licenceOneOf
else this.formLicenceOneOf = undefined
if (query.languageOneOf) this.formLanguageOneOf = query.languageOneOf
else this.formLanguageOneOf = undefined
if (query.tagsAllOf) this.formTagsAllOf = extractTagsFromQuery(query.tagsAllOf)
else this.formTagsAllOf = []
if (query.tagsOneOf) this.formTagsOneOf = extractTagsFromQuery(query.tagsOneOf)
else this.formTagsOneOf = []
if (query.isLive) this.formIsLive = query.isLive
else this.formIsLive = undefined
if (query.host) this.formHost = query.host
else this.formHost = ''
},
resetField (field: string) {
if (field === 'nsfw') this.formNSFW = undefined
else if (field === 'publishedDateRange') this.formPublishedDateRange = undefined
else if (field === 'durationRange') this.formDurationRange = undefined
else if (field === 'categoryOneOf') this.formCategoryOneOf = undefined
else if (field === 'licenceOneOf') this.formLicenceOneOf = undefined
else if (field === 'languageOneOf') this.formLanguageOneOf = undefined
else if (field === 'isLive') this.formIsLive = undefined
else if (field === 'tagsAllOf') this.formTagsAllOf = []
else if (field === 'tagsOneOf') this.formTagsOneOf = []
else if (field === 'host') this.formHost = ''
}
}
})
</script>
<style scoped lang="scss">
@use 'sass:math';
@import '../scss/_variables';
.filters-content {
display: flex;
flex-wrap: wrap;
margin-top: 1.25rem;
.form-group:nth-child(2n-1) {
padding-right: 20px;
}
.form-group {
width: 50%;
min-height: 60px;
display: inline-block;
margin: 10px 0;
font-size: 0.875rem;
}
@media screen and (max-width: $small-view) {
.form-group {
width: 100%;
padding-right: 0;
}
}
.form-group > label,
.label-container label {
font-weight: $font-semibold;
}
.form-group > label,
.label-container {
display: inline-block;
margin-bottom: 5px;
}
.form-group.small-height {
min-height: 30px;
}
.peertube-radio-container {
display: inline-block;
margin: 0 10px 5px 0;
}
.button-block {
width: 100%;
text-align: right;
}
.radio-label {
display: block;
}
.reset-button {
background: none;
border: none;
font-weight: 600;
font-size: 0.7rem;
opacity: 0.7;
margin-left: 5px;
cursor: pointer;
}
}
</style>