Merge branch 'master' of github.com:Lissy93/dashy into snyk-upgrade-adfb0783bfec9e15e9d969b71ebd52a9

This commit is contained in:
Alicia Sykes 2021-08-11 21:56:47 +01:00
commit 2d5347bfea
42 changed files with 655 additions and 210 deletions

30
.github/CHANGELOG.md vendored
View File

@ -1,8 +1,34 @@
# Changelog
## ✨ 1.5.8 - Multi-Tasking Support in Workspace View [PR #146](https://github.com/Lissy93/dashy/pull/146)
- Adds option to keep launched apps open in the background, to reduce friction when switching between websites, Re: #144
- This can be enabled by setting `appConfig.enableMultiTasking: true`
- Note that having many apps opened simultaneously, will have an impact on performance
## ✨ 1.5.7 - Adds Support for Material Design Icons [PR #141](https://github.com/Lissy93/dashy/pull/141)
- Enables user to use any icon from [materialdesignicons.com](https://dev.materialdesignicons.com/icons), Re: #139
- Also adds support for [simpleicons.org](https://simpleicons.org/)
- Assets only loaded when needed
- Adds docs for using MDI icons
## ⚡️ 1.5.6 - Refactor + Couple of small things [PR #135](https://github.com/Lissy93/dashy/pull/135)
- The main Dockerfile now uses yarn.lock instead of package-lock.json
- Adds a check to verify password is not empty in cloud backup screen
- Improves responsiveness of config modals for mobile devices
- Enables the user to use their own self-hosted Sentry instance
- Removes the View Config tab of the Config menu, as not needed
- Updates and fixes some typos in the readme
## 🌐 1.5.5 - Adds Missing Translations + Small UI Issues [PR #129](https://github.com/Lissy93/dashy/pull/129)
- Adds missing translations to several UI elements, Re: #126
- Fixes login translations not being picked up on page load, Re: #127
- Fixes small text overflow glitch in config icon, Re: #123
- Several small UI improvements: height of config editor, scrollbar on theme dropdown, page height, white-on-white on material theme, etc
- Adds an action to auto-assign reviewer based on ./.github/CODEOWNERS file
## 🐳 1.5.4 - Docker ARM Support [PR #122](https://github.com/Lissy93/dashy/pull/122)
- Adds Docker files for `arm64v8` and `arm32v7` in order to support Raspberry Pi and other modern ARM-based devices
- Publishes these images on DockerHub and sets up a workflow to submit a new container every time a release is made
- Adds a Dockerfile for `arm64v8` and `arm32v7`, to support Raspberry Pi and other modern ARM-based devices
- Sets up automated workflow to publish ARM containers to DockerHub after every new release
- Adds documentation for running Dashy on RPi/ ARM-based devices, Re: #117
## 🩹 1.5.3 - UI Quick Fix [PR #121](https://github.com/Lissy93/dashy/pull/121)

16
.github/CODEOWNERS vendored Normal file
View File

@ -0,0 +1,16 @@
# Code Owners helps give greater control to those who developed a feature
# PR's which modify files that you own will be marked as trusted
# After developing a feature, you can add yourself as it's owner
# Each line starts with file pattern, followed by one or more owners
# Codeowners Docs: https://github.blog/2017-07-06-introducing-code-owners/
# Repo Owner
* @lissy93
# Translations
src/assets/locales/de.json @niklashere
src/assets/locales/nl.json @evroon
# Bot PR Permissions
docs/assets/CONTRIBUTORS.svg @liss-bot
docs/*.md @liss-bot

View File

@ -1,15 +1,16 @@
FROM node:lts-alpine
FROM node:lts-alpine3.14
# Define some ENV Vars
ENV PORT 80
ENV DIRECTORY /app
ENV IS_DOCKER true
ENV PORT=80 \
DIRECTORY=/app \
IS_DOCKER=true
# Create and set the working directory
WORKDIR ${DIRECTORY}
# Copy over both 'package.json' and 'package-lock.json' (if available)
COPY package*.json ./
COPY yarn.lock ./
# Install project dependencies
RUN yarn

View File

@ -1,9 +1,22 @@
FROM arm32v7/node:latest
FROM alpine:3.12 AS builder
# Download QEMU, see https://github.com/docker/hub-feedback/issues/1261
RUN QEMU_URL=https://github.com/balena-io/qemu/releases/download/v5.2.0%2Bbalena4/qemu-5.2.0.balena4-arm.tar.gz \
&& apk add curl && curl -L $QEMU_URL | tar zxvf - -C . --strip-components 1
# Start second (arm32v7) stage
FROM arm32v7/alpine:3.12
# Add QEMU from build stage
COPY --from=builder qemu-arm-static /usr/bin
# Install Node and Yarn
RUN apk add --update --no-cache nodejs npm yarn
# Define some ENV Vars
ENV PORT 80
ENV DIRECTORY /app
ENV IS_DOCKER true
ENV PORT=80 \
DIRECTORY=/app \
IS_DOCKER=true
# Create and set the working directory
WORKDIR ${DIRECTORY}

View File

@ -1,9 +1,22 @@
FROM arm64v8/node:latest
FROM alpine:3.12 AS builder
# Download QEMU, see https://github.com/docker/hub-feedback/issues/1261
RUN QEMU_URL=https://github.com/balena-io/qemu/releases/download/v5.2.0%2Bbalena4/qemu-5.2.0.balena4-aarch64.tar.gz \
&& apk add curl && curl -L $QEMU_URL | tar zxvf - -C . --strip-components 1
# Start second (arm64v8) stage
FROM arm64v8/alpine:3.12
# Add QEMU from build stage
COPY --from=builder qemu-aarch64-static /usr/bin
# Install Node and Yarn
RUN apk add --update --no-cache nodejs npm yarn
# Define some ENV Vars
ENV PORT 80
ENV DIRECTORY /app
ENV IS_DOCKER true
ENV PORT=80 \
DIRECTORY=/app \
IS_DOCKER=true
# Create and set the working directory
WORKDIR ${DIRECTORY}

View File

@ -40,7 +40,7 @@
</ul>
<li><b>Community</b></li>
<ul>
<li><a href="#getting-help-">🙋‍♀️ Getting Help</a></li>
<li><a href="#getting-help-%EF%B8%8F">🙋‍♀️ Getting Help</a></li>
<li><a href="#raising-issues-">🐛 Raising Issues</a></li>
<li><a href="#supporting-dashy-">💖 Supporting Dashy</a></li>
<li><a href="#credits-">🏆 Credits</a></li>
@ -58,18 +58,19 @@
- Instant search by name, domain and tags - just start typing
- Full customizable keyboard shortcuts for navigation, filtering and launching apps
- Multiple built-in color themes, with UI color configurator and support for custom CSS
- Easy to customize every part of your dashboard, layout, icon sizes, behavior and colors etc
- Many options for icons, including Font-Awesome support, auto-fetching service favicon, images and emojis
- Multiple built-in color themes, with UI color editor and support for custom CSS
- Customizable layout, sizes, text, component visibility, behavior and colors etc
- Many options for icons, including Font-Awesome support, auto-fetching favicon, images and emojis
- Option to show service status for each of your apps / links, for basic availability and uptime monitoring
- Multiple ways of opening apps, either in your browser, a pop-up modal or workspace view
- Choose how to launch apps, either in your browser, a pop-up modal or workspace view
- Option for full-screen background image, custom nav-bar links, html footer, title, and more
- Encrypted cloud backup and restore feature available
- Optional authentication, requiring admins and non-privileged users to log in
- Easy single-file YAML-based configuration, which can also be configured directly through the UI
- Small bundle size, fully responsive UI and PWA makes the app easy to use on any device
- Easy to setup with Docker, or on bare metal, or with 1-Click cloud deployment
- Multi-language support, with additional languages coming soon
- Multi-language support, with more languages being added regularly
- Easy single-file YAML-based configuration, or configure app directly through the UI
- Strong focus on privacy
- Plus lots more...
## Demo ⚡
@ -101,7 +102,7 @@ Are using Dashy? Want to share your dashboard here too - [Submit your Screenshot
> For full setup instructions, see: [**Deployment**](./docs/deployment.md)
#### Deploying from Docker Hub 🐳
### Deploying from Docker Hub 🐳
You will need [Docker](https://docs.docker.com/get-docker/) installed on your system
@ -121,13 +122,12 @@ docker run -d \
```
If you prefer to use Docker Compose, [here is an example](./docs/deployment.md#using-docker-compose).
You can also build the Docker container from source, by cloning the repo, cd'ing into it and running `docker build .` and `docker compose up`.
> Once you've got Dashy running, you can take a look at [App Management Docs](./docs/management.md), for info on using health checks, provisioning assets, configuring web servers, securing your app, logs, performance and more.
#### Deploying from Source 🚀
### Deploying from Source 🚀
You will need both [git](https://git-scm.com/downloads) and the latest or LTS version of [Node.js](https://nodejs.org/) installed on your system
You will need [git](https://git-scm.com/downloads), the latest or LTS version of [Node.js](https://nodejs.org/) and (optionally) [Yarn](https://yarnpkg.com/) installed on your system.
- Get Code: `git clone git@github.com:Lissy93/dashy.git` and `cd dashy`
- Configuration: Fill in you're settings in `./public/conf.yml`
@ -137,7 +137,7 @@ You will need both [git](https://git-scm.com/downloads) and the latest or LTS ve
> See docs [Full list of Dashy's commands](./docs/management.md#basic-commands)
#### Deploy to the Cloud ☁️
### Deploy to the Cloud ☁️
Dashy supports 1-Click deployments on several popular cloud platforms. To spin up a new instance, just click a link below:
- [<img src="https://i.ibb.co/ZxtzrP3/netlify.png" width="18"/> Deploy to Netlify](https://app.netlify.com/start/deploy?repository=https://github.com/lissy93/dashy)
@ -206,7 +206,8 @@ Both sections and items can have an icon associated with them, and defined under
- **Generative**: Setting `icon: generative`, will generate a unique for a given service, based on it's URL or IP
- **Emoji**: Use an emoji as a tile icon, by putting the emoji's code as the icon attribute. Emojis can be specified either as emojis (`🚀`), unicode (`'U+1F680'`) or shortcode (`':rocket:'`).
- **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.
- **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.
- **Material Design Icons**: You can also use any icon from [materialdesignicons.com](https://dev.materialdesignicons.com/icons) by setting the icon to `mdi-[icon-name]`.
**[⬆️ Back to Top](#dashy)**
@ -348,8 +349,9 @@ Dashy has the ability to support multiple languages and locales. When available,
#### Supported Languages
- 🇬🇧 **English**: `en`
- 🇩🇪 **German**: `de`
- 🇳🇱 **Dutch**: `nl`
- 🇩🇪 **German**: `de` - Contributed by **[@Niklashere](https://github.com/Niklashere)**
- 🇳🇱 **Dutch**: `nl` - Contributed by **[@evroon](https://github.com/evroon)**
- 🇲🇫 **French**: `fr` - Contributed by **[@EVOTk](https://github.com/EVOTk)**
#### Add your Language
It would be awesome for open source projects to be available to everyone, without language being a barrier to entry for non-native English speakers. If you have a few minutes to sapir, you're help with translating it would be very much appreciated.
@ -393,7 +395,7 @@ pageInfo:
> For general discussions, check out the **[Discussions Board](https://github.com/Lissy93/dashy/discussions)**
If you're having trouble getting things up and running, feel free to ask a question. The best way to do so is in the [discussion](https://github.com/Lissy93/dashy/discussions), or if you think you think the issue is on Dashy's side, you can [raise a ticket](https://github.com/Lissy93/dashy/issues/new/choose). It's best to check the [docs](./docs) and [previous questions](https://github.com/Lissy93/dashy/issues?q=label%3A%22%F0%9F%A4%B7%E2%80%8D%E2%99%82%EF%B8%8F+Question%22+) first, as you'll likley find the solution there.
If you're having trouble getting things up and running, feel free to ask a question. The best way to do so is in the [discussion](https://github.com/Lissy93/dashy/discussions), or if you think you think the issue is on Dashy's side, you can [raise a ticket](https://github.com/Lissy93/dashy/issues/new/choose). It's best to check the [docs](./docs) and [previous questions](https://github.com/Lissy93/dashy/issues?q=label%3A%22%F0%9F%A4%B7%E2%80%8D%E2%99%82%EF%B8%8F+Question%22+) first, as you'll likely find the solution there.
**[⬆️ Back to Top](#dashy)**
@ -405,7 +407,8 @@ Found a bug, or something that isn't working as you'd expect? Please raise it as
- [Submit a Feature Request 🦄](https://github.com/Lissy93/dashy/issues/new?assignees=Lissy93&labels=%F0%9F%A6%84+Feature+Request&template=feature-request---.md&title=%5BFEATURE_REQUEST%5D)
- [Share Feedback 🌈](https://github.com/Lissy93/dashy/issues/new?assignees=&labels=%F0%9F%8C%88+Feedback&template=share-feedback---.md&title=%5BFEEDBACK%5D)
**Issue Status** [![Resolution Time](http://isitmaintained.com/badge/resolution/lissy93/dashy.svg) ![Open Issues](http://isitmaintained.com/badge/open/lissy93/dashy.svg) ![Closed Issues](https://badgen.net/github/closed-issues/lissy93/dashy)](https://isitmaintained.com/project/lissy93/dashy)
**Issue Status** [![Resolution Time](http://isitmaintained.com/badge/resolution/lissy93/dashy.svg) ![Open Issues](http://isitmaintained.com/badge/open/lissy93/dashy.svg) ![Closed Issues](https://badgen.net/github/closed-issues/lissy93/dashy)](https://isitmaintained.com/project/lissy93/dashy) [![GitHub Discussions](https://img.shields.io/github/discussions/lissy93/dashy)
](https://github.com/Lissy93/dashy/discussions)
**[⬆️ Back to Top](#dashy)**
@ -435,7 +438,8 @@ Thank you so much to everyone who has helped with Dashy so far, every contributi
#### Sponsors
Huge thanks to the sponsors helping to support Dashy's development!
<!-- sponsors --><!-- sponsors -->
<!-- readme: sponsors -start -->
<!-- readme: sponsors -end -->
#### Contributors
![Auto-generated contributors](https://raw.githubusercontent.com/Lissy93/dashy/master/docs/assets/CONTRIBUTORS.svg)
@ -471,11 +475,12 @@ Like most Git repos, we are following the [Github Flow](https://guides.github.co
Branch names are specified in the following format: `[TYPE]/[TICKET]_[TITLE]`. E.g. `FEATURE/420_Awesome-feature` or `FIX/690_login-server-error`.
Most commits have been using git commit emojis, see [gitmoji.dev](https://gitmoji.dev/) for what each emoji indicates.
Most commit messages use git [commit emojis](https://gist.github.com/parmentf/035de27d6ed1dce0b36a) - e.g. ✨ = New feature, 🐛 = Bug fix, 💄 = UI stuff, 🚧 = Work in progress, 🔖 = New release, and so on. Take a look at [gitmoji.dev](https://gitmoji.dev/) for a list of what each emoji indicates
Before you submit your pull request, please ensure you've checked off all the boxes in the template. For your PR to be merged, it must:
- Must be backwards compatible
- The build, lint and tests (run by GH actions) must pass
- Any new features should be documented
- The build, lint and tests (run by GH actions) should all pass (there are some exceptions)
- There must not be any merge conflicts
If you're new to web development, I've put together a short [list of resources](https://github.com/Lissy93/dashy/blob/master/docs/developing.md#resources-for-beginners), to help beginners get started
@ -524,9 +529,9 @@ If you're new to web development, I've put together a short [list of resources](
---
## 🛣️ Roadmap
## Roadmap 🛣️
> For past and future app updates, see: [**Changelog**](./docs/changelog.md)
> For past and future app updates, see: [**Changelog**](/.github/CHANGELOG.md)
The following features and tasks are planned for the near future.
@ -542,7 +547,10 @@ The following features and tasks are planned for the near future.
## Alternatives 🙌
There are a few self-hosted web apps, that serve a similar purpose to Dashy. If you're looking for a dashboard, and Dashy doesn't meet your needs, I highly recommend you check these projects out!
[HomeDash2](https://lamarios.github.io/Homedash2), [Homer](https://github.com/bastienwirtz/homer) (`Apache License 2.0`), [Organizr](https://organizr.app/) (`GPL-3.0 License`) and [Heimdall](https://github.com/linuxserver/Heimdall) (`MIT License`)
- [HomeDash2](https://lamarios.github.io/Homedash2)
- [Homer](https://github.com/bastienwirtz/homer) (`Apache License 2.0`)
- [Organizr](https://organizr.app/) (`GPL-3.0 License`)
- [Heimdall](https://github.com/linuxserver/Heimdall) (`MIT License`)
**[⬆️ Back to Top](#dashy)**
@ -589,9 +597,15 @@ For more info, see TLDR Legal's [Explanation of MIT](https://tldrlegal.com/licen
<p align="center">
Thank you for Visiting<br>
<a href="https://github.com/Lissy93/dashy">
<img src="https://github.githubassets.com/images/icons/emoji/octocat.png" />
</a>
<br>
<a href="https://dashboard.trackgit.com/token/ks0bx7bb14lsvbwoc3ik">
<img src="https://us-central1-trackgit-analytics.cloudfunctions.net/token/ping/ks0bx7bb14lsvbwoc3ik?style=flat-square" />
</a>
<br><br>
<a href="https://github.com/Lissy93/dashy">
<img src="https://github.githubassets.com/images/icons/emoji/octocat.png" />
</a>
<br><br>
<i>Thank you for Visiting</i>
</p>

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 760 KiB

After

Width:  |  Height:  |  Size: 925 KiB

View File

@ -72,8 +72,10 @@ To disallow any changes from being written to disk via the UI config editor, set
**`externalStyleSheet`** | `string` or `string[]` | _Optional_ | Either a URL to an external stylesheet or an array or URLs, which can be applied as themes within the UI
**`customCss`** | `string` | _Optional_ | Raw CSS that will be applied to the page. This can also be set from the UI. Please minify it first.
**`hideComponents`** | `object` | _Optional_ | A list of key page components (header, footer, search, settings, etc) that are present by default, but can be removed using this option. See [`appConfig.hideComponents`](#appconfighideComponents-optional)
**`enableMultiTasking`** | `boolean` | _Optional_ | If set to true, will keep apps open in the background when in the workspace view. Useful for quickly switching between multiple sites, and preserving their state, but comes at the cost of performance.
**`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.
**`enableErrorReporting`** | `boolean` | _Optional_ | Enable reporting of unexpected errors and crashes. This is off by default, and **no data will ever be captured unless you explicitly enable it**. Turning on error reporting helps previously unknown bugs get discovered and fixed. Dashy uses [Sentry](https://github.com/getsentry/sentry) for error reporting. Defaults to `false`.
**`sentryDsn`** | `boolean` | _Optional_ | If you need to monitor errors in your instance, then you can use Sentry to collect and process bug reports. Sentry can be self-hosted, or used as SaaS, once your instance is setup, then all you need to do is pass in the DSN here, and enable error reporting. You can learn more on the [Sentry DSN Docs](https://docs.sentry.io/product/sentry-basics/dsn-explainer/). Note that this will only ever be used if `enableErrorReporting` is explicitly enabled.
**`disableUpdateChecks`** | `boolean` | _Optional_ | If set to true, Dashy will not check for updates. Defaults to `false`.
**`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.
**`disableContextMenu`** | `boolean` | _Optional_ | If set to `true`, the custom right-click context menu will be disabled. Defaults to `false`.
@ -152,7 +154,7 @@ To disallow any changes from being written to disk via the UI config editor, set
**Field** | **Type** | **Required**| **Description**
--- | --- | --- | ---
**`icon`** | `string` | _Optional_ | The icon for a given item or section. Can be a font-awesome icon, favicon, remote URL or local URL. If set to `favicon`, the icon will be automatically fetched from the items website URL. To use font-awesome, specify the category, followed by the icon name, e.g. `fas fa-rocket`, `fab fa-monero` or `fal fa-duck` - note that to use pro icons, you mut specify `appConfig.fontAwesomeKey`. If set to `generative`, then a unique icon is generated from the apps URL or IP. You can also use hosted any by specifying it's URL, e.g. `https://i.ibb.co/710B3Yc/space-invader-x256.png`. To use a local image, first store it in `./public/item-icons/` (or `-v /app/public/item-icons/` in Docker) , and reference it by name and extension - e.g. set `image.png` to use `./public/item-icon/image.png`, you can also use sub-folders if you have a lot of icons, to keep them organised.
**`icon`** | `string` | _Optional_ | The icon for a given item or section. Can be a font-awesome icon, favicon, remote URL or local URL. If set to `favicon`, the icon will be automatically fetched from the items website URL. To use font-awesome, specify the category, followed by the icon name, e.g. `fas fa-rocket`, `fab fa-monero` or `fal fa-duck` - note that to use pro icons, you mut specify `appConfig.fontAwesomeKey`. Similarly, you can also use [simple-icons](https://simpleicons.org/) by setting icon to `si-[icon-name]` or [material-design-icons](https://dev.materialdesignicons.com/icons) by setting icon to `mdi-[icon-name]`. If set to `generative`, then a unique icon is generated from the apps URL or IP. You can also use hosted any by specifying it's URL, e.g. `https://i.ibb.co/710B3Yc/space-invader-x256.png`. To use a local image, first store it in `./public/item-icons/` (or `-v /app/public/item-icons/` in Docker) , and reference it by name and extension - e.g. set `image.png` to use `./public/item-icon/image.png`, you can also use sub-folders if you have a lot of icons, to keep them organised.
**[⬆️ Back to Top](#configuring)**

View File

@ -10,6 +10,10 @@ Contributing to the code or documentation is super helpful. You can fix a bug, a
## Add Translations
If you speak another language, then adding translations would be really helpful, and you will be credited in the readme for your work. Multi-language support makes Dashy accessible for non-English speakers, which I feel is important. This is a very quick and easy task, as all application text is located in [`locales/en.json`](https://github.com/Lissy93/dashy/blob/master/src/assets/locales/en.json), so adding a new language is as simple as copying this file and translating the values. You don't have to translate it all, as any missing attributes will just fallback to English. For a full tutorial, see the [Multi-Language Support Docs](https://github.com/Lissy93/dashy/blob/master/docs/multi-language-support.md).
## Improve the Docs
Found a typo, or something that isn't as clear as it could be? Maybe I've missed something off altogether, or you hit a roadblock that took you a while to figure out. Submitting a pull request to add to or improve the documentation will help future users get Dashy up and running more easily.
All content is located either in the [`./README.md`](/README.md) or [`/docs/`](/docs) directory, and synced to the Wiki and website using a GH [action](/actions/workflows/wiki-sync.yml).
## Raise a bug
If you've found a bug, then please do raise it as an issue. This will help me know if there's something that needs fixing. Try and include as much detail as possible, such as your environment, steps to reproduce, any console output and maybe an example screenshot or recording if necessary. You can [Raise a Bug here](https://github.com/Lissy93/dashy/issues/new?assignees=Lissy93&labels=%F0%9F%90%9B+Bug&template=bug-report---.md&title=%5BBUG%5D) 🐛.
@ -33,11 +37,12 @@ Dashy is still a relatively young project, and as such not many people know of i
[![Share Dashy via Telegram](https://img.shields.io/badge/Share-Telegram-%230088cc?style=for-the-badge&logo=telegram)](https://t.me/share/url?url=https%3A%2F%2Fgithub.com%2Flissy93%2Fdashy&text=Check%20out%20Dashy%2C%20the%20self-hosted%20dashboard%20for%20your%20homelab%20%F0%9F%9A%80)
[![Share Dashy via Email](https://img.shields.io/badge/Share-Email-%238A90C7?style=for-the-badge&logo=protonmail)](mailto:info@example.com?&subject=Check%20out%20Dashy%20-%20The%20self-hosted%20dashboard%20for%20your%20homelab%20%F0%9F%9A%80&cc=&bcc=&body=https://github.com/lissy93/dashy)
## Leave a review
## Star, Upvote or Leave a Review
Dashy is on the following platforms, and if you could spare a few seconds to give it an upvote or review, this will also help new users find it.
[![ProductHunt](https://img.shields.io/badge/Review-ProductHunt-%23b74424?style=for-the-badge&logo=producthunt)](https://www.producthunt.com/posts/dashy)
[![AlternativeTo](https://img.shields.io/badge/Review-AlternativeTo-%235581a6?style=for-the-badge&logo=abletonlive)](https://alternativeto.net/software/dashy/about/)
[![Star on GitHub](https://img.shields.io/github/stars/Lissy93/Dashy?color=ba96d6&label=Star%20-%20GitHub&logo=github&style=for-the-badge)](https://github.com/Lissy93/dashy/stargazers)
## Make a small donation
@ -47,10 +52,15 @@ Please only do this is you can definitely afford to. Don't feel any pressure to
Sponsoring will give you several perks, from $1 / £0.70 per month, as well as a sponsor badge on your profile, you can also be credited on the readme, with a link to your website/ profile/ socials, get priority support, have your feature ideas implemented, plus lots more. For more info, see [@Lissy93's Sponsor Page](https://github.com/sponsors/Lissy93).
You can also send one-off small contriutions using crypto:
<details>
<summary>You can also send a one-off small contribution using crypto</summary>
<p>
- **BTC**: `3853bSxupMjvxEYfwGDGAaLZhTKxB2vEVC`
- **ETH**: `0x0fc98cBf8bea932B4470C46C0FbE1ed1f6765017` / `aliciasykes.eth`
- **XMR**: `471KZdxb6N63aABR4WYwMRjTVkc1p1x7wGsUTEF7AMYzL8L94A5pCuYWkosgJQ5Ze8Y2PscVCGZFJa3hDPg6MaDq47GUm8r`#
- **XMR**: `471KZdxb6N63aABR4WYwMRjTVkc1p1x7wGsUTEF7AMYzL8L94A5pCuYWkosgJQ5Ze8Y2PscVCGZFJa3hDPg6MaDq47GUm8r`
</p>
</details>
## Request a feature via BountySource
BountySource is a platform for sponsoring the development of certain features on open source projects. If there is a feature you'd like implemented into Dashy, but either isn't high enough priority or is deemed to be more work than it's worth, then you can instead contribute a bounty towards it's development. You won't pay a penny until your proposal is fully built, and you are satisfied with the result. This helps support the developers, and makes Dashy better for everyone.
@ -69,7 +79,7 @@ appConfig:
All reporting is **disabled** by default, and no data will ever be sent to any external endpoint without your explicit consent. In fact, the error tracking package will not even be imported unless you have actively enabled it. All statistics are anonomized and stored securely. For more about privacy and security, see the [Sentry Docs](https://sentry.io/security/).
## Follow for More
If you've enjoyed Dashy, you can follow the me to get updates about other projects that I am working on. Or [subscribe to my mailing list](https://notes.aliciasykes.com/subscribe) for very occasional blog post updates.
If you've enjoyed Dashy, you can follow the me to get updates about other projects that I am working on.
[![Alicia Sykes on Twitter](https://img.shields.io/twitter/follow/Lissy_Sykes?style=social&logo=twitter)](https://twitter.com/Lissy_Sykes)
[![Alicia Sykes on GitHub](https://img.shields.io/github/followers/lissy93?label=Lissy93&style=social)](https://github.com/Lissy93)
@ -79,10 +89,14 @@ If you've enjoyed Dashy, you can follow the me to get updates about other projec
[![Alicia Sykes's Website](https://img.shields.io/badge/aliciasykes.com--lightgrey?style=social&logo=Tencent%20QQ)](https://aliciasykes.com)
[![Alicia Sykes's Blog](https://img.shields.io/badge/Blog--lightgrey?style=social&logo=micro.blog)](https://notes.aliciasykes.com/)
If you like, you could also consider [subscribing to my mailing list](https://notes.aliciasykes.com/subscribe) for very occasional blog post updates, or even [nominating me (`@lissy93`)](https://stars.github.com/nominate/) on the GitHub Star Programme.
---
### Contributors
For a full list of Dashy's contributors, see the [Credits Page](/docs/credits.md)
![Auto-generated contributors](https://raw.githubusercontent.com/Lissy93/dashy/master/docs/assets/CONTRIBUTORS.svg)
### Star-Gazers Over Time

View File

@ -13,7 +13,7 @@
</td>
<td align="center">
<a href="https://github.com/swcarlosrj">
<img src="https://avatars.githubusercontent.com/u/9881700?v=4" width="80;" alt="swcarlosrj"/>
<img src="https://avatars.githubusercontent.com/u/9881700?u=c92e4a0ccc0bff241e50582bce914b179b6d89b6&v=4" width="80;" alt="swcarlosrj"/>
<br />
<sub><b>Carlos Rufo</b></sub>
</a>
@ -39,6 +39,13 @@
<sub><b>Erik Vroon</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/EVOTk">
<img src="https://avatars.githubusercontent.com/u/45015615?v=4" width="80;" alt="EVOTk"/>
<br />
<sub><b>EVOTk</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/BeginCI">
<img src="https://avatars.githubusercontent.com/u/57495754?v=4" width="80;" alt="BeginCI"/>
@ -59,7 +66,8 @@
<br />
<sub><b>Ryan Turner</b></sub>
</a>
</td>
</td></tr>
<tr>
<td align="center">
<a href="https://github.com/snyk-bot">
<img src="https://avatars.githubusercontent.com/u/19733683?v=4" width="80;" alt="snyk-bot"/>
@ -71,7 +79,7 @@
<!-- readme: contributors -end -->
## Helpful Users
<!-- readme: EVOTk,shadowking001,turnrye,Robert-Ernst,MilesTEG1,Niklashere -start -->
<!-- readme: EVOTk,shadowking001,turnrye,Robert-Ernst,Niklashere,evroon,MilesTEG1 -start -->
<table>
<tr>
<td align="center">
@ -152,7 +160,7 @@
This app definitely wouldn't have been quite so possible without the making use of the following package and components. Full credit and big kudos to their respective authors, who've done an amazing job in building and maintaining them. For a full breakdown of dependency licenses, please see [Legal](https://github.com/Lissy93/dashy/blob/master/.github/LEGAL.md)
##### Core
At it's core, the application uses [Vue.js](https://github.com/vuejs/vue), as well as it's services. Styling is done with [SCSS](https://github.com/sass/sass), JavaScript is currently [Babel](https://github.com/babel/babel), (but I am in the process of converting to [TypeScript](https://github.com/Microsoft/TypeScript)), linting is done with [ESLint](https://github.com/eslint/eslint), the config is defined in [YAML](https://github.com/yaml/yaml), and there is a simple [Node.js](https://github.com/nodejs/node) server to serve up the static app.
At it's core, the application uses [Vue.js](https://github.com/vuejs/vue), as well as it's services. Styling is done with [SCSS](https://github.com/sass/sass), JavaScript is currently [Babel](https://github.com/babel/babel), (but I am in the process of converting to [TypeScript](https://github.com/Microsoft/TypeScript)). Linting is done with [ESLint](https://github.com/eslint/eslint) and [Prettier](https://prettier.io/), both following the [AirBnB Styleguide](https://github.com/airbnb/javascript). The config is defined in [YAML](https://github.com/yaml/yaml), and there is a simple [Node.js](https://github.com/nodejs/node) server to serve up the static app and the optional API endpoints.
##### Utilities
- [`crypto-js`](https://github.com/brix/crypto-js) - Encryption implementations by @evanvosberg and community `MIT`
@ -176,7 +184,7 @@ At it's core, the application uses [Vue.js](https://github.com/vuejs/vue), as we
Although the app is purely frontend, there is an optional cloud backup and restore feature. This is built as a serverless function on [Cloudflare workers](https://workers.cloudflare.com/) using [KV](https://developers.cloudflare.com/workers/runtime-apis/kv) and [web crypto](https://developers.cloudflare.com/workers/runtime-apis/web-crypto)
##### External Services
The 1-Click deploy demo uses [Play-with-Docker Labs](https://play-with-docker.com/). Code is hosted on [GitHub](https://github.com), Docker image is hosted on [DockerHub](https://hub.docker.com/), and the demos are hosted on [Netlify](https://www.netlify.com/).
The 1-Click deploy demo uses [Play-with-Docker Labs](https://play-with-docker.com/). Code is hosted on [GitHub](https://github.com), Docker images are hosted on [DockerHub](https://hub.docker.com/), and the demos are hosted on [Netlify](https://www.netlify.com/).
---

View File

@ -10,7 +10,7 @@ docker run -p 8080:80 lissy93/dashy
See [Management Docs](./docs/management.md) for info about securing, monitoring, updating, health checks, auto starting, web server configuration, etc
Once you've got Dashy up and running, you'll want to configure it with your own content. You can either reference the [configuring docs]() or follow this [step-by-step guide]().
Once you've got Dashy up and running, you'll want to configure it with your own content, for this you can reference the [configuring docs](./docs/configuring.md).
## Deployment Methods
@ -100,12 +100,6 @@ If you do not want to use Docker, you can run Dashy directly on your host system
4. Build: `yarn build`
5. Run: `yarn start`
### Run as executable
### Install with NPM
### Use managed instance
### Deploy to cloud service
If you don't have a home server, then fear not - Dashy can be deployed to pretty much any cloud provider. The above Docker and NPM guides will work exactly the same on a VPS, but I've also setup some 1-Click deploy links for 10+ of the most common cloud providers, to make things easier. Note that if your instance is exposed to the internet, it will be your responsibility to adequately secure it.

View File

@ -14,6 +14,8 @@ Both sections and items can have an icon, which is specified using the `icon` at
<img width="500" src="https://i.ibb.co/GTVmZnc/dashy-example-icons.png" />
</p>
Note that, if you are using icons from an external source (like font-awesome or material-design-icons), then the relevant font file will be loaded in automatically if and when needed, but combining icons from multiple services may have a negative impact on performance.
### 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`.
@ -54,7 +56,7 @@ You can use almost any emoji as an icon for items or sections. You can specify t
<img width="580" src="https://i.ibb.co/YLwgTf9/emoji-icons-1.png" />
</p>
The following example shows the unicode options available, all three will render the 🚀 emoji.
The following examples will all render the same rocket (🚀) emoji:
```yaml
items:
@ -74,5 +76,25 @@ You may also want to store your icons locally, bundled within Dashy so that ther
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`
### Material Design Icons
Dashy also supports 5000+ [material-design-icons](https://github.com/Templarian/MaterialDesign). To use these, first find the name/ slug for your icon [here](https://dev.materialdesignicons.com/icons), and then prefix is with `mdi-`.
For example:
```yaml
sections:
- name: Material Design Icons Example
items:
- title: Alien Icon
icon: mdi-alien
- title: Fire Icon
icon: mdi-fire
- title: Dino Icon
icon: mdi-google-downasaur
```
### Simple Icons
To use glyphs from [SimpleIcons.org](https://simpleicons.org/), first find the icon slug, and then prefix it with `si-`. The image will be loaded directly from the Simple Icons
### No Icon
If you don't wish for a given item or section to have an icon, just leave out the `icon` attribute.

View File

@ -31,12 +31,14 @@ The status check util will ping your services directly, and does not rely on any
When the application loads, it checks for updates. The results of which are displayed in the config menu of the UI. This was implemented because using a very outdated version of Dashy may have unfixed issues. Your version is fetched from the source (local request), but the latest version is fetched from GitHub, which is an external request. This can be disabled by setting `appConfig.disableUpdateChecks: true`
### Anonymous Error Reporting
Error reporting is disabled by default, and no data will ever be sent without your explicit consent. In fact, the error tracking method will not even be imported unless you have actively enabled it. [Sentry](https://github.com/getsentry/sentry) is used for this, it's an open source error tracking and performance monitoring tool, which is used to identify any errors which occur in the production app (if you enable it).
Error reporting is disabled by default, and no data will ever be sent without your explicit consent. In fact, the error tracking method will not even be imported unless you have actively enabled it. [Sentry](https://github.com/getsentry/sentry) is used for this, it's an open source error tracking and performance monitoring tool, which is used to identify any issues which occur in the production app (if you enable it).
The crash report includes the file or line of code that triggered the error, and a 2-layer deep stack trace. Reoccurring errors will also include the following user information: OS type (Mac, Windows, Linux, Android or iOS) and browser type (Firefox, Chrome, IE, Safari). Data scrubbing is enabled. IP address will not be stored. If any potentially identifiable data ever finds its way into a crash report, it will be automatically and permanently erased. All statistics collected are anonomized and stored securely, and ae automatically deleted after 14 days. For more about privacy and security, see the [Sentry Docs](https://sentry.io/security/).
Enabling anonymous error reporting helps me to discover bugs I was unaware of, and then fix them, in order to make Dashy more reliable long term. Error reporting is activated by setting `appConfig.enableErrorReporting: true`.
If you need to monitor bugs yourself, then you can [self-host your own Sentry Server](https://develop.sentry.dev/self-hosted/), and use it by setting `appConfig.sentryDsn` to your Sentry instances [Data Source Name](https://docs.sentry.io/product/sentry-basics/dsn-explainer/), then just enable error reporting in Dashy.
---
## Dependencies
@ -58,6 +60,7 @@ There is very little complexity involved with Dashy, and therefore the attack su
- Enable and configure firewall rules
- Implement security, malware and traffic scanning
- Setup malicious traffic detection
- Understand the [Docker attack fronts](https://docs.docker.com/engine/security/), and follow [Docker Security Best Practices](https://snyk.io/blog/10-docker-image-security-best-practices/)
This is covered in more detail in [App Management](/docs/management.md).

View File

@ -21,7 +21,7 @@
- [Status Indicators](/docs/status-indicators.md) - Using Dashy to monitor uptime and status of your apps
- [Theming](/docs/theming.md) - Complete guide to applying, writing and modifying themes and styles
#### Misc
### Misc
- [Privacy & Security](/docs/privacy.md) - List of requests, potential issues, and security resources
- [License](/LICENSE) - Copy of the MIT License
- [Legal](/.github/LEGAL.md) - Licenses of direct dependencies

8
hooks/pre_build Normal file
View File

@ -0,0 +1,8 @@
#!/bin/bash
# Source: https://github.com/ckulka/docker-multi-arch-example/blob/master/hooks/pre_build
# Used to setup QEMU to build arm images on amd64 processors.
# Register qemu-*-static for all supported processors except the
# current one, but also remove all registered binfmt_misc before
docker run --rm --privileged multiarch/qemu-user-static:register --reset

View File

@ -1,6 +1,6 @@
{
"name": "Dashy",
"version": "1.5.4",
"version": "1.5.8",
"license": "MIT",
"main": "server",
"scripts": {
@ -22,7 +22,6 @@
"body-parser": "^1.19.0",
"connect": "^3.7.0",
"crypto-js": "^4.0.0",
"highlight.js": "^11.0.0",
"js-yaml": "^4.1.0",
"npm-run-all": "^4.1.5",
"prismjs": "^1.24.1",
@ -75,6 +74,7 @@
],
"rules": {
"import/no-unresolved": "off",
"import/extensions": "off",
"arrow-parens": 0,
"no-else-return": 0
},

View File

@ -17,10 +17,16 @@
"remember-me-never": "Never",
"remember-me-hour": "4 Hours",
"remember-me-day": "1 Day",
"remember-me-week": "1 Week"
"remember-me-week": "1 Week",
"error-missing-username": "Missing Username",
"error-missing-password": "Missing Password",
"error-incorrect-username": "User not found",
"error-incorrect-password": "Incorrect Password",
"success-message": "Logging in...",
"logout-message": "Logged Out"
},
"config": {
"main-tab": "Config",
"main-tab": "Main Menu",
"view-config-tab": "View Config",
"edit-config-tab": "Edit Config",
"custom-css-tab": "Custom Styles",
@ -59,7 +65,9 @@
"item-size-small": "Small",
"item-size-medium": "Medium",
"item-size-large": "Large",
"config-launcher-label": "Config"
"config-launcher-label": "Config",
"config-launcher-tooltip": "Update Configuration",
"sign-out-tooltip": "Sign Out"
},
"updates": {
"app-version-note": "Dashy version",
@ -134,6 +142,7 @@
"restore-id-label": "Restore ID",
"restore-password-label": "Password",
"restore-button": "Restore",
"backup-missing-password": "Missing Password",
"backup-error-unknown": "Unable to process request",
"backup-error-password": "Incorrect password. Please enter your current password.",
"backup-success-msg": "Completed Successfully",

151
src/assets/locales/fr.json Normal file
View File

@ -0,0 +1,151 @@
{
"home": {
"no-results": "Aucun résultat",
"no-data": "Aucune donnée configurée"
},
"search": {
"search-label": "Recherche",
"search-placeholder": "Commencez à taper pour filtrer",
"clear-search-tooltip": "Effacer la recherche"
},
"login": {
"title": "Dashy",
"username-label": "Nom d'utilisateur",
"password-label": "Mot de passe",
"login-button": "Connexion",
"remember-me-label": "Se souvenir de moi",
"remember-me-never": "Jamais",
"remember-me-hour": "4 Heures",
"remember-me-day": "1 Jour",
"remember-me-week": "1 Semaine",
"error-missing-username": "Nom d'utilisateur manquant",
"error-missing-password": "Mot de passe manquant",
"error-incorrect-username": "Utilisateur inexistant",
"error-incorrect-password": "Mot de passe incorrect",
"success-message": "Connexion ...",
"logout-message": "Déconnexion"
},
"config": {
"main-tab": "Menu principal",
"view-config-tab": "Afficher la configuration",
"edit-config-tab": "Modifier la configuration",
"custom-css-tab": "Styles personnalisés",
"heading": "Options de Configuration",
"download-config-button": "Télécharger la configuration",
"edit-config-button": "Modifier la configuration",
"edit-css-button": "Styles personnalisés",
"cloud-sync-button": "Activer la synchro. dans le cloud",
"edit-cloud-sync-button": "Modifier la synchro. dans le cloud",
"rebuild-app-button": "Reconstruire l'application",
"change-language-button": "Changer la langue",
"reset-settings-button": "Réinitialiser les paramètres locaux",
"app-info-button": "Informations sur l'application",
"backup-note": "Il est recommandé de faire une sauvegarde de votre configuration avant d'apporter des modifications.",
"reset-config-msg-l1": "Cela supprimera tous les paramètres utilisateur du stockage local, mais n'affectera pas votre fichier 'conf.yml'.",
"reset-config-msg-l2": "Vous devez d'abord sauvegarder toutes les modifications locales si vous souhaitez les utiliser à l'avenir.",
"reset-config-msg-l3": "Êtes-vous sur de vouloir continuer ?",
"data-cleared-msg": "Données effacées avec succès",
"actions-label": "Actions",
"copy-config-label": "Copier la configuration",
"data-copied-msg": "La configuration a été copiée dans le presse-papiers",
"reset-config-label": "Réinitialiser la configuration",
"css-save-btn": "Enregistrer",
"css-note-label": "Note",
"css-note-l1": "Vous devrez actualiser la page pour que les modifications prennent effet.",
"css-note-l2": "Les modifications ne sont stockés que localement, il est donc recommandé de faire une copie de votre CSS.",
"css-note-l3": "Pour supprimer tous les styles personnalisés, supprimez le contenu et appuyez sur Enregistrer."
},
"settings": {
"theme-label": "Thème",
"layout-label": "Disposition",
"layout-auto": "Auto",
"layout-horizontal": "Horizontal",
"layout-vertical": "Vertical",
"item-size-label": "Taille",
"item-size-small": "Petite",
"item-size-medium": "Moyenne",
"item-size-large": "Grande",
"config-launcher-label": "Config.",
"config-launcher-tooltip": "Modifier la configuration",
"sign-out-tooltip": "Déconnexion"
},
"updates": {
"app-version-note": "Version de Dashy",
"up-to-date": "À jour",
"out-of-date": "Mise à jour disponible !",
"unsupported-version-l1": "Vous utilisez une version non prise en charge de Dashy",
"unsupported-version-l2": "Pour une meilleure expérience et des correctifs de sécurité récents, veuillez mettre à jour vers"
},
"language-switcher": {
"title": "Changer la langue",
"dropdown-label": "Sélectionnez une langue",
"save-button": "Enregistrer",
"success-msg": "Langue mise à jour vers"
},
"theme-maker": {
"title": "Configurateur de Thèmes",
"export-button": "Exporter des variables personnalisées",
"reset-button": "Réinitialiser les styles pour",
"show-all-button": "Afficher toutes les variables",
"save-button": "Enregistrer",
"cancel-button": "Annuler",
"saved-toast": "{theme} mis à jour avec succès",
"copied-toast": "Données du thème {theme} copiées dans le presse-papiers",
"reset-toast": "Couleurs personnalisées pour {theme} supprimées"
},
"config-editor": {
"save-location-label": "Enregistrer localement",
"location-local-label": "Appliquer localement",
"location-disk-label": "Appliquer dans le fichier de configuration",
"save-button": "Enregistrer",
"valid-label": "La configuration est valide",
"status-success-msg": "Tâche terminée",
"status-fail-msg": "Échec de la tâche",
"success-msg-disk": "Le fichier de configuration est écrit avec succès sur le disque",
"success-msg-local": "Les modifications locales ont bien été enregistrées",
"success-note-l1": "L'application devrait se reconstruire automatiquement.",
"success-note-l2": "Cela peut prendre une minute.",
"success-note-l3": "Vous devrez actualiser la page pour que les modifications prennent effet.",
"error-msg-save-mode": "Veuillez sélectionner un mode d'enregistrement : Local ou Fichier",
"error-msg-cannot-save": "Une erreur s'est produite lors de l'enregistrement de la configuration",
"error-msg-bad-json": "Erreur dans le fichier JSON, il est peut-être mal formé",
"warning-msg-validation": "Attention"
},
"app-rebuild": {
"title": "Reconstruire l'application",
"rebuild-note-l1": "Une reconstruction est requise pour que les modifications écrites dans le fichier conf.yml prennent effet.",
"rebuild-note-l2": "Cela devrait se produire automatiquement, mais si ce n'est pas le cas, vous pouvez le déclencher manuellement ici.",
"rebuild-note-l3": "Ceci n'est pas nécessaire pour les modifications stockées localement.",
"rebuild-button": "Démarrer la reconstruction",
"rebuilding-status-1": "Reconstruction ...",
"rebuilding-status-2": "Cela peut prendre quelques minutes",
"error-permission": "Vous n'êtes pas autorisé à executer cette action",
"success-msg": "Construction terminée avec succès",
"fail-msg": "Échec de la construction",
"reload-note": "Un rechargement de la page est maintenant requis pour que les modifications prennent effet",
"reload-button": "Rafraîchir la page"
},
"cloud-sync": {
"title": "Sauvegarde Cloud & Restauration",
"intro-l1": "Ce service de sauvegarde et de restauration depuis le cloud est une fonctionnalité facultative qui vous permet de télécharger votre configuration sur Internet, puis de la restaurer sur n'importe quel autre appareil ou instance de Dashy.",
"intro-l2": "Toutes les données sont entièrement chiffrées de bout en bout avec le protocole AES, en utilisant votre mot de passe comme clé.",
"intro-l3": "Pour plus d'informations, veuillez consulter la",
"backup-title-setup": "Sauvegarder",
"backup-title-update": "Mettre à jour la sauvegarde",
"password-label-setup": "Choisissez un mot de passe",
"password-label-update": "Entrer votre mot de passe",
"backup-button-setup": "Sauvegarde",
"backup-button-update": "Mettre à jour la sauvegarde",
"backup-id-label": "Votre identifiant de sauvegarde",
"backup-id-note": "Il vous sera demandé par la suite pour restaurer à partir de votre sauvegarde. Alors gardez-le, avec votre mot de passe dans un endroit sûr.",
"restore-title": "Restauration",
"restore-id-label": "Identifiant de sauvegarde",
"restore-password-label": "Mot de passe",
"restore-button": "Restaurer",
"backup-missing-password": "Mot de passe manquant",
"backup-error-unknown": "Impossible de traiter la demande",
"backup-error-password": "Mot de passe incorrect. Veuillez saisir votre mot de passe actuel.",
"backup-success-msg": "Sauvegarde effectuée avec succès",
"restore-success-msg": "Configuration restaurée avec succès"
}
}

View File

@ -96,7 +96,9 @@ export default {
},
checkPass() {
const savedHash = localStorage[localStorageKeys.BACKUP_HASH] || undefined;
if (!savedHash) {
if (!this.backupPassword) {
this.showErrorMsg(this.$t('cloud-sync.backup-missing-password'));
} else if (!savedHash) {
this.makeBackup();
} else if (savedHash === this.makeHash(this.backupPassword)) {
this.makeUpdate();

View File

@ -10,15 +10,15 @@
{{ $t('config.download-config-button') }}
</button>
</a>
<button class="config-button center" @click="() => navigateToTab(2)">
<button class="config-button center" @click="() => navigateToTab(1)">
<EditIcon class="button-icon"/>
{{ $t('config.edit-config-button') }}
</button>
<button class="config-button center" @click="() => navigateToTab(4)">
<button class="config-button center" @click="() => navigateToTab(3)">
<CustomCssIcon class="button-icon"/>
{{ $t('config.edit-css-button') }}
</button>
<button class="config-button center" @click="() => navigateToTab(3)">
<button class="config-button center" @click="() => navigateToTab(2)">
<CloudIcon class="button-icon"/>
{{backupId ? $t('config.edit-cloud-sync-button') : $t('config.cloud-sync-button') }}
</button>
@ -51,21 +51,6 @@
<!-- Rebuild App Modal -->
<RebuildApp />
</TabItem>
<TabItem :name="$t('config.view-config-tab')" class="code-container">
<pre id="conf-yaml">{{yaml}}</pre>
<div class="yaml-action-buttons">
<h2>{{ $t('config.actions-label') }}</h2>
<a class="yaml-button download" @click="downloadConfigFile('conf.yml', yaml)">
{{ $t('config.download-config-button') }}
</a>
<a class="yaml-button copy" @click="copyConfigToClipboard()">
{{ $t('config.copy-config-label') }}
</a>
<a class="yaml-button reset" @click="resetLocalSettings()">
{{ $t('config.reset-config-label') }}
</a>
</div>
</TabItem>
<TabItem :name="$t('config.edit-config-tab')">
<JsonEditor :config="config" />
</TabItem>
@ -79,9 +64,6 @@
</template>
<script>
import hljs from 'highlight.js/lib/core';
import yaml from 'highlight.js/lib/languages/yaml';
import 'highlight.js/styles/mono-blue.css';
import JsonToYaml from '@/utils/JsonToYaml';
import { localStorageKeys, modalNames } from '@/utils/defaults';
@ -179,20 +161,11 @@ export default {
element.click();
document.body.removeChild(element);
},
/* Highlights the YAML config in View config tab */
initiateStntaxHighlighter() {
hljs.registerLanguage('yaml', yaml);
const highlighted = hljs.highlight(this.jsonParser(this.config), { language: 'yaml' }).value;
document.getElementById('conf-yaml').innerHTML = highlighted;
},
getLanguage() {
const lang = getUsersLanguage();
return lang ? `${lang.flag} ${lang.name}` : '';
},
},
mounted() {
this.initiateStntaxHighlighter();
},
};
</script>

