From dc0868262e37bd457a22254702c49ba5ce530aa7 Mon Sep 17 00:00:00 2001 From: axolotle Date: Sun, 6 Feb 2022 20:07:28 +0100 Subject: [PATCH 01/12] rename TabForm to AbstractForm --- app/src/components/globals/{TabForm.vue => AbstractForm.vue} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename app/src/components/globals/{TabForm.vue => AbstractForm.vue} (100%) diff --git a/app/src/components/globals/TabForm.vue b/app/src/components/globals/AbstractForm.vue similarity index 100% rename from app/src/components/globals/TabForm.vue rename to app/src/components/globals/AbstractForm.vue From c17834799081e760407b68ca8401ba764d55234e Mon Sep 17 00:00:00 2001 From: axolotle Date: Sun, 6 Feb 2022 20:31:53 +0100 Subject: [PATCH 02/12] update AbstractForm to be more generic --- app/src/components/globals/AbstractForm.vue | 30 +++++++++------------ 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/app/src/components/globals/AbstractForm.vue b/app/src/components/globals/AbstractForm.vue index 2d8c3d7a..77c4e78d 100644 --- a/app/src/components/globals/AbstractForm.vue +++ b/app/src/components/globals/AbstractForm.vue @@ -1,40 +1,37 @@ From 7d5d29af1e7e23b9c62e900f1ca76e0bc2f2ca83 Mon Sep 17 00:00:00 2001 From: axolotle Date: Sun, 6 Feb 2022 20:40:07 +0100 Subject: [PATCH 04/12] add ConfigPanel component to display a specific panel (can be used as a view) --- app/src/components/ConfigPanel.vue | 70 ++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 app/src/components/ConfigPanel.vue diff --git a/app/src/components/ConfigPanel.vue b/app/src/components/ConfigPanel.vue new file mode 100644 index 00000000..be92c993 --- /dev/null +++ b/app/src/components/ConfigPanel.vue @@ -0,0 +1,70 @@ + + + + + From b7aa8117ece373bf50e352d398f48a60e2f4a5ae Mon Sep 17 00:00:00 2001 From: axolotle Date: Sun, 6 Feb 2022 20:42:28 +0100 Subject: [PATCH 05/12] update ConfigPanels using RoutableTabs --- app/src/components/ConfigPanels.vue | 73 +++++++++++------------------ 1 file changed, 28 insertions(+), 45 deletions(-) diff --git a/app/src/components/ConfigPanels.vue b/app/src/components/ConfigPanels.vue index d77f5459..ff8aa820 100644 --- a/app/src/components/ConfigPanels.vue +++ b/app/src/components/ConfigPanels.vue @@ -1,67 +1,50 @@ diff --git a/app/src/router/index.js b/app/src/router/index.js index 86295d51..7873dbe9 100644 --- a/app/src/router/index.js +++ b/app/src/router/index.js @@ -1,6 +1,5 @@ import Vue from 'vue' import VueRouter from 'vue-router' -import i18n from '@/i18n' import routes from './routes' import store from '@/store' @@ -30,6 +29,7 @@ const router = new VueRouter({ router.beforeEach((to, from, next) => { store.dispatch('UPDATE_ROUTER_KEY', { to, from }) + store.dispatch('UPDATE_BREADCRUMB', { to, from }) if (store.getters.error) { 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 diff --git a/app/src/router/routes.js b/app/src/router/routes.js index 518594f5..2f705404 100644 --- a/app/src/router/routes.js +++ b/app/src/router/routes.js @@ -17,10 +17,8 @@ const routes = [ name: 'home', path: '/', component: Home, - // Leave the empty breadcrumb as it is used by the animated transition to know which way to go meta: { - args: { trad: 'home' }, - breadcrumb: [] + args: { trad: 'home' } } }, @@ -30,8 +28,7 @@ const routes = [ component: Login, meta: { noAuth: true, - args: { trad: 'login' }, - breadcrumb: [] + args: { trad: 'login' } } }, @@ -42,12 +39,10 @@ const routes = [ name: 'post-install', path: '/postinstall', component: () => import(/* webpackChunkName: "views/post-install" */ '@/views/PostInstall'), - // Leave the breadcrumb meta: { noAuth: true, - args: { trad: 'postinstall.title' }, - breadcrumb: [] - } + args: { trad: 'postinstall.title' } + } }, /* ───────╮ diff --git a/app/src/store/info.js b/app/src/store/info.js index 41aade6f..f557fe1c 100644 --- a/app/src/store/info.js +++ b/app/src/store/info.js @@ -16,7 +16,8 @@ export default { error: null, // null || request historyTimer: null, // null || setTimeout id 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: { @@ -92,6 +93,10 @@ export default { 'SET_ROUTER_KEY' (state, key) { state.routerKey = key + }, + + 'SET_BREADCRUMB' (state, breadcrumb) { + state.breadcrumb = breadcrumb } }, @@ -287,6 +292,47 @@ export default { : Object.values(to.params) 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') return request || state.requests[state.requests.length - 1] }, - routerKey: state => state.routerKey + routerKey: state => state.routerKey, + breadcrumb: state => state.breadcrumb } } From fa63687cd6b7b8c5bafa9c9bcdb9e304604d22ad Mon Sep 17 00:00:00 2001 From: axolotle Date: Sun, 6 Feb 2022 21:04:53 +0100 Subject: [PATCH 11/12] externalize main RouterLink transition name computation to store --- app/src/App.vue | 18 +----------------- app/src/router/index.js | 4 ++++ app/src/store/info.js | 17 +++++++++++++++-- 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/app/src/App.vue b/app/src/App.vue index b320c6d6..f205e207 100644 --- a/app/src/App.vue +++ b/app/src/App.vue @@ -86,33 +86,17 @@ export default { ViewLockOverlay }, - data () { - return { - transitionName: null - } - }, - computed: { ...mapGetters([ 'connected', 'yunohost', 'routerKey', 'transitions', + 'transitionName', 'waiting' ]) }, - watch: { - // Set the css class to animate the components transition - '$route' (to, from) { - if (!this.transitions || from.name === null) return - // Use the breadcrumb array length as a direction indicator - const toDepth = to.meta.breadcrumb.length - const fromDepth = from.meta.breadcrumb.length - this.transitionName = toDepth < fromDepth ? 'slide-right' : 'slide-left' - } - }, - methods: { async logout () { this.$store.dispatch('LOGOUT') diff --git a/app/src/router/index.js b/app/src/router/index.js index 7873dbe9..9530f8f9 100644 --- a/app/src/router/index.js +++ b/app/src/router/index.js @@ -30,6 +30,10 @@ const router = new VueRouter({ router.beforeEach((to, from, next) => { store.dispatch('UPDATE_ROUTER_KEY', { to, from }) store.dispatch('UPDATE_BREADCRUMB', { to, from }) + if (store.getters.transitions && from.name !== null) { + store.dispatch('UPDATE_TRANSITION_NAME', { to, from }) + } + if (store.getters.error) { store.dispatch('DISMISS_ERROR', true) } diff --git a/app/src/store/info.js b/app/src/store/info.js index f557fe1c..1304c1ed 100644 --- a/app/src/store/info.js +++ b/app/src/store/info.js @@ -17,7 +17,8 @@ export default { historyTimer: null, // null || setTimeout id tempMessages: [], // Array of messages routerKey: undefined, // String if current route has params - breadcrumb: [] // Array of routes + breadcrumb: [], // Array of routes + transitionName: null // String of CSS class if transitions are enabled }, mutations: { @@ -97,6 +98,10 @@ export default { 'SET_BREADCRUMB' (state, breadcrumb) { state.breadcrumb = breadcrumb + }, + + 'SET_TRANSITION_NAME' (state, transitionName) { + state.transitionName = transitionName } }, @@ -333,6 +338,13 @@ export default { // Display a simplified breadcrumb as the document title. document.title = `${getTitle(breadcrumb)} | ${i18n.t('yunohost_admin')}` + }, + + 'UPDATE_TRANSITION_NAME' ({ state, commit }, { to, from }) { + // Use the breadcrumb array length as a direction indicator + const toDepth = (to.meta.breadcrumb || []).length + const fromDepth = (from.meta.breadcrumb || []).length + commit('SET_TRANSITION_NAME', toDepth < fromDepth ? 'slide-right' : 'slide-left') } }, @@ -350,6 +362,7 @@ export default { return request || state.requests[state.requests.length - 1] }, routerKey: state => state.routerKey, - breadcrumb: state => state.breadcrumb + breadcrumb: state => state.breadcrumb, + transitionName: state => state.transitionName } } From 19d8ebb4a69e4e8b72a27e74ad5f8c7fc6f41da0 Mon Sep 17 00:00:00 2001 From: axolotle Date: Mon, 7 Feb 2022 04:42:03 +0100 Subject: [PATCH 12/12] fix weird bug by updating routerKey on router "afterEach" hook --- app/src/router/index.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/src/router/index.js b/app/src/router/index.js index 9530f8f9..9a4e2b85 100644 --- a/app/src/router/index.js +++ b/app/src/router/index.js @@ -28,8 +28,6 @@ const router = new VueRouter({ }) router.beforeEach((to, from, next) => { - store.dispatch('UPDATE_ROUTER_KEY', { to, from }) - store.dispatch('UPDATE_BREADCRUMB', { to, from }) if (store.getters.transitions && from.name !== null) { store.dispatch('UPDATE_TRANSITION_NAME', { to, from }) } @@ -45,4 +43,9 @@ router.beforeEach((to, from, next) => { } }) +router.afterEach((to, from) => { + store.dispatch('UPDATE_ROUTER_KEY', { to, from }) + store.dispatch('UPDATE_BREADCRUMB', { to, from }) +}) + export default router