mirror of
https://github.com/Lissy93/dashy.git
synced 2024-12-26 10:24:40 +03:00
Merge branch 'Lissy93:master' into master
This commit is contained in:
commit
c7c4df7a55
15
.github/AUTHORS.txt
vendored
15
.github/AUTHORS.txt
vendored
@ -38,7 +38,6 @@ Steffen <chmid> - 1 commits
|
||||
Steven <as> - 1 commits
|
||||
Xert <xertdev@gmail.com> - 1 commits
|
||||
deepsource-io[bot] <deepsource-io[bot]@users.noreply.github.com> - 1 commits
|
||||
dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> - 1 commits
|
||||
dr460nf1r3 <njcrypted@protonmail.com> - 1 commits
|
||||
flechaig <flechaig@users.noreply.github.com> - 1 commits
|
||||
icy-comet <50461557+icy-comet@users.noreply.github.com> - 1 commits
|
||||
@ -58,13 +57,13 @@ BOZG <sr@bozg.se> - 2 commits
|
||||
Brendan <'Lear> - 2 commits
|
||||
CHAIYEON <H> - 2 commits
|
||||
Dan <ilber> - 2 commits
|
||||
Matthias <ilge> - 2 commits
|
||||
Ruben <ilv> - 2 commits
|
||||
Thomas <isser> - 2 commits
|
||||
cauterize <cauterize@programmer.net> - 2 commits
|
||||
k073l <21180271+k073l@users.noreply.github.com> - 2 commits
|
||||
liss-bot <87835202+liss-bot@users.noreply.github.com> - 2 commits
|
||||
patrickheeney <patrickheeney@gmail.com> - 2 commits
|
||||
rtm516 <rtm516@users.noreply.github.com> - 2 commits
|
||||
ᗪєνιη <υн> - 2 commits
|
||||
Alucarddelta <dreyer.brent@gmail.com> - 3 commits
|
||||
Tuzi555 <jakub.tuzar@gmail.com> - 3 commits
|
||||
@ -72,6 +71,7 @@ Walkx <71191962+walkxcode@users.noreply.github.com> - 3 commits
|
||||
aterox <kenneth@kenneth.church> - 3 commits
|
||||
bogyeong <boggyhint@gmail.com> - 3 commits
|
||||
stanly0726 <37040069+stanly0726@users.noreply.github.com> - 3 commits
|
||||
Alberto <aravac> - 4 commits
|
||||
David <laso> - 4 commits
|
||||
Lissy93 <alicia@omg.lol> - 4 commits
|
||||
Niklas <abe> - 4 commits
|
||||
@ -91,17 +91,18 @@ Kashif <ohai> - 9 commits
|
||||
Alejandro <ina> - 14 commits
|
||||
Alicia <yke> - 16 commits
|
||||
github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> - 16 commits
|
||||
Matthias <ilge> - 17 commits
|
||||
snyk-bot <snyk-bot@users.noreply.github.com> - 18 commits
|
||||
aterox <church.kennetha@gmail.com> - 19 commits
|
||||
EVOTk <45015615+EVOTk@users.noreply.github.com> - 22 commits
|
||||
Marcell <ülö> - 24 commits
|
||||
Alicia <yke> - 28 commits
|
||||
repo-visualizer <repo-visualizer@users.noreply.github.com> - 70 commits
|
||||
snyk-bot <snyk-bot@snyk.io> - 74 commits
|
||||
repo-visualizer <repo-visualizer@users.noreply.github.com> - 72 commits
|
||||
snyk-bot <snyk-bot@snyk.io> - 75 commits
|
||||
Lissy93 <gh@d0h.co> - 78 commits
|
||||
Alicia <o> - 128 commits
|
||||
liss-bot <liss-bot@d0h.co> - 140 commits
|
||||
Alicia <o> - 134 commits
|
||||
liss-bot <liss-bot@d0h.co> - 144 commits
|
||||
Lissy93 <Lissy93@users.noreply.github.com> - 208 commits
|
||||
Alicia <yke> - 250 commits
|
||||
Alicia <yke> - 257 commits
|
||||
Alicia <yke> - 440 commits
|
||||
Alicia <yke> - 1488 commits
|
5
.github/workflows/generate-credits.yml
vendored
5
.github/workflows/generate-credits.yml
vendored
@ -42,8 +42,8 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
name: Inserts contributors into credits.md
|
||||
steps:
|
||||
- name: Contribute List - Credits Page
|
||||
uses: akhilmhdh/contributors-readme-action@v2.2
|
||||
- name: Contributer List - Credits Page
|
||||
uses: akhilmhdh/contributors-readme-action@v2.3.6
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
@ -51,6 +51,7 @@ jobs:
|
||||
readme_path: docs/credits.md
|
||||
columns_per_row: 6
|
||||
commit_message: ':purple_heart: Updates contributors list'
|
||||
collaborators: all
|
||||
committer_username: liss-bot
|
||||
committer_email: liss-bot@d0h.co
|
||||
- name: Sponsors List - Readme
|
||||
|
@ -50,4 +50,4 @@ CMD [ "yarn", "start" ]
|
||||
EXPOSE ${PORT}
|
||||
|
||||
# Run simple healthchecks every 5 mins, to check that everythings still great
|
||||
HEALTHCHECK --interval=5m --timeout=2s --start-period=30s CMD yarn health-check
|
||||
HEALTHCHECK --interval=5m --timeout=5s --start-period=30s CMD yarn health-check
|
||||
|
24
README.md
24
README.md
@ -552,28 +552,21 @@ Huge thanks to the sponsors helping to support Dashy's development!
|
||||
<sub><b>Eddy Lazzarin</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/Geolim4">
|
||||
<img src="https://avatars.githubusercontent.com/u/1332071?u=5d84984897f094932c4829583fee19b121f3aab8&v=4" width="80;" alt="Geolim4"/>
|
||||
<br />
|
||||
<sub><b>Georges.L</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/AnandChowdhary">
|
||||
<img src="https://avatars.githubusercontent.com/u/2841780?u=ca8e292b15abcc6cddaeae0abded0115c51b4789&v=4" width="80;" alt="AnandChowdhary"/>
|
||||
<br />
|
||||
<sub><b>Anand Chowdhary</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
</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>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/k-rol">
|
||||
<img src="https://avatars.githubusercontent.com/u/4050412?u=1162510eec7b7aeb31d4c7c65d51d4f773d823b0&v=4" width="80;" alt="k-rol"/>
|
||||
@ -608,14 +601,21 @@ Huge thanks to the sponsors helping to support Dashy's development!
|
||||
<br />
|
||||
<sub><b>Brian McGonagill</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/vlad-timofeev">
|
||||
<img src="https://avatars.githubusercontent.com/u/11474041?v=4" width="80;" alt="vlad-timofeev"/>
|
||||
<br />
|
||||
<sub><b>Vlad Timofeev</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/iJasonWade">
|
||||
<img src="https://avatars.githubusercontent.com/u/12824479?v=4" width="80;" alt="iJasonWade"/>
|
||||
<br />
|
||||
<sub><b>Jason Ash</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/PAPAMICA">
|
||||
|
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 16 MiB After Width: | Height: | Size: 16 MiB |
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 102 KiB After Width: | Height: | Size: 102 KiB |
409
docs/credits.md
409
docs/credits.md
@ -32,28 +32,21 @@
|
||||
<sub><b>Eddy Lazzarin</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/Geolim4">
|
||||
<img src="https://avatars.githubusercontent.com/u/1332071?u=5d84984897f094932c4829583fee19b121f3aab8&v=4" width="80;" alt="Geolim4"/>
|
||||
<br />
|
||||
<sub><b>Georges.L</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/AnandChowdhary">
|
||||
<img src="https://avatars.githubusercontent.com/u/2841780?u=ca8e292b15abcc6cddaeae0abded0115c51b4789&v=4" width="80;" alt="AnandChowdhary"/>
|
||||
<br />
|
||||
<sub><b>Anand Chowdhary</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
</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>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/k-rol">
|
||||
<img src="https://avatars.githubusercontent.com/u/4050412?u=1162510eec7b7aeb31d4c7c65d51d4f773d823b0&v=4" width="80;" alt="k-rol"/>
|
||||
@ -88,14 +81,21 @@
|
||||
<br />
|
||||
<sub><b>Brian McGonagill</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/vlad-timofeev">
|
||||
<img src="https://avatars.githubusercontent.com/u/11474041?v=4" width="80;" alt="vlad-timofeev"/>
|
||||
<br />
|
||||
<sub><b>Vlad Timofeev</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/iJasonWade">
|
||||
<img src="https://avatars.githubusercontent.com/u/12824479?v=4" width="80;" alt="iJasonWade"/>
|
||||
<br />
|
||||
<sub><b>Jason Ash</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/PAPAMICA">
|
||||
@ -175,6 +175,13 @@
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/m42e">
|
||||
<img src="https://avatars.githubusercontent.com/u/2410802?v=4" width="80;" alt="m42e"/>
|
||||
<br />
|
||||
<sub><b>Matthias Bilger</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/pinarruiz">
|
||||
<img src="https://avatars.githubusercontent.com/u/37040888?v=4" width="80;" alt="pinarruiz"/>
|
||||
@ -209,15 +216,15 @@
|
||||
<br />
|
||||
<sub><b>Jammo2k5</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/lordpansar">
|
||||
<img src="https://avatars.githubusercontent.com/u/14231148?v=4" width="80;" alt="lordpansar"/>
|
||||
<br />
|
||||
<sub><b>Magnus Sundström</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/Cereal916">
|
||||
<img src="https://avatars.githubusercontent.com/u/7526937?v=4" width="80;" alt="Cereal916"/>
|
||||
@ -232,6 +239,13 @@
|
||||
<sub><b>UrekD</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/albcp">
|
||||
<img src="https://avatars.githubusercontent.com/u/3170731?v=4" width="80;" alt="albcp"/>
|
||||
<br />
|
||||
<sub><b>Alberto</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/Tracreed">
|
||||
<img src="https://avatars.githubusercontent.com/u/6306365?v=4" width="80;" alt="Tracreed"/>
|
||||
@ -245,7 +259,8 @@
|
||||
<br />
|
||||
<sub><b>Remygrandin</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/Totto16">
|
||||
<img src="https://avatars.githubusercontent.com/u/32566573?v=4" width="80;" alt="Totto16"/>
|
||||
@ -259,8 +274,7 @@
|
||||
<br />
|
||||
<sub><b>Brent</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/Bogyie">
|
||||
<img src="https://avatars.githubusercontent.com/u/82003678?v=4" width="80;" alt="Bogyie"/>
|
||||
@ -282,6 +296,14 @@
|
||||
<sub><b>Rúben Silva</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/rtm516">
|
||||
<img src="https://avatars.githubusercontent.com/u/5401186?v=4" width="80;" alt="rtm516"/>
|
||||
<br />
|
||||
<sub><b>Rtm516</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/onedr0p">
|
||||
<img src="https://avatars.githubusercontent.com/u/213795?v=4" width="80;" alt="onedr0p"/>
|
||||
@ -302,8 +324,7 @@
|
||||
<br />
|
||||
<sub><b>Stephen Rigney</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/moemoeq">
|
||||
<img src="https://avatars.githubusercontent.com/u/1808434?v=4" width="80;" alt="moemoeq"/>
|
||||
@ -318,25 +339,355 @@
|
||||
<sub><b>Dan Gilbert</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/m42e">
|
||||
<img src="https://avatars.githubusercontent.com/u/2410802?v=4" width="80;" alt="m42e"/>
|
||||
<br />
|
||||
<sub><b>Matthias Bilger</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/thomasdissert">
|
||||
<img src="https://avatars.githubusercontent.com/u/11446531?v=4" width="80;" alt="thomasdissert"/>
|
||||
<br />
|
||||
<sub><b>Thomas Dissert</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/k073l">
|
||||
<img src="https://avatars.githubusercontent.com/u/21180271?v=4" width="80;" alt="k073l"/>
|
||||
<br />
|
||||
<sub><b>K073l</b></sub>
|
||||
<sub><b>Null</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/patrickheeney">
|
||||
<img src="https://avatars.githubusercontent.com/u/1407228?v=4" width="80;" alt="patrickheeney"/>
|
||||
<br />
|
||||
<sub><b>Patrick Heeney</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/Singebob">
|
||||
<img src="https://avatars.githubusercontent.com/u/24290044?v=4" width="80;" alt="Singebob"/>
|
||||
<br />
|
||||
<sub><b>Jeremy Chauvin</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/0n1cOn3">
|
||||
<img src="https://avatars.githubusercontent.com/u/27576311?v=4" width="80;" alt="0n1cOn3"/>
|
||||
<br />
|
||||
<sub><b>0n1cOn3</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/a-mnich">
|
||||
<img src="https://avatars.githubusercontent.com/u/56564725?v=4" width="80;" alt="a-mnich"/>
|
||||
<br />
|
||||
<sub><b>Alexander Mnich</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/AaronPorts">
|
||||
<img src="https://avatars.githubusercontent.com/u/32810520?v=4" width="80;" alt="AaronPorts"/>
|
||||
<br />
|
||||
<sub><b>Artyom</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/BRAVO68WEB">
|
||||
<img src="https://avatars.githubusercontent.com/u/41448663?v=4" width="80;" alt="BRAVO68WEB"/>
|
||||
<br />
|
||||
<sub><b>Jyotirmoy Bandyopadhyaya [Bravo68]</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/BeginCI">
|
||||
<img src="https://avatars.githubusercontent.com/u/57495754?v=4" width="80;" alt="BeginCI"/>
|
||||
<br />
|
||||
<sub><b>Begin</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/bskim45">
|
||||
<img src="https://avatars.githubusercontent.com/u/5674934?v=4" width="80;" alt="bskim45"/>
|
||||
<br />
|
||||
<sub><b>Bumsoo Kim</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/skaarj1989">
|
||||
<img src="https://avatars.githubusercontent.com/u/34756939?v=4" width="80;" alt="skaarj1989"/>
|
||||
<br />
|
||||
<sub><b>David</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/DawidPietrykowski">
|
||||
<img src="https://avatars.githubusercontent.com/u/53954695?v=4" width="80;" alt="DawidPietrykowski"/>
|
||||
<br />
|
||||
<sub><b>Null</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/deepsourcebot">
|
||||
<img src="https://avatars.githubusercontent.com/u/60907429?v=4" width="80;" alt="deepsourcebot"/>
|
||||
<br />
|
||||
<sub><b>DeepSource Bot</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/dkyeremeh">
|
||||
<img src="https://avatars.githubusercontent.com/u/52928432?v=4" width="80;" alt="dkyeremeh"/>
|
||||
<br />
|
||||
<sub><b>Desmond Kyeremeh</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/dougaldhub">
|
||||
<img src="https://avatars.githubusercontent.com/u/25713235?v=4" width="80;" alt="dougaldhub"/>
|
||||
<br />
|
||||
<sub><b>Doug Lock</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/Dylan-Bs">
|
||||
<img src="https://avatars.githubusercontent.com/u/35694107?v=4" width="80;" alt="Dylan-Bs"/>
|
||||
<br />
|
||||
<sub><b>Dylan Bersans</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/emiran-orange">
|
||||
<img src="https://avatars.githubusercontent.com/u/71817149?v=4" width="80;" alt="emiran-orange"/>
|
||||
<br />
|
||||
<sub><b>Null</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/FormatToday">
|
||||
<img src="https://avatars.githubusercontent.com/u/20515769?v=4" width="80;" alt="FormatToday"/>
|
||||
<br />
|
||||
<sub><b>FormatToday</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/nealian">
|
||||
<img src="https://avatars.githubusercontent.com/u/865115?v=4" width="80;" alt="nealian"/>
|
||||
<br />
|
||||
<sub><b>Ian Neal</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/Compunctus">
|
||||
<img src="https://avatars.githubusercontent.com/u/5058853?v=4" width="80;" alt="Compunctus"/>
|
||||
<br />
|
||||
<sub><b>Iaroslav Dronskii</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/b1thunt3r">
|
||||
<img src="https://avatars.githubusercontent.com/u/791091?v=4" width="80;" alt="b1thunt3r"/>
|
||||
<br />
|
||||
<sub><b>Ishan Jain</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/Hellhium">
|
||||
<img src="https://avatars.githubusercontent.com/u/11504877?v=4" width="80;" alt="Hellhium"/>
|
||||
<br />
|
||||
<sub><b>Jemy SCHNEPP</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/KierenConnell">
|
||||
<img src="https://avatars.githubusercontent.com/u/46445781?v=4" width="80;" alt="KierenConnell"/>
|
||||
<br />
|
||||
<sub><b>Kieren Connell</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/LeoColman">
|
||||
<img src="https://avatars.githubusercontent.com/u/1577251?v=4" width="80;" alt="LeoColman"/>
|
||||
<br />
|
||||
<sub><b>Leonardo Colman Lopes</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/asenov">
|
||||
<img src="https://avatars.githubusercontent.com/u/280619?v=4" width="80;" alt="asenov"/>
|
||||
<br />
|
||||
<sub><b>Мирослав Асенов</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/markusdd">
|
||||
<img src="https://avatars.githubusercontent.com/u/25175069?v=4" width="80;" alt="markusdd"/>
|
||||
<br />
|
||||
<sub><b>Markus Krause</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/maximemoreillon">
|
||||
<img src="https://avatars.githubusercontent.com/u/29086128?v=4" width="80;" alt="maximemoreillon"/>
|
||||
<br />
|
||||
<sub><b>Maxime Moreillon</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/miclav">
|
||||
<img src="https://avatars.githubusercontent.com/u/11891522?v=4" width="80;" alt="miclav"/>
|
||||
<br />
|
||||
<sub><b>Michael Lavaire</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/PlusaN">
|
||||
<img src="https://avatars.githubusercontent.com/u/61884717?v=4" width="80;" alt="PlusaN"/>
|
||||
<br />
|
||||
<sub><b>Andrey</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/PrynsTag">
|
||||
<img src="https://avatars.githubusercontent.com/u/56314705?v=4" width="80;" alt="PrynsTag"/>
|
||||
<br />
|
||||
<sub><b>Prince Carl Velasco</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/rubjo">
|
||||
<img src="https://avatars.githubusercontent.com/u/42270947?v=4" width="80;" alt="rubjo"/>
|
||||
<br />
|
||||
<sub><b>Null</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/turnrye">
|
||||
<img src="https://avatars.githubusercontent.com/u/701035?v=4" width="80;" alt="turnrye"/>
|
||||
<br />
|
||||
<sub><b>Ryan Turner</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/royshreyaaa">
|
||||
<img src="https://avatars.githubusercontent.com/u/88572557?v=4" width="80;" alt="royshreyaaa"/>
|
||||
<br />
|
||||
<sub><b>Shreya Roy</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/Smexhy">
|
||||
<img src="https://avatars.githubusercontent.com/u/4880625?v=4" width="80;" alt="Smexhy"/>
|
||||
<br />
|
||||
<sub><b>Null</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/XenonR">
|
||||
<img src="https://avatars.githubusercontent.com/u/18627623?v=4" width="80;" alt="XenonR"/>
|
||||
<br />
|
||||
<sub><b>Steffen Schmidt</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/StevKast">
|
||||
<img src="https://avatars.githubusercontent.com/u/17804308?v=4" width="80;" alt="StevKast"/>
|
||||
<br />
|
||||
<sub><b>Steven Kast</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/XertDev">
|
||||
<img src="https://avatars.githubusercontent.com/u/16572811?v=4" width="80;" alt="XertDev"/>
|
||||
<br />
|
||||
<sub><b>Xert</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/dr460nf1r3">
|
||||
<img src="https://avatars.githubusercontent.com/u/12834713?v=4" width="80;" alt="dr460nf1r3"/>
|
||||
<br />
|
||||
<sub><b>Nico</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/flechaig">
|
||||
<img src="https://avatars.githubusercontent.com/u/10887132?v=4" width="80;" alt="flechaig"/>
|
||||
<br />
|
||||
<sub><b>Null</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/icy-comet">
|
||||
<img src="https://avatars.githubusercontent.com/u/50461557?v=4" width="80;" alt="icy-comet"/>
|
||||
<br />
|
||||
<sub><b>Aniket Teredesai</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/imlonghao">
|
||||
<img src="https://avatars.githubusercontent.com/u/4951333?v=4" width="80;" alt="imlonghao"/>
|
||||
<br />
|
||||
<sub><b>Imlonghao</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/jnach">
|
||||
<img src="https://avatars.githubusercontent.com/u/33467747?v=4" width="80;" alt="jnach"/>
|
||||
<br />
|
||||
<sub><b>Jnach</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/jrobles98">
|
||||
<img src="https://avatars.githubusercontent.com/u/30221842?v=4" width="80;" alt="jrobles98"/>
|
||||
<br />
|
||||
<sub><b>Null</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/lxjv">
|
||||
<img src="https://avatars.githubusercontent.com/u/63261955?v=4" width="80;" alt="lxjv"/>
|
||||
<br />
|
||||
<sub><b>Laker Turner</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/pablomalo">
|
||||
<img src="https://avatars.githubusercontent.com/u/25877142?v=4" width="80;" alt="pablomalo"/>
|
||||
<br />
|
||||
<sub><b>Null</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/sur1v">
|
||||
<img src="https://avatars.githubusercontent.com/u/19678230?v=4" width="80;" alt="sur1v"/>
|
||||
<br />
|
||||
<sub><b>José Ignacio</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/tazboyz16">
|
||||
<img src="https://avatars.githubusercontent.com/u/12215340?v=4" width="80;" alt="tazboyz16"/>
|
||||
<br />
|
||||
<sub><b>Null</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/zcq100">
|
||||
<img src="https://avatars.githubusercontent.com/u/425234?v=4" width="80;" alt="zcq100"/>
|
||||
<br />
|
||||
<sub><b>Null</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/AmadeusGraves">
|
||||
<img src="https://avatars.githubusercontent.com/u/18572939?v=4" width="80;" alt="AmadeusGraves"/>
|
||||
<br />
|
||||
<sub><b>Ángel Fernández Sánchez</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
</table>
|
||||
|
141
docs/widgets.md
141
docs/widgets.md
@ -35,6 +35,8 @@ Dashy has support for displaying dynamic content in the form of widgets. There a
|
||||
- [GitHub Trending](#github-trending)
|
||||
- [GitHub Profile Stats](#github-profile-stats)
|
||||
- [Healthchecks Status](#healthchecks status)
|
||||
- [Mvg Departure](#mvg-departure)
|
||||
- [Mvg Connection](#mvg-connection)
|
||||
- **[Self-Hosted Services Widgets](#self-hosted-services-widgets)**
|
||||
- [System Info](#system-info)
|
||||
- [Cron Monitoring](#cron-monitoring-health-checks)
|
||||
@ -43,7 +45,7 @@ Dashy has support for displaying dynamic content in the form of widgets. There a
|
||||
- [System Load History](#load-history-netdata)
|
||||
- [Pi Hole Stats](#pi-hole-stats)
|
||||
- [Pi Hole Queries](#pi-hole-queries)
|
||||
- [Recent Traffic](#recent-traffic)
|
||||
- [Pi Hole Recent Traffic](#pi-hole-recent-traffic)
|
||||
- [Stat Ping Statuses](#stat-ping-statuses)
|
||||
- [Synology Download Station](#synology-download-station)
|
||||
- [AdGuard Home Block Stats](#adguard-home-block-stats)
|
||||
@ -58,6 +60,7 @@ Dashy has support for displaying dynamic content in the form of widgets. There a
|
||||
- [Nextcloud PHP OPcache](#nextcloud-php-opcache-stats)
|
||||
- [Sabnzbd](#sabnzbd)
|
||||
- [Gluetun VPN Info](#gluetun-vpn-info)
|
||||
- [Drone CI Build](#drone-ci-builds)
|
||||
- **[System Resource Monitoring](#system-resource-monitoring)**
|
||||
- [CPU Usage Current](#current-cpu-usage)
|
||||
- [CPU Usage Per Core](#cpu-usage-per-core)
|
||||
@ -620,7 +623,7 @@ Keep track of recent security advisories and vulnerabilities, with optional filt
|
||||
**`minScore`** | `number` | _Optional_ | If set, will only display results with a CVE score higher than the number specified. Can be a number between `0` and `9.9`. By default, vulnerabilities of all CVE scores are shown
|
||||
**`hasExploit`** | `boolean` | _Optional_ | If set to `true`, will only show results with active exploits. Defaults to `false`
|
||||
**`vendorId`** | `number` | _Optional_ | Only show results from a specific vendor, specified by ID. See [Vendor Search](https://www.cvedetails.com/vendor-search.php) for list of vendors. E.g. `23` (Debian), `26` (Microsoft), `23682` (CloudFlare)
|
||||
**`productId`** | `number` | _Optional_ | Only show results from a specific app or product, specified by ID. See [Product Search](https://www.cvedetails.com/product-search.php) for list of products. E.g. `13534` (Docker), `15913` (NextCloud), `19294` (Portainer), `17908` (ProtonMail)
|
||||
**`productId`** | `number` | _Optional_ | Only show results from a specific app or product, specified by ID. See [Product Search](https://www.cvedetails.com/product-search.php) for list of products. E.g. `28125` (Docker), `34622` (NextCloud), `50211` (Portainer), `95391` (ProtonMail)
|
||||
|
||||
#### Example
|
||||
|
||||
@ -635,7 +638,7 @@ or
|
||||
options:
|
||||
sortBy: publish-date
|
||||
productId: 28125
|
||||
hasExploit: true
|
||||
hasExploit: false
|
||||
minScore: 5
|
||||
limit: 30
|
||||
```
|
||||
@ -1173,6 +1176,92 @@ Display status of one or more HealthChecks project(s). Works with healthcheck.io
|
||||
|
||||
---
|
||||
|
||||
### MVG Departure
|
||||
|
||||
Display departure time of a MVG (Münchner Verkehrs Gesellschaft) station.
|
||||
|
||||
From https://www.mvg.de/impressum.html:
|
||||
|
||||
> [...] Die Verarbeitung unserer Inhalte oder Daten durch Dritte erfordert unsere ausdrückliche Zustimmung. Für private, nicht-kommerzielle Zwecke, wird eine gemäßigte Nutzung ohne unsere ausdrückliche Zustimmung geduldet. Jegliche Form von Data-Mining stellt keine gemäßigte Nutzung dar.[...]
|
||||
|
||||
In other words: Private, noncomercial, moderate use of the API is tolerated. They don’t consider data mining as moderate use. (This is not a legal advice)
|
||||
|
||||
#### Options
|
||||
|
||||
**Field** | **Type** | **Required** | **Description**
|
||||
--- | --- | --- | ---
|
||||
**`location`** | `string` | Required | The name of the location (exact) or the location id, startin with `de:09162:`
|
||||
**`limit`** | `integer` | _Optional_ | Limit number of entries, defaults to 10.
|
||||
**`title`** | `string` | _Optional_ | A custom title to be displayed.
|
||||
**`header`** | `bool` | _Optional_ | Shall the title be shown?
|
||||
**`filters`** | `object` | _Optional_ | Filter results
|
||||
**`filters.line`** | `string/array` | _Optional_ | Filter results for given line(s).
|
||||
**`filters.product`** | `string/array` | _Optional_ | Filter results for specific product (TRAM, UBAHN, SBAHN, BUS).
|
||||
**`filters.destination`** | `string/object` | _Optional_ | Filter results for specific destination(s)
|
||||
|
||||
```yaml
|
||||
- type: mvg
|
||||
options:
|
||||
location: Marienplatz
|
||||
limit: 5
|
||||
```
|
||||
|
||||
#### Info
|
||||
|
||||
- **CORS**: 🟢 Enabled
|
||||
- **Auth**: 🟢 Not Required
|
||||
- **Price**: 🟢 Free / Private use only
|
||||
- **Host**: [MVG](https://mvg.de)
|
||||
- **Privacy**: _See [MVG Datenschutz](https://www.mvg.de/datenschutz-mvg.html)_
|
||||
|
||||
---
|
||||
|
||||
### MVG Connection
|
||||
|
||||
Display the next connection for two addresses/coordinates, stations or POI within Munich using MVG MVG (Münchner Verkehrs Gesellschaft).
|
||||
|
||||
From https://www.mvg.de/impressum.html:
|
||||
|
||||
> [...] Die Verarbeitung unserer Inhalte oder Daten durch Dritte erfordert unsere ausdrückliche Zustimmung. Für private, nicht-kommerzielle Zwecke, wird eine gemäßigte Nutzung ohne unsere ausdrückliche Zustimmung geduldet. Jegliche Form von Data-Mining stellt keine gemäßigte Nutzung dar.[...]
|
||||
|
||||
In other words: Private, noncomercial, moderate use of the API is tolerated. They don’t consider data mining as moderate use. (This is not a legal advice)
|
||||
|
||||
#### Options
|
||||
|
||||
**Field** | **Type** | **Required** | **Description**
|
||||
--- | --- | --- | ---
|
||||
**`origin`** | `string` | Required | Origin of the connection.
|
||||
**`destination`** | `string` | Required | Destination of the connection.
|
||||
**`title`** | `string` | _Optional_ | A custom title to be displayed.
|
||||
**`header`** | `bool` | _Optional_ | Shall the title be shown?
|
||||
**`filters`** | `object` | _Optional_ | Filter results
|
||||
**`filters.line`** | `string/array` | _Optional_ | Filter results for given line(s).
|
||||
**`filters.product`** | `string/array` | _Optional_ | Filter results for specific product (TRAM, UBAHN, SBAHN, BUS).
|
||||
**`filters.destination`** | `string/object` | _Optional_ | Filter results for specific destination(s)
|
||||
|
||||
```yaml
|
||||
- type: mvg-connection
|
||||
options:
|
||||
from: Marienplatz
|
||||
from: Dachauer Straße 123
|
||||
header: true
|
||||
filters:
|
||||
product: [UBAHN]
|
||||
line: [U1,U2,U4,U5]
|
||||
|
||||
```
|
||||
|
||||
#### Info
|
||||
|
||||
- **CORS**: 🟢 Enabled
|
||||
- **Auth**: 🟢 Not Required
|
||||
- **Price**: 🟢 Free / Private use only
|
||||
- **Host**: [MVG](https://mvg.de)
|
||||
- **Privacy**: _See [MVG Datenschutz](https://www.mvg.de/datenschutz-mvg.html)_
|
||||
|
||||
---
|
||||
|
||||
|
||||
## Self-Hosted Services Widgets
|
||||
|
||||
### System Info
|
||||
@ -1338,6 +1427,7 @@ Displays the number of queries blocked by [Pi-Hole](https://pi-hole.net/).
|
||||
--- | --- | --- | ---
|
||||
**`hostname`** | `string` | Required | The URL to your Pi-Hole instance
|
||||
**`hideStatus`** / **`hideChart`** / **`hideInfo`** | `boolean` | _Optional_ | Optionally hide any of the three parts of the widget
|
||||
**`apiKey`** | `string` | Required | Your Pi-Hole web password. It is **NOT** your pi-hole admin interface or server password. It can be found in `/etc/pihole/setupVars.conf`, and is a 64-character located on the line that starts with `WEBPASSWORD`
|
||||
|
||||
#### Example
|
||||
|
||||
@ -1345,12 +1435,13 @@ Displays the number of queries blocked by [Pi-Hole](https://pi-hole.net/).
|
||||
- type: pi-hole-stats
|
||||
options:
|
||||
hostname: http://192.168.130.1
|
||||
apiKey: xxxxxxxxxxxxxxxxxxxxxxx
|
||||
```
|
||||
|
||||
#### Info
|
||||
|
||||
- **CORS**: 🟢 Enabled
|
||||
- **Auth**: 🟢 Not Required
|
||||
- **Auth**: 🔴 Required
|
||||
- **Price**: 🟢 Free
|
||||
- **Host**: Self-Hosted (see [GitHub - Pi-hole](https://github.com/pi-hole/pi-hole))
|
||||
- **Privacy**: _See [Pi-Hole Privacy Guide](https://pi-hole.net/privacy/)_
|
||||
@ -1390,7 +1481,7 @@ Shows top queries that were blocked and allowed by [Pi-Hole](https://pi-hole.net
|
||||
|
||||
---
|
||||
|
||||
### Recent Traffic
|
||||
### Pi Hole Recent Traffic
|
||||
|
||||
Shows number of recent traffic, using allowed and blocked queries from [Pi-Hole](https://pi-hole.net/)
|
||||
|
||||
@ -1401,6 +1492,7 @@ Shows number of recent traffic, using allowed and blocked queries from [Pi-Hole]
|
||||
**Field** | **Type** | **Required** | **Description**
|
||||
--- | --- | --- | ---
|
||||
**`hostname`** | `string` | Required | The URL to your Pi-Hole instance
|
||||
**`apiKey`** | `string` | Required | Your Pi-Hole web password. It is **NOT** your pi-hole admin interface or server password. It can be found in `/etc/pihole/setupVars.conf`, and is a 64-character located on the line that starts with `WEBPASSWORD`
|
||||
|
||||
#### Example
|
||||
|
||||
@ -1408,12 +1500,13 @@ Shows number of recent traffic, using allowed and blocked queries from [Pi-Hole]
|
||||
- type: pi-hole-traffic
|
||||
options:
|
||||
hostname: https://pi-hole.local
|
||||
apiKey: xxxxxxxxxxxxxxxxxxxxxxx
|
||||
```
|
||||
|
||||
#### Info
|
||||
|
||||
- **CORS**: 🟢 Enabled
|
||||
- **Auth**: 🟢 Not Required
|
||||
- **Auth**: 🔴 Required
|
||||
- **Price**: 🟢 Free
|
||||
- **Host**: Self-Hosted (see [GitHub - Pi-hole](https://github.com/pi-hole/pi-hole))
|
||||
- **Privacy**: _See [Pi-Hole Privacy Guide](https://pi-hole.net/privacy/)_
|
||||
@ -1943,6 +2036,42 @@ Display info from the Gluetun VPN container public IP API. This can show the IP
|
||||
|
||||
---
|
||||
|
||||
### Drone CI Builds
|
||||
|
||||
Display the last builds from a [Drone CI](https://www.drone.ci) instance. A self-hosted CI system that uses docker.
|
||||
|
||||
<p align="center"><img width="380" src="https://i.ibb.co/nQM3BXj/Bildschirm-foto-2023-01-07-um-01-31-45.png" /></p>
|
||||
|
||||
#### Options
|
||||
|
||||
**Field** | **Type** | **Required** | **Description**
|
||||
--- | --- | --- | ---
|
||||
**`host`** | `string` | Required | The histname of the Drone CI instance.
|
||||
**`apiKey`** | `string` | Required | The API key (https://<your-drone-instance>/account).
|
||||
**`limit`** | `integer` | _Optional_ | Limit the amounts of listed builds.
|
||||
**`repo`** | `string` | _Optional_ | Show only builds of the specified repo
|
||||
|
||||
#### Example
|
||||
|
||||
```yaml
|
||||
- type: drone-io
|
||||
updateInterval: 30
|
||||
options:
|
||||
host: https://drone.somedomain.com
|
||||
apiKey: my-very-secret-api-key
|
||||
limit: 10
|
||||
```
|
||||
|
||||
#### Info
|
||||
|
||||
- **CORS**: 🟢 Enabled
|
||||
- **Auth**: 🟢 Required
|
||||
- **Price**: 🟢 Free
|
||||
- **Host**: Self-Hosted (see [Drone](https://www.drone.io))
|
||||
- **Privacy**: _See [Drone](https://www.drone.io)_
|
||||
|
||||
---
|
||||
|
||||
## System Resource Monitoring
|
||||
|
||||
### Glances
|
||||
|
@ -4,14 +4,21 @@
|
||||
* Note that exiting with code 1 indicates failure, and 0 is success
|
||||
*/
|
||||
|
||||
const http = require('http');
|
||||
const isSsl = !!process.env.SSL_PRIV_KEY_PATH && !!process.env.SSL_PUB_KEY_PATH;
|
||||
|
||||
const http = require(isSsl ? 'https' : 'http');
|
||||
|
||||
/* Location of the server to test */
|
||||
const port = process.env.PORT || !!process.env.IS_DOCKER ? 80 : 4000;
|
||||
const isDocker = !!process.env.IS_DOCKER;
|
||||
const port = isSsl ? (process.env.SSL_PORT || (isDocker ? 443 : 4001)) : (process.env.PORT || isDocker ? 80 : 4000);
|
||||
const host = process.env.HOST || '0.0.0.0';
|
||||
const timeout = 2000;
|
||||
|
||||
const requestOptions = { host, port, timeout };
|
||||
const agent = new http.Agent({
|
||||
rejectUnauthorized: false, // Allow self-signed certificates
|
||||
});
|
||||
|
||||
const requestOptions = { host, port, timeout, agent };
|
||||
|
||||
const startTime = new Date(); // Initialize timestamp to calculate time taken
|
||||
|
||||
|
@ -92,7 +92,7 @@ export default {
|
||||
},
|
||||
endpoint() {
|
||||
return `${widgetApiEndpoints.cveVulnerabilities}?${this.sortBy}${this.limit}`
|
||||
+ `${this.minScore}${this.vendorId}${this.hasExploit}`;
|
||||
+ `${this.minScore}${this.vendorId}${this.productId}${this.hasExploit}`;
|
||||
},
|
||||
proxyReqEndpoint() {
|
||||
const baseUrl = process.env.VUE_APP_DOMAIN || window.location.origin;
|
||||
|
238
src/components/Widgets/DroneCi.vue
Normal file
238
src/components/Widgets/DroneCi.vue
Normal file
@ -0,0 +1,238 @@
|
||||
<template>
|
||||
<div class="droneci-builds-wrapper" v-if="builds">
|
||||
<div
|
||||
class="build-row"
|
||||
v-for="build in builds" :key="build.id"
|
||||
v-tooltip="infoTooltip(build)"
|
||||
>
|
||||
<div class="status">
|
||||
<p :class="build.build.status">{{ build.build.status | formatStatus }}</p>
|
||||
<span v-if="build.build.status == 'running'">
|
||||
{{ build.build.started*1000 | formatTimeAgo }} ago
|
||||
</span>
|
||||
<span v-else-if="build.build.status != 'pending' ">
|
||||
{{ formatBuildDuration(build) }}
|
||||
</span>
|
||||
<span v-else>
|
||||
{{ build.build.created*1000 | formatTimeAgo }} ago
|
||||
</span>
|
||||
</div>
|
||||
<div class="info">
|
||||
<div class="build-name">
|
||||
{{ build.name }}
|
||||
<a
|
||||
class="droneci-build-number"
|
||||
:href="build.baseurl + '/' + build.slug + '/' +build.build.number"
|
||||
target="_blank"
|
||||
>{{ build.build.number }}</a>
|
||||
</div>
|
||||
<div class="build-desc">
|
||||
<span class="droneci-extra">
|
||||
<template v-if="build.build.event == 'pull_request'">
|
||||
<a
|
||||
:href="build.build.link"
|
||||
target="_blank"
|
||||
class="droneci-extra-info"
|
||||
>#{{ formatPrId(build.build.link) }}</a> to
|
||||
</template>
|
||||
<template v-else-if="build.build.event == 'push'">
|
||||
<a
|
||||
:href="build.build.link"
|
||||
target="_blank"
|
||||
class="droneci-extra-info"
|
||||
>push</a> to
|
||||
</template>
|
||||
<a
|
||||
:href="build.git_http_url"
|
||||
target="_blank"
|
||||
class="droneci-extra-info"
|
||||
>
|
||||
{{ build.build.target }}
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import WidgetMixin from '@/mixins/WidgetMixin';
|
||||
import { getTimeAgo, getTimeDifference, timestampToDateTime } from '@/utils/MiscHelpers';
|
||||
|
||||
export default {
|
||||
mixins: [WidgetMixin],
|
||||
components: {},
|
||||
data() {
|
||||
return {
|
||||
builds: null,
|
||||
};
|
||||
},
|
||||
filters: {
|
||||
formatStatus(status) {
|
||||
let symbol = '';
|
||||
if (status === 'success') symbol = '✔';
|
||||
if (status === 'failure' || status === 'error' || status === 'killed') symbol = '✘';
|
||||
if (status === 'running') symbol = '❖';
|
||||
if (status === 'skipped') symbol = '↠';
|
||||
return `${symbol}`;
|
||||
},
|
||||
formatDate(timestamp) {
|
||||
return timestampToDateTime(timestamp);
|
||||
},
|
||||
formatTimeAgo(timestamp) {
|
||||
return getTimeAgo(timestamp);
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
/* API endpoint, either for self-hosted or managed instance */
|
||||
endpointBuilds() {
|
||||
if (!this.options.host) this.error('drone.ci Host is required');
|
||||
return `${this.options.host}/api/user/builds`;
|
||||
},
|
||||
endpointRepoInfo() {
|
||||
if (!this.options.host) this.error('drone.ci Host is required');
|
||||
return `${this.options.host}/api/repos/${this.options.repo}`;
|
||||
},
|
||||
endpointRepoBuilds() {
|
||||
if (!this.options.host) this.error('drone.ci Host is required');
|
||||
return `${this.options.host}/api/repos/${this.options.repo}/builds`;
|
||||
},
|
||||
repo() {
|
||||
if (this.options.repo) return this.options.repo;
|
||||
return false;
|
||||
},
|
||||
apiKey() {
|
||||
if (!this.options.apiKey) {
|
||||
this.error('An API key is required, please see the docs for more info');
|
||||
}
|
||||
return this.options.apiKey;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
/* Fetch new data, configured by updateInterval */
|
||||
update() {
|
||||
this.startLoading();
|
||||
this.fetchData();
|
||||
this.finishLoading();
|
||||
},
|
||||
/* Make GET request to Drone CI API endpoint */
|
||||
fetchData() {
|
||||
const authHeaders = { Authorization: `Bearer ${this.apiKey}` };
|
||||
if (this.repo !== false) {
|
||||
this.makeRequest(this.endpointRepoInfo, authHeaders).then(
|
||||
(repoInfo) => {
|
||||
this.makeRequest(this.endpointRepoBuilds, authHeaders).then(
|
||||
(buildInfo) => {
|
||||
this.processRepoBuilds(repoInfo, buildInfo);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
} else {
|
||||
this.makeRequest(this.endpointBuilds, authHeaders).then(
|
||||
(response) => { this.processBuilds(response); },
|
||||
);
|
||||
}
|
||||
},
|
||||
/* Assign data variables to the returned data */
|
||||
processBuilds(data) {
|
||||
const results = data.slice(0, this.options.limit)
|
||||
.map((obj) => ({ ...obj, baseurl: this.options.host }));
|
||||
this.builds = results;
|
||||
},
|
||||
processRepoBuilds(repo, builds) {
|
||||
const results = builds.slice(0, this.options.limit)
|
||||
.map((obj) => ({ build: { ...obj }, baseurl: this.options.host, ...repo }));
|
||||
this.builds = results;
|
||||
},
|
||||
infoTooltip(build) {
|
||||
const content = `<b>Trigger:</b> ${build.build.event} by ${build.build.trigger}<br>`
|
||||
+ `<b>Repo:</b> ${build.slug}<br>`
|
||||
+ `<b>Branch:</b> ${build.build.target}<br>`;
|
||||
return {
|
||||
content, html: true, trigger: 'hover focus', delay: 250, classes: 'build-info-tt',
|
||||
};
|
||||
},
|
||||
formatPrId(link) {
|
||||
return link.split('/').pop();
|
||||
},
|
||||
formatBuildDuration(build) {
|
||||
return getTimeDifference(build.build.started * 1000, build.build.finished * 1000);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.droneci-builds-wrapper {
|
||||
color: var(--widget-text-color);
|
||||
.build-row {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 2.5fr;
|
||||
justify-content: left;
|
||||
align-items: center;
|
||||
padding: 0.25rem 0;
|
||||
.status {
|
||||
font-size: 1rem;
|
||||
font-weight: bold;
|
||||
p {
|
||||
margin: 0;
|
||||
color: var(--info);
|
||||
&.success { color: var(--success); }
|
||||
&.failure { color: var(--danger); }
|
||||
&.error { color: var(--danger); }
|
||||
&.running { color: var(--neutral); }
|
||||
}
|
||||
span {
|
||||
font-size: 0.75rem;
|
||||
color: var(--secondary);
|
||||
}
|
||||
}
|
||||
.info {
|
||||
div.build-name {
|
||||
margin: 0.25rem 0;
|
||||
font-weight: bold;
|
||||
color: var(--widget-text-color);
|
||||
a, a:hover, a:visited, a:active {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
.droneci-build-number::before {
|
||||
content: "#";
|
||||
}
|
||||
}
|
||||
div.build-desc {
|
||||
margin: 0;
|
||||
font-size: 0.85rem;
|
||||
color: var(--widget-text-color);
|
||||
opacity: var(--dimming-factor);
|
||||
a, a:hover, a:visited, a:active {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
.droneci-extra {
|
||||
.droneci-extra-info {
|
||||
margin: 0.25em;
|
||||
padding: 0em 0.25em;
|
||||
background: var(--item-background);
|
||||
border: 1px solid var(--primary);
|
||||
border-radius: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
&:not(:last-child) {
|
||||
border-bottom: 1px dashed var(--widget-text-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<style lang="scss">
|
||||
.build-info-tt {
|
||||
min-width: 20rem;
|
||||
}
|
||||
</style>
|
@ -1,14 +1,15 @@
|
||||
<template>
|
||||
<div class="health-checks-wrapper" v-if="crons">
|
||||
<template
|
||||
v-for="cron in crons" :key="cron.id"
|
||||
v-for="cron in crons"
|
||||
>
|
||||
<div class="status">
|
||||
<div class="status" v-bind:key="cron.id + 'status'">
|
||||
<p :class="cron.status">{{ cron.status | formatStatus }}</p>
|
||||
</div>
|
||||
<div
|
||||
<div
|
||||
class="info"
|
||||
v-tooltip="pingTimeTooltip(cron)"
|
||||
v-bind:key="cron.id + 'info'"
|
||||
>
|
||||
<p class="cron-name">{{ cron.name }}</p>
|
||||
<p class="cron-desc">{{ cron.desc }}</p>
|
||||
@ -37,7 +38,7 @@ export default {
|
||||
if (status === 'down') symbol = '✘';
|
||||
if (status === 'new') symbol = '❖';
|
||||
if (status === 'paused') symbol = '⏸';
|
||||
if (status === 'running') symbol = '▶'
|
||||
if (status === 'running') symbol = '▶';
|
||||
return `${symbol} ${capitalize(status)}`;
|
||||
},
|
||||
formatDate(timestamp) {
|
||||
@ -54,8 +55,8 @@ export default {
|
||||
if (!this.options.apiKey) {
|
||||
this.error('An API key is required, please see the docs for more info');
|
||||
}
|
||||
if (typeof(this.options.apiKey) === "string") {
|
||||
return [ this.options.apiKey ];
|
||||
if (typeof this.options.apiKey === 'string') {
|
||||
return [this.options.apiKey];
|
||||
}
|
||||
return this.options.apiKey;
|
||||
},
|
||||
@ -71,7 +72,7 @@ export default {
|
||||
(response) => { this.processData(response, results); },
|
||||
);
|
||||
});
|
||||
results.sort((a,b) => (a.name > b.name) ? 1 : ((b.name > a.name) ? -1 : 0));
|
||||
results.sort((a, b) => ((a.name > b.name) ? 1 : -1));
|
||||
this.crons = results;
|
||||
},
|
||||
/* Assign data variables to the returned data */
|
||||
|
353
src/components/Widgets/Mvg.vue
Normal file
353
src/components/Widgets/Mvg.vue
Normal file
@ -0,0 +1,353 @@
|
||||
<template>
|
||||
<div class="mvg-wrapper" v-if="departures">
|
||||
<template
|
||||
v-for="departure in departures"
|
||||
>
|
||||
<div class="departure" v-bind:key="departure.key" v-tooltip="mvgTooltipDeparture(departure)">
|
||||
<span :class="{live: departure.live}">
|
||||
{{ departure.realtimeDepartureTime | formatDepartureTime }}
|
||||
</span>
|
||||
</div>
|
||||
<div class='line'
|
||||
v-bind:key="departure.key + 'line'"
|
||||
>
|
||||
<div
|
||||
class="transport"
|
||||
:class="['type-' + departure.transportType,
|
||||
'line-' + departure.label,
|
||||
]"
|
||||
>{{ departure.label }}</div>
|
||||
<div
|
||||
class='destination'
|
||||
v-tooltip="mvgTooltipDestination(departure)"
|
||||
:class="{cancelled: departure.cancelled}">{{ departure.destination }}</div>
|
||||
<span class="delay"
|
||||
:class="{'has-delay': departure.realtimeDepartureTime > departure.plannedDepartureTime}"
|
||||
>{{ Math.max(0,
|
||||
(departure.realtimeDepartureTime - departure.plannedDepartureTime)/60000) }}</span>
|
||||
<span class="occupancy"
|
||||
:class="'occupancy-' + departure.occupancy"
|
||||
v-if="departure.occupancy != 'UNKNOWN'"
|
||||
v-tooltip="departure.occupancy"
|
||||
>■</span>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import WidgetMixin from '@/mixins/WidgetMixin';
|
||||
import { widgetApiEndpoints } from '@/utils/defaults';
|
||||
import { timestampToTime } from '@/utils/MiscHelpers';
|
||||
|
||||
export default {
|
||||
mixins: [WidgetMixin],
|
||||
components: {},
|
||||
data() {
|
||||
return {
|
||||
departures: null,
|
||||
locationSearch: null,
|
||||
};
|
||||
},
|
||||
created() {
|
||||
if (!this.isLocationId) {
|
||||
this.makeRequest(this.endpointLocation).then(
|
||||
(response) => {
|
||||
const stations = response.filter((r) => r.type === 'STATION');
|
||||
if (stations.length > 0) {
|
||||
this.location = stations[0].globalId;
|
||||
this.fetchData();
|
||||
} else {
|
||||
this.error('Cannot find station for specified string');
|
||||
}
|
||||
},
|
||||
);
|
||||
} else {
|
||||
this.location = this.options.location;
|
||||
}
|
||||
},
|
||||
filters: {
|
||||
formatDepartureTime(timestamp) {
|
||||
const msDifference = new Date(timestamp).getTime() - new Date().getTime();
|
||||
const diff = Math.max(0, Math.round(msDifference / 60000));
|
||||
return diff;
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
isLocationId() {
|
||||
if (!this.options.location) {
|
||||
this.error('Location is required');
|
||||
}
|
||||
if (typeof this.options.location !== 'string') this.error('Location can only be a string');
|
||||
if (this.options.location.startsWith('de:09162:')) return true;
|
||||
return false;
|
||||
},
|
||||
offset() {
|
||||
if (this.options.offset) return this.options.offset;
|
||||
return 0;
|
||||
},
|
||||
limit() {
|
||||
return this.options.limit || 10;
|
||||
},
|
||||
endpointDeparture() {
|
||||
return `${widgetApiEndpoints.mvg}/departure?globalId=${this.location}&limit=30&offsetInMinutes=${this.offset}&transportTypes=UBAHN,TRAM,BUS,SBAHN`;
|
||||
},
|
||||
endpointLocation() {
|
||||
return `${widgetApiEndpoints.mvg}/location?query=${encodeURIComponent(this.options.location)}`;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
update() {
|
||||
this.startLoading();
|
||||
this.fetchData();
|
||||
this.finishLoading();
|
||||
},
|
||||
fetchData() {
|
||||
if (this.location !== undefined) {
|
||||
this.makeRequest(this.endpointDeparture).then(
|
||||
(response) => { this.processData(response); },
|
||||
);
|
||||
}
|
||||
},
|
||||
/* Assign data variables to the returned data */
|
||||
processData(data) {
|
||||
let i = 0;
|
||||
const results = [];
|
||||
data
|
||||
.filter(this.filter_results)
|
||||
.sort(this.sort_results)
|
||||
.slice(0, this.limit).forEach((dep) => {
|
||||
results.push({ ...dep, key: `mvg-dep-${this.location}-${i}` });
|
||||
i += 1;
|
||||
});
|
||||
this.departures = results;
|
||||
},
|
||||
ensure_array(value) {
|
||||
if (typeof value === 'string') {
|
||||
return [value];
|
||||
}
|
||||
return value;
|
||||
},
|
||||
filter_results(value) {
|
||||
if (!this.options.filters) return true;
|
||||
let useEntry = (
|
||||
(!this.options.filters.line)
|
||||
|| this.ensure_array(this.options.filters.line).includes(value.label)
|
||||
);
|
||||
useEntry = useEntry
|
||||
&& (
|
||||
(!this.options.filters.product)
|
||||
|| this.ensure_array(this.options.filters.product)
|
||||
.some(x => x.toLowerCase() === value.transportType.toLowerCase())
|
||||
);
|
||||
useEntry = useEntry
|
||||
&& (
|
||||
(!this.options.filters.destination)
|
||||
|| this.ensure_array(this.options.filters.destination)
|
||||
.some(x => x.toLowerCase() === value.destination.toLowerCase())
|
||||
);
|
||||
return useEntry;
|
||||
},
|
||||
sort_results(a, b) {
|
||||
const depa = a.realtimeDepartureTime ? a.realtimeDepartureTime : a.plannedDepartureTime;
|
||||
const depb = b.realtimeDepartureTime ? b.realtimeDepartureTime : b.plannedDepartureTime;
|
||||
if (depa > depb) return 1;
|
||||
if (depa < depb) return -1;
|
||||
if (a.label < b.label) return 1;
|
||||
if (a.label > b.label) return -1;
|
||||
if (a.destination < b.destination) return 1;
|
||||
if (a.destination > b.destination) return -1;
|
||||
return 0;
|
||||
},
|
||||
makeUrl(cronId) {
|
||||
const base = this.options.host || 'https://healthchecks.io';
|
||||
return `${base}/checks/${cronId}/details`;
|
||||
},
|
||||
mvgTooltipDeparture(data) {
|
||||
let departureDetails = '';
|
||||
if (data.realtime) {
|
||||
departureDetails += `Live: ${timestampToTime(data.realtimeDepartureTime)}<br />`;
|
||||
}
|
||||
departureDetails += `Planned: ${timestampToTime(data.plannedDepartureTime)}<br />`;
|
||||
if (data.realtime) {
|
||||
departureDetails += 'Live!<br />';
|
||||
}
|
||||
return {
|
||||
content: departureDetails, html: true, trigger: 'hover', delay: 250, classes: 'mvg-info-tt',
|
||||
};
|
||||
},
|
||||
mvgTooltipDestination(data) {
|
||||
let departureDetails = `<b>Infos:</b><br />${data.messages.join('<br />')}`;
|
||||
if (data.platform) {
|
||||
departureDetails += `Platform: ${data.platform}<br />`;
|
||||
}
|
||||
if (data.cancelled) {
|
||||
departureDetails += '<b>Cancelled!</b><br />';
|
||||
}
|
||||
return {
|
||||
content: departureDetails, html: true, trigger: 'hover', delay: 250, classes: 'mvg-info-tt',
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.mvg-wrapper {
|
||||
display: grid;
|
||||
justify-content: left;
|
||||
grid-template-columns: 1fr 9fr;
|
||||
color: var(--widget-text-color);
|
||||
padding: 0.25rem 0;
|
||||
grid-row-gap: 0.4em;
|
||||
.departure {
|
||||
min-width: 1rem;
|
||||
font-size: 1.1rem;
|
||||
font-weight: bold;
|
||||
text-align: right;
|
||||
margin-right: 0.2rem;
|
||||
span.live {
|
||||
color: var(--success);
|
||||
}
|
||||
}
|
||||
.line {
|
||||
background-color: #FFFFFF;
|
||||
margin: 0;
|
||||
padding-right: 0.2em;
|
||||
border-radius: 0.2em;
|
||||
display: grid;
|
||||
grid-template-columns: 2.2em 1fr minmax(1.5em,max-content) 0.75em;
|
||||
.type-UBAHN {
|
||||
border: 0px;
|
||||
}
|
||||
.type-SBAHN {
|
||||
border: 0px;
|
||||
}
|
||||
.type-BUS {
|
||||
}
|
||||
.type-TRAM {
|
||||
}
|
||||
.transport{
|
||||
border-top-left-radius: 0.2em 0.2em;
|
||||
border-bottom-left-radius: 0.2em 0.2em;
|
||||
margin: 0em;
|
||||
padding: 0.15em 0;
|
||||
color: #FFFFFF;
|
||||
margin-right: 0.40em;
|
||||
text-align: center;
|
||||
span {
|
||||
min-width: 2em;
|
||||
display: inline-block;
|
||||
}
|
||||
&.line-U1 {
|
||||
background-color: #468447;
|
||||
}
|
||||
&.line-U2 {
|
||||
background-color: #dd3d4d;
|
||||
}
|
||||
&.line-U3 {
|
||||
background-color: #ef8824;
|
||||
}
|
||||
&.line-U4 {
|
||||
background-color: #04af90;
|
||||
}
|
||||
&.line-U5 {
|
||||
background-color: #b78730;
|
||||
}
|
||||
&.line-U6 {
|
||||
background-color: #0472b3;
|
||||
}
|
||||
&.line-S1 {
|
||||
background-color: #79c6e7;
|
||||
}
|
||||
&.line-S2 {
|
||||
background-color: #9bc04c;
|
||||
}
|
||||
&.line-S3 {
|
||||
background-color: #942d8d;
|
||||
}
|
||||
&.line-S4 {
|
||||
background-color: #d4214d;
|
||||
}
|
||||
&.line-S5 {
|
||||
background-color: #03a074;
|
||||
}
|
||||
&.line-S6 {
|
||||
background-color: #03a074;
|
||||
}
|
||||
&.line-S7 {
|
||||
background-color: #964438;
|
||||
}
|
||||
&.line-S8 {
|
||||
background-color: #000000;
|
||||
}
|
||||
&.type-BUS {
|
||||
background-color: #0d5c70;
|
||||
}
|
||||
}
|
||||
.destination{
|
||||
border-radius: 0.2em;
|
||||
width: 100%;
|
||||
background-color: #FFFFFF;
|
||||
color: #000;
|
||||
padding-top: 0.15em;
|
||||
padding-bottom: 0.15em;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
span.cancelled {
|
||||
color: var(--danger);
|
||||
text-decoration: line-through;
|
||||
}
|
||||
span.destination {
|
||||
overflow: clip;
|
||||
margin-right: 0.25em;
|
||||
width: 75%;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
.delay{
|
||||
padding: 0.15em;
|
||||
font-weight: bold;
|
||||
&.has-delay{
|
||||
padding: 0.15em;
|
||||
background-color: var(--danger);
|
||||
color: #FFF;
|
||||
border-radius: 0.2em;
|
||||
}
|
||||
}
|
||||
.delay::before{
|
||||
content: "+";
|
||||
}
|
||||
.occupancy{
|
||||
display: inline-block;
|
||||
padding: 0 0.15em;
|
||||
border-radius: 0.2em;
|
||||
&.occupancy-LOW {
|
||||
color: green;
|
||||
}
|
||||
&.occupancy-MEDIUM {
|
||||
color: orange;
|
||||
}
|
||||
&.occupancy-HIGH {
|
||||
color: red;
|
||||
}
|
||||
}
|
||||
}
|
||||
&:not(:last-child) {
|
||||
border-bottom: 1px dashed var(--widget-text-color);
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<style lang="scss">
|
||||
.ping-times-tt {
|
||||
min-width: 20rem;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss">
|
||||
.mvg-info-tt {
|
||||
min-width: 20rem;
|
||||
}
|
||||
</style>
|
372
src/components/Widgets/MvgConnection.vue
Normal file
372
src/components/Widgets/MvgConnection.vue
Normal file
@ -0,0 +1,372 @@
|
||||
<template>
|
||||
<div class="mvg-connections-outer-wrapper">
|
||||
<div class="mvg-connections-header" v-if="showTitle">{{ connectionName }}</div>
|
||||
<div class="mvg-wrapper" v-if="connections">
|
||||
<div
|
||||
v-for="connection in connections"
|
||||
v-bind:key="connection.uniqueId"
|
||||
class="line"
|
||||
v-tooltip="mvgTooltipConnection(connection)"
|
||||
>
|
||||
<div
|
||||
class="departure"
|
||||
>
|
||||
<span class="time"
|
||||
>
|
||||
{{connection.parts[0].from.plannedDeparture | formatTime}}
|
||||
</span>
|
||||
<span class="delay"
|
||||
:class="{'has-delay': connection.parts[0].from.departureDelayInMinutes > 0}"
|
||||
>{{ Math.max(parseInt(connection.parts[0].from.departureDelayInMinutes) || 0, 0) }}</span>
|
||||
</div>
|
||||
<div
|
||||
class="changes"
|
||||
>
|
||||
<template
|
||||
v-for="(part,index) in connection.parts"
|
||||
>
|
||||
<span
|
||||
v-if="index > 0"
|
||||
v-bind:key="'change-' + index"
|
||||
class="change"
|
||||
v-tooltip="part.from.name"
|
||||
>⬌</span>
|
||||
<span
|
||||
v-bind:key="'transport-' + index"
|
||||
:class="['type-' + part.line.transportType,
|
||||
'line-' + part.line.label,
|
||||
]"
|
||||
v-if="part.line.transportType != 'PEDESTRIAN'"
|
||||
class="transport"
|
||||
>{{part.line.label}}</span>
|
||||
<span v-else
|
||||
v-bind:key="'transport-' + index"
|
||||
>🚶</span>
|
||||
</template>
|
||||
</div>
|
||||
<span class="time">
|
||||
{{Date.parse(connection.parts[connection.parts.length-1]
|
||||
.to.plannedDeparture) - Date.parse(connection.parts[0]
|
||||
.from.plannedDeparture) | formatDuration}}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import WidgetMixin from '@/mixins/WidgetMixin';
|
||||
import { widgetApiEndpoints } from '@/utils/defaults';
|
||||
|
||||
export default {
|
||||
mixins: [WidgetMixin],
|
||||
components: {},
|
||||
data() {
|
||||
return {
|
||||
connections: null,
|
||||
locationSearch: null,
|
||||
connectionName: null,
|
||||
defaultTitle: "Connection",
|
||||
locations: {
|
||||
origin: undefined,
|
||||
destination: undefined,
|
||||
},
|
||||
};
|
||||
},
|
||||
created() {
|
||||
const promStart = this.getLocationId(this.start);
|
||||
const promEnd = this.getLocationId(this.end);
|
||||
Promise.all([promStart, promEnd]).then(
|
||||
(results) => {
|
||||
[this.locations.origin, this.locations.destination] = results.map((r) => r[0]);
|
||||
this.defaultTitle = `${this.locations.origin.name} - ${this.locations.destination.name}`;
|
||||
this.fetchData();
|
||||
},
|
||||
);
|
||||
},
|
||||
filters: {
|
||||
formatDepartureTime(timestamp) {
|
||||
const msDifference = new Date(timestamp).getTime() - new Date().getTime();
|
||||
const diff = Math.max(0, Math.round(msDifference / 60000));
|
||||
return diff;
|
||||
},
|
||||
formatTime(str) {
|
||||
const d = new Date(Date.parse(str));
|
||||
function ii(i) {
|
||||
let s = `${i}`;
|
||||
if (s.length < 2) s = `0${s}`;
|
||||
return s;
|
||||
}
|
||||
return `${ii(d.getHours())}:${ii(d.getMinutes())}`;
|
||||
},
|
||||
formatDuration(val) {
|
||||
function ii(i) {
|
||||
let s = `${i}`;
|
||||
if (s.length < 2) s = `0${s}`;
|
||||
return s;
|
||||
}
|
||||
return `${Math.floor(val / 3600000)}:${ii(Math.floor(val / 60000))}`;
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
start() {
|
||||
return this.options.from || this.options.start || this.options.origin || 'Marienplatz';
|
||||
},
|
||||
end() {
|
||||
return this.options.to || this.options.end || this.options.destination || 'Giesing';
|
||||
},
|
||||
title() {
|
||||
if (this.options.title) {
|
||||
return this.options.title;
|
||||
}
|
||||
return this.defaultTitle;
|
||||
},
|
||||
showTitle() {
|
||||
return (this.options.header) ? this.options.header : true;
|
||||
},
|
||||
transportTypes() {
|
||||
if (this.options.transportations) {
|
||||
return this.options.transportations.join(',');
|
||||
}
|
||||
return 'UBAHN,TRAM,BUS,SBAHN';
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
formatPoint(point, typ) {
|
||||
if (point.type === 'ADDRESS' || point.type === 'POI') {
|
||||
return `${typ}Latitude=${point.latitude}&${typ}Longitude=${point.longitude}`;
|
||||
}
|
||||
return `${typ}StationGlobalId=${point.globalId}`;
|
||||
},
|
||||
isLocationId(loc) {
|
||||
if (!loc) {
|
||||
this.error('Location is required');
|
||||
}
|
||||
if (typeof loc !== 'string') this.error('Location can only be a string');
|
||||
return (loc.startsWith('de:09162:'));
|
||||
},
|
||||
getLocationId(loc) {
|
||||
return this.makeRequest(this.getEndpointLocation(loc));
|
||||
},
|
||||
getEndpointLocation(loc) {
|
||||
return `${widgetApiEndpoints.mvg}/location?query=${encodeURIComponent(loc)}`;
|
||||
},
|
||||
endpointConnection() {
|
||||
return `${widgetApiEndpoints.mvg}/connection?${this.formatPoint(this.locations.origin, 'origin')}&${this.formatPoint(this.locations.destination, 'destination')}&routingDateTime=${(new Date()).toISOString()}&offsetInMinutes=${this.offset}&transportTypes=${this.transportTypes}`;
|
||||
},
|
||||
update() {
|
||||
this.startLoading();
|
||||
this.fetchData();
|
||||
this.finishLoading();
|
||||
},
|
||||
fetchData() {
|
||||
if (this.locations.origin !== undefined
|
||||
&& this.locations.destination !== undefined) {
|
||||
this.makeRequest(this.endpointConnection()).then(
|
||||
(response) => { this.processData(response); },
|
||||
);
|
||||
}
|
||||
},
|
||||
/* Assign data variables to the returned data */
|
||||
processData(data) {
|
||||
this.connections = data;
|
||||
},
|
||||
ensure_array(value) {
|
||||
if (typeof value === 'string') {
|
||||
return [value];
|
||||
}
|
||||
return value;
|
||||
},
|
||||
mvgTooltipConnection(data) {
|
||||
let connectionDetails = '';
|
||||
const self = this;
|
||||
function addStep(step) {
|
||||
connectionDetails += `<b>${self.$options.filters.formatTime(step.plannedDeparture)}</b>
|
||||
<span class="delay">+${Math.max(parseInt(step.departureDelayInMinutes, 10) || 0, 0)}</span>
|
||||
<span>${step.name}</span>`;
|
||||
}
|
||||
addStep(data.parts[0].from);
|
||||
data.parts.forEach((part) => {
|
||||
addStep(part.to);
|
||||
});
|
||||
return {
|
||||
content: connectionDetails, html: true, trigger: 'hover', delay: 250, classes: 'mvg-connection-detail',
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.mvg-header {
|
||||
color: var(--widget-text-color);
|
||||
font-size:1.2em;
|
||||
}
|
||||
.mvg-wrapper {
|
||||
display: grid;
|
||||
justify-content: left;
|
||||
grid-template-columns: 100%;
|
||||
color: var(--widget-text-color);
|
||||
padding: 0.25rem 0;
|
||||
grid-row-gap: 0.4em;
|
||||
.departure {
|
||||
min-width: 1rem;
|
||||
font-size: 1.1rem;
|
||||
font-weight: bold;
|
||||
text-align: right;
|
||||
margin-right: 0.2rem;
|
||||
span.live {
|
||||
color: var(--success);
|
||||
}
|
||||
}
|
||||
.line {
|
||||
margin: 0em;
|
||||
padding: 0em;
|
||||
border-radius: 0.2em;
|
||||
display: grid;
|
||||
grid-template-columns: 2fr 5fr 0.75fr;
|
||||
.changes {
|
||||
text-align: center;
|
||||
}
|
||||
.type-UBAHN {
|
||||
border: 0px;
|
||||
}
|
||||
.type-SBAHN {
|
||||
border: 0px;
|
||||
}
|
||||
.type-BUS {
|
||||
}
|
||||
.type-TRAM {
|
||||
background-color: #dd3d4d;
|
||||
}
|
||||
.transport{
|
||||
border-radius: 0.2em;
|
||||
margin: 0em;
|
||||
padding: 0.15em 0.15em;
|
||||
color: #FFFFFF;
|
||||
margin-right: 0.40em;
|
||||
margin-left: 0.40em;
|
||||
text-align: center;
|
||||
span {
|
||||
min-width: 2em;
|
||||
display: inline-block;
|
||||
}
|
||||
&.line-Fussweg {
|
||||
text-indent: 100%;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
&.line-U1 {
|
||||
background-color: #468447;
|
||||
}
|
||||
&.line-U2 {
|
||||
background-color: #dd3d4d;
|
||||
}
|
||||
&.line-U3 {
|
||||
background-color: #ef8824;
|
||||
}
|
||||
&.line-U4 {
|
||||
background-color: #04af90;
|
||||
}
|
||||
&.line-U5 {
|
||||
background-color: #b78730;
|
||||
}
|
||||
&.line-U6 {
|
||||
background-color: #0472b3;
|
||||
}
|
||||
&.line-S1 {
|
||||
background-color: #79c6e7;
|
||||
}
|
||||
&.line-S2 {
|
||||
background-color: #9bc04c;
|
||||
}
|
||||
&.line-S3 {
|
||||
background-color: #942d8d;
|
||||
}
|
||||
&.line-S4 {
|
||||
background-color: #d4214d;
|
||||
}
|
||||
&.line-S5 {
|
||||
background-color: #03a074;
|
||||
}
|
||||
&.line-S6 {
|
||||
background-color: #03a074;
|
||||
}
|
||||
&.line-S7 {
|
||||
background-color: #964438;
|
||||
}
|
||||
&.line-S8 {
|
||||
background-color: #000000;
|
||||
}
|
||||
&.type-BUS {
|
||||
background-color: #0d5c70;
|
||||
}
|
||||
}
|
||||
.destination{
|
||||
border-radius: 0.2em;
|
||||
width: 100%;
|
||||
background-color: #FFFFFF;
|
||||
color: #000;
|
||||
padding-top: 0.15em;
|
||||
padding-bottom: 0.15em;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
span.cancelled {
|
||||
color: var(--danger);
|
||||
text-decoration: line-through;
|
||||
}
|
||||
span.destination {
|
||||
overflow: clip;
|
||||
margin-right: 0.25em;
|
||||
width: 75%;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
.delay{
|
||||
padding: 0.15em;
|
||||
font-weight: bold;
|
||||
&.has-delay{
|
||||
padding: 0.15em;
|
||||
background-color: var(--danger);
|
||||
color: #FFF;
|
||||
border-radius: 0.2em;
|
||||
}
|
||||
}
|
||||
.delay::before{
|
||||
content: "+";
|
||||
}
|
||||
.occupancy{
|
||||
display: inline-block;
|
||||
padding: 0 0.15em;
|
||||
border-radius: 0.2em;
|
||||
&.occupancy-LOW {
|
||||
color: green;
|
||||
}
|
||||
&.occupancy-MEDIUM {
|
||||
color: orange;
|
||||
}
|
||||
&.occupancy-HIGH {
|
||||
color: red;
|
||||
}
|
||||
}
|
||||
}
|
||||
&:not(:last-child) {
|
||||
border-bottom: 1px dashed var(--widget-text-color);
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<style lang="scss">
|
||||
.ping-times-tt {
|
||||
min-width: 20rem;
|
||||
}
|
||||
</style>
|
||||
<style lang="scss">
|
||||
.mvg-connection-detail .tooltip-inner {
|
||||
min-width: 20rem;
|
||||
display: grid;
|
||||
grid-template-columns: 2fr 1fr 6fr;
|
||||
}
|
||||
</style>
|
@ -40,8 +40,12 @@ export default {
|
||||
if (!usersChoice) this.error('You must specify the hostname for your Pi-Hole server');
|
||||
return usersChoice || 'http://pi.hole';
|
||||
},
|
||||
apiKey() {
|
||||
if (!this.options.apiKey) this.error('API Key is required, please see the docs');
|
||||
return this.options.apiKey;
|
||||
},
|
||||
endpoint() {
|
||||
return `${this.hostname}/admin/api.php`;
|
||||
return `${this.hostname}/admin/api.php?summary&auth=${this.apiKey}`;
|
||||
},
|
||||
hideStatus() { return this.options.hideStatus; },
|
||||
hideChart() { return this.options.hideChart; },
|
||||
@ -57,7 +61,11 @@ export default {
|
||||
fetchData() {
|
||||
this.makeRequest(this.endpoint)
|
||||
.then((response) => {
|
||||
this.processData(response);
|
||||
if (Array.isArray(response)) {
|
||||
this.error('Got success, but found no results, possible authorization error');
|
||||
} else {
|
||||
this.processData(response);
|
||||
}
|
||||
});
|
||||
},
|
||||
/* Assign data variables to the returned data */
|
||||
|
@ -23,8 +23,12 @@ export default {
|
||||
if (!usersChoice) this.error('You must specify the hostname for your Pi-Hole server');
|
||||
return usersChoice || 'http://pi.hole';
|
||||
},
|
||||
apiKey() {
|
||||
if (!this.options.apiKey) this.error('API Key is required, please see the docs');
|
||||
return this.options.apiKey;
|
||||
},
|
||||
endpoint() {
|
||||
return `${this.hostname}/admin/api.php?overTimeData10mins`;
|
||||
return `${this.hostname}/admin/api.php?overTimeData10mins&auth=${this.apiKey}`;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
@ -38,7 +42,9 @@ export default {
|
||||
});
|
||||
},
|
||||
validate(response) {
|
||||
if (!response.ads_over_time || !response.domains_over_time) {
|
||||
if (Array.isArray(response)) {
|
||||
this.error('Got success, but found no results, possible authorization error');
|
||||
} else if (!response.ads_over_time || !response.domains_over_time) {
|
||||
this.error('Expected data was not returned from Pi-Hole');
|
||||
return false;
|
||||
} else if (response.ads_over_time.length < 1) {
|
||||
|
@ -56,6 +56,7 @@ const COMPAT = {
|
||||
'domain-monitor': 'DomainMonitor',
|
||||
'code-stats': 'CodeStats',
|
||||
'covid-stats': 'CovidStats',
|
||||
'drone-ci': 'DroneCi',
|
||||
embed: 'EmbedWidget',
|
||||
'eth-gas-prices': 'EthGasPrices',
|
||||
'exchange-rates': 'ExchangeRates',
|
||||
@ -82,6 +83,8 @@ const COMPAT = {
|
||||
image: 'ImageWidget',
|
||||
joke: 'Jokes',
|
||||
'mullvad-status': 'MullvadStatus',
|
||||
mvg: 'Mvg',
|
||||
'mvg-connection': 'MvgConnection',
|
||||
'nd-cpu-history': 'NdCpuHistory',
|
||||
'nd-load-history': 'NdLoadHistory',
|
||||
'nd-ram-history': 'NdRamHistory',
|
||||
|
@ -236,6 +236,7 @@ module.exports = {
|
||||
jokes: 'https://v2.jokeapi.dev/joke/',
|
||||
news: 'https://api.currentsapi.services/v1/latest-news',
|
||||
mullvad: 'https://am.i.mullvad.net/json',
|
||||
mvg: 'https://www.mvg.de/api/fib/v2/',
|
||||
publicIp: 'https://ipapi.co/json',
|
||||
publicIp2: 'https://api.ipgeolocation.io/ipgeo',
|
||||
publicIp3: 'http://ip-api.com/json',
|
||||
|
Loading…
Reference in New Issue
Block a user