Merge branch 'master' into update-simple-icons
@ -21,4 +21,4 @@ indent_size = 2
|
|||||||
[*.md]
|
[*.md]
|
||||||
trim_trailing_whitespace = false
|
trim_trailing_whitespace = false
|
||||||
|
|
||||||
# Licensed under MIT, (C) 2021 Alicia Sykes <https://aliciasykes.com>
|
# Licensed under MIT, (C) 2024 Alicia Sykes <https://aliciasykes.com>
|
32
.env
@ -24,9 +24,35 @@
|
|||||||
# Defaults to true
|
# Defaults to true
|
||||||
# REDIRECT_HTTPS=true
|
# REDIRECT_HTTPS=true
|
||||||
|
|
||||||
|
# The path to the user data directory
|
||||||
|
# USER_DATA_DIR=user-data
|
||||||
|
|
||||||
|
# Enable HTTP basic auth to protect your *.yml config files
|
||||||
|
# ENABLE_HTTP_AUTH=true
|
||||||
|
|
||||||
|
# Enable basic HTTP auth to protect your *.yml config files
|
||||||
|
# BASIC_AUTH_USERNAME
|
||||||
|
# BASIC_AUTH_PASSWORD
|
||||||
|
|
||||||
|
# If you'd like frontend to automatically authenticate when basic auth enabled, set credentials here too
|
||||||
|
# VUE_APP_BASIC_AUTH_USERNAME
|
||||||
|
# VUE_APP_BASIC_AUTH_PASSWORD
|
||||||
|
|
||||||
|
# Override where the path to the configuration file is, can be a remote URL
|
||||||
|
# VUE_APP_CONFIG_PATH=/conf.yml
|
||||||
|
|
||||||
# Usually the same as BASE_URL, but accessible in frontend
|
# Usually the same as BASE_URL, but accessible in frontend
|
||||||
# VUE_APP_DOMAIN=https://dashy.to
|
# VUE_APP_DOMAIN=https://dashy.to
|
||||||
|
|
||||||
|
# Override the page title for the frontend app
|
||||||
|
# VUE_APP_TITLE=''
|
||||||
|
|
||||||
|
# Set the default view to load on startup (can be `minimal`, `workspace` or `home`)
|
||||||
|
# VUE_APP_STARTING_VIEW=home
|
||||||
|
|
||||||
|
# Set the Vue app routing mode (can be 'hash', 'history' or 'abstract')
|
||||||
|
# VUE_APP_ROUTING_MODE=history
|
||||||
|
|
||||||
# Should enable SRI for build script and link resources
|
# Should enable SRI for build script and link resources
|
||||||
# INTEGRITY=true
|
# INTEGRITY=true
|
||||||
|
|
||||||
@ -37,4 +63,8 @@
|
|||||||
# VUE_APP_VERSION=2.0.0
|
# VUE_APP_VERSION=2.0.0
|
||||||
|
|
||||||
# Directory for conf.yml backups
|
# Directory for conf.yml backups
|
||||||
# BACKUP_DIR=./public/
|
# BACKUP_DIR=./user-data/config-backups
|
||||||
|
|
||||||
|
# Setup any other user defined vars by prepending VUE_APP_ to the var name
|
||||||
|
# VUE_APP_pihole_ip=http://your.pihole.ip
|
||||||
|
# VUE_APP_pihole_key=your_pihole_secret_key
|
||||||
|
31
.github/AUTHORS.txt
vendored
@ -2,6 +2,7 @@
|
|||||||
5idereal <nelson22768384@gmail.com> - 1 commits
|
5idereal <nelson22768384@gmail.com> - 1 commits
|
||||||
Alberto <3170731+albcp@users.noreply.github.com> - 1 commits
|
Alberto <3170731+albcp@users.noreply.github.com> - 1 commits
|
||||||
Alicia <liss-bot@d0h.co> - 1 commits
|
Alicia <liss-bot@d0h.co> - 1 commits
|
||||||
|
Aly Mohamed <alydemah@gmail.com> - 1 commits
|
||||||
Artyom <32810520+AaronPorts@users.noreply.github.com> - 1 commits
|
Artyom <32810520+AaronPorts@users.noreply.github.com> - 1 commits
|
||||||
BRAVO68WEB <jbandyopadhayaya@gmail.com> - 1 commits
|
BRAVO68WEB <jbandyopadhayaya@gmail.com> - 1 commits
|
||||||
Begin <support@begin.com> - 1 commits
|
Begin <support@begin.com> - 1 commits
|
||||||
@ -9,6 +10,8 @@ Bhasher <github.it@bhasher.com> - 1 commits
|
|||||||
Bjorn Lammers <walkxnl@gmail.com> - 1 commits
|
Bjorn Lammers <walkxnl@gmail.com> - 1 commits
|
||||||
Bumsoo Kim <bskim45@gmail.com> - 1 commits
|
Bumsoo Kim <bskim45@gmail.com> - 1 commits
|
||||||
BySempron <barquin_rkz@hotmail.com> - 1 commits
|
BySempron <barquin_rkz@hotmail.com> - 1 commits
|
||||||
|
Celestial.y <celestial.y@outlook.com> - 1 commits
|
||||||
|
CrazyWolf13 <CrazyWolf13@users.noreply.github.com> - 1 commits
|
||||||
David <skaarj1989@gmail.com> - 1 commits
|
David <skaarj1989@gmail.com> - 1 commits
|
||||||
Dawid Pietrykowski <d.pietrykowski16@gmail.com> - 1 commits
|
Dawid Pietrykowski <d.pietrykowski16@gmail.com> - 1 commits
|
||||||
DeepSource Bot <bot@deepsource.io> - 1 commits
|
DeepSource Bot <bot@deepsource.io> - 1 commits
|
||||||
@ -23,6 +26,7 @@ FedelloKirfed <fedellokirfed@proton.me> - 1 commits
|
|||||||
FormatToday <616099456@qq.com> - 1 commits
|
FormatToday <616099456@qq.com> - 1 commits
|
||||||
Garrett Brown <gdbrown09@gmail.com> - 1 commits
|
Garrett Brown <gdbrown09@gmail.com> - 1 commits
|
||||||
Harald Töpfer <62364169+hubortje@users.noreply.github.com> - 1 commits
|
Harald Töpfer <62364169+hubortje@users.noreply.github.com> - 1 commits
|
||||||
|
Hendrik Strydom <56320839+FraglyG@users.noreply.github.com> - 1 commits
|
||||||
Ian Neal <wopr@wopr.tech> - 1 commits
|
Ian Neal <wopr@wopr.tech> - 1 commits
|
||||||
Iaroslav Dronskii <iaroslav@dronskii.ru> - 1 commits
|
Iaroslav Dronskii <iaroslav@dronskii.ru> - 1 commits
|
||||||
Ishan Jain <ishan@jain.se> - 1 commits
|
Ishan Jain <ishan@jain.se> - 1 commits
|
||||||
@ -68,9 +72,9 @@ icy-comet <50461557+icy-comet@users.noreply.github.com> - 1 commits
|
|||||||
imlonghao <github@esd.cc> - 1 commits
|
imlonghao <github@esd.cc> - 1 commits
|
||||||
jnach <33467747+jnach@users.noreply.github.com> - 1 commits
|
jnach <33467747+jnach@users.noreply.github.com> - 1 commits
|
||||||
jrobles98 <jose98_21@hotmail.com> - 1 commits
|
jrobles98 <jose98_21@hotmail.com> - 1 commits
|
||||||
kt-alt <kiettrang@hotmail.com> - 1 commits
|
|
||||||
kxenox <floriandel@msn.com> - 1 commits
|
kxenox <floriandel@msn.com> - 1 commits
|
||||||
laker j.v <la@laker.gay> - 1 commits
|
laker j.v <la@laker.gay> - 1 commits
|
||||||
|
markxoe <mark@oude-elberink.de> - 1 commits
|
||||||
pablomalo <paul.gouin50@gmail.com> - 1 commits
|
pablomalo <paul.gouin50@gmail.com> - 1 commits
|
||||||
poisonadder7 <github.com@loginz.uk> - 1 commits
|
poisonadder7 <github.com@loginz.uk> - 1 commits
|
||||||
rtm516 <ryantmilner@hotmail.co.uk> - 1 commits
|
rtm516 <ryantmilner@hotmail.co.uk> - 1 commits
|
||||||
@ -81,6 +85,7 @@ sur1v <gsuriv@gmail.com> - 1 commits
|
|||||||
tazboyz16 <tazboyz_16@yahoo.com> - 1 commits
|
tazboyz16 <tazboyz_16@yahoo.com> - 1 commits
|
||||||
zcq100 <zcq100@gmail.com> - 1 commits
|
zcq100 <zcq100@gmail.com> - 1 commits
|
||||||
Ángel Fernández Sánchez <angelfx19@gmail.com> - 1 commits
|
Ángel Fernández Sánchez <angelfx19@gmail.com> - 1 commits
|
||||||
|
Al Saleh <alayham@alayham.com> - 2 commits
|
||||||
Alejandro Pinar Ruiz <37040888+pinarruiz@users.noreply.github.com> - 2 commits
|
Alejandro Pinar Ruiz <37040888+pinarruiz@users.noreply.github.com> - 2 commits
|
||||||
Alessandro Del Prete <alessandro.delprete@gmail.com> - 2 commits
|
Alessandro Del Prete <alessandro.delprete@gmail.com> - 2 commits
|
||||||
Alexander Mnich <56564725+a-mnich@users.noreply.github.com> - 2 commits
|
Alexander Mnich <56564725+a-mnich@users.noreply.github.com> - 2 commits
|
||||||
@ -89,18 +94,22 @@ Brendan O'Leary <boleary@gitlab.com> - 2 commits
|
|||||||
CHAIYEON CHO <stoutcho21@gmail.com> - 2 commits
|
CHAIYEON CHO <stoutcho21@gmail.com> - 2 commits
|
||||||
Dan Gilbert <ddg@daentech.co.uk> - 2 commits
|
Dan Gilbert <ddg@daentech.co.uk> - 2 commits
|
||||||
Denis Savosin <dsavosin@at-consulting.ru> - 2 commits
|
Denis Savosin <dsavosin@at-consulting.ru> - 2 commits
|
||||||
|
Mihai <31653632+z3r0l1nk@users.noreply.github.com> - 2 commits
|
||||||
Ruben Silva <rubensilva945@gmail.com> - 2 commits
|
Ruben Silva <rubensilva945@gmail.com> - 2 commits
|
||||||
|
Tammes Burghard <kde@kuchenmampfer.de> - 2 commits
|
||||||
Thomas Dissert <dissertthomas@gmail.com> - 2 commits
|
Thomas Dissert <dissertthomas@gmail.com> - 2 commits
|
||||||
cauterize <cauterize@programmer.net> - 2 commits
|
cauterize <cauterize@programmer.net> - 2 commits
|
||||||
hockeymikey <hockeymikey@hockeymikey.com> - 2 commits
|
hockeymikey <hockeymikey@hockeymikey.com> - 2 commits
|
||||||
itsmejoeeey <9375730+itsmejoeeey@users.noreply.github.com> - 2 commits
|
itsmejoeeey <9375730+itsmejoeeey@users.noreply.github.com> - 2 commits
|
||||||
k073l <21180271+k073l@users.noreply.github.com> - 2 commits
|
k073l <21180271+k073l@users.noreply.github.com> - 2 commits
|
||||||
|
kt-alt <kiettrang@hotmail.com> - 2 commits
|
||||||
liss-bot <87835202+liss-bot@users.noreply.github.com> - 2 commits
|
liss-bot <87835202+liss-bot@users.noreply.github.com> - 2 commits
|
||||||
mmihaly <mmihaly@gmail.com> - 2 commits
|
mmihaly <mmihaly@gmail.com> - 2 commits
|
||||||
patrickheeney <patrickheeney@gmail.com> - 2 commits
|
patrickheeney <patrickheeney@gmail.com> - 2 commits
|
||||||
rokiden <cheto@bk.ru> - 2 commits
|
rokiden <cheto@bk.ru> - 2 commits
|
||||||
root <root@dashy-dev.alayham.com> - 2 commits
|
root <root@dashy-dev.alayham.com> - 2 commits
|
||||||
rtm516 <rtm516@users.noreply.github.com> - 2 commits
|
rtm516 <rtm516@users.noreply.github.com> - 2 commits
|
||||||
|
z3r0l1nk <stroescu.mihai@gmail.com> - 2 commits
|
||||||
zcq100 <m@zcq100.com> - 2 commits
|
zcq100 <m@zcq100.com> - 2 commits
|
||||||
ᗪєνιη ᗷυнʟ <onedr0p@users.noreply.github.com> - 2 commits
|
ᗪєνιη ᗷυнʟ <onedr0p@users.noreply.github.com> - 2 commits
|
||||||
Alucarddelta <dreyer.brent@gmail.com> - 3 commits
|
Alucarddelta <dreyer.brent@gmail.com> - 3 commits
|
||||||
@ -119,7 +128,6 @@ Rémy GRANDIN <remy.gr@ndin.fr> - 4 commits
|
|||||||
Todd E Johnson <todd@toddejohnson.net> - 4 commits
|
Todd E Johnson <todd@toddejohnson.net> - 4 commits
|
||||||
Totto16 <tobiausgais@gmail.com> - 4 commits
|
Totto16 <tobiausgais@gmail.com> - 4 commits
|
||||||
Walkx <walkxnl@gmail.com> - 4 commits
|
Walkx <walkxnl@gmail.com> - 4 commits
|
||||||
dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> - 4 commits
|
|
||||||
wozboz <philip@iuno.tech> - 4 commits
|
wozboz <philip@iuno.tech> - 4 commits
|
||||||
Alberto Caravaca <3170731+albcp@users.noreply.github.com> - 5 commits
|
Alberto Caravaca <3170731+albcp@users.noreply.github.com> - 5 commits
|
||||||
Alicie <gh@d0h.co> - 5 commits
|
Alicie <gh@d0h.co> - 5 commits
|
||||||
@ -130,10 +138,15 @@ Erik Vroon <erik.vroon22@gmail.com> - 6 commits
|
|||||||
Jammo2k5 <jammo2k5@hotmail.co.uk> - 6 commits
|
Jammo2k5 <jammo2k5@hotmail.co.uk> - 6 commits
|
||||||
Leonardo Covarrubias <leos@leocov.com> - 6 commits
|
Leonardo Covarrubias <leos@leocov.com> - 6 commits
|
||||||
Magnus Sundström <kmvsundstrom@gmail.com> - 6 commits
|
Magnus Sundström <kmvsundstrom@gmail.com> - 6 commits
|
||||||
|
dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> - 6 commits
|
||||||
kristian <kristianbrasel@gmail.com> - 6 commits
|
kristian <kristianbrasel@gmail.com> - 6 commits
|
||||||
liss-bot <liss-bot@users.noreply.github.com> - 6 commits
|
liss-bot <liss-bot@users.noreply.github.com> - 6 commits
|
||||||
Josua Blejeru <josua@blejeru.com> - 8 commits
|
Josua Blejeru <josua@blejeru.com> - 8 commits
|
||||||
|
Tobias <tobias.meier109@gmail.com> - 8 commits
|
||||||
|
Jimmeh <jimmeh@gmail.com> - 9 commits
|
||||||
Kashif Sohail <kashif.ezone@gmail.com> - 9 commits
|
Kashif Sohail <kashif.ezone@gmail.com> - 9 commits
|
||||||
|
Liss-Bot <liss-bot@d0h.co> - 11 commits
|
||||||
|
Tobias <96661824+CrazyWolf13@users.noreply.github.com> - 12 commits
|
||||||
Alejandro Pinar Ruiz <alejandropinarruiz@gmail.com> - 14 commits
|
Alejandro Pinar Ruiz <alejandropinarruiz@gmail.com> - 14 commits
|
||||||
Alicia Sykes <=> - 16 commits
|
Alicia Sykes <=> - 16 commits
|
||||||
github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> - 16 commits
|
github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> - 16 commits
|
||||||
@ -141,14 +154,14 @@ snyk-bot <snyk-bot@users.noreply.github.com> - 18 commits
|
|||||||
Matthias Bilger <matthias@bilger.info> - 19 commits
|
Matthias Bilger <matthias@bilger.info> - 19 commits
|
||||||
aterox <church.kennetha@gmail.com> - 19 commits
|
aterox <church.kennetha@gmail.com> - 19 commits
|
||||||
EVOTk <45015615+EVOTk@users.noreply.github.com> - 24 commits
|
EVOTk <45015615+EVOTk@users.noreply.github.com> - 24 commits
|
||||||
|
snyk-bot <snyk-bot@snyk.io> - 24 commits
|
||||||
Marcell Fülöp <marekful@protonmail.com> - 27 commits
|
Marcell Fülöp <marekful@protonmail.com> - 27 commits
|
||||||
Alicia Sykes <alicia@futr.ai> - 28 commits
|
Alicia Sykes <alicia@futr.ai> - 28 commits
|
||||||
Lissy93 <gh@d0h.co> - 78 commits
|
Lissy93 <gh@d0h.co> - 78 commits
|
||||||
snyk-bot <snyk-bot@snyk.io> - 83 commits
|
repo-visualizer <repo-visualizer@users.noreply.github.com> - 128 commits
|
||||||
repo-visualizer <repo-visualizer@users.noreply.github.com> - 117 commits
|
Lissy93 <Lissy93@users.noreply.github.com> - 222 commits
|
||||||
Lissy93 <Lissy93@users.noreply.github.com> - 210 commits
|
Alicia Bot <87835202+liss-bot@users.noreply.github.com> - 240 commits
|
||||||
liss-bot <liss-bot@d0h.co> - 212 commits
|
liss-bot <liss-bot@d0h.co> - 244 commits
|
||||||
Alicia Bot <87835202+liss-bot@users.noreply.github.com> - 215 commits
|
Alicia Sykes <gh@d0h.co> - 439 commits
|
||||||
Alicia Sykes <alicia@omg.lol> - 352 commits
|
Alicia Sykes <alicia@omg.lol> - 471 commits
|
||||||
Alicia Sykes <gh@d0h.co> - 440 commits
|
|
||||||
Alicia Sykes <sykes.alicia@gmail.com> - 1488 commits
|
Alicia Sykes <sykes.alicia@gmail.com> - 1488 commits
|
13
.github/workflows/apply-done-label.yml
vendored
@ -1,13 +0,0 @@
|
|||||||
# When a PR is merged, any associated issues will have a Done label applied
|
|
||||||
# The label will depend on the issue type, see: ./github/close-label.yml
|
|
||||||
name: 💡 Apply Done Label
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
types: [opened, merged, closed]
|
|
||||||
jobs:
|
|
||||||
triage:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: logerfo/close-label@0.0.4
|
|
||||||
with:
|
|
||||||
repo-token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
|
15
.github/workflows/assign-reviewer.yml
vendored
@ -1,15 +0,0 @@
|
|||||||
# Automatically assigns the author as a reviewer to opened PRs and issues
|
|
||||||
name: 💡 Auto-Assign Author to PR
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
types: [opened]
|
|
||||||
issues:
|
|
||||||
types: [opened]
|
|
||||||
jobs:
|
|
||||||
assign-author:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Assign author
|
|
||||||
uses: technote-space/assign-author@v1
|
|
||||||
with:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
|
6
.github/workflows/auto-tag-pr.yml
vendored
@ -8,6 +8,8 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
tag-pre-release:
|
tag-pre-release:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
outputs:
|
outputs:
|
||||||
tag: ${{ steps.autotag.outputs.tagname }}
|
tag: ${{ steps.autotag.outputs.tagname }}
|
||||||
steps:
|
steps:
|
||||||
@ -25,12 +27,14 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: ncipollo/release-action@v1
|
- uses: ncipollo/release-action@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
|
||||||
tag: ${{ needs.tag-pre-release.outputs.tag }}
|
tag: ${{ needs.tag-pre-release.outputs.tag }}
|
||||||
bodyFile: ".github/LATEST_CHANGELOG.md"
|
bodyFile: ".github/LATEST_CHANGELOG.md"
|
||||||
mark-issue-fixed:
|
mark-issue-fixed:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
if: ${{ github.event_name == 'issues' }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: Label Fixed Issues
|
- name: Label Fixed Issues
|
||||||
|
14
.github/workflows/broadcast-message.yml
vendored
@ -1,14 +0,0 @@
|
|||||||
# Updates multiple issues with a certain tag, with a comment containing a given message
|
|
||||||
name: 🎯 Broadcast Message across Issues
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
message: { required: false }
|
|
||||||
labels: { required: false }
|
|
||||||
jobs:
|
|
||||||
broadcast:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: jenschelkopf/broadcast-action@master
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
|
25
.github/workflows/build-app.yml
vendored
@ -1,25 +0,0 @@
|
|||||||
# This action builds and deploys the master branch
|
|
||||||
name: 🏗️ Build App to Branch
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [ master ]
|
|
||||||
pull_request:
|
|
||||||
branches: [ master ]
|
|
||||||
workflow_dispatch:
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout 🛎️
|
|
||||||
uses: actions/checkout@v2.3.1
|
|
||||||
- name: Install and Build 🔧
|
|
||||||
run: |
|
|
||||||
npm install
|
|
||||||
npm run build
|
|
||||||
- name: Deploy 🚀
|
|
||||||
uses: JamesIves/github-pages-deploy-action@4.1.4
|
|
||||||
if: ${{ github.repository_owner == 'lissy93' }}
|
|
||||||
with:
|
|
||||||
branch: dev-demo
|
|
||||||
folder: dist
|
|
||||||
|
|
18
.github/workflows/build-docs-site.yml
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# Builds and published Dashy's documentation website
|
||||||
|
name: 📝 Build Docs Site
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
push:
|
||||||
|
branches: [ WEBSITE/docs-site-source ]
|
||||||
|
jobs:
|
||||||
|
deploy:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: github.ref == 'refs/heads/WEBSITE/docs-site-source'
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@master
|
||||||
|
- uses: redkubes/docusaurus-deploy-action@v1
|
||||||
|
with:
|
||||||
|
source-folder: ./
|
||||||
|
git-user: ${{ github.actor }}
|
||||||
|
git-password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
deployment-branch: gh-pages
|
13
.github/workflows/cache-artifacts.yml
vendored
@ -1,13 +0,0 @@
|
|||||||
# Caches artifacts, including NPM dependencies, to speed up build times
|
|
||||||
name: 🏗️ Caching Artifacts
|
|
||||||
on: push
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/cache@v2
|
|
||||||
with:
|
|
||||||
path: ~/.npm
|
|
||||||
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-node-
|
|
22
.github/workflows/check-duplicate-issues.yml
vendored
@ -1,22 +0,0 @@
|
|||||||
# Attempts to auto-detect weather an issue is a duplicate, and adds a comment
|
|
||||||
name: 🎯 Issue Duplicate Check
|
|
||||||
on:
|
|
||||||
issues:
|
|
||||||
types: [opened, edited]
|
|
||||||
jobs:
|
|
||||||
check-duplicate:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: wow-actions/potential-duplicates@v1
|
|
||||||
with:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
|
||||||
filter: ''
|
|
||||||
exclude: '[BUG] [QUESTION] [FEEDBACK] [SHOWCASE]'
|
|
||||||
label: '🕸️ Potential Duplicate'
|
|
||||||
state: all
|
|
||||||
threshold: 0.75
|
|
||||||
reactions: 'eyes'
|
|
||||||
comment: >
|
|
||||||
Potential duplicates: {{#issues}}
|
|
||||||
- [#{{ number }}] {{ title }} ({{ accuracy }}%)
|
|
||||||
{{/issues}}
|
|
6
.github/workflows/close-stale-issues.yml
vendored
@ -13,7 +13,7 @@ jobs:
|
|||||||
uses: actions/stale@v4
|
uses: actions/stale@v4
|
||||||
with:
|
with:
|
||||||
repo-token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
repo-token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||||||
days-before-stale: 90
|
days-before-stale: 360
|
||||||
days-before-close: 5
|
days-before-close: 5
|
||||||
operations-per-run: 30
|
operations-per-run: 30
|
||||||
remove-stale-when-updated: true
|
remove-stale-when-updated: true
|
||||||
@ -25,9 +25,9 @@ jobs:
|
|||||||
This PR is stale because it has been open 6 weeks with no activity. Either remove the stale label or comment below with a short update,
|
This PR is stale because it has been open 6 weeks with no activity. Either remove the stale label or comment below with a short update,
|
||||||
otherwise this PR will be closed in 5 days.
|
otherwise this PR will be closed in 5 days.
|
||||||
close-issue-message: >
|
close-issue-message: >
|
||||||
This issue was automatically closed because it has been stalled for over 6 weeks with no activity.
|
This issue was automatically closed because it has been stalled for over 1 year with no activity.
|
||||||
close-pr-message: >
|
close-pr-message: >
|
||||||
This pull request was automatically closed because it has been stalled for over 6 weeks with no activity.
|
This pull request was automatically closed because it has been stalled for over 1 year with no activity.
|
||||||
stale-issue-label: '⚰️ Stale'
|
stale-issue-label: '⚰️ Stale'
|
||||||
close-issue-label: '🕸️ Inactive'
|
close-issue-label: '🕸️ Inactive'
|
||||||
stale-pr-label: '⚰️ Stale'
|
stale-pr-label: '⚰️ Stale'
|
||||||
|
20
.github/workflows/code-linter.yml
vendored
@ -1,20 +0,0 @@
|
|||||||
# Lints code merged into master branch
|
|
||||||
name: 🌈 Lint Code Base
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
branches: [master]
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
name: Lint Code Base
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout Code
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
- name: Lint Code Base
|
|
||||||
uses: github/super-linter@v4
|
|
||||||
env:
|
|
||||||
VALIDATE_ALL_CODEBASE: false
|
|
||||||
DEFAULT_BRANCH: master
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
30
.github/workflows/code-spell-check.yml
vendored
@ -1,30 +0,0 @@
|
|||||||
# Finds typos in the English language within the app, submits a PR with fixes
|
|
||||||
name: 🌈 Spelling Auto-Fix
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [ master ]
|
|
||||||
pull_request:
|
|
||||||
types: [opened]
|
|
||||||
workflow_dispatch:
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
if: startsWith(github.head_ref, 'AUTO/') == false
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
- name: Spell Check
|
|
||||||
if: startsWith(github.head_ref, 'AUTO/') == false
|
|
||||||
uses: sobolevn/misspell-fixer-action@master
|
|
||||||
- name: Create PR
|
|
||||||
uses: peter-evans/create-pull-request@v3.10.1
|
|
||||||
if: startsWith(github.head_ref, 'AUTO/') == false
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
|
||||||
base: master
|
|
||||||
commit-message: ':pencil2: Auto-fix typos in text'
|
|
||||||
title: '[AUTO] Fix spelling and language'
|
|
||||||
branch: 'AUTO/spelling-corrections'
|
|
||||||
committer: 'Liss-Bot <alicia-gh-bot@mail.as93.net>'
|
|
||||||
assignees: Lissy93
|
|
||||||
reviewers: Lissy93
|
|
@ -15,4 +15,3 @@ jobs:
|
|||||||
collapsibleThreshold: '25'
|
collapsibleThreshold: '25'
|
||||||
failOnDowngrade: 'false'
|
failOnDowngrade: 'false'
|
||||||
path: 'yarn.lock'
|
path: 'yarn.lock'
|
||||||
updateComment: 'true'
|
|
||||||
|
46
.github/workflows/docker-build-publish.yml
vendored
@ -11,6 +11,15 @@ on:
|
|||||||
- 'src/**'
|
- 'src/**'
|
||||||
- 'public/**'
|
- 'public/**'
|
||||||
- 'services/**'
|
- 'services/**'
|
||||||
|
- '.github/workflows/docker-build-publish.yml'
|
||||||
|
- 'Dockerfile'
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
packages: write
|
||||||
|
|
||||||
env:
|
env:
|
||||||
DH_IMAGE: ${{ secrets.DOCKER_REPO }}
|
DH_IMAGE: ${{ secrets.DOCKER_REPO }}
|
||||||
@ -30,12 +39,6 @@ jobs:
|
|||||||
uses: tyankatsu0105/read-package-version-actions@v1
|
uses: tyankatsu0105/read-package-version-actions@v1
|
||||||
id: package-version
|
id: package-version
|
||||||
|
|
||||||
# - name: ✨ Validate Dockerfile
|
|
||||||
# uses: ghe-actions/dockerfile-validator@v1
|
|
||||||
# with:
|
|
||||||
# dockerfile: 'Dockerfile'
|
|
||||||
# lint: 'hadolint'
|
|
||||||
|
|
||||||
- name: 🗂️ Make Docker Meta
|
- name: 🗂️ Make Docker Meta
|
||||||
id: meta
|
id: meta
|
||||||
uses: docker/metadata-action@v3
|
uses: docker/metadata-action@v3
|
||||||
@ -43,7 +46,6 @@ jobs:
|
|||||||
images: |
|
images: |
|
||||||
${{ env.DH_IMAGE }}
|
${{ env.DH_IMAGE }}
|
||||||
ghcr.io/${{ env.GH_IMAGE }}
|
ghcr.io/${{ env.GH_IMAGE }}
|
||||||
# ${{ secrets.ACR_SERVER }}/${{ secrets.ACR_USERNAME }}
|
|
||||||
tags: |
|
tags: |
|
||||||
type=ref,event=tag,prefix=release-,suffix={{tag}}
|
type=ref,event=tag,prefix=release-,suffix={{tag}}
|
||||||
type=semver,pattern={{raw}},value=${{ steps.package-version.outputs.version }}
|
type=semver,pattern={{raw}},value=${{ steps.package-version.outputs.version }}
|
||||||
@ -57,9 +59,22 @@ jobs:
|
|||||||
|
|
||||||
- name: 🔧 Set up QEMU
|
- name: 🔧 Set up QEMU
|
||||||
uses: docker/setup-qemu-action@v1
|
uses: docker/setup-qemu-action@v1
|
||||||
|
with:
|
||||||
|
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
||||||
|
|
||||||
- name: 🔧 Set up Docker Buildx
|
- name: 🔧 Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v1
|
uses: docker/setup-buildx-action@v1
|
||||||
|
id: buildx
|
||||||
|
with:
|
||||||
|
driver-opts: image=moby/buildkit:v0.10.6
|
||||||
|
|
||||||
|
- name: 👀 Inspect builder
|
||||||
|
run: |
|
||||||
|
echo "Name: ${{ steps.buildx.outputs.name }}"
|
||||||
|
echo "Endpoint: ${{ steps.buildx.outputs.endpoint }}"
|
||||||
|
echo "Status: ${{ steps.buildx.outputs.status }}"
|
||||||
|
echo "Flags: ${{ steps.buildx.outputs.flags }}"
|
||||||
|
echo "Platforms: ${{ steps.buildx.outputs.platforms }}"
|
||||||
|
|
||||||
- name: 🔑 Login to DockerHub
|
- name: 🔑 Login to DockerHub
|
||||||
uses: docker/login-action@v1
|
uses: docker/login-action@v1
|
||||||
@ -74,13 +89,6 @@ jobs:
|
|||||||
username: ${{ github.repository_owner }}
|
username: ${{ github.repository_owner }}
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
# - name: 🔑 Login to Azure Container Registry
|
|
||||||
# uses: docker/login-action@v1
|
|
||||||
# with:
|
|
||||||
# registry: ${{ secrets.ACR_SERVER }}
|
|
||||||
# username: ${{ secrets.ACR_USERNAME }}
|
|
||||||
# password: ${{ secrets.ACR_PASSWORD }}
|
|
||||||
|
|
||||||
- name: 🚦 Check Registry Status
|
- name: 🚦 Check Registry Status
|
||||||
uses: crazy-max/ghaction-docker-status@v1
|
uses: crazy-max/ghaction-docker-status@v1
|
||||||
|
|
||||||
@ -93,13 +101,3 @@ jobs:
|
|||||||
tags: ${{ steps.meta.outputs.tags }}
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
labels: ${{ steps.meta.outputs.labels }}
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
push: true
|
push: true
|
||||||
|
|
||||||
# - name: 💬 Set Docker Hub Description
|
|
||||||
# uses: peter-evans/dockerhub-description@v2
|
|
||||||
# with:
|
|
||||||
# repository: lissy93/dashy
|
|
||||||
# readme-filepath: ./docker/docker-readme.md
|
|
||||||
# short-description: Dashy - A self-hosted start page for your server
|
|
||||||
# username: ${{ secrets.DOCKER_USERNAME }}
|
|
||||||
# password: ${{ secrets.DOCKER_USER_PASS }}
|
|
||||||
|
|
||||||
|
63
.github/workflows/docker-publish.yml
vendored
@ -1,63 +0,0 @@
|
|||||||
# Builds a Docker image from with latest tag when master branch is updated
|
|
||||||
# The publishes it to GitHub container registry as a package
|
|
||||||
name: 🏗️ Build + Publish Docker Image to GHCR
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
push:
|
|
||||||
branches: ['master']
|
|
||||||
tags: [v*]
|
|
||||||
env:
|
|
||||||
REGISTRY: ghcr.io
|
|
||||||
IMAGE_NAME: dashy
|
|
||||||
jobs:
|
|
||||||
build-and-push-image:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: "!contains(github.event.head_commit.message, '[ci-skip]')"
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
packages: write
|
|
||||||
steps:
|
|
||||||
# Fetch the code
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
|
|
||||||
- name: Prepare
|
|
||||||
id: prep
|
|
||||||
run: echo ::set-output name=version::${GITHUB_REF##*/}
|
|
||||||
|
|
||||||
# Use QEMU for multi-architecture builds
|
|
||||||
- name: Set up QEMU
|
|
||||||
uses: docker/setup-qemu-action@v1
|
|
||||||
with:
|
|
||||||
platforms: all
|
|
||||||
|
|
||||||
# # Use Moby BuildKit
|
|
||||||
# - name: Set up Docker Buildx
|
|
||||||
# id: buildx
|
|
||||||
# uses: docker/setup-buildx-action@v1
|
|
||||||
# with:
|
|
||||||
# install: true
|
|
||||||
# version: latest
|
|
||||||
# driver-opts: image=moby/buildkit:master
|
|
||||||
|
|
||||||
# Login into GH container registry
|
|
||||||
- name: Log in to registry
|
|
||||||
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
|
|
||||||
|
|
||||||
# Build the image from default Dockerfile
|
|
||||||
- name: Build image
|
|
||||||
run: docker build . --file docker/Dockerfile-multi-arch --tag $IMAGE_NAME --label "runnumber=${GITHUB_RUN_ID}"
|
|
||||||
|
|
||||||
# Push build image
|
|
||||||
- name: Push image
|
|
||||||
run: |
|
|
||||||
IMAGE_ID=ghcr.io/${{ github.repository_owner }}/$IMAGE_NAME
|
|
||||||
IMAGE_ID=$(echo $IMAGE_ID | tr '[A-Z]' '[a-z]')
|
|
||||||
VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,')
|
|
||||||
[[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//')
|
|
||||||
[ "$VERSION" == "master" ] && VERSION=latest
|
|
||||||
echo IMAGE_ID=$IMAGE_ID
|
|
||||||
echo VERSION=$VERSION
|
|
||||||
docker tag $IMAGE_NAME $IMAGE_ID:$VERSION
|
|
||||||
docker push $IMAGE_ID:$VERSION
|
|
||||||
|
|
33
.github/workflows/docs-link-checker.yml
vendored
@ -1,33 +0,0 @@
|
|||||||
# Checks for any broken links in the docs, and raises an issue if found
|
|
||||||
name: 🌈 Broken Link Checker
|
|
||||||
on:
|
|
||||||
repository_dispatch:
|
|
||||||
workflow_dispatch:
|
|
||||||
schedule:
|
|
||||||
- cron: '0 1 1 * *' # Run monthly
|
|
||||||
jobs:
|
|
||||||
link-checker:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
|
|
||||||
- name: Load Excludes
|
|
||||||
run: |
|
|
||||||
LYCHEE_EXCLUDE=$(sed -e :a -e 'N;s/\n/ /;ta' .github/.lycheeexclude)
|
|
||||||
echo "LYCHEE_EXCLUDE=$LYCHEE_EXCLUDE" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Check for Broken Links
|
|
||||||
uses: lycheeverse/lychee-action@v1.0.8
|
|
||||||
with:
|
|
||||||
args: --verbose -a 200,302,304,429 --exclude ${{ env.LYCHEE_EXCLUDE }} --exclude-mail --no-progress **/*.md
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{secrets.BOT_GITHUB_TOKEN}}
|
|
||||||
LYCHEE_OUT: .github/broken-link-report.md
|
|
||||||
|
|
||||||
- name: Raise an Issue with Results
|
|
||||||
uses: peter-evans/create-issue-from-file@v3
|
|
||||||
with:
|
|
||||||
token: ${{secrets.BOT_GITHUB_TOKEN}}
|
|
||||||
title: '[DOCS] Broken Links found in Documentation'
|
|
||||||
content-filepath: .github/broken-link-report.md
|
|
||||||
labels: '📕 Docs, 👩💻 Good First Issue, 💤 Low Priority, 🤖 Auto'
|
|
43
.github/workflows/domain-expirey-check.yml
vendored
@ -1,43 +0,0 @@
|
|||||||
name: 📕 Check Docs Domain Expiry
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
schedule:
|
|
||||||
- cron: '0 1 * * 0' # At 01:00 on Sunday.
|
|
||||||
jobs:
|
|
||||||
check-domain:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
name: Check domain
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
domain:
|
|
||||||
- https://dashy.to
|
|
||||||
steps:
|
|
||||||
- name: Check domain SSL and registry expire date
|
|
||||||
id: check-domain
|
|
||||||
uses: codex-team/action-check-domain@v1
|
|
||||||
with:
|
|
||||||
url: ${{ matrix.domain }}
|
|
||||||
- name: Raise issue if domain expiring soon
|
|
||||||
if: ${{ steps.check-domain.outputs.paid-till-days-left && steps.check-domain.outputs.paid-till-days-left < 30 }}
|
|
||||||
uses: rishabhgupta/git-action-issue@v2
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
|
||||||
assignees: Lissy93
|
|
||||||
title: '[WEBSITE] Domain Expiring Soon'
|
|
||||||
body: >
|
|
||||||
**Priority Notice**
|
|
||||||
Domain, ${{ matrix.domain }} will expire in ${{ steps.check-domain.outputs.paid-till-days-left }} days.
|
|
||||||
@Lissy93 - Please take action immediately to prevent any downtime
|
|
||||||
|
|
||||||
- name: Raise issue if SSL Cert expiring soon
|
|
||||||
if: ${{ steps.check-domain.outputs.ssl-expire-days-left && steps.check-domain.outputs.ssl-expire-days-left < 14 }}
|
|
||||||
uses: rishabhgupta/git-action-issue@v2
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
|
||||||
assignees: Lissy93
|
|
||||||
title: '[WEBSITE] SSL Cert Expiring Soon'
|
|
||||||
body: >
|
|
||||||
**Priority Notice**
|
|
||||||
The SSL Certificate for ${{ matrix.domain }} will expire in ${{ steps.check-domain.outputs.ssl-expire-days-left }} days, on ${{ steps.check-domain.outputs.ssl-expire-date }}.
|
|
||||||
@Lissy93 - Please take action immediately to prevent any downtime
|
|
||||||
|
|
15
.github/workflows/generate-credits.yml
vendored
@ -66,18 +66,3 @@ jobs:
|
|||||||
committer_username: liss-bot
|
committer_username: liss-bot
|
||||||
committer_email: liss-bot@d0h.co
|
committer_email: liss-bot@d0h.co
|
||||||
|
|
||||||
make-author-list:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout 🛎️
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
- uses: wow-actions/update-authors@v1.1.4
|
|
||||||
with:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
|
||||||
sort: commits
|
|
||||||
bots: true
|
|
||||||
path: .github/AUTHORS.txt
|
|
||||||
commit: ':blue_heart: Makes author list'
|
|
||||||
template: '{{name}} <{{email}}> - {{commits}} commits'
|
|
||||||
|
18
.github/workflows/issue-translator.yml
vendored
@ -1,18 +0,0 @@
|
|||||||
# Will translate any issues opened in foraign language, and add the English translation as a comment
|
|
||||||
name: 🎯 Issue Translator
|
|
||||||
on:
|
|
||||||
issue_comment:
|
|
||||||
types: [created]
|
|
||||||
issues:
|
|
||||||
types: [opened]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: tomsun28/issues-translate-action@v2.5
|
|
||||||
with:
|
|
||||||
BOT_GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
|
||||||
BOT_LOGIN_NAME: liss-bot
|
|
||||||
IS_MODIFY_TITLE: true
|
|
||||||
CUSTOM_BOT_NOTE: It looks like this issue isn't in English - not a problem, here's the translation! 🇬🇧
|
|
16
.github/workflows/label-sponsors.yml
vendored
@ -1,16 +0,0 @@
|
|||||||
# Adds a label to any issues raised by a sponsor of Lissy93/Dashy
|
|
||||||
# In order to allow their request can be prioritized
|
|
||||||
name: 🎯 Label sponsors
|
|
||||||
on:
|
|
||||||
issues:
|
|
||||||
types: [opened]
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
name: is-sponsor-label
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: JasonEtco/is-sponsor-label-action@v1
|
|
||||||
with:
|
|
||||||
label: Priority Request - Sponsor 💖
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
18
.github/workflows/label-top-issues.yml
vendored
@ -1,18 +0,0 @@
|
|||||||
# Applies the 'Top Issue' label to tickets with most user reactions
|
|
||||||
name: 🎯 Label Top Issues
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
schedule:
|
|
||||||
- cron: '0 1 * * *' # Run at 01:00 each day
|
|
||||||
jobs:
|
|
||||||
labelTopIssues:
|
|
||||||
name: Label Top Issues
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Label Issues
|
|
||||||
uses: adamzolyak/top-issues-action@master
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
|
||||||
TOP_NUMBER_OF_ISSUES: 10
|
|
||||||
TOP_LABEL_NAME: "👍 Top 10 Issue!"
|
|
||||||
TOP_LABEL_COLOR: FBCA04
|
|
20
.github/workflows/mind-your-language.yml
vendored
@ -1,20 +0,0 @@
|
|||||||
# Detects offensive language in comments and takes reaction
|
|
||||||
name: 🎯 Mind your language
|
|
||||||
on:
|
|
||||||
issues:
|
|
||||||
types: [opened]
|
|
||||||
issue_comment:
|
|
||||||
types: [created]
|
|
||||||
pull_request:
|
|
||||||
types: [opened]
|
|
||||||
jobs:
|
|
||||||
echo_issue_comment:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
name: profanity check
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
- name: Profanity check step
|
|
||||||
uses: tailaiw/mind-your-language-action@v1.0.3
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
|
22
.github/workflows/new-issues-check.yml
vendored
@ -1,22 +0,0 @@
|
|||||||
name: ⭐ Hello non-Stargazers
|
|
||||||
on:
|
|
||||||
issues:
|
|
||||||
types: [opened, reopened]
|
|
||||||
jobs:
|
|
||||||
check-user:
|
|
||||||
if: >
|
|
||||||
${{
|
|
||||||
! contains( github.event.issue.labels.*.name, '📌 Keep Open') &&
|
|
||||||
! contains( github.event.issue.labels.*.name, '🌈 Feedback') &&
|
|
||||||
! contains( github.event.issue.labels.*.name, '💯 Showcase') &&
|
|
||||||
github.event.comment.author_association != 'CONTRIBUTOR'
|
|
||||||
}}
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
name: Add comment to issues opened by non-stargazers
|
|
||||||
steps:
|
|
||||||
- name: comment
|
|
||||||
uses: qxip/please-star-light@v4
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
|
||||||
autoclose: false
|
|
||||||
message: "If you're enjoying Dashy, consider dropping us a ⭐<br>_<sub>🤖 I'm a bot, and this message was automated</sub>_"
|
|
13
.github/workflows/pr-commenter.yml
vendored
@ -1,13 +0,0 @@
|
|||||||
# Adds comments to PR, based on which files are modified
|
|
||||||
name: 💡 PR Commenter
|
|
||||||
on: [ pull_request_target ]
|
|
||||||
jobs:
|
|
||||||
pr-comment:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: exercism/pr-commenter-action@v1.3.0
|
|
||||||
with:
|
|
||||||
github-token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
|
||||||
config-file: .github/pr-auto-comments.yml
|
|
||||||
template-variables: |
|
|
||||||
{ "prAuthor": "${{ github.event.pull_request.user.login }}" }
|
|
12
.github/workflows/pr-labler.yml
vendored
@ -1,12 +0,0 @@
|
|||||||
# Labels pull requests based on their branch name
|
|
||||||
name: 💡 PR Branch Labeler
|
|
||||||
on: pull_request
|
|
||||||
jobs:
|
|
||||||
label-pr:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Label PR
|
|
||||||
if: github.event.action == 'opened'
|
|
||||||
uses: ffittschen/pr-branch-labeler@v1
|
|
||||||
with:
|
|
||||||
repo-token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
|
13
.github/workflows/raise-issue-from-todo.yml
vendored
@ -1,13 +0,0 @@
|
|||||||
# Finds any TO-DO notes within the code, and opens up an issue for it to be fixed
|
|
||||||
name: 🌈 Open issue for Todos
|
|
||||||
on: ["push"]
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: "ubuntu-latest"
|
|
||||||
steps:
|
|
||||||
- uses: "actions/checkout@master"
|
|
||||||
- name: "TODO to Issue"
|
|
||||||
uses: "alstr/todo-to-issue-action@v4.2"
|
|
||||||
id: "todo"
|
|
||||||
with:
|
|
||||||
TOKEN: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
|
6
.github/workflows/release-commenter.yml
vendored
@ -10,10 +10,8 @@ jobs:
|
|||||||
- uses: apexskier/github-release-commenter@v1
|
- uses: apexskier/github-release-commenter@v1
|
||||||
with:
|
with:
|
||||||
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||||||
label-template: 🛩️ Released {release_tag}, 🔨 Fixed
|
label-template: 🛩️ Released {release_tag}
|
||||||
comment-template: |
|
comment-template: |
|
||||||
**The fix for this issue has now been released in {release_name} ✨**
|
**This has now been released in {release_name} ✨**
|
||||||
|
|
||||||
If you haven't done so already, please [update your instance](https://github.com/Lissy93/dashy/blob/master/docs/management.md#updating) to `{release_tag}` or later. See {release_link} for full info.
|
If you haven't done so already, please [update your instance](https://github.com/Lissy93/dashy/blob/master/docs/management.md#updating) to `{release_tag}` or later. See {release_link} for full info.
|
||||||
|
|
||||||
Feel free to reach out if you need any more support. If you are enjoying Dashy, consider [supporting the project](https://github.com/Lissy93/dashy/blob/master/docs/contributing.md#contributing).
|
|
||||||
|
92
.github/workflows/repo-visualization.yml
vendored
@ -1,92 +0,0 @@
|
|||||||
# Generates series of diagrams and visualizations
|
|
||||||
name: 📊 Generate Repo Stats
|
|
||||||
on:
|
|
||||||
workflow_dispatch: # Manual dispatch
|
|
||||||
schedule:
|
|
||||||
- cron: '0 1 * * 0' # At 01:00 on Sunday.
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
# File structure chart
|
|
||||||
file-structure:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@master
|
|
||||||
- name: Generate File Structure Diagram
|
|
||||||
uses: githubocto/repo-visualizer@0.7.1
|
|
||||||
with:
|
|
||||||
root_path: 'src/'
|
|
||||||
output_file: docs/assets/repo-visualization.svg
|
|
||||||
excluded_paths: dist,node_modules
|
|
||||||
commit_message: ':yellow_heart: Updates repo diagram'
|
|
||||||
branch: master
|
|
||||||
|
|
||||||
# Hercules git branching stats
|
|
||||||
git-stats:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@master
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
- name: Hercules
|
|
||||||
uses: src-d/hercules@master
|
|
||||||
- uses: actions/upload-artifact@master
|
|
||||||
with:
|
|
||||||
name: hercules_charts
|
|
||||||
path: hercules_charts.tar
|
|
||||||
|
|
||||||
# Lowlighter metrics community metrics
|
|
||||||
community-stats:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@master
|
|
||||||
- name: Generate Repo Metrics
|
|
||||||
uses: lowlighter/metrics@latest
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.LISSY93_PAT }}
|
|
||||||
committer_token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
|
||||||
committer_branch: master
|
|
||||||
committer_message: ':purple_heart: Adds repo metrics'
|
|
||||||
filename: docs/assets/repo-metrics.*
|
|
||||||
template: classic
|
|
||||||
user: Lissy93
|
|
||||||
repo: dashy
|
|
||||||
delay: 5
|
|
||||||
|
|
||||||
- name: Generate License Metrics
|
|
||||||
uses: lowlighter/metrics@latest
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.LISSY93_PAT }}
|
|
||||||
committer_token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
|
||||||
committer_branch: master
|
|
||||||
committer_message: ':purple_heart: Adds license metrics'
|
|
||||||
filename: docs/assets/license-metrics.*
|
|
||||||
template: repository
|
|
||||||
user: Lissy93
|
|
||||||
repo: dashy
|
|
||||||
delay: 5
|
|
||||||
plugin_licenses: yes
|
|
||||||
plugin_licenses_setup: yarn build
|
|
||||||
plugin_licenses_ratio: yes
|
|
||||||
plugin_licenses_legal: yes
|
|
||||||
|
|
||||||
- name: Generate Contributor Metrics
|
|
||||||
uses: lowlighter/metrics@latest
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.LISSY93_PAT }}
|
|
||||||
committer_token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
|
||||||
committer_branch: master
|
|
||||||
committer_message: ':purple_heart: Adds contributor metrics'
|
|
||||||
filename: docs/assets/controbutor-metrics.*
|
|
||||||
user: Lissy93
|
|
||||||
repo: dashy
|
|
||||||
delay: 5
|
|
||||||
plugin_contributors: yes
|
|
||||||
plugin_contributors_base: ""
|
|
||||||
plugin_contributors_head: master
|
|
||||||
plugin_contributors_ignored: bot
|
|
||||||
plugin_contributors_contributions: yes
|
|
||||||
plugin_contributors_sections: contributors
|
|
||||||
|
|
15
.github/workflows/save-repo-analytics.yml
vendored
@ -1,15 +0,0 @@
|
|||||||
name: 📊 Save Repo Analytics
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
schedule:
|
|
||||||
- cron: '0 1 * * 0' # At 01:00 on Sunday.
|
|
||||||
jobs:
|
|
||||||
gen-stats:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Repo Analytics
|
|
||||||
uses: jgehrcke/github-repo-stats@HEAD
|
|
||||||
with:
|
|
||||||
repository: lissy93/dashy
|
|
||||||
databranch: DATA/repo-stats
|
|
||||||
ghtoken: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
|
19
.github/workflows/security-scanning.yml
vendored
@ -1,19 +0,0 @@
|
|||||||
# Uses Snyk to check for potential vulnerabilities, then sends results to GH security tab
|
|
||||||
name: 💡 Vulnerability Scanning
|
|
||||||
on: push
|
|
||||||
jobs:
|
|
||||||
security:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@master
|
|
||||||
- name: Run Snyk to check for vulnerabilities
|
|
||||||
uses: snyk/actions/node@master
|
|
||||||
continue-on-error: true
|
|
||||||
env:
|
|
||||||
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
|
|
||||||
with:
|
|
||||||
args: --sarif-file-output=snyk.sarif
|
|
||||||
- name: Upload result to GitHub Code Scanning
|
|
||||||
uses: github/codeql-action/upload-sarif@v1
|
|
||||||
with:
|
|
||||||
sarif_file: snyk.sarif
|
|
17
.github/workflows/unfurl-links.yml
vendored
@ -1,17 +0,0 @@
|
|||||||
# Expands any raw pasted link in comments. Useful so people know what they're clicking
|
|
||||||
name: 🎯 Unfurl Links
|
|
||||||
on:
|
|
||||||
issues:
|
|
||||||
types: [opened]
|
|
||||||
issue_comment:
|
|
||||||
types: [created]
|
|
||||||
pull_request:
|
|
||||||
types: [opened]
|
|
||||||
jobs:
|
|
||||||
run:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: wow-actions/unfurl-links@v1
|
|
||||||
with:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
|
||||||
raw: true
|
|
58
.github/workflows/update-docs-site.yml
vendored
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
name: 📝 Update Documentation
|
||||||
|
|
||||||
|
# This will run whenever the /docs directory in master branch is updated,
|
||||||
|
# or if the workflow is manually dispatched, plus a sync check on Sun at 03:30 UTC
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
schedule:
|
||||||
|
- cron: '30 3 * * 0'
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
paths:
|
||||||
|
- 'docs/**'
|
||||||
|
|
||||||
|
|
||||||
|
# Jobs to be run:
|
||||||
|
# 1. Checkout master branch
|
||||||
|
# 2. Checkout website source code branch
|
||||||
|
# 3. Install Python
|
||||||
|
# 4. Copy /docs from master to website branch
|
||||||
|
# 5. Run the script which processes documentation
|
||||||
|
# 6. Commit and push updated docs to the website source code branch
|
||||||
|
jobs:
|
||||||
|
update-docs:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout master branch 🛎️
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
path: 'master-docs'
|
||||||
|
|
||||||
|
- name: Checkout WEBSITE/docs-site-source branch 🛎️
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
ref: 'WEBSITE/docs-site-source'
|
||||||
|
path: 'website-docs'
|
||||||
|
|
||||||
|
- name: Install Python 🐍
|
||||||
|
uses: actions/setup-python@v2
|
||||||
|
with:
|
||||||
|
python-version: '3.x'
|
||||||
|
|
||||||
|
- name: Run script to update documentation 🪄
|
||||||
|
working-directory: website-docs
|
||||||
|
run: |
|
||||||
|
cp -r ../master-docs/docs ./
|
||||||
|
python ./do-markdown-magic.py
|
||||||
|
|
||||||
|
- name: Commit changes 🚀
|
||||||
|
run: |
|
||||||
|
cd website-docs
|
||||||
|
git config --local user.email "liss-bot@d0h.co"
|
||||||
|
git config --local user.name "Liss-Bot"
|
||||||
|
git add docs
|
||||||
|
git commit -m "Update documentation" || echo "No changes to commit"
|
||||||
|
git push
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
1
.yarnrc.yml
Normal file
@ -0,0 +1 @@
|
|||||||
|
nodeLinker: node-modules
|
10
Dockerfile
@ -1,4 +1,4 @@
|
|||||||
FROM node:16.13.2-alpine AS BUILD_IMAGE
|
FROM node:18.19.1-alpine AS BUILD_IMAGE
|
||||||
|
|
||||||
# Set the platform to build image for
|
# Set the platform to build image for
|
||||||
ARG TARGETPLATFORM
|
ARG TARGETPLATFORM
|
||||||
@ -16,7 +16,7 @@ WORKDIR /app
|
|||||||
|
|
||||||
# Install app dependencies
|
# Install app dependencies
|
||||||
COPY package.json yarn.lock ./
|
COPY package.json yarn.lock ./
|
||||||
RUN yarn install --frozen-lockfile --network-timeout 1000000
|
RUN yarn install --ignore-engines --immutable --no-cache --network-timeout 300000 --network-concurrency 1
|
||||||
|
|
||||||
# Copy over all project files and folders to the working directory
|
# Copy over all project files and folders to the working directory
|
||||||
COPY . ./
|
COPY . ./
|
||||||
@ -25,10 +25,10 @@ COPY . ./
|
|||||||
RUN yarn build --mode production
|
RUN yarn build --mode production
|
||||||
|
|
||||||
# Production stage
|
# Production stage
|
||||||
FROM node:16.13.2-alpine
|
FROM node:20.11.1-alpine3.19
|
||||||
|
|
||||||
# Define some ENV Vars
|
# Define some ENV Vars
|
||||||
ENV PORT=80 \
|
ENV PORT=8080 \
|
||||||
DIRECTORY=/app \
|
DIRECTORY=/app \
|
||||||
IS_DOCKER=true
|
IS_DOCKER=true
|
||||||
|
|
||||||
@ -40,8 +40,6 @@ RUN apk add --no-cache tzdata
|
|||||||
|
|
||||||
# Copy built application from build phase
|
# Copy built application from build phase
|
||||||
COPY --from=BUILD_IMAGE /app ./
|
COPY --from=BUILD_IMAGE /app ./
|
||||||
# Ensure only one version of conf.yml exists
|
|
||||||
RUN rm dist/conf.yml
|
|
||||||
|
|
||||||
# Finally, run start command to serve up the built application
|
# Finally, run start command to serve up the built application
|
||||||
CMD [ "yarn", "start" ]
|
CMD [ "yarn", "start" ]
|
||||||
|
2
LICENSE
@ -1,6 +1,6 @@
|
|||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2021-2022 Alicia Sykes <https://aliciasykes.com>
|
Copyright (c) 2021-2024 Alicia Sykes <https://aliciasykes.com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
194
README.md
@ -6,27 +6,20 @@
|
|||||||
<img width="120" src="https://i.ibb.co/yhbt6CY/dashy.png" />
|
<img width="120" src="https://i.ibb.co/yhbt6CY/dashy.png" />
|
||||||
<br/>
|
<br/>
|
||||||
<b><a href="./docs/showcase.md">User Showcase</a></b> | <b><a href="https://demo.dashy.to">Live Demo</a></b> | <b><a href="./docs/quick-start.md">Getting Started</a></b> | <b><a href="https://dashy.to/docs">Documentation</a></b> | <b><a href="https://github.com/Lissy93/dashy">GitHub</a></b>
|
<b><a href="./docs/showcase.md">User Showcase</a></b> | <b><a href="https://demo.dashy.to">Live Demo</a></b> | <b><a href="./docs/quick-start.md">Getting Started</a></b> | <b><a href="https://dashy.to/docs">Documentation</a></b> | <b><a href="https://github.com/Lissy93/dashy">GitHub</a></b>
|
||||||
<br/><br/>
|
</p>
|
||||||
<a href="https://github.com/awesome-selfhosted/awesome-selfhosted#personal-dashboards">
|
|
||||||
<img src="https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg" alt="Awesome Self-Hosted">
|
<p align="center">
|
||||||
</a>
|
<br>
|
||||||
<a href="./LICENSE">
|
<sup>Dashy is kindly sponsored by <a href="https://umbrel.com?ref=dashy">Umbrel</a> - the personal home cloud and OS for self-hosting</sup><br>
|
||||||
<img src="https://img.shields.io/badge/License-MIT-0aa8d2?logo=opensourceinitiative&logoColor=fff" alt="License MIT">
|
<a href="https://umbrel.com?ref=dashy">
|
||||||
</a>
|
<img width="400" src="https://github.com/Lissy93/dashy/blob/WEBSITE/docs-site-source/static/umbrel-banner.jpg?raw=true" />
|
||||||
<a href="./.github/CHANGELOG.md">
|
|
||||||
<img src="https://img.shields.io/github/package-json/v/lissy93/dashy?logo=azurepipelines&color=0aa8d2" alt="Current Version">
|
|
||||||
</a>
|
|
||||||
<a href="https://hub.docker.com/r/lissy93/dashy">
|
|
||||||
<img src="https://img.shields.io/docker/pulls/lissy93/dashy?logo=docker&color=0aa8d2&logoColor=fff" alt="Docker Pulls">
|
|
||||||
</a>
|
|
||||||
<a href="http://as93.link/dashy-build-status">
|
|
||||||
<img src="https://badgen.net/github/status/lissy93/dashy?icon=github" alt="GitHub Status">
|
|
||||||
</a>
|
|
||||||
<a href="https://snyk.io/test/github/lissy93/dashy">
|
|
||||||
<img src="https://snyk.io/test/github/lissy93/dashy/badge.svg" alt="Known Vulnerabilities">
|
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> Version [3.0.0](https://github.com/Lissy93/dashy/releases/tag/3.0.0) has been released, and requires some changes to your setup, see [#1529](https://github.com/Lissy93/dashy/discussions/1529) for details.
|
||||||
|
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary><b>Table of Contents</b></summary>
|
<summary><b>Table of Contents</b></summary>
|
||||||
<p>
|
<p>
|
||||||
@ -95,7 +88,7 @@
|
|||||||
|
|
||||||
**Screenshots**: Checkout the [Showcase](./docs/showcase.md), to see example dashboards from the community
|
**Screenshots**: Checkout the [Showcase](./docs/showcase.md), to see example dashboards from the community
|
||||||
|
|
||||||
**Spin up your own demo**: [](https://labs.play-with-docker.com/?stack=https://raw.githubusercontent.com/Lissy93/dashy/master/docker-compose.yml) or [`docker run -p 8080:80 lissy93/dashy`](./docs/quick-start.md)
|
**Spin up your own demo**: [](https://labs.play-with-docker.com/?stack=https://raw.githubusercontent.com/Lissy93/dashy/master/docker-compose.yml) or [`docker run -p 8080:8080 lissy93/dashy`](./docs/quick-start.md)
|
||||||
|
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
@ -116,15 +109,15 @@
|
|||||||
You will need [Docker](https://docs.docker.com/get-docker/) installed on your system
|
You will need [Docker](https://docs.docker.com/get-docker/) installed on your system
|
||||||
|
|
||||||
```
|
```
|
||||||
docker run -p 8080:80 lissy93/dashy
|
docker run -p 8080:8080 lissy93/dashy
|
||||||
```
|
```
|
||||||
|
|
||||||
Or
|
Or
|
||||||
|
|
||||||
```docker
|
```docker
|
||||||
docker run -d \
|
docker run -d \
|
||||||
-p 4000:80 \
|
-p 4000:8080 \
|
||||||
-v /root/my-local-conf.yml:/app/public/conf.yml \
|
-v /root/my-local-conf.yml:/app/user-data/conf.yml \
|
||||||
--name my-dashboard \
|
--name my-dashboard \
|
||||||
--restart=always \
|
--restart=always \
|
||||||
lissy93/dashy:latest
|
lissy93/dashy:latest
|
||||||
@ -140,7 +133,7 @@ See also: [examples with Docker Compose](./docs/deployment.md#using-docker-compo
|
|||||||
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.
|
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.
|
||||||
|
|
||||||
- Clone the Repo: `git clone https://github.com/Lissy93/dashy.git` and `cd dashy`
|
- Clone the Repo: `git clone https://github.com/Lissy93/dashy.git` and `cd dashy`
|
||||||
- Configuration: Fill in your settings in `./public/conf.yml`
|
- Configuration: Fill in your settings in `./user-data/conf.yml`
|
||||||
- Install dependencies: `yarn`
|
- Install dependencies: `yarn`
|
||||||
- Build: `yarn build`
|
- Build: `yarn build`
|
||||||
- Run: `yarn start`
|
- Run: `yarn start`
|
||||||
@ -154,6 +147,7 @@ Dashy supports **1-Click deployments** on several popular cloud platforms. To sp
|
|||||||
- [<img src="https://i.ibb.co/d2P1WZ7/heroku.png" width="18"/> Deploy to Heroku](https://heroku.com/deploy?template=https://github.com/Lissy93/dashy)
|
- [<img src="https://i.ibb.co/d2P1WZ7/heroku.png" width="18"/> Deploy to Heroku](https://heroku.com/deploy?template=https://github.com/Lissy93/dashy)
|
||||||
- [<img src="https://i.ibb.co/Ld2FZzb/vercel.png" width="18"/> Deploy to Vercel](https://vercel.com/new/project?template=https://github.com/lissy93/dashy)
|
- [<img src="https://i.ibb.co/Ld2FZzb/vercel.png" width="18"/> Deploy to Vercel](https://vercel.com/new/project?template=https://github.com/lissy93/dashy)
|
||||||
- [<img src="https://i.ibb.co/xCHtzgh/render.png" width="18"/> Deploy to Render](https://render.com/deploy?repo=https://github.com/lissy93/dashy/tree/deploy_render)
|
- [<img src="https://i.ibb.co/xCHtzgh/render.png" width="18"/> Deploy to Render](https://render.com/deploy?repo=https://github.com/lissy93/dashy/tree/deploy_render)
|
||||||
|
- [<img src="https://railway.app/brand/logo-light.png" width="18"/> Deploy to Railway](https://railway.app/template/MtdjAQ?referralCode=app)
|
||||||
- [<img src="https://i.ibb.co/J7MGymY/googlecloud.png" width="18"/> Deploy to GCP](https://deploy.cloud.run/?git_repo=https://github.com/lissy93/dashy.git)
|
- [<img src="https://i.ibb.co/J7MGymY/googlecloud.png" width="18"/> Deploy to GCP](https://deploy.cloud.run/?git_repo=https://github.com/lissy93/dashy.git)
|
||||||
- [<img src="https://i.ibb.co/HVWVYF7/docker.png" width="18"/> Deploy to PWD](https://labs.play-with-docker.com/?stack=https://raw.githubusercontent.com/Lissy93/dashy/master/docker-compose.yml)
|
- [<img src="https://i.ibb.co/HVWVYF7/docker.png" width="18"/> Deploy to PWD](https://labs.play-with-docker.com/?stack=https://raw.githubusercontent.com/Lissy93/dashy/master/docker-compose.yml)
|
||||||
- [<img src="https://i.ibb.co/7NxnM2P/easypanel.png" width="18"/> Deploy to Easypanel](https://easypanel.io/docs/templates/dashy)
|
- [<img src="https://i.ibb.co/7NxnM2P/easypanel.png" width="18"/> Deploy to Easypanel](https://easypanel.io/docs/templates/dashy)
|
||||||
@ -168,7 +162,7 @@ Dashy supports **1-Click deployments** on several popular cloud platforms. To sp
|
|||||||
|
|
||||||
> For full configuration documentation, see: [**Configuring**](./docs/configuring.md)
|
> For full configuration documentation, see: [**Configuring**](./docs/configuring.md)
|
||||||
|
|
||||||
Dashy is configured through a YAML file, located at `./public/conf.yml`. In addition, you can find a complete list of available options in the [Configuring Docs](./docs/configuring.md). The config can also be edited and saved directly through the UI.
|
Dashy is configured through a YAML file, located at `./user-data/conf.yml`. In addition, you can find a complete list of available options in the [Configuring Docs](./docs/configuring.md). The config can also be edited and saved directly through the UI.
|
||||||
|
|
||||||
**[⬆️ Back to Top](#dashy)**
|
**[⬆️ Back to Top](#dashy)**
|
||||||
|
|
||||||
@ -531,6 +525,13 @@ Huge thanks to the sponsors helping to support Dashy's development!
|
|||||||
<!-- readme: sponsors -start -->
|
<!-- readme: sponsors -start -->
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/undefined">
|
||||||
|
<img src="" width="80;" alt="undefined"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Undefined</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
<td align="center">
|
<td align="center">
|
||||||
<a href="https://github.com/koconder">
|
<a href="https://github.com/koconder">
|
||||||
<img src="https://avatars.githubusercontent.com/u/25068?u=582657b23622aaa3dfe68bd028a780f272f456fa&v=4" width="80;" alt="koconder"/>
|
<img src="https://avatars.githubusercontent.com/u/25068?u=582657b23622aaa3dfe68bd028a780f272f456fa&v=4" width="80;" alt="koconder"/>
|
||||||
@ -538,9 +539,16 @@ Huge thanks to the sponsors helping to support Dashy's development!
|
|||||||
<sub><b>Vincent Koc</b></sub>
|
<sub><b>Vincent Koc</b></sub>
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/Admonstrator">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/69824?u=1e226d7a36cdd661c3e4cd486fea140d045b7d57&v=4" width="80;" alt="Admonstrator"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Aaron Viehl</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
<td align="center">
|
<td align="center">
|
||||||
<a href="https://github.com/tbjers">
|
<a href="https://github.com/tbjers">
|
||||||
<img src="https://avatars.githubusercontent.com/u/1117052?u=539d96d5e581b3139c75713ce35b89a36626404c&v=4" width="80;" alt="tbjers"/>
|
<img src="https://avatars.githubusercontent.com/u/1117052?v=4" width="80;" alt="tbjers"/>
|
||||||
<br />
|
<br />
|
||||||
<sub><b>Torgny Bjers</b></sub>
|
<sub><b>Torgny Bjers</b></sub>
|
||||||
</a>
|
</a>
|
||||||
@ -554,11 +562,12 @@ Huge thanks to the sponsors helping to support Dashy's development!
|
|||||||
</td>
|
</td>
|
||||||
<td align="center">
|
<td align="center">
|
||||||
<a href="https://github.com/AnandChowdhary">
|
<a href="https://github.com/AnandChowdhary">
|
||||||
<img src="https://avatars.githubusercontent.com/u/2841780?u=2d606fd66dbb1e7a102d54b4c90f078760de6674&v=4" width="80;" alt="AnandChowdhary"/>
|
<img src="https://avatars.githubusercontent.com/u/2841780?u=747e554b3a7f12eb20b7910e1c87d817844f714f&v=4" width="80;" alt="AnandChowdhary"/>
|
||||||
<br />
|
<br />
|
||||||
<sub><b>Anand Chowdhary</b></sub>
|
<sub><b>Anand Chowdhary</b></sub>
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td></tr>
|
||||||
|
<tr>
|
||||||
<td align="center">
|
<td align="center">
|
||||||
<a href="https://github.com/shrippen">
|
<a href="https://github.com/shrippen">
|
||||||
<img src="https://avatars.githubusercontent.com/u/2873570?v=4" width="80;" alt="shrippen"/>
|
<img src="https://avatars.githubusercontent.com/u/2873570?v=4" width="80;" alt="shrippen"/>
|
||||||
@ -566,14 +575,6 @@ Huge thanks to the sponsors helping to support Dashy's development!
|
|||||||
<sub><b>Shrippen</b></sub>
|
<sub><b>Shrippen</b></sub>
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/davidpaulyoung">
|
|
||||||
<img src="https://avatars.githubusercontent.com/u/3418369?v=4" width="80;" alt="davidpaulyoung"/>
|
|
||||||
<br />
|
|
||||||
<sub><b>David Young</b></sub>
|
|
||||||
</a>
|
|
||||||
</td></tr>
|
|
||||||
<tr>
|
|
||||||
<td align="center">
|
<td align="center">
|
||||||
<a href="https://github.com/bile0026">
|
<a href="https://github.com/bile0026">
|
||||||
<img src="https://avatars.githubusercontent.com/u/5022496?u=aec96ad173c0ea9baaba93807efa8a848af6595c&v=4" width="80;" alt="bile0026"/>
|
<img src="https://avatars.githubusercontent.com/u/5022496?u=aec96ad173c0ea9baaba93807efa8a848af6595c&v=4" width="80;" alt="bile0026"/>
|
||||||
@ -590,11 +591,26 @@ Huge thanks to the sponsors helping to support Dashy's development!
|
|||||||
</td>
|
</td>
|
||||||
<td align="center">
|
<td align="center">
|
||||||
<a href="https://github.com/digitalarche">
|
<a href="https://github.com/digitalarche">
|
||||||
<img src="https://avatars.githubusercontent.com/u/6546135?u=d033c9c16e8367987aec3f9ff5922bc67dd1eedf&v=4" width="80;" alt="digitalarche"/>
|
<img src="https://avatars.githubusercontent.com/u/6546135?u=564756d7f44ab2206819eb3148f6d822673f5066&v=4" width="80;" alt="digitalarche"/>
|
||||||
<br />
|
<br />
|
||||||
<sub><b>Digital Archeology</b></sub>
|
<sub><b>Digital Archeology</b></sub>
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/InDieTasten">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/7047377?u=8d8f8017628b38bc46dcbf3620e194b01d3fb2d1&v=4" width="80;" alt="InDieTasten"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>InDieTasten</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/araguaci">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/7318668?v=4" width="80;" alt="araguaci"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Araguaci</b></sub>
|
||||||
|
</a>
|
||||||
|
</td></tr>
|
||||||
|
<tr>
|
||||||
<td align="center">
|
<td align="center">
|
||||||
<a href="https://github.com/bmcgonag">
|
<a href="https://github.com/bmcgonag">
|
||||||
<img src="https://avatars.githubusercontent.com/u/7346620?u=2a0f9284f3e12ac1cc15288c254d1ec68a5081e8&v=4" width="80;" alt="bmcgonag"/>
|
<img src="https://avatars.githubusercontent.com/u/7346620?u=2a0f9284f3e12ac1cc15288c254d1ec68a5081e8&v=4" width="80;" alt="bmcgonag"/>
|
||||||
@ -609,26 +625,83 @@ Huge thanks to the sponsors helping to support Dashy's development!
|
|||||||
<sub><b>Vlad Timofeev</b></sub>
|
<sub><b>Vlad Timofeev</b></sub>
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/helixzz">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/12218889?u=d06d0c103dfbdb99450623064f7da3c5a3675fb6&v=4" width="80;" alt="helixzz"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>HeliXZz</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/patvdv">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/12430107?u=e8911c2fb91af4d30432f76da8c40927b2830bd7&v=4" width="80;" alt="patvdv"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Patrick Van Der Veken</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/plgonzalezrx8">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/19900049?v=4" width="80;" alt="plgonzalezrx8"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Pedro Gonzalez</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/mryesiller">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/24632172?u=0d20f2d615158f87cd60a3398d3efb026c32f291&v=4" width="80;" alt="mryesiller"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Göksel Yeşiller</b></sub>
|
||||||
|
</a>
|
||||||
|
</td></tr>
|
||||||
|
<tr>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/allesauseinerhand">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/32039836?v=4" width="80;" alt="allesauseinerhand"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Allesauseinerhand</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/lamtrinhdev">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/49742151?u=c5eaca5aa6841a80605cf4f7d0e861a9e6339ef3&v=4" width="80;" alt="lamtrinhdev"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>LamTrinh.Dev</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
<td align="center">
|
<td align="center">
|
||||||
<a href="https://github.com/Bastii717">
|
<a href="https://github.com/Bastii717">
|
||||||
<img src="https://avatars.githubusercontent.com/u/53431819?u=604977bed6ad6875ada890d0d3765a4cacc2fa14&v=4" width="80;" alt="Bastii717"/>
|
<img src="https://avatars.githubusercontent.com/u/53431819?u=604977bed6ad6875ada890d0d3765a4cacc2fa14&v=4" width="80;" alt="Bastii717"/>
|
||||||
<br />
|
<br />
|
||||||
<sub><b>Bastii717</b></sub>
|
<sub><b>Bastii717</b></sub>
|
||||||
</a>
|
</a>
|
||||||
</td></tr>
|
</td>
|
||||||
<tr>
|
|
||||||
<td align="center">
|
<td align="center">
|
||||||
<a href="https://github.com/ratty222">
|
<a href="https://github.com/M2TD">
|
||||||
<img src="https://avatars.githubusercontent.com/u/92832598?u=137b65530cbd5f5af9c24cde51baa6cc77cc934b&v=4" width="80;" alt="ratty222"/>
|
<img src="https://avatars.githubusercontent.com/u/85460457?v=4" width="80;" alt="M2TD"/>
|
||||||
<br />
|
<br />
|
||||||
<sub><b>Ratty222</b></sub>
|
<sub><b>M2TD</b></sub>
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td align="center">
|
<td align="center">
|
||||||
<a href="https://github.com/CrossPatch9000">
|
<a href="https://github.com/frankdez93">
|
||||||
<img src="https://avatars.githubusercontent.com/u/150388639?u=2de7d52e66299307a2d8f863f81b5f493b068e4c&v=4" width="80;" alt="CrossPatch9000"/>
|
<img src="https://avatars.githubusercontent.com/u/87549420?v=4" width="80;" alt="frankdez93"/>
|
||||||
<br />
|
<br />
|
||||||
<sub><b>CrossPatch9000</b></sub>
|
<sub><b>Frankdez93</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/NixyJuppie">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/138570196?u=b102c222487905728b858704962d32759df29ebe&v=4" width="80;" alt="NixyJuppie"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Nixy</b></sub>
|
||||||
|
</a>
|
||||||
|
</td></tr>
|
||||||
|
<tr>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/nrvo">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/151435968?u=e1dcb307fd0efdc45cddbe9490a7b956e4da6835&v=4" width="80;" alt="nrvo"/>
|
||||||
|
<br />
|
||||||
|
<sub><b>Nrvo</b></sub>
|
||||||
</a>
|
</a>
|
||||||
</td></tr>
|
</td></tr>
|
||||||
</table>
|
</table>
|
||||||
@ -743,7 +816,7 @@ A few self-hosted web apps serve a similar purpose to Dashy. If you're looking f
|
|||||||
Dashy is Licensed under [MIT X11](https://en.wikipedia.org/wiki/MIT_License)
|
Dashy is Licensed under [MIT X11](https://en.wikipedia.org/wiki/MIT_License)
|
||||||
|
|
||||||
```
|
```
|
||||||
Copyright © 2021-2022 Alicia Sykes <https://aliciasykes.com>
|
Copyright © 2021-2024 Alicia Sykes <https://aliciasykes.com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
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
|
software and associated documentation files (the "Software"), to deal in the Software
|
||||||
@ -778,16 +851,25 @@ For more info, see TLDR Legal's [Explanation of MIT](https://tldrlegal.com/licen
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
<!-- License + Copyright -->
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<br>
|
<i>© <a href="https://aliciasykes.com">Alicia Sykes</a> 2024</i><br>
|
||||||
<a href="https://dashboard.trackgit.com/token/ks0bx7bb14lsvbwoc3ik">
|
<i>Licensed under <a href="https://gist.github.com/Lissy93/143d2ee01ccc5c052a17">MIT</a></i><br>
|
||||||
<img src="https://us-central1-trackgit-analytics.cloudfunctions.net/token/ping/ks0bx7bb14lsvbwoc3ik?style=flat-square" />
|
<a href="https://github.com/lissy93"><img src="https://i.ibb.co/4KtpYxb/octocat-clean-mini.png" /></a><br>
|
||||||
</a>
|
<sup>Thanks for visiting :)</sup>
|
||||||
<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>
|
</p>
|
||||||
|
|
||||||
|
<!-- Dinosaurs are Awesome -->
|
||||||
|
<!--
|
||||||
|
. - ~ ~ ~ - .
|
||||||
|
.. _ .-~ ~-.
|
||||||
|
//| \ `..~ `.
|
||||||
|
|| | } } / \ \
|
||||||
|
(\ \\ \~^..' | } \
|
||||||
|
\`.-~ o / } | / \
|
||||||
|
(__ | / | / `.
|
||||||
|
`- - ~ ~ -._| /_ - ~ ~ ^| /- _ `.
|
||||||
|
| / | / ~-. ~- _
|
||||||
|
|_____| |_____| ~ - . _ _~_-_
|
||||||
|
-->
|
||||||
|
|
||||||
|
@ -12,21 +12,17 @@ services:
|
|||||||
# To build from source, replace 'image: lissy93/dashy' with 'build: .'
|
# To build from source, replace 'image: lissy93/dashy' with 'build: .'
|
||||||
# build: .
|
# build: .
|
||||||
|
|
||||||
# Or, to use a Dockerfile for your archtecture, uncomment the following
|
|
||||||
# context: .
|
|
||||||
# dockerfile: ./docker/Dockerfile-arm32v7
|
|
||||||
|
|
||||||
# You can also use an image with a different tag, or pull from a different registry, e.g:
|
# You can also use an image with a different tag, or pull from a different registry, e.g:
|
||||||
# image: ghcr.io/lissy93/dashy or image: lissy93/dashy:arm64v8
|
# image: ghcr.io/lissy93/dashy or image: lissy93/dashy:3.0.0
|
||||||
|
|
||||||
# Pass in your config file below, by specifying the path on your host machine
|
# Pass in your config file below, by specifying the path on your host machine
|
||||||
# volumes:
|
# volumes:
|
||||||
# - /path/to/my-config.yml:/app/public/conf.yml
|
# - /path/to/my-config.yml:/app/user-data/conf.yml
|
||||||
# - /path/to/item-icons:/app/public/item-icons
|
# - /path/to/item-icons:/app/user-data/item-icons/
|
||||||
|
|
||||||
# Set port that web service will be served on. Keep container port as 80
|
# Set port that web service will be served on. Keep container port as 8080
|
||||||
ports:
|
ports:
|
||||||
- 4000:80
|
- 4000:8080
|
||||||
|
|
||||||
# Set any environmental variables
|
# Set any environmental variables
|
||||||
environment:
|
environment:
|
||||||
|
@ -55,7 +55,7 @@
|
|||||||
|
|
||||||
**Screenshots**: Checkout the [Showcase](https://github.com/Lissy93/dashy/blob/master/docs/showcase.md), to see example dashboards from the community
|
**Screenshots**: Checkout the [Showcase](https://github.com/Lissy93/dashy/blob/master/docs/showcase.md), to see example dashboards from the community
|
||||||
|
|
||||||
**Spin up your own demo**: [](https://labs.play-with-docker.com/?stack=https://raw.githubusercontent.com/Lissy93/dashy/master/docker-compose.yml) or [`docker run -p 8080:80 lissy93/dashy`](./docs/quick-start.md)
|
**Spin up your own demo**: [](https://labs.play-with-docker.com/?stack=https://raw.githubusercontent.com/Lissy93/dashy/master/docker-compose.yml) or [`docker run -p 8080:8080 lissy93/dashy`](./docs/quick-start.md)
|
||||||
|
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
@ -69,7 +69,7 @@
|
|||||||
|
|
||||||
## Getting Started 🛫
|
## Getting Started 🛫
|
||||||
|
|
||||||
To deploy Dashy with Docker, just run `docker run -p 8080:80 lissy93/dashy`, then open `http://localhost:8080`
|
To deploy Dashy with Docker, just run `docker run -p 8080:8080 lissy93/dashy`, then open `http://localhost:8080`
|
||||||
|
|
||||||
For full list of options and a Docker compose file, see the [Deployment Docs](https://github.com/Lissy93/dashy/blob/master/docs/deployment.md).
|
For full list of options and a Docker compose file, see the [Deployment Docs](https://github.com/Lissy93/dashy/blob/master/docs/deployment.md).
|
||||||
|
|
||||||
@ -112,7 +112,7 @@ Dashy can also be run on bare metal using Node.js, or deployed to a cloud servic
|
|||||||
Dashy is Licensed under [MIT X11](https://en.wikipedia.org/wiki/MIT_License)
|
Dashy is Licensed under [MIT X11](https://en.wikipedia.org/wiki/MIT_License)
|
||||||
|
|
||||||
```
|
```
|
||||||
Copyright © 2021 Alicia Sykes <https://aliciasykes.com>
|
Copyright © 2024 Alicia Sykes <https://aliciasykes.com>
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
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
|
software and associated documentation files (the "Software"), to deal in the Software
|
||||||
|
Before Width: | Height: | Size: 27 MiB After Width: | Height: | Size: 30 MiB |
Before Width: | Height: | Size: 94 KiB After Width: | Height: | Size: 94 KiB |
@ -6,7 +6,10 @@
|
|||||||
- [Logging In and Out](#logging-in-and-out)
|
- [Logging In and Out](#logging-in-and-out)
|
||||||
- [Guest Access](#enabling-guest-access)
|
- [Guest Access](#enabling-guest-access)
|
||||||
- [Per-User Access](#granular-access)
|
- [Per-User Access](#granular-access)
|
||||||
|
- [Using Environment Variables for Passwords](#using-environment-variables-for-passwords)
|
||||||
|
- [Adding HTTP Auth to Configuration](#adding-http-auth-to-configuration)
|
||||||
- [Security Considerations](#security)
|
- [Security Considerations](#security)
|
||||||
|
- [HTTP Auth](#http-auth)
|
||||||
- [Keycloak Auth](#keycloak)
|
- [Keycloak Auth](#keycloak)
|
||||||
- [Deploying Keycloak](#1-deploy-keycloak)
|
- [Deploying Keycloak](#1-deploy-keycloak)
|
||||||
- [Setting up Keycloak](#2-setup-keycloak-users)
|
- [Setting up Keycloak](#2-setup-keycloak-users)
|
||||||
@ -18,10 +21,21 @@
|
|||||||
- [OAuth Services](#oauth-services)
|
- [OAuth Services](#oauth-services)
|
||||||
- [Auth on Cloud Hosting Services](#static-site-hosting-providers)
|
- [Auth on Cloud Hosting Services](#static-site-hosting-providers)
|
||||||
|
|
||||||
|
|
||||||
|
> [!IMPORTANT]
|
||||||
|
> Dashy's built-in auth is not indented to protect a publicly hosted instance against unauthorized access. Instead you should use an auth provider compatible with your reverse proxy, or access Dashy via your VPN, or implement your own SSO logic.
|
||||||
|
>
|
||||||
|
> In cases where Dashy is only accessibly within your home network, and you just want to add a login page, then the built-in auth may be sufficient, but keep in mind that configuration can still be accessed.
|
||||||
|
|
||||||
## Built-In Auth
|
## Built-In Auth
|
||||||
|
|
||||||
Dashy has a basic login page included, and frontend authentication. You can enable this by adding users to the `auth` section under `appConfig` in your `conf.yml`. If this section is not specified, then no authentication will be required to access the app, and the homepage will resolve to your dashboard.
|
Dashy has a basic login page included, and frontend authentication. You can enable this by adding users to the `auth` section under `appConfig` in your `conf.yml`. If this section is not specified, then no authentication will be required to access the app, and the homepage will resolve to your dashboard.
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> Since the auth is initiated in the main app entry point (for security), a rebuild is required to apply changes to the auth configuration.
|
||||||
|
> You can trigger a rebuild through the UI, under Config --> Rebuild, or by running `yarn build` in the root directory.
|
||||||
|
|
||||||
|
|
||||||
### Setting Up Authentication
|
### Setting Up Authentication
|
||||||
|
|
||||||
The `auth` property takes an array of users. Each user needs to include a username, hash and optional user type (`admin` or `normal`). The hash property is a [SHA-256 Hash](https://en.wikipedia.org/wiki/SHA-2) of your desired password.
|
The `auth` property takes an array of users. Each user needs to include a username, hash and optional user type (`admin` or `normal`). The hash property is a [SHA-256 Hash](https://en.wikipedia.org/wiki/SHA-2) of your desired password.
|
||||||
@ -104,6 +118,27 @@ You can also prevent any user from writing changes to disk, using `preventWriteT
|
|||||||
|
|
||||||
To disable all UI config features, including View Config, set `disableConfiguration`. Alternatively you can disable UI config features for all non admin users by setting `disableConfigurationForNonAdmin` to true.
|
To disable all UI config features, including View Config, set `disableConfiguration`. Alternatively you can disable UI config features for all non admin users by setting `disableConfigurationForNonAdmin` to true.
|
||||||
|
|
||||||
|
### Using Environment Variables for Passwords
|
||||||
|
|
||||||
|
If you don't want to hash your password, you can instead leave out the `hash` attribute, and replace it with `password` which should have the value of an environmental variable name you wish to use.
|
||||||
|
|
||||||
|
Note that env var must begin with `VUE_APP_`, and you must set this variable before building the app.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
auth:
|
||||||
|
users:
|
||||||
|
- user: bob
|
||||||
|
password: VUE_APP_BOB
|
||||||
|
```
|
||||||
|
|
||||||
|
Just be sure to set `VUE_APP_BOB='my super secret password'` before build-time.
|
||||||
|
|
||||||
|
### Adding HTTP Auth to Configuration
|
||||||
|
|
||||||
|
If you'd also like to prevent direct visit access to your configuration file, you can set the `ENABLE_HTTP_AUTH` environmental variable.
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
||||||
With basic auth, all logic is happening on the client-side, which could mean a skilled user could manipulate the code to view parts of your configuration, including the hash. If the SHA-256 hash is of a common password, it may be possible to determine it, using a lookup table, in order to find the original password. Which can be used to manually generate the auth token, that can then be inserted into session storage, to become a valid logged in user. Therefore, you should always use a long, strong and unique password, and if you instance contains security-critical info and/ or is exposed directly to the internet, and alternative authentication method may be better. The purpose of the login page is merely to prevent immediate unauthorized access to your homepage.
|
With basic auth, all logic is happening on the client-side, which could mean a skilled user could manipulate the code to view parts of your configuration, including the hash. If the SHA-256 hash is of a common password, it may be possible to determine it, using a lookup table, in order to find the original password. Which can be used to manually generate the auth token, that can then be inserted into session storage, to become a valid logged in user. Therefore, you should always use a long, strong and unique password, and if you instance contains security-critical info and/ or is exposed directly to the internet, and alternative authentication method may be better. The purpose of the login page is merely to prevent immediate unauthorized access to your homepage.
|
||||||
@ -112,6 +147,16 @@ With basic auth, all logic is happening on the client-side, which could mean a s
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## HTTP Auth
|
||||||
|
|
||||||
|
If you'd like to protect all your config files from direct access, you can set the `BASIC_AUTH_USERNAME` and `BASIC_AUTH_PASSWORD` environmental variables. You'll then be prompted to enter these credentials when visiting Dashy.
|
||||||
|
|
||||||
|
Then, if you'd like your frontend to automatically log you in, without prompting you for credentials, then also specify `VUE_APP_BASIC_AUTH_USERNAME` and `VUE_APP_BASIC_AUTH_PASSWORD`. This is useful for when you're hosting Dashy on a private server, and you want to prevent unauthorized access to your config files, while still allowing the frontend to access them. Note that a rebuild is required for these changes to take effect.
|
||||||
|
|
||||||
|
**[⬆️ Back to Top](#authentication)**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Keycloak
|
## Keycloak
|
||||||
|
|
||||||
Dashy also supports using a [Keycloak](https://www.keycloak.org/) authentication server. The setup for this is a bit more involved, but it gives you greater security overall, useful for if your instance is exposed to the internet.
|
Dashy also supports using a [Keycloak](https://www.keycloak.org/) authentication server. The setup for this is a bit more involved, but it gives you greater security overall, useful for if your instance is exposed to the internet.
|
||||||
@ -257,7 +302,7 @@ In NGINX you can specify [control access](https://docs.nginx.com/nginx/admin-gui
|
|||||||
|
|
||||||
```text
|
```text
|
||||||
server {
|
server {
|
||||||
listen 80;
|
listen 8080;
|
||||||
server_name www.dashy.example.com;
|
server_name www.dashy.example.com;
|
||||||
location / {
|
location / {
|
||||||
root /path/to/dashy/;
|
root /path/to/dashy/;
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
# Cloud Backup and Restore
|
# Cloud Backup and Restore
|
||||||
|
|
||||||
|
Beyond the cloud backup/restore service, there are several other self-hosted options you can use to backup Dashy, and any other Docker container data. These are outlined in the Management docs, at: [Docker Backup Options](/docs/management.md#backing-up).
|
||||||
|
|
||||||
Dashy has a built-in feature for securely backing up your config to a hosted cloud service, and then restoring it on another instance. This feature is totally optional, and if you do not enable it, then Dashy will not make any external network requests.
|
Dashy has a built-in feature for securely backing up your config to a hosted cloud service, and then restoring it on another instance. This feature is totally optional, and if you do not enable it, then Dashy will not make any external network requests.
|
||||||
|
|
||||||
This is useful not only for backing up your configuration off-site, but it also enables Dashy to be used without having write a YAML config file, and makes it possible to use a public hosted instance, without the need to self-host.
|
This is useful not only for backing up your configuration off-site, but it also enables Dashy to be used without having write a YAML config file, and makes it possible to use a public hosted instance, without the need to self-host.
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# Configuring
|
# Configuring
|
||||||
|
|
||||||
All app configuration is specified in [`/public/conf.yml`](https://github.com/Lissy93/dashy/blob/master/public/conf.yml) which is in [YAML Format](https://yaml.org/) format. If you're using Docker, this file can be passed in as a volume. Changes can either be made directly to this file, or done [through the UI](#editing-config-through-the-ui). From the UI you can also export, backup, reset, validate and download your configuration file.
|
All app configuration is specified in [`/user-data/conf.yml`](https://github.com/Lissy93/dashy/blob/master/user-data/conf.yml) which is in [YAML Format](https://yaml.org/) format. If you're using Docker, this file can be passed in as a volume. Changes can either be made directly to this file, or done [through the UI](#editing-config-through-the-ui). From the UI you can also export, backup, reset, validate and download your configuration file.
|
||||||
|
|
||||||
## There are three ways to edit the config
|
## There are three ways to edit the config
|
||||||
|
|
||||||
@ -36,6 +36,7 @@ The following file provides a reference of all supported configuration options.
|
|||||||
- [`auth`](#appconfigauth-optional) - Built-in authentication setup
|
- [`auth`](#appconfigauth-optional) - Built-in authentication setup
|
||||||
- [`users`](#appconfigauthusers-optional) - List or users (for simple auth)
|
- [`users`](#appconfigauthusers-optional) - List or users (for simple auth)
|
||||||
- [`keycloak`](#appconfigauthkeycloak-optional) - Auth config for Keycloak
|
- [`keycloak`](#appconfigauthkeycloak-optional) - Auth config for Keycloak
|
||||||
|
- [`headerAuth`](#appconfigauthheaderauth-optional) - Auth config for HeaderAuth
|
||||||
- [**`sections`**](#section) - List of sections
|
- [**`sections`**](#section) - List of sections
|
||||||
- [`displayData`](#sectiondisplaydata-optional) - Section display settings
|
- [`displayData`](#sectiondisplaydata-optional) - Section display settings
|
||||||
- [`show/hideForKeycloakUsers`](#sectiondisplaydatahideforkeycloakusers-sectiondisplaydatashowforkeycloakusers-itemdisplaydatahideforkeycloakusers-and-itemdisplaydatashowforkeycloakusers) - Set user controls
|
- [`show/hideForKeycloakUsers`](#sectiondisplaydatahideforkeycloakusers-sectiondisplaydatashowforkeycloakusers-itemdisplaydatahideforkeycloakusers-and-itemdisplaydatashowforkeycloakusers) - Set user controls
|
||||||
@ -101,12 +102,12 @@ The following file provides a reference of all supported configuration options.
|
|||||||
**Field** | **Type** | **Required**| **Description**
|
**Field** | **Type** | **Required**| **Description**
|
||||||
--- | --- | --- | ---
|
--- | --- | --- | ---
|
||||||
**`language`** | `string` | _Optional_ | The 2 (or 4-digit) [ISO 639-1 code](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) for your language, e.g. `en` or `en-GB`. This must be a language that the app has already been [translated](https://github.com/Lissy93/dashy/tree/master/src/assets/locales) into. If your language is unavailable, Dashy will fallback to English. By default Dashy will attempt to auto-detect your language, although this may not work on some privacy browsers.
|
**`language`** | `string` | _Optional_ | The 2 (or 4-digit) [ISO 639-1 code](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) for your language, e.g. `en` or `en-GB`. This must be a language that the app has already been [translated](https://github.com/Lissy93/dashy/tree/master/src/assets/locales) into. If your language is unavailable, Dashy will fallback to English. By default Dashy will attempt to auto-detect your language, although this may not work on some privacy browsers.
|
||||||
**`startingView`** | `enum` | _Optional_ | Which page to load by default, and on the base page or domain root. You can still switch to different views from within the UI. Can be either `default`, `minimal` or `workspace`. Defaults to `default`
|
~~**`startingView`**~~ | `enum` | _Optional_ | Which page to load by default, and on the base page or domain root. You can still switch to different views from within the UI. Can be either `default`, `minimal` or `workspace`. Defaults to `default`. NOTE: This has been replaced by an environmental variable: `VUE_APP_STARTING_VIEW` in V3 onwards
|
||||||
**`defaultOpeningMethod`** | `enum` | _Optional_ | The default opening method for items, if no `target` is specified for a given item. Can be either `newtab`, `sametab`, `modal`, `workspace`, `clipboard`, `top` or `parent`. Defaults to `newtab`
|
**`defaultOpeningMethod`** | `enum` | _Optional_ | The default opening method for items, if no `target` is specified for a given item. Can be either `newtab`, `sametab`, `modal`, `workspace`, `clipboard`, `top` or `parent`. Defaults to `newtab`
|
||||||
**`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`
|
**`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`
|
**`statusCheckInterval`** | `number` | _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`
|
||||||
**`webSearch`** | `object` | _Optional_ | Configuration options for the web search feature, set your default search engine, opening method or disable web search. See [`webSearch`](#appconfigwebsearch-optional)
|
**`webSearch`** | `object` | _Optional_ | Configuration options for the web search feature, set your default search engine, opening method or disable web search. See [`webSearch`](#appconfigwebsearch-optional)
|
||||||
**`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
|
**`backgroundImg`** | `string` | _Optional_ | Path to an optional full-screen app background image. This can be either remote (http) or local (relative to /app/public/item-icons/ inside the container). Note that this will slow down initial load
|
||||||
**`enableFontAwesome`** | `boolean` | _Optional_ | If set to `true` font-awesome will be loaded, if set to `false` they will not be. if left blank font-awesome will be enabled only if required by 1 or more icons
|
**`enableFontAwesome`** | `boolean` | _Optional_ | If set to `true` font-awesome will be loaded, if set to `false` they will not be. if left blank font-awesome will be enabled only if required by 1 or more icons
|
||||||
**`enableMaterialDesignIcons`** | `boolean` | _Optional_ | If set to `true` mdi icons will be loaded, if set to `false` they will not be. Where `true` is enabled, if left blank material design icons will be enabled only if required by 1 or more icons
|
**`enableMaterialDesignIcons`** | `boolean` | _Optional_ | If set to `true` mdi icons will be loaded, if set to `false` they will not be. Where `true` is enabled, if left blank material design icons 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`)
|
**`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`)
|
||||||
@ -142,11 +143,21 @@ The following file provides a reference of all supported configuration options.
|
|||||||
|
|
||||||
## `appConfig.auth` _(optional)_
|
## `appConfig.auth` _(optional)_
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> Since the auth is initiated in the main app entry point (for security), a rebuild is required to apply changes to the auth configuration.
|
||||||
|
> You can trigger a rebuild through the UI, under Config --> Rebuild, or by running `yarn build` in the root directory.
|
||||||
|
|
||||||
|
> [!WARNING]
|
||||||
|
> Built-in auth should **not be used** for security-critical applications, or if your Dashy instance is publicly accessible.
|
||||||
|
> For these, it is recommended to use an [alternate authentication method](/docs/authentication.md#alternative-authentication-methods).
|
||||||
|
|
||||||
**Field** | **Type** | **Required**| **Description**
|
**Field** | **Type** | **Required**| **Description**
|
||||||
--- | --- | --- | ---
|
--- | --- | --- | ---
|
||||||
**`users`** | `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. See [`appConfig.auth.users`](#appconfigauthusers-optional). <br>**Note** this method of authentication is handled on the client side, so for security critical situations, it is recommended to use an [alternate authentication method](/docs/authentication.md#alternative-authentication-methods).
|
**`users`** | `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. See [`appConfig.auth.users`](#appconfigauthusers-optional). <br>**Note** this method of authentication is handled on the client side, so for security critical situations, it is recommended to use an [alternate authentication method](/docs/authentication.md#alternative-authentication-methods).
|
||||||
**`enableKeycloak`** | `boolean` | _Optional_ | If set to `true`, then authentication using Keycloak will be enabled. Note that you need to have an instance running, and have also configured `auth.keycloak`. Defaults to `false`
|
**`enableKeycloak`** | `boolean` | _Optional_ | If set to `true`, then authentication using Keycloak will be enabled. Note that you need to have an instance running, and have also configured `auth.keycloak`. Defaults to `false`
|
||||||
**`keycloak`** | `object` | _Optional_ | Config options to point Dashy to your Keycloak server. Requires `enableKeycloak: true`. See [`auth.keycloak`](#appconfigauthkeycloak-optional) for more info
|
**`keycloak`** | `object` | _Optional_ | Config options to point Dashy to your Keycloak server. Requires `enableKeycloak: true`. See [`auth.keycloak`](#appconfigauthkeycloak-optional) for more info
|
||||||
|
**`enableHeaderAuth`** | `boolean` | _Optional_ | If set to `true`, then authentication using HeaderAuth will be enabled. Note that you need to have your web server/reverse proxy running, and have also configured `auth.headerAuth`. Defaults to `false`
|
||||||
|
**`headerAuth`** | `object` | _Optional_ | Config options to point Dashy to your headers for authentication. Requires `enableHeaderAuth: true`. See [`auth.headerAuth`](#appconfigauthheaderauth-optional) for more info
|
||||||
**`enableGuestAccess`** | `boolean` | _Optional_ | When set to `true`, an unauthenticated user will be able to access the dashboard, with read-only access, without having to login. Requires `auth.users` to be configured. Defaults to `false`.
|
**`enableGuestAccess`** | `boolean` | _Optional_ | When set to `true`, an unauthenticated user will be able to access the dashboard, with read-only access, without having to login. Requires `auth.users` to be configured. Defaults to `false`.
|
||||||
|
|
||||||
For more info, see the **[Authentication Docs](/docs/authentication.md)**
|
For more info, see the **[Authentication Docs](/docs/authentication.md)**
|
||||||
@ -174,6 +185,15 @@ For more info, see the **[Authentication Docs](/docs/authentication.md)**
|
|||||||
|
|
||||||
**[⬆️ Back to Top](#configuring)**
|
**[⬆️ Back to Top](#configuring)**
|
||||||
|
|
||||||
|
## `appConfig.auth.headerAuth` _(optional)_
|
||||||
|
|
||||||
|
**Field** | **Type** | **Required**| **Description**
|
||||||
|
--- | --- | --- | ---
|
||||||
|
**`userHeader`** | `string` | _Optional_ | The Header name which contains username (default: REMOTE_USER). Case insensitive
|
||||||
|
**`proxyWhitelist`** | `array` | Required | An array of Upstream proxy servers to expect authencticated requests from
|
||||||
|
|
||||||
|
**[⬆️ Back to Top](#configuring)**
|
||||||
|
|
||||||
## `appConfig.webSearch` _(optional)_
|
## `appConfig.webSearch` _(optional)_
|
||||||
|
|
||||||
**Field** | **Type** | **Required**| **Description**
|
**Field** | **Type** | **Required**| **Description**
|
||||||
@ -228,6 +248,7 @@ For more info, see the **[Authentication Docs](/docs/authentication.md)**
|
|||||||
**`statusCheckAcceptCodes`** | `string` | _Optional_ | If your service's response code is anything other than 2xx, then you can opt to specify an alternative success code. E.g. if you expect your server to return 403, but still want the status indicator to be green, set this value to `403`
|
**`statusCheckAcceptCodes`** | `string` | _Optional_ | If your service's response code is anything other than 2xx, then you can opt to specify an alternative success code. E.g. if you expect your server to return 403, but still want the status indicator to be green, set this value to `403`
|
||||||
**`statusCheckMaxRedirects`** | `number` | _Optional_ | If your service redirects to another page, and you would like status checks to follow redirects, then specify the maximum number of redirects here. Defaults to `0` / will not follow redirects
|
**`statusCheckMaxRedirects`** | `number` | _Optional_ | If your service redirects to another page, and you would like status checks to follow redirects, then specify the maximum number of redirects here. Defaults to `0` / will not follow redirects
|
||||||
**`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
|
**`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
|
||||||
|
**`rel`** | `string` | _Optional_ | The value of the `rel` attribute for the link. Useful for specifying the relationship between the target link/document and Dashy. Defaults to `noopener noreferrer`
|
||||||
**`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
|
**`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
|
||||||
**`provider`** | `string` | _Optional_ | The name of the provider for a given service, useful for when including hosted apps. In some themes, this is visible under the item name
|
**`provider`** | `string` | _Optional_ | The name of the provider for a given service, useful for when including hosted apps. In some themes, this is visible under the item name
|
||||||
**`displayData`** | `object` | _Optional_ | Meta-data to optionally override display settings for a given item. See [`displayData`](#itemdisplaydata-optional)
|
**`displayData`** | `object` | _Optional_ | Meta-data to optionally override display settings for a given item. See [`displayData`](#itemdisplaydata-optional)
|
||||||
@ -246,7 +267,7 @@ For more info, see the **[Authentication Docs](/docs/authentication.md)**
|
|||||||
|
|
||||||
**[⬆️ Back to Top](#configuring)**
|
**[⬆️ Back to Top](#configuring)**
|
||||||
|
|
||||||
## `section.widget` _(optional)_
|
## `section.widgets` _(optional)_
|
||||||
|
|
||||||
**Field** | **Type** | **Required**| **Description**
|
**Field** | **Type** | **Required**| **Description**
|
||||||
--- | --- | --- | ---
|
--- | --- | --- | ---
|
||||||
|
@ -130,7 +130,7 @@ If you like, you could also consider [subscribing to my mailing list](https://no
|
|||||||
|
|
||||||
For a full list of Dashy's contributors, see the [Credits Page](/docs/credits.md)
|
For a full list of Dashy's contributors, see the [Credits Page](/docs/credits.md)
|
||||||
|
|
||||||
[](/docs/credits.md)
|
[](https://github.com/Lissy93/dashy/blob/master/docs/credits.md)
|
||||||
|
|
||||||
### Star-Gazers Over Time
|
### Star-Gazers Over Time
|
||||||
|
|
||||||
|
1063
docs/credits.md
@ -7,7 +7,7 @@ Welcome to Dashy, so glad you're here :) Deployment is super easy, and there are
|
|||||||
If you want to skip the fuss, and [get straight down to it](/docs/quick-start.md), then you can spin up a new instance of Dashy by running:
|
If you want to skip the fuss, and [get straight down to it](/docs/quick-start.md), then you can spin up a new instance of Dashy by running:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker run -p 8080:80 lissy93/dashy
|
docker run -p 8080:8080 lissy93/dashy
|
||||||
```
|
```
|
||||||
|
|
||||||
See [Management Docs](/docs/management.md) for info about securing, monitoring, updating, health checks, auto starting, web server configuration, etc
|
See [Management Docs](/docs/management.md) for info about securing, monitoring, updating, health checks, auto starting, web server configuration, etc
|
||||||
@ -21,6 +21,7 @@ Once you've got Dashy up and running, you'll want to configure it with your own
|
|||||||
- [Deployment Methods](#deployment-methods)
|
- [Deployment Methods](#deployment-methods)
|
||||||
- [Deploy with Docker](#deploy-with-docker)
|
- [Deploy with Docker](#deploy-with-docker)
|
||||||
- [Using Docker Compose](#using-docker-compose)
|
- [Using Docker Compose](#using-docker-compose)
|
||||||
|
- [Kubernetes](#kubernetes)
|
||||||
- [Unraid](#unraid)
|
- [Unraid](#unraid)
|
||||||
- [Synology NAS](#synology-nas)
|
- [Synology NAS](#synology-nas)
|
||||||
- [Build from Source](#build-from-source)
|
- [Build from Source](#build-from-source)
|
||||||
@ -32,6 +33,7 @@ Once you've got Dashy up and running, you'll want to configure it with your own
|
|||||||
- [Google Cloud Platform](#google-cloud-platform)
|
- [Google Cloud Platform](#google-cloud-platform)
|
||||||
- [Platform.sh](#platformsh)
|
- [Platform.sh](#platformsh)
|
||||||
- [Render](#render)
|
- [Render](#render)
|
||||||
|
- [Railway](#railway)
|
||||||
- [Scalingo](#scalingo)
|
- [Scalingo](#scalingo)
|
||||||
- [Play-with-Docker](#play-with-docker)
|
- [Play-with-Docker](#play-with-docker)
|
||||||
- [Surge.sh](#surgesh)
|
- [Surge.sh](#surgesh)
|
||||||
@ -65,8 +67,8 @@ Dashy has a built container image hosted on [Docker Hub](https://hub.docker.com/
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker run -d \
|
docker run -d \
|
||||||
-p 8080:80 \
|
-p 8080:8080 \
|
||||||
-v /root/my-local-conf.yml:/app/public/conf.yml \
|
-v /root/my-local-conf.yml:/app/user-data/conf.yml \
|
||||||
--name my-dashboard \
|
--name my-dashboard \
|
||||||
--restart=always \
|
--restart=always \
|
||||||
lissy93/dashy:latest
|
lissy93/dashy:latest
|
||||||
@ -108,9 +110,9 @@ services:
|
|||||||
container_name: Dashy
|
container_name: Dashy
|
||||||
# Pass in your config file below, by specifying the path on your host machine
|
# Pass in your config file below, by specifying the path on your host machine
|
||||||
# volumes:
|
# volumes:
|
||||||
# - /root/my-config.yml:/app/public/conf.yml
|
# - /root/my-config.yml:/app/user-data/conf.yml
|
||||||
ports:
|
ports:
|
||||||
- 4000:80
|
- 4000:8080
|
||||||
# Set any environmental variables
|
# Set any environmental variables
|
||||||
environment:
|
environment:
|
||||||
- NODE_ENV=production
|
- NODE_ENV=production
|
||||||
@ -134,6 +136,12 @@ If you are building from source, and would like to use one of the [other Dockerf
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Kubernetes
|
||||||
|
|
||||||
|
@vyrtualsynthese has written a Helm Chart for deploying with Kubernetes, available [here](https://github.com/vyrtualsynthese/selfhosted-helmcharts/tree/main/charts/dashy)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Unraid
|
## Unraid
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
@ -158,8 +166,8 @@ Installing dashy is really simply and fast:
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker run -d \
|
docker run -d \
|
||||||
-p 4000:80 \
|
-p 4000:8080 \
|
||||||
-v /volume1/docker/dashy/my-local-conf.yml:/app/public/conf.yml \
|
-v /volume1/docker/dashy/my-local-conf.yml:/app/user-data/conf.yml \
|
||||||
--name dashy \
|
--name dashy \
|
||||||
--restart=always \
|
--restart=always \
|
||||||
lissy93/dashy:latest
|
lissy93/dashy:latest
|
||||||
@ -174,7 +182,7 @@ dashy should be up within 1-2min after you've started the install task procedure
|
|||||||
If you do not want to use Docker, you can run Dashy directly on your host system. For this, you will need both [git](https://git-scm.com/downloads) and the latest or LTS version of [Node.js](https://nodejs.org/) installed, and optionally [yarn](https://yarnpkg.com/)
|
If you do not want to use Docker, you can run Dashy directly on your host system. For this, you will need both [git](https://git-scm.com/downloads) and the latest or LTS version of [Node.js](https://nodejs.org/) installed, and optionally [yarn](https://yarnpkg.com/)
|
||||||
|
|
||||||
1. Get Code: `git clone https://github.com/Lissy93/dashy.git` and `cd dashy`
|
1. Get Code: `git clone https://github.com/Lissy93/dashy.git` and `cd dashy`
|
||||||
2. Configuration: Fill in you're settings in `./public/conf.yml`
|
2. Configuration: Fill in you're settings in `./user-data/conf.yml`
|
||||||
3. Install dependencies: `yarn`
|
3. Install dependencies: `yarn`
|
||||||
4. Build: `yarn build`
|
4. Build: `yarn build`
|
||||||
5. Run: `yarn start`
|
5. Run: `yarn start`
|
||||||
@ -187,7 +195,8 @@ If you don't have a home server, then fear not - Dashy can be deployed to pretty
|
|||||||
|
|
||||||
Some hosting providers required a bit of extra configuration, which was why I've made separate branches for deploying to those services (named: [`deploy_cloudflare`](https://github.com/Lissy93/dashy/tree/deploy_cloudflare), [`deploy_digital-ocean`](https://github.com/Lissy93/dashy/tree/deploy_digital-ocean), [`deploy_platform-sh`](https://github.com/Lissy93/dashy/tree/deploy_platform-sh) and [`deploy_render`](https://github.com/Lissy93/dashy/tree/deploy_render)). If there's another cloud service which you'd like 1-click deployment to be supported for, feel free to raise an issue.
|
Some hosting providers required a bit of extra configuration, which was why I've made separate branches for deploying to those services (named: [`deploy_cloudflare`](https://github.com/Lissy93/dashy/tree/deploy_cloudflare), [`deploy_digital-ocean`](https://github.com/Lissy93/dashy/tree/deploy_digital-ocean), [`deploy_platform-sh`](https://github.com/Lissy93/dashy/tree/deploy_platform-sh) and [`deploy_render`](https://github.com/Lissy93/dashy/tree/deploy_render)). If there's another cloud service which you'd like 1-click deployment to be supported for, feel free to raise an issue.
|
||||||
|
|
||||||
**Note** If you use a static hosting provider, then status checks, writing new config changes to disk from the UI, and triggering a rebuild through the UI will not be available. This is because these features need endpoints provided by Dashy's local Node server. Everything else should work just the same though.
|
> [!NOTE]
|
||||||
|
> If you use a static hosting provider, then status checks, writing new config changes to disk from the UI, and triggering a rebuild through the UI will not be available. This is because these features need endpoints provided by Dashy's local Node server. Everything else should work just the same though.
|
||||||
|
|
||||||
### Netlify
|
### Netlify
|
||||||
|
|
||||||
@ -271,6 +280,16 @@ To deploy Dashy to Render, use the following link
|
|||||||
https://render.com/deploy?repo=https://github.com/lissy93/dashy/tree/deploy_render
|
https://render.com/deploy?repo=https://github.com/lissy93/dashy/tree/deploy_render
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Railway
|
||||||
|
|
||||||
|
[](https://railway.app/template/MtdjAQ?referralCode=app)
|
||||||
|
|
||||||
|
[Railway](https://railway.app/) is a Platform as a Service (PaaS) that offers a complete platform for building and delivering programs to the backend of the cloud. You bring your code and Railway does the rest. Railway offers an extremely good developer experience and makes it effortless to deploy apps. Railway offers a free Trial Plan, and paid plans start at $5/month. Railway has 4 server locations: US-west, US-east, EU-west and ASIA-South-East.
|
||||||
|
|
||||||
|
```text
|
||||||
|
https://railway.app/template/MtdjAQ
|
||||||
|
```
|
||||||
|
|
||||||
### Scalingo
|
### Scalingo
|
||||||
|
|
||||||
[](https://my.scalingo.com/deploy?source=https://github.com/lissy93/dashy#master)
|
[](https://my.scalingo.com/deploy?source=https://github.com/lissy93/dashy#master)
|
||||||
|
@ -51,7 +51,7 @@ Dashy should now be being served on <http://localhost:8080/>. Hot reload is enab
|
|||||||
|
|
||||||
#### Utils and Checks
|
#### Utils and Checks
|
||||||
|
|
||||||
- **`yarn validate-config`** - If you have quite a long configuration file, you may wish to check that it's all good to go, before deploying the app. This can be done with `yarn validate-config` or `docker exec -it [container-id] yarn validate-config`. Your config file needs to be in `/public/conf.yml` (or within your Docker container at `/app/public/conf.yml`). This will first check that your YAML is valid, and then validates it against Dashy's [schema](https://github.com/Lissy93/dashy/blob/master/src/utils/ConfigSchema.js).
|
- **`yarn validate-config`** - If you have quite a long configuration file, you may wish to check that it's all good to go, before deploying the app. This can be done with `yarn validate-config` or `docker exec -it [container-id] yarn validate-config`. Your config file needs to be in `/user-data/conf.yml` (or within your Docker container at `/app/user-data/conf.yml`). This will first check that your YAML is valid, and then validates it against Dashy's [schema](https://github.com/Lissy93/dashy/blob/master/src/utils/ConfigSchema.js).
|
||||||
- **`yarn health-check`** - Checks that the application is up and running on it's specified port, and outputs current status and response times. Useful for integrating into your monitoring service, if you need to maintain high system availability
|
- **`yarn health-check`** - Checks that the application is up and running on it's specified port, and outputs current status and response times. Useful for integrating into your monitoring service, if you need to maintain high system availability
|
||||||
|
|
||||||
#### Alternate Start Commands
|
#### Alternate Start Commands
|
||||||
|
@ -104,7 +104,7 @@ If you are not comfortable with making pull requests, or do not want to modify t
|
|||||||
|
|
||||||
This section is for, adding a new setting to the config file.
|
This section is for, adding a new setting to the config file.
|
||||||
|
|
||||||
All of the users config is specified in `./public/conf.yml` - see [Configuring Docs](./configuring.md) for info.
|
All of the users config is specified in `./user-data/conf.yml` - see [Configuring Docs](./configuring.md) for info.
|
||||||
It's important to first ensure that there isn't a similar option already available, the new option is definitely necessary, and most importantly that it is fully backwards compatible.
|
It's important to first ensure that there isn't a similar option already available, the new option is definitely necessary, and most importantly that it is fully backwards compatible.
|
||||||
|
|
||||||
Next choose the appropriate section to place it under
|
Next choose the appropriate section to place it under
|
||||||
|
@ -167,7 +167,7 @@ You can also set an icon by passing in a valid URL pointing to the icons locatio
|
|||||||
|
|
||||||
## Local Icons
|
## 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 `./user-data/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/user-data/item-icons/`. To reference an icon stored locally, just specify it's name and extension. For example, if my icon was stored in `/app/user-data/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 organized. You would then specify an icon with it's folder name slash image name. For example: `networking/monit.png`
|
You can also use sub-folders within the `item-icons` directory to keep things organized. You would then specify an icon with it's folder name slash image name. For example: `networking/monit.png`
|
||||||
|
|
||||||
@ -187,7 +187,7 @@ If you don't wish for a given item or section to have an icon, just leave out th
|
|||||||
|
|
||||||
## Icon Collections and Resources
|
## Icon Collections and Resources
|
||||||
|
|
||||||
The following websites provide good-quality, free icon sets. To use any of these icons, either copy the link to the raw icon (it should end in `.svg` or `.png`) and paste it as your `icon`, or download and save the icons in `/public/item-icons` / mapped Docker volume. Full credit to the authors, please see the licenses for each service for usage and copyright information.
|
The following websites provide good-quality, free icon sets. To use any of these icons, either copy the link to the raw icon (it should end in `.svg` or `.png`) and paste it as your `icon`, or download and save the icons in `/user-data/item-icons` / mapped Docker volume. Full credit to the authors, please see the licenses for each service for usage and copyright information.
|
||||||
|
|
||||||
- [Icons for Self-Hosted Apps](https://thehomelab.wiki/books/helpful-tools-resources/page/icons-for-self-hosted-dashboards) - 350+ high-quality icons for commonly self-hosted services
|
- [Icons for Self-Hosted Apps](https://thehomelab.wiki/books/helpful-tools-resources/page/icons-for-self-hosted-dashboards) - 350+ high-quality icons for commonly self-hosted services
|
||||||
- [SVG Box](https://svgbox.net/iconsets/) - Cryptocurrency, social media apps and flag icons
|
- [SVG Box](https://svgbox.net/iconsets/) - Cryptocurrency, social media apps and flag icons
|
||||||
|
@ -30,11 +30,11 @@ _The following article is a primer on managing self-hosted apps. It covers every
|
|||||||
|
|
||||||
Although not essential, you will most likely want to provide several assets to your running app.
|
Although not essential, you will most likely want to provide several assets to your running app.
|
||||||
|
|
||||||
This is easy to do using [Docker Volumes](https://docs.docker.com/storage/volumes/), which lets you share a file or directory between your host system, and the container. Volumes are specified in the Docker run command, or Docker compose file, using the `--volume` or `-v` flags. The value of which consists of the path to the file / directory on your host system, followed by the destination path within the container. Fields are separated by a colon (`:`), and must be in the correct order. For example: `-v ~/alicia/my-local-conf.yml:/app/public/conf.yml`
|
This is easy to do using [Docker Volumes](https://docs.docker.com/storage/volumes/), which lets you share a file or directory between your host system, and the container. Volumes are specified in the Docker run command, or Docker compose file, using the `--volume` or `-v` flags. The value of which consists of the path to the file / directory on your host system, followed by the destination path within the container. Fields are separated by a colon (`:`), and must be in the correct order. For example: `-v ~/alicia/my-local-conf.yml:/app/user-data/conf.yml`
|
||||||
|
|
||||||
In Dashy, commonly configured resources include:
|
In Dashy, commonly configured resources include:
|
||||||
|
|
||||||
- `./public/conf.yml` - Your main application config file
|
- `./user-data/conf.yml` - Your main application config file
|
||||||
- `./public/item-icons` - A directory containing your own icons. This allows for offline access, and better performance than fetching from a CDN
|
- `./public/item-icons` - A directory containing your own icons. This allows for offline access, and better performance than fetching from a CDN
|
||||||
- Also within `./public` you'll find standard website assets, including `favicon.ico`, `manifest.json`, `robots.txt`, etc. There's no need to pass these in, but you can do so if you wish
|
- Also within `./public` you'll find standard website assets, including `favicon.ico`, `manifest.json`, `robots.txt`, etc. There's no need to pass these in, but you can do so if you wish
|
||||||
- `/src/styles/user-defined-themes.scss` - A stylesheet for applying custom CSS to your app. You can also write your own themes here.
|
- `/src/styles/user-defined-themes.scss` - A stylesheet for applying custom CSS to your app. You can also write your own themes here.
|
||||||
@ -197,7 +197,9 @@ docker run --rm -v some_volume:/volume -v /tmp:/backup alpine sh -c "rm -rf /vol
|
|||||||
|
|
||||||
### Dashy-Specific Backup
|
### Dashy-Specific Backup
|
||||||
|
|
||||||
Since Dashy is open source, and freely available, providing you're configuration data is passed in as volumes, there shouldn't be any need to backup the main container. Your main config file, and any assets you're using should be kept backed up, preferably in at least two places, and you should ensure that you can easily restore from backup, if needed.
|
All configuration and dashboard settings are stored in your `user-data/conf.yml` file. If you provide additional assets (like icons, fonts, themes, etc), these will also live in the `user-data` directory. So to backup all Dashy data, this is the only directory you need to backup.
|
||||||
|
|
||||||
|
Since Dashy is open source, there shouldn't be any need to backup the main container.
|
||||||
|
|
||||||
Dashy also has a built-in cloud backup feature, which is free for personal users, and will let you make and restore fully encrypted backups of your config directly through the UI. To learn more, see the [Cloud Backup Docs](/docs/backup-restore.md)
|
Dashy also has a built-in cloud backup feature, which is free for personal users, and will let you make and restore fully encrypted backups of your config directly through the UI. To learn more, see the [Cloud Backup Docs](/docs/backup-restore.md)
|
||||||
|
|
||||||
@ -238,7 +240,7 @@ Once you've generated your SSL cert, you'll need to pass it to Dashy. This can b
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker run -d \
|
docker run -d \
|
||||||
-p 8080:80 \
|
-p 8080:8080 \
|
||||||
-v ~/my-private-key.key:/etc/ssl/certs/dashy-priv.key:ro \
|
-v ~/my-private-key.key:/etc/ssl/certs/dashy-priv.key:ro \
|
||||||
-v ~/my-public-key.pem:/etc/ssl/certs/dashy-pub.pem:ro \
|
-v ~/my-public-key.pem:/etc/ssl/certs/dashy-pub.pem:ro \
|
||||||
lissy93/dashy:latest
|
lissy93/dashy:latest
|
||||||
@ -276,9 +278,9 @@ services:
|
|||||||
container_name: Dashy
|
container_name: Dashy
|
||||||
image: lissy93/dashy
|
image: lissy93/dashy
|
||||||
volumes:
|
volumes:
|
||||||
- /root/my-config.yml:/app/public/conf.yml
|
- /root/my-config.yml:/app/user-data/conf.yml
|
||||||
ports:
|
ports:
|
||||||
- 4000:80
|
- 4000:8080
|
||||||
environment:
|
environment:
|
||||||
- BASE_URL=/my-dashboard
|
- BASE_URL=/my-dashboard
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@ -550,7 +552,7 @@ upstream dashy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
server {
|
server {
|
||||||
listen 80;
|
listen 8080;
|
||||||
server_name dashy.mydomain.com;
|
server_name dashy.mydomain.com;
|
||||||
|
|
||||||
# Setup SSL
|
# Setup SSL
|
||||||
@ -577,7 +579,7 @@ Similarly, a basic `Caddyfile` might look like:
|
|||||||
|
|
||||||
```text
|
```text
|
||||||
dashy.example.com {
|
dashy.example.com {
|
||||||
reverse_proxy / nginx:80
|
reverse_proxy / nginx:8080
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -614,7 +616,7 @@ To prevent known container escape vulnerabilities, which typically end in escala
|
|||||||
Docker enables you to limit resource consumption (CPU, memory, disk) on a per-container basis. This not only enhances system performance, but also prevents a compromised container from consuming a large amount of resources, in order to disrupt service or perform malicious activities. To learn more, see the [Resource Constraints Docs](https://docs.docker.com/config/containers/resource_constraints/)
|
Docker enables you to limit resource consumption (CPU, memory, disk) on a per-container basis. This not only enhances system performance, but also prevents a compromised container from consuming a large amount of resources, in order to disrupt service or perform malicious activities. To learn more, see the [Resource Constraints Docs](https://docs.docker.com/config/containers/resource_constraints/)
|
||||||
|
|
||||||
For example, to run Dashy with max of 1GB ram, and max of 50% of 1 CP core:
|
For example, to run Dashy with max of 1GB ram, and max of 50% of 1 CP core:
|
||||||
`docker run -d -p 8080:80 --cpus=".5" --memory="1024m" lissy93/dashy:latest`
|
`docker run -d -p 8080:8080 --cpus=".5" --memory="1024m" lissy93/dashy:latest`
|
||||||
|
|
||||||
### Don't Run as Root
|
### Don't Run as Root
|
||||||
|
|
||||||
@ -629,7 +631,7 @@ One of the best ways to prevent privilege escalation attacks, is to configure th
|
|||||||
You can specify a user, using the [`--user` param](https://docs.docker.com/engine/reference/run/#user), and should include the user ID (`UID`), which can be found by running `id -u`, and the and the group ID (`GID`), using `id -g`.
|
You can specify a user, using the [`--user` param](https://docs.docker.com/engine/reference/run/#user), and should include the user ID (`UID`), which can be found by running `id -u`, and the and the group ID (`GID`), using `id -g`.
|
||||||
|
|
||||||
With Docker run, you specify it like:
|
With Docker run, you specify it like:
|
||||||
`docker run --user 1000:1000 -p 8080:80 lissy93/dashy`
|
`docker run --user 1000:1000 -p 8080:8080 lissy93/dashy`
|
||||||
|
|
||||||
Of if you're using Docker-compose, you could use an environmental variable
|
Of if you're using Docker-compose, you could use an environmental variable
|
||||||
|
|
||||||
@ -639,7 +641,7 @@ services:
|
|||||||
dashy:
|
dashy:
|
||||||
image: lissy93/dashy
|
image: lissy93/dashy
|
||||||
user: ${CURRENT_UID}
|
user: ${CURRENT_UID}
|
||||||
ports: [ 4000:80 ]
|
ports: [ 4000:8080 ]
|
||||||
```
|
```
|
||||||
|
|
||||||
And then to set the variable, and start the container, run: `CURRENT_UID=$(id -u):$(id -g) docker-compose up`
|
And then to set the variable, and start the container, run: `CURRENT_UID=$(id -u):$(id -g) docker-compose up`
|
||||||
@ -659,7 +661,7 @@ version: "3.8"
|
|||||||
services:
|
services:
|
||||||
dashy:
|
dashy:
|
||||||
image: lissy93/dashy
|
image: lissy93/dashy
|
||||||
ports: [ 4000:80 ]
|
ports: [ 4000:8080 ]
|
||||||
cap_drop:
|
cap_drop:
|
||||||
- ALL
|
- ALL
|
||||||
cap_add:
|
cap_add:
|
||||||
@ -675,7 +677,7 @@ services:
|
|||||||
To prevent processes inside the container from getting additional privileges, pass in the `--security-opt=no-new-privileges:true` option to the Docker run command (see [docs](https://docs.docker.com/engine/reference/run/#security-configuration)).
|
To prevent processes inside the container from getting additional privileges, pass in the `--security-opt=no-new-privileges:true` option to the Docker run command (see [docs](https://docs.docker.com/engine/reference/run/#security-configuration)).
|
||||||
|
|
||||||
Run Command:
|
Run Command:
|
||||||
`docker run --security-opt=no-new-privileges:true -p 8080:80 lissy93/dashy`
|
`docker run --security-opt=no-new-privileges:true -p 8080:8080 lissy93/dashy`
|
||||||
|
|
||||||
Docker Compose
|
Docker Compose
|
||||||
|
|
||||||
@ -701,14 +703,14 @@ You can specify that a specific volume should be read-only by appending `:ro` to
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker run -d \
|
docker run -d \
|
||||||
-p 8080:80 \
|
-p 8080:8080 \
|
||||||
-v ~/dashy-conf.yml:/app/public/conf.yml \
|
-v ~/dashy-conf.yml:/app/user-data/conf.yml \
|
||||||
-v ~/dashy-icons:/app/public/item-icons:ro \
|
-v ~/dashy-icons:/app/public/item-icons:ro \
|
||||||
-v ~/dashy-theme.scss:/app/src/styles/user-defined-themes.scss:ro \
|
-v ~/dashy-theme.scss:/app/src/styles/user-defined-themes.scss:ro \
|
||||||
lissy93/dashy:latest
|
lissy93/dashy:latest
|
||||||
```
|
```
|
||||||
|
|
||||||
You can also prevent a container from writing any changes to volumes on your host's disk, using the `--read-only` flag. Although, for Dashy, you will not be able to write config changes to disk, when edited through the UI with this method. You could make this work, by specifying the config directory as a temp write location, with `--tmpfs /app/public/conf.yml` - but that this will not write the volume back to your host.
|
You can also prevent a container from writing any changes to volumes on your host's disk, using the `--read-only` flag. Although, for Dashy, you will not be able to write config changes to disk, when edited through the UI with this method. You could make this work, by specifying the config directory as a temp write location, with `--tmpfs /app/user-data/conf.yml` - but that this will not write the volume back to your host.
|
||||||
|
|
||||||
### Set the Logging Level
|
### Set the Logging Level
|
||||||
|
|
||||||
@ -778,8 +780,8 @@ Create a new file in `/etc/nginx/sites-enabled/dashy`
|
|||||||
|
|
||||||
```text
|
```text
|
||||||
server {
|
server {
|
||||||
listen 80;
|
listen 8080;
|
||||||
listen [::]:80;
|
listen [::]:8080;
|
||||||
|
|
||||||
root /var/www/dashy/html;
|
root /var/www/dashy/html;
|
||||||
index index.html;
|
index index.html;
|
||||||
@ -898,7 +900,7 @@ Similar to above, you'll first need to fork and clone Dashy to your local system
|
|||||||
|
|
||||||
Then, either use Dashy's default [`Dockerfile`](https://github.com/Lissy93/dashy/blob/master/Dockerfile) as is, or modify it according to your needs.
|
Then, either use Dashy's default [`Dockerfile`](https://github.com/Lissy93/dashy/blob/master/Dockerfile) as is, or modify it according to your needs.
|
||||||
|
|
||||||
To build and deploy locally, first build the app with: `docker build -t dashy .`, and then start the app with `docker run -p 8080:80 --name my-dashboard dashy`. Or modify the `docker-compose.yml` file, replacing `image: lissy93/dashy` with `build: .` and run `docker compose up`.
|
To build and deploy locally, first build the app with: `docker build -t dashy .`, and then start the app with `docker run -p 8080:8080 --name my-dashboard dashy`. Or modify the `docker-compose.yml` file, replacing `image: lissy93/dashy` with `build: .` and run `docker compose up`.
|
||||||
|
|
||||||
Your container should now be running, and will appear in the list when you run `docker container ls –a`. If you'd like to enter the container, run `docker exec -it [container-id] /bin/ash`.
|
Your container should now be running, and will appear in the list when you run `docker container ls –a`. If you'd like to enter the container, run `docker exec -it [container-id] /bin/ash`.
|
||||||
|
|
||||||
|
@ -192,7 +192,7 @@ The following section outlines all data that is stored in the browsers, as cooki
|
|||||||
> [Local storage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) is persisted between sessions, and only deleted when manually removed
|
> [Local storage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) is persisted between sessions, and only deleted when manually removed
|
||||||
|
|
||||||
- `LANGUAGE` - The locale to show app text in
|
- `LANGUAGE` - The locale to show app text in
|
||||||
- `HIDE_WELCOME_BANNER` - Set to true once user dismissed welcome message, so that it's not shown again
|
- `HIDE_INFO_NOTIFICATION` - Set to true once user dismissed welcome message, so that it's not shown again
|
||||||
- `LAYOUT_ORIENTATION` - Preferred section layout, either horizontal, vertical or auto
|
- `LAYOUT_ORIENTATION` - Preferred section layout, either horizontal, vertical or auto
|
||||||
- `COLLAPSE_STATE` - Remembers which sections are collapsed
|
- `COLLAPSE_STATE` - Remembers which sections are collapsed
|
||||||
- `ICON_SIZE` - Size of items, either small, medium or large
|
- `ICON_SIZE` - Size of items, either small, medium or large
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
Welcome to Dashy! So glad you're here 😊 In a couple of minutes, you'll have your new dashboard up and running 🚀
|
Welcome to Dashy! So glad you're here 😊 In a couple of minutes, you'll have your new dashboard up and running 🚀
|
||||||
|
|
||||||
**TLDR;** Run `docker run -p 8080:80 lissy93/dashy`, then open `http://localhost:8080`
|
**TLDR;** Run `docker run -p 8080:8080 lissy93/dashy`, then open `http://localhost:8080`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -19,8 +19,8 @@ To pull the latest image, and build and start the app run:
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker run -d \
|
docker run -d \
|
||||||
-p 8080:80 \
|
-p 8080:8080 \
|
||||||
-v ~/my-conf.yml:/app/public/conf.yml \
|
-v ~/my-conf.yml:/app/user-data/conf.yml \
|
||||||
--name my-dashboard \
|
--name my-dashboard \
|
||||||
--restart=always \
|
--restart=always \
|
||||||
lissy93/dashy:latest
|
lissy93/dashy:latest
|
||||||
@ -32,15 +32,41 @@ Your dashboard should now be up and running at `http://localhost:8080` (or your
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 3. Configure
|
## 3. User Data Directory
|
||||||
|
|
||||||
|
Your config file should be placed inside `user-data/` (in Docker, that's `/app/user-data/`).
|
||||||
|
|
||||||
|
This directory can also contain some optional assets you wish to use within your dashboard, like icons, fonts, styles, scripts, etc.
|
||||||
|
|
||||||
|
Any files placed here will be served up to the root of the domain, and override the contents of `public/`.
|
||||||
|
For example, if you had `user-data/favicon.ico` this would be accessible at `http://my-dashy-instance.local/favicon.ico`
|
||||||
|
|
||||||
|
Example Files in `user-data`:
|
||||||
|
- `conf.yml` - This is the only file that is compulsary, it's your main Dashy config
|
||||||
|
- `**.yml` - Include more config files, if you'd like to have multiple pages, see [Multi-page support](/docs/pages-and-sections.md#multi-page-support) for docs
|
||||||
|
- `favicon.ico` - The default favicon, shown in the browser's tab title
|
||||||
|
- `initialization.html` - Static HTML page displayed before the app has finished compiling, see [`public/initialization.html`](https://github.com/Lissy93/dashy/blob/master/public/initialization.html)
|
||||||
|
- `robots.txt` - Search engine crawl rules, override this if you want your dashboard to be indexable
|
||||||
|
- `manifest.json` - PWA configuration file, for installing Dashy on mobile devices
|
||||||
|
- `index.html` - The main index page which initializes the client-side app, copy it from [`/public/index.html`](https://github.com/Lissy93/dashy/blob/master/public/index.html)
|
||||||
|
- `**.html` - Write your own HTML pages, and access them at `http://my-dashy-instance.local/my-page.html`
|
||||||
|
- `fonts/` - Custom fonts (be sure to include the ones already in [`public/fonts`](https://github.com/Lissy93/dashy/tree/master/public/fonts)
|
||||||
|
- `item-icons/` - To use your own icons for items on your dashboard, see [Icons --> Local Icons](/docs/icons.md#local-icons)
|
||||||
|
- `web-icons/` - Override Dashy logo
|
||||||
|
- `widget-resources/` - Fonts, icons and assets for custom widgets
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Configure
|
||||||
|
|
||||||
Now that you've got Dashy running, you are going to want to set it up with your own content.
|
Now that you've got Dashy running, you are going to want to set it up with your own content.
|
||||||
Config is written in [YAML Format](https://yaml.org/), and saved in [`/public/conf.yml`](https://github.com/Lissy93/dashy/blob/master/public/conf.yml).
|
Config is written in [YAML Format](https://yaml.org/), and saved in [`/user-data/conf.yml`](https://github.com/Lissy93/dashy/blob/master/user-data/conf.yml).
|
||||||
The format on the config file is pretty straight forward. There are three root attributes:
|
The format on the config file is pretty straight forward. There are three root attributes:
|
||||||
|
|
||||||
- [`pageInfo`](https://github.com/Lissy93/dashy/blob/master/docs/configuring.md#pageinfo) - Dashboard meta data, like title, description, nav bar links and footer text
|
- [`pageInfo`](https://github.com/Lissy93/dashy/blob/master/docs/configuring.md#pageinfo) - Dashboard meta data, like title, description, nav bar links and footer text
|
||||||
- [`appConfig`](https://github.com/Lissy93/dashy/blob/master/docs/configuring.md#appconfig-optional) - Dashboard settings, like themes, authentication, language and customization
|
- [`appConfig`](https://github.com/Lissy93/dashy/blob/master/docs/configuring.md#appconfig-optional) - Dashboard settings, like themes, authentication, language and customization
|
||||||
- [`sections`](https://github.com/Lissy93/dashy/blob/master/docs/configuring.md#section) - An array of sections, each including an array of items
|
- [`sections`](https://github.com/Lissy93/dashy/blob/master/docs/configuring.md#section) - An array of sections, each including an array of items
|
||||||
|
- [`pages`](https://github.com/Lissy93/dashy/blob/master/docs/configuring.md#pages-optional) - Have multiples pages in your dashboard
|
||||||
|
|
||||||
You can view a full list of all available config options in the [Configuring Docs](https://github.com/Lissy93/dashy/blob/master/docs/configuring.md).
|
You can view a full list of all available config options in the [Configuring Docs](https://github.com/Lissy93/dashy/blob/master/docs/configuring.md).
|
||||||
|
|
||||||
@ -72,15 +98,15 @@ sections: # An array of sections
|
|||||||
Notes:
|
Notes:
|
||||||
|
|
||||||
- You can use a Docker volume to pass a config file from your host system to the container
|
- You can use a Docker volume to pass a config file from your host system to the container
|
||||||
- E.g. `-v ./host-system/my-local-conf.yml:/app/public/conf.yml`
|
- E.g. `-v ./host-system/my-local-conf.yml:/app/user-data/conf.yml`
|
||||||
- It's also possible to edit your config directly through the UI, and changes will be saved in this file
|
- It's also possible to edit your config directly through the UI, and changes will be saved in this file
|
||||||
- Check your config against Dashy's schema, with `docker exec -it [container-id] yarn validate-config`
|
- Check your config against Dashy's schema, with `docker exec -it [container-id] yarn validate-config`
|
||||||
- You might find it helpful to look at some examples, a collection of which can be [found here](https://gist.github.com/Lissy93/000f712a5ce98f212817d20bc16bab10)
|
- You might find it helpful to look at some examples, a collection of which can be [found here](https://gist.github.com/Lissy93/000f712a5ce98f212817d20bc16bab10)
|
||||||
- After editing your config, the app will rebuild in the background, which may take a minute
|
- It's also possible to load a remote config, e.g. from a GitHub Gist
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 4. Further Customisation
|
## 5. Further Customisation
|
||||||
|
|
||||||
Once you've got Dashy setup, you'll want to ensure the container is properly healthy, secured, backed up and kept up-to-date. All this is covered in the [Management Docs](https://github.com/Lissy93/dashy/blob/master/docs/management.md).
|
Once you've got Dashy setup, you'll want to ensure the container is properly healthy, secured, backed up and kept up-to-date. All this is covered in the [Management Docs](https://github.com/Lissy93/dashy/blob/master/docs/management.md).
|
||||||
|
|
||||||
@ -97,7 +123,7 @@ You might also want to check out the docs for specific features you'd like to us
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 5. Final Note
|
## 6. Final Note
|
||||||
|
|
||||||
If you need any help or support in getting Dashy running, head over to the [Discussions](https://github.com/Lissy93/dashy/discussions) page. If you think you've found a bug, please do [raise it](https://github.com/Lissy93/dashy/issues/new/choose) so it can be fixed. For contact options, see the [Support Page](https://github.com/Lissy93/dashy/blob/master/.github/SUPPORT.md).
|
If you need any help or support in getting Dashy running, head over to the [Discussions](https://github.com/Lissy93/dashy/discussions) page. If you think you've found a bug, please do [raise it](https://github.com/Lissy93/dashy/issues/new/choose) so it can be fixed. For contact options, see the [Support Page](https://github.com/Lissy93/dashy/blob/master/.github/SUPPORT.md).
|
||||||
|
|
||||||
@ -118,7 +144,7 @@ yarn build # Build the app
|
|||||||
yarn start # Start the app
|
yarn start # Start the app
|
||||||
```
|
```
|
||||||
|
|
||||||
Then edit `./public/conf.yml` and rebuild the app with `yarn build`
|
Then edit `./user-data/conf.yml`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -129,7 +155,7 @@ Don't have a server? No problem! You can run Dashy for free on Netlify (as well
|
|||||||
1. Fork Dashy's repository on GitHub
|
1. Fork Dashy's repository on GitHub
|
||||||
2. [Log in](app.netlify.com/login/) to Netlify with GitHub
|
2. [Log in](app.netlify.com/login/) to Netlify with GitHub
|
||||||
3. Click "New site from Git" and select your forked repo, then click **Deploy**!
|
3. Click "New site from Git" and select your forked repo, then click **Deploy**!
|
||||||
4. You can then edit the config in `./public/conf.yml` in your repo, and Netlify will rebuild the app
|
4. You can then edit the config in `./user-data/conf.yml` in your repo, and Netlify will rebuild the app
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -3,6 +3,14 @@
|
|||||||
| 💗 Got a sweet dashboard? Submit it to the showcase! 👉 [See How](#submitting-your-dashboard) |
|
| 💗 Got a sweet dashboard? Submit it to the showcase! 👉 [See How](#submitting-your-dashboard) |
|
||||||
|-|
|
|-|
|
||||||
|
|
||||||
|
## MNDashboard
|
||||||
|
|
||||||
|
> By [@mahrnet](https://github.com/mahrnet) <sup>Re: [#1491](https://github.com/Lissy93/dashy/issues/1491)</sup>
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Home Lab 2.0
|
## Home Lab 2.0
|
||||||
|
|
||||||

|

|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
## Contents
|
## Contents
|
||||||
|
|
||||||
|
- [Config not saving](#config-not-saving)
|
||||||
- [Refused to Connect in Web Content View](#refused-to-connect-in-modal-or-workspace-view)
|
- [Refused to Connect in Web Content View](#refused-to-connect-in-modal-or-workspace-view)
|
||||||
- [404 On Static Hosting](#404-on-static-hosting)
|
- [404 On Static Hosting](#404-on-static-hosting)
|
||||||
- [404 from Mobile Home Screen](#404-after-launch-from-mobile-home-screen)
|
- [404 from Mobile Home Screen](#404-after-launch-from-mobile-home-screen)
|
||||||
@ -18,6 +19,7 @@
|
|||||||
- [App Not Starting After Update to 2.0.4](#app-not-starting-after-update-to-204)
|
- [App Not Starting After Update to 2.0.4](#app-not-starting-after-update-to-204)
|
||||||
- [Keycloak Redirect Error](#keycloak-redirect-error)
|
- [Keycloak Redirect Error](#keycloak-redirect-error)
|
||||||
- [Docker Directory Error](#docker-directory)
|
- [Docker Directory Error](#docker-directory)
|
||||||
|
- [Config not Saving on Vercel / Netlify / CDN](#user-content-config-not-saving-on-vercel--netlify--cdn)
|
||||||
- [Config Not Updating](#config-not-updating)
|
- [Config Not Updating](#config-not-updating)
|
||||||
- [Config Still not Updating](#config-still-not-updating)
|
- [Config Still not Updating](#config-still-not-updating)
|
||||||
- [Styles and Assets not Updating](#styles-and-assets-not-updating)
|
- [Styles and Assets not Updating](#styles-and-assets-not-updating)
|
||||||
@ -45,6 +47,25 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Config not saving
|
||||||
|
|
||||||
|
### Possible Issue 1: Unable to call save endpoint from CDN/static server
|
||||||
|
If you're running Dashy using a static hosting provider (like Vercel), then there is no Node server, and so the save config action will not work via the UI.
|
||||||
|
You'll instead need to copy the YAML after making your changes, and paste that into your `conf.yml` directly. If you've connected Vercel to git, then these changes will take effect automatically, once you commit your changes.
|
||||||
|
Look here for more information: [https://dashy.to/docs/deployment#deploy-to-cloud-service](https://dashy.to/docs/deployment#deploy-to-cloud-service)
|
||||||
|
|
||||||
|
If you're running on Netlify, there are some cloud functions which take care of all the server endpoints (like status checking), so these will work as expected.
|
||||||
|
|
||||||
|
See also [#1465](https://github.com/Lissy93/dashy/issues/1465)
|
||||||
|
|
||||||
|
### Possible Issue 2: Unable to save
|
||||||
|
In Docker, double check that the file isn't read-only, and that the container actually has permissions to modify it. You shouldn't really be running it as a root user, and I'm not sure if it will work if you do-
|
||||||
|
|
||||||
|
### Possible Issue 3: Saved but not updating
|
||||||
|
After saving, the frontend will recompile, which may take a couple seconds (or a bit longer on a Pi or low-powered device). If it doesn't recompile, you can manually trigger a re-build.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## `Refused to Connect` in Modal or Workspace View
|
## `Refused to Connect` in Modal or Workspace View
|
||||||
|
|
||||||
This is not an issue with Dashy, but instead caused by the target app preventing direct access through embedded elements.
|
This is not an issue with Dashy, but instead caused by the target app preventing direct access through embedded elements.
|
||||||
@ -135,7 +156,7 @@ If you're getting an error about scenarios, then you've likely installed the wro
|
|||||||
Alternatively, as a workaround, you have several options:
|
Alternatively, as a workaround, you have several options:
|
||||||
|
|
||||||
- Try using [NPM](https://www.npmjs.com/get-npm) instead: So clone, cd, then run `npm install`, `npm run build` and `npm start`
|
- Try using [NPM](https://www.npmjs.com/get-npm) instead: So clone, cd, then run `npm install`, `npm run build` and `npm start`
|
||||||
- Try using [Docker](https://www.docker.com/get-started) instead, and all of the system setup and dependencies will already be taken care of. So from within the directory, just run `docker build -t lissy93/dashy .` to build, and then use docker start to run the project, e.g: `docker run -it -p 8080:80 lissy93/dashy` (see the [deploying docs](https://github.com/Lissy93/dashy/blob/master/docs/deployment.md#deploy-with-docker) for more info)
|
- Try using [Docker](https://www.docker.com/get-started) instead, and all of the system setup and dependencies will already be taken care of. So from within the directory, just run `docker build -t lissy93/dashy .` to build, and then use docker start to run the project, e.g: `docker run -it -p 8080:8080 lissy93/dashy` (see the [deploying docs](https://github.com/Lissy93/dashy/blob/master/docs/deployment.md#deploy-with-docker) for more info)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -213,7 +234,7 @@ Version 2.0.4 introduced changes to how the config is read, and the app is build
|
|||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
volumes:
|
volumes:
|
||||||
- /srv/dashy/conf.yml:/app/public/conf.yml
|
- /srv/dashy/conf.yml:/app/user-data/conf.yml
|
||||||
- /srv/dashy/item-icons:/app/public/item-icons
|
- /srv/dashy/item-icons:/app/public/item-icons
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -252,12 +273,23 @@ See also: #479, #409, #507, #491, #341, #520
|
|||||||
Error response from daemon: OCI runtime create failed: container_linux.go:380:
|
Error response from daemon: OCI runtime create failed: container_linux.go:380:
|
||||||
starting container process caused: process_linux.go:545: container init caused:
|
starting container process caused: process_linux.go:545: container init caused:
|
||||||
rootfs_linux.go:76: mounting "/home/ubuntu/my-conf.yml" to rootfs at
|
rootfs_linux.go:76: mounting "/home/ubuntu/my-conf.yml" to rootfs at
|
||||||
"/app/public/conf.yml" caused: mount through procfd: not a directory:
|
"/app/user-data/conf.yml" caused: mount through procfd: not a directory:
|
||||||
unknown: Are you trying to mount a directory onto a file (or vice-versa)?
|
unknown: Are you trying to mount a directory onto a file (or vice-versa)?
|
||||||
Check if the specified host path exists and is the expected type.
|
Check if the specified host path exists and is the expected type.
|
||||||
```
|
```
|
||||||
|
|
||||||
If you get an error similar to the one above, you are mounting a directory to the config file's location, when a plain file is expected. Create a YAML file, (`touch my-conf.yml`), populate it with a sample config, then pass it as a volume: `-v ./my-local-conf.yml:/app/public/conf.yml`
|
If you get an error similar to the one above, you are mounting a directory to the config file's location, when a plain file is expected. Create a YAML file, (`touch my-conf.yml`), populate it with a sample config, then pass it as a volume: `-v ./my-local-conf.yml:/app/user-data/conf.yml`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Config not Saving on Vercel / Netlify / CDN
|
||||||
|
|
||||||
|
If you're running Dashy using a static hosting provider (like Vercel), then there is no Node server, and so the save config action will not work via the UI.
|
||||||
|
You'll instead need to copy the YAML after making your changes, and paste that into your `conf.yml` directly. If you've connected Vercel to git, then these changes will take effect automatically, once you commit your changes.
|
||||||
|
|
||||||
|
If you're running on Netlify, there are some cloud functions which take care of all the server endpoints (like status checking), so these will work as expected.
|
||||||
|
|
||||||
|
See also [#1465](https://github.com/Lissy93/dashy/issues/1465)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -504,9 +536,11 @@ Usually, Font Awesome will be automatically enabled if one or more of your icons
|
|||||||
|
|
||||||
If you are trying to use a premium icon, then you must have a [Pro License](https://fontawesome.com/plans). You'll then need to specify your Pro plan API key under `appConfig.fontAwesomeKey`. You can find this key, by logging into your FA account, navigate to Account → [Kits](https://fontawesome.com/kits) → New Kit → Copy Kit Code. The code is a 10-digit alpha-numeric code, and is also visible within the new kit's URL, for example: `81e48ce079`.
|
If you are trying to use a premium icon, then you must have a [Pro License](https://fontawesome.com/plans). You'll then need to specify your Pro plan API key under `appConfig.fontAwesomeKey`. You can find this key, by logging into your FA account, navigate to Account → [Kits](https://fontawesome.com/kits) → New Kit → Copy Kit Code. The code is a 10-digit alpha-numeric code, and is also visible within the new kit's URL, for example: `81e48ce079`.
|
||||||
|
|
||||||
|
<p align="center"><img src="https://i.ibb.co/hZ0D9vs/where-do-i-find-my-font-awesome-key.png" width="600" /></p>
|
||||||
|
|
||||||
Be sure that you're specifying the icon category and name correctly. You're icon should look be `[category] fa-[icon-name]`. The following categories are supported: `far` _(regular)_, `fas` _(solid)_, `fal`_(light)_, `fad` _(duo-tone)_ and `fab`_(brands)_. With the exception of brands, you'll usually want all your icons to be in from same category, so they look uniform.
|
Be sure that you're specifying the icon category and name correctly. You're icon should look be `[category] fa-[icon-name]`. The following categories are supported: `far` _(regular)_, `fas` _(solid)_, `fal`_(light)_, `fad` _(duo-tone)_ and `fab`_(brands)_. With the exception of brands, you'll usually want all your icons to be in from same category, so they look uniform.
|
||||||
|
|
||||||
Ensure the icon you are trying to use, is available within [FontAwesome Version 5](https://fontawesome.com/v5/search).
|
Ensure the icon you are trying to use, is available within [FontAwesome Version 5](https://fontawesome.com/v5/search) (we've not yet upgraded to V6, as it works a little differently).
|
||||||
|
|
||||||
Examples: `fab fa-raspberry-pi`, `fas fa-database`, `fas fa-server`, `fas fa-ethernet`
|
Examples: `fab fa-raspberry-pi`, `fas fa-database`, `fas fa-server`, `fas fa-ethernet`
|
||||||
|
|
||||||
@ -535,8 +569,7 @@ For example:
|
|||||||
export NODE_OPTIONS=--openssl-legacy-provider
|
export NODE_OPTIONS=--openssl-legacy-provider
|
||||||
```
|
```
|
||||||
|
|
||||||
For more info, see [webpack/webpack#14532](https://github.com/webpack/webpack/issues/14532) and [nodejs/node#40455](https://github.com/nodejs/node/issues/40455).
|
This will be fixed once [webpack/webpack#17659](https://github.com/webpack/webpack/pull/17659) is merged.
|
||||||
This occours because [Node 17+](https://medium.com/the-node-js-collection/node-js-17-is-here-8dba1e14e382) no longer supports MD4 as hash function, we're in the process of upgrading Dashy dependencies to all use SHA1 for hashing bundle IDs.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
145
docs/widgets.md
@ -66,6 +66,7 @@ Dashy has support for displaying dynamic content in the form of widgets. There a
|
|||||||
- [Gluetun VPN Info](#gluetun-vpn-info)
|
- [Gluetun VPN Info](#gluetun-vpn-info)
|
||||||
- [Drone CI Build](#drone-ci-builds)
|
- [Drone CI Build](#drone-ci-builds)
|
||||||
- [Linkding](#linkding)
|
- [Linkding](#linkding)
|
||||||
|
- [Uptime Kuma](#uptime-kuma)
|
||||||
- **[System Resource Monitoring](#system-resource-monitoring)**
|
- **[System Resource Monitoring](#system-resource-monitoring)**
|
||||||
- [CPU Usage Current](#current-cpu-usage)
|
- [CPU Usage Current](#current-cpu-usage)
|
||||||
- [CPU Usage Per Core](#cpu-usage-per-core)
|
- [CPU Usage Per Core](#cpu-usage-per-core)
|
||||||
@ -91,6 +92,7 @@ Dashy has support for displaying dynamic content in the form of widgets. There a
|
|||||||
- [Widget Usage Guide](#widget-usage-guide)
|
- [Widget Usage Guide](#widget-usage-guide)
|
||||||
- [Continuous Updates](#continuous-updates)
|
- [Continuous Updates](#continuous-updates)
|
||||||
- [Proxying Requests](#proxying-requests)
|
- [Proxying Requests](#proxying-requests)
|
||||||
|
- [Handling Secrets](#handling-secrets)
|
||||||
- [Setting Timeout](#setting-timeout)
|
- [Setting Timeout](#setting-timeout)
|
||||||
- [Adding Labels](#adding-labels)
|
- [Adding Labels](#adding-labels)
|
||||||
- [Ignoring Errors](#ignoring-errors)
|
- [Ignoring Errors](#ignoring-errors)
|
||||||
@ -151,6 +153,8 @@ A simple, live-updating local weather component, showing temperature, conditions
|
|||||||
**`city`** | `string` | Required | A city name to use for fetching weather. This can also be a state code or country code, following the ISO-3166 format
|
**`city`** | `string` | Required | A city name to use for fetching weather. This can also be a state code or country code, following the ISO-3166 format
|
||||||
**`units`** | `string` | _Optional_ | The units to use for displaying data, can be either `metric` or `imperial`. Defaults to `metric`
|
**`units`** | `string` | _Optional_ | The units to use for displaying data, can be either `metric` or `imperial`. Defaults to `metric`
|
||||||
**`hideDetails`** | `boolean` | _Optional_ | If set to `true`, the additional details (wind, humidity, pressure, etc) will not be shown. Defaults to `false`
|
**`hideDetails`** | `boolean` | _Optional_ | If set to `true`, the additional details (wind, humidity, pressure, etc) will not be shown. Defaults to `false`
|
||||||
|
**`lat`** | `number` | _Optional_ | To show weather for a specific location, you can provide the latitude and longitude coordinates. If provided, this will override the `city` option
|
||||||
|
**`lon`** | `number` | _Optional_ | To show weather for a specific location, you can provide the latitude and longitude coordinates. If provided, this will override the `city` option
|
||||||
|
|
||||||
#### Example
|
#### Example
|
||||||
|
|
||||||
@ -160,7 +164,7 @@ A simple, live-updating local weather component, showing temperature, conditions
|
|||||||
apiKey: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
apiKey: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||||
city: London
|
city: London
|
||||||
units: metric
|
units: metric
|
||||||
hideDetails: false
|
hideDetails: true
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Info
|
#### Info
|
||||||
@ -701,6 +705,8 @@ Display current FX rates in your native currency. Hover over a row to view more
|
|||||||
|
|
||||||
Counting down to the next day off work? This widget displays upcoming public holidays for your country. Data is fetched from [Enrico](http://kayaposoft.com/enrico/)
|
Counting down to the next day off work? This widget displays upcoming public holidays for your country. Data is fetched from [Enrico](http://kayaposoft.com/enrico/)
|
||||||
|
|
||||||
|
Note, config for this widget is case-sensetive (see [#1268](https://github.com/Lissy93/dashy/issues/1268))
|
||||||
|
|
||||||
<p align="center"><img width="400" src="https://i.ibb.co/VC6fZqn/public-holidays.png" /></p>
|
<p align="center"><img width="400" src="https://i.ibb.co/VC6fZqn/public-holidays.png" /></p>
|
||||||
|
|
||||||
#### Options
|
#### Options
|
||||||
@ -1549,6 +1555,19 @@ Displays the number of queries blocked by [Pi-Hole](https://pi-hole.net/).
|
|||||||
apiKey: xxxxxxxxxxxxxxxxxxxxxxx
|
apiKey: xxxxxxxxxxxxxxxxxxxxxxx
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
|
> In order to avoid leaking secret data, both `hostname` and `apiKey` can leverage environment variables. Simply pass the name of the variable, which MUST start with `VUE_APP_`.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- type: pi-hole-stats
|
||||||
|
options:
|
||||||
|
hostname: VUE_APP_pihole_ip
|
||||||
|
apiKey: VUE_APP_pihole_key
|
||||||
|
```
|
||||||
|
|
||||||
|
> [!IMPORTANT]
|
||||||
|
> You will need to restart the server (or the docker image) if adding/editing an env var for this to be refreshed.
|
||||||
|
|
||||||
#### Info
|
#### Info
|
||||||
|
|
||||||
- **CORS**: 🟢 Enabled
|
- **CORS**: 🟢 Enabled
|
||||||
@ -2109,7 +2128,9 @@ This will show the list of nodes.
|
|||||||
token_name: dashy
|
token_name: dashy
|
||||||
token_uuid: bfb152df-abcd-abcd-abcd-ccb95a472d01
|
token_uuid: bfb152df-abcd-abcd-abcd-ccb95a472d01
|
||||||
```
|
```
|
||||||
|
|
||||||
This will show the list of VMs, with a title and a linked fotter, hiding VM templates.
|
This will show the list of VMs, with a title and a linked fotter, hiding VM templates.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- type: proxmox-lists
|
- type: proxmox-lists
|
||||||
useProxy: true
|
useProxy: true
|
||||||
@ -2126,6 +2147,7 @@ This will show the list of VMs, with a title and a linked fotter, hiding VM temp
|
|||||||
footer_as_link: true
|
footer_as_link: true
|
||||||
hide_templates: 1
|
hide_templates: 1
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Info
|
#### Info
|
||||||
|
|
||||||
- **CORS**: 🟠 Proxied
|
- **CORS**: 🟠 Proxied
|
||||||
@ -2134,6 +2156,12 @@ This will show the list of VMs, with a title and a linked fotter, hiding VM temp
|
|||||||
- **Host**: Self-Hosted (see [Proxmox Virtual Environment](https://proxmox.com/en/proxmox-ve))
|
- **Host**: Self-Hosted (see [Proxmox Virtual Environment](https://proxmox.com/en/proxmox-ve))
|
||||||
- **Privacy**: _See [Proxmox's Privacy Policy](https://proxmox.com/en/privacy-policy)_
|
- **Privacy**: _See [Proxmox's Privacy Policy](https://proxmox.com/en/privacy-policy)_
|
||||||
|
|
||||||
|
#### Troubleshooting
|
||||||
|
- **404 Error in development mode**: The error might disappear in production mode `yarn start`
|
||||||
|
- **500 Error in production mode**: Try adding the certificate authority (CA) certificate of your Proxmox host to Node.js.
|
||||||
|
- Download the Proxmox CA certificate to your Dashy host.
|
||||||
|
- Export environment variable `NODE_EXTRA_CA_CERTS` and set its value to the path of the downloaded CA certificate. Example: `export NODE_EXTRA_CA_CERTS=/usr/local/share/ca-certificates/devlab_ca.pem`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### Sabnzbd
|
### Sabnzbd
|
||||||
@ -2216,7 +2244,7 @@ Display the last builds from a [Drone CI](https://www.drone.ci) instance. A self
|
|||||||
**Field** | **Type** | **Required** | **Description**
|
**Field** | **Type** | **Required** | **Description**
|
||||||
--- | --- | --- | ---
|
--- | --- | --- | ---
|
||||||
**`host`** | `string` | Required | The hostname of the Drone CI instance.
|
**`host`** | `string` | Required | The hostname of the Drone CI instance.
|
||||||
**`apiKey`** | `string` | Required | The API key (https://<your-drone-instance>/account).
|
**`apiKey`** | `string` | Required | The API key (https://[your-drone-instance]/account).
|
||||||
**`limit`** | `integer` | _Optional_ | Limit the amounts of listed builds.
|
**`limit`** | `integer` | _Optional_ | Limit the amounts of listed builds.
|
||||||
**`repo`** | `string` | _Optional_ | Show only builds of the specified repo
|
**`repo`** | `string` | _Optional_ | Show only builds of the specified repo
|
||||||
|
|
||||||
@ -2250,7 +2278,7 @@ Linkding is a self-hosted bookmarking service, which has a clean interface and i
|
|||||||
**Field** | **Type** | **Required** | **Description**
|
**Field** | **Type** | **Required** | **Description**
|
||||||
--- | --- | --- | ---
|
--- | --- | --- | ---
|
||||||
**`host`** | `string` | Required | The hostname of the Drone CI instance.
|
**`host`** | `string` | Required | The hostname of the Drone CI instance.
|
||||||
**`apiKey`** | `string` | Required | The API key (https://<your-linkding-instance>/settings/integrations).
|
**`apiKey`** | `string` | Required | The API key (https://your-linkding-instance/settings/integrations).
|
||||||
**`tags`** | `list of string` | _Optional_ | Filter the links by tag.
|
**`tags`** | `list of string` | _Optional_ | Filter the links by tag.
|
||||||
|
|
||||||
#### Example
|
#### Example
|
||||||
@ -2276,6 +2304,37 @@ Linkding is a self-hosted bookmarking service, which has a clean interface and i
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
### Uptime Kuma
|
||||||
|
|
||||||
|
[Uptime Kuma](https://github.com/louislam/uptime-kuma) is an easy-to-use self-hosted monitoring tool.
|
||||||
|
|
||||||
|
#### Options
|
||||||
|
|
||||||
|
| **Field** | **Type** | **Required** | **Description** |
|
||||||
|
| ------------ | -------- | ------------ | ------------------------------------------------------------------------ |
|
||||||
|
| **`url`** | `string` | Required | The URL of the Uptime Kuma instance |
|
||||||
|
| **`apiKey`** | `string` | Required | The API key (see https://github.com/louislam/uptime-kuma/wiki/API-Keys). |
|
||||||
|
|
||||||
|
#### Example
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- type: uptime-kuma
|
||||||
|
useProxy: true
|
||||||
|
options:
|
||||||
|
apiKey: uk2_99H0Yd3I2pPNIRfn0TqBFu4g5q85R1Mh75yZzw6H
|
||||||
|
url: http://192.168.1.106:3691/metrics
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Info
|
||||||
|
|
||||||
|
- **CORS**: 🟢 Enabled
|
||||||
|
- **Auth**: 🟢 Required
|
||||||
|
- **Price**: 🟢 Free
|
||||||
|
- **Host**: Self-Hosted (see [Uptime Kuma](https://github.com/louislam/uptime-kuma) )
|
||||||
|
- **Privacy**: _See [Uptime Kuma](https://github.com/louislam/uptime-kuma)_
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## System Resource Monitoring
|
## System Resource Monitoring
|
||||||
|
|
||||||
### Glances
|
### Glances
|
||||||
@ -2285,8 +2344,28 @@ Glances is a cross-platform monitoring tool developed by [@nicolargo](https://gi
|
|||||||
|
|
||||||
If you don't already have it installed, either follow the [Installation Guide](https://github.com/nicolargo/glances/blob/master/README.rst) for your system, or setup [with Docker](https://glances.readthedocs.io/en/latest/docker.html), or use the one-line install script: `curl -L https://bit.ly/glances | /bin/bash`.
|
If you don't already have it installed, either follow the [Installation Guide](https://github.com/nicolargo/glances/blob/master/README.rst) for your system, or setup [with Docker](https://glances.readthedocs.io/en/latest/docker.html), or use the one-line install script: `curl -L https://bit.ly/glances | /bin/bash`.
|
||||||
|
|
||||||
|
If you are using Docker to run glances make sure to add the enviroment variable `-e TZ = {YourTimeZone}`. You can get a list of valid timezones by running `timedatectl list-timezones` on any linux system. This is needed so the graphs show the currect time.
|
||||||
|
|
||||||
|
Here an example for Docker
|
||||||
|
```
|
||||||
|
docker run -d \
|
||||||
|
--name glances \
|
||||||
|
--restart unless-stopped \
|
||||||
|
-v /var/run/docker.sock:/var/run/docker.sock:ro \
|
||||||
|
-p 61208:61208 \
|
||||||
|
--pid host \
|
||||||
|
--privileged \
|
||||||
|
-e GLANCES_OPT=-w \
|
||||||
|
-e PUID=1000 \
|
||||||
|
-e PGID=1000 \
|
||||||
|
-e TZ=Europe/Zurich \
|
||||||
|
nicolargo/glances:latest
|
||||||
|
```
|
||||||
|
|
||||||
Glances can be launched with the `glances` command. You'll need to run it in web server mode, using the `-w` option for the API to be reachable. If you don't plan on using the Web UI, then you can disable it using `--disable-webui`. See the [command reference docs](https://glances.readthedocs.io/en/latest/cmds.html) for more info.
|
Glances can be launched with the `glances` command. You'll need to run it in web server mode, using the `-w` option for the API to be reachable. If you don't plan on using the Web UI, then you can disable it using `--disable-webui`. See the [command reference docs](https://glances.readthedocs.io/en/latest/cmds.html) for more info.
|
||||||
|
|
||||||
|
If Glaces is running on a Windows system it is recommanded to add the following arguments ```--disable-plugin all --enable-plugin cpu,mem,diskio,ip,network,containers,quicklook,load,fs,alert -w``` This is due to Glances not being that stable on windows, so disabling all plugins that aren't used by Dashy widgets can save on ressources.
|
||||||
|
|
||||||
#### Options
|
#### Options
|
||||||
|
|
||||||
All Glance's based widgets require a `hostname`. All other parameters are optional.
|
All Glance's based widgets require a `hostname`. All other parameters are optional.
|
||||||
@ -2331,6 +2410,22 @@ Live-updating current CPU usage, as a combined average across all cores
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
### Current CPU Usage Speedometer
|
||||||
|
|
||||||
|
Speedometer styled version of the Current CPU Usage widget
|
||||||
|
|
||||||
|
<p align="center"><img width="400" src="https://i.ibb.co/7RHTRNq/gl-cpu-speedometer.png" /></p>
|
||||||
|
|
||||||
|
#### Example
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- type: gl-cpu-speedometer
|
||||||
|
options:
|
||||||
|
hostname: http://192.168.130.2:61208
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### CPU Usage Per Core
|
### CPU Usage Per Core
|
||||||
|
|
||||||
Live-updating CPU usage breakdown per core
|
Live-updating CPU usage breakdown per core
|
||||||
@ -2386,6 +2481,22 @@ Real-time memory usage gauge, with more info visible on click
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
### Current Memory Usage Speedometer
|
||||||
|
|
||||||
|
Speedometer styled version of the Current Memory Usage widget
|
||||||
|
|
||||||
|
<p align="center"><img width="400" src="https://i.ibb.co/wsNW7Xr/gl-mem-speedometer.png" /></p>
|
||||||
|
|
||||||
|
#### Example
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- type: gl-mem-speedometer
|
||||||
|
options:
|
||||||
|
hostname: http://192.168.130.2:61208
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### Memory Usage History
|
### Memory Usage History
|
||||||
|
|
||||||
Recent memory usage chart
|
Recent memory usage chart
|
||||||
@ -2746,6 +2857,32 @@ Vary: Origin
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
### Handling Secrets
|
||||||
|
|
||||||
|
Some widgets require you to pass potentially sensetive info such as API keys. The `conf.yml` is not ideal for this, as it's stored in plaintext.
|
||||||
|
Instead, for secrets you should use environmental vairables.
|
||||||
|
|
||||||
|
You can do this, by setting the environmental variable name as the value, instead of the actual key, and then setting that env var in your container or local environment.
|
||||||
|
|
||||||
|
The key can be named whatever you like, but it must start with `VUE_APP_` (to be picked up by Vue). If you need to update any of these values, a rebuild is required (this can be done under the Config menu in the UI, or by running `yarn build` then restarting the container).
|
||||||
|
|
||||||
|
For more infomation about setting and managing your environmental variables, see [Management Docs --> Environmental Variables](/docs/management.md#passing-in-environmental-variables).
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- type: weather
|
||||||
|
options:
|
||||||
|
apiKey: VUE_APP_WEATHER_TOKEN
|
||||||
|
city: London
|
||||||
|
units: metric
|
||||||
|
hideDetails: true
|
||||||
|
```
|
||||||
|
|
||||||
|
Then, set `VUE_APP_WEATHER_TOKEN='xxx'`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### Setting Timeout
|
### Setting Timeout
|
||||||
|
|
||||||
If the endpoint you are requesting data from is slow to respond, you may see a timeout error in the console. This can easily be fixed by specifying the `timeout` property on the offending widget. This should be an integer value, in milliseconds. By default timeout is `2500` ms (2½ seconds).
|
If the endpoint you are requesting data from is slow to respond, you may see a timeout error in the console. This can easily be fixed by specifying the `timeout` property on the offending widget. This should be an integer value, in milliseconds. By default timeout is `2500` ms (2½ seconds).
|
||||||
@ -2878,7 +3015,7 @@ Please only request widgets for services that:
|
|||||||
|
|
||||||
You can suggest a widget [here](https://git.io/Jygo3), please star the repo before submitting a ticket. If you are a monthly GitHub sponsor, I will happily build out a custom widget for any service that meets the above criteria, usually within 2 weeks of initial request.
|
You can suggest a widget [here](https://git.io/Jygo3), please star the repo before submitting a ticket. If you are a monthly GitHub sponsor, I will happily build out a custom widget for any service that meets the above criteria, usually within 2 weeks of initial request.
|
||||||
|
|
||||||
For services that are not officially supported, it is likely still possible to display data using either the [iframe](#iframe-widget), [embed](#html-embedded-widget) or [API response](#api-response) widgets. For more advanced features, like charts and action buttons, you could also build your own widget, using [this tutorial](/docs/development-guides.md#building-a-widget), it's fairly straight forward, and you can use an [existing widget](https://github.com/Lissy93/dashy/tree/master/src/components/Widgets) (or [this example](https://git.io/JygKI)) as a template.
|
For services that are not officially supported, it is likely still possible to display data using either the [iframe](#iframe-widget), [embed](#html-embedded-widget) or [API response](#api-response) widgets. For more advanced features, like charts and action buttons, you could also build your own widget, using [this tutorial](/docs/development-guides.md/#building-a-widget), it's fairly straight forward, and you can use an [existing widget](https://github.com/Lissy93/dashy/tree/master/src/components/Widgets) (or [this example](https://git.io/JygKI)) as a template.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
12
netlify.toml
@ -8,14 +8,12 @@
|
|||||||
command = "yarn build"
|
command = "yarn build"
|
||||||
publish = "dist"
|
publish = "dist"
|
||||||
functions = "services/serverless-functions"
|
functions = "services/serverless-functions"
|
||||||
environment = { NODE_VERSION = "16.13.2" }
|
|
||||||
|
|
||||||
# Site info, used for the 1-Click deploy page
|
# Environmental variables for build command
|
||||||
[template.environment]
|
[build.environment]
|
||||||
STATUSKIT_PAGE_TITLE = "Dashy"
|
NODE_VERSION = "20.11.1"
|
||||||
STATUSKIT_COMPANY_LOGO = "https://raw.githubusercontent.com/Lissy93/dashy/master/docs/assets/logo.png"
|
NODE_OPTIONS = "--openssl-legacy-provider"
|
||||||
STATUSKIT_SUPPORT_CONTACT_LINK = "https://github.com/lissy93/dashy"
|
YARN_FLAGS = "--ignore-engines"
|
||||||
STATUSKIT_RESOURCES_LINK = "https://dashy.to/docs"
|
|
||||||
|
|
||||||
# Redirect the Node endpoints to serverless functions
|
# Redirect the Node endpoints to serverless functions
|
||||||
[[redirects]]
|
[[redirects]]
|
||||||
|
33
package.json
@ -1,38 +1,40 @@
|
|||||||
{
|
{
|
||||||
"name": "Dashy",
|
"name": "dashy",
|
||||||
"version": "2.1.1",
|
"version": "3.0.1",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"main": "server",
|
"main": "server",
|
||||||
"author": "Alicia Sykes <alicia@omg.lol> (https://aliciasykes.com)",
|
"author": "Alicia Sykes <alicia@omg.lol> (https://aliciasykes.com)",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "node server",
|
"start": "node server",
|
||||||
"dev": "vue-cli-service serve",
|
"dev": "NODE_OPTIONS=--openssl-legacy-provider vue-cli-service serve",
|
||||||
"build": "vue-cli-service build",
|
"build": "NODE_OPTIONS=--openssl-legacy-provider vue-cli-service build",
|
||||||
"lint": "vue-cli-service lint",
|
"lint": "vue-cli-service lint",
|
||||||
"pm2-start": "npx pm2 start server.js",
|
"pm2-start": "npx pm2 start server.js",
|
||||||
"build-watch": "vue-cli-service build --watch --mode production",
|
"build-watch": "vue-cli-service build --watch --mode production",
|
||||||
"build-and-start": "npm-run-all --parallel build-watch start",
|
"build-and-start": "NODE_OPTIONS=--openssl-legacy-provider npm-run-all --parallel build start",
|
||||||
"validate-config": "node services/config-validator",
|
"validate-config": "node services/config-validator",
|
||||||
"health-check": "node services/healthcheck",
|
"health-check": "node services/healthcheck",
|
||||||
"dependency-audit": "npx improved-yarn-audit --ignore-dev-deps"
|
"dependency-audit": "npx improved-yarn-audit --ignore-dev-deps"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@babel/core": "^7.0.0",
|
||||||
"@formschema/native": "^2.0.0-beta.6",
|
"@formschema/native": "^2.0.0-beta.6",
|
||||||
"@sentry/tracing": "^6.17.5",
|
"@sentry/tracing": "^7.102.1",
|
||||||
"@sentry/vue": "^6.17.4",
|
"@sentry/vue": "^7.102.1",
|
||||||
"ajv": "^8.10.0",
|
"ajv": "^8.10.0",
|
||||||
"axios": "^0.27.2",
|
"axios": "^1.6.0",
|
||||||
"connect-history-api-fallback": "^1.6.0",
|
"connect-history-api-fallback": "^1.6.0",
|
||||||
"crypto-js": "^4.1.1",
|
"crypto-js": "^4.2.0",
|
||||||
"express": "^4.17.2",
|
"express": "^4.17.2",
|
||||||
|
"express-basic-auth": "^1.2.1",
|
||||||
"frappe-charts": "^1.6.2",
|
"frappe-charts": "^1.6.2",
|
||||||
"js-yaml": "^4.1.0",
|
"js-yaml": "^4.1.0",
|
||||||
"keycloak-js": "^20.0.3",
|
"keycloak-js": "^20.0.3",
|
||||||
"register-service-worker": "^1.7.2",
|
"register-service-worker": "^1.7.2",
|
||||||
"remedial": "^1.0.8",
|
"remedial": "^1.0.8",
|
||||||
"rss-parser": "3.13.0",
|
"rss-parser": "3.13.0",
|
||||||
"rsup-progress": "^3.0.0",
|
|
||||||
"simple-icons": "^10.4.0",
|
"simple-icons": "^10.4.0",
|
||||||
|
"rsup-progress": "^3.2.0",
|
||||||
"v-jsoneditor": "^1.4.5",
|
"v-jsoneditor": "^1.4.5",
|
||||||
"v-tooltip": "^2.1.3",
|
"v-tooltip": "^2.1.3",
|
||||||
"vue": "^2.7.0",
|
"vue": "^2.7.0",
|
||||||
@ -47,27 +49,28 @@
|
|||||||
"vuex": "^3.6.2"
|
"vuex": "^3.6.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@architect/sandbox": "^4.5.2",
|
|
||||||
"@babel/preset-env": "^7.17.10",
|
"@babel/preset-env": "^7.17.10",
|
||||||
"@vue/cli-plugin-babel": "^4.5.15",
|
"@vue/cli-plugin-babel": "^4.5.15",
|
||||||
"@vue/cli-plugin-eslint": "^4.5.15",
|
"@vue/cli-plugin-eslint": "^4.5.15",
|
||||||
"@vue/cli-plugin-pwa": "^4.5.15",
|
"@vue/cli-plugin-pwa": "^4.5.15",
|
||||||
"@vue/cli-service": "^4.5.15",
|
"@vue/cli-plugin-typescript": "^5.0.8",
|
||||||
|
"@vue/cli-service": "^4.5.19",
|
||||||
"@vue/eslint-config-standard": "^4.0.0",
|
"@vue/eslint-config-standard": "^4.0.0",
|
||||||
"babel-eslint": "^10.0.1",
|
"babel-eslint": "^10.0.1",
|
||||||
"eslint": "^7.24.0",
|
"copy-webpack-plugin": "6.4.0",
|
||||||
|
"eslint": "^6.8.0",
|
||||||
"eslint-config-airbnb": "^18.0.1",
|
"eslint-config-airbnb": "^18.0.1",
|
||||||
"eslint-plugin-vue": "^7.9.0",
|
"eslint-plugin-vue": "^7.9.0",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"progress-bar-webpack-plugin": "^2.1.0",
|
|
||||||
"sass": "^1.38.0",
|
"sass": "^1.38.0",
|
||||||
"sass-loader": "^7.1.0",
|
"sass-loader": "^7.1.0",
|
||||||
|
"typescript": "^5.4.4",
|
||||||
"vue-cli-plugin-yaml": "^1.0.2",
|
"vue-cli-plugin-yaml": "^1.0.2",
|
||||||
"vue-svg-loader": "^0.16.0",
|
"vue-svg-loader": "^0.16.0",
|
||||||
"vue-template-compiler": "^2.7.0"
|
"vue-template-compiler": "^2.7.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16.0.0 <18.0.0"
|
"node": ">=16.0.0 <21.6.2"
|
||||||
},
|
},
|
||||||
"eslintConfig": {
|
"eslintConfig": {
|
||||||
"root": true,
|
"root": true,
|
||||||
|
Before Width: | Height: | Size: 45 KiB |
Before Width: | Height: | Size: 45 KiB |
Before Width: | Height: | Size: 827 B |
@ -1,5 +1,5 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<!-- Dashy: Licensed under MIT, (C) 2021 Alicia Sykes <https://aliciasykes.com> -->
|
<!-- Dashy: Licensed under MIT, (C) 2024 Alicia Sykes <https://aliciasykes.com> -->
|
||||||
<!-- This is the default page, displayed while the app is still building -->
|
<!-- This is the default page, displayed while the app is still building -->
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
@ -50,6 +50,14 @@
|
|||||||
|
|
||||||
<p class="time-note" id="note">This may take a minute or two</p>
|
<p class="time-note" id="note">This may take a minute or two</p>
|
||||||
|
|
||||||
|
<div class="why-am-i-seeing-this">
|
||||||
|
<h3>Why are you seeing this screen?</h3>
|
||||||
|
<p>
|
||||||
|
The app's built files aren't yet present in the /dist directory,
|
||||||
|
so this page is displayed while we compile the source.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
<style lang="css">
|
<style lang="css">
|
||||||
/* Page Layout Styles */
|
/* Page Layout Styles */
|
||||||
body,
|
body,
|
||||||
@ -60,7 +68,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
background: #141b33;
|
background: #0d1220;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
@ -194,11 +202,30 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.hide { display: none; }
|
.hide { display: none; }
|
||||||
|
|
||||||
|
.why-am-i-seeing-this {
|
||||||
|
color: #808080a6;
|
||||||
|
font-family: Tahoma, 'Trebuchet MS', sans-serif;
|
||||||
|
max-width: 25rem;
|
||||||
|
border: 2px solid #808080a6;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 0.5rem;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 1rem;
|
||||||
|
background: #8080800d;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
.why-am-i-seeing-this h3 {
|
||||||
|
margin: 0 0 0.5rem 0;
|
||||||
|
}
|
||||||
|
.why-am-i-seeing-this p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
const refreshRate = 8000;
|
// Refresh the page every 10 seconds
|
||||||
// Refresh at interval
|
const refreshRate = 10000;
|
||||||
setTimeout(() => { location.reload(); }, refreshRate);
|
setTimeout(() => { location.reload(); }, refreshRate);
|
||||||
|
|
||||||
// Get current stage
|
// Get current stage
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Styles applied to index.html for the loading screen, prior to the app being injected */
|
/* Styles applied to index.html for the loading screen, prior to the app being injected */
|
||||||
/* Dashy - Licensed under MIT, (C) Alicia Sykes 2022 */
|
/* Dashy - Licensed under MIT, (C) Alicia Sykes 2024 */
|
||||||
|
|
||||||
body { margin: 0; }
|
body { margin: 0; }
|
||||||
#app .loading-placeholder {
|
#app .loading-placeholder {
|
||||||
|
114
server.js
@ -6,19 +6,27 @@
|
|||||||
* */
|
* */
|
||||||
|
|
||||||
/* Import built-in Node server modules */
|
/* Import built-in Node server modules */
|
||||||
|
const fs = require('fs');
|
||||||
|
const os = require('os');
|
||||||
|
const dns = require('dns');
|
||||||
const http = require('http');
|
const http = require('http');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const util = require('util');
|
const util = require('util');
|
||||||
const dns = require('dns');
|
const crypto = require('crypto');
|
||||||
const os = require('os');
|
|
||||||
|
/* Import NPM dependencies */
|
||||||
|
const yaml = require('js-yaml');
|
||||||
|
|
||||||
/* Import Express + middleware functions */
|
/* Import Express + middleware functions */
|
||||||
const express = require('express');
|
const express = require('express');
|
||||||
|
const basicAuth = require('express-basic-auth');
|
||||||
const history = require('connect-history-api-fallback');
|
const history = require('connect-history-api-fallback');
|
||||||
|
|
||||||
/* Kick of some basic checks */
|
/* Kick of some basic checks */
|
||||||
require('./services/update-checker'); // Checks if there are any updates available, prints message
|
require('./services/update-checker'); // Checks if there are any updates available, prints message
|
||||||
require('./services/config-validator'); // Include and kicks off the config file validation script
|
|
||||||
|
let config = {}; // setup the config
|
||||||
|
config = require('./services/config-validator'); // Include and kicks off the config file validation script
|
||||||
|
|
||||||
/* Include route handlers for API endpoints */
|
/* Include route handlers for API endpoints */
|
||||||
const statusCheck = require('./services/status-check'); // Used by the status check feature, uses GET
|
const statusCheck = require('./services/status-check'); // Used by the status check feature, uses GET
|
||||||
@ -27,6 +35,7 @@ const rebuild = require('./services/rebuild-app'); // A script to programmatical
|
|||||||
const systemInfo = require('./services/system-info'); // Basic system info, for resource widget
|
const systemInfo = require('./services/system-info'); // Basic system info, for resource widget
|
||||||
const sslServer = require('./services/ssl-server'); // TLS-enabled web server
|
const sslServer = require('./services/ssl-server'); // TLS-enabled web server
|
||||||
const corsProxy = require('./services/cors-proxy'); // Enables API requests to CORS-blocked services
|
const corsProxy = require('./services/cors-proxy'); // Enables API requests to CORS-blocked services
|
||||||
|
const getUser = require('./services/get-user'); // Enables server side user lookup
|
||||||
|
|
||||||
/* Helper functions, and default config */
|
/* Helper functions, and default config */
|
||||||
const printMessage = require('./services/print-message'); // Function to print welcome msg on start
|
const printMessage = require('./services/print-message'); // Function to print welcome msg on start
|
||||||
@ -35,12 +44,15 @@ const ENDPOINTS = require('./src/utils/defaults').serviceEndpoints; // API endpo
|
|||||||
/* Checks if app is running within a container, from env var */
|
/* Checks if app is running within a container, from env var */
|
||||||
const isDocker = !!process.env.IS_DOCKER;
|
const isDocker = !!process.env.IS_DOCKER;
|
||||||
|
|
||||||
/* Checks env var for port. If undefined, will use Port 80 for Docker, or 4000 for metal */
|
/* Checks env var for port. If undefined, will use Port 8080 for Docker, or 4000 for metal */
|
||||||
const port = process.env.PORT || (isDocker ? 80 : 4000);
|
const port = process.env.PORT || (isDocker ? 8080 : 4000);
|
||||||
|
|
||||||
/* Checks env var for host. If undefined, will use 0.0.0.0 */
|
/* Checks env var for host. If undefined, will use 0.0.0.0 */
|
||||||
const host = process.env.HOST || '0.0.0.0';
|
const host = process.env.HOST || '0.0.0.0';
|
||||||
|
|
||||||
|
/* Indicates for the webpack config, that running as a server */
|
||||||
|
process.env.IS_SERVER = 'True';
|
||||||
|
|
||||||
/* Attempts to get the users local IP, used as part of welcome message */
|
/* Attempts to get the users local IP, used as part of welcome message */
|
||||||
const getLocalIp = () => {
|
const getLocalIp = () => {
|
||||||
const dnsLookup = util.promisify(dns.lookup);
|
const dnsLookup = util.promisify(dns.lookup);
|
||||||
@ -55,7 +67,7 @@ const printWelcomeMessage = () => {
|
|||||||
console.log(printMessage(ip, port, isDocker)); // eslint-disable-line no-console
|
console.log(printMessage(ip, port, isDocker)); // eslint-disable-line no-console
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Fetching info for welcome message failed, print simple msg instead
|
// No clue what could of gone wrong here, but print fallback message if above failed
|
||||||
console.log(`Dashy server has started (${port})`); // eslint-disable-line no-console
|
console.log(`Dashy server has started (${port})`); // eslint-disable-line no-console
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -65,18 +77,72 @@ const printWarning = (msg, error) => {
|
|||||||
console.warn(`\x1b[103m\x1b[34m${msg}\x1b[0m\n`, error || ''); // eslint-disable-line no-console
|
console.warn(`\x1b[103m\x1b[34m${msg}\x1b[0m\n`, error || ''); // eslint-disable-line no-console
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Load appConfig.auth.users from config (if present) for authorization purposes */
|
||||||
|
function loadUserConfig() {
|
||||||
|
try {
|
||||||
|
const filePath = path.join(__dirname, process.env.USER_DATA_DIR || 'user-data', 'conf.yml');
|
||||||
|
const fileContents = fs.readFileSync(filePath, 'utf8');
|
||||||
|
const data = yaml.load(fileContents);
|
||||||
|
return data?.appConfig?.auth?.users || null;
|
||||||
|
} catch (e) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If HTTP auth is enabled, and no username/password are pre-set, then check passed credentials */
|
||||||
|
function customAuthorizer(username, password) {
|
||||||
|
const sha256 = (input) => crypto.createHash('sha256').update(input).digest('hex').toUpperCase();
|
||||||
|
const generateUserToken = (user) => {
|
||||||
|
if (!user.user || (!user.hash && !user.password)) return '';
|
||||||
|
const strAndUpper = (input) => input.toString().toUpperCase();
|
||||||
|
const passwordHash = user.hash || sha256(process.env[user.password]);
|
||||||
|
const sha = sha256(strAndUpper(user.user) + strAndUpper(passwordHash));
|
||||||
|
return strAndUpper(sha);
|
||||||
|
};
|
||||||
|
if (password.startsWith('Bearer ')) {
|
||||||
|
const token = password.slice('Bearer '.length);
|
||||||
|
const users = loadUserConfig();
|
||||||
|
return users.some(user => generateUserToken(user) === token);
|
||||||
|
} else {
|
||||||
|
const users = loadUserConfig();
|
||||||
|
const userHash = sha256(password);
|
||||||
|
return users.some(user => (
|
||||||
|
user.user.toLowerCase() === username.toLowerCase() && user.hash.toUpperCase() === userHash
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If a username and password are set, setup auth for config access, otherwise skip */
|
||||||
|
function getBasicAuthMiddleware() {
|
||||||
|
const configUsers = process.env.ENABLE_HTTP_AUTH ? loadUserConfig() : null;
|
||||||
|
const { BASIC_AUTH_USERNAME, BASIC_AUTH_PASSWORD } = process.env;
|
||||||
|
if (BASIC_AUTH_USERNAME && BASIC_AUTH_PASSWORD) {
|
||||||
|
return basicAuth({
|
||||||
|
users: { [BASIC_AUTH_USERNAME]: BASIC_AUTH_PASSWORD },
|
||||||
|
challenge: true,
|
||||||
|
unauthorizedResponse: () => 'Unauthorized - Incorrect username or password',
|
||||||
|
});
|
||||||
|
} else if ((configUsers && configUsers.length > 0)) {
|
||||||
|
return basicAuth({
|
||||||
|
authorizer: customAuthorizer,
|
||||||
|
challenge: true,
|
||||||
|
unauthorizedResponse: () => 'Unauthorized - Incorrect token',
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return (req, res, next) => next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const protectConfig = getBasicAuthMiddleware();
|
||||||
|
|
||||||
/* A middleware function for Connect, that filters requests based on method type */
|
/* A middleware function for Connect, that filters requests based on method type */
|
||||||
const method = (m, mw) => (req, res, next) => (req.method === m ? mw(req, res, next) : next());
|
const method = (m, mw) => (req, res, next) => (req.method === m ? mw(req, res, next) : next());
|
||||||
|
|
||||||
const app = express()
|
const app = express()
|
||||||
// Load SSL redirection middleware
|
// Load SSL redirection middleware
|
||||||
.use(sslServer.middleware)
|
.use(sslServer.middleware)
|
||||||
// Serves up static files
|
|
||||||
.use(express.static(path.join(__dirname, 'dist')))
|
|
||||||
.use(express.static(path.join(__dirname, 'public'), { index: 'initialization.html' }))
|
|
||||||
// Load middlewares for parsing JSON, and supporting HTML5 history routing
|
// Load middlewares for parsing JSON, and supporting HTML5 history routing
|
||||||
.use(express.json({ limit: '1mb' }))
|
.use(express.json({ limit: '1mb' }))
|
||||||
.use(history())
|
|
||||||
// GET endpoint to run status of a given URL with GET request
|
// GET endpoint to run status of a given URL with GET request
|
||||||
.use(ENDPOINTS.statusCheck, (req, res) => {
|
.use(ENDPOINTS.statusCheck, (req, res) => {
|
||||||
try {
|
try {
|
||||||
@ -87,10 +153,11 @@ const app = express()
|
|||||||
printWarning(`Error running status check for ${req.url}\n`, e);
|
printWarning(`Error running status check for ${req.url}\n`, e);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
// POST Endpoint used to save config, by writing conf.yml to disk
|
// POST Endpoint used to save config, by writing config file to disk
|
||||||
.use(ENDPOINTS.save, method('POST', (req, res) => {
|
.use(ENDPOINTS.save, method('POST', (req, res) => {
|
||||||
try {
|
try {
|
||||||
saveConfig(req.body, (results) => { res.end(results); });
|
saveConfig(req.body, (results) => { res.end(results); });
|
||||||
|
config = req.body.config; // update the config
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
printWarning('Error writing config file to disk', e);
|
printWarning('Error writing config file to disk', e);
|
||||||
res.end(JSON.stringify({ success: false, message: e }));
|
res.end(JSON.stringify({ success: false, message: e }));
|
||||||
@ -122,8 +189,29 @@ const app = express()
|
|||||||
res.end(JSON.stringify({ success: false, message: e }));
|
res.end(JSON.stringify({ success: false, message: e }));
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
// GET fallback endpoint
|
// GET endpoint to return user info
|
||||||
.get('*', (req, res) => res.sendFile(path.join(__dirname, 'dist', 'index.html')));
|
.use(ENDPOINTS.getUser, (req, res) => {
|
||||||
|
try {
|
||||||
|
const user = getUser(config, req);
|
||||||
|
res.end(JSON.stringify(user));
|
||||||
|
} catch (e) {
|
||||||
|
res.end(JSON.stringify({ success: false, message: e }));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// Middleware to serve any .yml files in USER_DATA_DIR with optional protection
|
||||||
|
.get('/*.yml', protectConfig, (req, res) => {
|
||||||
|
const ymlFile = req.path.split('/').pop();
|
||||||
|
res.sendFile(path.join(__dirname, process.env.USER_DATA_DIR || 'user-data', ymlFile));
|
||||||
|
})
|
||||||
|
// Serves up static files
|
||||||
|
.use(express.static(path.join(__dirname, process.env.USER_DATA_DIR || 'user-data')))
|
||||||
|
.use(express.static(path.join(__dirname, 'dist')))
|
||||||
|
.use(express.static(path.join(__dirname, 'public'), { index: 'initialization.html' }))
|
||||||
|
.use(history())
|
||||||
|
// If no other route is matched, serve up the index.html with a 404 status
|
||||||
|
.use((req, res) => {
|
||||||
|
res.status(404).sendFile(path.join(__dirname, 'dist', 'index.html'));
|
||||||
|
});
|
||||||
|
|
||||||
/* Create HTTP server from app on port, and print welcome message */
|
/* Create HTTP server from app on port, and print welcome message */
|
||||||
http.createServer(app)
|
http.createServer(app)
|
||||||
|
@ -11,7 +11,7 @@ const schema = require('../src/utils/ConfigSchema.json');
|
|||||||
|
|
||||||
/* Tell AJV to use strict mode, and report all errors */
|
/* Tell AJV to use strict mode, and report all errors */
|
||||||
const validatorOptions = {
|
const validatorOptions = {
|
||||||
strict: true,
|
strict: false,
|
||||||
allowUnionTypes: true,
|
allowUnionTypes: true,
|
||||||
allErrors: true,
|
allErrors: true,
|
||||||
};
|
};
|
||||||
@ -98,11 +98,14 @@ const printFileReadError = (e) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let config = {};
|
||||||
|
|
||||||
try { // Try to open and parse the YAML file
|
try { // Try to open and parse the YAML file
|
||||||
const config = yaml.load(fs.readFileSync('./public/conf.yml', 'utf8'));
|
config = yaml.load(fs.readFileSync(`./${process.env.USER_DATA_DIR || 'user-data'}/conf.yml`, 'utf8'));
|
||||||
validate(config);
|
validate(config);
|
||||||
} catch (e) { // Something went very wrong...
|
} catch (e) { // Something went very wrong...
|
||||||
setIsValidVariable(false);
|
setIsValidVariable(false);
|
||||||
logToConsole(bigError());
|
logToConsole(bigError());
|
||||||
printFileReadError(e);
|
printFileReadError(e);
|
||||||
}
|
}
|
||||||
|
module.exports = config;
|
||||||
|
15
services/get-user.js
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
module.exports = (config, req) => {
|
||||||
|
try {
|
||||||
|
if (config.appConfig.auth.enableHeaderAuth) {
|
||||||
|
const { userHeader } = config.appConfig.auth.headerAuth;
|
||||||
|
const { proxyWhitelist } = config.appConfig.auth.headerAuth;
|
||||||
|
if (proxyWhitelist.includes(req.socket.remoteAddress)) {
|
||||||
|
return { success: true, user: req.headers[userHeader.toLowerCase()] };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('Error get-user: ', e);
|
||||||
|
return { success: false };
|
||||||
|
}
|
||||||
|
};
|
@ -6,11 +6,17 @@
|
|||||||
|
|
||||||
const isSsl = !!process.env.SSL_PRIV_KEY_PATH && !!process.env.SSL_PUB_KEY_PATH;
|
const isSsl = !!process.env.SSL_PRIV_KEY_PATH && !!process.env.SSL_PUB_KEY_PATH;
|
||||||
|
|
||||||
|
// eslint-disable-next-line import/no-dynamic-require
|
||||||
const http = require(isSsl ? 'https' : 'http');
|
const http = require(isSsl ? 'https' : 'http');
|
||||||
|
|
||||||
/* Location of the server to test */
|
/* Location of the server to test */
|
||||||
const isDocker = !!process.env.IS_DOCKER;
|
const isDocker = !!process.env.IS_DOCKER;
|
||||||
const port = isSsl ? (process.env.SSL_PORT || (isDocker ? 443 : 4001)) : (process.env.PORT || (isDocker ? 80 : 4000));
|
|
||||||
|
/* Get the port to use (depending on, if docker, if SSL) */
|
||||||
|
const sslPort = process.env.SSL_PORT || (isDocker ? 443 : 4001);
|
||||||
|
const normalPort = process.env.PORT || (isDocker ? 8080 : 4000);
|
||||||
|
const port = isSsl ? sslPort : normalPort;
|
||||||
|
|
||||||
const host = process.env.HOST || '0.0.0.0';
|
const host = process.env.HOST || '0.0.0.0';
|
||||||
const timeout = 2000;
|
const timeout = 2000;
|
||||||
|
|
||||||
@ -18,7 +24,9 @@ const agent = new http.Agent({
|
|||||||
rejectUnauthorized: false, // Allow self-signed certificates
|
rejectUnauthorized: false, // Allow self-signed certificates
|
||||||
});
|
});
|
||||||
|
|
||||||
const requestOptions = { host, port, timeout, agent };
|
const requestOptions = {
|
||||||
|
host, port, timeout, agent,
|
||||||
|
};
|
||||||
|
|
||||||
const startTime = new Date(); // Initialize timestamp to calculate time taken
|
const startTime = new Date(); // Initialize timestamp to calculate time taken
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ module.exports = (ip, port, isDocker) => {
|
|||||||
} else {
|
} else {
|
||||||
// Prepare message for users running app on bare metal
|
// Prepare message for users running app on bare metal
|
||||||
msg = `${chars.GREEN}┏${line(75)}┓${chars.BR}`
|
msg = `${chars.GREEN}┏${line(75)}┓${chars.BR}`
|
||||||
+ `┃ ${chars.CYAN}Welcome to Dashy! 🚀${blanks(55)}${chars.GREEN}┃${chars.BR}`
|
+ `┃ ${chars.CYAN}Welcome to Dashy! 🚀${blanks(54)}${chars.GREEN}┃${chars.BR}`
|
||||||
+ `┃ ${chars.CYAN}Your new dashboard is now up and running at ${chars.BRIGHT}`
|
+ `┃ ${chars.CYAN}Your new dashboard is now up and running at ${chars.BRIGHT}`
|
||||||
+ `http://${ip}:${port}${chars.RESET}${blanks(18 - ip.length)}${chars.GREEN}┃${chars.BR}`
|
+ `http://${ip}:${port}${chars.RESET}${blanks(18 - ip.length)}${chars.GREEN}┃${chars.BR}`
|
||||||
+ `┗${line(75)}┛${chars.BR}${chars.BR}${chars.RESET}`;
|
+ `┗${line(75)}┛${chars.BR}${chars.BR}${chars.RESET}`;
|
||||||
|
@ -14,19 +14,24 @@ module.exports = async (newConfig, render) => {
|
|||||||
return configObj.filename.replaceAll('/', '').replaceAll('..', '');
|
return configObj.filename.replaceAll('/', '').replaceAll('..', '');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Path to config file (with navigational characters stripped)
|
||||||
const usersFileName = makeSafeFileName(newConfig);
|
const usersFileName = makeSafeFileName(newConfig);
|
||||||
|
|
||||||
|
// Path to user data directory
|
||||||
|
const userDataDirectory = process.env.USER_DATA_DIR || './user-data/';
|
||||||
|
|
||||||
// Define constants for the config file
|
// Define constants for the config file
|
||||||
const settings = {
|
const settings = {
|
||||||
defaultLocation: './public/',
|
defaultLocation: userDataDirectory,
|
||||||
|
backupLocation: process.env.BACKUP_DIR || path.join(userDataDirectory, 'config-backups'),
|
||||||
defaultFile: 'conf.yml',
|
defaultFile: 'conf.yml',
|
||||||
filename: 'conf',
|
filename: 'conf',
|
||||||
backupDenominator: '.backup.yml',
|
backupDenominator: '.backup.yml',
|
||||||
};
|
};
|
||||||
|
|
||||||
// Make the full file name and path to save the backup config file
|
// Make the full file name and path to save the backup config file
|
||||||
const backupFilePath = path.normalize(process.env.BACKUP_DIR || settings.defaultLocation)
|
const backupFilePath = `${path.normalize(settings.backupLocation)
|
||||||
+ `/${usersFileName || settings.filename}-`
|
}/${usersFileName || settings.filename}-`
|
||||||
+ `${Math.round(new Date() / 1000)}${settings.backupDenominator}`;
|
+ `${Math.round(new Date() / 1000)}${settings.backupDenominator}`;
|
||||||
|
|
||||||
// The path where the main conf.yml should be read and saved to
|
// The path where the main conf.yml should be read and saved to
|
||||||
@ -45,15 +50,20 @@ module.exports = async (newConfig, render) => {
|
|||||||
message: !success ? errorMsg : getSuccessMessage(),
|
message: !success ? errorMsg : getSuccessMessage(),
|
||||||
});
|
});
|
||||||
|
|
||||||
// Makes a backup of the existing config file
|
// Create a backup of current config, and if backup dir doesn't yet exist, create it
|
||||||
await fsPromises
|
await fsPromises
|
||||||
.copyFile(defaultFilePath, backupFilePath)
|
.mkdir(settings.backupLocation, { recursive: true })
|
||||||
.catch((error) => render(getRenderMessage(false, `Unable to backup conf.yml: ${error}`)));
|
.then(() => fsPromises.copyFile(defaultFilePath, backupFilePath))
|
||||||
|
.catch((error) => render(
|
||||||
|
getRenderMessage(false, `Unable to backup ${settings.defaultFile}: ${error}`),
|
||||||
|
));
|
||||||
|
|
||||||
// Writes the new content to the conf.yml file
|
// Writes the new content to the conf.yml file
|
||||||
await fsPromises
|
await fsPromises
|
||||||
.writeFile(defaultFilePath, newConfig.config.toString(), writeFileOptions)
|
.writeFile(defaultFilePath, newConfig.config.toString(), writeFileOptions)
|
||||||
.catch((error) => render(getRenderMessage(false, `Unable to write to conf.yml: ${error}`)));
|
.catch((error) => render(
|
||||||
|
getRenderMessage(false, `Unable to write to ${settings.defaultFile}: ${error}`),
|
||||||
|
));
|
||||||
|
|
||||||
// If successful, then render hasn't yet been called- call it
|
// If successful, then render hasn't yet been called- call it
|
||||||
await render(getRenderMessage(true));
|
await render(getRenderMessage(true));
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
<LoadingScreen :isLoading="isLoading" v-if="shouldShowSplash" />
|
<LoadingScreen :isLoading="isLoading" v-if="shouldShowSplash" />
|
||||||
<Header :pageInfo="pageInfo" />
|
<Header :pageInfo="pageInfo" />
|
||||||
<router-view v-if="!isFetching" />
|
<router-view v-if="!isFetching" />
|
||||||
|
<CriticalError v-if="hasCriticalError" />
|
||||||
<Footer :text="footerText" v-if="visibleComponents.footer && !isFetching" />
|
<Footer :text="footerText" v-if="visibleComponents.footer && !isFetching" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -12,6 +13,7 @@
|
|||||||
import Header from '@/components/PageStrcture/Header.vue';
|
import Header from '@/components/PageStrcture/Header.vue';
|
||||||
import Footer from '@/components/PageStrcture/Footer.vue';
|
import Footer from '@/components/PageStrcture/Footer.vue';
|
||||||
import EditModeTopBanner from '@/components/InteractiveEditor/EditModeTopBanner.vue';
|
import EditModeTopBanner from '@/components/InteractiveEditor/EditModeTopBanner.vue';
|
||||||
|
import CriticalError from '@/components/PageStrcture/CriticalError.vue';
|
||||||
import LoadingScreen from '@/components/PageStrcture/LoadingScreen.vue';
|
import LoadingScreen from '@/components/PageStrcture/LoadingScreen.vue';
|
||||||
import { welcomeMsg } from '@/utils/CoolConsole';
|
import { welcomeMsg } from '@/utils/CoolConsole';
|
||||||
import ErrorHandler from '@/utils/ErrorHandler';
|
import ErrorHandler from '@/utils/ErrorHandler';
|
||||||
@ -29,6 +31,7 @@ export default {
|
|||||||
Footer,
|
Footer,
|
||||||
LoadingScreen,
|
LoadingScreen,
|
||||||
EditModeTopBanner,
|
EditModeTopBanner,
|
||||||
|
CriticalError,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@ -64,7 +67,7 @@ export default {
|
|||||||
return this.$store.getters.pageInfo;
|
return this.$store.getters.pageInfo;
|
||||||
},
|
},
|
||||||
sections() {
|
sections() {
|
||||||
return this.$store.getters.pageInfo;
|
return this.$store.getters.sections;
|
||||||
},
|
},
|
||||||
visibleComponents() {
|
visibleComponents() {
|
||||||
return this.$store.getters.visibleComponents;
|
return this.$store.getters.visibleComponents;
|
||||||
@ -72,6 +75,9 @@ export default {
|
|||||||
isEditMode() {
|
isEditMode() {
|
||||||
return this.$store.state.editMode;
|
return this.$store.state.editMode;
|
||||||
},
|
},
|
||||||
|
hasCriticalError() {
|
||||||
|
return this.$store.state.criticalError;
|
||||||
|
},
|
||||||
subPageClassName() {
|
subPageClassName() {
|
||||||
const currentSubPage = this.$store.state.currentConfigInfo;
|
const currentSubPage = this.$store.state.currentConfigInfo;
|
||||||
return (currentSubPage && currentSubPage.pageId) ? currentSubPage.pageId : '';
|
return (currentSubPage && currentSubPage.pageId) ? currentSubPage.pageId : '';
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"home": {
|
"home": {
|
||||||
"no-results": "لا نتائج للبحث",
|
"no-results": "لا نتائج للبحث",
|
||||||
"no-data": "لم يتم تكوين بيانات"
|
"no-data": "لا يوجد بيانات"
|
||||||
},
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"search-label": "بحث",
|
"search-label": "بحث",
|
||||||
@ -33,11 +33,11 @@
|
|||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"main-tab": "القائمة الرئيسية",
|
"main-tab": "القائمة الرئيسية",
|
||||||
"view-config-tab": "مشاهدة ملف Config",
|
"view-config-tab": "مشاهده ملف الإعدادات",
|
||||||
"edit-config-tab": "تحرير التكوين",
|
"edit-config-tab": "تغير ملف الاع",
|
||||||
"custom-css-tab": "الأنماط المخصصة",
|
"custom-css-tab": "الأنماط المخصصة",
|
||||||
"heading": "خيارات الإعداد",
|
"heading": "خيارات الإعداد",
|
||||||
"download-config-button": "تنزيل Config",
|
"download-config-button": "تنزيل ملف الإعدادات",
|
||||||
"edit-config-button": "تحرير التكوين",
|
"edit-config-button": "تحرير التكوين",
|
||||||
"edit-css-button": "تحرير CSS مخصص",
|
"edit-css-button": "تحرير CSS مخصص",
|
||||||
"cloud-sync-button": "قم بتمكين Cloud Sync",
|
"cloud-sync-button": "قم بتمكين Cloud Sync",
|
||||||
@ -84,7 +84,7 @@
|
|||||||
"sign-in-welcome": "مرحبًا {username}!"
|
"sign-in-welcome": "مرحبًا {username}!"
|
||||||
},
|
},
|
||||||
"updates": {
|
"updates": {
|
||||||
"app-version-note": "نسخة متهورة",
|
"app-version-note": "ملاحظة نسخة التطبيق",
|
||||||
"up-to-date": "حتى الآن",
|
"up-to-date": "حتى الآن",
|
||||||
"out-of-date": "التحديث متاح",
|
"out-of-date": "التحديث متاح",
|
||||||
"unsupported-version-l1": "أنت تستخدم إصدارًا غير مدعوم من Dashy",
|
"unsupported-version-l1": "أنت تستخدم إصدارًا غير مدعوم من Dashy",
|
||||||
|
@ -1,20 +1,21 @@
|
|||||||
{
|
{
|
||||||
"home":
|
"home": {
|
||||||
{
|
|
||||||
"no-results": "keine Suchergebnisse",
|
"no-results": "keine Suchergebnisse",
|
||||||
"no-data": "keine Daten konfiguriert",
|
"no-data": "keine Daten konfiguriert",
|
||||||
"no-items-section": "Noch keine Elemente zum Anzeigen"
|
"no-items-section": "Noch keine Elemente zum Anzeigen"
|
||||||
},
|
},
|
||||||
"search":
|
"search": {
|
||||||
{
|
|
||||||
"search-label": "Suche",
|
"search-label": "Suche",
|
||||||
"search-placeholder": "Tippen um zu filtern",
|
"search-placeholder": "Tippe um zu filtern",
|
||||||
"clear-search-tooltip": "Suchfeld leeren",
|
"clear-search-tooltip": "Suchfeld leeren",
|
||||||
"enter-to-search-web": "Drücke Enter um das Internet zu durchsuchen"
|
"enter-to-search-web": "Drücke Enter um das Internet zu durchsuchen"
|
||||||
},
|
},
|
||||||
"login":
|
"splash-screen": {
|
||||||
{
|
"loading": "Lädt"
|
||||||
|
},
|
||||||
|
"login": {
|
||||||
"title": "Dashy",
|
"title": "Dashy",
|
||||||
|
"guest-label": "Gastzugriff",
|
||||||
"username-label": "Benutzername",
|
"username-label": "Benutzername",
|
||||||
"password-label": "Passwort",
|
"password-label": "Passwort",
|
||||||
"login-button": "Anmelden",
|
"login-button": "Anmelden",
|
||||||
@ -34,10 +35,47 @@
|
|||||||
"already-logged-in-text": "Angemeldet als",
|
"already-logged-in-text": "Angemeldet als",
|
||||||
"proceed-to-dashboard": "Zum Dashboard fortfahren",
|
"proceed-to-dashboard": "Zum Dashboard fortfahren",
|
||||||
"log-out-button": "Abmelden",
|
"log-out-button": "Abmelden",
|
||||||
"proceed-guest-button": "Als Gast fortfahren"
|
"proceed-guest-button": "Als Gast fortfahren",
|
||||||
|
"guest-intro-1": "Diese Instanz hat Gastzugriffe aktiviert",
|
||||||
|
"guest-intro-2": "Gäste haben lesenden Zugriff auf Dashboards, können also keine Veränderungen auf die Festplatte schreiben.",
|
||||||
|
"error": "Error",
|
||||||
|
"error-no-user-configured": "Authentifizierung ist nicht aktiviert, oder es sind keine Benutzer konfiguriert",
|
||||||
|
"error-go-home-button": "Geh nach Hause",
|
||||||
|
"logged-in-guest": "Als Gast eingeloggt, Umleitung...",
|
||||||
|
"error-guest-access": "Gastzugriff nicht erlaubt"
|
||||||
},
|
},
|
||||||
"config":
|
"app-info": {
|
||||||
{
|
"title": "App Info",
|
||||||
|
"error-log": "Fehlerprotokoll",
|
||||||
|
"no-errors": "Keine kürzlichen Fehler erkannt",
|
||||||
|
"help-support": "Hilfe & Support",
|
||||||
|
"help-support-description": "Um beim Betrieb oder der Konfiguration von Dashy Hilfe zu bekommen, siehe die",
|
||||||
|
"help-support-discussions": "Diskussionen",
|
||||||
|
"support-dashy": "Dashy unterstützen",
|
||||||
|
"support-dashy-description": "Für Wege, sich zu beteiligen, besuchen Sie die",
|
||||||
|
"support-dashy-link": "Contributions Seite",
|
||||||
|
"report-bug": "Melde einen Fehler",
|
||||||
|
"report-bug-description": "Wenn Sie glauben, einen Fehler gefunden zu haben, dann bitte",
|
||||||
|
"report-bug-link": "öffne ein Issue",
|
||||||
|
"more-info": "Mehr Informationen",
|
||||||
|
"source": "Quellcode",
|
||||||
|
"documentation": "Dokumentation",
|
||||||
|
"privacy-and-security": "Datenschutz & Sicherheit",
|
||||||
|
"privacy-and-security-l1": "Für eine Übersicht, wie Dashy mit Ihren Daten umgeht, siehe die",
|
||||||
|
"privacy-and-security-privacy-policy": "Datenschutzerklärung",
|
||||||
|
"privacy-and-security-advice": "Für Anleitung, um Ihr Dashboard zu sichern, konsultieren Sie die",
|
||||||
|
"privacy-and-security-advice-link": "Management Dokumentation",
|
||||||
|
"privacy-and-security-security-issue": "Wenn Sie glauben, eine mögliche Sicherheitslücke gefunden zu haben, melde sie wie beschrieben in unserer",
|
||||||
|
"privacy-and-security-security-policy": "Security Policy",
|
||||||
|
"license": "Lizenz",
|
||||||
|
"license-under": "Lizensiert unter",
|
||||||
|
"licence-third-party": "Für Lizenzen von Drittanbietermodulen, siehe",
|
||||||
|
"licence-third-party-link": "Legal",
|
||||||
|
"list-contributors": "Für eine vollstandige Liste aller Beteiligten und Dank, siehe",
|
||||||
|
"list-contributors-link": "Credits",
|
||||||
|
"version": "Version"
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
"main-tab": "Hauptmenü",
|
"main-tab": "Hauptmenü",
|
||||||
"view-config-tab": "Konfiguration",
|
"view-config-tab": "Konfiguration",
|
||||||
"edit-config-tab": "Konfiguration bearbeiten",
|
"edit-config-tab": "Konfiguration bearbeiten",
|
||||||
@ -51,6 +89,8 @@
|
|||||||
"rebuild-app-button": "Anwendung neu kompilieren",
|
"rebuild-app-button": "Anwendung neu kompilieren",
|
||||||
"change-language-button": "App-Sprache ändern",
|
"change-language-button": "App-Sprache ändern",
|
||||||
"reset-settings-button": "lokale Einstellungen zurücksetzen",
|
"reset-settings-button": "lokale Einstellungen zurücksetzen",
|
||||||
|
"disabled-note": "Einige Konfigurationsoptionen wurden vom Administrator deaktivert",
|
||||||
|
"small-screen-note": "Sie benutzen einen sehr kleinen Bildschirm. Einige Seiten in diesem Menü sind dafür möglicherweise nicht ideal.",
|
||||||
"app-info-button": "App Informationen",
|
"app-info-button": "App Informationen",
|
||||||
"backup-note": "Es wird empfohlen ein Backup der Konfiguration zu erstellen bevor Änderungen durchgeführt werden.",
|
"backup-note": "Es wird empfohlen ein Backup der Konfiguration zu erstellen bevor Änderungen durchgeführt werden.",
|
||||||
"reset-config-msg-l1": "Dadurch werden alle Benutzereinstellungen aus dem lokalen Speicher entfernt, dies hat jedoch keine Auswirkungen auf Ihre Datei 'conf.yml'.",
|
"reset-config-msg-l1": "Dadurch werden alle Benutzereinstellungen aus dem lokalen Speicher entfernt, dies hat jedoch keine Auswirkungen auf Ihre Datei 'conf.yml'.",
|
||||||
@ -65,7 +105,11 @@
|
|||||||
"css-note-label": "Bemerkung",
|
"css-note-label": "Bemerkung",
|
||||||
"css-note-l1": "Sie müssen die Seite aktualisieren, damit Ihre Änderungen wirksam werden.",
|
"css-note-l1": "Sie müssen die Seite aktualisieren, damit Ihre Änderungen wirksam werden.",
|
||||||
"css-note-l2": "Stilüberschreibungen werden nur lokal gespeichert, daher wird empfohlen vorher eine Kopie Ihres CSS zu erstellen.",
|
"css-note-l2": "Stilüberschreibungen werden nur lokal gespeichert, daher wird empfohlen vorher eine Kopie Ihres CSS zu erstellen.",
|
||||||
"css-note-l3": "Um alle benutzerdefinierten Stile zu entfernen löschen Sie den Inhalt und klicken Sie auf Änderungen speichern."
|
"css-note-l3": "Um alle benutzerdefinierten Stile zu entfernen löschen Sie den Inhalt und klicken Sie auf Änderungen speichern.",
|
||||||
|
"custom-css": {
|
||||||
|
"title": "Eigenes CSS",
|
||||||
|
"base-theme": "Basisdesign"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"alternate-views": {
|
"alternate-views": {
|
||||||
"alternate-view-heading": "Ansicht wechseln",
|
"alternate-view-heading": "Ansicht wechseln",
|
||||||
@ -73,8 +117,7 @@
|
|||||||
"workspace": "Arbeitsplatz",
|
"workspace": "Arbeitsplatz",
|
||||||
"minimal": "Minimal"
|
"minimal": "Minimal"
|
||||||
},
|
},
|
||||||
"settings":
|
"settings": {
|
||||||
{
|
|
||||||
"theme-label": "Design",
|
"theme-label": "Design",
|
||||||
"layout-label": "Layout",
|
"layout-label": "Layout",
|
||||||
"layout-auto": "Auto",
|
"layout-auto": "Auto",
|
||||||
@ -88,25 +131,24 @@
|
|||||||
"config-launcher-tooltip": "Konfiguration aktualisieren",
|
"config-launcher-tooltip": "Konfiguration aktualisieren",
|
||||||
"sign-out-tooltip": "Abmelden",
|
"sign-out-tooltip": "Abmelden",
|
||||||
"sign-in-tooltip": "Anmelden",
|
"sign-in-tooltip": "Anmelden",
|
||||||
"sign-in-welcome": "Hallo {username}!"
|
"sign-in-welcome": "Hallo {username}!",
|
||||||
|
"hide": "Verstecke",
|
||||||
|
"open": "Öffne"
|
||||||
},
|
},
|
||||||
"updates":
|
"updates": {
|
||||||
{
|
|
||||||
"app-version-note": "Dashy Version",
|
"app-version-note": "Dashy Version",
|
||||||
"up-to-date": "Aktuell",
|
"up-to-date": "Aktuell",
|
||||||
"out-of-date": "Update verfügbar",
|
"out-of-date": "Update verfügbar",
|
||||||
"unsupported-version-l1": "Sie verwenden eine nicht unterstützte Version von Dashy",
|
"unsupported-version-l1": "Sie verwenden eine nicht unterstützte Version von Dashy",
|
||||||
"unsupported-version-l2": "Für die beste Erfahrung und aktuelle Sicherheitspatches aktualisieren Sie bitte auf"
|
"unsupported-version-l2": "Für die beste Erfahrung und aktuelle Sicherheitspatches aktualisieren Sie bitte auf"
|
||||||
},
|
},
|
||||||
"language-switcher":
|
"language-switcher": {
|
||||||
{
|
|
||||||
"title": "Applikationssprache ändern",
|
"title": "Applikationssprache ändern",
|
||||||
"dropdown-label": "Sprache auswählen",
|
"dropdown-label": "Sprache auswählen",
|
||||||
"save-button": "Speichern",
|
"save-button": "Speichern",
|
||||||
"success-msg": "Sprache geändert auf"
|
"success-msg": "Sprache geändert auf"
|
||||||
},
|
},
|
||||||
"theme-maker":
|
"theme-maker": {
|
||||||
{
|
|
||||||
"title": "Design Konfigurator",
|
"title": "Design Konfigurator",
|
||||||
"export-button": "Benutzerdefinierte Variablen exportieren",
|
"export-button": "Benutzerdefinierte Variablen exportieren",
|
||||||
"reset-button": "CSS zurücksetzen für",
|
"reset-button": "CSS zurücksetzen für",
|
||||||
@ -118,8 +160,7 @@
|
|||||||
"copied-toast": "Designdaten für {theme} wurden in die Zwischenablage kopiert.",
|
"copied-toast": "Designdaten für {theme} wurden in die Zwischenablage kopiert.",
|
||||||
"reset-toast": "Benutzerdefinierte Farben für {theme} wurden entfernt"
|
"reset-toast": "Benutzerdefinierte Farben für {theme} wurden entfernt"
|
||||||
},
|
},
|
||||||
"config-editor":
|
"config-editor": {
|
||||||
{
|
|
||||||
"save-location-label": "Speicherort",
|
"save-location-label": "Speicherort",
|
||||||
"location-local-label": "Lokal anwenden",
|
"location-local-label": "Lokal anwenden",
|
||||||
"location-disk-label": "Änderungen in die Konfigurationsdatei schreiben",
|
"location-disk-label": "Änderungen in die Konfigurationsdatei schreiben",
|
||||||
@ -139,13 +180,12 @@
|
|||||||
"warning-msg-validation": "Validierungswarnung",
|
"warning-msg-validation": "Validierungswarnung",
|
||||||
"not-admin-note": "Änderungen können nicht auf die Festplatte gespeichert werden, da Sie nicht als Administrator angemeldet sind"
|
"not-admin-note": "Änderungen können nicht auf die Festplatte gespeichert werden, da Sie nicht als Administrator angemeldet sind"
|
||||||
},
|
},
|
||||||
"app-rebuild":
|
"app-rebuild": {
|
||||||
{
|
"title": "Applikation neu kompilieren",
|
||||||
"title": "Applikation re-kompilieren",
|
"rebuild-note-l1": "Damit die in die Datei conf.yml geschriebenen Änderungen wirksam werden ist ein Neukompilieren erforderlich.",
|
||||||
"rebuild-note-l1": "Damit die in die Datei conf.yml geschriebenen Änderungen wirksam werden ist ein re-kompilieren erforderlich.",
|
|
||||||
"rebuild-note-l2": "Dies sollte automatisch passieren, aber falls nicht können Sie es hier manuell starten.",
|
"rebuild-note-l2": "Dies sollte automatisch passieren, aber falls nicht können Sie es hier manuell starten.",
|
||||||
"rebuild-note-l3": "Dies ist bei lokal gespeicherten Änderungen nicht erforderlich.",
|
"rebuild-note-l3": "Dies ist bei lokal gespeicherten Änderungen nicht erforderlich.",
|
||||||
"rebuild-button": "Start Kompilierung",
|
"rebuild-button": "Starte Kompilierung",
|
||||||
"rebuilding-status-1": "Baue...",
|
"rebuilding-status-1": "Baue...",
|
||||||
"rebuilding-status-2": "Das kann ein paar Minuten dauern",
|
"rebuilding-status-2": "Das kann ein paar Minuten dauern",
|
||||||
"error-permission": "Sie sind nicht berechtigt diese Aktion auszulösen",
|
"error-permission": "Sie sind nicht berechtigt diese Aktion auszulösen",
|
||||||
@ -154,12 +194,12 @@
|
|||||||
"reload-note": "Ein neu Laden der Seite ist erforderlich, damit die Änderungen wirksam werden.",
|
"reload-note": "Ein neu Laden der Seite ist erforderlich, damit die Änderungen wirksam werden.",
|
||||||
"reload-button": "Seite neu laden"
|
"reload-button": "Seite neu laden"
|
||||||
},
|
},
|
||||||
"cloud-sync":
|
"cloud-sync": {
|
||||||
{
|
|
||||||
"title": "Cloud Backup & Wiederherstellung",
|
"title": "Cloud Backup & Wiederherstellung",
|
||||||
"intro-l1": "Cloud-Backup und Wiederherstellung ist eine optionale Funktion mit der Sie Ihre Konfiguration in das Internet hochladen und dann auf einem anderen Gerät oder einer anderen Dashy-Instanz wiederherstellen können.",
|
"intro-l1": "Cloud-Backup und Wiederherstellung ist eine optionale Funktion mit der Sie Ihre Konfiguration in das Internet hochladen und dann auf einem anderen Gerät oder einer anderen Dashy-Instanz wiederherstellen können.",
|
||||||
"intro-l2": "Alle Daten sind vollständig Ende-zu-Ende mit AES verschlüsselt. Ihr Passwort wird als Schlüssel verwendet.",
|
"intro-l2": "Alle Daten sind vollständig Ende-zu-Ende mit AES verschlüsselt. Ihr Passwort wird als Schlüssel verwendet.",
|
||||||
"intro-l3": "Weitere Informationen finden Sie im",
|
"intro-l3": "Weitere Informationen finden Sie in der",
|
||||||
|
"intro-docs": "Dokumentation",
|
||||||
"backup-title-setup": "Backup erstellen",
|
"backup-title-setup": "Backup erstellen",
|
||||||
"backup-title-update": "Backup aktualisieren",
|
"backup-title-update": "Backup aktualisieren",
|
||||||
"password-label-setup": "Passwort auswählen",
|
"password-label-setup": "Passwort auswählen",
|
||||||
@ -172,14 +212,14 @@
|
|||||||
"restore-id-label": "ID wiederherstellen",
|
"restore-id-label": "ID wiederherstellen",
|
||||||
"restore-password-label": "Passwort",
|
"restore-password-label": "Passwort",
|
||||||
"restore-button": "Wiederherstellen",
|
"restore-button": "Wiederherstellen",
|
||||||
|
"backup-missing-password": "Passwort fehlt",
|
||||||
"backup-error-unknown": "Anfrage kann nicht verarbeitet werden",
|
"backup-error-unknown": "Anfrage kann nicht verarbeitet werden",
|
||||||
"backup-error-password": "Falsches Passwort. Bitte geben Sie Ihr aktuelles Passwort ein.",
|
"backup-error-password": "Falsches Passwort. Bitte geben Sie Ihr aktuelles Passwort ein.",
|
||||||
"backup-success-msg": "Erfolgreich abgeschlossen",
|
"backup-success-msg": "Erfolgreich abgeschlossen",
|
||||||
"restore-success-msg": "Konfiguration erfolgreich wiederhergestellt"
|
"restore-success-msg": "Konfiguration erfolgreich wiederhergestellt"
|
||||||
},
|
},
|
||||||
"menu":
|
"menu": {
|
||||||
{
|
"open-section-title": "Öffne in",
|
||||||
"open-section-title": "Öffnen in",
|
|
||||||
"sametab": "Aktueller Tab",
|
"sametab": "Aktueller Tab",
|
||||||
"newtab": "Neuer Tab",
|
"newtab": "Neuer Tab",
|
||||||
"modal": "Popup Modal",
|
"modal": "Popup Modal",
|
||||||
@ -189,10 +229,8 @@
|
|||||||
"move-item": "Kopieren oder Verschieben",
|
"move-item": "Kopieren oder Verschieben",
|
||||||
"remove-item": "Entfernen"
|
"remove-item": "Entfernen"
|
||||||
},
|
},
|
||||||
"context-menus":
|
"context-menus": {
|
||||||
{
|
"item": {
|
||||||
"item":
|
|
||||||
{
|
|
||||||
"open-section-title": "Öffnen in",
|
"open-section-title": "Öffnen in",
|
||||||
"sametab": "Aktueller Tab",
|
"sametab": "Aktueller Tab",
|
||||||
"newtab": "Neuer Tab",
|
"newtab": "Neuer Tab",
|
||||||
@ -205,8 +243,7 @@
|
|||||||
"remove-item": "Entfernen",
|
"remove-item": "Entfernen",
|
||||||
"copied-toast": "URL wurde in die Zwischenablage kopiert"
|
"copied-toast": "URL wurde in die Zwischenablage kopiert"
|
||||||
},
|
},
|
||||||
"section":
|
"section": {
|
||||||
{
|
|
||||||
"open-section": "Sektion öffnen",
|
"open-section": "Sektion öffnen",
|
||||||
"edit-section": "Bearbeiten",
|
"edit-section": "Bearbeiten",
|
||||||
"expand-collapse": "Aus- / Einklappen",
|
"expand-collapse": "Aus- / Einklappen",
|
||||||
@ -214,10 +251,14 @@
|
|||||||
"remove-section": "Entfernen"
|
"remove-section": "Entfernen"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"interactive-editor":
|
"footer": {
|
||||||
{
|
"dev-by": "Entwickelt von",
|
||||||
"menu":
|
"licensed-under": "Lizensiert unter",
|
||||||
{
|
"get-the": "Hole dir den",
|
||||||
|
"source-code": "Quellcode"
|
||||||
|
},
|
||||||
|
"interactive-editor": {
|
||||||
|
"menu": {
|
||||||
"start-editing-tooltip": "Interaktiven Editor starten",
|
"start-editing-tooltip": "Interaktiven Editor starten",
|
||||||
"edit-site-data-subheading": "Seiteninformationen bearbeiten",
|
"edit-site-data-subheading": "Seiteninformationen bearbeiten",
|
||||||
"edit-page-info-btn": "Seiteninformationen bearbeiten",
|
"edit-page-info-btn": "Seiteninformationen bearbeiten",
|
||||||
@ -246,27 +287,23 @@
|
|||||||
"cancel-stage-btn": "Abbrechen",
|
"cancel-stage-btn": "Abbrechen",
|
||||||
"save-locally-warning": "Wenn Sie fortfahren werden die Änderungen nur in Ihrem Browser gespeichert. Um die Konfiguration auf anderen Geräten zu nutzen sollten Sie sie exportieren. Möchten Sie fortfahren?"
|
"save-locally-warning": "Wenn Sie fortfahren werden die Änderungen nur in Ihrem Browser gespeichert. Um die Konfiguration auf anderen Geräten zu nutzen sollten Sie sie exportieren. Möchten Sie fortfahren?"
|
||||||
},
|
},
|
||||||
"edit-item":
|
"edit-item": {
|
||||||
{
|
|
||||||
"missing-title-err": "Ein Titel is zwingend notwendig"
|
"missing-title-err": "Ein Titel is zwingend notwendig"
|
||||||
},
|
},
|
||||||
"edit-section":
|
"edit-section": {
|
||||||
{
|
|
||||||
"edit-section-title": "Sektion bearbeiten",
|
"edit-section-title": "Sektion bearbeiten",
|
||||||
"add-section-title": "Neue Sektion hinzufügen",
|
"add-section-title": "Neue Sektion hinzufügen",
|
||||||
"edit-tooltip": "Klicken zum Bearbeiten oder Rechtsklick für weitere Optionen",
|
"edit-tooltip": "Klicken zum Bearbeiten oder Rechtsklick für weitere Optionen",
|
||||||
"remove-confirm": "Sind Sie sicher, dass sie diese Sektion entfernen möchten? Diese Aktion kann nicht rückgänging gemacht werden."
|
"remove-confirm": "Sind Sie sicher, dass sie diese Sektion entfernen möchten? Diese Aktion kann nicht rückgänging gemacht werden."
|
||||||
},
|
},
|
||||||
"edit-app-config":
|
"edit-app-config": {
|
||||||
{
|
|
||||||
"warning-msg-title": "Ab hier ist Vorsicht geboten",
|
"warning-msg-title": "Ab hier ist Vorsicht geboten",
|
||||||
"warning-msg-l1": "Die folgenden Optionen sind für fortgeschrittene Konfigurationen.",
|
"warning-msg-l1": "Die folgenden Optionen sind für fortgeschrittene Konfigurationen.",
|
||||||
"warning-msg-l2": "Sollten Felder unklar sein, konsultieren Sie die",
|
"warning-msg-l2": "Sollten Felder unklar sein, konsultieren Sie die",
|
||||||
"warning-msg-docs": "Dokumentation",
|
"warning-msg-docs": "Dokumentation",
|
||||||
"warning-msg-l3": "um unbeabsichtigte Folgen zu vermeiden."
|
"warning-msg-l3": "um unbeabsichtigte Folgen zu vermeiden."
|
||||||
},
|
},
|
||||||
"export":
|
"export": {
|
||||||
{
|
|
||||||
"export-title": "Konfiguration exportieren",
|
"export-title": "Konfiguration exportieren",
|
||||||
"copy-clipboard-btn": "In Zwischenablage kopieren",
|
"copy-clipboard-btn": "In Zwischenablage kopieren",
|
||||||
"copy-clipboard-tooltip": "Applikationskonfiguration als YAML in Zwischenablage kopieren",
|
"copy-clipboard-tooltip": "Applikationskonfiguration als YAML in Zwischenablage kopieren",
|
||||||
@ -275,57 +312,49 @@
|
|||||||
"view-title": "Konfiguration anzeigen"
|
"view-title": "Konfiguration anzeigen"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"widgets":
|
"widgets": {
|
||||||
{
|
"general": {
|
||||||
"general":
|
|
||||||
{
|
|
||||||
"loading": "Lade...",
|
"loading": "Lade...",
|
||||||
"show-more": "Details",
|
"show-more": "Details",
|
||||||
|
"cpu-details": "Details CPU",
|
||||||
|
"mem-details": "Details Arbeitsspeicher",
|
||||||
"show-less": "Weniger anzeigen",
|
"show-less": "Weniger anzeigen",
|
||||||
"open-link": "Weiterlesen"
|
"open-link": "Weiterlesen"
|
||||||
},
|
},
|
||||||
"pi-hole":
|
"pi-hole": {
|
||||||
{
|
|
||||||
"status-heading": "Status"
|
"status-heading": "Status"
|
||||||
},
|
},
|
||||||
"stat-ping":
|
"stat-ping": {
|
||||||
{
|
|
||||||
"up": "Online",
|
"up": "Online",
|
||||||
"down": "Offline"
|
"down": "Offline"
|
||||||
},
|
},
|
||||||
"net-data":
|
"net-data": {
|
||||||
{
|
|
||||||
"cpu-chart-title": "CPU Historie",
|
"cpu-chart-title": "CPU Historie",
|
||||||
"mem-chart-title": "Speichernutzung",
|
"mem-chart-title": "Speichernutzung",
|
||||||
"mem-breakdown-title": "Speichernutzung",
|
"mem-breakdown-title": "Speichernutzung",
|
||||||
"load-chart-title": "Systemlast"
|
"load-chart-title": "Systemlast"
|
||||||
},
|
},
|
||||||
"glances":
|
"glances": {
|
||||||
{
|
|
||||||
"disk-space-free": "Frei",
|
"disk-space-free": "Frei",
|
||||||
"disk-space-used": "Genutzt",
|
"disk-space-used": "Genutzt",
|
||||||
"disk-mount-point": "Mount Punkt",
|
"disk-mount-point": "Mountpunkt",
|
||||||
"disk-file-system": "Dateisystem,",
|
"disk-file-system": "Dateisystem,",
|
||||||
"disk-io-read": "Lesen",
|
"disk-io-read": "Lesen",
|
||||||
"disk-io-write": "Schreiben",
|
"disk-io-write": "Schreiben",
|
||||||
"system-load-desc": "Prozesse in Warteschlange. (Durchschnitt aller Kerne)"
|
"system-load-desc": "Prozesse in der Warteschlange, Durchschnitt aller Kerne"
|
||||||
},
|
},
|
||||||
"system-info":
|
"system-info": {
|
||||||
{
|
|
||||||
"uptime": "Uptime"
|
"uptime": "Uptime"
|
||||||
},
|
},
|
||||||
"flight-data":
|
"flight-data": {
|
||||||
{
|
|
||||||
"arrivals": "Ankünfte",
|
"arrivals": "Ankünfte",
|
||||||
"departures": "Abflüge"
|
"departures": "Abflüge"
|
||||||
},
|
},
|
||||||
"tfl-status":
|
"tfl-status": {
|
||||||
{
|
|
||||||
"good-service-all": "Guter Service auf allen Leitungen",
|
"good-service-all": "Guter Service auf allen Leitungen",
|
||||||
"good-service-rest": "Guter Service auf allen anderen Leitungen"
|
"good-service-rest": "Guter Service auf allen anderen Leitungen"
|
||||||
},
|
},
|
||||||
"synology-download":
|
"synology-download": {
|
||||||
{
|
|
||||||
"download": "Download",
|
"download": "Download",
|
||||||
"upload": "Upload",
|
"upload": "Upload",
|
||||||
"downloaded": "Heruntergeladen",
|
"downloaded": "Heruntergeladen",
|
||||||
@ -334,8 +363,7 @@
|
|||||||
"up": "Hoch",
|
"up": "Hoch",
|
||||||
"down": "Runter"
|
"down": "Runter"
|
||||||
},
|
},
|
||||||
"gluetun-status":
|
"gluetun-status": {
|
||||||
{
|
|
||||||
"vpn-ip": "VPN IP",
|
"vpn-ip": "VPN IP",
|
||||||
"country": "Land",
|
"country": "Land",
|
||||||
"region": "Bundesland",
|
"region": "Bundesland",
|
||||||
@ -345,8 +373,7 @@
|
|||||||
"timezone": "Zeitzone",
|
"timezone": "Zeitzone",
|
||||||
"organization": "Organisation"
|
"organization": "Organisation"
|
||||||
},
|
},
|
||||||
"nextcloud":
|
"nextcloud": {
|
||||||
{
|
|
||||||
"active": "Aktiv",
|
"active": "Aktiv",
|
||||||
"and": "und",
|
"and": "und",
|
||||||
"applications": "Anwendungen",
|
"applications": "Anwendungen",
|
||||||
@ -356,61 +383,61 @@
|
|||||||
"chat-room": "Chatraum",
|
"chat-room": "Chatraum",
|
||||||
"delete-all": "Alle löschen",
|
"delete-all": "Alle löschen",
|
||||||
"delete-notification": "Benachrichtigung löschen",
|
"delete-notification": "Benachrichtigung löschen",
|
||||||
"disabled": "Deaktivert",
|
"disabled": "deaktivert",
|
||||||
"disk-quota": "Disk Quota",
|
"disk-quota": "Disk Quota",
|
||||||
"disk-space": "Disk Speicherplatz",
|
"disk-space": "Disk Speicherplatz",
|
||||||
"dnd": "Nicht stören",
|
"dnd": "Nicht stören",
|
||||||
"email": "EMail",
|
"email": "E-Mail",
|
||||||
"enabled": "Aktiviert",
|
"enabled": "aktiviert",
|
||||||
"federated-shares-ucfirst": "Verbundsfreigaben",
|
"federated-shares-ucfirst": "Föderierte Freigaben",
|
||||||
"federated-shares": "Verbundsfreigaben",
|
"federated-shares": "föderierte Freigaben",
|
||||||
"files": "Dateien{plural}",
|
"files": "Dateien",
|
||||||
"free": "Frei",
|
"free": "frei",
|
||||||
"groups": "Gruppen",
|
"groups": "Gruppen",
|
||||||
"hit-rate": "Trefferrate",
|
"hit-rate": "Trefferrate",
|
||||||
"hits": "Treffer",
|
"hits": "Treffer",
|
||||||
"home": "Zuhause",
|
"home": "Zuhause",
|
||||||
"in": "in",
|
"in": "in",
|
||||||
"keys": "Schlüssel",
|
"keys": "Schlüssel",
|
||||||
"last-24-hours": "Letzte 24 Stunden",
|
"last-24-hours": "letzte 24 Stunden",
|
||||||
"last-5-minutes": "in den letzten 5 Minuten",
|
"last-5-minutes": "in den letzten 5 Minuten",
|
||||||
"last-hour": "in der letzten Stunde",
|
"last-hour": "in der letzten Stunde",
|
||||||
"last-login": "Letzte Anmeldung",
|
"last-login": "Letzte Anmeldung",
|
||||||
"last-restart": "Letzter Neustart",
|
"last-restart": "Letzter Neustart",
|
||||||
"load-averages": "Systemlast aller CPU-Kerne",
|
"load-averages": "Systemlast aller CPU-Kerne",
|
||||||
"local-shares": "Lokale Freigaben",
|
"local-shares": "Lokale Freigaben",
|
||||||
"local": "Lokal",
|
"local": "lokal",
|
||||||
"max-keys": "Maximale Schlüssel",
|
"max-keys": "Maximale Schlüssel",
|
||||||
"memory-used": "Speuchernutzung",
|
"memory-used": "Speichernutzung",
|
||||||
"memory-utilisation": "Speuchernutzung",
|
"memory-utilisation": "Speichernutzung",
|
||||||
"memory": "Speicher",
|
"memory": "Speicher",
|
||||||
"misses": "Fehlschläge",
|
"misses": "Fehlschläge",
|
||||||
"no-notifications": "Keine Benachrichtigungen",
|
"no-notifications": "Keine Benachrichtigungen",
|
||||||
"no-pending-updates": "Keine ausstehenden Aktualisierungen",
|
"no-pending-updates": "keine ausstehenden Aktualisierungen",
|
||||||
"nothing-to-show": "Momentan gibt es hier nichts zu zeigen",
|
"nothing-to-show": "Momentan gibt es hier nichts zu zeigen",
|
||||||
"of-which": "welche",
|
"of-which": "welche",
|
||||||
"of": "von",
|
"of": "von",
|
||||||
"offline": "Offline",
|
"offline": "Offline",
|
||||||
"online": "Online",
|
"online": "Online",
|
||||||
"other": "Andere",
|
"other": "andere",
|
||||||
"overall": "Insgesamt",
|
"overall": "Insgesamt",
|
||||||
"private-link": "privater Link",
|
"private-link": "privater Link",
|
||||||
"public-link": "öffentlicher Link",
|
"public-link": "öffentlicher Link",
|
||||||
"quota-enabled": "Disk Quota ist {nicht}aktiviert für diesen Benutzer",
|
"quota-enabled": "Disk Quota ist {nicht}aktiviert für diesen Benutzer",
|
||||||
"received": "Empfangen",
|
"received": "empfangen",
|
||||||
"scripts": "Skripte",
|
"scripts": "Skripte",
|
||||||
"sent": "Gesendet",
|
"sent": "gesendet",
|
||||||
"started": "Gestartet",
|
"started": "gestartet",
|
||||||
"storages-by-type": "Speicher nach Typ",
|
"storages-by-type": "Speicher nach Typ",
|
||||||
"storages": "Speicher{plural}",
|
"storages": "Speicher",
|
||||||
"strings-use": "Strings benutzen",
|
"strings-use": "Strings benutzen",
|
||||||
"tasks": "Aufgaben",
|
"tasks": "Aufgaben",
|
||||||
"total-files": "Dateien gesamt",
|
"total-files": "Dateien gesamt",
|
||||||
"total-users": "Benutzer gesamt",
|
"total-users": "Benutzer gesamt",
|
||||||
"total": "Insgesamt",
|
"total": "insgesamt",
|
||||||
"until": "Bis",
|
"until": "Bis",
|
||||||
"updates-available-for": "Aktualisierungen sind verfügbar für",
|
"updates-available-for": "Aktualisierungen sind verfügbar für",
|
||||||
"updates-available": "Aktualisierungen{plural} verfügbar",
|
"updates-available": "Aktualisierungen verfügbar",
|
||||||
"used": "benutzt",
|
"used": "benutzt",
|
||||||
"user": "Benutzer",
|
"user": "Benutzer",
|
||||||
"using": "nutzt",
|
"using": "nutzt",
|
||||||
|
@ -63,8 +63,8 @@
|
|||||||
"privacy-and-security": "Privacy & Security",
|
"privacy-and-security": "Privacy & Security",
|
||||||
"privacy-and-security-l1": "For a break-down of how your data is managed by Dashy, see the",
|
"privacy-and-security-l1": "For a break-down of how your data is managed by Dashy, see the",
|
||||||
"privacy-and-security-privacy-policy": "Privacy Policy",
|
"privacy-and-security-privacy-policy": "Privacy Policy",
|
||||||
"app-info.privacy-and-security-advice": "For advise in securing your dashboard, you can reference the",
|
"privacy-and-security-advice": "For advise in securing your dashboard, you can reference the",
|
||||||
"app-info.privacy-and-security-advice-link": "Management Docs",
|
"privacy-and-security-advice-link": "Management Docs",
|
||||||
"privacy-and-security-security-issue": "If you've found a potential security issue, report it following our",
|
"privacy-and-security-security-issue": "If you've found a potential security issue, report it following our",
|
||||||
"privacy-and-security-security-policy": "Security Policy",
|
"privacy-and-security-security-policy": "Security Policy",
|
||||||
"license": "License",
|
"license": "License",
|
||||||
@ -171,9 +171,9 @@
|
|||||||
"status-fail-msg": "Task Failed",
|
"status-fail-msg": "Task Failed",
|
||||||
"success-msg-disk": "Config file written to disk successfully",
|
"success-msg-disk": "Config file written to disk successfully",
|
||||||
"success-msg-local": "Local changes saved successfully",
|
"success-msg-local": "Local changes saved successfully",
|
||||||
"success-note-l1": "The app should rebuild automatically.",
|
"success-note-l1": "You will need to refresh the page for changes to take effect.",
|
||||||
"success-note-l2": "This may take up to a minute.",
|
"success-note-l2": "",
|
||||||
"success-note-l3": "You will need to refresh the page for changes to take effect.",
|
"success-note-l3": "",
|
||||||
"error-msg-save-mode": "Please select a Save Mode: Local or File",
|
"error-msg-save-mode": "Please select a Save Mode: Local or File",
|
||||||
"error-msg-cannot-save": "An error occurred saving config",
|
"error-msg-cannot-save": "An error occurred saving config",
|
||||||
"error-msg-bad-json": "Error in JSON, possibly malformed",
|
"error-msg-bad-json": "Error in JSON, possibly malformed",
|
||||||
@ -182,9 +182,9 @@
|
|||||||
},
|
},
|
||||||
"app-rebuild": {
|
"app-rebuild": {
|
||||||
"title": "Rebuild Application",
|
"title": "Rebuild Application",
|
||||||
"rebuild-note-l1": "A rebuild is required for changes written to the conf.yml file to take effect.",
|
"rebuild-note-l1": "A rebuild is no longer required for changes to take effect.",
|
||||||
"rebuild-note-l2": "This should happen automatically, but if it hasn't, you can manually trigger it here.",
|
"rebuild-note-l2": "Some changes (entry-point, and auth settings) are read at build-time. So to apply these, you should trigger a rebuild here.",
|
||||||
"rebuild-note-l3": "This is not required for modifications stored locally.",
|
"rebuild-note-l3": "Note that this is only available on Node and Docker installations, not via statically deployed instances.",
|
||||||
"rebuild-button": "Start Build",
|
"rebuild-button": "Start Build",
|
||||||
"rebuilding-status-1": "Building...",
|
"rebuilding-status-1": "Building...",
|
||||||
"rebuilding-status-2": "This may take a few minutes",
|
"rebuilding-status-2": "This may take a few minutes",
|
||||||
@ -312,10 +312,20 @@
|
|||||||
"view-title": "View Config"
|
"view-title": "View Config"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"critical-error": {
|
||||||
|
"title": "Configuration Load Error",
|
||||||
|
"subtitle": "Dashy has failed to load correctly due to a configuration error.",
|
||||||
|
"sub-ensure-that": "Ensure that",
|
||||||
|
"sub-error-details": "Error Details",
|
||||||
|
"sub-next-steps": "Next Steps",
|
||||||
|
"ignore-button": "Ignore Critical Errors"
|
||||||
|
},
|
||||||
"widgets": {
|
"widgets": {
|
||||||
"general": {
|
"general": {
|
||||||
"loading": "Loading...",
|
"loading": "Loading...",
|
||||||
"show-more": "Expand Details",
|
"show-more": "Expand Details",
|
||||||
|
"cpu-details": "CPU Details",
|
||||||
|
"mem-details": "Memory Details",
|
||||||
"show-less": "Show Less",
|
"show-less": "Show Less",
|
||||||
"open-link": "Continue Reading"
|
"open-link": "Continue Reading"
|
||||||
},
|
},
|
||||||
|
@ -63,8 +63,8 @@
|
|||||||
"privacy-and-security": "Privacidade e seguridade",
|
"privacy-and-security": "Privacidade e seguridade",
|
||||||
"privacy-and-security-l1": "Para obter detalles sobre como os teus datos son xestionados por Dashy, consulta a",
|
"privacy-and-security-l1": "Para obter detalles sobre como os teus datos son xestionados por Dashy, consulta a",
|
||||||
"privacy-and-security-privacy-policy": "Política de privacidade",
|
"privacy-and-security-privacy-policy": "Política de privacidade",
|
||||||
"app-info.privacy-and-security-advice": "Para consellos sobre como asegurar o teu panel de control, consulta os",
|
"privacy-and-security-advice": "Para consellos sobre como asegurar o teu panel de control, consulta os",
|
||||||
"app-info.privacy-and-security-advice-link": "Documentos de xestión",
|
"privacy-and-security-advice-link": "Documentos de xestión",
|
||||||
"privacy-and-security-security-issue": "Se atopaches un problema de seguridade potencial, informa seguindo a nosa",
|
"privacy-and-security-security-issue": "Se atopaches un problema de seguridade potencial, informa seguindo a nosa",
|
||||||
"privacy-and-security-security-policy": "Política de seguridade",
|
"privacy-and-security-security-policy": "Política de seguridade",
|
||||||
"license": "Licenza",
|
"license": "Licenza",
|
||||||
|
@ -63,8 +63,8 @@
|
|||||||
"privacy-and-security": "プライバシーとセキュリティー",
|
"privacy-and-security": "プライバシーとセキュリティー",
|
||||||
"privacy-and-security-l1": "Daisyがどのようにあなたのデータを管理するかについての概要は、こちらをご覧ください: ",
|
"privacy-and-security-l1": "Daisyがどのようにあなたのデータを管理するかについての概要は、こちらをご覧ください: ",
|
||||||
"privacy-and-security-privacy-policy": "プライバシーポリシー",
|
"privacy-and-security-privacy-policy": "プライバシーポリシー",
|
||||||
"app-info.privacy-and-security-advice": "ダッシュボードを安全に保つためのアドバイスは、こちらを参照してください: ",
|
"privacy-and-security-advice": "ダッシュボードを安全に保つためのアドバイスは、こちらを参照してください: ",
|
||||||
"app-info.privacy-and-security-advice-link": "管理ドキュメント",
|
"privacy-and-security-advice-link": "管理ドキュメント",
|
||||||
"privacy-and-security-security-issue": "セキュリティー問題の可能性のある事象を見つけた場合、セキュリティーポリシーに従ってください: ",
|
"privacy-and-security-security-issue": "セキュリティー問題の可能性のある事象を見つけた場合、セキュリティーポリシーに従ってください: ",
|
||||||
"privacy-and-security-security-policy": "セキュリティーポリシー",
|
"privacy-and-security-security-policy": "セキュリティーポリシー",
|
||||||
"license": "ライセンス",
|
"license": "ライセンス",
|
||||||
|
@ -10,8 +10,12 @@
|
|||||||
"clear-search-tooltip": "Limpar busca",
|
"clear-search-tooltip": "Limpar busca",
|
||||||
"enter-to-search-web": "Tecle enter para buscar na rede"
|
"enter-to-search-web": "Tecle enter para buscar na rede"
|
||||||
},
|
},
|
||||||
|
"splash-screen": {
|
||||||
|
"loading": "Carregando"
|
||||||
|
},
|
||||||
"login": {
|
"login": {
|
||||||
"title": "Dashy",
|
"title": "Dashy",
|
||||||
|
"guest-label": "Entrar como convidado",
|
||||||
"username-label": "Nome do usuário",
|
"username-label": "Nome do usuário",
|
||||||
"password-label": "Senha",
|
"password-label": "Senha",
|
||||||
"login-button": "Conectar",
|
"login-button": "Conectar",
|
||||||
@ -31,8 +35,20 @@
|
|||||||
"already-logged-in-text": "Você está logado como",
|
"already-logged-in-text": "Você está logado como",
|
||||||
"proceed-to-dashboard": "Ir para o Painel",
|
"proceed-to-dashboard": "Ir para o Painel",
|
||||||
"log-out-button": "Sair",
|
"log-out-button": "Sair",
|
||||||
"proceed-guest-button": "Seguir como Convidado"
|
"proceed-guest-button": "Seguir como Convidado",
|
||||||
|
"guest-intro-1": "Essa instância possui o acesso como convidado ativado",
|
||||||
|
"guest-intro-2": "Convidados podem apenas visualizar os painéis, logo não podem escrever quaisquer mudanças no disco.",
|
||||||
|
"error": "Erro",
|
||||||
|
"error-no-user-configured": "Autenticação não está habilitada, ou nenhum usuário foi configurado.",
|
||||||
|
"error-go-home-button": "Ir para a página inicial",
|
||||||
|
"logged-in-guest": "Logado como convidado. Redirecionando...",
|
||||||
|
"error-guest-access": "O acesso como convidado não foi permitido"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"app-info": {
|
||||||
|
"title": "Informação do App"
|
||||||
|
},
|
||||||
|
|
||||||
"config": {
|
"config": {
|
||||||
"main-tab": "Menu Principal",
|
"main-tab": "Menu Principal",
|
||||||
"view-config-tab": "Ver configuração",
|
"view-config-tab": "Ver configuração",
|
||||||
@ -299,6 +315,16 @@
|
|||||||
"remaining": "Restante",
|
"remaining": "Restante",
|
||||||
"up": "Up",
|
"up": "Up",
|
||||||
"down": "Down"
|
"down": "Down"
|
||||||
|
},
|
||||||
|
"gluetun-status": {
|
||||||
|
"vpn-ip": "IP da VPN",
|
||||||
|
"country": "País",
|
||||||
|
"region": "Região",
|
||||||
|
"city": "Cidade",
|
||||||
|
"post-code": "Código postal",
|
||||||
|
"location": "Localização",
|
||||||
|
"timezone": "Fuso horário",
|
||||||
|
"organization": "Organização"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
448
src/assets/locales/ro.json
Normal file
@ -0,0 +1,448 @@
|
|||||||
|
{
|
||||||
|
"home": {
|
||||||
|
"no-results": "Niciun rezultat găsit",
|
||||||
|
"no-data": "Nicio dată configurată",
|
||||||
|
"no-items-section": "Niciun element de afișat încă"
|
||||||
|
},
|
||||||
|
"search": {
|
||||||
|
"search-label": "Caută",
|
||||||
|
"search-placeholder": "Începeți să tastați pentru a filtra",
|
||||||
|
"clear-search-tooltip": "Șterge căutarea",
|
||||||
|
"enter-to-search-web": "Apasă enter pentru a căuta pe web"
|
||||||
|
},
|
||||||
|
"splash-screen": {
|
||||||
|
"loading": "Încărcare"
|
||||||
|
},
|
||||||
|
"login": {
|
||||||
|
"title": "Dashy",
|
||||||
|
"guest-label": "Acces Vizitator",
|
||||||
|
"username-label": "Nume utilizator",
|
||||||
|
"password-label": "Parolă",
|
||||||
|
"login-button": "Autentificare",
|
||||||
|
"remember-me-label": "Ține-mă minte pentru",
|
||||||
|
"remember-me-never": "Niciodată",
|
||||||
|
"remember-me-hour": "4 Ore",
|
||||||
|
"remember-me-day": "1 Zi",
|
||||||
|
"remember-me-week": "1 Săptămână",
|
||||||
|
"remember-me-long-time": "O perioadă lungă",
|
||||||
|
"error-missing-username": "Lipsește numele de utilizator",
|
||||||
|
"error-missing-password": "Lipsește parola",
|
||||||
|
"error-incorrect-username": "Utilizator negăsit",
|
||||||
|
"error-incorrect-password": "Parolă incorectă",
|
||||||
|
"success-message": "Autentificare...",
|
||||||
|
"logout-message": "Deconectat",
|
||||||
|
"already-logged-in-title": "Deja autentificat",
|
||||||
|
"already-logged-in-text": "Ești autentificat ca",
|
||||||
|
"proceed-to-dashboard": "Continuă către Tabloul de bord",
|
||||||
|
"log-out-button": "Deconectare",
|
||||||
|
"proceed-guest-button": "Continuă ca Vizitator",
|
||||||
|
"guest-intro-1": "Această instanță are acces pentru vizitatori activat.",
|
||||||
|
"guest-intro-2": "Vizitatorii au acces doar pentru vizualizare la tablourile de bord, deci nu pot scrie modificări pe disc.",
|
||||||
|
"error": "Eroare",
|
||||||
|
"error-no-user-configured": "Autentificarea nu este activată, sau nu au fost configurați utilizatori",
|
||||||
|
"error-go-home-button": "Mergi la Pagina Principală",
|
||||||
|
"logged-in-guest": "Autentificat ca Vizitator, Redirecționare...",
|
||||||
|
"error-guest-access": "Acces Vizitator Interzis"
|
||||||
|
},
|
||||||
|
"app-info": {
|
||||||
|
"title": "Informații Aplicație",
|
||||||
|
"error-log": "Jurnal Erori",
|
||||||
|
"no-errors": "Nicio eroare recentă detectată",
|
||||||
|
"help-support": "Ajutor & Suport",
|
||||||
|
"help-support-description" : "Pentru suport în utilizarea sau configurarea Dashy, consultați",
|
||||||
|
"help-support-discussions": "Discuțiile",
|
||||||
|
"support-dashy": "Suport pentru Dashy",
|
||||||
|
"support-dashy-description": "Pentru moduri în care poți contribui, verificați",
|
||||||
|
"support-dashy-link": "Pagina de Contribuții",
|
||||||
|
"report-bug": "Raportează o Eroare",
|
||||||
|
"report-bug-description": "Dacă crezi că ai găsit o eroare, atunci te rog",
|
||||||
|
"report-bug-link": "deschide o Problemă",
|
||||||
|
"more-info": "Mai Multe Informații",
|
||||||
|
"source": "Sursă",
|
||||||
|
"documentation": "Documentație",
|
||||||
|
"privacy-and-security": "Confidențialitate & Securitate",
|
||||||
|
"privacy-and-security-l1": "Pentru o descompunere a modului în care datele tale sunt gestionate de Dashy, consultați",
|
||||||
|
"privacy-and-security-privacy-policy": "Politica de Confidențialitate",
|
||||||
|
"privacy-and-security-advice": "Pentru sfaturi în securizarea tabloului tău de bord, poți consulta",
|
||||||
|
"privacy-and-security-advice-link": "Documentele de Management",
|
||||||
|
"privacy-and-security-security-issue": "Dacă ați descoperit o potențială problemă de securitate, raportați-o urmând",
|
||||||
|
"privacy-and-security-security-policy": "Politica de Securitate",
|
||||||
|
"license": "Licență",
|
||||||
|
"license-under": "Licențiat sub",
|
||||||
|
"licence-third-party": "Pentru licențele modulelor terțe părți, vă rugăm să consultați",
|
||||||
|
"licence-third-party-link": "Legal",
|
||||||
|
"list-contributors": "Pentru lista completă a contribuitorilor și mulțumiri, vedeți",
|
||||||
|
"list-contributors-link": "Credite",
|
||||||
|
"version": "Versiune"
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"main-tab": "Meniu Principal",
|
||||||
|
"view-config-tab": "Vizualizare Configurație",
|
||||||
|
"edit-config-tab": "Editare Configurație",
|
||||||
|
"custom-css-tab": "Stiluri Personalizate",
|
||||||
|
"heading": "Opțiuni de Configurare",
|
||||||
|
"download-config-button": "Vizualizați / Exportați Configurația",
|
||||||
|
"edit-config-button": "Editare Configurație",
|
||||||
|
"edit-css-button": "Editare CSS Personalizat",
|
||||||
|
"cloud-sync-button": "Activează Sincronizarea în Cloud",
|
||||||
|
"edit-cloud-sync-button": "Editare Sincronizare în Cloud",
|
||||||
|
"rebuild-app-button": "Reconstruire Aplicație",
|
||||||
|
"change-language-button": "Schimbă Limba Aplicației",
|
||||||
|
"reset-settings-button": "Resetează Setările Locale",
|
||||||
|
"disabled-note": "Unele caracteristici de configurare au fost dezactivate de administratorul tău",
|
||||||
|
"small-screen-note": "Utilizați un ecran foarte mic, și unele ecrane din acest meniu s-ar putea să nu fie optimale",
|
||||||
|
"app-info-button": "Informații Aplicație",
|
||||||
|
"backup-note": "Este recomandat să faceți o copie de siguranță a configurației înainte de a face modificări.",
|
||||||
|
"reset-config-msg-l1": "Aceasta va elimina toate setările utilizatorilor din stocarea locală, dar nu va afecta fișierul 'conf.yml'.",
|
||||||
|
"reset-config-msg-l2": "Ar trebui să faceți mai întâi o copie de siguranță a oricăror modificări pe care le-ați făcut local, dacă doriți să le utilizați în viitor.",
|
||||||
|
"reset-config-msg-l3": "Sunteți sigur că doriți să continuați?",
|
||||||
|
"data-cleared-msg": "Datele au fost șterse cu succes",
|
||||||
|
"actions-label": "Acțiuni",
|
||||||
|
"copy-config-label": "Copiază Configurația",
|
||||||
|
"data-copied-msg": "Configurația a fost copiată în clipboard",
|
||||||
|
"reset-config-label": "Resetează Configurația",
|
||||||
|
"css-save-btn": "Salvează Modificările",
|
||||||
|
"css-note-label": "Notă",
|
||||||
|
"css-note-l1": "Va trebui să reîmprospătați pagina pentru ca modificările să aibă efect.",
|
||||||
|
"css-note-l2": "Suprascrierile de stiluri sunt stocate doar local, deci este recomandat să faceți o copie a CSS-ului dvs.",
|
||||||
|
"css-note-l3": "Pentru a elimina toate stilurile personalizate, ștergeți conținutul și apăsați 'Salvează Modificările'",
|
||||||
|
"custom-css": {
|
||||||
|
"title": "CSS Personalizat",
|
||||||
|
"base-theme": "Tema de Bază"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"alternate-views": {
|
||||||
|
"alternate-view-heading": "Schimbă Vederea",
|
||||||
|
"default": "Implicit",
|
||||||
|
"workspace": "Spațiu de Lucru",
|
||||||
|
"minimal": "Minimal"
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"theme-label": "Temă",
|
||||||
|
"layout-label": "Aspect",
|
||||||
|
"layout-auto": "Automat",
|
||||||
|
"layout-horizontal": "Orizontal",
|
||||||
|
"layout-vertical": "Vertical",
|
||||||
|
"item-size-label": "Dimensiune Element",
|
||||||
|
"item-size-small": "Mic",
|
||||||
|
"item-size-medium": "Mediu",
|
||||||
|
"item-size-large": "Mare",
|
||||||
|
"config-launcher-label": "Config",
|
||||||
|
"config-launcher-tooltip": "Actualizează Configurația",
|
||||||
|
"sign-out-tooltip": "Deconectare",
|
||||||
|
"sign-in-tooltip": "Conectare",
|
||||||
|
"sign-in-welcome": "Bună {username}!",
|
||||||
|
"hide": "Ascunde",
|
||||||
|
"open": "Deschide"
|
||||||
|
},
|
||||||
|
"updates": {
|
||||||
|
"app-version-note": "Versiune Dashy",
|
||||||
|
"up-to-date": "Actualizat",
|
||||||
|
"out-of-date": "Actualizare Disponibilă",
|
||||||
|
"unsupported-version-l1": "Utilizați o versiune nesuportată de Dashy",
|
||||||
|
"unsupported-version-l2": "Pentru cea mai bună experiență și patch-uri de securitate recente, vă rugăm să actualizați la"
|
||||||
|
},
|
||||||
|
"language-switcher": {
|
||||||
|
"title": "Schimbă Limba Aplicației",
|
||||||
|
"dropdown-label": "Selectați o Limbă",
|
||||||
|
"save-button": "Salvează",
|
||||||
|
"success-msg": "Limba Actualizată la"
|
||||||
|
},
|
||||||
|
"theme-maker": {
|
||||||
|
"title": "Configurator de Temă",
|
||||||
|
"export-button": "Exportă Variabile Personalizate",
|
||||||
|
"reset-button": "Resetează Stilurile pentru",
|
||||||
|
"show-all-button": "Arată Toate Variabilele",
|
||||||
|
"change-fonts-button": "Schimbă Fonturile",
|
||||||
|
"save-button": "Salvează",
|
||||||
|
"cancel-button": "Anulează",
|
||||||
|
"saved-toast": "{theme} Actualizat cu Succes",
|
||||||
|
"copied-toast": "Datele temei pentru {theme} au fost copiate în clipboard",
|
||||||
|
"reset-toast": "Culorile Personalizate pentru {theme} au fost Eliminate"
|
||||||
|
},
|
||||||
|
"config-editor": {
|
||||||
|
"save-location-label": "Locația de Salvare",
|
||||||
|
"location-local-label": "Aplică Local",
|
||||||
|
"location-disk-label": "Scrie Modificările în Fișierul de Configurație",
|
||||||
|
"save-button": "Salvează Modificările",
|
||||||
|
"preview-button": "Previzualizează Modificările",
|
||||||
|
"valid-label": "Configurația este Valabilă",
|
||||||
|
"status-success-msg": "Sarcină Completată",
|
||||||
|
"status-fail-msg": "Sarcină Eșuată",
|
||||||
|
"success-msg-disk": "Fișierul de configurație a fost scris pe disc cu succes",
|
||||||
|
"success-msg-local": "Modificările locale au fost salvate cu succes",
|
||||||
|
"success-note-l1": "Aplicația ar trebui să se reconstruiască automat.",
|
||||||
|
"success-note-l2": "Aceasta poate dura până la un minut.",
|
||||||
|
"success-note-l3": "Va trebui să reîmprospătați pagina pentru ca modificările să aibă efect.",
|
||||||
|
"error-msg-save-mode": "Vă rugăm să selectați un Mod de Salvare: Local sau Fișier",
|
||||||
|
"error-msg-cannot-save": "A apărut o eroare la salvarea configurației",
|
||||||
|
"error-msg-bad-json": "Eroare în JSON, posibil malformat",
|
||||||
|
"warning-msg-validation": "Avertisment de Validare",
|
||||||
|
"not-admin-note": "Nu puteți scrie modificările pe disc deoarece nu sunteți conectat ca administrator"
|
||||||
|
},
|
||||||
|
"app-rebuild": {
|
||||||
|
"title": "Reconstruire Aplicație",
|
||||||
|
"rebuild-note-l1": "O reconstruire este necesară pentru ca modificările scrise în fișierul conf.yml să aibă efect.",
|
||||||
|
"rebuild-note-l2": "Aceasta ar trebui să se întâmple automat, dar dacă nu s-a întâmplat, o puteți declanșa manual aici.",
|
||||||
|
"rebuild-note-l3": "Aceasta nu este necesară pentru modificările stocate local.",
|
||||||
|
"rebuild-button": "Începeți Reconstruirea",
|
||||||
|
"rebuilding-status-1": "Se reconstruiește...",
|
||||||
|
"rebuilding-status-2": "Aceasta poate dura câteva minute",
|
||||||
|
"error-permission": "Nu aveți permisiunea de a declanșa această acțiune",
|
||||||
|
"success-msg": "Reconstruirea a fost completată cu succes",
|
||||||
|
"fail-msg": "Operațiunea de reconstruire a eșuat",
|
||||||
|
"reload-note": "Este necesară reîncărcarea paginii pentru ca modificările să aibă efect",
|
||||||
|
"reload-button": "Reîncarcă Pagina"
|
||||||
|
},
|
||||||
|
"cloud-sync": {
|
||||||
|
"title": "Backup și Restaurare în Cloud",
|
||||||
|
"intro-l1": "Backup-ul și restaurarea în cloud este o caracteristică opțională, care vă permite să încărcați configurația pe internet și apoi să o restaurați pe orice alt dispozitiv sau instanță de Dashy.",
|
||||||
|
"intro-l2": "Toate datele sunt criptate end-to-end cu AES, folosind parola dumneavoastră ca cheie.",
|
||||||
|
"intro-l3": "Pentru mai multe informații, vă rugăm să consultați",
|
||||||
|
"intro-docs": "documentația",
|
||||||
|
"backup-title-setup": "Creați un Backup",
|
||||||
|
"backup-title-update": "Actualizați Backup-ul",
|
||||||
|
"password-label-setup": "Alegeți o Parolă",
|
||||||
|
"password-label-update": "Introduceți Parola",
|
||||||
|
"backup-button-setup": "Backup",
|
||||||
|
"backup-button-update": "Actualizați Backup-ul",
|
||||||
|
"backup-id-label": "ID-ul Dvs. de Backup",
|
||||||
|
"backup-id-note": "Acesta este utilizat pentru a restaura din backup-uri mai târziu. Deci păstrați-l, împreună cu parola dvs., într-un loc sigur.",
|
||||||
|
"restore-title": "Restaurare Backup",
|
||||||
|
"restore-id-label": "ID de Restaurare",
|
||||||
|
"restore-password-label": "Parola",
|
||||||
|
"restore-button": "Restaurare",
|
||||||
|
"backup-missing-password": "Lipsește Parola",
|
||||||
|
"backup-error-unknown": "Imposibil de procesat solicitarea",
|
||||||
|
"backup-error-password": "Parolă incorectă. Vă rugăm să introduceți parola actuală.",
|
||||||
|
"backup-success-msg": "Finalizat cu Succes",
|
||||||
|
"restore-success-msg": "Configurația a fost Restaurată cu Succes"
|
||||||
|
},
|
||||||
|
"menu": {
|
||||||
|
"open-section-title": "Deschide În",
|
||||||
|
"sametab": "Tab Curent",
|
||||||
|
"newtab": "Tab Nou",
|
||||||
|
"modal": "Modal Pop-Up",
|
||||||
|
"workspace": "Vizualizare Spațiu de Lucru",
|
||||||
|
"options-section-title": "Opțiuni",
|
||||||
|
"edit-item": "Editare",
|
||||||
|
"move-item": "Copiază sau Mută",
|
||||||
|
"remove-item": "Șterge"
|
||||||
|
},
|
||||||
|
"context-menus": {
|
||||||
|
"item": {
|
||||||
|
"open-section-title": "Deschide În",
|
||||||
|
"sametab": "Tab Curent",
|
||||||
|
"newtab": "Tab Nou",
|
||||||
|
"modal": "Modal Pop-Up",
|
||||||
|
"workspace": "Vizualizare Spațiu de Lucru",
|
||||||
|
"clipboard": "Copiază în Clipboard",
|
||||||
|
"options-section-title": "Opțiuni",
|
||||||
|
"edit-item": "Editare",
|
||||||
|
"move-item": "Copiază sau Mută",
|
||||||
|
"remove-item": "Șterge",
|
||||||
|
"copied-toast": "URL-ul a fost copiat în clipboard"
|
||||||
|
},
|
||||||
|
"section": {
|
||||||
|
"open-section": "Deschide Secțiunea",
|
||||||
|
"edit-section": "Editare",
|
||||||
|
"expand-collapse": "Extinde / Colapsează",
|
||||||
|
"move-section": "Mută La",
|
||||||
|
"remove-section": "Șterge"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"footer": {
|
||||||
|
"dev-by": "Dezvoltat de",
|
||||||
|
"licensed-under": "Licențiat sub",
|
||||||
|
"get-the": "Obțineți",
|
||||||
|
"source-code": "Codul Sursă"
|
||||||
|
},
|
||||||
|
"interactive-editor": {
|
||||||
|
"menu": {
|
||||||
|
"start-editing-tooltip": "Intră în Editorul Interactiv",
|
||||||
|
"edit-site-data-subheading": "Editează Datele Site-ului",
|
||||||
|
"edit-page-info-btn": "Editează Informațiile Paginii",
|
||||||
|
"edit-page-info-tooltip": "Titlul aplicației, descriere, link-uri de navigare, textul din footer, etc.",
|
||||||
|
"edit-app-config-btn": "Editează Configurația Aplicației",
|
||||||
|
"edit-app-config-tooltip": "Toate celelalte opțiuni de configurare a aplicației",
|
||||||
|
"edit-pages-btn": "Editează Paginile",
|
||||||
|
"edit-pages-tooltip": "Adaugă sau elimină vizualizări suplimentare",
|
||||||
|
"config-save-methods-subheading": "Opțiuni de Salvare a Configurației",
|
||||||
|
"save-locally-btn": "Salvează Local",
|
||||||
|
"save-locally-tooltip": "Salvează configurația local, în stocarea browserului. Aceasta nu va afecta fișierul tău de configurare, dar schimbările vor fi salvate doar pe acest dispozitiv",
|
||||||
|
"save-disk-btn": "Salvează pe Disc",
|
||||||
|
"save-disk-tooltip": "Salvează configurația în fișierul conf.yml de pe disc. Aceasta va face un backup și apoi va suprascrie configurația existentă",
|
||||||
|
"export-config-btn": "Exportă Configurația",
|
||||||
|
"export-config-tooltip": "Vizualizează și exportă noua configurație, fie într-un fișier, fie în clipboard",
|
||||||
|
"cloud-backup-btn": "Backup în Cloud",
|
||||||
|
"cloud-backup-tooltip": "Salvează un backup criptat al configurației în cloud",
|
||||||
|
"edit-raw-config-btn": "Editează Configurația Brută",
|
||||||
|
"edit-raw-config-tooltip": "Vizualizează și modifică configurația brută prin editorul JSON",
|
||||||
|
"cancel-changes-btn": "Anulează Modificările",
|
||||||
|
"cancel-changes-tooltip": "Resetează modificările curente și ieși din Modul de Editare. Aceasta nu va afecta configurația salvată",
|
||||||
|
"edit-mode-name": "Mod de Editare",
|
||||||
|
"edit-mode-subtitle": "Ești în Modul de Editare",
|
||||||
|
"edit-mode-description": "Aceasta înseamnă că poți face modificări la configurația ta și să previzualizezi rezultatele, dar până nu salvezi, niciuna dintre modificările tale nu va fi păstrată.",
|
||||||
|
"save-stage-btn": "Salvează",
|
||||||
|
"cancel-stage-btn": "Anulează",
|
||||||
|
"save-locally-warning": "Dacă vei continua, modificările vor fi salvate doar în browserul tău. Ar trebui să exporți o copie a configurației tale pentru utilizare pe alte mașini. Dorești să continui?"
|
||||||
|
},
|
||||||
|
"edit-item": {
|
||||||
|
"missing-title-err": "Este necesar un titlu pentru element"
|
||||||
|
},
|
||||||
|
"edit-section": {
|
||||||
|
"edit-section-title": "Editează Secțiunea",
|
||||||
|
"add-section-title": "Adaugă o Secțiune Nouă",
|
||||||
|
"edit-tooltip": "Clic pentru a edita, sau clic dreapta pentru mai multe opțiuni",
|
||||||
|
"remove-confirm": "Ești sigur că vrei să elimini această secțiune? Această acțiune poate fi anulată mai târziu."
|
||||||
|
},
|
||||||
|
"edit-app-config": {
|
||||||
|
"warning-msg-title": "Procedează cu Atenție",
|
||||||
|
"warning-msg-l1": "Următoarele opțiuni sunt pentru configurarea avansată a aplicației.",
|
||||||
|
"warning-msg-l2": "Dacă nu ești sigur în legătură cu oricare dintre câmpuri, te rog să consulți",
|
||||||
|
"warning-msg-docs": "documentația",
|
||||||
|
"warning-msg-l3": "pentru a evita consecințele nedorite."
|
||||||
|
},
|
||||||
|
"export": {
|
||||||
|
"export-title": "Exportă Configurația",
|
||||||
|
"copy-clipboard-btn": "Copiază în Clipboard",
|
||||||
|
"copy-clipboard-tooltip": "Copiază toată configurația aplicației în clipboard-ul sistemului, în format YAML",
|
||||||
|
"download-file-btn": "Descarcă ca Fișier",
|
||||||
|
"download-file-tooltip": "Descarcă toată configurația aplicației pe dispozitivul tău, într-un fișier YAML",
|
||||||
|
"view-title": "Vizualizează Configurația"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"widgets": {
|
||||||
|
"general": {
|
||||||
|
"loading": "Se încarcă...",
|
||||||
|
"show-more": "Extinde Detaliile",
|
||||||
|
"cpu-details": "Detalii CPU",
|
||||||
|
"mem-details": "Detalii Memorie",
|
||||||
|
"show-less": "Arată Mai Puțin",
|
||||||
|
"open-link": "Continuă Citirea"
|
||||||
|
},
|
||||||
|
"pi-hole": {
|
||||||
|
"status-heading": "Stare"
|
||||||
|
},
|
||||||
|
"stat-ping": {
|
||||||
|
"up": "Online",
|
||||||
|
"down": "Offline"
|
||||||
|
},
|
||||||
|
"net-data": {
|
||||||
|
"cpu-chart-title": "Istoric CPU",
|
||||||
|
"mem-chart-title": "Utilizare Memorie",
|
||||||
|
"mem-breakdown-title": "Detalii Memorie",
|
||||||
|
"load-chart-title": "Încărcare Sistem"
|
||||||
|
},
|
||||||
|
"glances": {
|
||||||
|
"disk-space-free": "Liber",
|
||||||
|
"disk-space-used": "Utilizat",
|
||||||
|
"disk-mount-point": "Punct de Montare",
|
||||||
|
"disk-file-system": "Sistem de Fișiere",
|
||||||
|
"disk-io-read": "Citire",
|
||||||
|
"disk-io-write": "Scriere",
|
||||||
|
"system-load-desc": "Numărul de procese așteptând în coada de execuție, mediat pe toate nucleele"
|
||||||
|
},
|
||||||
|
"system-info": {
|
||||||
|
"uptime": "Timp de Funcționare"
|
||||||
|
},
|
||||||
|
"flight-data": {
|
||||||
|
"arrivals": "Sosiri",
|
||||||
|
"departures": "Plecări"
|
||||||
|
},
|
||||||
|
"tfl-status": {
|
||||||
|
"good-service-all": "Servicii Bune pe Toate Liniile",
|
||||||
|
"good-service-rest": "Servicii Bune pe Celelalte Linii"
|
||||||
|
},
|
||||||
|
"synology-download": {
|
||||||
|
"download": "Descărcare",
|
||||||
|
"upload": "Încărcare",
|
||||||
|
"downloaded": "Descărcat",
|
||||||
|
"uploaded": "Încărcat",
|
||||||
|
"remaining": "Rămas",
|
||||||
|
"up": "Sus",
|
||||||
|
"down": "Jos"
|
||||||
|
},
|
||||||
|
"gluetun-status": {
|
||||||
|
"vpn-ip": "IP VPN",
|
||||||
|
"country": "Țară",
|
||||||
|
"region": "Regiune",
|
||||||
|
"city": "Oraș",
|
||||||
|
"post-code": "Cod Poștal",
|
||||||
|
"location": "Locație",
|
||||||
|
"timezone": "Fus Orar",
|
||||||
|
"organization": "Organizație"
|
||||||
|
},
|
||||||
|
"nextcloud": {
|
||||||
|
"active": "activ",
|
||||||
|
"and": "și",
|
||||||
|
"applications": "aplicații",
|
||||||
|
"available": "disponibil",
|
||||||
|
"away": "Plecat",
|
||||||
|
"cache-full": "CACHE PLIN",
|
||||||
|
"chat-room": "camera de chat",
|
||||||
|
"delete-all": "Șterge tot",
|
||||||
|
"delete-notification": "Șterge notificarea",
|
||||||
|
"disabled": "dezactivat",
|
||||||
|
"disk-quota": "Cotă de Disc",
|
||||||
|
"disk-space": "Spațiu pe Disc",
|
||||||
|
"dnd": "Nu Deranja",
|
||||||
|
"email": "email",
|
||||||
|
"enabled": "activat",
|
||||||
|
"federated-shares-ucfirst": "Partajări Federate",
|
||||||
|
"federated-shares": "partajări federate",
|
||||||
|
"files": "fișier{plural}",
|
||||||
|
"free": "liber",
|
||||||
|
"groups": "grupuri",
|
||||||
|
"hit-rate": "rata de accesare",
|
||||||
|
"hits": "accesări",
|
||||||
|
"home": "acasă",
|
||||||
|
"in": "în",
|
||||||
|
"keys": "chei",
|
||||||
|
"last-24-hours": "ultimele 24 de ore",
|
||||||
|
"last-5-minutes": "în ultimele 5 minute",
|
||||||
|
"last-hour": "în ultima oră",
|
||||||
|
"last-login": "Ultima autentificare",
|
||||||
|
"last-restart": "Ultimul restart",
|
||||||
|
"load-averages": "Mediile de Încărcare pe toate nucleele CPU",
|
||||||
|
"local-shares": "Partajări Locale",
|
||||||
|
"local": "local",
|
||||||
|
"max-keys": "chei maxime",
|
||||||
|
"memory-used": "memorie utilizată",
|
||||||
|
"memory-utilisation": "utilizarea memoriei",
|
||||||
|
"memory": "memorie",
|
||||||
|
"misses": "rateuri",
|
||||||
|
"no-notifications": "Fără notificări",
|
||||||
|
"no-pending-updates": "fără actualizări în așteptare",
|
||||||
|
"nothing-to-show": "Nimic de afișat aici în acest moment",
|
||||||
|
"of-which": "din care",
|
||||||
|
"of": "din",
|
||||||
|
"offline": "Deconectat",
|
||||||
|
"online": "Conectat",
|
||||||
|
"other": "alt",
|
||||||
|
"overall": "În total",
|
||||||
|
"private-link": "link privat",
|
||||||
|
"public-link": "link public",
|
||||||
|
"quota-enabled": "Cota de Disc este {not}activată pentru acest utilizator",
|
||||||
|
"received": "primit",
|
||||||
|
"scripts": "scripturi",
|
||||||
|
"sent": "trimis",
|
||||||
|
"started": "Început",
|
||||||
|
"storages-by-type": "Stocări pe tip",
|
||||||
|
"storages": "stocare{plural}",
|
||||||
|
"strings-use": "utilizare șiruri",
|
||||||
|
"tasks": "Sarcini",
|
||||||
|
"total-files": "total fișiere",
|
||||||
|
"total-users": "total utilizatori",
|
||||||
|
"total": "total",
|
||||||
|
"until": "Până la",
|
||||||
|
"updates-available-for": "Actualizări disponibile pentru",
|
||||||
|
"updates-available": "actualizare{plural} disponibilă",
|
||||||
|
"used": "utilizat",
|
||||||
|
"user": "utilizator",
|
||||||
|
"using": "utilizând",
|
||||||
|
"version": "versiune",
|
||||||
|
"wasted": "pierdut"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -63,8 +63,8 @@
|
|||||||
"privacy-and-security": "Конфіденційність та безпека",
|
"privacy-and-security": "Конфіденційність та безпека",
|
||||||
"privacy-and-security-l1": "Для детальної інформації про те, як Dashy керує вашими даними, див.",
|
"privacy-and-security-l1": "Для детальної інформації про те, як Dashy керує вашими даними, див.",
|
||||||
"privacy-and-security-privacy-policy": "Політика конфіденційності",
|
"privacy-and-security-privacy-policy": "Політика конфіденційності",
|
||||||
"app-info.privacy-and-security-advice": "Щоб отримати поради щодо захисту вашої інформаційної панелі, ви можете звернутися до розділу",
|
"privacy-and-security-advice": "Щоб отримати поради щодо захисту вашої інформаційної панелі, ви можете звернутися до розділу",
|
||||||
"app-info.privacy-and-security-advice-link": "Документи керування",
|
"privacy-and-security-advice-link": "Документи керування",
|
||||||
"privacy-and-security-security-issue": "Якщо ви виявили потенційну проблему з безпекою, повідомте про це до розділу",
|
"privacy-and-security-security-issue": "Якщо ви виявили потенційну проблему з безпекою, повідомте про це до розділу",
|
||||||
"privacy-and-security-security-policy": "Політика безпеки",
|
"privacy-and-security-security-policy": "Політика безпеки",
|
||||||
"license": "Ліцензія",
|
"license": "Ліцензія",
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
"error-missing-password": "密码空缺",
|
"error-missing-password": "密码空缺",
|
||||||
"error-incorrect-username": "用户不存在",
|
"error-incorrect-username": "用户不存在",
|
||||||
"error-incorrect-password": "密码不正确",
|
"error-incorrect-password": "密码不正确",
|
||||||
"success-message": "登陆成功。。。",
|
"success-message": "登陆成功。",
|
||||||
"logout-message": "注销",
|
"logout-message": "注销",
|
||||||
"already-logged-in-title": "已经成功登陆",
|
"already-logged-in-title": "已经成功登陆",
|
||||||
"already-logged-in-text": "你的登陆身份",
|
"already-logged-in-text": "你的登陆身份",
|
||||||
@ -37,11 +37,11 @@
|
|||||||
"log-out-button": "注销",
|
"log-out-button": "注销",
|
||||||
"proceed-guest-button": "以游客身份前往",
|
"proceed-guest-button": "以游客身份前往",
|
||||||
"guest-intro-1": "该实例已启用访客访问.",
|
"guest-intro-1": "该实例已启用访客访问.",
|
||||||
"guest-intro-2": "访客只有访问权限,无法保存变更",
|
"guest-intro-2": "访客只有访问权限,无法保存变更",
|
||||||
"error": "错误",
|
"error": "错误",
|
||||||
"error-no-user-configured": "没有启用验证,或者未配置用户",
|
"error-no-user-configured": "没有启用验证,或者未配置用户",
|
||||||
"error-go-home-button": "Go Home",
|
"error-go-home-button": "Go Home",
|
||||||
"logged-in-guest": "以访客身份登陆,正在跳转...",
|
"logged-in-guest": "以访客身份登陆,正在跳转...",
|
||||||
"error-guest-access": "不允许访客访问"
|
"error-guest-access": "不允许访客访问"
|
||||||
},
|
},
|
||||||
"app-info": {
|
"app-info": {
|
||||||
@ -63,8 +63,8 @@
|
|||||||
"privacy-and-security": "隐私与安全",
|
"privacy-and-security": "隐私与安全",
|
||||||
"privacy-and-security-l1": "关于Dashy如何管理您的数据的详细信息,请参阅",
|
"privacy-and-security-l1": "关于Dashy如何管理您的数据的详细信息,请参阅",
|
||||||
"privacy-and-security-privacy-policy": "隐私政策",
|
"privacy-and-security-privacy-policy": "隐私政策",
|
||||||
"app-info.privacy-and-security-advice": "如果您需要保护您的仪表盘,请参考",
|
"privacy-and-security-advice": "如果您需要保护您的仪表盘,请参考",
|
||||||
"app-info.privacy-and-security-advice-link": "管理文档",
|
"privacy-and-security-advice-link": "管理文档",
|
||||||
"privacy-and-security-security-issue": "如果您发现潜在的安全问题,请遵循我们的",
|
"privacy-and-security-security-issue": "如果您发现潜在的安全问题,请遵循我们的",
|
||||||
"privacy-and-security-security-policy": "安全政策",
|
"privacy-and-security-security-policy": "安全政策",
|
||||||
"license": "许可证",
|
"license": "许可证",
|
||||||
@ -78,22 +78,22 @@
|
|||||||
"config": {
|
"config": {
|
||||||
"main-tab": "主菜单",
|
"main-tab": "主菜单",
|
||||||
"view-config-tab": "视图设置",
|
"view-config-tab": "视图设置",
|
||||||
"edit-config-tab": "编辑设置",
|
"edit-config-tab": "修改设置",
|
||||||
"custom-css-tab": "自定义样式",
|
"custom-css-tab": "自定义样式",
|
||||||
"heading": "设置选项",
|
"heading": "设置选项",
|
||||||
"download-config-button": "下载配置",
|
"download-config-button": "下载配置",
|
||||||
"edit-config-button": "编辑设置",
|
"edit-config-button": "修改设置",
|
||||||
"edit-css-button": "编辑自定义 CSS",
|
"edit-css-button": "自定义CSS",
|
||||||
"cloud-sync-button": "启用云端同步",
|
"cloud-sync-button": "云端同步",
|
||||||
"edit-cloud-sync-button": "编辑云端同步",
|
"edit-cloud-sync-button": "修改云端同步",
|
||||||
"rebuild-app-button": "重建应用",
|
"rebuild-app-button": "重建应用",
|
||||||
"change-language-button": "更改语言",
|
"change-language-button": "更改语言",
|
||||||
"reset-settings-button": "恢复本地设置",
|
"reset-settings-button": "恢复默认设置",
|
||||||
"disabled-note": "您的管理员已禁用某些配置功能",
|
"disabled-note": "您的管理员已禁用某些配置功能",
|
||||||
"small-screen-note": "您正在使用非常小的屏幕,某些菜单屏幕可能不够优化",
|
"small-screen-note": "您正在使用非常小的屏幕,某些菜单屏幕可能不够优化",
|
||||||
"app-info-button": "应用详情",
|
"app-info-button": "应用详情",
|
||||||
"backup-note": "建议在进行更改之前备份你的配置。",
|
"backup-note": "建议在进行更改之前备份你的配置。",
|
||||||
"reset-config-msg-l1": "这将从本地存储中删除所有用户设置,但不会影响‘conf.yml’文件。",
|
"reset-config-msg-l1": "这将从本地存储中删除所有用户设置,但不会影响 conf.yml 文件。",
|
||||||
"reset-config-msg-l2": "如果想在以后使用它们,应该首先备份你所做的任何更改。",
|
"reset-config-msg-l2": "如果想在以后使用它们,应该首先备份你所做的任何更改。",
|
||||||
"reset-config-msg-l3": "确定执行吗?",
|
"reset-config-msg-l3": "确定执行吗?",
|
||||||
"data-cleared-msg": "成功清空数据",
|
"data-cleared-msg": "成功清空数据",
|
||||||
@ -103,9 +103,9 @@
|
|||||||
"reset-config-label": "重置设置",
|
"reset-config-label": "重置设置",
|
||||||
"css-save-btn": "保存更改",
|
"css-save-btn": "保存更改",
|
||||||
"css-note-label": "注意",
|
"css-note-label": "注意",
|
||||||
"css-note-l1": "你需要刷新页面才能使更改生效。",
|
"css-note-l1": "需刷新页面使其生效。",
|
||||||
"css-note-l2": "样式覆盖仅存储在本地,因此建议复制你的 CSS。",
|
"css-note-l2": "自定义样式仅在本地有效,设置储存在当前浏览器,建议做好备份。",
|
||||||
"css-note-l3": "要删除所有自定义样式,请删除内容并点击保存更改",
|
"css-note-l3": "如需删除自定义样式,清空上面内容并点击保存。",
|
||||||
"custom-css": {
|
"custom-css": {
|
||||||
"title": "自定义 CSS",
|
"title": "自定义 CSS",
|
||||||
"base-theme": "基础主题"
|
"base-theme": "基础主题"
|
||||||
@ -132,8 +132,8 @@
|
|||||||
"sign-out-tooltip": "注销",
|
"sign-out-tooltip": "注销",
|
||||||
"sign-in-tooltip": "登陆",
|
"sign-in-tooltip": "登陆",
|
||||||
"sign-in-welcome": "你好 {username}!",
|
"sign-in-welcome": "你好 {username}!",
|
||||||
"hide": "Hide",
|
"hide": "隐藏",
|
||||||
"open": "Open"
|
"open": "打开"
|
||||||
},
|
},
|
||||||
"updates": {
|
"updates": {
|
||||||
"app-version-note": "Dashy 版本",
|
"app-version-note": "Dashy 版本",
|
||||||
@ -195,9 +195,10 @@
|
|||||||
"reload-button": "刷新页面"
|
"reload-button": "刷新页面"
|
||||||
},
|
},
|
||||||
"cloud-sync": {
|
"cloud-sync": {
|
||||||
"title": "云备份 & 云恢复",
|
"title": "云备份&恢复",
|
||||||
"intro-l1": "云备份和云恢复是一项试验性功能,你将配置上传到网络,然后在其他设备或 Dashy 实例上恢复。",
|
"intro-l1": "云备份和云恢复是一项试验性功能,你将配置上传到网络,然后在其他设备或 Dashy 实例上恢复。",
|
||||||
"intro-l2": "所有数据都使用AES端对端加密,使用你的密码作为密钥。",
|
"intro-l2": "所有数据都使用AES端对端加密,使用你的密码作为密钥。",
|
||||||
|
"intro-docs": "文档",
|
||||||
"intro-l3": "有关更多信息,请参阅",
|
"intro-l3": "有关更多信息,请参阅",
|
||||||
"backup-title-setup": "创建备份",
|
"backup-title-setup": "创建备份",
|
||||||
"backup-title-update": "更新备份",
|
"backup-title-update": "更新备份",
|
||||||
@ -268,9 +269,9 @@
|
|||||||
"edit-pages-tooltip": "添加或删除其他的视图",
|
"edit-pages-tooltip": "添加或删除其他的视图",
|
||||||
"config-save-methods-subheading": "配置保存选项",
|
"config-save-methods-subheading": "配置保存选项",
|
||||||
"save-locally-btn": "暂存本地",
|
"save-locally-btn": "暂存本地",
|
||||||
"save-locally-tooltip": "将设置保存在本地浏览器上. 这不会影响配置文件,但更改只会保留在当前设备上.",
|
"save-locally-tooltip": "将设置保存在浏览器上。这不会影响配置文件,仅作用于当前的浏览器。",
|
||||||
"save-disk-btn": "保存",
|
"save-disk-btn": "保存",
|
||||||
"save-disk-tooltip": "将设置保存到服务端的conf.yml文件.它会备份之前的配置文件.",
|
"save-disk-tooltip": "将设置保存到服务端的conf.yml文件,它会备份之前的配置文件.",
|
||||||
"export-config-btn": "导出配置",
|
"export-config-btn": "导出配置",
|
||||||
"export-config-tooltip": "查看并导出新的配置到 文件 或 剪贴板",
|
"export-config-tooltip": "查看并导出新的配置到 文件 或 剪贴板",
|
||||||
"cloud-backup-btn": "备份到云端",
|
"cloud-backup-btn": "备份到云端",
|
||||||
@ -284,10 +285,10 @@
|
|||||||
"edit-mode-description": "你可以对配置进行修改并预览,在保存之前,你的任何更改都不会被保留。",
|
"edit-mode-description": "你可以对配置进行修改并预览,在保存之前,你的任何更改都不会被保留。",
|
||||||
"save-stage-btn": "保存",
|
"save-stage-btn": "保存",
|
||||||
"cancel-stage-btn": "取消",
|
"cancel-stage-btn": "取消",
|
||||||
"save-locally-warning": "如果你继续,更改将仅保存在你的浏览器中。 你应该导出配置的副本以在其他机器上使用。 你想继续吗?"
|
"save-locally-warning": "配置将保存到你当前的浏览器上。你也可以导出配置到其他设备上使用。是否继续?"
|
||||||
},
|
},
|
||||||
"edit-item": {
|
"edit-item": {
|
||||||
"missing-title-err": "项目标题是必需的"
|
"missing-title-err": "标题是必需的"
|
||||||
},
|
},
|
||||||
"edit-section": {
|
"edit-section": {
|
||||||
"edit-section-title": "编辑 Section",
|
"edit-section-title": "编辑 Section",
|
||||||
@ -314,7 +315,9 @@
|
|||||||
"widgets": {
|
"widgets": {
|
||||||
"general": {
|
"general": {
|
||||||
"loading": "加载中...",
|
"loading": "加载中...",
|
||||||
"show-more": "展开详情",
|
"show-more": "显示更多",
|
||||||
|
"cpu-details": "CPU 详情",
|
||||||
|
"mem-details": "内存 详情",
|
||||||
"show-less": "显示更少信息",
|
"show-less": "显示更少信息",
|
||||||
"open-link": "继续读取"
|
"open-link": "继续读取"
|
||||||
},
|
},
|
||||||
|
@ -63,8 +63,8 @@
|
|||||||
"privacy-and-security": "隱私權和安全性",
|
"privacy-and-security": "隱私權和安全性",
|
||||||
"privacy-and-security-l1": "若要了解 Dashy 是如何管理您的資料,請參閱",
|
"privacy-and-security-l1": "若要了解 Dashy 是如何管理您的資料,請參閱",
|
||||||
"privacy-and-security-privacy-policy": "隱私權政策",
|
"privacy-and-security-privacy-policy": "隱私權政策",
|
||||||
"app-info.privacy-and-security-advice": "關於提升儀錶板安全性的建議,請參閱",
|
"privacy-and-security-advice": "關於提升儀錶板安全性的建議,請參閱",
|
||||||
"app-info.privacy-and-security-advice-link": "管理文件",
|
"privacy-and-security-advice-link": "管理文件",
|
||||||
"privacy-and-security-security-issue": "若您找到潛在的安全問題,請回報,並遵照我們的",
|
"privacy-and-security-security-issue": "若您找到潛在的安全問題,請回報,並遵照我們的",
|
||||||
"privacy-and-security-security-policy": "安全政策",
|
"privacy-and-security-security-policy": "安全政策",
|
||||||
"license": "授權條款",
|
"license": "授權條款",
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
<!-- License -->
|
<!-- License -->
|
||||||
<h3>{{ $t('app-info.license') }}</h3>
|
<h3>{{ $t('app-info.license') }}</h3>
|
||||||
{{ $t('app-info.license-under') }} <a href="https://github.com/Lissy93/dashy/blob/master/LICENSE">MIT X11</a>.
|
{{ $t('app-info.license-under') }} <a href="https://github.com/Lissy93/dashy/blob/master/LICENSE">MIT X11</a>.
|
||||||
Copyright <a href="https://aliciasykes.com">Alicia Sykes</a> © 2021.<br>
|
Copyright <a href="https://aliciasykes.com">Alicia Sykes</a> © {{new Date().getFullYear()}}.<br>
|
||||||
{{ $t('app-info.licence-third-party') }} <a href="https://github.com/Lissy93/dashy/blob/master/.github/LEGAL.md">{{ $t('app-info.licence-third-party-link') }}</a>.<br>
|
{{ $t('app-info.licence-third-party') }} <a href="https://github.com/Lissy93/dashy/blob/master/.github/LEGAL.md">{{ $t('app-info.licence-third-party-link') }}</a>.<br>
|
||||||
{{ $t('app-info.list-contributors') }} <a href="https://github.com/Lissy93/dashy/blob/master/docs/credits.md">{{ $t('app-info.list-contributors-link') }}</a>.
|
{{ $t('app-info.list-contributors') }} <a href="https://github.com/Lissy93/dashy/blob/master/docs/credits.md">{{ $t('app-info.list-contributors-link') }}</a>.
|
||||||
<!-- App Version -->
|
<!-- App Version -->
|
||||||
|
@ -155,13 +155,24 @@ export default {
|
|||||||
},
|
},
|
||||||
/* When restored data is revieved, then save to local storage, and apply it in state */
|
/* When restored data is revieved, then save to local storage, and apply it in state */
|
||||||
applyRestoredData(config, backupId) {
|
applyRestoredData(config, backupId) {
|
||||||
// Store restored data in local storage
|
const isSubPage = !!this.$store.state.currentConfigInfo.confId;
|
||||||
|
if (isSubPage) { // Apply to sub-page only
|
||||||
|
const subConfigId = this.$store.state.currentConfigInfo.confId;
|
||||||
|
const sectionStorageKey = `${localStorageKeys.CONF_SECTIONS}-${subConfigId}`;
|
||||||
|
const pageInfoStorageKey = `${localStorageKeys.PAGE_INFO}-${subConfigId}`;
|
||||||
|
const themeStoreKey = `${localStorageKeys.THEME}-${subConfigId}`;
|
||||||
|
localStorage.setItem(sectionStorageKey, JSON.stringify(config.sections));
|
||||||
|
localStorage.setItem(pageInfoStorageKey, JSON.stringify(config.pageInfo));
|
||||||
|
localStorage.setItem(themeStoreKey, config.appConfig.theme);
|
||||||
|
} else { // Apply to main config
|
||||||
localStorage.setItem(localStorageKeys.CONF_SECTIONS, JSON.stringify(config.sections));
|
localStorage.setItem(localStorageKeys.CONF_SECTIONS, JSON.stringify(config.sections));
|
||||||
localStorage.setItem(localStorageKeys.APP_CONFIG, JSON.stringify(config.appConfig));
|
localStorage.setItem(localStorageKeys.APP_CONFIG, JSON.stringify(config.appConfig));
|
||||||
localStorage.setItem(localStorageKeys.PAGE_INFO, JSON.stringify(config.pageInfo));
|
localStorage.setItem(localStorageKeys.PAGE_INFO, JSON.stringify(config.pageInfo));
|
||||||
|
localStorage.setItem(localStorageKeys.CONF_PAGES, JSON.stringify(config.pages || []));
|
||||||
if (config.appConfig.theme) {
|
if (config.appConfig.theme) {
|
||||||
localStorage.setItem(localStorageKeys.THEME, config.appConfig.theme);
|
localStorage.setItem(localStorageKeys.THEME, config.appConfig.theme);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Save hashed token in local storage
|
// Save hashed token in local storage
|
||||||
this.setBackupIdLocally(backupId, this.restorePassword);
|
this.setBackupIdLocally(backupId, this.restorePassword);
|
||||||
// Update the current state
|
// Update the current state
|
||||||
|
@ -47,16 +47,17 @@
|
|||||||
</Button>
|
</Button>
|
||||||
<!-- Display app version and language -->
|
<!-- Display app version and language -->
|
||||||
<p class="language">{{ getLanguage() }}</p>
|
<p class="language">{{ getLanguage() }}</p>
|
||||||
<p v-if="$store.state.currentConfigInfo" class="config-location">
|
<!-- Display location of config file -->
|
||||||
Using Config From<br>
|
<p class="config-location">
|
||||||
{{ $store.state.currentConfigInfo.confPath }}
|
Using config from
|
||||||
|
<a :href="configPath">{{ configPath }}</a>
|
||||||
</p>
|
</p>
|
||||||
<AppVersion />
|
<AppVersion />
|
||||||
</div>
|
</div>
|
||||||
<!-- Display note if Config disabled, or if on mobile -->
|
<!-- Display note if Config disabled, or if on mobile -->
|
||||||
<p v-if="!enableConfig" class="config-disabled-note">{{ $t('config.disabled-note') }}</p>
|
<p v-if="!enableConfig" class="config-disabled-note">{{ $t('config.disabled-note') }}</p>
|
||||||
<p class="small-screen-note" style="display: none;">{{ $t('config.small-screen-note') }}</p>
|
<p class="small-screen-note" style="display: none;">{{ $t('config.small-screen-note') }}</p>
|
||||||
<div class="config-note">
|
<div class="config-note" @click="openExportConfigModal">
|
||||||
<span>{{ $t('config.backup-note') }}</span>
|
<span>{{ $t('config.backup-note') }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -116,6 +117,11 @@ export default {
|
|||||||
enableConfig() {
|
enableConfig() {
|
||||||
return this.$store.getters.permissions.allowViewConfig;
|
return this.$store.getters.permissions.allowViewConfig;
|
||||||
},
|
},
|
||||||
|
configPath() {
|
||||||
|
return this.$store.state.currentConfigInfo?.confPath
|
||||||
|
|| process.env.VUE_APP_CONFIG_PATH
|
||||||
|
|| '/conf.yml';
|
||||||
|
},
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
Button,
|
Button,
|
||||||
@ -248,8 +254,12 @@ a.hyperlink-wrapper {
|
|||||||
p.app-version, p.language, p.config-location {
|
p.app-version, p.language, p.config-location {
|
||||||
margin: 0.5rem auto;
|
margin: 0.5rem auto;
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
color: var(--transparent-white-50);
|
color: var(--config-settings-color);
|
||||||
cursor: default;
|
cursor: default;
|
||||||
|
opacity: var(--dimming-factor);
|
||||||
|
a {
|
||||||
|
color: var(--config-settings-color);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
div.code-container {
|
div.code-container {
|
||||||
|
@ -115,7 +115,10 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.jsonData = this.config;
|
const jsonData = { ...this.config };
|
||||||
|
jsonData.sections = (jsonData.sections || []).map(({ filteredItems, ...section }) => section);
|
||||||
|
if (!jsonData.pageInfo) jsonData.pageInfo = { title: 'Dashy' };
|
||||||
|
this.jsonData = jsonData;
|
||||||
if (!this.allowWriteToDisk) this.saveMode = 'local';
|
if (!this.allowWriteToDisk) this.saveMode = 'local';
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@ -141,7 +144,11 @@ export default {
|
|||||||
this.$modal.hide(modalNames.CONF_EDITOR);
|
this.$modal.hide(modalNames.CONF_EDITOR);
|
||||||
},
|
},
|
||||||
writeToDisk() {
|
writeToDisk() {
|
||||||
this.writeConfigToDisk(this.config);
|
const newData = this.jsonData;
|
||||||
|
this.writeConfigToDisk(newData);
|
||||||
|
// this.$store.commit(StoreKeys.SET_APP_CONFIG, newData.appConfig);
|
||||||
|
this.$store.commit(StoreKeys.SET_PAGE_INFO, newData.pageInfo);
|
||||||
|
this.$store.commit(StoreKeys.SET_SECTIONS, newData.sections);
|
||||||
},
|
},
|
||||||
saveLocally() {
|
saveLocally() {
|
||||||
const msg = this.$t('interactive-editor.menu.save-locally-warning');
|
const msg = this.$t('interactive-editor.menu.save-locally-warning');
|
||||||
|
@ -94,6 +94,7 @@ export default {
|
|||||||
const raw = rawAppConfig;
|
const raw = rawAppConfig;
|
||||||
const isEmptyObject = (obj) => (typeof obj === 'object' && Object.keys(obj).length === 0);
|
const isEmptyObject = (obj) => (typeof obj === 'object' && Object.keys(obj).length === 0);
|
||||||
const isEmpty = (value) => (value === undefined || isEmptyObject(value));
|
const isEmpty = (value) => (value === undefined || isEmptyObject(value));
|
||||||
|
|
||||||
// Delete empty values
|
// Delete empty values
|
||||||
Object.keys(raw).forEach(key => {
|
Object.keys(raw).forEach(key => {
|
||||||
if (isEmpty(raw[key])) delete raw[key];
|
if (isEmpty(raw[key])) delete raw[key];
|
||||||
|
@ -22,6 +22,14 @@
|
|||||||
<DownloadConfigIcon />
|
<DownloadConfigIcon />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- Show path to which config file is being used -->
|
||||||
|
<div class="config-path-info">
|
||||||
|
<h3>Config Location</h3>
|
||||||
|
<p>
|
||||||
|
The base config file you are currently using is
|
||||||
|
<a :href="configPath">{{ configPath }}</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
<!-- View Config in Tree Mode Section -->
|
<!-- View Config in Tree Mode Section -->
|
||||||
<h3>{{ $t('interactive-editor.export.view-title') }}</h3>
|
<h3>{{ $t('interactive-editor.export.view-title') }}</h3>
|
||||||
<tree-view :data="config" class="config-tree-view" />
|
<tree-view :data="config" class="config-tree-view" />
|
||||||
@ -61,6 +69,11 @@ export default {
|
|||||||
allowViewConfig() {
|
allowViewConfig() {
|
||||||
return this.$store.getters.permissions.allowViewConfig;
|
return this.$store.getters.permissions.allowViewConfig;
|
||||||
},
|
},
|
||||||
|
configPath() {
|
||||||
|
return this.$store.state.currentConfigInfo?.confPath
|
||||||
|
|| process.env.VUE_APP_CONFIG_PATH
|
||||||
|
|| '/conf.yml';
|
||||||
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
convertJsonToYaml() {
|
convertJsonToYaml() {
|
||||||
@ -121,6 +134,13 @@ export default {
|
|||||||
border-bottom: 1px dashed var(--interactive-editor-color);
|
border-bottom: 1px dashed var(--interactive-editor-color);
|
||||||
button { margin: 0 1rem; }
|
button { margin: 0 1rem; }
|
||||||
}
|
}
|
||||||
|
.config-path-info {
|
||||||
|
p, a {
|
||||||
|
color: var(--interactive-editor-color);
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
border-bottom: 1px dashed var(--interactive-editor-color);
|
||||||
|
}
|
||||||
.config-tree-view {
|
.config-tree-view {
|
||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
font-family: var(--font-monospace);
|
font-family: var(--font-monospace);
|
||||||
|
@ -64,7 +64,6 @@ export default {
|
|||||||
return this.$store.state.editMode;
|
return this.$store.state.editMode;
|
||||||
},
|
},
|
||||||
sectionKey() {
|
sectionKey() {
|
||||||
if (this.isEditMode) return undefined;
|
|
||||||
return `collapsible-${this.uniqueKey}`;
|
return `collapsible-${this.uniqueKey}`;
|
||||||
},
|
},
|
||||||
collapseClass() {
|
collapseClass() {
|
||||||
@ -104,12 +103,23 @@ export default {
|
|||||||
watch: {
|
watch: {
|
||||||
checkboxState(newState) {
|
checkboxState(newState) {
|
||||||
this.isExpanded = newState;
|
this.isExpanded = newState;
|
||||||
|
this.updateLocalStorage(); // Save every change immediately
|
||||||
},
|
},
|
||||||
uniqueKey() {
|
uniqueKey(newVal, oldVal) {
|
||||||
this.checkboxState = this.isExpanded;
|
if (newVal !== oldVal) {
|
||||||
|
this.refreshCollapseState(); // Refresh state when key changes
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
refreshCollapseState() {
|
||||||
|
this.checkboxState = this.isExpanded;
|
||||||
|
},
|
||||||
|
updateLocalStorage() {
|
||||||
|
const collapseState = this.locallyStoredCollapseStates();
|
||||||
|
collapseState[this.uniqueKey] = this.checkboxState;
|
||||||
|
localStorage.setItem(localStorageKeys.COLLAPSE_STATE, JSON.stringify(collapseState));
|
||||||
|
},
|
||||||
/* Either expand or collapse section, based on it's current state */
|
/* Either expand or collapse section, based on it's current state */
|
||||||
toggle() {
|
toggle() {
|
||||||
this.checkboxState = !this.checkboxState;
|
this.checkboxState = !this.checkboxState;
|
||||||
|
@ -9,7 +9,8 @@
|
|||||||
:target="anchorTarget"
|
:target="anchorTarget"
|
||||||
:class="`item ${makeClassList}`"
|
:class="`item ${makeClassList}`"
|
||||||
v-tooltip="getTooltipOptions()"
|
v-tooltip="getTooltipOptions()"
|
||||||
rel="noopener noreferrer" tabindex="0"
|
:rel="`${item.rel || 'noopener noreferrer'}`"
|
||||||
|
tabindex="0"
|
||||||
:id="`link-${item.id}`"
|
:id="`link-${item.id}`"
|
||||||
:style="customStyle"
|
:style="customStyle"
|
||||||
>
|
>
|
||||||
@ -255,8 +256,12 @@ export default {
|
|||||||
-webkit-line-clamp: 3;
|
-webkit-line-clamp: 3;
|
||||||
-webkit-box-orient: vertical;
|
-webkit-box-orient: vertical;
|
||||||
word-break: keep-all;
|
word-break: keep-all;
|
||||||
|
overflow: hidden;
|
||||||
span.text {
|
span.text {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
display: block;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -385,6 +390,7 @@ p.description {
|
|||||||
font-size: .9em;
|
font-size: .9em;
|
||||||
line-height: 1rem;
|
line-height: 1rem;
|
||||||
height: 2rem;
|
height: 2rem;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -74,8 +74,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<!-- Modal for opening in modal view -->
|
<!-- Modal for opening in modal view -->
|
||||||
<IframeModal
|
<IframeModal
|
||||||
:ref="`iframeModal`"
|
:ref="`iframeModal-${groupId}`"
|
||||||
:name="`iframeModal`"
|
:name="`iframeModal-${groupId}`"
|
||||||
@closed="$emit('itemClicked')"
|
@closed="$emit('itemClicked')"
|
||||||
/>
|
/>
|
||||||
<!-- Edit item menu -->
|
<!-- Edit item menu -->
|
||||||
@ -213,7 +213,7 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
/* Opens the iframe modal */
|
/* Opens the iframe modal */
|
||||||
triggerModal(url) {
|
triggerModal(url) {
|
||||||
this.$refs.iframeModal.show(url);
|
this.$refs[`iframeModal-${this.groupId}`].show(url);
|
||||||
},
|
},
|
||||||
/* Sorts items alphabetically using the title attribute */
|
/* Sorts items alphabetically using the title attribute */
|
||||||
sortAlphabetically(items) {
|
sortAlphabetically(items) {
|
||||||
|
153
src/components/PageStrcture/CriticalError.vue
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
<template>
|
||||||
|
<div class="critical-error-wrap" v-if="shouldShow">
|
||||||
|
<button class="close" title="Close Warning" @click="close">🗙</button>
|
||||||
|
<h3>{{ $t('critical-error.title') }}</h3>
|
||||||
|
<p>{{ $t('critical-error.subtitle') }}</p>
|
||||||
|
<h4>{{ $t('critical-error.sub-ensure-that') }}</h4>
|
||||||
|
<ul>
|
||||||
|
<li>The configuration file can be found at the specified location</li>
|
||||||
|
<li>There are no CORS rules preventing client-side access</li>
|
||||||
|
<li>The YAML is valid, parsable and matches the schema</li>
|
||||||
|
</ul>
|
||||||
|
<h4>{{ $t('critical-error.sub-error-details') }}</h4>
|
||||||
|
<pre>{{ this.$store.state.criticalError }}</pre>
|
||||||
|
<h4>{{ $t('critical-error.sub-next-steps') }}</h4>
|
||||||
|
<ul>
|
||||||
|
<li>Check the browser console for more details
|
||||||
|
(<a href="https://github.com/Lissy93/dashy/blob/master/docs/troubleshooting.md#how-to-open-browser-console">see how</a>)
|
||||||
|
</li>
|
||||||
|
<li>View the
|
||||||
|
<a href="https://github.com/Lissy93/dashy/blob/master/docs/troubleshooting.md">Troubleshooting Guide</a>
|
||||||
|
and <a href="https://dashy.to/docs/">Docs</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
If you've verified the config is present, accessible and valid, and cannot find the solution
|
||||||
|
in the troubleshooting, docs or GitHub issues,
|
||||||
|
then <a href="https://github.com/Lissy93/dashy/issues/new/choose">open a ticket on GitHub</a>
|
||||||
|
</li>
|
||||||
|
<li>Click 'Ignore Critical Errors' below to not show this warning again</li>
|
||||||
|
</ul>
|
||||||
|
<button class="user-doesnt-care" @click="ignoreWarning">
|
||||||
|
{{ $t('critical-error.ignore-button') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { localStorageKeys } from '@/utils/defaults';
|
||||||
|
import Keys from '@/utils/StoreMutations';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'CriticalError',
|
||||||
|
computed: {
|
||||||
|
/* Determines if we should show this component.
|
||||||
|
* If error present AND user hasn't disabled */
|
||||||
|
shouldShow() {
|
||||||
|
return this.$store.state.criticalError
|
||||||
|
&& !localStorage[localStorageKeys.DISABLE_CRITICAL_WARNING];
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/* Ignore all future errors, by putting a key in local storage */
|
||||||
|
ignoreWarning() {
|
||||||
|
localStorage.setItem(localStorageKeys.DISABLE_CRITICAL_WARNING, true);
|
||||||
|
this.close();
|
||||||
|
},
|
||||||
|
/* Close this dialog, by removing this error from the local store */
|
||||||
|
close() {
|
||||||
|
this.$store.commit(Keys.CRITICAL_ERROR_MSG, null);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
@import '@/styles/media-queries.scss';
|
||||||
|
.critical-error-wrap {
|
||||||
|
position: absolute;
|
||||||
|
top: 40%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
z-index: 3;
|
||||||
|
max-width: 50rem;
|
||||||
|
background: var(--background-darker);
|
||||||
|
padding: 1rem;
|
||||||
|
border-radius: var(--curve-factor);
|
||||||
|
color: var(--danger);
|
||||||
|
border: 2px solid var(--danger);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
transition: all 0.2s ease-in-out;
|
||||||
|
@include tablet-down {
|
||||||
|
top: 50%;
|
||||||
|
width: 85vw;
|
||||||
|
}
|
||||||
|
p, ul, h4, a {
|
||||||
|
margin: 0;
|
||||||
|
color: var(--white);
|
||||||
|
}
|
||||||
|
pre {
|
||||||
|
color: var(--warning);
|
||||||
|
font-size: 0.8rem;
|
||||||
|
overflow: auto;
|
||||||
|
background: var(--transparent-white-10);
|
||||||
|
padding: 0.5rem;
|
||||||
|
border-radius: var(--curve-factor);
|
||||||
|
}
|
||||||
|
h4 {
|
||||||
|
margin: 0.5rem 0 0 0;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
h3 {
|
||||||
|
font-size: 2.2rem;
|
||||||
|
text-align: center;
|
||||||
|
background: var(--danger);
|
||||||
|
color: var(--white);
|
||||||
|
margin: -1rem -1rem 1rem -1rem;
|
||||||
|
padding: 0.5rem;
|
||||||
|
}
|
||||||
|
ul {
|
||||||
|
padding-left: 1rem;
|
||||||
|
}
|
||||||
|
.user-doesnt-care {
|
||||||
|
background: var(--background-darker);
|
||||||
|
color: var(--white);
|
||||||
|
border-radius: var(--curve-factor);
|
||||||
|
border: none;
|
||||||
|
text-decoration: underline;
|
||||||
|
padding: 0.25rem 0.5rem;
|
||||||
|
cursor: pointer;
|
||||||
|
width: fit-content;
|
||||||
|
margin: 0 auto;
|
||||||
|
transition: all 0.2s ease-in-out;
|
||||||
|
&:hover {
|
||||||
|
background: var(--danger);
|
||||||
|
color: var(--background-darker);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.close {
|
||||||
|
position: absolute;
|
||||||
|
top: 1rem;
|
||||||
|
right: 1rem;
|
||||||
|
width: 1.5rem;
|
||||||
|
height: 1.5rem;
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 1rem;
|
||||||
|
background: var(--background);
|
||||||
|
color: var(--primary);
|
||||||
|
border: none;
|
||||||
|
border-radius: var(--curve-factor);
|
||||||
|
transition: all 0.2s ease-in-out;
|
||||||
|
&:hover {
|
||||||
|
background: var(--primary);
|
||||||
|
color: var(--background);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,16 +1,13 @@
|
|||||||
<template>
|
<template>
|
||||||
<!-- User Footer -->
|
<footer v-if="visible">
|
||||||
<footer v-if="text && text !== '' && visible" v-html="text"></footer>
|
<!-- User-defined footer -->
|
||||||
<!-- Default Footer -->
|
<span v-if="text" v-html="text"></span>
|
||||||
<footer v-else-if="visible">
|
<!-- Default footer -->
|
||||||
<span v-if="$store.state.currentConfigInfo" class="path-to-config">
|
<span v-else>
|
||||||
Using: {{ $store.state.currentConfigInfo.confPath }}
|
<a :href="defaultInfo.projectUrl">Dashy</a> is free & open source
|
||||||
</span>
|
- licensed under <a :href="defaultInfo.licenseUrl">{{defaultInfo.license}}</a>,
|
||||||
<span>
|
© <a :href="defaultInfo.authorUrl">{{defaultInfo.authorName}}</a> {{defaultInfo.date}}.
|
||||||
{{ $t('footer.dev-by') }} <a :href="authorUrl">{{authorName}}</a>.
|
Get support on GitHub, at <a :href="defaultInfo.repoUrl">{{defaultInfo.repoName}}</a>.
|
||||||
{{ $t('footer.licensed-under') }} <a :href="licenseUrl">{{license}}</a>
|
|
||||||
{{ showCopyright? '©': '' }} {{date}}.
|
|
||||||
{{ $t('footer.get-the') }} <a :href="repoUrl">{{ $t('footer.source-code') }}</a>.
|
|
||||||
</span>
|
</span>
|
||||||
</footer>
|
</footer>
|
||||||
</template>
|
</template>
|
||||||
@ -23,13 +20,20 @@ export default {
|
|||||||
name: 'Footer',
|
name: 'Footer',
|
||||||
props: {
|
props: {
|
||||||
text: String,
|
text: String,
|
||||||
authorName: { type: String, default: 'Alicia Sykes' },
|
},
|
||||||
authorUrl: { type: String, default: 'https://aliciasykes.com' },
|
data() {
|
||||||
license: { type: String, default: 'MIT' },
|
return {
|
||||||
licenseUrl: { type: String, default: 'https://gist.github.com/Lissy93/143d2ee01ccc5c052a17' },
|
defaultInfo: {
|
||||||
date: { type: String, default: `${new Date().getFullYear()}` },
|
authorName: 'Alicia Sykes',
|
||||||
showCopyright: { type: Boolean, default: true },
|
authorUrl: 'https://as93.net',
|
||||||
repoUrl: { type: String, default: 'https://github.com/lissy93/dashy' },
|
license: 'MIT',
|
||||||
|
licenseUrl: 'https://gist.github.com/Lissy93/143d2ee01ccc5c052a17',
|
||||||
|
date: `${new Date().getFullYear()}`,
|
||||||
|
repoUrl: 'https://github.com/lissy93/dashy',
|
||||||
|
repoName: 'Lissy93/Dashy',
|
||||||
|
projectUrl: 'https://dashy.to',
|
||||||
|
},
|
||||||
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
visible() {
|
visible() {
|
||||||
@ -56,7 +60,7 @@ footer {
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
span.path-to-config {
|
span.path-to-config {
|
||||||
float: right;
|
float: left;
|
||||||
font-size: 0.75rem;
|
font-size: 0.75rem;
|
||||||
margin: 0.1rem 0.5rem 0 0;
|
margin: 0.1rem 0.5rem 0 0;
|
||||||
opacity: var(--dimming-factor);
|
opacity: var(--dimming-factor);
|
||||||
|
@ -66,7 +66,7 @@ export default {
|
|||||||
span.subtitle {
|
span.subtitle {
|
||||||
color: var(--heading-text-color);
|
color: var(--heading-text-color);
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
text-shadow: 1px 1px 2px #130f23;
|
text-shadow: 1px 1px 2px #130f2347;
|
||||||
opacity: var(--dimming-factor);
|
opacity: var(--dimming-factor);
|
||||||
}
|
}
|
||||||
img.site-logo {
|
img.site-logo {
|
||||||
|
@ -319,6 +319,10 @@ div.action-buttons {
|
|||||||
min-width: 6rem;
|
min-width: 6rem;
|
||||||
padding: 0.25rem 0.5rem;
|
padding: 0.25rem 0.5rem;
|
||||||
margin: 1rem 0.5rem 0.5rem;
|
margin: 1rem 0.5rem 0.5rem;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,8 +37,10 @@ export default {
|
|||||||
input: '',
|
input: '',
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
props: {
|
computed: {
|
||||||
iconSize: String,
|
iconSize() {
|
||||||
|
return this.$store.getters.iconSize;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
IconSmall,
|
IconSmall,
|
||||||
|
@ -5,19 +5,19 @@
|
|||||||
<IconDeafault
|
<IconDeafault
|
||||||
@click="updateDisplayLayout('auto')"
|
@click="updateDisplayLayout('auto')"
|
||||||
v-tooltip="tooltip($t('settings.layout-auto'))"
|
v-tooltip="tooltip($t('settings.layout-auto'))"
|
||||||
:class="`layout-icon ${displayLayout === 'auto' ? 'selected' : ''}`"
|
:class="`layout-icon ${layout === 'auto' ? 'selected' : ''}`"
|
||||||
tabindex="-2"
|
tabindex="-2"
|
||||||
/>
|
/>
|
||||||
<IconHorizontal
|
<IconHorizontal
|
||||||
@click="updateDisplayLayout('horizontal')"
|
@click="updateDisplayLayout('horizontal')"
|
||||||
v-tooltip="tooltip($t('settings.layout-horizontal'))"
|
v-tooltip="tooltip($t('settings.layout-horizontal'))"
|
||||||
:class="`layout-icon ${displayLayout === 'horizontal' ? 'selected' : ''}`"
|
:class="`layout-icon ${layout === 'horizontal' ? 'selected' : ''}`"
|
||||||
tabindex="-2"
|
tabindex="-2"
|
||||||
/>
|
/>
|
||||||
<IconVertical
|
<IconVertical
|
||||||
@click="updateDisplayLayout('vertical')"
|
@click="updateDisplayLayout('vertical')"
|
||||||
v-tooltip="tooltip($t('settings.layout-vertical'))"
|
v-tooltip="tooltip($t('settings.layout-vertical'))"
|
||||||
:class="`layout-icon ${displayLayout === 'vertical' ? 'selected' : ''}`"
|
:class="`layout-icon ${layout === 'vertical' ? 'selected' : ''}`"
|
||||||
tabindex="-2"
|
tabindex="-2"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -40,6 +40,11 @@ export default {
|
|||||||
IconHorizontal,
|
IconHorizontal,
|
||||||
IconVertical,
|
IconVertical,
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
layout() {
|
||||||
|
return this.$store.getters.layout;
|
||||||
|
},
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
updateDisplayLayout(layout) {
|
updateDisplayLayout(layout) {
|
||||||
this.$store.commit(StoreKeys.SET_ITEM_LAYOUT, layout);
|
this.$store.commit(StoreKeys.SET_ITEM_LAYOUT, layout);
|
||||||
|
@ -1,36 +1,70 @@
|
|||||||
<template>
|
<template>
|
||||||
<transition name="slide-fade">
|
<transition name="slide-fade">
|
||||||
<div class="kb-sc-info" v-if="!shouldHide">
|
<div class="kb-sc-info" v-if="!shouldHide">
|
||||||
<h5>There are keyboard shortcuts! ⌨️🙌</h5>
|
<h5>{{ popupContent.title }}</h5>
|
||||||
<div class="close" title="Hide forever [Esc]" @click="hideWelcomeHelper()">x</div>
|
<div class="close" title="Hide forever [Esc]" @click="hideWelcomeHelper()">x</div>
|
||||||
<p title="Press [Esc] to hide this tip forever. See there's even a shortcut for that! 🚀">
|
<p :title="popupContent.hoverText">{{ popupContent.message }}</p>
|
||||||
Just start typing to filter. Then use the tab key to cycle through results,
|
<p :title="popupContent.hoverText">{{ popupContent.messageContinued }}</p>
|
||||||
and press enter to launch the selected item, or alt + enter to open in a modal.
|
<div class="action-buttons">
|
||||||
You can hit Esc at anytime to clear the search. Easy 🥳
|
<button @click="exportConfig">Export Local Config</button>
|
||||||
</p>
|
<button @click="saveConfig">Save Changes to Disk</button>
|
||||||
|
<button @click="resetLocalConfig">Reset Local Changes</button>
|
||||||
|
<button @click="hideWelcomeHelper">Dismiss this Notification</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
import { localStorageKeys } from '@/utils/defaults';
|
import { localStorageKeys, modalNames } from '@/utils/defaults';
|
||||||
|
import StoreKeys from '@/utils/StoreMutations';
|
||||||
|
import configSavingMixin from '@/mixins/ConfigSaving';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'KeyboardShortcutInfo',
|
name: 'KeyboardShortcutInfo',
|
||||||
|
mixins: [configSavingMixin],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
shouldHide: true, // False = show/ true = hide. Intuitive, eh?
|
shouldHide: true, // False = show/ true = hide. Intuitive, eh?
|
||||||
timeDelay: 3000, // Short delay in ms before popup appears
|
timeDelay: 2000, // Short delay in ms before popup appears
|
||||||
|
popupContent: {
|
||||||
|
title: '⚠️ You\'re using a local config',
|
||||||
|
message: `This means that your settings are saved in this browser only,
|
||||||
|
and won't persist across devices.`,
|
||||||
|
messageContinued: `To ensure you don't loose your changes,
|
||||||
|
it's recommended to download a copy of your config, so you can restore it later.`,
|
||||||
|
hoverText: 'Press [Esc] to hide this warning',
|
||||||
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
exportConfig() {
|
||||||
|
this.$modal.show(modalNames.EXPORT_CONFIG_MENU);
|
||||||
|
this.shouldHide = true;
|
||||||
|
},
|
||||||
|
saveConfig() {
|
||||||
|
const localConfig = this.$store.state.config;
|
||||||
|
this.writeConfigToDisk(localConfig);
|
||||||
|
this.shouldHide = true;
|
||||||
|
},
|
||||||
|
resetLocalConfig() {
|
||||||
|
const msg = `${this.$t('config.reset-config-msg-l1')} `
|
||||||
|
+ `${this.$t('config.reset-config-msg-l2')}\n\n${this.$t('config.reset-config-msg-l3')}`;
|
||||||
|
const isTheUserSure = confirm(msg); // eslint-disable-line no-alert, no-restricted-globals
|
||||||
|
if (isTheUserSure) {
|
||||||
|
localStorage.clear();
|
||||||
|
this.$toasted.show(this.$t('config.data-cleared-msg'));
|
||||||
|
this.$store.dispatch(StoreKeys.INITIALIZE_CONFIG);
|
||||||
|
this.shouldHide = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
* Returns true if the key exists in session storage, otherwise false
|
* Returns true if the key exists in session storage, otherwise false
|
||||||
* And the !! just converts 'false' to false, as strings resolve to true
|
* And the !! just converts 'false' to false, as strings resolve to true
|
||||||
*/
|
*/
|
||||||
shouldHideWelcomeMessage() {
|
shouldHideWelcomeMessage() {
|
||||||
return !!localStorage[localStorageKeys.HIDE_WELCOME_BANNER];
|
return !!localStorage[localStorageKeys.HIDE_INFO_NOTIFICATION];
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* Update session storage, so that it won't be shown again
|
* Update session storage, so that it won't be shown again
|
||||||
@ -38,7 +72,7 @@ export default {
|
|||||||
*/
|
*/
|
||||||
hideWelcomeHelper() {
|
hideWelcomeHelper() {
|
||||||
this.shouldHide = true;
|
this.shouldHide = true;
|
||||||
localStorage.setItem(localStorageKeys.HIDE_WELCOME_BANNER, true);
|
localStorage.setItem(localStorageKeys.HIDE_INFO_NOTIFICATION, true);
|
||||||
window.removeEventListener('keyup', this.keyPressEvent);
|
window.removeEventListener('keyup', this.keyPressEvent);
|
||||||
},
|
},
|
||||||
/* Passed to window function, to add/ remove event listener */
|
/* Passed to window function, to add/ remove event listener */
|
||||||
@ -114,6 +148,23 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.action-buttons {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
margin-top: 1em;
|
||||||
|
button {
|
||||||
|
padding: 0.2rem;
|
||||||
|
background: var(--welcome-popup-background);
|
||||||
|
color: var(--welcome-popup-text-color);
|
||||||
|
border: 1px solid var(--welcome-popup-text-color);
|
||||||
|
border-radius: var(--curve-factor);
|
||||||
|
transition: all 0.2s ease-in-out;
|
||||||
|
&:hover {
|
||||||
|
background: var(--welcome-popup-text-color);
|
||||||
|
color: var(--welcome-popup-background);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
/* Animations, animations everywhere */
|
/* Animations, animations everywhere */
|
||||||
.slide-fade-enter-active {
|
.slide-fade-enter-active {
|
||||||
transition: all 1s ease;
|
transition: all 1s ease;
|
@ -95,7 +95,8 @@ export default {
|
|||||||
},
|
},
|
||||||
/* If configured, launch specific app when hotkey pressed */
|
/* If configured, launch specific app when hotkey pressed */
|
||||||
handleHotKey(key) {
|
handleHotKey(key) {
|
||||||
const usersHotKeys = this.getCustomKeyShortcuts();
|
const sections = this.$store.getters.sections || [];
|
||||||
|
const usersHotKeys = this.getCustomKeyShortcuts(sections);
|
||||||
usersHotKeys.forEach((hotkey) => {
|
usersHotKeys.forEach((hotkey) => {
|
||||||
if (hotkey.hotkey === parseInt(key, 10)) {
|
if (hotkey.hotkey === parseInt(key, 10)) {
|
||||||
if (hotkey.url) window.open(hotkey.url, '_blank');
|
if (hotkey.url) window.open(hotkey.url, '_blank');
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<div class="options-outer">
|
<div class="options-outer">
|
||||||
<div :class="`options-container ${!settingsVisible ? 'hide' : ''}`">
|
<div :class="`options-container ${!settingsVisible ? 'hide' : ''}`">
|
||||||
<ThemeSelector />
|
<ThemeSelector />
|
||||||
<LayoutSelector :displayLayout="displayLayout" />
|
<LayoutSelector :displayLayout="$store.getters.layout" />
|
||||||
<ItemSizeSelector :iconSize="iconSize" />
|
<ItemSizeSelector :iconSize="iconSize" />
|
||||||
<ConfigLauncher />
|
<ConfigLauncher />
|
||||||
<AuthButtons v-if="userState !== 0" :userType="userState" />
|
<AuthButtons v-if="userState !== 0" :userType="userState" />
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
:value="$store.getters.theme"
|
:value="$store.getters.theme"
|
||||||
class="theme-dropdown"
|
class="theme-dropdown"
|
||||||
:tabindex="-2"
|
:tabindex="-2"
|
||||||
@input="themeChanged"
|
@input="themeChangedInUI"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<IconPalette
|
<IconPalette
|
||||||
@ -28,18 +28,13 @@
|
|||||||
<script>
|
<script>
|
||||||
|
|
||||||
import CustomThemeMaker from '@/components/Settings/CustomThemeMaker';
|
import CustomThemeMaker from '@/components/Settings/CustomThemeMaker';
|
||||||
import {
|
|
||||||
LoadExternalTheme,
|
|
||||||
ApplyLocalTheme,
|
|
||||||
ApplyCustomVariables,
|
|
||||||
} from '@/utils/ThemeHelper';
|
|
||||||
import Defaults, { localStorageKeys } from '@/utils/defaults';
|
|
||||||
import Keys from '@/utils/StoreMutations';
|
import Keys from '@/utils/StoreMutations';
|
||||||
import ErrorHandler from '@/utils/ErrorHandler';
|
|
||||||
import IconPalette from '@/assets/interface-icons/config-color-palette.svg';
|
import IconPalette from '@/assets/interface-icons/config-color-palette.svg';
|
||||||
|
import ThemingMixin from '@/mixins/ThemingMixin';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ThemeSelector',
|
name: 'ThemeSelector',
|
||||||
|
mixins: [ThemingMixin],
|
||||||
props: {
|
props: {
|
||||||
hidePallete: Boolean,
|
hidePallete: Boolean,
|
||||||
},
|
},
|
||||||
@ -47,101 +42,16 @@ export default {
|
|||||||
CustomThemeMaker,
|
CustomThemeMaker,
|
||||||
IconPalette,
|
IconPalette,
|
||||||
},
|
},
|
||||||
watch: {
|
|
||||||
/* When theme in VueX store changes, then update theme */
|
|
||||||
themeFromStore(newTheme) {
|
|
||||||
this.selectedTheme = newTheme;
|
|
||||||
this.updateTheme(newTheme);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
selectedTheme: '',
|
|
||||||
themeConfiguratorOpen: false, // Control the opening of theme config popup
|
themeConfiguratorOpen: false, // Control the opening of theme config popup
|
||||||
themeHelper: new LoadExternalTheme(),
|
|
||||||
ApplyLocalTheme,
|
|
||||||
ApplyCustomVariables,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {},
|
||||||
/* Get appConfig from store */
|
|
||||||
appConfig() {
|
|
||||||
return this.$store.getters.appConfig;
|
|
||||||
},
|
|
||||||
/* Get users theme from store */
|
|
||||||
themeFromStore() {
|
|
||||||
return this.$store.getters.theme;
|
|
||||||
},
|
|
||||||
/* Combines all theme names (builtin and user defined) together */
|
|
||||||
themeNames: function themeNames() {
|
|
||||||
const externalThemeNames = Object.keys(this.externalThemes);
|
|
||||||
const specialThemes = ['custom'];
|
|
||||||
return [...this.extraThemeNames, ...externalThemeNames,
|
|
||||||
...Defaults.builtInThemes, ...specialThemes];
|
|
||||||
},
|
|
||||||
extraThemeNames() {
|
|
||||||
const userThemes = this.appConfig.cssThemes || [];
|
|
||||||
if (typeof userThemes === 'string') return [userThemes];
|
|
||||||
return userThemes;
|
|
||||||
},
|
|
||||||
/* Returns an array of links to external CSS from the Config */
|
|
||||||
externalThemes() {
|
|
||||||
const availibleThemes = {};
|
|
||||||
if (this.appConfig && this.appConfig.externalStyleSheet) {
|
|
||||||
const externals = this.appConfig.externalStyleSheet;
|
|
||||||
if (Array.isArray(externals)) {
|
|
||||||
externals.forEach((ext, i) => {
|
|
||||||
availibleThemes[`External Stylesheet ${i + 1}`] = ext;
|
|
||||||
});
|
|
||||||
} else if (typeof externals === 'string') {
|
|
||||||
availibleThemes['External Stylesheet'] = this.appConfig.externalStyleSheet;
|
|
||||||
} else {
|
|
||||||
ErrorHandler('External stylesheets must be of type string or string[]');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// availibleThemes.Default = '#';
|
|
||||||
return availibleThemes;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
mounted() {
|
mounted() {
|
||||||
const initialTheme = this.getInitialTheme();
|
this.initializeTheme();
|
||||||
this.selectedTheme = initialTheme;
|
|
||||||
// Quicker loading, if the theme is local we can apply it immidiatley
|
|
||||||
if (this.isThemeLocal(initialTheme)) {
|
|
||||||
this.updateTheme(initialTheme);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If it's an external stylesheet, then wait for promise to resolve
|
|
||||||
if (this.externalThemes && Object.entries(this.externalThemes).length > 0) {
|
|
||||||
const added = Object.keys(this.externalThemes).map(
|
|
||||||
name => this.themeHelper.add(name, this.externalThemes[name]),
|
|
||||||
);
|
|
||||||
// Once, added, then apply users initial theme
|
|
||||||
Promise.all(added).then(() => {
|
|
||||||
this.updateTheme(initialTheme);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
/* Called when dropdown changed
|
|
||||||
* Updates store, which will in turn update theme through watcher
|
|
||||||
*/
|
|
||||||
themeChanged() {
|
|
||||||
const pageId = this.$store.state.currentConfigInfo?.pageId || null;
|
|
||||||
this.$store.commit(Keys.SET_THEME, { theme: this.selectedTheme, pageId });
|
|
||||||
this.updateTheme(this.selectedTheme);
|
|
||||||
},
|
|
||||||
/* Returns the initial theme */
|
|
||||||
getInitialTheme() {
|
|
||||||
const localTheme = localStorage[localStorageKeys.THEME];
|
|
||||||
if (localTheme && localTheme !== 'undefined') return localTheme;
|
|
||||||
return this.appConfig.theme || Defaults.theme;
|
|
||||||
},
|
|
||||||
/* Determines if a given theme is local / not a custom user stylesheet */
|
|
||||||
isThemeLocal(themeToCheck) {
|
|
||||||
const localThemes = [...Defaults.builtInThemes, ...this.extraThemeNames];
|
|
||||||
return localThemes.includes(themeToCheck);
|
|
||||||
},
|
|
||||||
/* Opens the theme color configurator popup */
|
/* Opens the theme color configurator popup */
|
||||||
openThemeConfigurator() {
|
openThemeConfigurator() {
|
||||||
this.$store.commit(Keys.SET_MODAL_OPEN, true);
|
this.$store.commit(Keys.SET_MODAL_OPEN, true);
|
||||||
@ -154,24 +64,6 @@ export default {
|
|||||||
this.themeConfiguratorOpen = false;
|
this.themeConfiguratorOpen = false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
/* Updates theme. Checks if the new theme is local or external,
|
|
||||||
and calls appropirate updating function. Updates local storage */
|
|
||||||
updateTheme(newTheme) {
|
|
||||||
if (newTheme === 'Default') {
|
|
||||||
this.resetToDefault();
|
|
||||||
this.themeHelper.theme = 'Default';
|
|
||||||
} else if (this.isThemeLocal(newTheme)) {
|
|
||||||
this.ApplyLocalTheme(newTheme);
|
|
||||||
} else {
|
|
||||||
this.themeHelper.theme = newTheme;
|
|
||||||
}
|
|
||||||
this.ApplyCustomVariables(newTheme);
|
|
||||||
// localStorage.setItem(localStorageKeys.THEME, newTheme);
|
|
||||||
},
|
|
||||||
/* Removes any applied themes */
|
|
||||||
resetToDefault() {
|
|
||||||
document.getElementsByTagName('html')[0].removeAttribute('data-theme');
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|