merge and externalize breadcrumb computation into the store

This commit is contained in:
axolotle 2022-02-06 21:03:31 +01:00
parent 4531433d60
commit b3e1860b6a
4 changed files with 60 additions and 72 deletions

View file

@ -1,13 +1,13 @@
<template> <template>
<b-breadcrumb v-if="routesList"> <b-breadcrumb v-if="breadcrumb.length">
<b-breadcrumb-item to="/"> <b-breadcrumb-item to="/">
<span class="sr-only">{{ $t('home') }}</span> <span class="sr-only">{{ $t('home') }}</span>
<icon iname="home" /> <icon iname="home" />
</b-breadcrumb-item> </b-breadcrumb-item>
<b-breadcrumb-item <b-breadcrumb-item
v-for="{ name, text } in breadcrumb" :key="name" v-for="({ name, text }, i) in breadcrumb" :key="name"
:to="{ name }" :active="name === $route.name" :to="{ name }" :active="i === breadcrumb.length - 1"
> >
{{ text }} {{ text }}
</b-breadcrumb-item> </b-breadcrumb-item>
@ -15,41 +15,13 @@
</template> </template>
<script> <script>
import { mapGetters } from 'vuex'
export default { export default {
name: 'Breadcrumb', name: 'Breadcrumb',
computed: { computed: {
routesList () { ...mapGetters(['breadcrumb'])
const routesList = this.$route.meta.breadcrumb
return routesList && routesList.length ? routesList : null
},
breadcrumb () {
if (!this.routesList) return
// Get current params to pass it to potential previous routes
const currentParams = this.$route.params
return this.routesList.map(name => {
const { trad, param } = this.getRouteArgs(name)
let text = ''
// if a traduction key string has been given and we also need to pass
// the route param as a variable.
if (trad && param) {
text = this.$i18n.t(trad, { [param]: currentParams[param] })
} else if (trad) {
text = this.$i18n.t(trad)
} else {
text = currentParams[param]
}
return { name, text }
})
}
},
methods: {
getRouteArgs (routeName) {
const route = this.$router.options.routes.find(route => route.name === routeName)
return route ? route.meta.args : {}
}
} }
} }
</script> </script>

View file

@ -1,6 +1,5 @@
import Vue from 'vue' import Vue from 'vue'
import VueRouter from 'vue-router' import VueRouter from 'vue-router'
import i18n from '@/i18n'
import routes from './routes' import routes from './routes'
import store from '@/store' import store from '@/store'
@ -30,6 +29,7 @@ const router = new VueRouter({
router.beforeEach((to, from, next) => { router.beforeEach((to, from, next) => {
store.dispatch('UPDATE_ROUTER_KEY', { to, from }) store.dispatch('UPDATE_ROUTER_KEY', { to, from })
store.dispatch('UPDATE_BREADCRUMB', { to, from })
if (store.getters.error) { if (store.getters.error) {
store.dispatch('DISMISS_ERROR', true) store.dispatch('DISMISS_ERROR', true)
} }
@ -41,30 +41,4 @@ router.beforeEach((to, from, next) => {
} }
}) })
router.afterEach((to, from) => {
// Display a simplified breadcrumb as the document title.
const routeParams = to.params
let breadcrumb = to.meta.breadcrumb
if (breadcrumb.length === 0) {
breadcrumb = [to.name]
} else if (breadcrumb.length > 2) {
breadcrumb = breadcrumb.slice(breadcrumb.length - 2)
}
const title = breadcrumb.map(name => {
const route = routes.find(route => route.name === name)
const { trad, param } = route ? route.meta.args : {}
// if a traduction key string has been given and we also need to pass
// the route param as a variable.
if (trad && param) {
return i18n.t(trad, { [param]: routeParams[param] })
} else if (trad) {
return i18n.t(trad)
}
return routeParams[param]
}).reverse().join(' / ')
document.title = `${title} | ${i18n.t('yunohost_admin')}`
})
export default router export default router

View file

@ -17,10 +17,8 @@ const routes = [
name: 'home', name: 'home',
path: '/', path: '/',
component: Home, component: Home,
// Leave the empty breadcrumb as it is used by the animated transition to know which way to go
meta: { meta: {
args: { trad: 'home' }, args: { trad: 'home' }
breadcrumb: []
} }
}, },
@ -30,8 +28,7 @@ const routes = [
component: Login, component: Login,
meta: { meta: {
noAuth: true, noAuth: true,
args: { trad: 'login' }, args: { trad: 'login' }
breadcrumb: []
} }
}, },
@ -42,11 +39,9 @@ const routes = [
name: 'post-install', name: 'post-install',
path: '/postinstall', path: '/postinstall',
component: () => import(/* webpackChunkName: "views/post-install" */ '@/views/PostInstall'), component: () => import(/* webpackChunkName: "views/post-install" */ '@/views/PostInstall'),
// Leave the breadcrumb
meta: { meta: {
noAuth: true, noAuth: true,
args: { trad: 'postinstall.title' }, args: { trad: 'postinstall.title' }
breadcrumb: []
} }
}, },

