From 0927ea879b82056b8c9bfe9f82cce5b99eb2a9f4 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Sun, 19 Sep 2021 21:18:41 +0100 Subject: [PATCH 001/391] :zap: Show loader when route changes --- src/router.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/router.js b/src/router.js index 1db8ceae..a1bdd95b 100644 --- a/src/router.js +++ b/src/router.js @@ -7,6 +7,7 @@ // Import Vue.js and vue router import Vue from 'vue'; import Router from 'vue-router'; +import ProgressBar from 'rsup-progress'; // Import views import Home from '@/views/Home.vue'; @@ -21,6 +22,7 @@ import { config } from '@/utils/ConfigHelpers'; import { metaTagData, startingView, routePaths } from '@/utils/defaults'; Vue.use(Router); +const progress = new ProgressBar({ color: 'var(--progress-bar)' }); /* Returns true if user is already authenticated, or if auth is not enabled */ const isAuthenticated = () => { @@ -119,12 +121,14 @@ const router = new Router({ * If not logged in, prevent all access and redirect them to login page * */ router.beforeEach((to, from, next) => { + progress.start(); if (to.name !== 'login' && !isAuthenticated()) next({ name: 'login' }); else next(); }); /* If title is missing, then apply default page title */ router.afterEach((to) => { + progress.end(); Vue.nextTick(() => { document.title = to.meta.title || 'Dashy'; }); From 6e0cda8709de6aded9c97e7f016b68c5b01cf5ee Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Sun, 19 Sep 2021 21:28:05 +0100 Subject: [PATCH 002/391] :children_crossing: Adds user-facing warning logging --- src/utils/CoolConsole.js | 2 +- src/utils/ErrorHandler.js | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/utils/CoolConsole.js b/src/utils/CoolConsole.js index 09efcd17..2871d0a5 100644 --- a/src/utils/CoolConsole.js +++ b/src/utils/CoolConsole.js @@ -28,7 +28,7 @@ export const statusMsg = (title, msg) => { /* Prints status message, with a stack trace */ export const statusErrorMsg = (title, msg, errorLog) => { console.log( - `%c${title || ''}\n%c${msg} \n%c${errorLog}`, + `%c${title || ''}\n%c${msg} \n%c${errorLog || ''}`, 'font-weight: bold; color: #0dd8d8; text-decoration: underline;', 'color: #ff025a', 'color: #ff025a80;', diff --git a/src/utils/ErrorHandler.js b/src/utils/ErrorHandler.js index d0c96f08..1d253281 100644 --- a/src/utils/ErrorHandler.js +++ b/src/utils/ErrorHandler.js @@ -1,5 +1,5 @@ import * as Sentry from '@sentry/vue'; -import { warningMsg, statusMsg } from '@/utils/CoolConsole'; +import { warningMsg, statusMsg, statusErrorMsg } from '@/utils/CoolConsole'; import { sessionStorageKeys } from '@/utils/defaults'; /* Makes the current time, like hh:mm:ss */ @@ -33,4 +33,9 @@ export const InfoHandler = (msg, title) => { statusMsg(title || 'Info', msg); }; +/* Outputs warnings caused by the user, such as missing field */ +export const WarningInfoHandler = (msg, title, log) => { + statusErrorMsg(title || 'Warning', msg, log); +}; + export default ErrorHandler; From cdab7981bd3bbb36e39b980d601830742d3dae67 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Sun, 19 Sep 2021 21:29:39 +0100 Subject: [PATCH 003/391] :zap: Replace error with warning for failed user actions --- src/components/Configuration/CloudBackupRestore.vue | 4 ++-- src/views/Login.vue | 8 +++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/components/Configuration/CloudBackupRestore.vue b/src/components/Configuration/CloudBackupRestore.vue index 83b303f4..e4a4139c 100644 --- a/src/components/Configuration/CloudBackupRestore.vue +++ b/src/components/Configuration/CloudBackupRestore.vue @@ -66,7 +66,7 @@ import IconBackup from '@/assets/interface-icons/config-backup.svg'; import IconRestore from '@/assets/interface-icons/config-restore.svg'; import { backup, update, restore } from '@/utils/CloudBackup'; import { localStorageKeys } from '@/utils/defaults'; -import ErrorHandler, { InfoHandler } from '@/utils/ErrorHandler'; +import { InfoHandler, WarningInfoHandler } from '@/utils/ErrorHandler'; export default { name: 'CloudBackupRestore', @@ -161,7 +161,7 @@ export default { this.backupPassword = ''; }, showErrorMsg(errorMsg) { - ErrorHandler(errorMsg); + WarningInfoHandler(errorMsg, 'Cloud Backup'); this.$toasted.show(errorMsg, { className: 'toast-error' }); }, showSuccessMsg(msg) { diff --git a/src/views/Login.vue b/src/views/Login.vue index 0b159f2c..27030208 100644 --- a/src/views/Login.vue +++ b/src/views/Login.vue @@ -76,7 +76,7 @@ import router from '@/router'; import Button from '@/components/FormElements/Button'; import Input from '@/components/FormElements/Input'; import Defaults, { localStorageKeys } from '@/utils/defaults'; -import { InfoHandler } from '@/utils/ErrorHandler'; +import { InfoHandler, WarningInfoHandler } from '@/utils/ErrorHandler'; import { checkCredentials, login, @@ -160,7 +160,7 @@ export default { this.goHome(); InfoHandler(`Succesfully signed in as ${this.username}`, 'Authentication'); } else { - InfoHandler(`Unable to Sign In - ${this.message}`, 'Authentication'); + WarningInfoHandler('Unable to Sign In', 'Authentication', this.message); } }, /* Calls function to double-check guest access enabled, then log in as guest */ @@ -168,9 +168,11 @@ export default { const isAllowed = this.isGuestAccessEnabled; if (isAllowed) { this.$toasted.show('Logged in as Guest, Redirecting...', { className: 'toast-success' }); + InfoHandler('Logged in as Guest', 'Authentication'); this.goHome(); } else { - this.$toasted.show('Guest access not allowed', { className: 'toast-error' }); + this.$toasted.show('Guest Access Not Allowed', { className: 'toast-error' }); + WarningInfoHandler('Guest Access Not Allowed', 'Authentication'); } }, /* Calls logout, shows status message, and refreshed page */ From b00c9ad90297ff1bb2c69de664b50c824a0fdc50 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Sun, 19 Sep 2021 22:22:12 +0100 Subject: [PATCH 004/391] :sparkles: Show splash screen before app loaded --- public/index.html | 51 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 9 deletions(-) diff --git a/public/index.html b/public/index.html index c02e9e4d..589395f5 100644 --- a/public/index.html +++ b/public/index.html @@ -1,27 +1,60 @@ - - - - + + + + Dashy + +
+ +

