🔀 Merge pull request #57 from Lissy93/REFACTOR_sw-improvments-and-docs

[REFACTOR] General small app improvements
- Fixes #55 - Favicon is now present :)
- Fixes #54 - Well, kinda, user can now disable SW
- Fixes #41 - Styling modifications mean the full title *(should)* now be visible for each item :)

Glad this is finally merged, it was a big one 😌
This commit is contained in:
Alicia Sykes 2021-06-23 21:40:29 +01:00 committed by GitHub
commit e6da1c4028
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
49 changed files with 868 additions and 298 deletions

View File

@ -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):
**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)**
**Issue Number** (if applicable):
### Category
> Please indicate the type of change your PR introduces
**Briefly outline your changes**:
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
**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

View File

@ -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 }}

17
LICENSE Normal file
View File

@ -0,0 +1,17 @@
Licensed under MIT X11. Copyright © 2021 Alicia Sykes <https://aliciasykes.com>
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.

View File

@ -2,14 +2,18 @@
<h1 align="center">Dashy</h1>
<p align="center"><i>Dashy helps you organize your self-hosted services, by making them all accessible from a single place</i></p>
<p align="center">
<img src="https://app.codacy.com/project/badge/Grade/3be23a4a3a8a4689bd47745b201ecb74" /> <img src="https://img.shields.io/github/issues/lissy93/dashy?style=flat-square" /> <img src="https://img.shields.io/github/languages/code-size/lissy93/dashy?style=flat-square" /> <img src="https://img.shields.io/tokei/lines/github/lissy93/dashy?style=flat-square" />
</p>
<p align="center">
<img width="220" src="https://i.ibb.co/yhbt6CY/dashy.png" />
</p>
[![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.
<p align="center">
<img width="400" src="https://i.ibb.co/GTVmZnc/dashy-example-icons.png" />
</p>
- 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)**
---

View File

@ -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`.

View File

@ -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

View File

@ -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)**
---

View File

@ -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)
<p align="center">
<img width="400" src="https://i.ibb.co/GTVmZnc/dashy-example-icons.png" />
</p>
### 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`

View File

@ -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"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -7,7 +7,8 @@
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<link rel="icon" type="image/png" sizes="64x64" href="/web-icons/favicon-64x64.png">
<link rel="icon" type="image/png" sizes="32x32" href="/web-icons/favicon-32x32.png">
<title>Dashy</title>
</head>

View File

@ -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"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 367 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 KiB

View File

@ -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;
};

View File

@ -0,0 +1 @@
<svg aria-hidden="true" focusable="false" data-prefix="far" data-icon="info" class="svg-inline--fa fa-info fa-w-8" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 512"><path fill="currentColor" d="M224 352.589V224c0-16.475-6.258-31.517-16.521-42.872C225.905 161.14 236 135.346 236 108 236 48.313 187.697 0 128 0 68.313 0 20 48.303 20 108c0 20.882 5.886 40.859 16.874 58.037C15.107 176.264 0 198.401 0 224v39.314c0 23.641 12.884 44.329 32 55.411v33.864C12.884 363.671 0 384.359 0 408v40c0 35.29 28.71 64 64 64h128c35.29 0 64-28.71 64-64v-40c0-23.641-12.884-44.329-32-55.411zM128 48c33.137 0 60 26.863 60 60s-26.863 60-60 60-60-26.863-60-60 26.863-60 60-60zm80 400c0 8.836-7.164 16-16 16H64c-8.836 0-16-7.164-16-16v-40c0-8.836 7.164-16 16-16h16V279.314H64c-8.836 0-16-7.164-16-16V224c0-8.836 7.164-16 16-16h96c8.836 0 16 7.164 16 16v168h16c8.836 0 16 7.164 16 16v40z"></path></svg>

After

Width:  |  Height:  |  Size: 894 B

View File

@ -0,0 +1 @@
<svg aria-hidden="true" focusable="false" data-prefix="fal" data-icon="ellipsis-v-alt" class="svg-inline--fa fa-ellipsis-v-alt fa-w-6" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 192 512"><path fill="currentColor" d="M96 152c39.8 0 72-32.2 72-72S135.8 8 96 8 24 40.2 24 80s32.2 72 72 72zm0-112c22.1 0 40 17.9 40 40s-17.9 40-40 40-40-17.9-40-40 17.9-40 40-40zm0 144c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72zm0 112c-22.1 0-40-17.9-40-40s17.9-40 40-40 40 17.9 40 40-17.9 40-40 40zm0 64c-39.8 0-72 32.2-72 72s32.2 72 72 72 72-32.2 72-72-32.2-72-72-72zm0 112c-22.1 0-40-17.9-40-40s17.9-40 40-40 40 17.9 40 40-17.9 40-40 40z"></path></svg>

After

Width:  |  Height:  |  Size: 671 B

View File

@ -1 +1 @@
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="th" class="svg-inline--fa fa-th fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M149.333 56v80c0 13.255-10.745 24-24 24H24c-13.255 0-24-10.745-24-24V56c0-13.255 10.745-24 24-24h101.333c13.255 0 24 10.745 24 24zm181.334 240v-80c0-13.255-10.745-24-24-24H205.333c-13.255 0-24 10.745-24 24v80c0 13.255 10.745 24 24 24h101.333c13.256 0 24.001-10.745 24.001-24zm32-240v80c0 13.255 10.745 24 24 24H488c13.255 0 24-10.745 24-24V56c0-13.255-10.745-24-24-24H386.667c-13.255 0-24 10.745-24 24zm-32 80V56c0-13.255-10.745-24-24-24H205.333c-13.255 0-24 10.745-24 24v80c0 13.255 10.745 24 24 24h101.333c13.256 0 24.001-10.745 24.001-24zm-205.334 56H24c-13.255 0-24 10.745-24 24v80c0 13.255 10.745 24 24 24h101.333c13.255 0 24-10.745 24-24v-80c0-13.255-10.745-24-24-24zM0 376v80c0 13.255 10.745 24 24 24h101.333c13.255 0 24-10.745 24-24v-80c0-13.255-10.745-24-24-24H24c-13.255 0-24 10.745-24 24zm386.667-56H488c13.255 0 24-10.745 24-24v-80c0-13.255-10.745-24-24-24H386.667c-13.255 0-24 10.745-24 24v80c0 13.255 10.745 24 24 24zm0 160H488c13.255 0 24-10.745 24-24v-80c0-13.255-10.745-24-24-24H386.667c-13.255 0-24 10.745-24 24v80c0 13.255 10.745 24 24 24zM181.333 376v80c0 13.255 10.745 24 24 24h101.333c13.255 0 24-10.745 24-24v-80c0-13.255-10.745-24-24-24H205.333c-13.255 0-24 10.745-24 24z"></path></svg>
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="table" class="svg-inline--fa fa-table fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M464 32H48C21.49 32 0 53.49 0 80v352c0 26.51 21.49 48 48 48h416c26.51 0 48-21.49 48-48V80c0-26.51-21.49-48-48-48zM224 416H64v-96h160v96zm0-160H64v-96h160v96zm224 160H288v-96h160v96zm0-160H288v-96h160v96z"></path></svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 433 B

View File

@ -1 +1 @@
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="grip-horizontal" class="svg-inline--fa fa-grip-horizontal fa-w-14" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M96 288H32c-17.67 0-32 14.33-32 32v64c0 17.67 14.33 32 32 32h64c17.67 0 32-14.33 32-32v-64c0-17.67-14.33-32-32-32zm160 0h-64c-17.67 0-32 14.33-32 32v64c0 17.67 14.33 32 32 32h64c17.67 0 32-14.33 32-32v-64c0-17.67-14.33-32-32-32zm160 0h-64c-17.67 0-32 14.33-32 32v64c0 17.67 14.33 32 32 32h64c17.67 0 32-14.33 32-32v-64c0-17.67-14.33-32-32-32zM96 96H32c-17.67 0-32 14.33-32 32v64c0 17.67 14.33 32 32 32h64c17.67 0 32-14.33 32-32v-64c0-17.67-14.33-32-32-32zm160 0h-64c-17.67 0-32 14.33-32 32v64c0 17.67 14.33 32 32 32h64c17.67 0 32-14.33 32-32v-64c0-17.67-14.33-32-32-32zm160 0h-64c-17.67 0-32 14.33-32 32v64c0 17.67 14.33 32 32 32h64c17.67 0 32-14.33 32-32v-64c0-17.67-14.33-32-32-32z"></path></svg>
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="th-list" class="svg-inline--fa fa-th-list fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M149.333 216v80c0 13.255-10.745 24-24 24H24c-13.255 0-24-10.745-24-24v-80c0-13.255 10.745-24 24-24h101.333c13.255 0 24 10.745 24 24zM0 376v80c0 13.255 10.745 24 24 24h101.333c13.255 0 24-10.745 24-24v-80c0-13.255-10.745-24-24-24H24c-13.255 0-24 10.745-24 24zM125.333 32H24C10.745 32 0 42.745 0 56v80c0 13.255 10.745 24 24 24h101.333c13.255 0 24-10.745 24-24V56c0-13.255-10.745-24-24-24zm80 448H488c13.255 0 24-10.745 24-24v-80c0-13.255-10.745-24-24-24H205.333c-13.255 0-24 10.745-24 24v80c0 13.255 10.745 24 24 24zm-24-424v80c0 13.255 10.745 24 24 24H488c13.255 0 24-10.745 24-24V56c0-13.255-10.745-24-24-24H205.333c-13.255 0-24 10.745-24 24zm24 264H488c13.255 0 24-10.745 24-24v-80c0-13.255-10.745-24-24-24H205.333c-13.255 0-24 10.745-24 24v80c0 13.255 10.745 24 24 24z"></path></svg>