View file

@ -16,7 +16,8 @@ export default {
error: null, // null || request error: null, // null || request
historyTimer: null, // null || setTimeout id historyTimer: null, // null || setTimeout id
tempMessages: [], // Array of messages tempMessages: [], // Array of messages
routerKey: undefined // String if current route has params routerKey: undefined, // String if current route has params
breadcrumb: [] // Array of routes
}, },
mutations: { mutations: {
@ -92,6 +93,10 @@ export default {
'SET_ROUTER_KEY' (state, key) { 'SET_ROUTER_KEY' (state, key) {
state.routerKey = key state.routerKey = key
},
'SET_BREADCRUMB' (state, breadcrumb) {
state.breadcrumb = breadcrumb
} }
}, },
@ -287,6 +292,47 @@ export default {
: Object.values(to.params) : Object.values(to.params)
commit('SET_ROUTER_KEY', `${to.name}-${params.join('-')}`) commit('SET_ROUTER_KEY', `${to.name}-${params.join('-')}`)
},
'UPDATE_BREADCRUMB' ({ commit }, { to, from }) {
function getRouteNames (route) {
if (route.meta.breadcrumb) return route.meta.breadcrumb
const parentRoute = route.matched.slice().reverse().find(route => route.meta.breadcrumb)
if (parentRoute) return parentRoute.meta.breadcrumb
return []
}
function formatRoute (route) {
const { trad, param } = route.meta.args || {}
let text = ''
// if a traduction key string has been given and we also need to pass
// the route param as a variable.
if (trad && param) {
text = i18n.t(trad, { [param]: to.params[param] })
} else if (trad) {
text = i18n.t(trad)
} else {
text = to.params[param]
}
return { name: route.name, text }
}
const routeNames = getRouteNames(to)
const allRoutes = router.getRoutes()
const breadcrumb = routeNames.map(name => {
const route = allRoutes.find(route => route.name === name)
return formatRoute(route)
})
commit('SET_BREADCRUMB', breadcrumb)
function getTitle (breadcrumb) {
if (breadcrumb.length === 0) return formatRoute(to).text
return (breadcrumb.length > 2 ? breadcrumb.slice(-2) : breadcrumb).map(route => route.text).reverse().join(' / ')
}
// Display a simplified breadcrumb as the document title.
document.title = `${getTitle(breadcrumb)} | ${i18n.t('yunohost_admin')}`
} }
}, },
@ -303,6 +349,7 @@ export default {
const request = state.requests.find(({ status }) => status === 'pending') const request = state.requests.find(({ status }) => status === 'pending')
return request || state.requests[state.requests.length - 1] return request || state.requests[state.requests.length - 1]
}, },
routerKey: state => state.routerKey routerKey: state => state.routerKey,
breadcrumb: state => state.breadcrumb
} }
} }