Update to vuejs 3
This commit is contained in:
parent
ed455a4d36
commit
afc6710112
|
@ -10,24 +10,23 @@
|
|||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"@johmun/vue-tags-input": "^2.1.0",
|
||||
"@jshmrtn/vue3-gettext": "^1.0.4",
|
||||
"@sipec/vue3-tags-input": "^3.0.4",
|
||||
"@types/axios": "^0.14.0",
|
||||
"@vue/cli-plugin-typescript": "^4.5.4",
|
||||
"@vue/cli-service": "^4.0.5",
|
||||
"@types/markdown-it": "^10.0.1",
|
||||
"@vue/cli-plugin-typescript": "~5.0.0-beta.2",
|
||||
"@vue/cli-service": "~5.0.0-beta.2",
|
||||
"@vue/compiler-sfc": "^3.1.0",
|
||||
"axios": "^0.20.0",
|
||||
"markdown-it": "^11.0.0",
|
||||
"node-sass": "^4.13.0",
|
||||
"nprogress": "^0.2.0",
|
||||
"register-service-worker": "^1.0.0",
|
||||
"rollup-plugin-commonjs": "^10.1.0",
|
||||
"rollup-plugin-vue": "^6.0.0-beta.10",
|
||||
"sass-loader": "^10.0.1",
|
||||
"vue": "^2.6.3",
|
||||
"vue-gettext": "^2.1.10",
|
||||
"vue-matomo": "^3.13.5-0",
|
||||
"vue-router": "^3.1.3",
|
||||
"vue-template-compiler": "^2.6.3"
|
||||
"sass": "^1.35.1",
|
||||
"sass-loader": "^12.1.0",
|
||||
"typescript": "~4.3.4",
|
||||
"vue": "^3.1.0",
|
||||
"vue-matomo": "^4.0.1",
|
||||
"vue-router": "^4.0.0"
|
||||
},
|
||||
"browserslist": [
|
||||
"> 1%",
|
||||
|
|
|
@ -7,9 +7,11 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue'
|
||||
|
||||
import Footer from './components/Footer.vue'
|
||||
|
||||
export default {
|
||||
export default defineComponent({
|
||||
components: {
|
||||
'my-footer': Footer
|
||||
},
|
||||
|
@ -19,7 +21,7 @@
|
|||
title: process.env.VUE_APP_TITLE
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
|
|
@ -53,17 +53,17 @@
|
|||
</style>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue, { PropType } from 'vue'
|
||||
import { defineComponent, PropType } from 'vue'
|
||||
import { AccountSummary, VideoChannelSummary } from '../../../PeerTube/shared/models'
|
||||
|
||||
export default Vue.extend({
|
||||
export default defineComponent({
|
||||
props: {
|
||||
actor: Object as PropType<AccountSummary | VideoChannelSummary>,
|
||||
type: String
|
||||
},
|
||||
|
||||
computed: {
|
||||
linkTitle () {
|
||||
linkTitle (): string {
|
||||
if (this.type === 'channel') return this.$gettext('Go on this channel page')
|
||||
|
||||
return this.$gettext('Go on this account page')
|
||||
|
|
|
@ -59,22 +59,23 @@
|
|||
</style>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue, { PropType } from 'vue'
|
||||
import { Video, VideoChannel } from '../../../PeerTube/shared/models'
|
||||
import { useGettext } from '@jshmrtn/vue3-gettext'
|
||||
import { defineComponent, PropType } from 'vue'
|
||||
import { VideoChannel } from '../../../PeerTube/shared/models'
|
||||
|
||||
export default Vue.extend({
|
||||
export default defineComponent({
|
||||
props: {
|
||||
channel: Object as PropType<VideoChannel>
|
||||
},
|
||||
|
||||
computed: {
|
||||
host () {
|
||||
host (): string {
|
||||
const url = this.channel.url
|
||||
|
||||
return new URL(url as string).host
|
||||
},
|
||||
|
||||
discoverChannelMessage () {
|
||||
discoverChannelMessage (): string {
|
||||
return this.$gettextInterpolate(this.$gettext('Discover this channel on %{host}'), { host: this.host })
|
||||
}
|
||||
}
|
||||
|
|
|
@ -154,10 +154,10 @@
|
|||
</style>
|
||||
|
||||
<script>
|
||||
import Vue from 'vue'
|
||||
import { defineComponent } from 'vue'
|
||||
import { getConfig } from '../shared/config'
|
||||
|
||||
export default Vue.extend({
|
||||
export default defineComponent({
|
||||
data () {
|
||||
return {
|
||||
legalNoticesUrl: ''
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
<img class="title-image" v-if="configLoaded && titleImageUrl" v-bind:src="titleImageUrl" v-bind:alt="indexName" />
|
||||
</h1>
|
||||
|
||||
|
||||
<template v-if="!smallFormat">
|
||||
<h4>
|
||||
<div v-translate>A search engine of <a href="https://joinpeertube.org" target="_blank">PeerTube</a> videos and channels</div>
|
||||
|
@ -102,12 +102,12 @@
|
|||
</style>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue'
|
||||
import { defineComponent } from 'vue'
|
||||
import { getConfig } from '../shared/config'
|
||||
import { buildApiUrl } from '../shared/utils'
|
||||
import InterfaceLanguageDropdown from './InterfaceLanguageDropdown.vue'
|
||||
|
||||
export default Vue.extend({
|
||||
export default defineComponent({
|
||||
components: {
|
||||
'interface-language-dropdown': InterfaceLanguageDropdown
|
||||
},
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
<img :title="imgTitle" v-on:click="toggleShow()" class="interface-language" src="/img/interface-languages.svg" alt="Change interface language">
|
||||
|
||||
<div v-if="showMenu" class="menu">
|
||||
<a v-for="(lang, locale) in $language.available" :key="locale" :href="buildLanguageRoute(locale)" class="menu-item">
|
||||
<a v-for="(lang, locale) in availableLanguages" :key="locale" :href="buildLanguageRoute(locale)" class="menu-item">
|
||||
{{lang}}
|
||||
</a>
|
||||
|
||||
<hr></hr>
|
||||
<hr />
|
||||
|
||||
<a class="menu-item add-your-language" target="_blank" href="https://weblate.framasoft.org/projects/peertube-search-index/client/">
|
||||
Translate
|
||||
|
@ -69,9 +69,10 @@
|
|||
</style>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue, { PropType } from 'vue'
|
||||
import { useGettext } from '@jshmrtn/vue3-gettext'
|
||||
import { defineComponent } from 'vue'
|
||||
|
||||
export default Vue.extend({
|
||||
export default defineComponent({
|
||||
data () {
|
||||
return {
|
||||
showMenu: false
|
||||
|
@ -81,6 +82,12 @@
|
|||
computed: {
|
||||
imgTitle () {
|
||||
return this.$gettext('Change interface language')
|
||||
},
|
||||
|
||||
availableLanguages (): { [id: string]: string } {
|
||||
const { available } = useGettext()
|
||||
|
||||
return available
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -88,10 +95,11 @@
|
|||
toggleShow () {
|
||||
this.showMenu = !this.showMenu;
|
||||
},
|
||||
|
||||
buildLanguageRoute(locale: string) {
|
||||
const paths = this.$route.fullPath.split('/')
|
||||
|
||||
if (paths.length > 0 && this.$language.available.hasOwnProperty(paths[0])) {
|
||||
if (paths.length > 0 && this.availableLanguages.hasOwnProperty(paths[0])) {
|
||||
return "/" + locale + "/" + paths.slice(1).join("/")
|
||||
} else {
|
||||
return "/" + locale + this.$route.fullPath
|
||||
|
|
|
@ -1,23 +1,23 @@
|
|||
<template>
|
||||
|
||||
<div class="pagination" v-if="searchDone">
|
||||
<router-link class="previous" v-bind:class="{ 'none-opacity': value === 1 }" :to="{ query: buildPageUrlQuery(value - 1) }">
|
||||
<router-link class="previous" v-bind:class="{ 'none-opacity': modelValue === 1 }" :to="{ query: buildPageUrlQuery(modelValue - 1) }">
|
||||
<translate>Previous page</translate>
|
||||
</router-link>
|
||||
|
||||
<div class="pages">
|
||||
<template v-for="page in pages">
|
||||
|
||||
<router-link v-if="page !== value" class="go-to-page" :to="{ query: buildPageUrlQuery(page) }" :key="page">
|
||||
<router-link v-if="page !== modelValue" class="go-to-page" :to="{ query: buildPageUrlQuery(page) }" :key="page">
|
||||
{{ page }}
|
||||
</router-link>
|
||||
|
||||
<div v-else class="current" :key="page">{{ page }}</div>
|
||||
<div v-else class="current">{{ page }}</div>
|
||||
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<router-link class="next" v-bind:class="{ 'none-opacity': value >= maxPage }" :to="{ query: buildPageUrlQuery(+value + 1) }">
|
||||
<router-link class="next" v-bind:class="{ 'none-opacity': modelValue >= maxPage }" :to="{ query: buildPageUrlQuery(+modelValue + 1) }">
|
||||
<translate>Next page</translate>
|
||||
</router-link>
|
||||
</div>
|
||||
|
@ -65,13 +65,13 @@
|
|||
</style>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue'
|
||||
import { defineComponent } from 'vue'
|
||||
|
||||
export default Vue.extend({
|
||||
export default defineComponent({
|
||||
props: {
|
||||
maxPage: Number,
|
||||
searchDone: Boolean,
|
||||
value: Number,
|
||||
modelValue: Number,
|
||||
pages: Array as () => number[]
|
||||
},
|
||||
|
||||
|
|
|
@ -102,12 +102,13 @@
|
|||
</style>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue, { PropType } from 'vue'
|
||||
import { defineComponent, PropType } from 'vue'
|
||||
import ActorMiniature from './ActorMiniature.vue'
|
||||
import { VideoPlaylist } from '../../../PeerTube/shared/models'
|
||||
import { renderMarkdown } from '../shared/markdown-render'
|
||||
import { useGettext } from '@jshmrtn/vue3-gettext'
|
||||
|
||||
export default Vue.extend({
|
||||
export default defineComponent({
|
||||
components: {
|
||||
'actor-miniature': ActorMiniature
|
||||
},
|
||||
|
@ -117,21 +118,21 @@
|
|||
},
|
||||
|
||||
computed: {
|
||||
host () {
|
||||
host (): string {
|
||||
const url = this.playlist.url
|
||||
|
||||
return new URL(url as string).host
|
||||
},
|
||||
|
||||
updateDate () {
|
||||
updateDate (): string {
|
||||
return new Date(this.playlist.updatedAt).toLocaleDateString()
|
||||
},
|
||||
|
||||
watchMessage () {
|
||||
watchMessage (): string {
|
||||
return this.$gettextInterpolate(this.$gettext('Watch the playlist on %{host}'), { host: this.host })
|
||||
},
|
||||
|
||||
videosLengthLabel () {
|
||||
videosLengthLabel (): string {
|
||||
return this.$gettextInterpolate(this.$gettext('%{videosLength} videos'), { videosLength: this.playlist.videosLength })
|
||||
}
|
||||
},
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<div class="block-warning" v-bind:class="{ highlight: highlight }" >
|
||||
<img src="/img/sepia-warning.svg" alt="">
|
||||
|
||||
<div v-translate="{ indexName: indexName }">
|
||||
<div v-translate>
|
||||
<strong>%{indexName}</strong> displays videos and channels that match your search but is not the publisher, nor the owner.
|
||||
If you notice any problems with a video, report it to the administrators on the PeerTube website where the video is published.
|
||||
</div>
|
||||
|
@ -49,9 +49,9 @@
|
|||
</style>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue'
|
||||
import { defineComponent } from 'vue'
|
||||
|
||||
export default Vue.extend({
|
||||
export default defineComponent({
|
||||
props: {
|
||||
indexName: String,
|
||||
highlight: Boolean
|
||||
|
|
|
@ -115,41 +115,42 @@
|
|||
</style>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue, { PropType } from 'vue'
|
||||
import { defineComponent, PropType } from 'vue'
|
||||
import ActorMiniature from './ActorMiniature.vue'
|
||||
import { Video } from '../../../PeerTube/shared/models'
|
||||
import { durationToString } from '../shared/utils'
|
||||
import { renderMarkdown } from '../shared/markdown-render'
|
||||
import { useGettext } from '@jshmrtn/vue3-gettext'
|
||||
import { EnhancedVideo } from '../../../server/types/video.model'
|
||||
|
||||
export default Vue.extend({
|
||||
export default defineComponent({
|
||||
components: {
|
||||
'actor-miniature': ActorMiniature
|
||||
},
|
||||
|
||||
props: {
|
||||
video: Object as PropType<Video>
|
||||
video: Object as PropType<EnhancedVideo>
|
||||
},
|
||||
|
||||
computed: {
|
||||
host () {
|
||||
host (): string {
|
||||
const url = this.video.url
|
||||
|
||||
return new URL(url as string).host
|
||||
},
|
||||
|
||||
formattedDuration () {
|
||||
formattedDuration (): string {
|
||||
return durationToString(this.video.duration)
|
||||
},
|
||||
|
||||
windowWidth () {
|
||||
windowWidth (): number {
|
||||
return window.innerWidth
|
||||
},
|
||||
|
||||
publicationDate () {
|
||||
publicationDate (): string {
|
||||
return new Date(this.video.publishedAt).toLocaleDateString()
|
||||
},
|
||||
|
||||
watchVideoMessage () {
|
||||
watchVideoMessage (): string {
|
||||
return this.$gettextInterpolate(this.$gettext('Watch the video on %{host}'), { host: this.host })
|
||||
}
|
||||
},
|
||||
|
|
|
@ -1,42 +1,39 @@
|
|||
import './scss/main.scss'
|
||||
import Vue from 'vue'
|
||||
import GetTextPlugin from 'vue-gettext'
|
||||
import { createApp } from 'vue'
|
||||
import VueMatomo from 'vue-matomo'
|
||||
import App from './App.vue'
|
||||
import Router from 'vue-router'
|
||||
import Search from './views/Search.vue'
|
||||
import VueRouter from 'vue-router'
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import { createGettext, useGettext } from '@jshmrtn/vue3-gettext'
|
||||
|
||||
Vue.use(VueRouter)
|
||||
|
||||
Vue.config.productionTip = process.env.NODE_ENV === 'production'
|
||||
const app = createApp(App)
|
||||
|
||||
// ############# I18N ##############
|
||||
|
||||
const availableLanguages = {
|
||||
'en_US': 'English',
|
||||
'fr_FR': 'Français',
|
||||
'de': 'Deutsch',
|
||||
'el': 'ελληνικά',
|
||||
'es': 'Español',
|
||||
'gd': 'Gàidhlig',
|
||||
'gl': 'galego',
|
||||
'ru': 'русский',
|
||||
'it': 'Italiano',
|
||||
'ja': '日本語',
|
||||
'sv': 'svenska',
|
||||
'nl': 'Nederlands',
|
||||
'oc': 'Occitan',
|
||||
'sq': 'Shqip',
|
||||
'pt_BR': 'Português (Brasil)',
|
||||
'bn': 'বাংলা',
|
||||
'pl': 'Polski'
|
||||
en_US: 'English',
|
||||
fr_FR: 'Français',
|
||||
de: 'Deutsch',
|
||||
el: 'ελληνικά',
|
||||
es: 'Español',
|
||||
gd: 'Gàidhlig',
|
||||
gl: 'galego',
|
||||
ru: 'русский',
|
||||
it: 'Italiano',
|
||||
ja: '日本語',
|
||||
sv: 'svenska',
|
||||
nl: 'Nederlands',
|
||||
oc: 'Occitan',
|
||||
sq: 'Shqip',
|
||||
pt_BR: 'Português (Brasil)',
|
||||
bn: 'বাংলা',
|
||||
pl: 'Polski'
|
||||
}
|
||||
const aliasesLanguages = {
|
||||
'en': 'en_US',
|
||||
'fr': 'fr_FR',
|
||||
'br': 'pt_BR',
|
||||
'pt': 'pt_BR'
|
||||
en: 'en_US',
|
||||
fr: 'fr_FR',
|
||||
br: 'pt_BR',
|
||||
pt: 'pt_BR'
|
||||
}
|
||||
const allLocales = Object.keys(availableLanguages).concat(Object.keys(aliasesLanguages))
|
||||
|
||||
|
@ -64,108 +61,107 @@ if (allLocales.includes(localePath)) {
|
|||
currentLanguage = aliasesLanguages[snakeCaseLanguage] ? aliasesLanguages[snakeCaseLanguage] : snakeCaseLanguage
|
||||
}
|
||||
|
||||
Vue.filter('translate', value => {
|
||||
return value ? Vue.prototype.$gettext(value.toString()) : ''
|
||||
})
|
||||
buildTranslationsPromise(defaultLanguage, currentLanguage)
|
||||
.catch(err => {
|
||||
console.error('Cannot load translations.', err)
|
||||
|
||||
const p = buildTranslationsPromise(defaultLanguage, currentLanguage)
|
||||
|
||||
p.catch(err => {
|
||||
console.error('Cannot load translations.', err)
|
||||
return { default: {} }
|
||||
}).then(translations => {
|
||||
Vue.use(GetTextPlugin, {
|
||||
translations,
|
||||
availableLanguages,
|
||||
defaultLanguage: 'en_US',
|
||||
silent: currentLanguage === 'en_US'
|
||||
return { default: {} }
|
||||
})
|
||||
|
||||
Vue.config.language = currentLanguage
|
||||
|
||||
// Routes
|
||||
let routes = []
|
||||
|
||||
for (const locale of [ '' ].concat(allLocales)) {
|
||||
const base = locale
|
||||
? '/' + locale + '/'
|
||||
: '/'
|
||||
|
||||
routes = routes.concat([
|
||||
{
|
||||
path: base,
|
||||
component: Search
|
||||
},
|
||||
{
|
||||
path: base + 'search',
|
||||
component: Search
|
||||
}
|
||||
])
|
||||
}
|
||||
|
||||
routes.push({
|
||||
path: '/*',
|
||||
// Don't want to create a 404 page
|
||||
component: Search
|
||||
})
|
||||
|
||||
const router = new Router({
|
||||
mode: 'history',
|
||||
routes
|
||||
})
|
||||
|
||||
// Stats Matomo
|
||||
if (!(navigator.doNotTrack === 'yes' ||
|
||||
navigator.doNotTrack === '1' ||
|
||||
window.doNotTrack === '1')
|
||||
) {
|
||||
Vue.use(VueMatomo, {
|
||||
// Configure your matomo server and site
|
||||
host: 'https://stats.framasoft.org/',
|
||||
siteId: 77,
|
||||
|
||||
// Enables automatically registering pageviews on the router
|
||||
router,
|
||||
|
||||
// Require consent before sending tracking information to matomo
|
||||
// Default: false
|
||||
requireConsent: false,
|
||||
|
||||
// Whether to track the initial page view
|
||||
// Default: true
|
||||
trackInitialView: true,
|
||||
|
||||
// Changes the default .js and .php endpoint's filename
|
||||
// Default: 'piwik'
|
||||
trackerFileName: 'p',
|
||||
|
||||
enableLinkTracking: true
|
||||
.then(translations => {
|
||||
const gettext = createGettext({
|
||||
translations,
|
||||
availableLanguages,
|
||||
defaultLanguage: currentLanguage,
|
||||
mutedLanguages: [ 'en_US' ]
|
||||
})
|
||||
|
||||
const _paq = []
|
||||
app.use(gettext)
|
||||
|
||||
// CNIL conformity
|
||||
_paq.push([ function piwikCNIL () {
|
||||
const self = this
|
||||
// Routes
|
||||
let routes = []
|
||||
|
||||
function getOriginalVisitorCookieTimeout () {
|
||||
const now = new Date()
|
||||
const nowTs = Math.round(now.getTime() / 1000)
|
||||
const visitorInfo = self.getVisitorInfo()
|
||||
const createTs = parseInt(visitorInfo[2], 10)
|
||||
const cookieTimeout = 33696000 // 13 months in seconds
|
||||
return (createTs + cookieTimeout) - nowTs
|
||||
}
|
||||
for (const locale of [ '' ].concat(allLocales)) {
|
||||
const base = locale
|
||||
? '/' + locale + '/'
|
||||
: '/'
|
||||
|
||||
this.setVisitorCookieTimeout(getOriginalVisitorCookieTimeout())
|
||||
} ])
|
||||
}
|
||||
routes = routes.concat([
|
||||
{
|
||||
path: base,
|
||||
component: Search
|
||||
},
|
||||
{
|
||||
path: base + 'search',
|
||||
component: Search
|
||||
}
|
||||
])
|
||||
}
|
||||
|
||||
new Vue({
|
||||
router,
|
||||
render: h => h(App)
|
||||
}).$mount('#app')
|
||||
})
|
||||
routes.push({
|
||||
path: '/*',
|
||||
// Don't want to create a 404 page
|
||||
component: Search
|
||||
})
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(),
|
||||
routes
|
||||
})
|
||||
|
||||
// Stats Matomo
|
||||
if (!(navigator.doNotTrack === 'yes' ||
|
||||
navigator.doNotTrack === '1' ||
|
||||
window.doNotTrack === '1')
|
||||
) {
|
||||
app.use(VueMatomo, {
|
||||
// Configure your matomo server and site
|
||||
host: 'https://stats.framasoft.org/',
|
||||
siteId: 77,
|
||||
|
||||
// Enables automatically registering pageviews on the router
|
||||
router,
|
||||
|
||||
// Require consent before sending tracking information to matomo
|
||||
// Default: false
|
||||
requireConsent: false,
|
||||
|
||||
// Whether to track the initial page view
|
||||
// Default: true
|
||||
trackInitialView: true,
|
||||
|
||||
// Changes the default .js and .php endpoint's filename
|
||||
// Default: 'piwik'
|
||||
trackerFileName: 'p',
|
||||
|
||||
enableLinkTracking: true
|
||||
})
|
||||
|
||||
const _paq = []
|
||||
|
||||
// CNIL conformity
|
||||
_paq.push([ function piwikCNIL () {
|
||||
// @ts-expect-error
|
||||
const self = this
|
||||
|
||||
function getOriginalVisitorCookieTimeout () {
|
||||
const now = new Date()
|
||||
const nowTs = Math.round(now.getTime() / 1000)
|
||||
const visitorInfo = self.getVisitorInfo()
|
||||
const createTs = parseInt(visitorInfo[2], 10)
|
||||
const cookieTimeout = 33696000 // 13 months in seconds
|
||||
return (createTs + cookieTimeout) - nowTs
|
||||
}
|
||||
|
||||
// @ts-expect-error
|
||||
this.setVisitorCookieTimeout(getOriginalVisitorCookieTimeout())
|
||||
} ])
|
||||
}
|
||||
|
||||
app.use(router)
|
||||
|
||||
app.mount('#app')
|
||||
})
|
||||
.catch(err => console.error(err))
|
||||
|
||||
function buildTranslationsPromise (defaultLanguage, currentLanguage) {
|
||||
const translations = {}
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
export interface SearchUrl {
|
||||
[id: string]: string | undefined | number[] | string[]
|
||||
|
||||
search?: string
|
||||
nsfw?: string
|
||||
publishedDateRange?: string
|
||||
|
@ -11,4 +9,9 @@ export interface SearchUrl {
|
|||
|
||||
tagsAllOf?: string[]
|
||||
tagsOneOf?: string[]
|
||||
|
||||
isLive?: boolean | string
|
||||
|
||||
sort?: string
|
||||
page?: number | string
|
||||
}
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
import Vue from 'vue'
|
||||
|
||||
function buildApiUrl (path: string) {
|
||||
const normalizedPath = path.startsWith('/') ? path : '/' + path
|
||||
if (Vue.config.productionTip) return normalizedPath
|
||||
|
||||
return process.env.VUE_APP_API_URL + normalizedPath
|
||||
const base = process.env.VUE_APP_API_URL || ''
|
||||
return base + normalizedPath
|
||||
}
|
||||
|
||||
function durationToString (duration: number) {
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
declare module '*.vue' {
|
||||
import Vue from 'vue'
|
||||
export default Vue
|
||||
}
|
||||
|
||||
declare var $language
|
|
@ -0,0 +1,11 @@
|
|||
import { Language } from '@jshmrtn/vue3-gettext'
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
export interface ComponentCustomProperties {
|
||||
$gettext: Language['$gettext']
|
||||
$pgettext: Language['$pgettext']
|
||||
$ngettext: Language['$ngettext']
|
||||
$npgettext: Language['$npgettext']
|
||||
$gettextInterpolate: Language['interpolate']
|
||||
}
|
||||
}
|
|
@ -1,13 +1,13 @@
|
|||
<template>
|
||||
<div>
|
||||
<my-header v-bind:indexName="indexName" v-bind:smallFormat="searchDone"></my-header>
|
||||
<router-link v-if="searchDone" class="header-left-logo" to="/" @click.native="simpleFormReset(false)" :title="homeTitleMessage">
|
||||
<router-link v-if="searchDone" class="header-left-logo" to="/" @click="simpleFormReset(false)" :title="homeTitleMessage">
|
||||
<img src="/img/peertube-logo.svg" alt="">
|
||||
</router-link>
|
||||
|
||||
<main>
|
||||
<form id="search-anchor" class="search-container" v-bind:class="{ 'search-container-small': !searchDone }" role="search" onsubmit="return false;">
|
||||
<input v-bind:placeholder="inputPlaceholder" autofocus v-on:keyup.enter="doNewSearch()" type="text" v-model="formSearch" name="search" autocapitalize="off" autocomplete="off" autocorrect="off" maxlength="1024" />
|
||||
<input v-bind:placeholder="inputPlaceholder" autofocus type="text" v-model="formSearch" name="search" autocapitalize="off" autocomplete="off" autocorrect="off" maxlength="1024" />
|
||||
|
||||
<button v-on:click="doNewSearch()">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
|
@ -225,6 +225,8 @@
|
|||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
@use 'sass:math';
|
||||
|
||||
@import '../scss/_variables';
|
||||
|
||||
main {
|
||||
|
@ -405,7 +407,7 @@
|
|||
position: absolute;
|
||||
right: 0;
|
||||
top: 50%;
|
||||
margin-top: -$size/2;
|
||||
margin-top: math.div(-$size, 2);
|
||||
margin-right: 10px;
|
||||
width: 0;
|
||||
height: 0;
|
||||
|
@ -439,7 +441,7 @@
|
|||
</style>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue'
|
||||
import { defineComponent } from 'vue'
|
||||
import Header from '../components/Header.vue'
|
||||
import SearchWarning from '../components/SearchWarning.vue'
|
||||
import VideoResult from '../components/VideoResult.vue'
|
||||
|
@ -451,14 +453,14 @@
|
|||
import { SearchUrl } from '../models'
|
||||
import { EnhancedVideo } from '../../../server/types/video.model'
|
||||
import { EnhancedVideoChannel } from '../../../server/types/channel.model'
|
||||
import VueTagsInput from '@johmun/vue-tags-input'
|
||||
import VueTagsInput from '@sipec/vue3-tags-input'
|
||||
import Pagination from '../components/Pagination.vue'
|
||||
import { VideoChannelsSearchQuery, ResultList, VideosSearchQuery } from '../../../PeerTube/shared/models'
|
||||
import Nprogress from 'nprogress'
|
||||
import { EnhancedPlaylist } from '../../../server/types/playlist.model'
|
||||
import { PlaylistsSearchQuery } from '../../../server/types/search-query/playlist-search.model'
|
||||
|
||||
export default Vue.extend({
|
||||
export default defineComponent({
|
||||
components: {
|
||||
'my-header': Header,
|
||||
'search-warning': SearchWarning,
|
||||
|
@ -534,7 +536,7 @@
|
|||
watch: {
|
||||
// For pagination change
|
||||
$route(to, from) {
|
||||
const urlPage = this.$route.query.page
|
||||
const urlPage = this.$route.query.page as string
|
||||
|
||||
const scrollToResults = urlPage && parseInt(urlPage) !== this.currentPage
|
||||
|
||||
|
@ -545,6 +547,8 @@
|
|||
return
|
||||
}
|
||||
|
||||
console.log('do search')
|
||||
|
||||
this.doSearch()
|
||||
if (scrollToResults) this.scrollToResults()
|
||||
},
|
||||
|
@ -555,20 +559,20 @@
|
|||
},
|
||||
|
||||
computed: {
|
||||
applyFiltersLabel () {
|
||||
applyFiltersLabel (): string {
|
||||
return this.$gettext('Apply filters')
|
||||
},
|
||||
|
||||
inputPlaceholder () {
|
||||
inputPlaceholder (): string {
|
||||
return this.$gettext('Keyword, channel, video, playlist, etc.')
|
||||
},
|
||||
|
||||
tagsPlaceholder () {
|
||||
tagsPlaceholder (): string {
|
||||
return this.$gettext('Add tag')
|
||||
},
|
||||
|
||||
publishedDateRanges () {
|
||||
return [
|
||||
publishedDateRanges (): { id: string, label: string }[] {
|
||||
return [
|
||||
{
|
||||
id: 'any_published_date',
|
||||
label: this.$gettext('Any')
|
||||
|
@ -592,7 +596,7 @@
|
|||
]
|
||||
},
|
||||
|
||||
durationRanges () {
|
||||
durationRanges (): { id: string, label: string }[] {
|
||||
return [
|
||||
{
|
||||
id: 'any_duration',
|
||||
|
@ -613,7 +617,7 @@
|
|||
]
|
||||
},
|
||||
|
||||
videoCategories () {
|
||||
videoCategories (): { id: string, label: string }[] {
|
||||
return [
|
||||
{ id: '1', label: this.$gettext('Music') },
|
||||
{ id: '2', label: this.$gettext('Films') },
|
||||
|
@ -636,7 +640,7 @@
|
|||
]
|
||||
},
|
||||
|
||||
videoLicences () {
|
||||
videoLicences (): { id: string, label: string }[] {
|
||||
return [
|
||||
{ id: '1', label: this.$gettext('Attribution') },
|
||||
{ id: '2', label: this.$gettext('Attribution - Share Alike') },
|
||||
|
@ -648,7 +652,7 @@
|
|||
]
|
||||
},
|
||||
|
||||
videoLanguages () {
|
||||
videoLanguages (): { id: string, label: string }[] {
|
||||
return [
|
||||
{ id: 'en', label: this.$gettext('English') },
|
||||
{ id: 'fr', label: this.$gettext('Français') },
|
||||
|
@ -673,7 +677,7 @@
|
|||
]
|
||||
},
|
||||
|
||||
boostLanguagesQuery () {
|
||||
boostLanguagesQuery (): string[] {
|
||||
const languages = new Set<string>()
|
||||
|
||||
for (const completeLanguage of navigator.languages) {
|
||||
|
@ -687,7 +691,7 @@
|
|||
return Array.from(languages)
|
||||
},
|
||||
|
||||
homeTitleMessage () {
|
||||
homeTitleMessage (): string {
|
||||
return this.$gettext('Display homepage')
|
||||
}
|
||||
},
|
||||
|
@ -695,6 +699,8 @@
|
|||
methods: {
|
||||
|
||||
doNewSearch () {
|
||||
console.log('do new search')
|
||||
|
||||
this.currentPage = 1
|
||||
this.channelsCount = null
|
||||
this.videosCount = null
|
||||
|
@ -728,8 +734,10 @@
|
|||
this.playlistsCount = playlistsResult.total
|
||||
|
||||
this.resultsCount = videosResult.total + channelsResult.total + playlistsResult.total
|
||||
this.results = channelsResult.data.concat(playlistsResult.data)
|
||||
.concat(videosResult.data)
|
||||
|
||||
this.results = channelsResult.data
|
||||
this.results = this.results.concat(playlistsResult.data)
|
||||
this.results = this.results.concat(videosResult.data)
|
||||
|
||||
if (this.formSort === '-match') {
|
||||
this.results.sort((r1, r2) => {
|
||||
|
@ -792,11 +800,11 @@
|
|||
page: this.currentPage
|
||||
}
|
||||
|
||||
this.$router.push({ path: '/search', query })
|
||||
this.$router.push({ path: '/search', query: query as any })
|
||||
},
|
||||
|
||||
loadUrl () {
|
||||
const query = this.$route.query as SearchUrl & { page: number }
|
||||
const query = this.$route.query as SearchUrl
|
||||
|
||||
if (query.search) this.formSearch = query.search
|
||||
else this.formSearch = undefined
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"module": "es2020",
|
||||
"target": "esnext",
|
||||
"module": "esnext",
|
||||
"strict": false,
|
||||
"noImplicitThis": true,
|
||||
"jsx": "preserve",
|
||||
"moduleResolution": "node",
|
||||
"experimentalDecorators": true,
|
||||
|
|
5476
client/yarn.lock
5476
client/yarn.lock
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue