Migrate to vuex@4 and vue-router@4

This commit is contained in:
Kasper Seweryn 2022-04-18 18:17:51 +02:00 committed by Georg Krause
parent 7c5d259c2b
commit 74ca3b1725
13 changed files with 182 additions and 134 deletions

View File

@ -39,11 +39,11 @@
"vue-gettext": "2.1.12",
"vue-lazyload": "1.3.4",
"vue-plyr": "7.0.0",
"vue-router": "3.5.4",
"vue-router": "4.0.14",
"vue-upload-component": "2.8.22",
"vue3-gettext": "2.2.0-alpha.1",
"vuedraggable": "2.24.3",
"vuex": "3.6.2",
"vuex": "4.0.2",
"vuex-persistedstate": "4.1.0",
"vuex-router-sync": "5.0.0"
},

View File

@ -144,10 +144,21 @@ const showSetInstanceModal = ref(false)
@touch-progress="player.setCurrentTime($event)"
/>
</transition>
<router-view
role="main"
:class="{hidden: store.state.ui.queueFocused}"
/>
v-slot="{ Component }"
>
<Suspense v-if="Component">
<component :is="Component" />
<template #fallback>
<!-- TODO (wvffle): Add loader -->
Loading...
</template>
</Suspense>
</router-view>
<audio-player ref="player" />
<playlist-modal v-if="store.state.auth.authenticated" />
<channel-upload-modal v-if="store.state.auth.authenticated" />

View File

@ -481,6 +481,8 @@ import Modal from '~/components/semantic/Modal.vue'
import $ from 'jquery'
import useThemeList from '~/composables/useThemeList'
import useTheme from '~/composables/useTheme'
import { useRoute } from 'vue-router'
import { computed } from 'vue'
export default {
name: 'Sidebar',
@ -498,7 +500,14 @@ export default {
const theme = useTheme()
const themes = useThemeList()
return { theme, themes }
const route = useRoute()
const url = computed(() => route.path)
return {
theme,
themes,
url
}
},
data () {
return {
@ -521,7 +530,6 @@ export default {
computed: {
...mapState({
queue: state => state.queue,
url: state => state.route.path
}),
...mapGetters({
additionalNotifications: 'ui/additionalNotifications'

View File

@ -145,12 +145,21 @@
import Modal from '~/components/semantic/Modal.vue'
import ChannelUploadForm from '~/components/channels/UploadForm.vue'
import { humanSize } from '~/init/filters'
import {onBeforeRouteLeave, onBeforeRouteUpdate} from 'vue-router'
export default {
components: {
Modal,
ChannelUploadForm
},
setup () {
const guard = () => {
this.$store.commit('channels/showUploadModal', { show: false })
}
onBeforeRouteUpdate(guard)
onBeforeRouteLeave(guard)
},
data () {
return {
step: 1,
@ -186,11 +195,6 @@ export default {
return info
}
},
watch: {
'$store.state.route.path' () {
this.$store.commit('channels/showUploadModal', { show: false })
}
},
methods: {
update (v) {
this.$store.commit('channels/showUploadModal', { show: v })

View File

@ -77,24 +77,36 @@
<div class="row">
<router-link
v-if="$store.state.auth.authenticated"
tag="div"
class="column"
:to="{name: 'notifications'}"
role="button"
v-slot="{ navigate }"
custom
:to="{ name: 'notifications' }"
>
<i class="user-modal list-icon bell icon" />
<span class="user-modal list-item">{{ labels.notifications }}</span>
<div
class="column"
role="button"
@click="navigate"
@keypress.enter="navigate"
>
<i class="user-modal list-icon bell icon" />
<span class="user-modal list-item">{{ labels.notifications }}</span>
</div>
</router-link>
</div>
<div class="row">
<router-link
tag="div"
class="column"
v-slot="{ navigate }"
custom
:to="{ path: '/settings' }"
role="button"
>
<i class="user-modal list-icon cog icon" />
<span class="user-modal list-item">{{ labels.settings }}</span>
<div
class="column"
role="button"
@click="navigate"
@keypress.enter="navigate"
>
<i class="user-modal list-icon cog icon" />
<span class="user-modal list-item">{{ labels.settings }}</span>
</div>
</router-link>
</div>
<div class="ui divider" />
@ -121,53 +133,71 @@
</div>
<div class="row">
<router-link
tag="div"
class="column"
v-slot="{ navigate }"
custom
:to="{ name: 'about' }"
role="button"
>
<i class="user-modal list-icon question circle outline icon" />
<span class="user-modal list-item">{{ labels.about }}</span>
<div
class="column"
role="button"
@click="navigate"
@keypress.enter="navigate"
>
<i class="user-modal list-icon question circle outline icon" />
<span class="user-modal list-item">{{ labels.about }}</span>
</div>
</router-link>
</div>
<div class="ui divider" />
<template v-if="$store.state.auth.authenticated">
<router-link
tag="div"
<router-link
v-if="$store.state.auth.authenticated"
v-slot="{ navigate }"
custom
:to="{ name: 'logout' }"
>
<div
class="column"
:to="{ name: 'logout' }"
role="button"
@click="navigate"
@keypress.enter="navigate"
>
<i class="user-modal list-icon sign out alternate icon" />
<span class="user-modal list-item">{{ labels.logout }}</span>
</router-link>
</template>
<template v-if="!$store.state.auth.authenticated">
<router-link
tag="div"
</div>
</router-link>
<router-link
v-else
v-slot="{ navigate }"
custom
:to="{ name: 'login' }"
>
<div
class="column"
:to="{ name: 'login' }"
role="button"
@click="navigate"
@keypress.enter="navigate"
>
<i class="user-modal list-icon sign in alternate icon" />
<span class="user-modal list-item">{{ labels.login }}</span>
</router-link>
</template>
<template
v-if="!$store.state.auth.authenticated"
&&
$store.state.instance.settings.users.registration_enabled.value
</div>
</router-link>
<router-link
v-if="!$store.state.auth.authenticated && $store.state.instance.settings.users.registration_enabled.value"
v-slot="{ navigate }"
custom
:to="{ name: 'signup' }"
>
<router-link
tag="div"
<div
class="column"
:to="{ name: 'signup' }"
role="button"
@click="navigate"
@keypress.enter="navigate"
>
<i class="user-modal list-item user icon" />
<span class="user-modal list-item">{{ labels.signup }}</span>
</router-link>
</template>
</div>
</router-link>
</div>
</div>
</modal>

View File

@ -9,11 +9,17 @@
<td>
<router-link
v-if="notificationData.detailUrl"
tag="span"
class="link"
v-slot="{ navigate }"
custom
:to="notificationData.detailUrl"
v-html="notificationData.message"
/>
>
<span
class="link"
@click="navigate"
@keypress.enter="navigate"
v-html="notificationData.message"
/>
</router-link>
<template
v-else
v-html="notificationData.message"

View File

@ -200,12 +200,22 @@ import { mapState } from 'vuex'
import logger from '~/logging'
import Modal from '~/components/semantic/Modal.vue'
import PlaylistForm from '~/components/playlists/Form.vue'
import { onBeforeRouteLeave, onBeforeRouteUpdate } from 'vue-router'
export default {
components: {
Modal,
PlaylistForm
},
setup () {
const guard = () => {
this.$store.commit('playlists/showModal', false)
this.showDuplicateTrackAddConfirmation = false
}
onBeforeRouteUpdate(guard)
onBeforeRouteLeave(guard)
},
data () {
return {
formKey: String(new Date()),
@ -238,10 +248,6 @@ export default {
}
},
watch: {
'$store.state.route.path' () {
this.$store.commit('playlists/showModal', false)
this.showDuplicateTrackAddConfirmation = false
},
'$store.state.playlists.showModal' () {
this.formKey = String(new Date())
this.showDuplicateTrackAddConfirmation = false

View File

@ -2,21 +2,14 @@ import logger from '~/logging'
import router from '~/router'
import VueLazyload from 'vue-lazyload'
import store from '~/store'
import { sync } from 'vuex-router-sync'
import Vue, { createApp } from 'vue'
import { createApp } from 'vue'
import useTheme from '~/composables/useTheme'
useTheme()
Vue.config.devtools = true
logger.default.info('Loading environment:', import.meta.env.MODE)
logger.default.debug('Environment variables:', import.meta.env)
sync(store, router)
const app = createApp({
store,
router,
components: {
App: () => import('~/App.vue')
},
@ -34,6 +27,8 @@ const app = createApp({
}
})
app.use(router)
app.use(store)
app.use(VueLazyload)
const modules: Promise<unknown>[] = []

View File

@ -1,9 +1,6 @@
import Vue from 'vue'
import Router from 'vue-router'
import {createRouter, createWebHistory} from 'vue-router'
import store from '~/store'
Vue.use(Router)
function adminPermissions (to, from, next) {
if (store.state.auth.authenticated === true && store.state.auth.availablePermissions.settings === true) {
next()
@ -32,10 +29,9 @@ function libraryPermissions (to, from, next) {
}
console.log('PROCESS', import.meta.env)
export default new Router({
mode: 'history',
export default createRouter({
history: createWebHistory(import.meta.env.VUE_APP_ROUTER_BASE_URL as string ?? '/'),
linkActiveClass: 'active',
base: import.meta.env.VUE_APP_ROUTER_BASE_URL || '/',
scrollBehavior (to, from, savedPosition) {
if (to.meta.preserveScrollPosition) {
return savedPosition
@ -1018,11 +1014,11 @@ export default new Router({
)
},
{
path: '*/index.html',
path: '/index.html',
redirect: '/'
},
{
path: '*',
path: '/:pathMatch(.*)*',
name: '404',
component: () =>
import('~/components/PageNotFound.vue')

View File

@ -1,5 +1,4 @@
import Vue from 'vue'
import Vuex, { Store } from 'vuex'
import { createStore, Store } from 'vuex'
import createPersistedState from 'vuex-persistedstate'
import favorites from './favorites'
@ -14,9 +13,7 @@ import player from './player'
import playlists from './playlists'
import ui from './ui'
Vue.use(Vuex)
export default <Store<any>> new Vuex.Store({
export default <Store<any>> createStore({
modules: {
ui,
auth,

View File

@ -46,11 +46,24 @@ import axios from 'axios'
import $ from 'jquery'
import SettingsGroup from '~/components/admin/SettingsGroup.vue'
import { nextTick } from 'vue'
import { useRoute } from 'vue-router'
export default {
components: {
SettingsGroup
},
async setup () {
await this.fetchSettings()
await nextTick()
const route = useRoute()
if (route.hash) {
this.scrollTo(route.hash.slice(1))
}
$('select.dropdown').dropdown()
},
data () {
return {
isLoading: false,
@ -189,23 +202,12 @@ export default {
})
}
},
created () {
const self = this
this.fetchSettings().then(r => {
self.$nextTick(() => {
if (self.$store.state.route.hash) {
self.scrollTo(self.$store.state.route.hash.substr(1))
}
$('select.dropdown').dropdown()
})
})
},
methods: {
scrollTo (id) {
this.current = id
document.getElementById(id).scrollIntoView()
},
fetchSettings () {
async fetchSettings () {
const self = this
self.isLoading = true
return axios.get('instance/admin/settings/').then(response => {

View File

@ -1,3 +1,28 @@
<script setup lang="ts">
import LoginForm from '~/components/auth/LoginForm.vue'
import { useRouter } from 'vue-router'
import { computed } from 'vue'
import { useGettext } from 'vue3-gettext'
import { useStore } from 'vuex'
const { $pgettext } = useGettext()
const labels = computed(() => ({
title: $pgettext('Head/Login/Title', 'Log In')
}))
const props = withDefaults(
defineProps<{ next?: string }>(),
{ next: '/library' }
)
const store = useStore()
if (store.state.auth.authenticated) {
const router = useRouter()
const resolved = router.resolve(props.next)
router.push(resolved.name === '404' ? '/library' : props.next)
}
</script>
<template>
<main
v-title="labels.title"
@ -15,39 +40,3 @@
</section>
</main>
</template>
<script>
import LoginForm from '~/components/auth/LoginForm.vue'
export default {
components: {
LoginForm
},
props: {
next: { type: String, default: '/library' }
},
data () {
return {
redirectTo: this.next
}
},
computed: {
labels () {
const title = this.$pgettext('Head/Login/Title', 'Log In')
return {
title
}
}
},
created () {
const resolved = this.$router.resolve(this.redirectTo)
console.log(resolved.route.name)
if (resolved.route.name === '404') {
this.redirectTo = '/library'
}
if (this.$store.state.auth.authenticated) {
this.$router.push(this.redirectTo)
}
}
}
</script>

View File

@ -1858,7 +1858,7 @@
"@vue/compiler-dom" "3.2.38"
"@vue/shared" "3.2.38"
"@vue/devtools-api@^6.2.1":
"@vue/devtools-api@^6.0.0", "@vue/devtools-api@^6.0.0-beta.11", "@vue/devtools-api@^6.2.1":
version "6.2.1"
resolved "https://registry.yarnpkg.com/@vue/devtools-api/-/devtools-api-6.2.1.tgz#6f2948ff002ec46df01420dfeff91de16c5b4092"
integrity sha512-OEgAMeQXvCoJ+1x8WyQuVZzFo0wcyCmUR3baRVLmKBo1LmYZWMlRiXlux5jd0fqVJu6PfDbOrZItVqUEzLobeQ==
@ -6748,10 +6748,12 @@ vue-plyr@7.0.0:
plyr "github:sampotts/plyr#develop"
vue "^2.6.12"
vue-router@3.5.4:
version "3.5.4"
resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-3.5.4.tgz#c453c0b36bc75554de066fefc3f2a9c3212aca70"
integrity sha512-x+/DLAJZv2mcQ7glH2oV9ze8uPwcI+H+GgTgTmb5I55bCgY3+vXWIsqbYUzbBSZnwFHEJku4eoaH/x98veyymQ==
vue-router@4.0.14:
version "4.0.14"
resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-4.0.14.tgz#ce2028c1c5c33e30c7287950c973f397fce1bd65"
integrity sha512-wAO6zF9zxA3u+7AkMPqw9LjoUCjSxfFvINQj3E/DceTt6uEz1XZLraDhdg2EYmvVwTBSGlLYsUw8bDmx0754Mw==
dependencies:
"@vue/devtools-api" "^6.0.0"
vue-template-compiler@2.6.14:
version "2.6.14"
@ -6823,10 +6825,12 @@ vuex-router-sync@5.0.0:
resolved "https://registry.yarnpkg.com/vuex-router-sync/-/vuex-router-sync-5.0.0.tgz#1a225c17a1dd9e2f74af0a1b2c62072e9492b305"
integrity sha512-Mry2sO4kiAG64714X1CFpTA/shUH1DmkZ26DFDtwoM/yyx6OtMrc+MxrU+7vvbNLO9LSpgwkiJ8W+rlmRtsM+w==
vuex@3.6.2:
version "3.6.2"
resolved "https://registry.yarnpkg.com/vuex/-/vuex-3.6.2.tgz#236bc086a870c3ae79946f107f16de59d5895e71"
integrity sha512-ETW44IqCgBpVomy520DT5jf8n0zoCac+sxWnn+hMe/CzaSejb/eVw2YToiXYX+Ex/AuHHia28vWTq4goAexFbw==
vuex@4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/vuex/-/vuex-4.0.2.tgz#f896dbd5bf2a0e963f00c67e9b610de749ccacc9"
integrity sha512-M6r8uxELjZIK8kTKDGgZTYX/ahzblnzC4isU1tpmEuOIIKmV+TRdc+H4s8ds2NuZ7wpUTdGRzJRtoj+lI+pc0Q==
dependencies:
"@vue/devtools-api" "^6.0.0-beta.11"
w3c-hr-time@^1.0.2:
version "1.0.2"