View File

@ -11,14 +11,15 @@
</template>
<script>
import CustomThemeMaker from '@/components/Settings/CustomThemeMaker';
import { getTheme } from '@/utils/ConfigHelpers';
import { PrismEditor } from 'vue-prism-editor';
import { highlight, languages } from 'prismjs/components/prism-core';
import 'prismjs/components/prism-css';
import 'prismjs/themes/prism-funky.css';
import 'vue-prism-editor/dist/prismeditor.min.css';
import CustomThemeMaker from '@/components/Settings/CustomThemeMaker';
import { getTheme } from '@/utils/ConfigHelpers';
import { localStorageKeys } from '@/utils/defaults';
export default {

View File

@ -4,7 +4,6 @@
<v-jsoneditor
v-model="jsonData"
:options="options"
height="500px"
/>
<!-- Options raido, and save button -->
<div class="save-options">
@ -56,12 +55,12 @@
<script>
import axios from 'axios';
import VJsoneditor from 'v-jsoneditor';
import { localStorageKeys } from '@/utils/defaults';
import configSchema from '@/utils/ConfigSchema.json';
import JsonToYaml from '@/utils/JsonToYaml';
import { isUserAdmin } from '@/utils/Auth';
import axios from 'axios';
export default {
name: 'JsonEditor',
@ -293,6 +292,10 @@ div.save-options {
}
}
.jsoneditor-container.min-box {
height: 58vh;
}
.jsoneditor, .jsoneditor-menu {
border-color: var(--primary);
}

View File

@ -3,7 +3,7 @@
<a @click="itemOpened"
@mouseup.right="openContextMenu"
@contextmenu.prevent
:href="target !== 'modal' ? url : '#'"
:href="(target !== 'modal' && target !== 'workspace') ? url : '#'"
:target="target === 'newtab' ? '_blank' : ''"
:class="`item ${!icon? 'short': ''} size-${itemSize}`"
v-tooltip="getTooltipOptions()"
@ -100,6 +100,8 @@ export default {
if (e.altKey || this.target === 'modal') {
e.preventDefault();
this.$emit('triggerModal', this.url);
} else if (this.target === 'workspace') {
router.push({ name: 'workspace', query: { url: this.url } });
} else {
this.$emit('itemClicked');
}

View File

@ -1,10 +1,19 @@
<template>
<div class="item-icon">
<!-- Font-Awesome Icon -->
<i v-if="iconType === 'font-awesome'" :class="`${icon} ${size}`" ></i>
<!-- Emoji Icon -->
<i v-else-if="iconType === 'emoji'" :class="`emoji-icon ${size}`" >{{getEmoji(iconPath)}}</i>
<!-- Material Design Icon -->
<span v-else-if="iconType === 'mdi'" :class=" `mdi ${icon} ${size}`"></span>
<!-- Simple-Icons -->
<object v-else-if="iconType === 'si'" :class="`simple-icons ${size}`"
type="image/svg+xml" :data="getSimpleIcon(icon)"></object>
<!-- Standard image asset icon -->
<img v-else-if="icon" :src="iconPath" @error="imageNotFound"
:class="`tile-icon ${size} ${broken ? 'broken' : ''}`"
/>
<!-- Icon could not load/ broken url -->
<BrokenImage v-if="broken" class="missing-image" />
</div>
</template>
@ -12,7 +21,7 @@
<script>
import BrokenImage from '@/assets/interface-icons/broken-icon.svg';
import ErrorHandler from '@/utils/ErrorHandler';
import { faviconApi as defaultFaviconApi, faviconApiEndpoints } from '@/utils/defaults';
import { faviconApi as defaultFaviconApi, faviconApiEndpoints, iconCdns } from '@/utils/defaults';
import EmojiUnicodeRegex from '@/utils/EmojiUnicodeRegex';
import emojiLookup from '@/utils/emojis.json';
@ -28,17 +37,18 @@ export default {
BrokenImage,
},
computed: {
/* Determines the type of icon */
iconType: function iconType() {
return this.determineImageType(this.icon);
},
/* Gets the icon path, dependent on icon type */
iconPath: function iconPath() {
return this.getIconPath(this.icon, this.url);
},
},
data() {
return {
broken: false,
// faviconApi: this.config.appConfig.faviconApi || defaultFaviconApi,
broken: false, // If true, was unable to resolve icon
};
},
methods: {
@ -80,7 +90,7 @@ export default {
getFavicon(fullUrl) {
if (this.shouldUseDefaultFavicon(fullUrl)) { // Check if we should use local icon
const urlParts = fullUrl.split('/');
if (urlParts.length >= 2) return `${urlParts[0]}/${urlParts[1]}/${urlParts[2]}/favicon.ico`;
if (urlParts.length >= 2) return `${urlParts[0]}/${urlParts[1]}/${urlParts[2]}/${iconCdns.faviconName}`;
} else if (fullUrl.includes('http')) { // Service is running publicly
const host = this.getHostName(fullUrl);
const faviconApi = this.config.appConfig.faviconApi || defaultFaviconApi;
@ -95,11 +105,18 @@ export default {
const isLocalIP = /(127\.)|(192\.168\.)|(10\.)|(172\.1[6-9]\.)|(172\.2[0-9]\.)|(172\.3[0-1]\.)|(::1$)|([fF][cCdD])|(localhost)/;
return (isLocalIP.test(fullUrl) || this.config.appConfig.faviconApi === 'local');
},
/* Fetches the path of local images, from Docker container */
getLocalImagePath(img) {
return `/item-icons/${img}`;
return `${iconCdns.localPath}/${img}`;
},
/* Formats the URL for fetching the generative icons */
getGenerativeIcon(url) {
return `https://ipsicon.io/${this.getHostName(url)}.svg`;
return `${iconCdns.generative}/${this.getHostName(url)}.svg`;
},
/* Formats the URL for getting Simple-Icons SVG asset */
getSimpleIcon(img) {
const imageName = img.replace('si-', '');
return `${iconCdns.si}/${imageName}.svg`;
},
/* Checks if the icon is from a local image, remote URL, SVG or font-awesome */
getIconPath(img, url) {
@ -108,8 +125,10 @@ export default {
case 'img': return this.getLocalImagePath(img);
case 'favicon': return this.getFavicon(url);
case 'generative': return this.getGenerativeIcon(url);
case 'svg': return img;
case 'emoji': return img;
case 'mdi': return img; // Material design icons
case 'simple-icons': return this.getSimpleIcon(img);
case 'svg': return img; // Local SVG icon
case 'emoji': return img; // Emoji/ unicode
default: return '';
}
},
@ -121,12 +140,15 @@ export default {
else if (this.isUrl(img)) imgType = 'url';
else if (this.isImage(img)) imgType = 'img';
else if (img.includes('fa-')) imgType = 'font-awesome';
else if (img.includes('mdi-')) imgType = 'mdi';
else if (img.includes('si-')) imgType = 'si';
else if (img === 'favicon') imgType = 'favicon';
else if (img === 'generative') imgType = 'generative';
else if (this.isEmoji(img).isEmoji) imgType = 'emoji';
else imgType = 'none';
return imgType;
},
/* For a given URL, return the hostname only. Used for favicon and generative icons */
getHostName(url) {
try { return new URL(url).hostname; } catch (e) { return url; }
},
@ -140,6 +162,7 @@ export default {
</script>
<style lang="scss">
/* Default Image Icon */
.tile-icon {
width: 2rem;
// filter: var(--item-icon-transform);
@ -152,7 +175,8 @@ export default {
width: 3rem;
}
}
i.fas, i.fab, i.far, i.fal, i.fad {
/* Font-Awesome and Material Design Icons */
i.fas, i.fab, i.far, i.fal, i.fad, span.mdi {
font-size: 2rem;
color: currentColor;
margin: 1px 4px;
@ -163,6 +187,9 @@ export default {
font-size: 2.5rem;
}
}
span.mdi {
font-size: 2.5rem;
}
object.tile-icon {
width: 55px;
height: 55px;
@ -170,6 +197,13 @@ export default {
fill: currentColor;
}
}
/* Simple Icons */
object.simple-icons {
width: 2rem;
&.small { width: 1.5rem; }
&.large { width: 2.5rem; }
}
/* Emoji Icons */
i.emoji-icon {
font-style: normal;
font-size: 2rem;
@ -181,6 +215,7 @@ export default {
font-size: 2.5rem;
}
}
/* Icon Not Found */
.missing-image {
width: 3.5rem;
path {

View File

@ -1,7 +1,7 @@
<template>
<div>
<div class="display-options">
<IconLogout @click="logout()" v-tooltip="tooltip('Sign Out')"
<IconLogout @click="logout()" v-tooltip="tooltip($t('settings.sign-out-tooltip'))"
class="layout-icon" tabindex="-2" />
</div>
</div>
@ -19,7 +19,7 @@ export default {
methods: {
logout() {
registerLogout();
this.$toasted.show('Logged Out');
this.$toasted.show(this.$t('login.logout-message'));
setTimeout(() => {
location.reload(true); // eslint-disable-line no-restricted-globals
}, 500);

View File

@ -4,7 +4,7 @@
<span>{{ $t('settings.config-launcher-label') }}</span>
<div class="config-buttons">
<IconSpanner @click="showEditor()" tabindex="-2"
v-tooltip="tooltip('Update configuration')" />
v-tooltip="tooltip($t('settings.config-launcher-tooltip'))" />
</div>
<!-- Modal containing all the configuration options -->
@ -15,7 +15,7 @@
<!-- Modal for manually changing locale -->
<modal :name="modalNames.LANG_SWITCHER" classes="dashy-modal"
:resizable="true" width="30%" height="25%">
:resizable="true" width="35%" height="35%">
<LanguageSwitcher />
</modal>
@ -73,6 +73,7 @@ export default {
display: flex;
flex-direction: column;
color: var(--settings-text-color);
min-width: 3.2rem;
svg {
path {
fill: var(--settings-text-color);

View File

@ -37,7 +37,6 @@ 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 IconOpen from '@/assets/interface-icons/config-open-settings.svg';
import IconClose from '@/assets/interface-icons/config-close.svg';
import {
@ -88,13 +87,6 @@ export default {
getInitialTheme() {
return this.appConfig.theme || '';
},
logout() {
registerLogout();
this.$toasted.show('Logged Out');
setTimeout(() => {
location.reload(true); // eslint-disable-line no-restricted-globals
}, 100);
},
isUserLoggedIn() {
return !!localStorage[localStorageKeys.USERNAME];
},
@ -199,25 +191,6 @@ export default {
}
}
svg.logout-icon {
path {
fill: var(--settings-text-color);
}
width: 1rem;
height: 1rem;
margin: 0.35rem 0.2rem;
padding: 0.2rem;
text-align: center;
background: var(--background);
border: 1px solid var(--settings-text-color);;
border-radius: var(--curve-factor);
cursor: pointer;
&:hover, &.selected {
background: var(--settings-text-color);
path { fill: var(--background); }
}
}
@include tablet {
section {
display: block;

View File

@ -126,6 +126,7 @@ export default {
<style lang="scss">
@import 'vue-select/src/scss/vue-select.scss';
@import '@/styles/style-helpers.scss';
.theme-dropdown {
div.vs__dropdown-toggle {
@ -146,10 +147,13 @@ export default {
}
ul.vs__dropdown-menu {
width: auto;
background: var(--background);
z-index: 5;
max-width: 13rem;
overflow-x: hidden;
@extend .scroll-bar;
background: var(--background);
border-radius: var(--curve-factor);
border-top: 1px solid var(--settings-text-color);
}
li.vs__dropdown-option--highlight {
background: var(--settings-text-color);

View File

@ -0,0 +1,62 @@
<template>
<div class="multi-taking-view" ref="container"></div>
</template>
<script>
import Vue from 'vue';
import WebContent from '@/components/Workspace/WebContent';
export default {
name: 'WebContent',
props: {
url: String, // The URL of currently visible app
},
data: () => ({
openApps: [], // List of all currently open apps
}),
watch: {
/* Update the currently open app, when URL changes */
url() { this.launchApp(); },
},
methods: {
/* Check if app already open or not, and call appropriate opener */
launchApp() {
if (this.openApps.includes(this.url)) {
this.openExistingApp();
} else {
this.openApps.push(this.url);
this.appendNewApp();
}
},
/* Opens a new app */
appendNewApp() {
const ComponentClass = Vue.extend(WebContent);
const instance = new ComponentClass({
propsData: { url: this.url, id: btoa(this.url) },
});
instance.$mount(); // pass nothing
this.$refs.container.appendChild(instance.$el);
},
/* Switches visibility to an already open app */
openExistingApp() {
Array.from(document.getElementsByClassName('web-content')).forEach((frame) => {
frame.classList.add('hide');
});
document.getElementById(btoa(this.url)).classList.remove('hide');
},
},
};
</script>
<style lang="scss" scoped>
iframe {
position: absolute;
left: var(--side-bar-width);
height: calc(100% - var(--header-height));
width: calc(100% - var(--side-bar-width));
border: none;
background: white;
}
</style>

View File

@ -44,8 +44,6 @@ export default {
</script>
<style lang="scss" scoped>
@import '@/styles/media-queries.scss';
@import '@/styles/style-helpers.scss';
div.side-bar-item {
color: var(--side-bar-color);
@ -56,8 +54,10 @@ div.side-bar-item {
border: none;
box-shadow: none;
p.small-title {
margin: 0.1rem auto;
margin: 0.1rem 0 0 -0.5rem;
font-size: 0.6rem;
transform: rotate(-25deg);
padding: 0.5rem 0;
}
}
}

View File

@ -1,5 +1,5 @@
<template>
<div class="web-content">
<div class="web-content" :id="id">
<iframe :src="url" />
</div>
</template>
@ -10,13 +10,15 @@ export default {
name: 'WebContent',
props: {
url: String,
id: {
type: String,
default: 'web-app-view',
},
},
};
</script>
<style lang="scss" scoped>
@import '@/styles/media-queries.scss';
@import '@/styles/style-helpers.scss';
iframe {
position: absolute;
@ -27,4 +29,8 @@ iframe {
background: white;
}
.web-content.hide {
display: none;
}
</style>

View File

@ -498,7 +498,7 @@ html[data-theme='material'] {
--nav-link-border-color: #0c4eba;
--settings-text-color: #363636;
--config-code-color: #363636;
--config-settings-background: #fff;
--config-settings-background: #f5f5f5;
--config-settings-color: #473f3f;
--heading-text-color: #fff;
--curve-factor: 4px;
@ -508,6 +508,11 @@ html[data-theme='material'] {
--footer-text-color: #f5f5f5cc;
// --login-form-background-secondary: #f5f5f5cc;
--context-menu-secondary-color: #f5f5f5;
--transparent-white-50: #00000080;
div.jsoneditor div.jsoneditor-menu {
background: #5c90eb !important;
}
header {
background: #4285f4;

View File

@ -1,5 +1,6 @@
@import '@/styles/style-helpers.scss';
@import '@/styles/media-queries.scss';
/* Essential global page layout styles */
html {
@ -26,6 +27,13 @@ html {
box-shadow: 0 40px 70px -2px hsl(0deg 0% 0% / 60%), 1px 1px 6px var(--primary) !important;
min-width: 350px;
min-height: 200px;
@include phone {
left: 0.5rem !important;
right: 0.5rem !important;
width: 95% !important;
top: 2rem !important;
}
}
.vm--overlay {
background: #00000080;

View File

@ -43,24 +43,24 @@ export const isLoggedIn = (users) => {
* @param {String[]} users An array of valid user objects
* @returns {Object} An object containing a boolean result and a message
*/
export const checkCredentials = (username, pass, users) => {
let response;
export const checkCredentials = (username, pass, users, messages) => {
let response; // Will store an object containing boolean and message
if (!username) {
response = { correct: false, msg: 'Missing Username' };
response = { correct: false, msg: messages.missingUsername };
} else if (!pass) {
response = { correct: false, msg: 'Missing Password' };
response = { correct: false, msg: messages.missingPassword };
} else {
users.forEach((user) => {
if (user.user.toLowerCase() === username.toLowerCase()) {
if (user.user.toLowerCase() === username.toLowerCase()) { // User found
if (user.hash.toLowerCase() === sha256(pass).toString().toLowerCase()) {
response = { correct: true, msg: 'Logging in...' };
} else {
response = { correct: false, msg: 'Incorrect Password' };
response = { correct: true, msg: messages.successMsg }; // Password is correct
} else { // User found, but password is not a match
response = { correct: false, msg: messages.incorrectPassword };
}
}
});
}
return response || { correct: false, msg: 'User not found' };
return response || { correct: false, msg: messages.incorrectUsername };
};
/**

View File

@ -239,6 +239,11 @@
}
}
},
"enableMultiTasking": {
"type": "boolean",
"default": false,
"description": "If set to true, will keep apps opened in the workspace open in the background. Useful for switching between sites, but comes at the cost of performance"
},
"allowConfigEdit": {
"type": "boolean",
"default": true,
@ -263,6 +268,10 @@
"type": "boolean",
"default": false,
"description": "Enable anonymous crash reports. This helps bugs be found and fixed, in order to make Dashy more stable. Reporting is off by default, and no data will EVER be collected without your explicit and active concent."
},
"sentryDsn": {
"type": "string",
"description": "The DSN to your self-hosted Sentry server, if you need to collect bug reports. Only used if enableErrorReporting is enabled"
}
},
"additionalProperties": false

View File

@ -10,6 +10,7 @@
/* eslint-disable global-require */
import ConfigAccumulator from '@/utils/ConfigAccumalator';
import { sentryDsn } from '@/utils/defaults';
const ErrorTracking = (Vue, router) => {
// Fetch users config
@ -19,7 +20,8 @@ const ErrorTracking = (Vue, router) => {
// Import Sentry
const Sentry = require('@sentry/vue');
const { Integrations } = require('@sentry/tracing');
const dsn = 'https://3138ea85f15a4fa883a5b27a4dc8ee28@o937511.ingest.sentry.io/5887934';
// Get the Data Source Name for your or Dashy's Sentry instance
const dsn = appConfig.sentryDsn || sentryDsn;
// Initialize Sentry
Sentry.init({
Vue,

View File

@ -126,6 +126,15 @@ module.exports = {
allesedv: 'https://f1.allesedv.com/128/$URL',
webmasterapi: 'https://api.webmasterapi.com/v1/favicon/yEwx0ZFs0CSPshHq/$URL',
},
/* The URL to CDNs used for external icons. These are only loaded when required */
iconCdns: {
fa: 'https://kit.fontawesome.com',
mdi: 'https://cdn.jsdelivr.net/npm/@mdi/font@5.9.55/css/materialdesignicons.min.css',
si: 'https://unpkg.com/simple-icons@v5/icons',
generative: 'https://ipsicon.io',
localPath: '/item-icons',
faviconName: 'favicon.ico',
},
/* Available built-in colors for the theme builder */
swatches: [
['#eb5cad', '#985ceb', '#5346f3', '#5c90eb'],
@ -136,4 +145,6 @@ module.exports = {
['#f5f5f5', '#d9d9d9', '#bfbfbf', '#9a9a9a'],
['#636363', '#363636', '#313941', '#0d0d0d'],
],
/* Use your own self-hosted Sentry instance. Only used if error reporting is turned on */
sentryDsn: 'https://3138ea85f15a4fa883a5b27a4dc8ee28@o937511.ingest.sentry.io/5887934',
};

View File

@ -2,6 +2,7 @@
import en from '@/assets/locales/en.json';
import de from '@/assets/locales/de.json';
import nl from '@/assets/locales/nl.json';
import fr from '@/assets/locales/fr.json';
// Language data - Add your country name, locale code and imported file here
export const languages = [
@ -23,6 +24,12 @@ export const languages = [
locale: nl,
flag: '🇳🇱',
},
{
name: 'French',
code: 'fr',
locale: fr,
flag: '🇲🇫',
},
// Including:
// name - Human readable name for your language (e.g German)
// code - ISO language code (e.g. de)

View File

@ -43,7 +43,7 @@
import SettingsContainer from '@/components/Settings/SettingsContainer.vue';
import ItemGroup from '@/components/LinkItems/ItemGroup.vue';
import Defaults, { localStorageKeys } from '@/utils/defaults';
import Defaults, { localStorageKeys, iconCdns } from '@/utils/defaults';
export default {
name: 'home',
@ -160,16 +160,21 @@ export default {
availibleThemes.Default = '#';
return availibleThemes;
},
/* Checks if any of the icons are Font Awesome glyphs */
checkIfFontAwesomeNeeded() {
/* Checks if any sections or items use icons from a given CDN */
checkIfIconLibraryNeeded(prefix) {
let isNeeded = false;
if (!this.sections) return false;
this.sections.forEach((section) => {
if (section.icon && section.icon.includes('fa-')) isNeeded = true;
if (section.icon && section.icon.includes(prefix)) isNeeded = true;
section.items.forEach((item) => {
if (item.icon && item.icon.includes('fa-')) isNeeded = true;
if (item.icon && item.icon.includes(prefix)) isNeeded = true;
});
});
return isNeeded;
},
/* Checks if any of the icons are Font Awesome glyphs */
checkIfFontAwesomeNeeded() {
let isNeeded = this.checkIfIconLibraryNeeded('fa-');
const currentTheme = localStorage[localStorageKeys.THEME]; // Some themes require FA
if (['material', 'material-dark'].includes(currentTheme)) isNeeded = true;
return isNeeded;
@ -179,10 +184,23 @@ export default {
if (this.appConfig.enableFontAwesome || this.checkIfFontAwesomeNeeded()) {
const fontAwesomeScript = document.createElement('script');
const faKey = this.appConfig.fontAwesomeKey || Defaults.fontAwesomeKey;
fontAwesomeScript.setAttribute('src', `https://kit.fontawesome.com/${faKey}.js`);
fontAwesomeScript.setAttribute('src', `${iconCdns.fa}/${faKey}.js`);
document.head.appendChild(fontAwesomeScript);
}
},
/* Checks if any of the icons are Material Design Icons */
checkIfMdiNeeded() {
return this.checkIfIconLibraryNeeded('mdi-');
},
/* Injects Material Design Icons, only if needed */
initiateMaterialDesignIcons() {
if (this.checkIfMdiNeeded()) {
const mdiStylesheet = document.createElement('link');
mdiStylesheet.setAttribute('rel', 'stylesheet');
mdiStylesheet.setAttribute('href', iconCdns.mdi);
document.head.appendChild(mdiStylesheet);
}
},
/* Returns true if there is more than 1 sub-result visible during searching */
checkIfResults() {
if (!this.sections) return false;
@ -204,6 +222,7 @@ export default {
},
mounted() {
this.initiateFontAwesome();
this.initiateMaterialDesignIcons();
this.layout = this.layoutOrientation;
this.itemSizeBound = this.iconSize;
},
@ -218,7 +237,7 @@ export default {
padding-bottom: 1px;
background: var(--background);
// min-height: calc(100vh - 126px);
min-height: calc(100vh - var(--footer-height));
min-height: calc(99.9vh - var(--footer-height));
}
/* Outside container wrapping the item groups*/

View File

@ -40,6 +40,10 @@ import { checkCredentials, login } from '@/utils/Auth';
export default {
name: 'login',
components: {
Button,
Input,
},
props: {
appConfig: Object,
},
@ -50,23 +54,41 @@ export default {
message: '',
status: 'waiting', // wating, error, success
timeout: { label: this.$t('login.remember-me-never'), time: 0 },
dropDownMenu: [ // Data for timeout dropdown menu, translated label + value in ms
};
},
computed: {
/* Data for timeout dropdown menu, translated label + value in ms */
dropDownMenu() {
return [
{ label: this.$t('login.remember-me-never'), time: 0 },
{ label: this.$t('login.remember-me-hour'), time: 14400 * 1000 },
{ label: this.$t('login.remember-me-day'), time: 86400 * 1000 },
{ label: this.$t('login.remember-me-week'), time: 604800 * 1000 },
],
};
},
components: {
Button,
Input,
];
},
/* Translations for login response messages */
responseMessages() {
return {
missingUsername: this.$t('login.error-missing-username'),
missingPassword: this.$t('login.error-missing-password'),
incorrectUsername: this.$t('login.error-incorrect-username'),
incorrectPassword: this.$t('login.error-incorrect-password'),
successMsg: this.$t('login.success-message'),
};
},
},
methods: {
/* Checks form is filled in, then initiates the login, and redirects to /home */
submitLogin() {
// Use selected timeout, if available,else revedrt to zero
const timeout = this.timeout ? this.timeout.time : 0;
const response = checkCredentials(this.username, this.password, this.appConfig.auth || []);
// Check users credentials
const response = checkCredentials(
this.username,
this.password,
this.appConfig.auth || [], // All users
this.responseMessages, // Translated response messages
);
this.message = response.msg; // Show error or success message to the user
this.status = response.correct ? 'success' : 'error';
if (response.correct) { // Yay, credentials were correct :)
@ -76,7 +98,7 @@ export default {
}, 250);
}
},
/* Since we don't have the Theme setter at this point, we must manually set users theme */
/* Since Theme setter isn't loaded at this point, we must manually get and apply users theme */
setTheme() {
const theme = localStorage[localStorageKeys.THEME] || Defaults.theme;
document.getElementsByTagName('html')[0].setAttribute('data-theme', theme);

View File

@ -1,7 +1,8 @@
<template>
<div class="work-space">
<SideBar :sections="sections" @launch-app="launchApp" />
<WebContent :url="url" />
<WebContent :url="url" v-if="!isMultiTaskingEnabled" />
<MultiTaskingWebComtent :url="url" v-else />
</div>
</template>
@ -9,6 +10,7 @@
import SideBar from '@/components/Workspace/SideBar';
import WebContent from '@/components/Workspace/WebContent';
import MultiTaskingWebComtent from '@/components/Workspace/MultiTaskingWebComtent';
import Defaults from '@/utils/defaults';
import { GetTheme, ApplyLocalTheme, ApplyCustomVariables } from '@/utils/ThemeHelper';
@ -24,9 +26,15 @@ export default {
ApplyLocalTheme,
ApplyCustomVariables,
}),
computed: {
isMultiTaskingEnabled() {
return this.appConfig.enableMultiTasking || false;
},
},
components: {
SideBar,
WebContent,
MultiTaskingWebComtent,
},
methods: {
launchApp(url) {

View File

@ -5055,11 +5055,6 @@ highlight.js@^10.7.1:
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.7.3.tgz#697272e3991356e40c3cac566a74eef681756531"
integrity sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==
highlight.js@^11.0.0:
version "11.1.0"
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-11.1.0.tgz#0198f7326e64ddfbea5f76b00e84ab542cf24ae8"
integrity sha512-X9VVhYKHQPPuwffO8jk4bP/FVj+ibNCy3HxZZNDXFtJrq4O5FdcdCDRIkDis5MiMnjh7UwEdHgRZJcHFYdzDdA==
hmac-drbg@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1"