Dashy

Loading...

+
- - -
+ + - \ No newline at end of file From b532e168fe2da0fb6b96f8d2601ed3e9e8641ec5 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Sun, 19 Sep 2021 22:23:26 +0100 Subject: [PATCH 005/391] :dizzy: Hide loader, if still visible --- src/App.vue | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/App.vue b/src/App.vue index 098656e9..cb34b125 100644 --- a/src/App.vue +++ b/src/App.vue @@ -53,8 +53,7 @@ export default { }, /* Determine if splash screen should be shown */ shouldShowSplash() { - return (this.visibleComponents || defaultVisibleComponents).splashScreen - || !localStorage[localStorageKeys.HIDE_WELCOME_BANNER]; + return (this.visibleComponents || defaultVisibleComponents).splashScreen; }, }, methods: { @@ -107,6 +106,10 @@ export default { this.$i18n.locale = language; document.getElementsByTagName('html')[0].setAttribute('lang', language); }, + hideLoader() { + const loader = document.getElementById('loader'); + if (loader) loader.style.display = 'none'; + }, }, /* When component mounted, hide splash and initiate the injection of custom styles */ mounted() { @@ -115,6 +118,7 @@ export default { if (this.appConfig.customCss) { const cleanedCss = this.appConfig.customCss.replace(/<\/?[^>]+(>|$)/g, ''); this.injectCustomStyles(cleanedCss); + this.hideLoader(); } welcomeMsg(); }, From d6a2c4d8106dcf9363f01355a9749d1ffd8e77c4 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Sun, 19 Sep 2021 22:23:53 +0100 Subject: [PATCH 006/391] :fire: Splash screen now off by default --- src/utils/defaults.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/utils/defaults.js b/src/utils/defaults.js index 115cd82b..35695eea 100644 --- a/src/utils/defaults.js +++ b/src/utils/defaults.js @@ -71,8 +71,9 @@ module.exports = { ], /* Which structural components should be visible by default */ visibleComponents: { - pageTitle: true, + splashScreen: false, navigation: true, + pageTitle: true, searchBar: true, settings: true, footer: true, From b3d0519d8d750d3146a916ca60df1e9fb3c1f71f Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Sun, 19 Sep 2021 22:44:02 +0100 Subject: [PATCH 007/391] :bookmark: Bumps to V 1.8.3 and updates changelog --- .github/CHANGELOG.md | 5 +++++ package.json | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md index 899b7da7..a8514e76 100644 --- a/.github/CHANGELOG.md +++ b/.github/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## ⚡️ 1.8.3 - Improved UX for Initial Load [PR #238](https://github.com/Lissy93/dashy/pull/238) +- Removes the old splash screen +- Adds placeholder in the HTML index, which will usually be visible on initial load +- Show progress bar on route switcher + ## ✨ 1.8.2 - Serverless Functions for Netlify Instances [PR #235](https://github.com/Lissy93/dashy/pull/235) - Previously when Dashy was deployed as a static site to Netlify, it was not possible to use several features, which required server-side code - This PR adds serverless cloud functions to provide most of this functionality diff --git a/package.json b/package.json index 8ceda392..023a0a46 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "Dashy", - "version": "1.8.2", + "version": "1.8.3", "license": "MIT", "main": "server", "scripts": { From 3a301afc6542c52eb4fd2530ad0ef6632687f2a3 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Sun, 19 Sep 2021 22:48:56 +0100 Subject: [PATCH 008/391] :wheelchair: Adds lang attr, for accessibility --- public/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/index.html b/public/index.html index 589395f5..fe4c82e0 100644 --- a/public/index.html +++ b/public/index.html @@ -1,5 +1,5 @@ - + From c7c9b0cf43e96f3659b241484325207ec5d52a57 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Mon, 20 Sep 2021 17:08:47 +0100 Subject: [PATCH 009/391] :memo: Updates the Auth contents page I forgot to do this previously, and it should make it easier to find things. Re: #240 --- docs/authentication.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/authentication.md b/docs/authentication.md index 1dfecc5e..e5de308c 100644 --- a/docs/authentication.md +++ b/docs/authentication.md @@ -4,7 +4,9 @@ - [Setting Up Authentication](#setting-up-authentication) - [Hash Password](#hash-password) - [Logging In and Out](#logging-in-and-out) - - [Security](#security) + - [Guest Access](#enabling-guest-access) + - [Per-User Access](#granular-access) + - [Security Considerations](#security) - [Keycloak Auth](#keycloak) - [Deploying Keycloak](#1-deploy-keycloak) - [Setting up Keycloak](#2-setup-keycloak-users) From 3619facd751f5950bbc9bf1045455bb77e18c7f8 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Fri, 24 Sep 2021 00:12:27 +0100 Subject: [PATCH 010/391] :wrench: Adds route name for 404 page --- src/utils/defaults.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/utils/defaults.js b/src/utils/defaults.js index 35695eea..49fa263c 100644 --- a/src/utils/defaults.js +++ b/src/utils/defaults.js @@ -35,6 +35,7 @@ module.exports = { about: '/about', login: '/login', download: '/download', + notFound: '/404', }, /* Server Endpoints */ serviceEndpoints: { @@ -84,6 +85,7 @@ module.exports = { 'login', 'download', 'landing-page-minimal', + // '404', ], /* Key names for local storage identifiers */ localStorageKeys: { From 728e39a83de201bfb1c5086a4a207e6e4c8c707a Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Fri, 24 Sep 2021 00:12:59 +0100 Subject: [PATCH 011/391] :sparkles: Builds a 404 not-found page --- src/views/404.vue | 90 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 src/views/404.vue diff --git a/src/views/404.vue b/src/views/404.vue new file mode 100644 index 00000000..7024fc3d --- /dev/null +++ b/src/views/404.vue @@ -0,0 +1,90 @@ + + + + + From 0e31e9ab4fc1e89300a23a4f5da57b2c7a483112 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Fri, 24 Sep 2021 00:13:25 +0100 Subject: [PATCH 012/391] :sparkles: Redirects not-found pages to the 404 route --- src/router.js | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/router.js b/src/router.js index a1bdd95b..e76efe42 100644 --- a/src/router.js +++ b/src/router.js @@ -9,17 +9,17 @@ import Vue from 'vue'; import Router from 'vue-router'; import ProgressBar from 'rsup-progress'; -// Import views +// Import views, that are not lazy-loaded 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 { isAuthEnabled, isLoggedIn, isGuestAccessEnabled } from '@/utils/Auth'; import { config } from '@/utils/ConfigHelpers'; import { metaTagData, startingView, routePaths } from '@/utils/defaults'; +import ErrorHandler from '@/utils/ErrorHandler'; Vue.use(Router); const progress = new ProgressBar({ color: 'var(--progress-bar)' }); @@ -102,16 +102,32 @@ const router = new Router({ { // The about app page path: routePaths.about, name: 'about', // We lazy load the About page so as to not slow down the app - component: () => import(/* webpackChunkName: "about" */ './views/About.vue'), + component: () => import('./views/About.vue'), meta: makeMetaTags('About Dashy'), }, { // The export config page path: routePaths.download, name: 'download', - component: DownloadConfig, + component: () => import('./views/DownloadConfig.vue'), props: config, meta: makeMetaTags('Download Config'), }, + { // Page not found, any non-defined routes will land here + path: routePaths.notFound, + name: '404', + component: () => import('./views/404.vue'), + meta: makeMetaTags('404 Not Found'), + beforeEnter: (to, from, next) => { + if (to.redirectedFrom) { // Log error, if redirected here from another route + ErrorHandler(`Route not found: '${to.redirectedFrom}'`); + } + next(); + }, + }, + { // Redirect any not-found routed to the 404 view + path: '*', + redirect: '/404', + }, ], }); From 3104cf605deaed96677e08a587eb9a1df81366b5 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Fri, 24 Sep 2021 00:13:55 +0100 Subject: [PATCH 013/391] :fire: Removes non-essential code from AppInfo modal --- src/components/Configuration/AppInfoModal.vue | 133 +++--------------- 1 file changed, 19 insertions(+), 114 deletions(-) diff --git a/src/components/Configuration/AppInfoModal.vue b/src/components/Configuration/AppInfoModal.vue index 8ba9dbc6..d8c4c98f 100644 --- a/src/components/Configuration/AppInfoModal.vue +++ b/src/components/Configuration/AppInfoModal.vue @@ -1,46 +1,32 @@ @@ -58,71 +44,13 @@ export default { return { modalName: modalNames.ABOUT_APP, appVersion: process.env.VUE_APP_VERSION, - systemInfo: this.getSystemInfo(), errorLog: this.getErrorLog(), - serviceWorkerInfo: 'Checking...', - showInfo: false, }; }, - mounted() { - setTimeout(() => { - this.serviceWorkerInfo = this.getSwStatus(); - }, 100); - }, methods: { getErrorLog() { return sessionStorage.getItem(sessionStorageKeys.ERROR_LOG) || ''; }, - getIsConfigValidStatus() { - const isValidVar = process.env.VUE_APP_CONFIG_VALID; - if (isValidVar === undefined) return 'Config validation status is missing'; - return `Config is ${isValidVar ? 'Valid' : 'Invalid'}`; - }, - getSwStatus() { - const sessionData = sessionStorage[sessionStorageKeys.SW_STATUS]; - const swInfo = sessionData ? JSON.parse(sessionData) : {}; - let swStatus = ''; - if (swInfo.registered) swStatus += 'Service worker registered\n'; - if (swInfo.ready) swStatus += 'Dashy is being served from service worker\n'; - if (swInfo.cached) swStatus += 'Content has been cached for offline use\n'; - if (swInfo.updateFound) swStatus += 'New content is downloading\n'; - if (swInfo.updated) swStatus += 'New content is available; please refresh\n'; - if (swInfo.offline) swStatus += 'No internet connection found. App is running in offline mode\n'; - if (swInfo.error) swStatus += 'Error during service worker registration\n'; - if (swInfo.devMode) swStatus += 'App running in dev mode, no need for service worker\n'; - if (swStatus.length === 0) swStatus += 'No service worker info available'; - return swStatus; - }, - getSystemInfo() { - const { userAgent } = navigator; - - // Find Operating System - let os = 'Unknown'; - if (userAgent.indexOf('Win') !== -1) os = 'Windows'; - else if (userAgent.indexOf('Mac') !== -1) os = 'MacOS'; - else if (userAgent.indexOf('Android') !== -1) os = 'Android'; - else if (userAgent.indexOf('iPhone') !== -1) os = 'iOS'; - else if (userAgent.indexOf('Linux') !== -1) os = 'Linux'; - else if (userAgent.indexOf('X11') !== -1) os = 'UNIX'; - - // Find Browser - let browser = 'Unknown'; - if (userAgent.indexOf('Opera') !== -1) browser = 'Opera'; - else if (userAgent.indexOf('Chrome') !== -1) browser = 'Chrome'; - else if (userAgent.indexOf('Safari') !== -1) browser = 'Safari'; - else if (userAgent.indexOf('Firefox') !== -1) browser = 'Firefox'; - else if (userAgent.indexOf('MSIE') !== -1) browser = 'IE'; - else browser = 'Unknown'; - - const isMobile = !!navigator.userAgent.match(/iphone|android|blackberry/ig) || false; - - return { - os, - browser, - userAgent, - isMobile, - }; - }, }, }; @@ -152,40 +80,17 @@ div.about-modal { } } h3 { - font-size: 1.3rem; - margin: 1rem 0 0.2rem 0; + font-size: 1rem; + margin: 0.5rem 0 0.2rem 0; color: var(--about-page-accent); } - p.small-note { - margin: 0.2rem 0; - } - p.about-text { - margin: 0.2rem 0; - } a { color: var(--about-page-accent); } - ul { - margin-top: 0.2rem; - } a.info { text-decoration: underline; margin-left: 0.2rem; } - .system-info { - font-size: 0.8rem; - background: var(--black); - color: var(--white); - border-radius: var(--curve-factor-small); - padding: 0.5rem; - border: 1px solid var(--white); - width: fit-content; - h4 { - font-size: 0.8rem; - margin: 0 0 0.2rem 0; - text-decoration: underline; - } - } .app-version { text-align: left; } From d5af0926967ef429f907ab27a1723efaaab71512 Mon Sep 17 00:00:00 2001 From: repo-visualizer Date: Sun, 26 Sep 2021 01:25:16 +0000 Subject: [PATCH 014/391] :yellow_heart: Updates repo diagram --- docs/assets/repo-visualization.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/assets/repo-visualization.svg b/docs/assets/repo-visualization.svg index 35834737..84224aa1 100644 --- a/docs/assets/repo-visualization.svg +++ b/docs/assets/repo-visualization.svg @@ -1 +1 @@ -viewsviewsutilsutilsstylesstylescomponentscomponentsassetsassetsWorkspaceWorkspaceSettingsSettingsPageStrcturePageStrctureMinimalViewMinimalViewLinkItemsLinkItemsFormElementsFormElementsConfigurationConfigurationlocaleslocalesinterface-iconsinterface-iconsLogin.vueLogin.vueLogin.vueHome.vueHome.vueHome.vueMinimal.vueMinimal.vueMinimal.vueemojis.jsonemojis.jsonemojis.jsonConfigSche...ConfigSche...ConfigSche...Auth.jsAuth.jsAuth.jsdefaults.jsdefaults.jsdefaults.jscolor-them...color-them...color-them...CustomThe...CustomThe...CustomThe...Item.vueItem.vueItem.vueItemIcon.vueItemIcon.vueItemIcon.vueSection.vueSection.vueSection.vueConfigCon...ConfigCon...ConfigCon...JsonEdito...JsonEdito...JsonEdito...CloudBac...CloudBac...CloudBac...hi.jsonhi.jsonhi.jsonru.jsonru.jsonru.jsonar.jsonar.jsonar.jsonja.jsonja.jsonja.jsonfr.jsonfr.jsonfr.jsones.jsones.jsones.jsonpt.jsonpt.jsonpt.jsonit.jsonit.jsonit.jsonsl.jsonsl.jsonsl.jsonen.jsonen.jsonen.jsonde.jsonde.jsonde.json.js.json.scss.svg.vueeach dot sized by file size \ No newline at end of file +viewsviewsutilsutilsstylesstylescomponentscomponentsassetsassetsWorkspaceWorkspaceSettingsSettingsPageStrcturePageStrctureMinimalViewMinimalViewLinkItemsLinkItemsFormElementsFormElementsConfigurationConfigurationlocaleslocalesinterface-iconsinterface-iconsLogin.vueLogin.vueLogin.vueHome.vueHome.vueHome.vueMinimal.vueMinimal.vueMinimal.vueemojis.jsonemojis.jsonemojis.jsonConfigSche...ConfigSche...ConfigSche...Auth.jsAuth.jsAuth.jsdefaults.jsdefaults.jsdefaults.jscolor-them...color-them...color-them...CustomThe...CustomThe...CustomThe...Item.vueItem.vueItem.vueItemIcon.vueItemIcon.vueItemIcon.vueSection.vueSection.vueSection.vueConfigCon...ConfigCon...ConfigCon...JsonEdito...JsonEdito...JsonEdito...CloudBac...CloudBac...CloudBac...hi.jsonhi.jsonhi.jsonru.jsonru.jsonru.jsonar.jsonar.jsonar.jsonja.jsonja.jsonja.jsonfr.jsonfr.jsonfr.jsones.jsones.jsones.jsonpt.jsonpt.jsonpt.jsonit.jsonit.jsonit.jsonsl.jsonsl.jsonsl.jsonen.jsonen.jsonen.jsonde.jsonde.jsonde.json.js.json.scss.svg.vueeach dot sized by file size \ No newline at end of file From 8d8a362b41ec93e66502f79695b06303fbcb5be1 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Mon, 27 Sep 2021 18:30:06 +0100 Subject: [PATCH 015/391] :adhesive_bandage: Re: #251 - Updates endpoint for status check debugging --- docs/status-indicators.md | 4 ++-- docs/troubleshooting.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/status-indicators.md b/docs/status-indicators.md index 9d3ad488..7bc866ae 100644 --- a/docs/status-indicators.md +++ b/docs/status-indicators.md @@ -74,13 +74,13 @@ If you get an error, like `Service Unavailable: Server resulted in a fatal error Currently, the status check needs a page to be rendered, so if this URL in your browser does not return anything, then status checks will not work. This may be modified in the future, but in the meantime, a fix would be to make your own status service, which just checks if your app responds with whatever code you'd like, and then return a 200 plus renders an arbitrary message. Then just point `statusCheckUrl` to your custom page. -For further troubleshooting, use an application like [Postman](https://postman.com) to diagnose the issue. Set the parameter to `GET`, and then make a call to: `https://[url-of-dashy]/ping/?&url=[service-url]`. Where the service URL must have first been encoded (e.g. with `encodeURIComponent()` or [urlencoder.io](https://www.urlencoder.io/)) +For further troubleshooting, use an application like [Postman](https://postman.com) to diagnose the issue. Set the parameter to `GET`, and then make a call to: `https://[url-of-dashy]/status-check/?&url=[service-url]`. Where the service URL must have first been encoded (e.g. with `encodeURIComponent()` or [urlencoder.io](https://www.urlencoder.io/)) If you're serving Dashy though a CDN, instead of using the Node server or Docker image, then the Node endpoint that makes requests will not be available to you, and all requests will fail. A workaround for this may be implemented in the future, but in the meantime, your only option is to use the Docker or Node deployment method. ## How it Works -When the app is loaded, if `appConfig.statusCheck: true` is set, or if any items have the `statusCheck: true` enabled, then Dashy will make a request, to `https://[your-host-name]/ping?url=[address-or-servce]` (may al include GET params for headers and the secure flag), which in turn will ping that running service, and respond with a status code. Response time is calculated from the difference between start and end time of the request. +When the app is loaded, if `appConfig.statusCheck: true` is set, or if any items have the `statusCheck: true` enabled, then Dashy will make a request, to `https://[your-host-name]/status-check?url=[address-or-servce]` (may al include GET params for headers and the secure flag), which in turn will ping that running service, and respond with a status code. Response time is calculated from the difference between start and end time of the request. When the response completes, an indicator will display next to each item. The color denotes the status: Yellow while waiting for the response to return, green if request was successful, red if it failed, and grey if it was unable to make the request all together. diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index 1e210967..c75a1941 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -154,6 +154,6 @@ If you get an error, like `Service Unavailable: Server resulted in a fatal error Currently, the status check needs a page to be rendered, so if this URL in your browser does not return anything, then status checks will not work. This may be modified in the future, but in the meantime, a fix would be to make your own status service, which just checks if your app responds with whatever code you'd like, and then return a 200 plus renders an arbitrary message. Then just point `statusCheckUrl` to your custom page. -For further troubleshooting, use an application like [Postman](https://postman.com) to diagnose the issue. Set the parameter to `GET`, and then make a call to: `https://[url-of-dashy]/ping/?&url=[service-url]`. Where the service URL must have first been encoded (e.g. with `encodeURIComponent()` or [urlencoder.io](https://www.urlencoder.io/)) +For further troubleshooting, use an application like [Postman](https://postman.com) to diagnose the issue. Set the parameter to `GET`, and then make a call to: `https://[url-of-dashy]/status-check/?&url=[service-url]`. Where the service URL must have first been encoded (e.g. with `encodeURIComponent()` or [urlencoder.io](https://www.urlencoder.io/)) If you're serving Dashy though a CDN, instead of using the Node server or Docker image, then the Node endpoint that makes requests will not be available to you, and all requests will fail. A workaround for this may be implemented in the future, but in the meantime, your only option is to use the Docker or Node deployment method. \ No newline at end of file From 390a62ac0ec6b85334f252f25a816b92bdf44561 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Tue, 28 Sep 2021 13:49:13 +0100 Subject: [PATCH 016/391] =?UTF-8?q?=F0=9F=A7=A1=20Adds=20embeded=20starhaz?= =?UTF-8?q?ers=20card?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/credits.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/docs/credits.md b/docs/credits.md index 691c4af6..34d87aba 100644 --- a/docs/credits.md +++ b/docs/credits.md @@ -108,7 +108,7 @@ ### Helpful Users - +
@@ -154,7 +154,7 @@
- + ### Bots @@ -207,6 +207,12 @@ > The above section is auto-generated, using [contribute-list](https://github.com/marketplace/actions/contribute-list) by @akhilmhdh. +### Newest Stargazers + +[![Recent Star Gazers](https://reporoster.com/stars/dark/Lissy93/dashy)](https://github.com/Lissy93/dashy/stargazers) + +[![Recent Forkers](https://reporoster.com/forks/dark/lissy93/dashy)](https://github.com/lissy93/dashy/network/members) + --- ## Dependencies From 174c49521c131c3bfea14b3486469f2740f17213 Mon Sep 17 00:00:00 2001 From: liss-bot Date: Tue, 28 Sep 2021 13:49:55 +0100 Subject: [PATCH 017/391] :purple_heart: Updates contributors list --- docs/credits.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/credits.md b/docs/credits.md index 34d87aba..c2ab469f 100644 --- a/docs/credits.md +++ b/docs/credits.md @@ -126,10 +126,10 @@ - - turnrye + + jhelmink
- Ryan Turner + Josh
@@ -147,10 +147,10 @@ - - niklashere + + lu4t
- Niklas + Lu4t
From e1241d4552cb4a5c8eda5db8f70829bdfdc5c071 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Tue, 28 Sep 2021 17:05:15 +0100 Subject: [PATCH 018/391] =?UTF-8?q?=F0=9F=91=B7=20Close=20stale=20and=20un?= =?UTF-8?q?replied=20to=20issues?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/close-stale-issues.yml | 38 ++++++++++++++++++++---- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/.github/workflows/close-stale-issues.yml b/.github/workflows/close-stale-issues.yml index 1ef583ec..9c448e11 100644 --- a/.github/workflows/close-stale-issues.yml +++ b/.github/workflows/close-stale-issues.yml @@ -8,7 +8,9 @@ jobs: stale: runs-on: ubuntu-latest steps: - - uses: actions/stale@v4 + # Comment on, then close issues that haven't been updated for ages + - name: Close Stale Issues + uses: actions/stale@v4 with: repo-token: ${{ secrets.BOT_GITHUB_TOKEN }} days-before-stale: 42 @@ -16,10 +18,16 @@ jobs: operations-per-run: 30 remove-stale-when-updated: true enable-statistics: true - stale-issue-message: 'This issue has gone 6 weeks without an update. To keep the ticket open, please indicate that it is still relevant in a comment below. Otherwise it will be closed in 5 working days.' - stale-pr-message: 'This PR is stale because it has been open 6 weeks with no activity. Either remove the stale label or comment below with a short update, otherwise this PR will be closed in 5 days.' - close-issue-message: 'This issue was automatically closed because it has been stalled for over 6 weeks with no activity.' - close-pr-message: 'This pull request was automatically closed because it has been stalled for over 6 weeks with no activity.' + stale-issue-message: > + This issue has gone 6 weeks without an update. To keep the ticket open, please indicate that it is still relevant in a comment below. + Otherwise it will be closed in 5 working days. + stale-pr-message: > + This PR is stale because it has been open 6 weeks with no activity. Either remove the stale label or comment below with a short update, + otherwise this PR will be closed in 5 days. + close-issue-message: > + This issue was automatically closed because it has been stalled for over 6 weeks with no activity. + close-pr-message: > + This pull request was automatically closed because it has been stalled for over 6 weeks with no activity. stale-issue-label: '⚰️ Stale' close-issue-label: '🕸️ Inactive' stale-pr-label: '⚰️ Stale' @@ -27,3 +35,23 @@ jobs: exempt-issue-labels: '📌 Keep Open' exempt-pr-labels: '📌 Keep Open' labels-to-add-when-unstale: '📌 Keep Open' + + # Comment on, then close issues that required a response from the user, but didn't get one + - name: Close Issues without Response + uses: actions/stale@v4 + with: + repo-token: ${{ secrets.BOT_GITHUB_TOKEN }} + days-before-stale: 7 + days-before-close: 3 + operations-per-run: 10 + remove-stale-when-updated: true + stale-issue-message: > + Hello! Looks like additional info is required for this issue to be addressed. + Don't forget to provide this within the next few days to keep your ticket open. + close-issue-message: 'Issue closed due to no response from user.' + only-labels: '🚏 Awaiting User Response' + labels-to-remove-when-unstale: '🚏 Awaiting User Response, 🛑 No Response' + stale-issue-label: '🛑 No Response' + close-issue-label: '🕸️ Inactive' + exempt-issue-labels: '📌 Keep Open' + exempt-pr-labels: '📌 Keep Open' From e54d662f7324fb20565a7b8a3f18a433d6a89e42 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Tue, 28 Sep 2021 18:22:46 +0100 Subject: [PATCH 019/391] =?UTF-8?q?=F0=9F=91=B7=20Adds=20action=20to=20rem?= =?UTF-8?q?ove=20stale=20label,=20on=20update?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/remove-stale-label.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 .github/workflows/remove-stale-label.yml diff --git a/.github/workflows/remove-stale-label.yml b/.github/workflows/remove-stale-label.yml new file mode 100644 index 00000000..aa266045 --- /dev/null +++ b/.github/workflows/remove-stale-label.yml @@ -0,0 +1,18 @@ +# When a new comment is added to an issue, if it had the Stale or Awaiting User Response labels, +# then those labels will be removed, providing it was not user lissy93 who added the commend. +name: 🎯 Remove Stale Label on Update +on: + issue_comment: + types: [created] +jobs: + remove-stale: + runs-on: ubuntu-latest + if: ${{ github.event.inputs.name != 'lissy93'}} + steps: + - name: Remove Stale labels when Updated + uses: actions-cool/issues-helper@v2 + with: + actions: remove-labels + token: ${{ secrets.BOT_GITHUB_TOKEN }} + issue-number: ${{ github.event.issue.number }} + labels: '🚏 Awaiting User Response,⚰️ Stale' From 9cb20dd0b0678f2de7ac4b756f163e056a2a0859 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Tue, 28 Sep 2021 18:37:56 +0100 Subject: [PATCH 020/391] =?UTF-8?q?=F0=9F=91=B7=20Skip=20event=20if=20comm?= =?UTF-8?q?ent=20was=20by=20liss-bot?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/remove-stale-label.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/remove-stale-label.yml b/.github/workflows/remove-stale-label.yml index aa266045..917a091a 100644 --- a/.github/workflows/remove-stale-label.yml +++ b/.github/workflows/remove-stale-label.yml @@ -7,7 +7,7 @@ on: jobs: remove-stale: runs-on: ubuntu-latest - if: ${{ github.event.inputs.name != 'lissy93'}} + if: ${{ !['liss-bot','lissy93'].includes(github.event.inputs.name.toLowerCase()) }} steps: - name: Remove Stale labels when Updated uses: actions-cool/issues-helper@v2 From 7623ea575ea4932c8df1463619f9e5f704600795 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Tue, 28 Sep 2021 20:56:39 +0100 Subject: [PATCH 021/391] :bookmark: Bumps to V 1.8.4 and updates changelog --- .github/CHANGELOG.md | 4 ++++ package.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md index a8514e76..b1f4fb38 100644 --- a/.github/CHANGELOG.md +++ b/.github/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## ✨ 1.8.4 - Custom Error Pages [PR #257](https://github.com/Lissy93/dashy/pull/257) +- Creates a 404 Not Found page +- Routes any missing views to the 404 page + ## ⚡️ 1.8.3 - Improved UX for Initial Load [PR #238](https://github.com/Lissy93/dashy/pull/238) - Removes the old splash screen - Adds placeholder in the HTML index, which will usually be visible on initial load diff --git a/package.json b/package.json index 023a0a46..7629a0cb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "Dashy", - "version": "1.8.3", + "version": "1.8.4", "license": "MIT", "main": "server", "scripts": { From 52fef039ca5db1fee50dd4387686298aa205c6ea Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Tue, 28 Sep 2021 20:59:22 +0100 Subject: [PATCH 022/391] :green_heart: Removed duplicate css property --- src/views/404.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/404.vue b/src/views/404.vue index 7024fc3d..8e067286 100644 --- a/src/views/404.vue +++ b/src/views/404.vue @@ -81,8 +81,8 @@ main.not-found-page { color: #0c0c0c; margin: 2rem 0 0; text-decoration: none; + background: #db78fc; box-shadow: 0 4px #b83ddd; - background: #db78fc; box-shadow: 0 4px #b83ddd; &:hover { box-shadow: 0 2px #b83ddd; } } ::selection { background-color: #db78fc; color: #121212; } From e84f09bb0aca2051fbcfd749fef4584029ba6d97 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Tue, 28 Sep 2021 21:07:35 +0100 Subject: [PATCH 023/391] :memo: Updates the Support docs and link --- .github/SUPPORT.md | 10 +++++++--- src/views/404.vue | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/.github/SUPPORT.md b/.github/SUPPORT.md index 28b82425..8ed0e88d 100644 --- a/.github/SUPPORT.md +++ b/.github/SUPPORT.md @@ -1,5 +1,9 @@ -# SUPPORT +# Support -For help with getting Dashy up and running, please see the [Discussion](https://github.com/Lissy93/dashy/discussions). +To raise a bug, please **[Open a new Issue](https://github.com/Lissy93/dashy/issues/new/choose)**. -If you'd like to help support Dashy's future development, see [Contributing](/docs/contributing.md) \ No newline at end of file +To report a potential vulnerability, please see **[Security](https://github.com/Lissy93/dashy/blob/master/.github/SECURITY.md#reporting-a-security-issue)**. + +For help with getting Dashy up and running, please see the **[Discussions](https://github.com/Lissy93/dashy/discussions)**. + +If you'd like to help support Dashy's future development, see **[Contributing](https://github.com/Lissy93/dashy/blob/master/docs/contributing.md)**. \ No newline at end of file diff --git a/src/views/404.vue b/src/views/404.vue index 8e067286..ef2c11f7 100644 --- a/src/views/404.vue +++ b/src/views/404.vue @@ -5,7 +5,7 @@

Page Not Found

Facing Issues? - Get Support. + Get Support.

Back Home From 5ae100b44f8cbd1c5455eb296030c1e232a2008f Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Tue, 28 Sep 2021 21:37:48 +0100 Subject: [PATCH 024/391] :sparkles: Adds support for home-lab icons --- docs/icons.md | 38 +++++++++++++++++++++++++++ src/components/LinkItems/ItemIcon.vue | 7 +++++ src/utils/defaults.js | 1 + 3 files changed, 46 insertions(+) diff --git a/docs/icons.md b/docs/icons.md index 2b4bcd53..7267dc81 100644 --- a/docs/icons.md +++ b/docs/icons.md @@ -94,6 +94,27 @@ For example, these will all render the same rocket (🚀) emoji: `icon: ':rocket --- +## Home-Lab Icons + +The [dashboard-icons](https://github.com/WalkxCode/dashboard-icons) repo by [@WalkxCode](https://github.com/WalkxCode) provides a comprehensive collection of 360+ high-quality PNG icons for commonly self-hosted services. Dashy natively supports these icons, and you can use them just by specifying the icon name (without extension) preceded by `hl-`. You can see a full list of all available icons [here](https://github.com/WalkxCode/dashboard-icons/tree/master/png). + +For example: +```yaml +sections: +- name: Home Lab Icons Example + items: + - title: AdGuard Home + icon: hl-adguardhome + - title: Long Horn + icon: hl-longhorn + - title: Nagios + icon: hl-nagios + - title: Whoogle Search + icon: hl-whooglesearch +``` + +--- + ## Icons by URL You can also set an icon by passing in a valid URL pointing to the icons location. For example `icon: https://i.ibb.co/710B3Yc/space-invader-x256.png`, this can be in .png, .jpg or .svg format, and hosted anywhere- so long as it's accessible from where you are hosting Dashy. The icon will be automatically scaled to fit, however loading in a lot of large icons may have a negative impact on performance, especially if you visit Dashy from new devices often. @@ -127,3 +148,20 @@ sections: ## No Icon If you don't wish for a given item or section to have an icon, just leave out the `icon` attribute. + + +--- + +## Icon Collections and Resources + +The following website provide good-quality, free icon sets. To use any of these icons, just copy the link to the raw icon (it should end in `.svg` or `.png`) and paste it as your `icon`, or download and save the icons in `/public/item-icons` or pass through with a Docker volume as described above. +Full credit to the authors, please see the licenses for each service for usage and copyright information. + +- [dashboard-icons](https://github.com/WalkxCode/dashboard-icons) - 350+ high-quality icons for commonly self-hosted services, maintained by [@WalkxCode](https://github.com/WalkxCode) +- [SVG Box](https://svgbox.net/iconsets/) - Cryptocurrency, social media apps and flag icons +- [Simple Icons](https://simpleicons.org/) - Free SVG brand icons, with easy API access +- [Icons8](https://icons8.com/icons) - Thousands of icons, all with free 64x64 versions +- [Flat Icon](https://www.flaticon.com/) - Wide variety of icon sets, almost all free to use + +If you are a student, then you can get free access to premium icons on [Icon Scout](https://education.github.com/pack/redeem/iconscout-student) or [Icons8](https://icons8.com/github-students) using the GitHub Student Pack. + diff --git a/src/components/LinkItems/ItemIcon.vue b/src/components/LinkItems/ItemIcon.vue index b8c3f9c6..0696e5d8 100644 --- a/src/components/LinkItems/ItemIcon.vue +++ b/src/components/LinkItems/ItemIcon.vue @@ -135,6 +135,11 @@ export default { const icon = simpleIcons.Get(imageName); return icon.path; }, + /* Gets home-lab icon from GitHub */ + getHomeLabIcon(img) { + const imageName = img.replace('hl-', '').toLocaleLowerCase(); + return `${iconCdns.homeLabIcons}/png/${imageName}.png`; + }, /* Checks if the icon is from a local image, remote URL, SVG or font-awesome */ getIconPath(img, url) { switch (this.determineImageType(img)) { @@ -145,6 +150,7 @@ export default { case 'generative': return this.getGenerativeIcon(url); case 'mdi': return img; // Material design icons case 'simple-icons': return this.getSimpleIcon(img); + case 'home-lab-icons': return this.getHomeLabIcon(img); case 'svg': return img; // Local SVG icon case 'emoji': return img; // Emoji/ unicode default: return ''; @@ -159,6 +165,7 @@ export default { else if (img.includes('fa-')) imgType = 'font-awesome'; else if (img.includes('mdi-')) imgType = 'mdi'; else if (img.includes('si-')) imgType = 'si'; + else if (img.includes('hl-')) imgType = 'home-lab-icons'; else if (img.includes('favicon-')) imgType = 'custom-favicon'; else if (img === 'favicon') imgType = 'favicon'; else if (img === 'generative') imgType = 'generative'; diff --git a/src/utils/defaults.js b/src/utils/defaults.js index 49fa263c..387d26e4 100644 --- a/src/utils/defaults.js +++ b/src/utils/defaults.js @@ -176,6 +176,7 @@ module.exports = { generative: 'https://ipsicon.io', localPath: '/item-icons', faviconName: 'favicon.ico', + homeLabIcons: 'https://raw.githubusercontent.com/WalkxCode/dashboard-icons/master/', }, /* URLs for web search engines */ searchEngineUrls: { From cf92331d8e050b4942a778dfe80f6739d82104de Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Tue, 28 Sep 2021 22:07:13 +0100 Subject: [PATCH 025/391] =?UTF-8?q?=F0=9F=90=9B=20Fix=20(hopefully)=20user?= =?UTF-8?q?name=20ignore=20check?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/remove-stale-label.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/remove-stale-label.yml b/.github/workflows/remove-stale-label.yml index 917a091a..6eab2210 100644 --- a/.github/workflows/remove-stale-label.yml +++ b/.github/workflows/remove-stale-label.yml @@ -7,7 +7,7 @@ on: jobs: remove-stale: runs-on: ubuntu-latest - if: ${{ !['liss-bot','lissy93'].includes(github.event.inputs.name.toLowerCase()) }} + if: ${{ github.event.inputs.name != 'liss-bot' }} steps: - name: Remove Stale labels when Updated uses: actions-cool/issues-helper@v2 From 66e4ada28f0bfd077bc5fcbedd5b8400efe86de1 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Wed, 29 Sep 2021 19:43:58 +0100 Subject: [PATCH 026/391] :memo: Updates privacy docs, re Generative icons --- docs/privacy.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/privacy.md b/docs/privacy.md index 76d3c271..434fac1d 100644 --- a/docs/privacy.md +++ b/docs/privacy.md @@ -18,6 +18,10 @@ If an item's icon is set to `favicon`, then it will be auto-fetched from the cor The default favicon API is [Favicon Kit](https://faviconkit.com/), but this can be changed by setting `appConfig.faviconApi` to an alternate source (`google`, `clearbit`, `webmasterapi` and `allesedv` are supported). If you do not want to use any API, then you can set this property to `local`, and the favicon will be fetched from the default path. For hosted services, this will still incur an external request. +### Generative Icons +If an item has the icon set to `generative`, then an external request it made to [Dice Bear](https://dicebear.com/) to fetch the uniquely generated icon. The URL of a given service is used as the key for generating the icon, but it is first hashed and encoded for basic privacy. For more info, please reference the [Dicebear Privacy Policy](https://avatars.dicebear.com/legal/privacy-policy) + + ### Other Icons Section icons, item icons and app icons are able to accept a URL to a raw image, if the image is hosted online then an external request will be made. To avoid the need to make external requests for icon assets, you can either use a self-hosted CDN, or store your images within `./public/item-icons` (which can be mounted as a volume if you're using Docker). From 5ec2abcf81c11dcd43e7da172dd7633878b5f291 Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Wed, 29 Sep 2021 19:46:04 +0100 Subject: [PATCH 027/391] :alien: New API for generative icons, Re: #163 --- docs/icons.md | 9 +++++++-- src/components/LinkItems/ItemIcon.vue | 8 +++++--- src/utils/MiscHelpers.js | 9 ++++++++- src/utils/defaults.js | 4 ++-- 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/docs/icons.md b/docs/icons.md index 7267dc81..df0b5850 100644 --- a/docs/icons.md +++ b/docs/icons.md @@ -75,10 +75,10 @@ If for a given service none of the APIs work in your situation, and nor does loc --- ## Generative Icons -Uses a unique and programmatically generated icon for a given service. This is particularly useful when you have a lot of similar services with a different IP or port, and no specific icon. These icons are generated with [ipsicon.io](https://ipsicon.io/). To use this option, just set an item's to: `icon: generative`. +Uses a unique and programmatically generated icon for a given service. This is particularly useful when you have a lot of similar services with a different IP or port, and no specific icon. These icons are generated with [DiceBear](https://avatars.dicebear.com/), and use a hash of the services domain/ ip for entropy, so each domain will always have the same icon. To use this option, just set an item's to: `icon: generative`.

- +

--- @@ -113,6 +113,11 @@ sections: icon: hl-whooglesearch ``` + +

+ +

+ --- ## Icons by URL diff --git a/src/components/LinkItems/ItemIcon.vue b/src/components/LinkItems/ItemIcon.vue index 0696e5d8..45aa5f1a 100644 --- a/src/components/LinkItems/ItemIcon.vue +++ b/src/components/LinkItems/ItemIcon.vue @@ -23,9 +23,10 @@ import simpleIcons from 'simple-icons'; import BrokenImage from '@/assets/interface-icons/broken-icon.svg'; import ErrorHandler from '@/utils/ErrorHandler'; -import { faviconApi as defaultFaviconApi, faviconApiEndpoints, iconCdns } from '@/utils/defaults'; import EmojiUnicodeRegex from '@/utils/EmojiUnicodeRegex'; import emojiLookup from '@/utils/emojis.json'; +import { faviconApi as defaultFaviconApi, faviconApiEndpoints, iconCdns } from '@/utils/defaults'; +import { asciiHash } from '@/utils/MiscHelpers'; export default { name: 'Icon', @@ -127,7 +128,8 @@ export default { }, /* Formats the URL for fetching the generative icons */ getGenerativeIcon(url) { - return `${iconCdns.generative}/${this.getHostName(url)}.svg`; + const host = encodeURI(url) || Math.random().toString(); + return iconCdns.generative.replace('{icon}', asciiHash(host)); }, /* Returns the SVG path content */ getSimpleIcon(img) { @@ -138,7 +140,7 @@ export default { /* Gets home-lab icon from GitHub */ getHomeLabIcon(img) { const imageName = img.replace('hl-', '').toLocaleLowerCase(); - return `${iconCdns.homeLabIcons}/png/${imageName}.png`; + return iconCdns.homeLabIcons.replace('{icon}', imageName); }, /* Checks if the icon is from a local image, remote URL, SVG or font-awesome */ getIconPath(img, url) { diff --git a/src/utils/MiscHelpers.js b/src/utils/MiscHelpers.js index 212e7495..add6f457 100644 --- a/src/utils/MiscHelpers.js +++ b/src/utils/MiscHelpers.js @@ -3,4 +3,11 @@ 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; +/* Very rudimentary hash function for generative icons */ +export const asciiHash = (input) => { + const str = (!input || input.length === 0) ? Math.random().toString() : input; + const reducer = (previousHash, char) => (previousHash || 0) + char.charCodeAt(0); + const asciiSum = str.split('').reduce(reducer).toString(); + const shortened = asciiSum.slice(0, 30) + asciiSum.slice(asciiSum.length - 30); + return window.btoa(shortened); +}; diff --git a/src/utils/defaults.js b/src/utils/defaults.js index 387d26e4..2a475d45 100644 --- a/src/utils/defaults.js +++ b/src/utils/defaults.js @@ -173,10 +173,10 @@ module.exports = { fa: 'https://kit.fontawesome.com', mdi: 'https://cdn.jsdelivr.net/npm/@mdi/font@5.9.55/css/materialdesignicons.min.css', si: 'https://unpkg.com/simple-icons@v5/icons', - generative: 'https://ipsicon.io', + generative: 'https://avatars.dicebear.com/api/identicon/{icon}.svg', localPath: '/item-icons', faviconName: 'favicon.ico', - homeLabIcons: 'https://raw.githubusercontent.com/WalkxCode/dashboard-icons/master/', + homeLabIcons: 'https://raw.githubusercontent.com/WalkxCode/dashboard-icons/master/png/{icon}.png', }, /* URLs for web search engines */ searchEngineUrls: { From 2f1dd2a9fa002e22e4735fe07303a0ebed65703c Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Wed, 29 Sep 2021 20:26:24 +0100 Subject: [PATCH 028/391] :sparkles: Re: #255 - Adds an option for landing URL in workspace --- docs/alternate-views.md | 4 +++- src/components/Workspace/SideBar.vue | 14 ++++++++++++++ src/views/Workspace.vue | 19 ++++++++++++------- 3 files changed, 29 insertions(+), 8 deletions(-) diff --git a/docs/alternate-views.md b/docs/alternate-views.md index de72cd1a..29dc032c 100644 --- a/docs/alternate-views.md +++ b/docs/alternate-views.md @@ -14,7 +14,9 @@ This is the main page that you will land on when you first launch the applicatio ### Workspace The workspace view displays your links in a sidebar on the left-hand side, and apps are launched within Dashy. This enables you to use all of your self-hosted apps from one place, and makes multi-tasking easy. -In the workspace view, you can keep previously opened websites/ apps open in the background, by setting `appConfig.enableMultiTasking: true`. This comes at the cost of performance, but does mean that your session with each app is preserved, enabling you to quickly switch between your apps. +In the workspace view, you can opt to keep previously opened websites/ apps open in the background, by setting `appConfig.enableMultiTasking: true`. This comes at the cost of performance, but does mean that your session with each app is preserved, enabling you to quickly switch between your apps. + +You can also specify a default app to be opened when you land on the workspace, by setting `appConfig.workspaceLandingUrl: https://app-to-open/`. If this app exists within your sections.items, then the corresponding section will also be expanded.

Example of Workspace View
diff --git a/src/components/Workspace/SideBar.vue b/src/components/Workspace/SideBar.vue index b75fba72..e3115d17 100644 --- a/src/components/Workspace/SideBar.vue +++ b/src/components/Workspace/SideBar.vue @@ -39,6 +39,7 @@ export default { inject: ['config'], props: { sections: Array, + initUrl: String, }, data() { return { @@ -56,9 +57,22 @@ export default { openSection(index) { this.isOpen = this.isOpen.map((val, ind) => (ind !== index ? false : !val)); }, + /* When item clicked, emit a launch event */ launchApp(url) { this.$emit('launch-app', url); }, + /* If an initial URL is specified, then open relevant section */ + openDefaultSection() { + if (!this.initUrl) return; + const process = (url) => url.replace(/[^\w\s]/gi, '').toLowerCase(); + const compare = (item) => (process(item.url) === process(this.initUrl)); + this.sections.forEach((section, sectionIndex) => { + if (section.items.findIndex(compare) !== -1) this.openSection(sectionIndex); + }); + }, + }, + mounted() { + this.openDefaultSection(); }, }; diff --git a/src/views/Workspace.vue b/src/views/Workspace.vue index 2878885c..bebbba1e 100644 --- a/src/views/Workspace.vue +++ b/src/views/Workspace.vue @@ -1,6 +1,6 @@