diff --git a/src/mixins/HomeMixin.js b/src/mixins/HomeMixin.js index 97c249f1..ea855c6f 100644 --- a/src/mixins/HomeMixin.js +++ b/src/mixins/HomeMixin.js @@ -36,7 +36,7 @@ const HomeMixin = { searchValue: '', }), async mounted() { - await this.getConfigForRoute(); + // await this.getConfigForRoute(); }, watch: { async $route() { @@ -44,15 +44,27 @@ const HomeMixin = { this.setTheme(); }, }, + async created() { + // console.log(this.$router.currentRoute.path); + const subPage = this.determineConfigFile(); + await this.$store.dispatch(Keys.INITIALIZE_CONFIG, subPage); + }, methods: { - async getConfigForRoute() { - this.$store.commit(Keys.SET_CURRENT_SUB_PAGE, this.subPageInfo); - if (this.subPageInfo && this.subPageInfo.confPath) { // Get config for sub-page - await this.$store.dispatch(Keys.INITIALIZE_MULTI_PAGE_CONFIG, this.subPageInfo.confPath); - } else { // Otherwise, use main config - this.$store.commit(Keys.USE_MAIN_CONFIG); - } + /* Based on the current route, get which config to display, null will use default */ + determineConfigFile() { + const pagePath = this.$router.currentRoute.path; + const isSubPage = new RegExp((/(home|workspace|minimal)\/[a-zA-Z0-9-]+/g)).test(pagePath); + const subPageName = isSubPage ? pagePath.split('/').pop() : null; + return subPageName; }, + // async getConfigForRoute() { + // this.$store.commit(Keys.SET_CURRENT_SUB_PAGE, this.subPageInfo); + // if (this.subPageInfo && this.subPageInfo.confPath) { // Get config for sub-page + // await this.$store.dispatch(Keys.INITIALIZE_MULTI_PAGE_CONFIG, this.subPageInfo.confPath); + // } else { // Otherwise, use main config + // this.$store.commit(Keys.USE_MAIN_CONFIG); + // } + // }, /* TEMPORARY: If on sub-page, check if custom theme is set and return it */ getSubPageTheme() { if (!this.pageId || this.pageId === 'home') { diff --git a/src/router.js b/src/router.js index 904eafef..5fbb12ea 100644 --- a/src/router.js +++ b/src/router.js @@ -14,7 +14,7 @@ import Home from '@/views/Home.vue'; // Import helper functions, config data and defaults import { isAuthEnabled, isLoggedIn, isGuestAccessEnabled } from '@/utils/Auth'; -import { makePageSlug, makePageName } from '@/utils/ConfigHelpers'; +// import { makePageSlug, makePageName } from '@/utils/ConfigHelpers'; import { metaTagData, startingView, routePaths } from '@/utils/defaults'; import ErrorHandler from '@/utils/ErrorHandler'; @@ -27,7 +27,7 @@ if (!conf) { // Assign top-level config fields, check not null const config = conf || {}; -const pages = config.pages || []; +// const pages = config.pages || []; const pageInfo = config.pageInfo || {}; const appConfig = config.appConfig || {}; @@ -64,54 +64,54 @@ const makeMetaTags = (defaultTitle) => ({ metaTags: metaTagData, }); -const makeSubConfigPath = (rawPath) => { - if (!rawPath) return ''; - if (rawPath.startsWith('/') || rawPath.startsWith('http')) return rawPath; - else return `/${rawPath}`; -}; +// const makeSubConfigPath = (rawPath) => { +// if (!rawPath) return ''; +// if (rawPath.startsWith('/') || rawPath.startsWith('http')) return rawPath; +// else return `/${rawPath}`; +// }; /* For each additional config file, create routes for home, minimal and workspace views */ -const makeMultiPageRoutes = (userPages) => { - // If no multi pages specified, or is not array, then return nothing - if (!userPages || !Array.isArray(userPages)) return []; - const multiPageRoutes = []; - // For each user page, create an additional route - userPages.forEach((page) => { - if (!page.name || !page.path) { // Sumin not right, show warning - ErrorHandler('Additional pages must have both a `name` and `path`'); - } - // Props to be passed to home mixin - const subPageInfo = { - subPageInfo: { - confPath: makeSubConfigPath(page.path), - pageId: makePageName(page.name), - pageTitle: page.name, - }, - }; - // Create route for default homepage - multiPageRoutes.push({ - path: makePageSlug(page.name, 'home'), - name: `${subPageInfo.subPageInfo.pageId}-home`, - component: Home, - props: subPageInfo, - }); - // Create route for the workspace view - multiPageRoutes.push({ - path: makePageSlug(page.name, 'workspace'), - name: `${subPageInfo.subPageInfo.pageId}-workspace`, - component: () => import('./views/Workspace.vue'), - props: subPageInfo, - }); - // Create route for the minimal view - multiPageRoutes.push({ - path: makePageSlug(page.name, 'minimal'), - name: `${subPageInfo.subPageInfo.pageId}-minimal`, - component: () => import('./views/Minimal.vue'), - props: subPageInfo, - }); - }); - return multiPageRoutes; -}; +// const makeMultiPageRoutes = (userPages) => { +// // If no multi pages specified, or is not array, then return nothing +// if (!userPages || !Array.isArray(userPages)) return []; +// const multiPageRoutes = []; +// // For each user page, create an additional route +// userPages.forEach((page) => { +// if (!page.name || !page.path) { // Sumin not right, show warning +// ErrorHandler('Additional pages must have both a `name` and `path`'); +// } +// // Props to be passed to home mixin +// const subPageInfo = { +// subPageInfo: { +// confPath: makeSubConfigPath(page.path), +// pageId: makePageName(page.name), +// pageTitle: page.name, +// }, +// }; +// // Create route for default homepage +// multiPageRoutes.push({ +// path: makePageSlug(page.name, 'home'), +// name: `${subPageInfo.subPageInfo.pageId}-home`, +// component: Home, +// props: subPageInfo, +// }); +// // Create route for the workspace view +// multiPageRoutes.push({ +// path: makePageSlug(page.name, 'workspace'), +// name: `${subPageInfo.subPageInfo.pageId}-workspace`, +// component: () => import('./views/Workspace.vue'), +// props: subPageInfo, +// }); +// // Create route for the minimal view +// multiPageRoutes.push({ +// path: makePageSlug(page.name, 'minimal'), +// name: `${subPageInfo.subPageInfo.pageId}-minimal`, +// component: () => import('./views/Minimal.vue'), +// props: subPageInfo, +// }); +// }); +// return multiPageRoutes; +// }; /* Routing mode, can be either 'hash', 'history' or 'abstract' */ const mode = appConfig.routingMode || 'history'; @@ -120,7 +120,7 @@ const mode = appConfig.routingMode || 'history'; const router = new Router({ mode, routes: [ - ...makeMultiPageRoutes(pages), + // ...makeMultiPageRoutes(pages), { // The default view can be customized by the user path: '/', name: `landing-page-${getStartingView()}`, diff --git a/src/store.js b/src/store.js index d6c4353b..28c3d2e0 100644 --- a/src/store.js +++ b/src/store.js @@ -4,7 +4,7 @@ import Vuex from 'vuex'; import axios from 'axios'; import yaml from 'js-yaml'; import Keys from '@/utils/StoreMutations'; -import ConfigAccumulator from '@/utils/ConfigAccumalator'; +// import ConfigAccumulator from '@/utils/ConfigAccumalator'; import { componentVisibility } from '@/utils/ConfigHelpers'; import { applyItemId } from '@/utils/SectionHelpers'; import filterUserSections from '@/utils/CheckSectionVisibility'; @@ -16,8 +16,10 @@ Vue.use(Vuex); const { INITIALIZE_CONFIG, - INITIALIZE_MULTI_PAGE_CONFIG, + INITIALIZE_ROOT_CONFIG, + // INITIALIZE_MULTI_PAGE_CONFIG, SET_CONFIG, + SET_ROOT_CONFIG, SET_REMOTE_CONFIG, SET_CURRENT_SUB_PAGE, SET_MODAL_OPEN, @@ -46,7 +48,8 @@ const { const store = new Vuex.Store({ state: { config: {}, // The current config, rendered to the UI - remoteConfig: {}, // The configuration stored on the server + rootConfig: null, // The config from the main config file + // remoteConfig: {}, // The configuration stored on the server editMode: false, // While true, the user can drag and edit items + sections modalOpen: false, // KB shortcut functionality will be disabled when modal is open currentConfigInfo: undefined, // For multi-page support, will store info about config file @@ -68,7 +71,7 @@ const store = new Vuex.Store({ return filterUserSections(state.config.sections || []); }, pages(state) { - return state.remoteConfig.pages || []; + return state.config.pages || []; }, theme(state) { let localTheme = null; @@ -145,6 +148,10 @@ const store = new Vuex.Store({ }, }, mutations: { + [SET_ROOT_CONFIG](state, config) { + if (!config.appConfig) config.appConfig = {}; + state.config = config; + }, [SET_CONFIG](state, config) { if (!config.appConfig) config.appConfig = {}; state.config = config; @@ -323,24 +330,43 @@ const store = new Vuex.Store({ }, actions: { /* Called when app first loaded. Reads config and sets state */ - async [INITIALIZE_CONFIG]({ commit }) { - // Get the config file from the server and store it for use by the accumulator - commit(SET_REMOTE_CONFIG, yaml.load((await axios.get('/conf.yml')).data)); - const deepCopy = (json) => JSON.parse(JSON.stringify(json)); - const config = deepCopy(new ConfigAccumulator().config()); - commit(SET_CONFIG, config); + // async [INITIALIZE_CONFIG]({ commit }) { + // // Get the config file from the server and store it for use by the accumulator + // commit(SET_REMOTE_CONFIG, yaml.load((await axios.get('/conf.yml')).data)); + // const deepCopy = (json) => JSON.parse(JSON.stringify(json)); + // const config = deepCopy(new ConfigAccumulator().config()); + // commit(SET_CONFIG, config); + // }, + /* Fetches the root config file, only ever called by INITIALIZE_CONFIG */ + async [INITIALIZE_ROOT_CONFIG]({ commit }) { + console.log('Initializing root config....'); + commit(SET_ROOT_CONFIG, yaml.load((await axios.get('/conf.yml')).data)); }, - /* Fetch config for a sub-page (sections and pageInfo only) */ - async [INITIALIZE_MULTI_PAGE_CONFIG]({ commit, state }, configPath) { - axios.get(configPath).then((response) => { - const subConfig = yaml.load(response.data); - const pageTheme = subConfig.appConfig?.theme; - subConfig.appConfig = state.config.appConfig; // Always use parent appConfig - if (pageTheme) subConfig.appConfig.theme = pageTheme; // Apply page theme override - commit(SET_CONFIG, subConfig); - }).catch((err) => { - ErrorHandler(`Unable to load config from '${configPath}'`, err); - }); + /** + * Fetches config and updates state + * If not on sub-page, will trigger the fetch of main config, then use that + * If using sub-page config, then fetch that sub-config, then + * override certain fields (appConfig, pages) and update config + */ + async [INITIALIZE_CONFIG]({ commit, state }, subConfigPath) { + const fetchPath = subConfigPath || '/conf.yml'; // The path to fetch config from + if (!state.rootConfig) { + await this.dispatch(Keys.INITIALIZE_ROOT_CONFIG); + } + console.log('rootConfig', state.rootConfig); + if (!subConfigPath) { // Use root config as config + commit(SET_CONFIG, state.rootConfig); + } else { // Fetch sub-config, and use as config + axios.get(fetchPath).then((response) => { + const configContent = yaml.load(response.data); + // Certain values must be inherited from root config + configContent.appConfig = state.rootConfig.appConfig; + configContent.pages = state.rootConfig.pages; + commit(SET_CONFIG, configContent); + }).catch((err) => { + ErrorHandler(`Unable to load config from '${fetchPath}'`, err); + }); + } }, }, modules: {}, diff --git a/src/utils/ConfigAccumalator.js b/src/utils/ConfigAccumalator.js index 76fefb62..7f83e28b 100644 --- a/src/utils/ConfigAccumalator.js +++ b/src/utils/ConfigAccumalator.js @@ -20,7 +20,7 @@ import buildConf from '../../public/conf.yml'; export default class ConfigAccumulator { constructor() { - this.conf = $store.state.remoteConfig; + this.conf = $store.state.config; } pages() { diff --git a/src/utils/StoreMutations.js b/src/utils/StoreMutations.js index 23448a1f..c9c1c68d 100644 --- a/src/utils/StoreMutations.js +++ b/src/utils/StoreMutations.js @@ -1,8 +1,10 @@ // A list of mutation names const KEY_NAMES = [ 'INITIALIZE_CONFIG', + 'INITIALIZE_ROOT_CONFIG', 'INITIALIZE_MULTI_PAGE_CONFIG', 'SET_CONFIG', + 'SET_ROOT_CONFIG', 'SET_REMOTE_CONFIG', 'SET_CURRENT_SUB_PAGE', 'SET_MODAL_OPEN', diff --git a/src/utils/defaults.js b/src/utils/defaults.js index 273dde06..62889e8c 100644 --- a/src/utils/defaults.js +++ b/src/utils/defaults.js @@ -28,9 +28,9 @@ module.exports = { openingMethod: 'newtab', /* The page paths for each route within the app for the router */ routePaths: { - home: '/home', - minimal: '/minimal', - workspace: '/workspace', + home: '/home/:config?/', + minimal: '/minimal/:config?/', + workspace: '/workspace/:config?/', about: '/about', login: '/login', download: '/download',