+
-
{{ $t('settings.config-launcher-label') }}
+
{{ $t('settings.config-launcher-label') }}
+
@@ -19,27 +21,55 @@
+
+
+
+ -
+
+ Default
+
+
+ -
+
+ Minimal
+
+
-
+
+ Workspace
+
+
+
+
@@ -93,4 +128,38 @@ export default {
}
}
}
+
+.view-switcher {
+ position: absolute;
+ right: 1rem;
+ margin-top: 3rem;
+ z-index: 5;
+ background: var(--background);
+ border: 1px solid var(--settings-text-color);
+ border-radius: var(--curve-factor);
+ box-shadow: var(--settings-container-shadow);
+ ul {
+ list-style: none;
+ margin: 0;
+ padding: 0;
+ li {
+ cursor: pointer;
+ padding: 0.25rem 0.75rem;
+ a {
+ color: var(--settings-text-color);
+ text-decoration: none;
+ display: flex;
+ align-items: center;
+ }
+ &:hover {
+ background: var(--settings-text-color);
+ a { color: var(--background); }
+ }
+ svg {
+ margin: 0 0.25rem 0 0;
+ border: none;
+ }
+ }
+ }
+}
diff --git a/src/router.js b/src/router.js
index a34cfb1a..9331226f 100644
--- a/src/router.js
+++ b/src/router.js
@@ -1,13 +1,24 @@
+/**
+ * This is the router config, which defined the location for
+ * each page within the app, and how they should be loaded
+ * Note that the page paths are defined in @/utils/defaults.js
+ */
+
+// Import Vue.js and vue router
import Vue from 'vue';
import Router from 'vue-router';
+// Import views
import Home from '@/views/Home.vue';
import Login from '@/views/Login.vue';
import Workspace from '@/views/Workspace.vue';
+import Minimal from '@/views/Minimal.vue';
import DownloadConfig from '@/views/DownloadConfig.vue';
+
+// Import helper functions, config data and defaults
import { isLoggedIn } from '@/utils/Auth';
import { config } from '@/utils/ConfigHelpers';
-import { metaTagData } from '@/utils/defaults';
+import { metaTagData, startingView, routePaths } from '@/utils/defaults';
Vue.use(Router);
@@ -21,30 +32,62 @@ const isAuthenticated = () => {
return (!users || users.length === 0 || isLoggedIn(users));
};
+/* Get the users chosen starting view from app config, or return default */
+const getStartingView = () => config.appConfig.startingView || startingView;
+
+/**
+ * Returns the component that should be rendered at the base path,
+ * Defaults to Home, but the user can change this to Workspace of Minimal
+ */
+const getStartingComponent = () => {
+ const usersPreference = getStartingView();
+ switch (usersPreference) {
+ case 'default': return Home;
+ case 'minimal': return Minimal;
+ case 'workspace': return Workspace;
+ default: return Home;
+ }
+};
+
+/* Returns the meta tags for each route */
+const makeMetaTags = (defaultTitle) => ({
+ title: config.pageInfo.title || defaultTitle,
+ metaTags: metaTagData,
+});
+
+/* List of all routes, props, components and metadata */
const router = new Router({
routes: [
- {
+ { // The default view can be customized by the user
path: '/',
+ name: `landing-page-${getStartingView()}`,
+ component: getStartingComponent(),
+ props: config,
+ meta: makeMetaTags('Home Page'),
+ },
+ { // Default home page
+ path: routePaths.home,
name: 'home',
component: Home,
props: config,
- meta: {
- title: config.pageInfo.title || 'Home Page',
- metaTags: metaTagData,
- },
+ meta: makeMetaTags('Home Page'),
},
- {
- path: '/workspace',
+ { // Workspace view page
+ path: routePaths.workspace,
name: 'workspace',
component: Workspace,
props: config,
- meta: {
- title: config.pageInfo.title || 'Dashy Workspace',
- metaTags: metaTagData,
- },
+ meta: makeMetaTags('Workspace'),
},
- {
- path: '/login',
+ { // Minimal view page
+ path: routePaths.minimal,
+ name: 'minimal',
+ component: Minimal,
+ props: config,
+ meta: makeMetaTags('Start Page'),
+ },
+ { // The login page
+ path: routePaths.login,
name: 'login',
component: Login,
props: {
@@ -55,34 +98,38 @@ const router = new Router({
next();
},
},
- {
- path: '/about',
+ { // The about app page
+ path: routePaths.about,
name: 'about',
component: () => import(/* webpackChunkName: "about" */ './views/About.vue'),
+ meta: makeMetaTags('About Dashy'),
},
- {
- path: '/download',
+ { // The export config page
+ path: routePaths.download,
name: 'download',
component: DownloadConfig,
props: config,
- meta: {
- title: config.pageInfo.title || 'Download Dashy Config',
- metaTags: metaTagData,
- },
+ meta: makeMetaTags('Download Config'),
},
],
});
+/**
+ * Before loading a route, check if the user has authentication enabled *
+ * if so, then ensure that they are correctly logged in as a valid user *
+ * If not logged in, prevent access and redirect them to the login page *
+ * */
router.beforeEach((to, from, next) => {
if (to.name !== 'login' && !isAuthenticated()) next({ name: 'login' });
else next();
});
-const defaultTitle = 'Dashy';
+/* If title is missing, then apply default page title */
router.afterEach((to) => {
Vue.nextTick(() => {
- document.title = to.meta.title || defaultTitle;
+ document.title = to.meta.title || 'Dashy';
});
});
+// Export the now configured router
export default router;
diff --git a/src/styles/color-palette.scss b/src/styles/color-palette.scss
index 7b0f0497..caa860fa 100644
--- a/src/styles/color-palette.scss
+++ b/src/styles/color-palette.scss
@@ -35,54 +35,74 @@
* all variables are optional, since they inherit initial values from above*
* Using specific variables makes overriding for custom themes really easy */
--heading-text-color: var(--primary);
+ // Nav-bar links
--nav-link-text-color: var(--primary);
--nav-link-background-color: #607d8b33;
--nav-link-text-color-hover: var(--primary);
--nav-link-background-color-hover: #607d8b33;
--nav-link-border-color: transparent;
--nav-link-border-color-hover: var(--primary);
+ // Link items and sections
--item-text-color: var(--primary);
--item-text-color-hover: var(--item-text-color);
--item-group-outer-background: var(--primary);
--item-group-heading-text-color: var(--item-group-background);
--item-group-heading-text-color-hover: var(--background);
+ // Settings and config
--settings-background: var(--background);
--settings-text-color: var(--primary);
- --search-container-background: var(--background-darker);
- --search-field-background: var(--background);
- --search-label-color: var(--settings-text-color);
- --footer-text-color: var(--medium-grey);
- --footer-text-color-link: var(--primary);
- --footer-background: var(--background-darker);
- --welcome-popup-background: var(--background-darker);
- --welcome-popup-text-color: var(--primary);
--config-code-background: #fff;
--config-code-color: var(--background);
--config-settings-color: var(--primary);
--config-settings-background: var(--background-darker);
- --toast-background: var(--primary);
- --toast-color: var(--background);
+ --code-editor-color: var(--black);
+ --code-editor-background: var(--white);
+ // Search bar (on homepage)
+ --search-container-background: var(--background-darker);
+ --search-field-background: var(--background);
+ --search-label-color: var(--settings-text-color);
+ // Page footer
+ --footer-text-color: var(--medium-grey);
+ --footer-text-color-link: var(--primary);
+ --footer-background: var(--background-darker);
+ // Right-click context menu
+ --context-menu-background: var(--background);
+ --context-menu-color: var(--primary);
+ --context-menu-secondary-color: var(--background-darker);
+ // Workspace view
+ --side-bar-background: var(--background-darker);
+ --side-bar-background-lighter: var(--background);
+ --side-bar-color: var(--primary);
+ // Minimal view
+ --minimal-view-background-color: var(--background);
+ --minimal-view-title-color: var(--primary);
+ --minimal-view-settings-color: var(--primary);
+ --minimal-view-section-heading-color: var(--primary);
+ --minimal-view-section-heading-background: var(--background-darker);
+ --minimal-view-search-background: var(--background-darker);
+ --minimal-view-search-color: var(--primary);
+ --minimal-view-group-color: var(--primary);
+ --minimal-view-group-background: var(--background-darker);
+ // Login page
+ --login-form-color: var(--primary);
+ --login-form-background: var(--background);
+ --login-form-background-secondary: var(--background-darker);
+ // About page
+ --about-page-color: var(--white);
+ --about-page-background: var(--background);
+ --about-page-accent: var(--primary);
+ // Webpage colors, highlight, scrollbar
--scroll-bar-color: var(--primary);
--scroll-bar-background: var(--background-darker);
--highlight-color: var(--background);
--highlight-background: var(--primary);
+ // Misc components
--loading-screen-color: var(--primary);
--loading-screen-background: var(--background);
- --login-form-color: var(--primary);
- --login-form-background: var(--background);
- --login-form-background-secondary: var(--background-darker);
- --about-page-color: var(--white);
- --about-page-background: var(--background);
- --about-page-accent: var(--primary);
- --side-bar-background: var(--background-darker);
- --side-bar-background-lighter: var(--background);
- --side-bar-color: var(--primary);
--status-check-tooltip-background: var(--background-darker);
--status-check-tooltip-color: var(--primary);
- --code-editor-color: var(--black);
- --code-editor-background: var(--white);
-
- --context-menu-background: var(--background);
- --context-menu-color: var(--primary);
- --context-menu-secondary-color: var(--background-darker);
+ --welcome-popup-background: var(--background-darker);
+ --welcome-popup-text-color: var(--primary);
+ --toast-background: var(--primary);
+ --toast-color: var(--background);
}
diff --git a/src/styles/color-themes.scss b/src/styles/color-themes.scss
index b395e0ef..6b352ece 100644
--- a/src/styles/color-themes.scss
+++ b/src/styles/color-themes.scss
@@ -481,7 +481,7 @@ html[data-theme='material'], html[data-theme='material-dark'] {
html[data-theme='material'] {
--primary: #363636;
- --background: #f5f5f5;
+ --background: #eee;
--background-darker: #5c90eb;
--item-group-outer-background: none;
--item-group-shadow: none;
@@ -501,7 +501,7 @@ html[data-theme='material'] {
--config-settings-background: #f5f5f5;
--config-settings-color: #473f3f;
--heading-text-color: #fff;
- --curve-factor: 4px;
+ --curve-factor: 3px;
--curve-factor-navbar: 8px;
--search-container-background: #4285f4;
--welcome-popup-text-color: #f5f5f5;
@@ -510,6 +510,30 @@ html[data-theme='material'] {
--context-menu-secondary-color: #f5f5f5;
--transparent-white-50: #00000080;
+ --minimal-view-background-color: var(--background);
+ --minimal-view-title-color: var(--background-darker);
+ --minimal-view-settings-color: var(--primary);
+ --minimal-view-section-heading-color: var(--primary);
+ --minimal-view-section-heading-background: #f6f6f6;
+ --minimal-view-search-background: #fff;
+ --minimal-view-search-color: var(--primary);
+ --minimal-view-group-color: var(--primary);
+ --minimal-view-group-background: #fff;
+
+ .minimal-section-inner.selected, div.minimal-section-heading {
+ border: none;
+ box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
+ }
+ .title-and-search form input {
+ box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
+ }
+ div.minimal-section-heading.selected {
+ background: #5c90eb;
+ }
+ div.minimal-section-inner {
+ background: #ffffff80;
+ }
+
div.jsoneditor div.jsoneditor-menu {
background: #5c90eb !important;
}
@@ -585,6 +609,25 @@ html[data-theme='material-dark'] {
// --login-form-color: #131a1f;
--login-form-background-secondary: #131a1f;
+ // --minimal-view-background-color: var(--background);
+ // --minimal-view-title-color: var(--primary);
+ // --minimal-view-settings-color: var(--primary);
+ --minimal-view-section-heading-color: #131a1f;
+ --minimal-view-section-heading-background: var(--background);
+ --minimal-view-search-background: #131a1f;
+ // --minimal-view-search-color: var(--primary);
+ // --minimal-view-group-color: var(--primary);
+ --minimal-view-group-background: #131a1f;
+
+ div.minimal-section-heading h3, div.minimal-section-heading.selected h3 {
+ color: #d5d5d5;
+ }
+ div.minimal-section-heading, .minimal-section-inner.selected, input.minimal-search {
+ box-shadow: 2px 2px 4px #000000, 0 1px 3px #000000cc;
+ border-color: #131a1f80;
+ }
+
+
&::-webkit-scrollbar-thumb {
border-left: 1px solid #131a1f;
}
@@ -812,6 +855,10 @@ html[data-theme="oblivion-scotch"] {
border: 1px solid #313d4f;
box-shadow: 0 1px 5px #0c0d0e;
}
+
+ .minimal-home div.item-group-container, input.minimal-search {
+ box-shadow: 0 1px 6px #00000099, 0 1px 1px #000000cc;
+ }
}
html[data-theme="oblivion-blue"] {
diff --git a/src/styles/style-helpers.scss b/src/styles/style-helpers.scss
index d5db94b0..ebcbd6c1 100644
--- a/src/styles/style-helpers.scss
+++ b/src/styles/style-helpers.scss
@@ -15,6 +15,30 @@
}
}
+.svg-button {
+ color: var(--primary);
+ width: 1.5rem;
+ height: 1.5rem;
+ svg {
+ path {
+ fill: var(--settings-text-color);
+ }
+ width: 1rem;
+ height: 1rem;
+ margin: 0.2rem;
+ padding: 0.2rem;
+ text-align: center;
+ background: var(--background);
+ border: 1px solid currentColor;
+ border-radius: var(--curve-factor);
+ cursor: pointer;
+ &:hover, &.selected {
+ background: var(--settings-text-color);
+ path { fill: var(--background); }
+ }
+ }
+}
+
/* Custom highlight color */
.highlight {
::selection {
diff --git a/src/utils/ConfigSchema.json b/src/utils/ConfigSchema.json
index 2bd605a5..9637195a 100644
--- a/src/utils/ConfigSchema.json
+++ b/src/utils/ConfigSchema.json
@@ -67,6 +67,15 @@
"type": "string",
"description": "The ISO code of your desired language, must have translations present, check docs for more info"
},
+ "startingView": {
+ "enum": [
+ "default",
+ "minimal",
+ "workspace"
+ ],
+ "default": "default",
+ "description": "Which page to load by default, and on the base page or domain root. You can still switch to different views from within the UI"
+ },
"theme": {
"type": "string",
"default": "callisto",
diff --git a/src/utils/MiscHelpers.js b/src/utils/MiscHelpers.js
new file mode 100644
index 00000000..212e7495
--- /dev/null
+++ b/src/utils/MiscHelpers.js
@@ -0,0 +1,6 @@
+import { hideFurnitureOn } from '@/utils/defaults';
+
+/* Returns false if page furniture should be hidden on said route */
+export const shouldBeVisible = (routeName) => !hideFurnitureOn.includes(routeName);
+
+export const x = () => null;
diff --git a/src/utils/defaults.js b/src/utils/defaults.js
index 1d731b9e..080a43f8 100644
--- a/src/utils/defaults.js
+++ b/src/utils/defaults.js
@@ -13,6 +13,8 @@ module.exports = {
appConfig: {},
/* Default language code */
language: 'en',
+ /* The page to use as the starting homepage */
+ startingView: 'default',
/* Default icon size to be applied on initial load */
iconSize: 'medium',
/* Default layout to be applied on initial load */
@@ -23,6 +25,15 @@ module.exports = {
fontAwesomeKey: '0821c65656',
/* Default API to use for fetching of user service favicon icons (if enabled) */
faviconApi: 'faviconkit',
+ /* The page paths for each route within the app for the router */
+ routePaths: {
+ home: '/home',
+ minimal: '/minimal',
+ workspace: '/workspace',
+ about: '/about',
+ login: '/login',
+ download: '/download',
+ },
/* List of built-in themes, to be displayed within the theme-switcher dropdown */
builtInThemes: [
'callisto',
@@ -58,6 +69,13 @@ module.exports = {
settings: true,
footer: true,
},
+ /* A list of route names that page furniture (header, footer, etc) should be hidden on */
+ hideFurnitureOn: [
+ 'minimal',
+ 'login',
+ 'download',
+ 'landing-page-minimal',
+ ],
/* Key names for local storage identifiers */
localStorageKeys: {
LANGUAGE: 'language',
diff --git a/src/views/Minimal.vue b/src/views/Minimal.vue
new file mode 100644
index 00000000..c0602b04
--- /dev/null
+++ b/src/views/Minimal.vue
@@ -0,0 +1,288 @@
+
+
+
+
+
+
+
+
+
+ {{ pageInfo.title }}
+
+ { this.searchValue = s; }" :active="!modalOpen" />
+
+
+
+
+
+
+
+ {{searchValue ? $t('home.no-results') : $t('home.no-data')}}
+
+
+
{{ $t('home.no-data') }}
+
+
+
+
+
+
+
+