diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 98f2ab52fb..3e80d1ec73 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,18 +1,30 @@ -**Please check the type of change your PR introduces**: -- [ ] Bugfix -- [ ] Feature -- [ ] Code style update (formatting, renaming) -- [ ] Refactoring (no functional changes, no api changes) -- [ ] Build related changes -- [ ] Documentation content changes -- [ ] Other (please describe): - -**Issue Number** (if applicable): - -**Briefly outline your changes**: - -**Before submitting, please ensure that**: -- [ ] Must be backwards compatible -- [ ] All lint checks and tests must pass -- [ ] If a new option in the the config file is added, it needs to be added into the schema, and documented in the configuring guide -- [ ] If a new dependency is required, it must be essential, and it must be thoroughly checked out for security or efficiency issues +**Thank you for contributing to Dashy! So that your PR can be handled effectively, please populate the following fields (delete sections that are not applicable)** + +### Category +> Please indicate the type of change your PR introduces + +Bugfix / Feature / Code style update / Refactoring Only / Build related changes / Documentation / Other (please specify) + + +### Overview +> Briefly outline your new changes... + + +### Issue Number _(if applicable)_ +#00 + +### New Vars _(if applicable)_ +> If you've added any new build scripts, environmental variables, config file options, dependency or devDependency, please outline here + + +### Screenshot _(if applicable)_ +> If you've introduced any significant UI changes, please include a screenshot + + +### Code Quality Checklist _(Please complete)_ +- [ ] All changes are backwards compatible +- [ ] All lint checks and tests are passing +- [ ] There are no (new) build warnings or errors +- [ ] _(If a new config option is added)_ Attribute is outlined in the schema and documented +- [ ] _(If a new dependency is added)_ Package is essential, and has been checked out for security or performance + diff --git a/.github/workflows/webpack-analyzer.yml b/.github/workflows/webpack-analyzer.yml deleted file mode 100644 index d59b3daf1c..0000000000 --- a/.github/workflows/webpack-analyzer.yml +++ /dev/null @@ -1,12 +0,0 @@ -on: push -name: packtracker.io -jobs: - report: - name: Report webpack stats - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@master - - name: report webpack stats - uses: packtracker/report@2.2.7 - env: - PT_PROJECT_TOKEN: ${{ secrets.PT_PROJECT_TOKEN }} diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000..05cc619f1e --- /dev/null +++ b/LICENSE @@ -0,0 +1,17 @@ +Licensed under MIT X11. Copyright © 2021 Alicia Sykes + +Permission is hereby granted, free of charge, to any person obtaining a copy of this +software and associated documentation files (the “Software”), to deal in the Software +without restriction, including without limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWAREOR THE USE +OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index 2a3c550b44..ba349cffcd 100644 --- a/README.md +++ b/README.md @@ -2,14 +2,18 @@

Dashy

Dashy helps you organize your self-hosted services, by making them all accessible from a single place

-

- -

-

