From a27316d5978642241a67cbec5db9e0b24f393bbe Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Sun, 4 Jul 2021 09:00:53 +0100 Subject: [PATCH 1/7] :recycle: Refactors the config accumulator into a Class --- src/utils/ConfigAccumalator.js | 129 +++++++++++++++++---------------- 1 file changed, 67 insertions(+), 62 deletions(-) diff --git a/src/utils/ConfigAccumalator.js b/src/utils/ConfigAccumalator.js index 0e04c2b6..a93efb51 100644 --- a/src/utils/ConfigAccumalator.js +++ b/src/utils/ConfigAccumalator.js @@ -3,73 +3,78 @@ * Also ensures that any missing attributes are populated with defaults, and the * object is structurally sound, to avoid any error if the user is missing something * The main config object is made up of three parts: appConfig, pageInfo and sections + * For anything other than these three sections, please see @utils/ConfigHelpers.js */ -import Defaults, { localStorageKeys } from '@/utils/defaults'; +import { + localStorageKeys, + appConfig as defaultAppConfig, + pageInfo as defaultPageInfo, + iconSize as defaultIconSize, + layout as defaultLayout, +} from '@/utils/defaults'; + import conf from '../../public/conf.yml'; -/** - * Returns the appConfig section, as JSON - */ -export const appConfig = (() => { - const appConfigFile = conf.appConfig || {}; - let usersAppConfig = Defaults.appConfig; - if (localStorage[localStorageKeys.APP_CONFIG]) { - usersAppConfig = JSON.parse(localStorage[localStorageKeys.APP_CONFIG]); - } else if (appConfigFile !== {}) { - usersAppConfig = appConfigFile; +export default class ConfigAccumulator { + constructor() { + this.conf = conf; } - usersAppConfig.layout = localStorage[localStorageKeys.LAYOUT_ORIENTATION] - || appConfigFile.layout || Defaults.layout; - usersAppConfig.iconSize = localStorage[localStorageKeys.ICON_SIZE] - || appConfigFile.iconSize || Defaults.iconSize; - return usersAppConfig; -})(); -/** - * Returns the pageInfo section, as JSON - */ -export const pageInfo = (() => { - const defaults = Defaults.pageInfo; - let localPageInfo; - try { - localPageInfo = JSON.parse(localStorage[localStorageKeys.PAGE_INFO]); - } catch (e) { - localPageInfo = {}; - } - const pi = conf.pageInfo || defaults; // The page info object to return - pi.title = localPageInfo.title || conf.pageInfo.title || defaults.title; - pi.description = localPageInfo.description || conf.pageInfo.description || defaults.description; - pi.navLinks = localPageInfo.navLinks || conf.pageInfo.navLinks || defaults.navLinks; - pi.footerText = localPageInfo.footerText || conf.pageInfo.footerText || defaults.footerText; - return pi; -})(); - -/** - * Returns the sections section, as an array of JSON objects - */ -export const sections = (() => { - // If the user has stored sections in local storage, return those - const localSections = localStorage[localStorageKeys.CONF_SECTIONS]; - if (localSections) { - try { - const json = JSON.parse(localSections); - if (json.length >= 1) return json; - } catch (e) { - // The data in local storage has been malformed, will return conf.sections instead + /* App Config */ + appConfig() { + const appConfigFile = this.conf.appConfig || {}; + let usersAppConfig = defaultAppConfig; + if (localStorage[localStorageKeys.APP_CONFIG]) { + usersAppConfig = JSON.parse(localStorage[localStorageKeys.APP_CONFIG]); + } else if (appConfigFile !== {}) { + usersAppConfig = appConfigFile; } + usersAppConfig.layout = localStorage[localStorageKeys.LAYOUT_ORIENTATION] + || appConfigFile.layout || defaultLayout; + usersAppConfig.iconSize = localStorage[localStorageKeys.ICON_SIZE] + || appConfigFile.iconSize || defaultIconSize; + return usersAppConfig; } - // If the function hasn't yet returned, then return the config file sections - return conf.sections; -})(); -/** - * Returns the complete configuration, as JSON - */ -export const config = (() => { - const result = { - appConfig, - pageInfo, - sections, - }; - return result; -})(); + /* Page Info */ + pageInfo() { + const defaults = defaultPageInfo; + let localPageInfo; + try { + localPageInfo = JSON.parse(localStorage[localStorageKeys.PAGE_INFO]); + } catch (e) { + localPageInfo = {}; + } + const pi = this.conf.pageInfo || defaults; // The page info object to return + pi.title = localPageInfo.title || conf.pageInfo.title || defaults.title; + pi.description = localPageInfo.description || conf.pageInfo.description || defaults.description; + pi.navLinks = localPageInfo.navLinks || conf.pageInfo.navLinks || defaults.navLinks; + pi.footerText = localPageInfo.footerText || conf.pageInfo.footerText || defaults.footerText; + return pi; + } + + /* Sections */ + sections() { + // If the user has stored sections in local storage, return those + const localSections = localStorage[localStorageKeys.CONF_SECTIONS]; + if (localSections) { + try { + const json = JSON.parse(localSections); + if (json.length >= 1) return json; + } catch (e) { + // The data in local storage has been malformed, will return conf.sections instead + } + } + // If the function hasn't yet returned, then return the config file sections + return this.conf.sections; + } + + /* Complete config */ + config() { + return { + appConfig: this.appConfig(), + pageInfo: this.pageInfo(), + sections: this.sections(), + }; + } +} From ec95fafe04ae9620d2db12ce6dbbe7049dc9a5d9 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Sun, 4 Jul 2021 09:01:56 +0100 Subject: [PATCH 2/7] :zap: Adds a helper function, to process component visiblity --- src/utils/ConfigHelpers.js | 42 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 src/utils/ConfigHelpers.js diff --git a/src/utils/ConfigHelpers.js b/src/utils/ConfigHelpers.js new file mode 100644 index 00000000..365d1b19 --- /dev/null +++ b/src/utils/ConfigHelpers.js @@ -0,0 +1,42 @@ +import ConfigAccumulator from '@/utils/ConfigAccumalator'; + +import { visibleComponents } from '@/utils/defaults'; + +/** + * Initiates the Accumulator class and generates a complete config object + * Self-executing function, returns the full user config as a JSON object + */ +export const config = (() => { + const Accumulator = new ConfigAccumulator(); + return Accumulator.config(); +})(); + +/** + * Generates an object containing booleans indicating which + * components should be hidden. This enables the user to hide + * parts of the page and disable functionality that they don't need/ want + * All options fallback on the values defined in the defaults + * @param {object} appConfig The full app config + * @returns {object} result + */ +export const componentVisibility = (appConfig) => { + // Get users choice from app config + const usersChoice = appConfig.hideComponents || {}; + // Checks if value is defined, and is a boolean + const isThere = (userValue) => typeof userValue === 'boolean'; + // For each option, return users choice (if specified), else use the default + return { + pageTitle: isThere(usersChoice.hideHeading) + ? !usersChoice.hideHeading : visibleComponents.pageTitle, + navigation: isThere(usersChoice.hideNav) + ? !usersChoice.hideNav : visibleComponents.navigation, + searchBar: isThere(usersChoice.hideSearch) + ? !usersChoice.hideSearch : visibleComponents.searchBar, + settings: isThere(usersChoice.hideSettings) + ? !usersChoice.hideSettings : visibleComponents.settings, + footer: isThere(usersChoice.hideFooter) + ? !usersChoice.hideFooter : visibleComponents.footer, + splashScreen: isThere(usersChoice.hideSplashScreen) + ? !usersChoice.hideSplashScreen : visibleComponents.splashScreen, + }; +}; From 3de9beee41b47aec18f55d18b54657676aba106f Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Sun, 4 Jul 2021 09:04:21 +0100 Subject: [PATCH 3/7] :construction_worker: Updates router to use the new format of Config Accumulator --- src/router.js | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/router.js b/src/router.js index 84627d02..f20b9803 100644 --- a/src/router.js +++ b/src/router.js @@ -6,13 +6,13 @@ import Login from '@/views/Login.vue'; import Workspace from '@/views/Workspace.vue'; import DownloadConfig from '@/views/DownloadConfig.vue'; import { isLoggedIn } from '@/utils/Auth'; -import { appConfig, pageInfo, sections } from '@/utils/ConfigAccumalator'; +import { config } from '@/utils/ConfigHelpers'; import { metaTagData } from '@/utils/defaults'; Vue.use(Router); const isAuthenticated = () => { - const users = appConfig.auth; + const users = config.appConfig.auth; return (!users || isLoggedIn(users)); }; @@ -22,13 +22,9 @@ const router = new Router({ path: '/', name: 'home', component: Home, - props: { - appConfig, - pageInfo, - sections, - }, + props: config, meta: { - title: pageInfo.title || 'Home Page', + title: config.pageInfo.title || 'Home Page', metaTags: metaTagData, }, }, @@ -36,9 +32,9 @@ const router = new Router({ path: '/workspace', name: 'workspace', component: Workspace, - props: { appConfig, pageInfo, sections }, + props: config, meta: { - title: pageInfo.title || 'Dashy Workspace', + title: config.pageInfo.title || 'Dashy Workspace', metaTags: metaTagData, }, }, @@ -47,7 +43,7 @@ const router = new Router({ name: 'login', component: Login, props: { - appConfig, + appConfig: config.appConfig, }, beforeEnter: (to, from, next) => { if (isAuthenticated()) router.push({ path: '/' }); @@ -63,9 +59,9 @@ const router = new Router({ path: '/download', name: 'download', component: DownloadConfig, - props: { appConfig, pageInfo, sections }, + props: config, meta: { - title: pageInfo.title || 'Download Dashy Config', + title: config.pageInfo.title || 'Download Dashy Config', metaTags: metaTagData, }, }, From b214785c8a981094bc3386249573e34fd6d6dc59 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Sun, 4 Jul 2021 09:04:53 +0100 Subject: [PATCH 4/7] :construction_worker: Injects visible component object, making it available to sub-components --- src/App.vue | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/App.vue b/src/App.vue index dff0e355..38d992b9 100644 --- a/src/App.vue +++ b/src/App.vue @@ -11,8 +11,17 @@ import Header from '@/components/PageStrcture/Header.vue'; import Footer from '@/components/PageStrcture/Footer.vue'; import LoadingScreen from '@/components/PageStrcture/LoadingScreen.vue'; -import Defaults, { localStorageKeys, splashScreenTime } from '@/utils/defaults'; -import { config, appConfig, pageInfo } from '@/utils/ConfigAccumalator'; +import { componentVisibility } from '@/utils/ConfigHelpers'; +import ConfigAccumulator from '@/utils/ConfigAccumalator'; +import { + localStorageKeys, + splashScreenTime, + visibleComponents as defaultVisibleComponents, +} from '@/utils/defaults'; + +const Accumulator = new ConfigAccumulator(); +const config = Accumulator.config(); +const visibleComponents = componentVisibility(config.appConfig) || defaultVisibleComponents; export default { name: 'app', @@ -23,13 +32,15 @@ export default { }, provide: { config, + visibleComponents, }, data() { return { - showFooter: Defaults.visibleComponents.footer, + showFooter: visibleComponents.footer, isLoading: true, - appConfig, - pageInfo, + appConfig: Accumulator.appConfig(), + pageInfo: Accumulator.pageInfo(), + visibleComponents, }; }, methods: { @@ -45,7 +56,8 @@ export default { document.head.append(style); }, shouldShowSplash() { - return this.appConfig.showSplashScreen || !localStorage[localStorageKeys.HIDE_WELCOME_BANNER]; + return (this.visibleComponents || defaultVisibleComponents).splashScreen + || !localStorage[localStorageKeys.HIDE_WELCOME_BANNER]; }, hideSplash() { if (this.shouldShowSplash() && !this.shouldHidePageComponents()) { From 3f4b1575f9febaf772336dd9c594f9fa14c43030 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Sun, 4 Jul 2021 09:05:38 +0100 Subject: [PATCH 5/7] :sparkles: Implements the checking if things should be visible, at component level --- src/components/PageStrcture/Header.vue | 8 ++++---- src/components/Settings/SettingsContainer.vue | 10 +++++++--- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/components/PageStrcture/Header.vue b/src/components/PageStrcture/Header.vue index b07ac0db..aa49d6c3 100644 --- a/src/components/PageStrcture/Header.vue +++ b/src/components/PageStrcture/Header.vue @@ -8,10 +8,11 @@