Before

Width:  |  Height:  |  Size: 933 B

After

Width:  |  Height:  |  Size: 1004 B

View File

@ -1 +1 @@
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="grip-vertical" class="svg-inline--fa fa-grip-vertical fa-w-10" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path fill="currentColor" d="M96 32H32C14.33 32 0 46.33 0 64v64c0 17.67 14.33 32 32 32h64c17.67 0 32-14.33 32-32V64c0-17.67-14.33-32-32-32zm0 160H32c-17.67 0-32 14.33-32 32v64c0 17.67 14.33 32 32 32h64c17.67 0 32-14.33 32-32v-64c0-17.67-14.33-32-32-32zm0 160H32c-17.67 0-32 14.33-32 32v64c0 17.67 14.33 32 32 32h64c17.67 0 32-14.33 32-32v-64c0-17.67-14.33-32-32-32zM288 32h-64c-17.67 0-32 14.33-32 32v64c0 17.67 14.33 32 32 32h64c17.67 0 32-14.33 32-32V64c0-17.67-14.33-32-32-32zm0 160h-64c-17.67 0-32 14.33-32 32v64c0 17.67 14.33 32 32 32h64c17.67 0 32-14.33 32-32v-64c0-17.67-14.33-32-32-32zm0 160h-64c-17.67 0-32 14.33-32 32v64c0 17.67 14.33 32 32 32h64c17.67 0 32-14.33 32-32v-64c0-17.67-14.33-32-32-32z"></path></svg>
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="columns" class="svg-inline--fa fa-columns fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M464 32H48C21.49 32 0 53.49 0 80v352c0 26.51 21.49 48 48 48h416c26.51 0 48-21.49 48-48V80c0-26.51-21.49-48-48-48zM224 416H64V160h160v256zm224 0H288V160h160v256z"></path></svg>

Before

Width:  |  Height:  |  Size: 924 B

After

Width:  |  Height:  |  Size: 394 B

View File

@ -0,0 +1,191 @@
<template>
<modal :name="modalName" :resizable="true" width="40%" height="60%" classes="dashy-modal">
<div class="about-modal">
<router-link to="/about">
<h2>Dashy V{{ appVersion }}</h2>
</router-link>
<h3>Service Worker Status</h3>
<code v-html="serviceWorkerInfo">{{ serviceWorkerInfo }}</code>
<br>
<h3>Config Validation Status</h3>
<code>{{getIsConfigValidStatus()}}</code>
<br>
<h3>Help & Support</h3>
<ul>
<li><a href="https://git.io/JnqPR">Report a Bug</a></li>
<li><a href="https://git.io/JnDxL">Request a Feature</a></li>
<li><a href="https://git.io/JnDxs">Ask a Question</a></li>
<li><a href="https://git.io/JnDxn">Leave Feedback</a></li>
<li><a href="https://github.com/Lissy93/dashy/discussions">Join the Discussion</a></li>
</ul>
<p class="small-note">Please include the following info in your bug report:</p>
<a @click="showInfo = !showInfo">{{ showInfo ? 'Hide' : 'Show'}} system info</a>
<div class="system-info" v-if="showInfo">
<h4>System Info</h4>
<code><b>Dashy Version:</b> V {{appVersion}}</code><br>
<code><b>Browser:</b> {{systemInfo.browser}}</code><br>
<code><b>Is Mobile?</b> {{systemInfo.isMobile ? 'Yes' : 'No'}}</code><br>
<code><b>OS:</b> {{systemInfo.os}}</code><br>
</div>
<h3>About</h3>
<p class="about-text">
Documentation and Source Code available on
<a href="https://github.com/lissy93/dashy">GitHub</a>
</p>
<h3>License</h3>
<code>Licensed under MIT X11. Copyright © 2021</code>
</div>
</modal>
</template>
<script>
import { modalNames, sessionStorageKeys } from '@/utils/defaults';
export default {
name: 'AppInfoModal',
data() {
return {
modalName: modalNames.ABOUT_APP,
appVersion: process.env.VUE_APP_VERSION,
systemInfo: this.getSystemInfo(),
serviceWorkerInfo: 'Checking...',
showInfo: false,
};
},
mounted() {
setTimeout(() => {
this.serviceWorkerInfo = this.getSwStatus();
}, 100);
},
methods: {
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<br>';
if (swInfo.ready) swStatus += 'Dashy is being served from service worker<br>';
if (swInfo.cached) swStatus += 'Content has been cached for offline use<br>';
if (swInfo.updateFound) swStatus += 'New content is downloading<br>';
if (swInfo.updated) swStatus += 'New content is available; please refresh<br>';
if (swInfo.offline) swStatus += 'No internet connection found. App is running in offline mode<br>';
if (swInfo.error) swStatus += 'Error during service worker registration<br>';
if (swInfo.devMode) swStatus += 'App running in dev mode, no need for service worker<br>';
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,
};
},
},
};
</script>
<style scoped lang="scss">
span.options-label {
color: var(--settings-text-color);
}
.display-options {
color: var(--settings-text-color);
svg {
path {
fill: var(--settings-text-color);
}
width: 1rem;
height: 1rem;
margin: 0.2rem;
padding: 0.2rem;
text-align: center;
background: var(--background);
border: 1px solid currentColor;
border-radius: var(--curve-factor);
cursor: pointer;
&:hover, &.selected {
background: var(--settings-text-color);
path { fill: var(--background); }
}
}
}
div.about-modal {
background: var(--about-page-background);
color: var(--about-page-color);
padding: 1rem;
height: 100%;
hr {
border-color: var(--about-page-accent);
}
h2 {
text-decoration: none;
font-size: 1.8rem;
text-align: center;
margin: 0.2rem;
}
h3 {
font-size: 1.3rem;
margin: 0.75rem 0 0.2rem 0;
color: var(--about-page-accent);
}
p.small-note {
font-size: 0.9rem;
margin: 0.2rem 0;
}
p.about-text {
margin: 0.2rem 0;
}
a {
color: var(--about-page-accent);
}
ul {
margin-top: 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;
}
}
}
</style>

View File

@ -29,12 +29,17 @@
<DeleteIcon class="button-icon"/>
Reset Local Settings
</button>
<button class="config-button center" @click="openAboutModal()">
<IconAbout class="button-icon" />
App Info
</button>
<p class="small-screen-note" style="display: none;">
You are using a very small screen, and some screens in this menu may not be optimal
</p>
<p class="app-version">Dashy version {{ appVersion }}</p>
<div class="config-note">
<span>
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.
</span>
</div>
</div>
@ -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);
}
}

View File

@ -8,10 +8,13 @@
This should happen automatically, but if it hasn't, you can manually trigger it here.<br>
This is not required for modifications stored locally.
</p>
<Button :click="startBuild" :disabled="loading">
<Button :click="startBuild" :disabled="loading || !allowRebuild" :disallow="!allowRebuild">
<template v-slot:text>{{ loading ? 'Building...' : 'Start Build' }}</template>
<template v-slot:icon><RebuildIcon /></template>
</Button>
<div v-if="!allowRebuild">
<p class="disallow-rebuild-msg">You do no have permission to trigger this action</p>
</div>
<!-- Loading animation and text (shown while build is happening) -->
<div v-if="loading" class="loader-info">
<LoadingAnimation class="loader" />
@ -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;
}
}
}
},
};
</script>
@ -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;

View File

@ -1,5 +1,5 @@
<template>
<button @click="click()" :disabled="disabled">
<button @click="click()" :disabled="disabled" :class="disallow ? 'disallowed': ''">
<slot></slot>
<slot name="text"></slot>
<slot name="icon"></slot>
@ -14,6 +14,7 @@ export default {
text: String,
click: Function,
disabled: Boolean,
disallow: Boolean,
},
};
</script>
@ -38,6 +39,9 @@ button {
fill: currentColor;
}
}
&.disallowed {
cursor: not-allowed !important;
}
}
/* Default visual settings, can be overridden when needed */

View File