+[![Awesome Self-Hosted](https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg)](https://github.com/awesome-selfhosted/awesome-selfhosted#personal-dashboards) +![Docker Pulls](https://img.shields.io/docker/pulls/lissy93/dashy?logo=docker&style=flat-square) +![Stars](https://flat.badgen.net/github/stars/lissy93/dashy?icon=github) +![Current Version](https://img.shields.io/github/package-json/v/lissy93/dashy?style=flat-square&logo=azurepipelines&color=00af87) +![GitHub Status](https://flat.badgen.net/github/status/lissy93/dashy?icon=github) +![App Size](https://img.shields.io/github/languages/code-size/lissy93/dashy?style=flat-square) +![Code Quality](https://app.codacy.com/project/badge/Grade/3be23a4a3a8a4689bd47745b201ecb74) +![Dependencies](https://img.shields.io/david/lissy93/dashy?style=flat-square) ## Features 🌈 @@ -22,7 +26,6 @@ - Option to show service status for each of your apps / links, for basic availability and uptime monitoring - Additional info for each item visible on hover (including opening method icon and description as a tooltip) - Option for full-screen background image, custom nav-bar links, and custom footer text -- User preferences stored in local storage and applied on load - Encrypted cloud backup and restore feature available - Optional authentication, requiring user to log in - Easy single-file YAML-based configuration @@ -67,7 +70,7 @@ docker run -d \ --restart=always \ lissy93/dashy:latest ``` -After making changes to your configuration file, you will need to run: `docker exec -it [container-id] yarn build` to rebuild. You can also run other commands, such as `yarn validate-config` this way too. Container ID can be found by running `docker ps`. Healthchecks are pre-configured to monitor the uptime and response times of Dashy, and the status of which can be seen in the container logs, e.g. `docker inspect --format "{{json .State.Health }}" [container-id]`. +Healthchecks are pre-configured to monitor the uptime and response times of Dashy, and the status of which can be seen in the container logs, e.g. `docker inspect --format "{{json .State.Health }}" [container-id]`. #### Deploying from Source 🚀 @@ -79,8 +82,6 @@ You will need both [git](https://git-scm.com/downloads) and the latest or LTS ve - Build: `yarn build` - Run: `yarn start` -After making changes to your configuration file, you will need to run: `yarn build` to rebuild. - #### Deploy to the Cloud Dashy supports 1-Click deployments on several popular cloud platforms (with more on the way!). To get started, just click a link below: @@ -91,6 +92,21 @@ Dashy supports 1-Click deployments on several popular cloud platforms (with more **[⬆️ Back to Top](#dashy)** +#### Basic Commands + +The following commands can be run on Dashy. If you are using Docker, than precede each command with `docker exec -it [container-id]`, where container id can be found by running `docker ps`, e.g. `docker exec -it 92490c12baff yarn build`. +If you prefer [`NPM`](https://docs.npmjs.com), then just replace `yarn` with `npm run` in the following commands. + +- `yarn build` - Builds the project for production, and outputs it into `./dist` +- `yarn start` - Starts a web server, and serves up the production site from `./dist` +- `yarn validate-config` - Parses and validates your `conf.yml` against Dashy's [schema](https://github.com/Lissy93/dashy/blob/master/src/utils/ConfigSchema.json) +- `yarn health-check` - Checks the health and status of Dashy's Node server +- `yarn pm2-start` - Starts the app using the [PM2](https://pm2.keymetrics.io/) process manager +- `yarn dev` - Starts the development server with hot reloading, linting, testing and verbose messaging +- `yarn lint` - Lints code to ensure it follows a consistent neat style +- `yarn test` - Runs tests, and outputs results +- `yarn install` - Install all dependencies + --- ## Configuring 🔧 @@ -133,17 +149,19 @@ You can also apply custom CSS overrides directly through the UI (Under Config me > For full iconography documentation, see: [**Icons**](./docs/icons.md) -Both sections and items can have an icon associated with them, and defined under the `icon` attribute. There are many options for icons, including Font Awesome support, automatic fetching from favicon, programmatically generated icons and of course URLs. +Both sections and items can have an icon associated with them, and defined under the `icon` attribute. There are many options for icons, including Font Awesome support, automatic fetching from favicon, programmatically generated icons and direct local or remote URLs.

-- Set `icon: favicon` to fetch a services icon automatically from the URL of the corresponding application -- To use any font-awesome icon, specify the category, followed by the icon name, e.g. `fas fa-rocket`, `fab fa-monero` or `fas fa-unicorn`. You can also use Pro icons by setting your API key under `appConfig.fontAwesomeKey` -- If you set `icon: generative`, then a unique icon is generated from the apps URL or IP -- You can also host an icon either locally or using any CDN service, then just pass it's URL into the icon attribute, e.g. `icon: https://i.ibb.co/710B3Yc/space-invader-x256.png`. -- To use a local image, store it in `./public/item-icons/` (or `-v /app/public/item-icons/` in Docker) , and reference it by name and extension - e.g. set `icon: image.png` to use `./public/item-icon/image.png`, you can also use sub-folders here if you have a lot of icons, to keep them organised. +- **Favicon**: Set `icon: favicon` to fetch a services icon automatically from the URL of the corresponding application +- **Font-Awesome**: To use any font-awesome icon, specify the category, followed by the icon name, e.g. `fas fa-rocket` or `fab fa-monero`. You can also use Pro icons if you have a license key, just set it under `appConfig.fontAwesomeKey` +- **Generative**: Setting `icon: generative`, will generate a unique for a given service, based on it's URL or IP +- **URL**: You can also pass in a URL to an icon asset, hosted either locally or using any CDN service. E.g. `icon: https://i.ibb.co/710B3Yc/space-invader-x256.png`. +- **Local Image**: To use a local image, store it in `./public/item-icons/` (or create a volume in Docker: `-v /local/image/directory:/app/public/item-icons/`) , and reference it by name and extension - e.g. set `icon: image.png` to use `./public/item-icon/image.png`. You can also use sub-folders here if you have a lot of icons, to keep them organized. + +**[⬆️ Back to Top](#dashy)** --- @@ -183,7 +201,9 @@ At present, access control is handled on the frontend, and therefore in security > For full monitoring documentation, see: [**Status Indicators**](./docs/status-indicators.md) -Dashy has an optional feature that can display a small icon ([like this](./docs/assets/status-check-demo.gif)) next to each of your running services, indicating it's current status. This is useful if you are using Dashy as your homelab's start page, as it gives you an overview of the health of each of your running services. By default, this feature is off, but you can enable it globally by setting `appConfig.statusCheck: true`, or enable/ disable it for an individual item, with `item[n].statusCheck`. +Dashy has an optional feature that can display a small icon ([like this](./docs/assets/status-check-demo.gif)) next to each of your running services, indicating it's current status. This is useful if you are using Dashy as your homelab's start page, as it gives you an overview of the health of each of your running services. Hovering over the indicator will show additional information, including average response time and an error message for services which are down. + +By default, this feature is off, but you can enable it globally by setting `appConfig.statusCheck: true`, or enable/ disable it for an individual item, with `item[n].statusCheck`. You can also specify an time interval in seconds under `appConfig.statusCheckInterval`, which will determine how often to recheck services, if this value is `0`, then status is only checked on initial page load, this is default behavior. **[⬆️ Back to Top](#dashy)** @@ -220,6 +240,20 @@ Before you submit your pull request, please ensure the following: - If a new dependency is required, it must be essential, and it must be thoroughly checked out for security or efficiency issues - Your pull request will need to be up-to-date with master, and the PR template must be filled in +### Repo Status +![Open Issues](https://flat.badgen.net/github/open-issues/lissy93/dashy?icon=github) +![Closed Issues](https://flat.badgen.net/github/closed-issues/lissy93/dashy?icon=github) +![Open PRs](https://flat.badgen.net/github/open-prs/lissy93/dashy?icon=github) +![Total PRs](https://flat.badgen.net/github/prs/lissy93/dashy?icon=github) +![GitHub commit activity](https://img.shields.io/github/commit-activity/m/lissy93/dashy?style=flat-square) +![Last Commit](https://flat.badgen.net/github/last-commit/lissy93/dashy?icon=github) +![Contributors](https://flat.badgen.net/github/contributors/lissy93/dashy?icon=github) +![GitHub Status](https://flat.badgen.net/github/status/lissy93/dashy?icon=github) +![Stars](https://flat.badgen.net/github/stars/lissy93/dashy?icon=github) +![Docker Pulls](https://img.shields.io/docker/pulls/lissy93/dashy?logo=docker&style=flat-square) +![Total Lines](https://img.shields.io/tokei/lines/github/lissy93/dashy?style=flat-square) +![Maintenance](https://img.shields.io/maintenance/yes/2021?style=flat-square) + **[⬆️ Back to Top](#dashy)** --- @@ -326,6 +360,14 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWAREOR THE OR OTHER DEALINGS IN THE SOFTWARE. ``` +**TDLR;** _You can do whatever you like with Dashy: use it in private or commercial settings,_ +_redistribute and modify it. But you must display this license and credit the author._ +_There is no warranty that this app will work as expected, and the author cannot be held_ +_liable for anything that goes wrong._ For more info, see +[TLDR Legal's MIT Explanation of the MIT License](https://tldrlegal.com/license/mit-license) + +![Octocat](https://github.githubassets.com/images/icons/emoji/octocat.png?v8) + **[⬆️ Back to Top](#dashy)** --- diff --git a/docs/authentication.md b/docs/authentication.md index 1d5b5413b6..4cba3e5bdf 100644 --- a/docs/authentication.md +++ b/docs/authentication.md @@ -39,9 +39,9 @@ Once authentication is enabled, so long as there is no valid token in cookie sto ## Security Since all authentication is happening entirely on the client-side, it is vulnerable to manipulation by an adversary. An attacker could look at the source code, find the function used generate the auth token, then decode the minified JavaScript to find the hash, and manually generate a token using it, then just insert that value as a cookie using the console, and become a logged in user. Therefore, if you need secure authentication for your app, it is strongly recommended to implement this using your web server, or use a VPN to control access to Dashy. The purpose of the login page is merely to prevent immediate unauthorized access to your homepage. -Addressing this is on the todo list, and there are two potential solutions: +Addressing this is on the todo list, and there are several potential solutions: 1. Encrypt all site data against the users password, so that an attacker can not physically access any data without the correct decryption key -2. Use a backend service to handle authentication, and do not return user data from the server until the correct credentials are provided. However, this would require either Dashy to be run using it's Node.js server, or the use of an external service +2. Use a backend service to handle authentication and configuration, with no user data returned from the server until the correct credentials are provided. However, this would require either Dashy to be run using it's Node.js server, or the use of an external service 3. Implement authentication using a self-hosted identity management solution, such as [Keycloak for Vue](https://www.keycloak.org/securing-apps/vue) **[⬆️ Back to Top](#authentication)** @@ -50,13 +50,13 @@ Addressing this is on the todo list, and there are two potential solutions: ## Alternative Authentication Methods -If you are hosting Dashy locally, and require remote access, it is recommend to configure a VPN connection into your local network. For instances running on the cloud, you have several other options: -- Authentication Server -- VPN -- IP-Based Access -- Web Server Authentication -- OAuth Services -- Password Protection (for cloud providers) +If you are self-hosting Dashy, and require secure authentication to prevent unauthorized access, you have several options: +- [Authentication Server](#authentication-server) - Put Dashy behind a self-hosted auth server +- [VPN](#vpn) - Use a VPN to tunnel into the network where Dashy is running +- [IP-Based Access](#ip-based-access) - Disallow access from all IP addresses, except your own +- [Web Server Authentication](#web-server-authentication) - Enable user control within your web server or proxy +- [OAuth Services](#oauth-services) - Implement a user management system using a cloud provider +- [Password Protection (for cloud providers)](#static-site-hosting-providers) - Enable password-protection on your site ### Authentication Server ##### Authelia @@ -141,6 +141,8 @@ basicauth /secret/* { } ``` +For more info about implementing a single sign on for all your apps with Caddy, see [this tutorial](https://joshstrange.com/securing-your-self-hosted-apps-with-single-signon/) + ##### Lighttpd You can use the [mod_auth](https://doc.lighttpd.net/lighttpd2/mod_auth.html) module to secure your site with Lighttpd. Like with Apache, you need to first create a password file listing your usersnames and hashed passwords, but in Lighttpd, it's usually called `.lighttpdpassword`. diff --git a/docs/configuring.md b/docs/configuring.md index fe49336cb1..6018730f2c 100644 --- a/docs/configuring.md +++ b/docs/configuring.md @@ -55,6 +55,8 @@ All fields are optional, unless otherwise stated. **Field** | **Type** | **Required**| **Description** --- | --- | --- | --- +**`statusCheck`** | `boolean` | _Optional_ | When set to `true`, Dashy will ping each of your services and display their status as a dot next to each item. This can be overridden by setting `statusCheck` under each item. Defaults to `false` +**`statusCheckInterval`** | `boolean` | _Optional_ | The number of seconds between checks. If set to `0` then service will only be checked on initial page load, which is usually the desired functionality. If value is less than `10` you may experience a hit in performance. Defaults to `0` **`backgroundImg`** | `string` | _Optional_ | Path to an optional full-screen app background image. This can be either remote (http) or local (/). Note that this will slow down initial load **`enableFontAwesome`** | `boolean` | _Optional_ | Where `true` is enabled, if left blank font-awesome will be enabled only if required by 1 or more icons **`fontAwesomeKey`** | `string` | _Optional_ | If you have a font-awesome key, then you can use it here and make use of premium icons. It is a 10-digit alpha-numeric string from you're FA kit URL (e.g. `13014ae648`) @@ -68,6 +70,7 @@ All fields are optional, unless otherwise stated. **`showSplashScreen`** | `boolean` | _Optional_ | Should display a splash screen while the app is loading. Defaults to false, except on first load **`auth`** | `array` | _Optional_ | An array of objects containing usernames and hashed passwords. If this is not provided, then authentication will be off by default, and you will not need any credentials to access the app. Note authentication is done on the client side, and so if your instance of Dashy is exposed to the internet, it is recommend to configure your web server to handle this. See [`auth`](#appconfigauth-optional) **`allowConfigEdit`** | `boolean` | _Optional_ | Should prevent / allow the user to write configuration changes to the conf.yml from the UI. When set to `false`, the user can only apply changes locally using the config editor within the app, whereas if set to `true` then changes can be written to disk directly through the UI. Defaults to `true`. Note that if authentication is enabled, the user must be of type `admin` in order to apply changes globally. +**`disableServiceWorker`** | `boolean` | _Optional_ | Service workers cache web applications to improve load times and offer basic offline functionality, and are enabled by default in Dashy. The service worker can sometimes cause older content to be cached, requiring the app to be hard-refreshed. If you do not want SW functionality, or are having issues with caching, set this property to `true` to disable all service workers. **[⬆️ Back to Top](#configuring)** @@ -101,6 +104,7 @@ All fields are optional, unless otherwise stated. **`url`** | `string` | Required | The URL / location of web address for when the item is clicked **`icon`** | `string` | _Optional_ | The icon for a given item. Can be a font-awesome icon, favicon, remote URL or local URL. See [`item.icon`](#sectionicon-and-sectionitemicon) **`target`** | `string` | _Optional_ | The opening method for when the item is clicked, either `newtab`, `sametab` or `iframe`. Where `newtab` will open the link in a new tab, `sametab` will open it in the current tab, and `iframe` will open a pop-up modal with the content displayed within that iframe. Note that for the iframe to load, you must have set the CORS headers to either allow `*` ot allow the domain that you are hosting Dashy on, for some websites and self-hosted services, this is already set. +**`statusCheck`** | `boolean` | _Optional_ | When set to `true`, Dashy will ping the URL associated with the current service, and display its status as a dot next to the item. The value here will override `appConfig.statusCheck` so you can turn off or on checks for a given service. Defaults to `appConfig.statusCheck`, falls back to `false` **`color`** | `string` | _Optional_ | An optional color for the text and font-awesome icon to be displayed in. Note that this will override the current theme and so may not display well **`backgroundColor`** | `string` | _Optional_ | An optional background fill color for the that given item. Again, this will override the current theme and so might not display well against the background diff --git a/docs/deployment.md b/docs/deployment.md index c867d7a659..158d53cbf2 100644 --- a/docs/deployment.md +++ b/docs/deployment.md @@ -218,6 +218,25 @@ For Podman, you can use `systemd` to create a service that launches your contain To restart the container after something within it has crashed, consider using [`docker-autoheal`](https://github.com/willfarrell/docker-autoheal) by @willfarrell, a service that monitors and restarts unhealthy containers. For more info, see the [Healthchecks](#healthchecks) section above. +### Securing + +##### SSL + +Enabling HTTPS with an SSL certificate is recommended if you hare hosting Dashy anywhere other than your home. This will ensure that all traffic is encrypted in transit. + +[Let's Encrypt](https://letsencrypt.org/docs/) is a global Certificate Authority, providing free SSL/TLS Domain Validation certificates in order to enable secure HTTPS access to your website. They have good browser/ OS [compatibility](https://letsencrypt.org/docs/certificate-compatibility/) with their ISRG X1 and DST CA X3 root certificates, support [Wildcard issuance](https://community.letsencrypt.org/t/acme-v2-production-environment-wildcards/55578) done via ACMEv2 using the DNS-01 and have [Multi-Perspective Validation](https://letsencrypt.org/2020/02/19/multi-perspective-validation.html). Let's Encrypt provide [CertBot](https://certbot.eff.org/) an easy app for generating and setting up an SSL certificate + +[ZeroSSL](https://zerossl.com/) is another popular certificate issuer, they are free for personal use, and also provide easy-to-use tools for getting things setup. + + +If you're hosting Dashy behind Cloudflare, then they offer [free and easy SSL](https://www.cloudflare.com/en-gb/learning/ssl/what-is-an-ssl-certificate/). + +If you're not so comfortable on the command line, then you can use a tool like [SSL For Free](https://www.sslforfree.com/) to generate your Let's Encrypt or ZeroSSL certificate, and support shared hosting servers. They also provide step-by-step tutorials on setting up your certificate on most common platforms. If you are using shared hosting, you may find [this tutorial](https://www.sitepoint.com/a-guide-to-setting-up-lets-encrypt-ssl-on-shared-hosting/) helpful. + +##### Authentication +Dashy has [basic authentication](/docs/authentication.md) built in, however at present this is handled on the front-end, and so where security is critical, it is recommended to use an alternative method. See [here](/docs/authentication.md#alternative-authentication-methods) for options regarding securing Dashy. + + **[⬆️ Back to Top](#deployment)** --- diff --git a/docs/icons.md b/docs/icons.md index a48c8cc363..e7d7b0dced 100644 --- a/docs/icons.md +++ b/docs/icons.md @@ -9,6 +9,10 @@ Both sections and items can have an icon, which is specified using the `icon` at - [Local Icons](#local-icons) - [No Icon](#no-icon) +

+ +

+ ### Font Awesome You can use any [Font Awesome Icon](https://fontawesome.com/icons) simply by specifying it's identifier. This is in the format of `[category] [name]` and can be found on the page for any given icon on the Font Awesome site. For example: `fas fa-rocket`, `fab fa-monero` or `fas fa-unicorn`. @@ -35,7 +39,7 @@ Uses a unique and programmatically generated icon for a given service. This is p 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. ### Local Icons -You may also want to store your icons locally, bundled within Dashy so that there is no reliance on outside services. This can be done by putting the icons within Dashy's ./public/item-icons/` directory. If you are using Docker, then the easiest option is to map a volume from your host system, for example: `-v /local/image/directory:/app/public/item-icons/`. To reference an icon stored locally, just specify it's name and extension. For example, if my icon was stored in `/app/public/item-icons/maltrail.png`, then I would just set `icon: maltrail.png`. +You may also want to store your icons locally, bundled within Dashy so that there is no reliance on outside services. This can be done by putting the icons within Dashy's `./public/item-icons/` directory. If you are using Docker, then the easiest option is to map a volume from your host system, for example: `-v /local/image/directory:/app/public/item-icons/`. To reference an icon stored locally, just specify it's name and extension. For example, if my icon was stored in `/app/public/item-icons/maltrail.png`, then I would just set `icon: maltrail.png`. You can also use sub-folders within the `item-icons` directory to keep things organised. You would then specify an icon with it's folder name slash image name. For example: `networking/monit.png` diff --git a/package.json b/package.json index d9ce84b1f1..a324a14738 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "Dashy", - "version": "0.1.0", + "version": "1.2.5", "license": "MIT", "main": "server", "scripts": { @@ -48,10 +48,12 @@ "eslint": "^7.24.0", "eslint-config-airbnb": "^18.0.1", "eslint-plugin-vue": "^7.9.0", + "progress-bar-webpack-plugin": "^2.1.0", "sass": "^1.18.0", "sass-loader": "^7.1.0", "vue-svg-loader": "^0.16.0", - "vue-template-compiler": "^2.6.10" + "vue-template-compiler": "^2.6.10", + "webpack-build-notifier": "^2.3.0" }, "gitHooks": { "pre-commit": "yarn lint" @@ -84,4 +86,4 @@ "> 1%", "last 2 versions" ] -} \ No newline at end of file +} diff --git a/public/favicon.ico b/public/favicon.ico index 638b826f8a..8352d15baf 100644 Binary files a/public/favicon.ico and b/public/favicon.ico differ diff --git a/public/index.html b/public/index.html index c6fb3383f9..4a291177de 100644 --- a/public/index.html +++ b/public/index.html @@ -7,7 +7,8 @@ - + + Dashy diff --git a/public/manifest.json b/public/manifest.json index 1c006cc569..a0447af2f3 100644 --- a/public/manifest.json +++ b/public/manifest.json @@ -1,6 +1,14 @@ { - "name": "Dashy", + "name": "Dashy Web", "short_name": "Dashy", + "description": "A Dashboard for your Homelab", + "scope": "/", + "start_url": "./index.html", + "display": "standalone", + "background_color": "#0b1021", + "theme_color": "#4DBA87", + "lang": "en-GB", + "orientation": "portrait-primary", "icons": [ { "src": "./web-icons/windows10/SmallTile.scale-100.png", @@ -507,8 +515,42 @@ "sizes": "16x16" } ], - "start_url": "./index.html", - "display": "standalone", - "background_color": "#0b1021", - "theme_color": "#4DBA87" + "screenshots": [ + { + "src": "./web-icons/screenshots/dashy-scrsht-1.png", + "sizes": "1523x1347", + "type": "image/png", + "label": "Dashy example homelab with Callisto theme" + }, + { + "src": "./web-icons/screenshots/dashy-scrsht-2.png", + "sizes": "1264x861", + "type": "image/png", + "label": "Example, Networking services with Minimal Dark theme and a Horizontal layout" + }, + { + "src": "./web-icons/screenshots/dashy-scrsht-3.png", + "sizes": "1303x864", + "type": "image/png", + "label": "Dashy example homelab with Material theme and auto-fetched favicons" + }, + { + "src": "./web-icons/screenshots/dashy-scrsht-4.png", + "sizes": "1273x865", + "type": "image/png", + "label": "Dashy CFT Toolbox using Matrix theme" + }, + { + "src": "./web-icons/screenshots/dashy-scrsht-5.png", + "sizes": "1146x851", + "type": "image/png", + "label": "Dashy as a Bookmark Manager, with Dracula theme and Font-Awesome icons" + }, + { + "src": "./web-icons/screenshots/dashy-scrsht-6.png", + "sizes": "1147x872", + "type": "image/png", + "label": "Dashy example homelab with Nord theme" + } + ] } \ No newline at end of file diff --git a/public/web-icons/dashy-logo.png b/public/web-icons/dashy-logo.png new file mode 100644 index 0000000000..78fabd2572 Binary files /dev/null and b/public/web-icons/dashy-logo.png differ diff --git a/public/web-icons/favicon-32x32.png b/public/web-icons/favicon-32x32.png new file mode 100644 index 0000000000..1c0a2979bc Binary files /dev/null and b/public/web-icons/favicon-32x32.png differ diff --git a/public/web-icons/favicon-64x64.png b/public/web-icons/favicon-64x64.png new file mode 100644 index 0000000000..369f1c6031 Binary files /dev/null and b/public/web-icons/favicon-64x64.png differ diff --git a/public/web-icons/screenshots/dashy-scrsht-1.png b/public/web-icons/screenshots/dashy-scrsht-1.png new file mode 100644 index 0000000000..d5f3cd3f12 Binary files /dev/null and b/public/web-icons/screenshots/dashy-scrsht-1.png differ diff --git a/public/web-icons/screenshots/dashy-scrsht-2.png b/public/web-icons/screenshots/dashy-scrsht-2.png new file mode 100644 index 0000000000..bfaab61879 Binary files /dev/null and b/public/web-icons/screenshots/dashy-scrsht-2.png differ diff --git a/public/web-icons/screenshots/dashy-scrsht-3.png b/public/web-icons/screenshots/dashy-scrsht-3.png new file mode 100644 index 0000000000..605a520c6f Binary files /dev/null and b/public/web-icons/screenshots/dashy-scrsht-3.png differ diff --git a/public/web-icons/screenshots/dashy-scrsht-4.png b/public/web-icons/screenshots/dashy-scrsht-4.png new file mode 100644 index 0000000000..a728a8a931 Binary files /dev/null and b/public/web-icons/screenshots/dashy-scrsht-4.png differ diff --git a/public/web-icons/screenshots/dashy-scrsht-5.png b/public/web-icons/screenshots/dashy-scrsht-5.png new file mode 100644 index 0000000000..9a61a2dc22 Binary files /dev/null and b/public/web-icons/screenshots/dashy-scrsht-5.png differ diff --git a/public/web-icons/screenshots/dashy-scrsht-6.png b/public/web-icons/screenshots/dashy-scrsht-6.png new file mode 100644 index 0000000000..8402f0a12b Binary files /dev/null and b/public/web-icons/screenshots/dashy-scrsht-6.png differ diff --git a/services/print-message.js b/services/print-message.js index a33df99c57..d7d19ed023 100644 --- a/services/print-message.js +++ b/services/print-message.js @@ -1,14 +1,14 @@ /** - * A function that prints a welcome message to the user when they start the app + * Returns a welcome message, to be printed to the user when they start the app * Contains essential info about restarting and managing the container or service - * @param String ip: The users local IP address - * @param Integer port: the port number the app is running at + * @param String ip: The users local IP address or hostname + * @param Integer port: the port number that the app is running at * @param Boolean isDocker: whether or not the app is being run within a container * @returns A string formatted for the terminal */ module.exports = (ip, port, isDocker) => { - let msg = ''; - const chars = { + let msg = ''; // To return + const chars = { // Color codes used in the message RESET: '\x1b[0m', CYAN: '\x1b[36m', GREEN: '\x1b[32m', @@ -16,10 +16,13 @@ module.exports = (ip, port, isDocker) => { BRIGHT: '\x1b[1m', BR: '\n', }; - const stars = (count) => new Array(count).fill('*').join(''); - const line = (count) => new Array(count).fill('━').join(''); - const blanks = (count) => new Array(count).fill(' ').join(''); + // Functions to insert string of set length of characters + const printChars = (count, char) => new Array(count).fill(char).join(''); + const stars = (count) => printChars(count, '*'); + const line = (count) => printChars(count, '━'); + const blanks = (count) => printChars(count, ' '); if (isDocker) { + // Prepare message for Docker users const containerId = process.env.HOSTNAME || undefined; msg = `${chars.BLUE}${stars(91)}${chars.BR}${chars.RESET}` + `${chars.CYAN}Welcome to Dashy! 🚀${chars.RESET}${chars.BR}` @@ -30,6 +33,7 @@ module.exports = (ip, port, isDocker) => { + `${chars.RESET}${chars.GREEN}' to rebuild${chars.BR}` + `${chars.BLUE}${stars(91)}${chars.BR}${chars.RESET}`; } else { + // Prepare message for users running app on bare metal msg = `${chars.GREEN}┏${line(75)}┓${chars.BR}` + `┃ ${chars.CYAN}Welcome to Dashy! 🚀${blanks(55)}${chars.GREEN}┃${chars.BR}` + `┃ ${chars.CYAN}Your new dashboard is now up and running at ${chars.BRIGHT}` @@ -38,5 +42,14 @@ module.exports = (ip, port, isDocker) => { + `${chars.RESET}${chars.CYAN}' to rebuild the app${blanks(6)}${chars.GREEN}┃${chars.BR}` + `┗${line(75)}┛${chars.BR}${chars.BR}${chars.RESET}`; } - return msg; + // Make some sexy ascii art ;) + const ascii = `\x1b[40m${chars.CYAN}\n\n` + + ' ██████╗ █████╗ ███████╗██╗ ██╗██╗ ██╗\n' + + ' ██╔══██╗██╔══██╗██╔════╝██║ ██║╚██╗ ██╔╝\n' + + ' ██║ ██║███████║███████╗███████║ ╚████╔╝\n' + + ' ██║ ██║██╔══██║╚════██║██╔══██║ ╚██╔╝\n' + + ' ██████╔╝██║ ██║███████║██║ ██║ ██║\n' + + ` ╚═════╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═╝\n${chars.RESET}\n`; + + return ascii + msg; }; diff --git a/src/assets/interface-icons/application-about.svg b/src/assets/interface-icons/application-about.svg new file mode 100644 index 0000000000..09728dfa31 --- /dev/null +++ b/src/assets/interface-icons/application-about.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/interface-icons/application-workspace.svg b/src/assets/interface-icons/application-workspace.svg new file mode 100644 index 0000000000..66518c81a5 --- /dev/null +++ b/src/assets/interface-icons/application-workspace.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/interface-icons/layout-default.svg b/src/assets/interface-icons/layout-default.svg index f5f60a7edb..2750cff1f9 100644 --- a/src/assets/interface-icons/layout-default.svg +++ b/src/assets/interface-icons/layout-default.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/assets/interface-icons/layout-horizontal.svg b/src/assets/interface-icons/layout-horizontal.svg index ff8db9a131..108272386a 100644 --- a/src/assets/interface-icons/layout-horizontal.svg +++ b/src/assets/interface-icons/layout-horizontal.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/assets/interface-icons/layout-vertical.svg b/src/assets/interface-icons/layout-vertical.svg index 67762d4abf..08bf2e0122 100644 --- a/src/assets/interface-icons/layout-vertical.svg +++ b/src/assets/interface-icons/layout-vertical.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/components/Configuration/AppInfoModal.vue b/src/components/Configuration/AppInfoModal.vue new file mode 100644 index 0000000000..ab136e0b52 --- /dev/null +++ b/src/components/Configuration/AppInfoModal.vue @@ -0,0 +1,191 @@ + + + + + diff --git a/src/components/Configuration/ConfigContainer.vue b/src/components/Configuration/ConfigContainer.vue index c69884836d..f33151abd1 100644 --- a/src/components/Configuration/ConfigContainer.vue +++ b/src/components/Configuration/ConfigContainer.vue @@ -29,12 +29,17 @@ Reset Local Settings + +

Dashy version {{ appVersion }}

- It is recommend to make a backup of your conf.yml file, before making any changes. + It is recommend to make a backup of your conf.yml file before making changes.
@@ -79,6 +84,7 @@ import EditIcon from '@/assets/interface-icons/config-edit-json.svg'; import CustomCssIcon from '@/assets/interface-icons/config-custom-css.svg'; import CloudIcon from '@/assets/interface-icons/cloud-backup-restore.svg'; import RebuildIcon from '@/assets/interface-icons/application-rebuild.svg'; +import IconAbout from '@/assets/interface-icons/application-about.svg'; export default { name: 'ConfigContainer', @@ -86,6 +92,7 @@ export default { return { jsonParser: JsonToYaml, backupId: localStorage[localStorageKeys.BACKUP_ID] || '', + appVersion: process.env.VUE_APP_VERSION, }; }, props: { @@ -109,6 +116,7 @@ export default { CloudIcon, CustomCssIcon, RebuildIcon, + IconAbout, }, methods: { /* Seletcs the edit tab of the tab view */ @@ -121,12 +129,15 @@ export default { this.$refs.tabView.activeTabItem({ tabItem: itemToSelect, byUser: true }); }, goToCustomCss() { - const itemToSelect = this.$refs.tabView.navItems[4]; + const itemToSelect = this.$refs.tabView.navItems[3]; this.$refs.tabView.activeTabItem({ tabItem: itemToSelect, byUser: true }); }, openRebuildAppModal() { this.$modal.show(modalNames.REBUILD_APP); }, + openAboutModal() { + this.$modal.show(modalNames.ABOUT_APP); + }, openCloudSync() { this.$modal.show(modalNames.CLOUD_BACKUP); }, @@ -210,6 +221,12 @@ a.config-button, button.config-button { } } +p.app-version { + margin: 0.5rem auto; + font-size: 1rem; + color: var(--transparent-white-50); +} + div.code-container { background: var(--config-code-background); #conf-yaml span { @@ -275,7 +292,7 @@ a.hyperlink-wrapper { background: var(--config-settings-background); height: calc(100% - 2rem); h2 { - margin: 1rem auto; + margin: 0 auto 1rem auto; color: var(--config-settings-color); } } diff --git a/src/components/Configuration/RebuildApp.vue b/src/components/Configuration/RebuildApp.vue index 23b582a0a1..4d1ebcaa3c 100644 --- a/src/components/Configuration/RebuildApp.vue +++ b/src/components/Configuration/RebuildApp.vue @@ -8,10 +8,13 @@ This should happen automatically, but if it hasn't, you can manually trigger it here.
This is not required for modifications stored locally.

- +
+

You do no have permission to trigger this action

+
@@ -45,6 +48,7 @@ import LoadingAnimation from '@/assets/interface-icons/loader.svg'; export default { name: 'RebuildApp', + inject: ['config'], components: { Button, RebuildIcon, @@ -58,6 +62,7 @@ export default { error: '', output: '', message: '', + allowRebuild: true, }), methods: { startBuild() { @@ -92,6 +97,15 @@ export default { location.reload(); // eslint-disable-line no-restricted-globals }, }, + mounted() { + if (this.config) { + if (this.config.appConfig) { + if (this.config.appConfig.allowConfigEdit === false) { + this.allowRebuild = false; + } + } + } + }, }; @@ -110,6 +124,13 @@ export default { color: var(--config-settings-color); } + p.disallow-rebuild-msg { + color: var(--danger); + font-size: 1.2rem; + margin: 0.2rem auto; + text-align: center; + } + h3.rebuild-app-title { text-align: center; font-size: 2rem; diff --git a/src/components/FormElements/Button.vue b/src/components/FormElements/Button.vue index f6c498f624..2c8f6279e8 100644 --- a/src/components/FormElements/Button.vue +++ b/src/components/FormElements/Button.vue @@ -1,5 +1,5 @@