@ -11,7 +11,6 @@
<!-- Item Text -->
<div :class="`tile-title ${!icon? 'bounce': ''}`" :id="`tile-${id}`" >
<span class="text">{{ title }}</span>
<div class="overflow-dots">...</div>
<p class="description">{{ description }}</p>
</div>
<!-- Item Icon -->
@ -80,18 +79,6 @@ export default {
this.$emit('itemClicked');
}
},
/**
* Detects overflowing text, shows ellipse, and allows is to marguee on hover
* The below code is horifically bad, it is embarassing that I wrote it...
*/
manageTitleEllipse() {
const tileElem = document.getElementById(`tile-${this.getId}`);
if (tileElem) {
const isOverflowing = (tileElem.scrollHeight > tileElem.clientHeight
|| tileElem.scrollWidth > tileElem.clientWidth) && this.title.length > 12;
if (isOverflowing) tileElem.className += ' is-overflowing';
} // Note from present me to past me: WTF?!
},
/* Returns configuration object for the tooltip */
getTooltipOptions() {
return {
@ -131,7 +118,6 @@ export default {
},
},
mounted() {
this.manageTitleEllipse();
if (this.enableStatusCheck) this.checkWebsiteStatus();
if (this.statusCheckInterval > 0) {
setInterval(this.checkWebsiteStatus, this.statusCheckInterval * 1000);
@ -157,10 +143,14 @@ export default {
cursor: pointer;
text-decoration: none;
position: relative;
transition: all 0.2s ease-in-out 0s;
&:hover {
box-shadow: var(--item-hover-shadow);
background: var(--item-background-hover);
position: relative;
.tile-title span.text {
white-space: pre-wrap;
}
}
&:focus {
outline: 2px solid var(--primary);
@ -177,36 +167,11 @@ export default {
text-overflow: ellipsis;
min-width: 120px;
height: 30px;
overflow: hidden;
position: relative;
padding: 0;
z-index: 2;
span.text {
position: absolute;
white-space: nowrap;
transition: 1s;
float: left;
left: 0;
}
&:not(.is-overflowing) span.text{
width: 100%;
}
.overflow-dots {
opacity: 0;
}
&.is-overflowing {
span.text {
overflow: hidden;
}
.overflow-dots {
display: block;
opacity: 1;
background: var(--item-background);
position: absolute;
z-index: 5;
right: 0;
transition: opacity 0.1s ease-in;
}
}
}
@ -275,6 +240,7 @@ export default {
}
.tile-title {
min-width: 100px;
max-width: 160px;
}
}
&.size-large {

View File

@ -1,8 +1,8 @@
<template>
<!-- User Footer -->
<footer v-if="text && text !== ''" v-html="text" :class="!scrollVisible ? 'fixed' : ''"></footer>
<footer v-if="text && text !== ''" v-html="text"></footer>
<!-- Default Footer -->
<footer v-else :class="!scrollVisible ? 'fixed' : ''">
<footer v-else>
Developed by <a :href="authorUrl">{{authorName}}</a>.
Licensed under <a :href="licenseUrl">{{license}}</a>
{{ showCopyright? '©': '' }} {{date}}.
@ -23,16 +23,11 @@ export default {
showCopyright: { type: Boolean, default: true },
repoUrl: { type: String, default: 'https://github.com/lissy93/dashy' },
},
data: () => ({
scrollVisible: false,
}),
mounted() {
this.scrollVisible = document.body.clientHeight > window.innerHeight;
},
};
</script>
<style scoped lang="scss">
@import '@/styles/media-queries.scss';
footer {
width: calc(100% - 0.5rem);
@ -44,7 +39,9 @@ footer {
background: var(--background-darker);
margin-top: 1.5rem;
border-top: 1px solid var(--outline-color);
&.fixed { position: fixed; }
@include tablet-down {
display: none;
}
}
footer a{

View File

@ -1,8 +1,8 @@
<template>
<div class="page-titles">
<router-link to="/" class="page-titles">
<h1>{{ title }}</h1>
<span class="subtitle">{{ description }}</span>
</div>
</router-link>
</template>
<script>
@ -21,6 +21,7 @@ export default {
.page-titles {
display: flex;
flex-direction: column;
text-decoration: none;
h1 {
color: var(--heading-text-color);
font-size: 2.5rem;

View File

@ -0,0 +1,62 @@
<template>
<div>
<div class="display-options">
<IconLogout @click="logout()" v-tooltip="tooltip('Sign Out')"
class="layout-icon" tabindex="-2" />
</div>
</div>
</template>
<script>
import { logout as registerLogout } from '@/utils/Auth';
import IconLogout from '@/assets/interface-icons/user-logout.svg';
export default {
name: 'AppButtons',
components: {
IconLogout,
},
methods: {
logout() {
registerLogout();
this.$toasted.show('Logged Out');
setTimeout(() => {
location.reload(true); // eslint-disable-line no-restricted-globals
}, 500);
},
tooltip(content) {
return { content, trigger: 'hover focus', delay: 250 };
},
},
};
</script>
<style scoped lang="scss">
span.options-label {
color: var(--settings-text-color);
}
.display-options {
color: var(--settings-text-color);
svg {
path {
fill: var(--settings-text-color);
}
width: 1rem;
height: 1rem;
margin: 0.2rem;
padding: 0.2rem;
text-align: center;
background: var(--background);
border: 1px solid currentColor;
border-radius: var(--curve-factor);
cursor: pointer;
&:hover, &.selected {
background: var(--settings-text-color);
path { fill: var(--background); }
}
}
}
</style>

View File

@ -13,12 +13,7 @@
<ItemSizeSelector :iconSize="iconSize" @iconSizeUpdated="updateIconSize" />
<ConfigLauncher :sections="sections" :pageInfo="pageInfo" :appConfig="appConfig"
@modalChanged="modalChanged" />
<IconLogout
v-if="isUserLoggedIn()"
@click="logout()"
v-tooltip="'Logout'"
class="logout-icon"
/>
<AppButtons v-if="isUserLoggedIn()" />
</div>
<div :class="`show-hide-container ${settingsVisible? 'hide-btn' : 'show-btn'}`">
<button @click="toggleSettingsVisibility()"
@ -29,6 +24,7 @@
</div>
</div>
<KeyboardShortcutInfo />
<AppInfoModal />
</section>
</template>
@ -39,9 +35,10 @@ import ConfigLauncher from '@/components/Settings/ConfigLauncher';
import ThemeSelector from '@/components/Settings/ThemeSelector';
import LayoutSelector from '@/components/Settings/LayoutSelector';
import ItemSizeSelector from '@/components/Settings/ItemSizeSelector';
import AppButtons from '@/components/Settings/AppButtons';
import KeyboardShortcutInfo from '@/components/Settings/KeyboardShortcutInfo';
import AppInfoModal from '@/components/Configuration/AppInfoModal';
import { logout as registerLogout } from '@/utils/Auth';
import IconLogout from '@/assets/interface-icons/user-logout.svg';
import IconOpen from '@/assets/interface-icons/config-open-settings.svg';
import IconClose from '@/assets/interface-icons/config-close.svg';
@ -62,8 +59,9 @@ export default {
ThemeSelector,
LayoutSelector,
ItemSizeSelector,
AppButtons,
KeyboardShortcutInfo,
IconLogout,
AppInfoModal,
IconOpen,
IconClose,
},

View File

@ -10,7 +10,7 @@ import Toasted from 'vue-toasted'; // Toast component, used to show confirmation
import { toastedOptions } from './utils/defaults';
import Dashy from './App.vue';
import router from './router';
import './registerServiceWorker';
import registerServiceWorker from './registerServiceWorker';
Vue.use(VTooltip);
Vue.use(VModal);
@ -20,6 +20,9 @@ Vue.component('v-select', VSelect);
Vue.config.productionTip = false;
// Register Service Worker
registerServiceWorker();
new Vue({
router,
render: (awesome) => awesome(Dashy),

View File

@ -1,32 +1,88 @@
/* eslint-disable no-console */
import { register } from 'register-service-worker';
import { sessionStorageKeys } from './utils/defaults';
import conf from '../public/conf.yml';
if (process.env.NODE_ENV === 'production') {
register(`${process.env.BASE_URL}service-worker.js`, {
ready() {
console.log(
'App is being served from cache by a service worker.\n'
+ 'For more details, visit https://goo.gl/AFskqB',
);
},
registered() {
console.log('Service worker has been registered.');
},
cached() {
console.log('Content has been cached for offline use.');
},
updatefound() {
console.log('New content is downloading.');
},
updated() {
console.log('New content is available; please refresh.');
},
offline() {
console.log('No internet connection found. App is running in offline mode.');
},
error(error) {
console.error('Error during service worker registration:', error);
},
});
}
/* Sets a local storage item with the state from the SW lifecycle */
const setSwStatus = (swStateToSet) => {
const initialSwState = {
ready: false,
registered: false,
cached: false,
updateFound: false,
updated: false,
offline: false,
error: false,
devMode: false,
disabledByUser: false,
};
const sessionData = sessionStorage[sessionStorageKeys.SW_STATUS];
const currentSwState = sessionData ? JSON.parse(sessionData) : initialSwState;
try {
const newSwState = { ...currentSwState, ...swStateToSet };
sessionStorage.setItem(sessionStorageKeys.SW_STATUS, JSON.stringify(newSwState));
} catch (e) {
console.warn('Error setting SW data', e);
}
};
/**
* Checks if service workers should be enabled
* Disable if not running in production
* Or disable if user specified to disable
*/
const shouldEnableServiceWorker = () => {
let shouldEnable = true;
if (conf && conf.appConfig) { // Check if app Config available
if (conf.appConfig.disableServiceWorker) { // Disable if user requested
shouldEnable = false;
setSwStatus({ disabledByUser: true });
}
}
if (process.env.NODE_ENV !== 'production') {
shouldEnable = false; // Disable if not in production
setSwStatus({ devMode: true });
}
return shouldEnable;
};
const registerServiceWorker = () => {
if (shouldEnableServiceWorker()) {
register(`${process.env.BASE_URL}service-worker.js`, {
ready() {
setSwStatus({ ready: true });
console.log(
'App is being served from cache by a service worker.\n'
+ 'For more details, visit https://goo.gl/AFskqB',
);
},
registered() {
setSwStatus({ registered: true });
console.log('Service worker has been registered.');
},
cached() {
setSwStatus({ cached: true });
console.log('Content has been cached for offline use.');
},
updatefound() {
setSwStatus({ updateFound: true });
console.log('New content is downloading.');
},
updated() {
setSwStatus({ updated: true });
console.log('New content is available; please refresh.');
},
offline() {
setSwStatus({ offline: true });
console.log('No internet connection found. App is running in offline mode.');
},
error(error) {
setSwStatus({ error: true });
console.error('Error during service worker registration:', error);
},
});
}
};
export default registerServiceWorker;

View File

@ -69,7 +69,7 @@
--login-form-background: var(--background);
--login-form-background-secondary: var(--background-darker);
--about-page-color: var(--white);
--about-page-background: #0b1021;
--about-page-background: var(--background);
--about-page-accent: var(--primary);
--side-bar-background: var(--background-darker);
--side-bar-background-lighter: var(--background);

View File

@ -87,6 +87,7 @@ html[data-theme='matrix'] {
--curve-factor: 0px;
--font-body: 'Cutive Mono', monospace;
--font-headings: 'VT323', monospace;
--about-page-background: var(--background);
.prism-editor-wrapper.my-editor {
border: 1px solid var(--primary);
}
@ -179,6 +180,9 @@ html[data-theme='material-original'] {
--status-check-tooltip-background: #f2f2f2;
--status-check-tooltip-color: #01579b;
--login-form-background: #fff;
--about-page-accent: #000;
--about-page-color: var(--background-darker);
--about-page-background: var(--background);
}
html[data-theme='material-dark-original'] {
@ -237,7 +241,6 @@ html[data-theme='colorful'] {
.item:nth-child(6n) { color: #afeb5c; border: 1px solid #afeb5c; }
.item:nth-child(7n) { color: #ebb75c; border: 1px solid #ebb75c; }
.item:nth-child(8n) { color: #eb615c; border: 1px solid #eb615c; }
.tile-title span.text { transition: none; }
.item:hover, .item:focus {
opacity: 0.85;
outline: none;
@ -254,6 +257,7 @@ html[data-theme='colorful'] {
html[data-theme='minimal-light'], html[data-theme='minimal-dark'], html[data-theme='vaporware'] {
--font-body: 'PTMono-Regular', 'Courier New', monospace;
--font-headings: 'PTMono-Regular', 'Courier New', monospace;
label.lbl-toggle h3 {
font-size: 1.8rem;
}
@ -289,6 +293,8 @@ html[data-theme='material'], html[data-theme='material-dark'] {
--font-headings: 'Francois One', serif;
--curve-factor: 4px;
--curve-factor-navbar: 8px;
--about-page-background: var(--background);
--about-page-color: var(--primary);
.collapsable {
margin: 0;
@ -397,9 +403,6 @@ html[data-theme='material'], html[data-theme='material-dark'] {
&:active {
background: #c7c7c754;
}
span.text {
transition: none;
}
&.size-small {
padding-left: 0.5rem;
min-width: 11rem;
@ -541,6 +544,8 @@ html[data-theme='minimal-light'] {
--status-check-tooltip-background: #f2f2f2;
--status-check-tooltip-color: #000;
--login-form-color: #101931;
--about-page-background: var(--background);
--about-page-color: var(--background-darker);
section.filter-container {
background: #fff;
@ -572,6 +577,8 @@ html[data-theme='minimal-dark'] {
--curve-factor-navbar: 8px;
--item-group-heading-text-color: #fff;
--item-group-heading-text-color-hover: #ffffffbf;
--about-page-background: var(--background);
--about-page-color: var(--primary);
label.lbl-toggle h3 {
font-size: 1.8rem;
@ -655,7 +662,6 @@ html[data-theme='vaporware'] {
background: #844ceb;
color: #09bfe6;
}
.tile-title span.text { transition: none; }
}
div.login-page {

View File

@ -10,6 +10,7 @@
/* Basic Page Components */
--scroll-bar-width: 8px;
--header-height: 6.3rem;
--footer-height: 125px;
/* Section & Item dimensions */
--item-group-padding: 5px; // Determines width of item-group outline

View File

@ -11,16 +11,17 @@ import conf from '../../public/conf.yml';
* Returns the appConfig section, as JSON
*/
export const appConfig = (() => {
const appConfigFile = conf.appConfig || {};
let usersAppConfig = Defaults.appConfig;
if (localStorage[localStorageKeys.APP_CONFIG]) {
usersAppConfig = JSON.parse(localStorage[localStorageKeys.APP_CONFIG]);
} else if (conf.appConfig) {
usersAppConfig = conf.appConfig;
} else if (appConfigFile !== {}) {
usersAppConfig = appConfigFile;
}
usersAppConfig.layout = localStorage[localStorageKeys.LAYOUT_ORIENTATION]
|| conf.appConfig.layout || Defaults.layout;
|| appConfigFile.layout || Defaults.layout;
usersAppConfig.iconSize = localStorage[localStorageKeys.ICON_SIZE]
|| conf.appConfig.iconSize || Defaults.iconSize;
|| appConfigFile.iconSize || Defaults.iconSize;
return usersAppConfig;
})();

View File

@ -172,6 +172,11 @@
"type": "boolean",
"default": true,
"description": "Can user write changes to conf.yml file from the UI. If set to false, preferences are only stored locally"
},
"disableServiceWorker": {
"type": "boolean",
"default": false,
"description": "If set to true, then service worker will not be used"
}
},
"additionalProperties": false

View File

@ -38,13 +38,19 @@ const bigError = () => {
return `\n${line}${msg}${line}\n`;
};
const setIsValidVariable = (isValid) => {
process.env.VUE_APP_CONFIG_VALID = isValid;
};
/* Start the validation */
const validate = (config) => {
console.log('\nChecking config file against schema...');
const valid = ajv.validate(schema, config);
if (valid) {
setIsValidVariable(true);
console.log(successMsg());
} else {
setIsValidVariable(false);
console.log(errorMsg(ajv.errors));
}
};
@ -53,6 +59,7 @@ try {
const config = yaml.load(fs.readFileSync('./public/conf.yml', 'utf8'));
validate(config);
} catch (e) {
setIsValidVariable(false);
console.log(bigError());
console.log('Please ensure that your config file is present, '
+ 'has the correct access rights and is parsable. '

View File

@ -61,10 +61,14 @@ module.exports = {
cookieKeys: {
AUTH_TOKEN: 'authenticationToken',
},
sessionStorageKeys: {
SW_STATUS: 'serviceWorkerStatus',
},
modalNames: {
CONF_EDITOR: 'CONF_EDITOR',
CLOUD_BACKUP: 'CLOUD_BACKUP',
REBUILD_APP: 'REBUILD_APP',
ABOUT_APP: 'ABOUT_APP',
},
topLevelConfKeys: {
PAGE_INFO: 'pageInfo',

View File

@ -210,7 +210,8 @@ export default {
.home {
padding-bottom: 1px;
background: var(--background);
min-height: calc(100vh - 126px);
// min-height: calc(100vh - 126px);
min-height: calc(100vh - var(--footer-height));
}
/* Outside container wrapping the item groups*/

View File

@ -18,7 +18,7 @@ export default {
appConfig: Object,
},
data: () => ({
url: '',
url: '', // this.$route.query.url || '',
}),
components: {
SideBar,
@ -40,15 +40,23 @@ export default {
fontAwesomeScript.setAttribute('src', `https://kit.fontawesome.com/${faKey}.js`);
document.head.appendChild(fontAwesomeScript);
},
repositionFooter() {
document.getElementsByTagName('footer')[0].style.position = 'fixed';
},
},
mounted() {
const route = this.$route;
if (route.query && route.query.url) this.url = decodeURI(route.query.url);
this.setTheme();
this.initiateFontAwesome();
// this.repositionFooter();
},
};
</script>
<style scoped lang="scss">
.work-space {
min-height: calc(100vh - var(--footer-height));
}
</style>

View File

@ -1,3 +1,9 @@
const ProgressBarPlugin = require('progress-bar-webpack-plugin');
const WebpackBuildNotifierPlugin = require('webpack-build-notifier');
// Get current version
process.env.VUE_APP_VERSION = require('./package.json').version;
module.exports = {
publicPath: process.env.BASE_URL, // || './',
chainWebpack: config => {
@ -10,15 +16,30 @@ module.exports = {
{ test: /.svg$/, loader: 'vue-svg-loader' },
],
},
plugins: [
new ProgressBarPlugin(),
new WebpackBuildNotifierPlugin({
title: 'Dashy Build Complete',
logo: './public/web-icons/dashy-logo.png',
suppressSuccess: true,
showDuration: true,
}),
],
},
pwa: {
name: 'Dashy',
themeColor: '#00CCB4',
manifestPath: './manifest.json',
themeColor: '#00af87',
msTileColor: '#0b1021',
manifestCrossorigin: 'use-credentials',
iconPaths: {
manifestCrossorigin: 'use-credentials',
favicon64: './web-icons/favicon-64x64.png',
favicon32: './web-icons/favicon-32x32.png',
maskIcon: './web-icons/dashy-logo.png',
msTileImage: './web-icons/dashy-logo.png',
},
},
pages: {
dashy: {
entry: 'src/main.js',

286
yarn.lock
View File

@ -16,22 +16,22 @@
dependencies:
"@babel/highlight" "^7.14.5"
"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.14.5":
version "7.14.5"
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.14.5.tgz#8ef4c18e58e801c5c95d3c1c0f2874a2680fadea"
integrity sha512-kixrYn4JwfAVPa0f2yfzc2AWti6WRRyO3XjWW5PJAvtE11qhSayrrcrEnee05KAtNaPC+EwehE8Qt1UedEVB8w==
"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.14.5", "@babel/compat-data@^7.14.7":
version "7.14.7"
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.14.7.tgz#7b047d7a3a89a67d2258dc61f604f098f1bc7e08"
integrity sha512-nS6dZaISCXJ3+518CWiBfEr//gHyMO02uDxBkXTKZDN5POruCnOZ1N4YBRZDCabwF8nZMWBpRxIicmXtBs+fvw==
"@babel/core@^7.11.0":
version "7.14.5"
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.14.5.tgz#d281f46a9905f07d1b3bf71ead54d9c7d89cb1e3"
integrity sha512-RN/AwP2DJmQTZSfiDaD+JQQ/J99KsIpOCfBE5pL+5jJSt7nI3nYGoAXZu+ffYSQ029NLs2DstZb+eR81uuARgg==
version "7.14.6"
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.14.6.tgz#e0814ec1a950032ff16c13a2721de39a8416fcab"
integrity sha512-gJnOEWSqTk96qG5BoIrl5bVtc23DCycmIePPYnamY9RboYdI4nFy5vAQMSl81O5K/W0sLDWfGysnOECC+KUUCA==
dependencies:
"@babel/code-frame" "^7.14.5"
"@babel/generator" "^7.14.5"
"@babel/helper-compilation-targets" "^7.14.5"
"@babel/helper-module-transforms" "^7.14.5"
"@babel/helpers" "^7.14.5"
"@babel/parser" "^7.14.5"
"@babel/helpers" "^7.14.6"
"@babel/parser" "^7.14.6"
"@babel/template" "^7.14.5"
"@babel/traverse" "^7.14.5"
"@babel/types" "^7.14.5"
@ -77,9 +77,9 @@
semver "^6.3.0"
"@babel/helper-create-class-features-plugin@^7.14.5":
version "7.14.5"
resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.14.5.tgz#8842ec495516dd1ed8f6c572be92ba78b1e9beef"
integrity sha512-Uq9z2e7ZtcnDMirRqAGLRaLwJn+Lrh388v5ETrR3pALJnElVh2zqQmdbz4W2RUJYohAPh2mtyPUgyMHMzXMncQ==
version "7.14.6"
resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.14.6.tgz#f114469b6c06f8b5c59c6c4e74621f5085362542"
integrity sha512-Z6gsfGofTxH/+LQXqYEK45kxmcensbzmk/oi8DmaQytlQCgqNZt9XQF8iqlI/SeXWVjaMNxvYvzaYw+kh42mDg==
dependencies:
"@babel/helper-annotate-as-pure" "^7.14.5"
"@babel/helper-function-name" "^7.14.5"
@ -141,9 +141,9 @@
"@babel/types" "^7.14.5"
"@babel/helper-member-expression-to-functions@^7.14.5":
version "7.14.5"
resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.14.5.tgz#d5c70e4ad13b402c95156c7a53568f504e2fb7b8"
integrity sha512-UxUeEYPrqH1Q/k0yRku1JE7dyfyehNwT6SVkMHvYvPDv4+uu627VXBckVj891BO8ruKBkiDoGnZf4qPDD8abDQ==
version "7.14.7"
resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.14.7.tgz#97e56244beb94211fe277bd818e3a329c66f7970"
integrity sha512-TMUt4xKxJn6ccjcOW7c4hlwyJArizskAhoSTOCkA0uZ+KghIaci0Qg9R043kUMWI9mtQfgny+NQ5QATnZ+paaA==
dependencies:
"@babel/types" "^7.14.5"
@ -240,10 +240,10 @@
"@babel/traverse" "^7.14.5"
"@babel/types" "^7.14.5"
"@babel/helpers@^7.14.5":
version "7.14.5"
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.14.5.tgz#4870f8d9a6fdbbd65e5674a3558b4ff7fef0d9b2"
integrity sha512-xtcWOuN9VL6nApgVHtq3PPcQv5qFBJzoSZzJ/2c0QK/IP/gxVcoWSNQwFEGvmbQsuS9rhYqjILDGGXcTkA705Q==
"@babel/helpers@^7.14.6":
version "7.14.6"
resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.14.6.tgz#5b58306b95f1b47e2a0199434fa8658fa6c21635"
integrity sha512-yesp1ENQBiLI+iYHSJdoZKUtRpfTlL1grDIX9NRlAVppljLw/4tTyYupIB7uIYmC3stW/imAv8EqaKaS/ibmeA==
dependencies:
"@babel/template" "^7.14.5"
"@babel/traverse" "^7.14.5"
@ -258,10 +258,10 @@
chalk "^2.0.0"
js-tokens "^4.0.0"
"@babel/parser@^7.14.5", "@babel/parser@^7.7.0":
version "7.14.5"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.14.5.tgz#4cd2f346261061b2518873ffecdf1612cb032829"
integrity sha512-TM8C+xtH/9n1qzX+JNHi7AN2zHMTiPUtspO0ZdHflW8KaskkALhMmuMHb4bCmNdv9VAPzJX3/bXqkVLnAvsPfg==
"@babel/parser@^7.14.5", "@babel/parser@^7.14.6", "@babel/parser@^7.14.7", "@babel/parser@^7.7.0":
version "7.14.7"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.14.7.tgz#6099720c8839ca865a2637e6c85852ead0bdb595"
integrity sha512-X67Z5y+VBJuHB/RjwECp8kSl5uYi0BvRbNeWqkaJCVh+LiTPl19WBUfG627psSgp9rSf6ojuXghQM3ha6qHHdA==
"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.14.5":
version "7.14.5"
@ -272,10 +272,10 @@
"@babel/helper-skip-transparent-expression-wrappers" "^7.14.5"
"@babel/plugin-proposal-optional-chaining" "^7.14.5"
"@babel/plugin-proposal-async-generator-functions@^7.14.5":
version "7.14.5"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.14.5.tgz#4024990e3dd74181f4f426ea657769ff49a2df39"
integrity sha512-tbD/CG3l43FIXxmu4a7RBe4zH7MLJ+S/lFowPFO7HetS2hyOZ/0nnnznegDuzFzfkyQYTxqdTH/hKmuBngaDAA==
"@babel/plugin-proposal-async-generator-functions@^7.14.7":
version "7.14.7"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.14.7.tgz#784a48c3d8ed073f65adcf30b57bcbf6c8119ace"
integrity sha512-RK8Wj7lXLY3bqei69/cc25gwS5puEc3dknoFPFbqfy3XxYQBQFvu4ioWpafMBAB+L9NyptQK4nMOa5Xz16og8Q==
dependencies:
"@babel/helper-plugin-utils" "^7.14.5"
"@babel/helper-remap-async-to-generator" "^7.14.5"
@ -355,12 +355,12 @@
"@babel/helper-plugin-utils" "^7.14.5"
"@babel/plugin-syntax-numeric-separator" "^7.10.4"
"@babel/plugin-proposal-object-rest-spread@^7.14.5":
version "7.14.5"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.14.5.tgz#e581d5ccdfa187ea6ed73f56c6a21c1580b90fbf"
integrity sha512-VzMyY6PWNPPT3pxc5hi9LloKNr4SSrVCg7Yr6aZpW4Ym07r7KqSU/QXYwjXLVxqwSv0t/XSXkFoKBPUkZ8vb2A==
"@babel/plugin-proposal-object-rest-spread@^7.14.7":
version "7.14.7"
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.14.7.tgz#5920a2b3df7f7901df0205974c0641b13fd9d363"
integrity sha512-082hsZz+sVabfmDWo1Oct1u1AgbKbUAyVgmX4otIc7bdsRgHBXwTwb3DpDmD4Eyyx6DNiuz5UAATT655k+kL5g==
dependencies:
"@babel/compat-data" "^7.14.5"
"@babel/compat-data" "^7.14.7"
"@babel/helper-compilation-targets" "^7.14.5"
"@babel/helper-plugin-utils" "^7.14.5"
"@babel/plugin-syntax-object-rest-spread" "^7.8.3"
@ -571,10 +571,10 @@
dependencies:
"@babel/helper-plugin-utils" "^7.14.5"
"@babel/plugin-transform-destructuring@^7.14.5":
version "7.14.5"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.14.5.tgz#d32ad19ff1a6da1e861dc62720d80d9776e3bf35"
integrity sha512-wU9tYisEbRMxqDezKUqC9GleLycCRoUsai9ddlsq54r8QRLaeEhc+d+9DqCG+kV9W2GgQjTZESPTpn5bAFMDww==
"@babel/plugin-transform-destructuring@^7.14.7":
version "7.14.7"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.14.7.tgz#0ad58ed37e23e22084d109f185260835e5557576"
integrity sha512-0mDE99nK+kVh3xlc5vKwB6wnP9ecuSj+zQCa/n0voENtP/zymdT4HH6QEb65wjjcbqr1Jb/7z9Qp7TF5FtwYGw==
dependencies:
"@babel/helper-plugin-utils" "^7.14.5"
@ -668,10 +668,10 @@
"@babel/helper-module-transforms" "^7.14.5"
"@babel/helper-plugin-utils" "^7.14.5"
"@babel/plugin-transform-named-capturing-groups-regex@^7.14.5":
version "7.14.5"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.14.5.tgz#d537e8ee083ee6f6aa4f4eef9d2081d555746e4c"
integrity sha512-+Xe5+6MWFo311U8SchgeX5c1+lJM+eZDBZgD+tvXu9VVQPXwwVzeManMMjYX6xw2HczngfOSZjoFYKwdeB/Jvw==
"@babel/plugin-transform-named-capturing-groups-regex@^7.14.7":
version "7.14.7"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.14.7.tgz#60c06892acf9df231e256c24464bfecb0908fd4e"
integrity sha512-DTNOTaS7TkW97xsDMrp7nycUVh6sn/eq22VaxWfEdzuEbRsiaOU0pqU7DlyUGHVsbQbSghvjKRpEl+nUCKGQSg==
dependencies:
"@babel/helper-create-regexp-features-plugin" "^7.14.5"
@ -737,10 +737,10 @@
dependencies:
"@babel/helper-plugin-utils" "^7.14.5"
"@babel/plugin-transform-spread@^7.14.5":
version "7.14.5"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.14.5.tgz#bd269fb4119754d2ce7f4cc39a96b4f71baae356"
integrity sha512-/3iqoQdiWergnShZYl0xACb4ADeYCJ7X/RgmwtXshn6cIvautRPAFzhd58frQlokLO6Jb4/3JXvmm6WNTPtiTw==
"@babel/plugin-transform-spread@^7.14.6":
version "7.14.6"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.14.6.tgz#6bd40e57fe7de94aa904851963b5616652f73144"
integrity sha512-Zr0x0YroFJku7n7+/HH3A2eIrGMjbmAIbJSVv0IZ+t3U2WUQUA64S/oeied2e+MaGSjmt4alzBCsK9E8gh+fag==
dependencies:
"@babel/helper-plugin-utils" "^7.14.5"
"@babel/helper-skip-transparent-expression-wrappers" "^7.14.5"
@ -782,16 +782,16 @@
"@babel/helper-plugin-utils" "^7.14.5"
"@babel/preset-env@^7.11.0":
version "7.14.5"
resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.14.5.tgz#c0c84e763661fd0e74292c3d511cb33b0c668997"
integrity sha512-ci6TsS0bjrdPpWGnQ+m4f+JSSzDKlckqKIJJt9UZ/+g7Zz9k0N8lYU8IeLg/01o2h8LyNZDMLGgRLDTxpudLsA==
version "7.14.7"
resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.14.7.tgz#5c70b22d4c2d893b03d8c886a5c17422502b932a"
integrity sha512-itOGqCKLsSUl0Y+1nSfhbuuOlTs0MJk2Iv7iSH+XT/mR8U1zRLO7NjWlYXB47yhK4J/7j+HYty/EhFZDYKa/VA==
dependencies:
"@babel/compat-data" "^7.14.5"
"@babel/compat-data" "^7.14.7"
"@babel/helper-compilation-targets" "^7.14.5"
"@babel/helper-plugin-utils" "^7.14.5"
"@babel/helper-validator-option" "^7.14.5"
"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.14.5"
"@babel/plugin-proposal-async-generator-functions" "^7.14.5"
"@babel/plugin-proposal-async-generator-functions" "^7.14.7"
"@babel/plugin-proposal-class-properties" "^7.14.5"
"@babel/plugin-proposal-class-static-block" "^7.14.5"
"@babel/plugin-proposal-dynamic-import" "^7.14.5"
@ -800,7 +800,7 @@
"@babel/plugin-proposal-logical-assignment-operators" "^7.14.5"
"@babel/plugin-proposal-nullish-coalescing-operator" "^7.14.5"
"@babel/plugin-proposal-numeric-separator" "^7.14.5"
"@babel/plugin-proposal-object-rest-spread" "^7.14.5"
"@babel/plugin-proposal-object-rest-spread" "^7.14.7"
"@babel/plugin-proposal-optional-catch-binding" "^7.14.5"
"@babel/plugin-proposal-optional-chaining" "^7.14.5"
"@babel/plugin-proposal-private-methods" "^7.14.5"
@ -826,7 +826,7 @@
"@babel/plugin-transform-block-scoping" "^7.14.5"
"@babel/plugin-transform-classes" "^7.14.5"
"@babel/plugin-transform-computed-properties" "^7.14.5"
"@babel/plugin-transform-destructuring" "^7.14.5"
"@babel/plugin-transform-destructuring" "^7.14.7"
"@babel/plugin-transform-dotall-regex" "^7.14.5"
"@babel/plugin-transform-duplicate-keys" "^7.14.5"
"@babel/plugin-transform-exponentiation-operator" "^7.14.5"
@ -838,7 +838,7 @@
"@babel/plugin-transform-modules-commonjs" "^7.14.5"
"@babel/plugin-transform-modules-systemjs" "^7.14.5"
"@babel/plugin-transform-modules-umd" "^7.14.5"
"@babel/plugin-transform-named-capturing-groups-regex" "^7.14.5"
"@babel/plugin-transform-named-capturing-groups-regex" "^7.14.7"
"@babel/plugin-transform-new-target" "^7.14.5"
"@babel/plugin-transform-object-super" "^7.14.5"
"@babel/plugin-transform-parameters" "^7.14.5"
@ -846,7 +846,7 @@
"@babel/plugin-transform-regenerator" "^7.14.5"
"@babel/plugin-transform-reserved-words" "^7.14.5"
"@babel/plugin-transform-shorthand-properties" "^7.14.5"
"@babel/plugin-transform-spread" "^7.14.5"
"@babel/plugin-transform-spread" "^7.14.6"
"@babel/plugin-transform-sticky-regex" "^7.14.5"
"@babel/plugin-transform-template-literals" "^7.14.5"
"@babel/plugin-transform-typeof-symbol" "^7.14.5"
@ -857,7 +857,7 @@
babel-plugin-polyfill-corejs2 "^0.2.2"
babel-plugin-polyfill-corejs3 "^0.2.2"
babel-plugin-polyfill-regenerator "^0.2.2"
core-js-compat "^3.14.0"
core-js-compat "^3.15.0"
semver "^6.3.0"
"@babel/preset-modules@^0.1.4":
@ -872,9 +872,9 @@
esutils "^2.0.2"
"@babel/runtime@^7.0.0", "@babel/runtime@^7.11.0", "@babel/runtime@^7.13.10", "@babel/runtime@^7.3.4", "@babel/runtime@^7.8.4":
version "7.14.5"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.5.tgz#665450911c6031af38f81db530f387ec04cd9a98"
integrity sha512-121rumjddw9c3NCQ55KGkyE1h/nzWhU/owjhw0l4mQrkzz4x9SGS1X8gFLraHwX7td3Yo4QTL+qj0NcIzN87BA==
version "7.14.6"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.6.tgz#535203bc0892efc7dec60bdc27b2ecf6e409062d"
integrity sha512-/PCB2uJ7oM44tz8YhC4Z/6PeOKXp4K588f+5M3clr1M4zbqztlo0XEfJ2LEzj/FgwfgGcIdl8n7YYjTCI0BYwg==
dependencies:
regenerator-runtime "^0.13.4"
@ -888,16 +888,16 @@
"@babel/types" "^7.14.5"
"@babel/traverse@^7.0.0", "@babel/traverse@^7.13.0", "@babel/traverse@^7.14.5", "@babel/traverse@^7.7.0":
version "7.14.5"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.14.5.tgz#c111b0f58afab4fea3d3385a406f692748c59870"
integrity sha512-G3BiS15vevepdmFqmUc9X+64y0viZYygubAMO8SvBmKARuF6CPSZtH4Ng9vi/lrWlZFGe3FWdXNy835akH8Glg==
version "7.14.7"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.14.7.tgz#64007c9774cfdc3abd23b0780bc18a3ce3631753"
integrity sha512-9vDr5NzHu27wgwejuKL7kIOm4bwEtaPQ4Z6cpCmjSuaRqpH/7xc4qcGEscwMqlkwgcXl6MvqoAjZkQ24uSdIZQ==
dependencies:
"@babel/code-frame" "^7.14.5"
"@babel/generator" "^7.14.5"
"@babel/helper-function-name" "^7.14.5"
"@babel/helper-hoist-variables" "^7.14.5"
"@babel/helper-split-export-declaration" "^7.14.5"
"@babel/parser" "^7.14.5"
"@babel/parser" "^7.14.7"
"@babel/types" "^7.14.5"
debug "^4.1.0"
globals "^11.1.0"
@ -1082,9 +1082,9 @@
integrity sha512-fZQQafSREFyuZcdWFAExYjBiCL7AUCdgsk80iO0q4yihYYdcIiH28CcuPTGFgLOCC8RlW49GSQxdHwZP+I7CNg==
"@types/node@*":
version "15.12.2"
resolved "https://registry.yarnpkg.com/@types/node/-/node-15.12.2.tgz#1f2b42c4be7156ff4a6f914b2fb03d05fa84e38d"
integrity sha512-zjQ69G564OCIWIOHSXyQEEDpdpGl+G348RAKY0XXy9Z5kU9Vzv1GMNnkar/ZJ8dzXB3COzD9Mo9NtRZ4xfgUww==
version "15.12.4"
resolved "https://registry.yarnpkg.com/@types/node/-/node-15.12.4.tgz#e1cf817d70a1e118e81922c4ff6683ce9d422e26"
integrity sha512-zrNj1+yqYF4WskCMOHwN+w9iuD12+dGm0rQ35HLl9/Ouuq52cEtd0CH9qMgrdNmi5ejC1/V7vKEXYubB+65DkA==
"@types/normalize-package-data@^2.4.0":
version "2.4.0"
@ -1418,14 +1418,15 @@
strip-ansi "^6.0.0"
"@vue/component-compiler-utils@^3.1.0", "@vue/component-compiler-utils@^3.1.2":
version "3.2.1"
resolved "https://registry.yarnpkg.com/@vue/component-compiler-utils/-/component-compiler-utils-3.2.1.tgz#c3e3cb85ea80cc157eeaffe128a25dfe77e2f326"
integrity sha512-Mci9WJYLRjyJEBkGHMPxZ1ihJ9l6gOy2Gr6hpYZUNpQoe5+nbpeb3w00aP+PSHJygCF+fxJsqp7Af1zGDITzuw==
version "3.2.2"
resolved "https://registry.yarnpkg.com/@vue/component-compiler-utils/-/component-compiler-utils-3.2.2.tgz#2f7ed5feed82ff7f0284acc11d525ee7eff22460"
integrity sha512-rAYMLmgMuqJFWAOb3Awjqqv5X3Q3hVr4jH/kgrFJpiU0j3a90tnNBplqbj+snzrgZhC9W128z+dtgMifOiMfJg==
dependencies:
consolidate "^0.15.1"
hash-sum "^1.0.2"
lru-cache "^4.1.2"
merge-source-map "^1.1.0"
postcss "^7.0.36"
postcss-selector-parser "^6.0.2"
source-map "~0.6.1"
vue-template-es2015-compiler "^1.9.0"
@ -1750,7 +1751,7 @@ anymatch@^2.0.0:
micromatch "^3.1.4"
normalize-path "^2.1.1"
anymatch@^3.0.0, anymatch@~3.1.1:
anymatch@^3.0.0, anymatch@~3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716"
integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==
@ -1985,12 +1986,12 @@ babel-plugin-polyfill-corejs2@^0.2.2:
semver "^6.1.1"
babel-plugin-polyfill-corejs3@^0.2.2:
version "0.2.2"
resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.2.2.tgz#7424a1682ee44baec817327710b1b094e5f8f7f5"
integrity sha512-l1Cf8PKk12eEk5QP/NQ6TH8A1pee6wWDJ96WjxrMXFLHLOBFzYM4moG80HFgduVhTqAFez4alnZKEhP/bYHg0A==
version "0.2.3"
resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.2.3.tgz#72add68cf08a8bf139ba6e6dfc0b1d504098e57b"
integrity sha512-rCOFzEIJpJEAU14XCcV/erIf/wZQMmMT5l5vXOpL5uoznyOGfDIjPj6FVytMvtzaKSTSVKouOCTPJ5OMUZH30g==
dependencies:
"@babel/helper-define-polyfill-provider" "^0.2.2"
core-js-compat "^3.9.1"
core-js-compat "^3.14.0"
babel-plugin-polyfill-regenerator@^0.2.2:
version "0.2.2"
@ -2411,9 +2412,9 @@ caniuse-api@^3.0.0:
lodash.uniq "^4.5.0"
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001219:
version "1.0.30001237"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001237.tgz#4b7783661515b8e7151fc6376cfd97f0e427b9e5"
integrity sha512-pDHgRndit6p1NR2GhzMbQ6CkRrp4VKuSsqbcLeOQppYPKOYkKT/6ZvZDvKJUqcmtyWIAHuZq3SVS2vc1egCZzw==
version "1.0.30001239"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001239.tgz#66e8669985bb2cb84ccb10f68c25ce6dd3e4d2b8"
integrity sha512-cyBkXJDMeI4wthy8xJ2FvDU6+0dtcZSJW3voUF8+e9f1bBeuvyZfc3PNbkOETyhbR+dGCPzn9E7MA3iwzusOhQ==
case-sensitive-paths-webpack-plugin@^2.3.0:
version "2.4.0"
@ -2434,6 +2435,14 @@ chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2:
escape-string-regexp "^1.0.5"
supports-color "^5.3.0"
chalk@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4"
integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==
dependencies:
ansi-styles "^4.1.0"
supports-color "^7.1.0"
chalk@^4.0.0, chalk@^4.1.0:
version "4.1.1"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.1.tgz#c80b3fab28bf6371e6863325eee67e618b77e6ad"
@ -2453,19 +2462,19 @@ check-types@^8.0.3:
integrity sha512-YpeKZngUmG65rLudJ4taU7VLkOCTMhNl/u4ctNC56LQS/zJTyNH0Lrtwm1tfTsbLlwvlfsA2d1c8vCf/Kh2KwQ==
"chokidar@>=3.0.0 <4.0.0", chokidar@^3.4.1:
version "3.5.1"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a"
integrity sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==
version "3.5.2"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.2.tgz#dba3976fcadb016f66fd365021d91600d01c1e75"
integrity sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==
dependencies:
anymatch "~3.1.1"
anymatch "~3.1.2"
braces "~3.0.2"
glob-parent "~5.1.0"
glob-parent "~5.1.2"
is-binary-path "~2.1.0"
is-glob "~4.0.1"
normalize-path "~3.0.0"
readdirp "~3.5.0"
readdirp "~3.6.0"
optionalDependencies:
fsevents "~2.3.1"
fsevents "~2.3.2"
chokidar@^2.1.8:
version "2.1.8"
@ -2805,9 +2814,9 @@ content-type@~1.0.4:
integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
convert-source-map@^1.7.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442"
integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==
version "1.8.0"
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369"
integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==
dependencies:
safe-buffer "~5.1.1"
@ -2856,10 +2865,10 @@ copy-webpack-plugin@^5.1.1:
serialize-javascript "^4.0.0"
webpack-log "^2.0.0"
core-js-compat@^3.14.0, core-js-compat@^3.6.5, core-js-compat@^3.9.1:
version "3.14.0"
resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.14.0.tgz#b574dabf29184681d5b16357bd33d104df3d29a5"
integrity sha512-R4NS2eupxtiJU+VwgkF9WTpnSfZW4pogwKHd8bclWU2sp93Pr5S1uYJI84cMOubJRou7bcfL0vmwtLslWN5p3A==
core-js-compat@^3.14.0, core-js-compat@^3.15.0, core-js-compat@^3.6.5:
version "3.15.1"
resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.15.1.tgz#1afe233716d37ee021956ef097594071b2b585a7"
integrity sha512-xGhzYMX6y7oEGQGAJmP2TmtBLvR4nZmRGEcFa3ubHOq5YEp51gGN9AovVa0AoujGZIq+Wm6dISiYyGNfdflYww==
dependencies:
browserslist "^4.16.6"
semver "7.0.0"
@ -2870,9 +2879,9 @@ core-js@^2.4.0:
integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==
core-js@^3.6.5:
version "3.14.0"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.14.0.tgz#62322b98c71cc2018b027971a69419e2425c2a6c"
integrity sha512-3s+ed8er9ahK+zJpp9ZtuVcDoFzHNiZsPbNAAE4KXgrRHbjSqqNN6xGSXq6bq7TZIbKj4NLrLb6bJ5i+vSVjHA==
version "3.15.1"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.15.1.tgz#6c08ab88abdf56545045ccf5fd81f47f407e7f1a"
integrity sha512-h8VbZYnc9pDzueiS2610IULDkpFFPunHwIpl8yRwFahAEEdSpHlTy3h3z3rKq5h11CaUdBEeRViu9AYvbxiMeg==
core-util-is@1.0.2, core-util-is@~1.0.0:
version "1.0.2"
@ -3471,9 +3480,9 @@ ejs@^2.6.1:
integrity sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==
electron-to-chromium@^1.3.723:
version "1.3.752"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.752.tgz#0728587f1b9b970ec9ffad932496429aef750d09"
integrity sha512-2Tg+7jSl3oPxgsBsWKh5H83QazTkmWG/cnNwJplmyZc7KcN61+I10oUgaXSVk/NwfvN3BdkKDR4FYuRBQQ2v0A==
version "1.3.755"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.755.tgz#4b6101f13de910cf3f0a1789ddc57328133b9332"
integrity sha512-BJ1s/kuUuOeo1bF/EM2E4yqW9te0Hpof3wgwBx40AWJE18zsD1Tqo0kr7ijnOc+lRsrlrqKPauJAHqaxOItoUA==
elliptic@^6.5.3:
version "6.5.4"
@ -3765,9 +3774,9 @@ eslint-visitor-keys@^2.0.0:
integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==
eslint@^7.24.0:
version "7.28.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.28.0.tgz#435aa17a0b82c13bb2be9d51408b617e49c1e820"
integrity sha512-UMfH0VSjP0G4p3EWirscJEQ/cHqnT/iuH6oNZOB94nBjWbMnhGEPxsZm1eyIW0C/9jLI0Fow4W5DXLjEI7mn1g==
version "7.29.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.29.0.tgz#ee2a7648f2e729485e4d0bd6383ec1deabc8b3c0"
integrity sha512-82G/JToB9qIy/ArBzIWG9xvvwL3R86AlCjtGw+A29OMZDqhTybz/MByORSukGxeI+YPCR4coYyITKk8BFH9nDA==
dependencies:
"@babel/code-frame" "7.12.11"
"@eslint/eslintrc" "^0.4.2"
@ -4309,7 +4318,7 @@ fsevents@^1.2.7:
bindings "^1.5.0"
nan "^2.12.1"
fsevents@~2.3.1:
fsevents@~2.3.2:
version "2.3.2"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
@ -4387,7 +4396,7 @@ glob-parent@^3.1.0:
is-glob "^3.1.0"
path-dirname "^1.0.0"
glob-parent@^5.1.2, glob-parent@~5.1.0:
glob-parent@^5.1.2, glob-parent@~5.1.2:
version "5.1.2"
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
@ -4472,6 +4481,11 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee"
integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==
growly@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081"
integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=
gzip-size@^5.0.0:
version "5.1.1"
resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-5.1.1.tgz#cb9bee692f87c0612b232840a873904e4c135274"
@ -5255,7 +5269,7 @@ is-wsl@^1.1.0:
resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d"
integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=
is-wsl@^2.1.1:
is-wsl@^2.1.1, is-wsl@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271"
integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==
@ -6106,6 +6120,18 @@ node-libs-browser@^2.2.1:
util "^0.11.0"
vm-browserify "^1.0.1"
node-notifier@9.0.1:
version "9.0.1"
resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-9.0.1.tgz#cea837f4c5e733936c7b9005e6545cea825d1af4"
integrity sha512-fPNFIp2hF/Dq7qLDzSg4vZ0J4e9v60gJR+Qx7RbjbWqzPDdEqeVpEx5CFeDAELIl+A/woaaNn1fQ5nEVerMxJg==
dependencies:
growly "^1.3.0"
is-wsl "^2.2.0"
semver "^7.3.2"
shellwords "^0.1.1"
uuid "^8.3.0"
which "^2.0.2"
node-releases@^1.1.71:
version "1.1.73"
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.73.tgz#dd4e81ddd5277ff846b80b52bb40c49edf7a7b20"
@ -7055,7 +7081,7 @@ postcss-value-parser@^4.0.2, postcss-value-parser@^4.1.0:
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb"
integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==
postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.27, postcss@^7.0.32, postcss@^7.0.5, postcss@^7.0.6:
postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.27, postcss@^7.0.32, postcss@^7.0.36, postcss@^7.0.5, postcss@^7.0.6:
version "7.0.36"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.36.tgz#056f8cffa939662a8f5905950c07d5285644dfcb"
integrity sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==
@ -7109,7 +7135,15 @@ process@^0.11.10:
resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI=
progress@^2.0.0:
progress-bar-webpack-plugin@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/progress-bar-webpack-plugin/-/progress-bar-webpack-plugin-2.1.0.tgz#f7f8c8c461f40b87a8ff168443f494289b07ee65"
integrity sha512-UtlZbnxpYk1wufEWfhIjRn2U52zlY38uvnzFhs8rRxJxC1hSqw88JNR2Mbpqq9Kix8L1nGb3uQ+/1BiUWbigAg==
dependencies:
chalk "^3.0.0"
progress "^2.0.3"
progress@^2.0.0, progress@^2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8"
integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==
@ -7320,10 +7354,10 @@ readdirp@^2.2.1:
micromatch "^3.1.10"
readable-stream "^2.0.2"
readdirp@~3.5.0:
version "3.5.0"
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.5.0.tgz#9ba74c019b15d365278d2e91bb8c48d7b4d42c9e"
integrity sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==
readdirp@~3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7"
integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==
dependencies:
picomatch "^2.2.1"
@ -7639,9 +7673,9 @@ sass-loader@^7.1.0:
semver "^6.3.0"
sass@^1.18.0:
version "1.34.1"
resolved "https://registry.yarnpkg.com/sass/-/sass-1.34.1.tgz#30f45c606c483d47b634f1e7371e13ff773c96ef"
integrity sha512-scLA7EIZM+MmYlej6sdVr0HRbZX5caX5ofDT9asWnUJj21oqgsC+1LuNfm0eg+vM0fCTZHhwImTiCU0sx9h9CQ==
version "1.35.1"
resolved "https://registry.yarnpkg.com/sass/-/sass-1.35.1.tgz#90ecf774dfe68f07b6193077e3b42fb154b9e1cd"
integrity sha512-oCisuQJstxMcacOPmxLNiLlj4cUyN2+8xJnG7VanRoh2GOLr9RqkvI4AxA4a6LHVg/rsu+PmxXeGhrdSF9jCiQ==
dependencies:
chokidar ">=3.0.0 <4.0.0"
@ -7830,6 +7864,11 @@ shell-quote@^1.6.1:
resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.2.tgz#67a7d02c76c9da24f99d20808fcaded0e0e04be2"
integrity sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==
shellwords@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b"
integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==
signal-exit@^3.0.0, signal-exit@^3.0.2:
version "3.0.3"
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c"
@ -8759,6 +8798,11 @@ uuid@^3.3.2, uuid@^3.4.0:
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
uuid@^8.3.0:
version "8.3.2"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
v-jsoneditor@^1.4.2:
version "1.4.4"
resolved "https://registry.yarnpkg.com/v-jsoneditor/-/v-jsoneditor-1.4.4.tgz#ecf0188e8e590222fb243380927db6001f9fade7"
@ -8890,9 +8934,9 @@ vue-resize@^1.0.1:
"@babel/runtime" "^7.13.10"
vue-router@^3.0.3:
version "3.5.1"
resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-3.5.1.tgz#edf3cf4907952d1e0583e079237220c5ff6eb6c9"
integrity sha512-RRQNLT8Mzr8z7eL4p7BtKvRaTSGdCbTy2+Mm5HTJvLGYSSeG9gDzNasJPP/yOYKLy+/cLG/ftrqq5fvkFwBJEw==
version "3.5.2"
resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-3.5.2.tgz#5f55e3f251970e36c3e8d88a7cd2d67a350ade5c"
integrity sha512-807gn82hTnjCYGrnF3eNmIw/dk7/GE4B5h69BlyCK9KHASwSloD1Sjcn06zg9fVG4fYH2DrsNBZkpLtb25WtaQ==
vue-select@^3.11.2:
version "3.11.2"
@ -8970,6 +9014,14 @@ wcwidth@^1.0.1:
dependencies:
defaults "^1.0.3"
webpack-build-notifier@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/webpack-build-notifier/-/webpack-build-notifier-2.3.0.tgz#cb314fbe85b2684e00443b465c08026e812b83f5"
integrity sha512-+/s6GrvSRwP0CHqHOqZcta7EcqjL1MUR9KmBSlkJj6xJVZtFB/z68CTeLPrHnMED/umlXN9hcFV8wmGjeI/K2A==
dependencies:
node-notifier "9.0.1"
strip-ansi "^6.0.0"
webpack-bundle-analyzer@^3.8.0:
version "3.9.0"
resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.9.0.tgz#f6f94db108fb574e415ad313de41a2707d33ef3c"
@ -9136,7 +9188,7 @@ which@^1.2.9:
dependencies:
isexe "^2.0.0"
which@^2.0.1:
which@^2.0.1, which@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"
integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==
@ -9381,9 +9433,9 @@ yargs-parser@^13.1.2:
decamelize "^1.2.0"
yargs-parser@^20.2.2:
version "20.2.7"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.7.tgz#61df85c113edfb5a7a4e36eb8aa60ef423cbc90a"
integrity sha512-FiNkvbeHzB/syOjIUxFDCnhSfzAL8R5vs40MgLFBorXACCOAEaWu0gRZl14vG8MR9AOJIZbmkjhusqBYZ3HTHw==
version "20.2.9"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee"
integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==
yargs@^13.3.2:
version "13.3.2"