Use templ ❤️
|
@ -1,4 +0,0 @@
|
|||
[build]
|
||||
bin = "tmp/godash"
|
||||
cmd = "go build -o tmp/godash cmd/godash/godash.go"
|
||||
exclude_dir = [".gitlab", "docker", "scripts", "web/node_modules", "web/static", "storage", "tmp"]
|
7
.gitignore
vendored
|
@ -6,7 +6,6 @@
|
|||
# Icon must end with two \r
|
||||
Icon
|
||||
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
|
@ -210,7 +209,5 @@ dist
|
|||
*.vsix
|
||||
|
||||
storage/
|
||||
tmp/
|
||||
**/style.css
|
||||
report.xml
|
||||
profile.cov
|
||||
**/*_templ.*
|
||||
assets/css/style.css
|
||||
|
|
|
@ -1,11 +1,55 @@
|
|||
stages:
|
||||
- test
|
||||
- build
|
||||
- deploy
|
||||
|
||||
include:
|
||||
- local: .gitlab/_common.gitlab-ci.yml
|
||||
- local: .gitlab/_rules.gitlab-ci.yml
|
||||
- local: /.gitlab/test.gitlab-ci.yml
|
||||
- local: /.gitlab/build.gitlab-ci.yml
|
||||
- local: /.gitlab/deploy.gitlab-ci.yml
|
||||
variables:
|
||||
LATEST_IMAGE: '$CI_REGISTRY_IMAGE:latest'
|
||||
PRODUCTION_URL: 'https://home.unjx.de'
|
||||
|
||||
image: docker:$DOCKER_VERSION-git
|
||||
|
||||
.auth_gitlab:
|
||||
before_script:
|
||||
- echo $CI_REGISTRY_PASSWORD | docker login --username $CI_REGISTRY_USER --password-stdin $CI_REGISTRY
|
||||
after_script:
|
||||
- docker logout
|
||||
|
||||
.rules:deploy:
|
||||
rules:
|
||||
- if: '$CI_PIPELINE_SOURCE = "push" && $CI_COMMIT_BRANCH = $CI_DEFAULT_BRANCH'
|
||||
|
||||
build:
|
||||
rules: !reference [.rules:deploy, rules]
|
||||
stage: build
|
||||
variables:
|
||||
DOCKER_BUILDKIT: 1
|
||||
CURRENT_IMAGE: '$CI_REGISTRY_IMAGE:$CI_COMMIT_TAG'
|
||||
before_script:
|
||||
- !reference [.auth_gitlab, before_script]
|
||||
script:
|
||||
- docker compose build godash
|
||||
- docker tag $CURRENT_IMAGE $LATEST_IMAGE
|
||||
- docker push $CURRENT_IMAGE
|
||||
- docker push $LATEST_IMAGE
|
||||
after_script:
|
||||
- !reference [.auth_gitlab, after_script]
|
||||
|
||||
deploy:
|
||||
rules: !reference [.rules:deploy, rules]
|
||||
stage: deploy
|
||||
image: debian:${DEBIAN_VERSION}-slim
|
||||
id_tokens:
|
||||
TBOT_GITLAB_JWT:
|
||||
aud: tp.unjx.de
|
||||
script:
|
||||
- apt-get update && apt-get install curl -y
|
||||
- cp tbot.yaml /tmp
|
||||
- cd /tmp
|
||||
- 'curl -O https://cdn.teleport.dev/teleport-v${TELEPORT_VERSION}-linux-amd64-bin.tar.gz'
|
||||
- tar -xvf teleport-v${TELEPORT_VERSION}-linux-amd64-bin.tar.gz
|
||||
- ./teleport/install
|
||||
- 'tbot start -c tbot.yaml'
|
||||
- 'tsh -i /tmp/machine-id/identity --proxy tp.unjx.de:443 ssh gitlab@berg "docker compose -f /opt/docker/helper/compose.yml up home -d --pull always && docker system prune --force"'
|
||||
environment:
|
||||
name: production
|
||||
url: $PRODUCTION_URL
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
variables:
|
||||
LATEST_IMAGE: '$CI_REGISTRY_IMAGE:latest'
|
||||
DOCKER_VERSION: '24.0.6'
|
||||
GOLANG_VERSION: '1.21'
|
||||
NODE_VERSION: 'lts'
|
||||
ALPINE_VERSION: '3'
|
||||
DEBIAN_VERSION: '12'
|
||||
TELEPORT_VERSION: '14.1.1'
|
||||
PRODUCTION_URL: 'https://home.unjx.de'
|
||||
|
||||
image: docker:$DOCKER_VERSION-git
|
||||
|
||||
.login_registry:
|
||||
before_script:
|
||||
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
|
||||
|
||||
.go-cache:
|
||||
variables:
|
||||
GOPATH: $CI_PROJECT_DIR/.go
|
||||
before_script:
|
||||
- mkdir -p .go
|
||||
- export PATH=$PATH:$GOROOT/bin:$GOPATH/bin
|
||||
cache:
|
||||
paths:
|
||||
- .go/pkg/mod/
|
|
@ -1,17 +0,0 @@
|
|||
.if-release-candidate-tag: &if-release-candidate-tag
|
||||
if: '$CI_COMMIT_TAG =~ /^v[0-9]+\.[0-9]+\.[0-9]+-rc[0-9]+/'
|
||||
|
||||
.if-stable-release-tag: &if-stable-release-tag
|
||||
if: '$CI_COMMIT_TAG =~ /^v[0-9]+\.[0-9]+\.[0-9]+$/'
|
||||
|
||||
.if-default-branch: &if-default-branch
|
||||
if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
||||
|
||||
.rules:release:
|
||||
rules:
|
||||
- <<: *if-release-candidate-tag
|
||||
- <<: *if-stable-release-tag
|
||||
|
||||
.rules:default:
|
||||
rules:
|
||||
- <<: *if-default-branch
|
|
@ -1,24 +0,0 @@
|
|||
build:
|
||||
rules: !reference [.rules:release, rules]
|
||||
stage: build
|
||||
extends: .login_registry
|
||||
services:
|
||||
- name: docker:$DOCKER_VERSION-dind
|
||||
alias: docker
|
||||
variables:
|
||||
DOCKER_TLS_CERTDIR: ''
|
||||
CURRENT_IMAGE: '$CI_REGISTRY_IMAGE:$CI_COMMIT_TAG'
|
||||
script:
|
||||
- >
|
||||
docker build .
|
||||
--file docker/Dockerfile
|
||||
--build-arg GOLANG_VERSION=$GOLANG_VERSION
|
||||
--build-arg NODE_VERSION=$NODE_VERSION
|
||||
--build-arg ALPINE_VERSION=$ALPINE_VERSION
|
||||
--build-arg APP_VERSION=$CI_COMMIT_TAG
|
||||
--build-arg BUILD_TIME=$CI_JOB_STARTED_AT
|
||||
--tag $CURRENT_IMAGE
|
||||
--tag $LATEST_IMAGE
|
||||
- docker inspect $CURRENT_IMAGE
|
||||
- docker push $CURRENT_IMAGE
|
||||
- docker push $LATEST_IMAGE
|
|
@ -1,19 +0,0 @@
|
|||
deploy:
|
||||
rules: !reference [.rules:release, rules]
|
||||
stage: deploy
|
||||
image: debian:${DEBIAN_VERSION}-slim
|
||||
id_tokens:
|
||||
TBOT_GITLAB_JWT:
|
||||
aud: tp.unjx.de
|
||||
script:
|
||||
- apt-get update && apt-get install curl -y
|
||||
- cd /tmp
|
||||
- 'curl -O https://cdn.teleport.dev/teleport-v${TELEPORT_VERSION}-linux-amd64-bin.tar.gz'
|
||||
- tar -xvf teleport-v${TELEPORT_VERSION}-linux-amd64-bin.tar.gz
|
||||
- ./teleport/install
|
||||
- 'tbot start --token=gitlab --destination-dir=/tmp/tbot-user --data-dir=/tmp/tbot-data --auth-server=tp.unjx.de:443 --join-method=gitlab --oneshot'
|
||||
- 'tsh -i /tmp/tbot-user/identity --proxy tp.unjx.de:443 ssh gitlab@berg "docker compose -f /opt/docker/helper/compose.yml up home -d --pull always"'
|
||||
- 'tsh -i /tmp/tbot-user/identity --proxy tp.unjx.de:443 ssh gitlab@berg "docker system prune --force"'
|
||||
environment:
|
||||
name: production
|
||||
url: $PRODUCTION_URL
|
|
@ -1,15 +0,0 @@
|
|||
unit_tests:
|
||||
rules: !reference [.rules:default, rules]
|
||||
stage: test
|
||||
image: golang:$GOLANG_VERSION-alpine
|
||||
extends:
|
||||
- .go-cache
|
||||
script:
|
||||
- go install gotest.tools/gotestsum@latest
|
||||
- gotestsum --junitfile report.xml --format testname -- ./... -coverprofile=profile.cov
|
||||
- go tool cover -func profile.cov
|
||||
coverage: '/\(statements\)(?:\s+)?(\d+(?:\.\d+)?%)/'
|
||||
artifacts:
|
||||
when: always
|
||||
reports:
|
||||
junit: report.xml
|
51
Dockerfile
Normal file
|
@ -0,0 +1,51 @@
|
|||
ARG GOLANG_VERSION
|
||||
ARG NODE_VERSION
|
||||
ARG ALPINE_VERSION
|
||||
FROM golang:${GOLANG_VERSION}-alpine AS goBuilder
|
||||
WORKDIR /app
|
||||
|
||||
RUN go install github.com/a-h/templ/cmd/templ@latest
|
||||
|
||||
COPY ./go.mod .
|
||||
COPY ./go.sum .
|
||||
RUN go mod download
|
||||
|
||||
COPY . .
|
||||
RUN templ generate
|
||||
RUN go build -ldflags="-s -w" -o godash main.go
|
||||
|
||||
FROM node:${NODE_VERSION}-alpine AS nodeBuilder
|
||||
WORKDIR /app
|
||||
|
||||
COPY package.json yarn.lock ./
|
||||
RUN yarn install --frozen-lockfile --network-timeout 30000
|
||||
|
||||
COPY assets/css ./assets/css
|
||||
COPY components ./components
|
||||
COPY views ./views
|
||||
COPY tailwind.config.js .
|
||||
RUN yarn run tw:build
|
||||
|
||||
FROM alpine:${ALPINE_VERSION} AS logo
|
||||
WORKDIR /app
|
||||
RUN apk add figlet
|
||||
RUN figlet GoDash > logo.txt
|
||||
|
||||
FROM alpine:${ALPINE_VERSION} AS final
|
||||
WORKDIR /app
|
||||
|
||||
RUN apk add tzdata
|
||||
|
||||
COPY scripts/entrypoint.sh .
|
||||
|
||||
COPY --from=logo /app/logo.txt .
|
||||
COPY --from=nodeBuilder /app/assets/css/style.css ./assets/css/style.css
|
||||
COPY --from=goBuilder /app/views ./views
|
||||
COPY --from=goBuilder /app/components ./components
|
||||
COPY --from=goBuilder /app/godash .
|
||||
|
||||
ARG APP_VERSION
|
||||
ENV APP_VERSION=$APP_VERSION
|
||||
|
||||
ENTRYPOINT ["/app/entrypoint.sh"]
|
||||
|
126
README.md
|
@ -1,126 +0,0 @@
|
|||
# GoDash
|
||||
|
||||
A blazing fast start-page for your services written in Go.
|
||||
|
||||
![](https://img.shields.io/badge/Language-Go-informational?style=for-the-badge&logo=go&color=00ADD8)
|
||||
![](https://img.shields.io/badge/Framework-TailwindCSS-informational?style=for-the-badge&logo=tailwind-css&color=06B6D4)
|
||||
|
||||
## How to use
|
||||
|
||||
Use the docker-compose to spin up the service.
|
||||
The Weather is fetched over a [Current Weather Api Call](https://openweathermap.org/current) with environment variables for the needed parameters.
|
||||
If you don't want to see the weather, do not provide a key as environment variable.
|
||||
Please refer to the available options as shown in the docker-compose example.
|
||||
|
||||
### Example of the config.yaml
|
||||
|
||||
All Bookmarks are read from a file called `config.yaml` located inside the `./storage` folder.
|
||||
The application will create a default file at startup and will automatically look for changes inside the file.
|
||||
Changes are printed in stdout when running with `LOG_LEVEL=trace`.
|
||||
|
||||
You can specify an icon of a bookmark either by using a link or by using the name of the file located inside the `./storage/icons` folder that is mounted via the docker compose file.
|
||||
The name and related link can be provided as well.
|
||||
|
||||
**config.yaml example:**
|
||||
|
||||
```yaml
|
||||
links:
|
||||
- category: "Code"
|
||||
entries:
|
||||
- name: "Github"
|
||||
url: "https://github.com"
|
||||
- category: "CI/CD"
|
||||
entries:
|
||||
- name: "Jenkins"
|
||||
url: "https://www.jenkins.io/"
|
||||
- category: "Server"
|
||||
entries:
|
||||
- name: "bwCloud"
|
||||
url: "https://portal.bw-cloud.org"
|
||||
|
||||
applications:
|
||||
- category: "Code"
|
||||
entries:
|
||||
- name: "Github"
|
||||
icon: "https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png"
|
||||
url: "https://github.com"
|
||||
- category: ""
|
||||
entries:
|
||||
- name: "Jenkins"
|
||||
icon: "https://www.jenkins.io/images/logos/jenkins/Jenkins-stop-the-war.svg"
|
||||
url: "https://www.jenkins.io/"
|
||||
- category: "Server"
|
||||
entries:
|
||||
- name: "bwCloud"
|
||||
icon: "https://portal.bw-cloud.org/static/dashboard/img/logo-splash.svg"
|
||||
url: "https://portal.bw-cloud.org"
|
||||
```
|
||||
|
||||
### Available environment variables with default values
|
||||
|
||||
```toml
|
||||
PORT = 4000
|
||||
ALLOWED_HOSTS = "*"
|
||||
TITLE = "GoDash"
|
||||
|
||||
LOG_LEVEL = "info"
|
||||
|
||||
LOCATION_LATITUDE = 48.780331609463815
|
||||
LOCATION_LONGITUDE = 9.177968320179422
|
||||
WEATHER_KEY = ""
|
||||
WEATHER_UNITS = "metric"
|
||||
WEATHER_LANG = "en"
|
||||
WEATHER_DIGITS = true
|
||||
|
||||
LIVE_SYSTEM = true
|
||||
```
|
||||
|
||||
## Heartbeat
|
||||
|
||||
`/health`
|
||||
|
||||
Heartbeat endpoint can be useful to setting up a load balancers or an external uptime testing service that can make a request before hitting any routes.
|
||||
|
||||
## A docker-compose example:
|
||||
|
||||
```yaml
|
||||
version: "3.9"
|
||||
|
||||
services:
|
||||
godash:
|
||||
image: unjxde/godash:latest
|
||||
container_name: godash
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
# https://docs.linuxserver.io/general/understanding-puid-and-pgid
|
||||
- PUID=1000
|
||||
- PGID=1000
|
||||
- TZ=Europe/Berlin
|
||||
# allowed hosts for cors, seperated by comma
|
||||
- ALLOWED_HOSTS=https://home.example.com,https://another.example.com
|
||||
# change title to something else
|
||||
- TITLE=GoDash
|
||||
# available log-levels: debug,info,warn,error,panic,fatal
|
||||
- LOG_LEVEL=info
|
||||
# create account here to get free key:
|
||||
# https://home.openweathermap.org/users/sign_up
|
||||
# remove to disable weather
|
||||
- WEATHER_KEY=thisIsNoFunctioningKey
|
||||
# standard, metric or imperial
|
||||
- WEATHER_UNITS=metric
|
||||
# https://openweathermap.org/current#multi
|
||||
- WEATHER_LANG=en
|
||||
# Temp is normally xx.xx, can be rounded to xx if desired
|
||||
- WEATHER_DIGITS=true
|
||||
# location is needed for weather
|
||||
- LOCATION_LATITUDE=48.644929601442485
|
||||
- LOCATION_LONGITUDE=9.349618464869025
|
||||
# show live system information
|
||||
- LIVE_SYSTEM=true
|
||||
volumes:
|
||||
# to mount the config.yaml and the icons folder on the system
|
||||
- ./storage:/app/storage
|
||||
# https://docs.docker.com/compose/compose-file/compose-file-v3/#ports
|
||||
ports:
|
||||
- "4000:4000"
|
||||
```
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 589 B After Width: | Height: | Size: 589 B |
Before Width: | Height: | Size: 786 B After Width: | Height: | Size: 786 B |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
@ -1,32 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"gitlab.unjx.de/flohoss/godash/internal/controller"
|
||||
"gitlab.unjx.de/flohoss/godash/internal/env"
|
||||
"gitlab.unjx.de/flohoss/godash/internal/logger"
|
||||
"gitlab.unjx.de/flohoss/godash/internal/router"
|
||||
)
|
||||
|
||||
func main() {
|
||||
env, err := env.Parse()
|
||||
if err != nil {
|
||||
slog.Error("cannot parse environment variables", "err", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
slog.SetDefault(logger.NewLogger(env.LogLevel))
|
||||
|
||||
r := router.InitRouter()
|
||||
c := controller.NewController(env)
|
||||
router.SetupRoutes(r, c)
|
||||
|
||||
slog.Info("starting server", "url", fmt.Sprintf("http://localhost:%d", env.Port))
|
||||
if err := r.Start(fmt.Sprintf(":%d", env.Port)); err != http.ErrServerClosed {
|
||||
slog.Error("cannot start server", "err", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
12
components/application.templ
Normal file
|
@ -0,0 +1,12 @@
|
|||
package components
|
||||
|
||||
import (
|
||||
"gitlab.unjx.de/flohoss/godash/services"
|
||||
)
|
||||
|
||||
templ Application(application services.Application) {
|
||||
<a href={ templ.URL(application.URL) } class="flex items-center hover-effect">
|
||||
<img class={ "rounded w-8 h-8 opacity-90", templ.KV("backgroundColor",application.Background !="") } src={ application.Icon }/>
|
||||
<div class="uppercase truncate ml-2">{ application.Name }</div>
|
||||
</a>
|
||||
}
|
11
components/link.templ
Normal file
|
@ -0,0 +1,11 @@
|
|||
package components
|
||||
|
||||
import (
|
||||
"gitlab.unjx.de/flohoss/godash/services"
|
||||
)
|
||||
|
||||
templ Link(link services.Link) {
|
||||
<a href={ templ.URL(link.URL) } class="hover-effect">
|
||||
<div class="uppercase truncate">{ link.Name }</div>
|
||||
</a>
|
||||
}
|
23
components/system.templ
Normal file
|
@ -0,0 +1,23 @@
|
|||
package components
|
||||
|
||||
import "html/template"
|
||||
|
||||
var barTemplate = template.Must(template.New("bar").Parse("<div id=\"{{ .Id }}\" class=\"progress-bar\" style=\"width: {{ .Percentage }}%\"></div>"))
|
||||
|
||||
type Bar struct {
|
||||
Id string
|
||||
Percentage float64
|
||||
}
|
||||
|
||||
templ System(icon string, infoPre string, infoPost string, extraInfo string, percentageId string, valueId string, percentage float64) {
|
||||
<div class="flex items-center">
|
||||
<span class={ "system-icon", icon }></span>
|
||||
<div class="w-full truncate">
|
||||
<div class="extra-info">{ extraInfo }</div>
|
||||
<div class="truncate"><span id={ valueId }>{ infoPre }</span>{ infoPost }</div>
|
||||
<div class="progress-bar-wrapper">
|
||||
@templ.FromGoHTML(barTemplate, Bar{Id:percentageId, Percentage:percentage})
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
38
components/uptime.templ
Normal file
|
@ -0,0 +1,38 @@
|
|||
package components
|
||||
|
||||
import "gitlab.unjx.de/flohoss/godash/services"
|
||||
import "fmt"
|
||||
import "html/template"
|
||||
|
||||
var countDownTemplate = template.Must(template.New("countdown").Parse("<span id=\"{{ .Id }}\" style=\"--value: {{ .Value }};\"></span>"))
|
||||
|
||||
type Countdown struct {
|
||||
Id string
|
||||
Value uint16
|
||||
}
|
||||
|
||||
templ Uptime(extraInfo string, id string, uptime services.Uptime) {
|
||||
<div class="flex items-center">
|
||||
<span class="system-icon icon-[bi--motherboard]"></span>
|
||||
<div class="w-full truncate">
|
||||
<div class="extra-info">{ extraInfo }</div>
|
||||
<div class="flex items-center gap-2 truncate">
|
||||
<div class="truncate">
|
||||
<span><span id="uptimeDays">{ fmt.Sprintf("%d",uptime.Days) }</span> days</span>
|
||||
<span class="countdown">
|
||||
@templ.FromGoHTML(countDownTemplate, Countdown{Id:"uptimeHours", Value:uptime.Hours})
|
||||
</span> hours
|
||||
<span class="countdown">
|
||||
@templ.FromGoHTML(countDownTemplate, Countdown{Id:"uptimeMinutes", Value:uptime.Minutes})
|
||||
</span> min
|
||||
<span class="countdown">
|
||||
@templ.FromGoHTML(countDownTemplate, Countdown{Id:"uptimeSeconds", Value:uptime.Seconds})
|
||||
</span> sec
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-bar-wrapper">
|
||||
@templ.FromGoHTML(barTemplate, Bar{Id:id, Percentage:float64(uptime.Percentage)})
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
48
compose.yml
|
@ -1,13 +1,14 @@
|
|||
services:
|
||||
godash:
|
||||
profiles: [build]
|
||||
image: ${CURRENT_IMAGE}
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ./docker/Dockerfile
|
||||
dockerfile: Dockerfile
|
||||
args:
|
||||
- GOLANG_VERSION=${GOLANG_VERSION}
|
||||
- NODE_VERSION=${NODE_VERSION}
|
||||
- ALPINE_VERSION=${ALPINE_VERSION}
|
||||
- APP_VERSION=${CI_COMMIT_TAG}
|
||||
|
||||
backend:
|
||||
build:
|
||||
|
@ -15,16 +16,16 @@ services:
|
|||
dockerfile_inline: |
|
||||
ARG GOLANG_VERSION
|
||||
FROM golang:${GOLANG_VERSION}-alpine
|
||||
RUN apk update
|
||||
RUN apk upgrade
|
||||
RUN apk add tzdata
|
||||
RUN apk update && \
|
||||
apk upgrade && \
|
||||
apk add tzdata
|
||||
|
||||
RUN go install github.com/cosmtrek/air@latest
|
||||
COPY ./.air.toml .
|
||||
COPY scripts/.air.toml .
|
||||
|
||||
WORKDIR /app
|
||||
COPY ./go.mod .
|
||||
COPY ./go.sum .
|
||||
COPY go.mod .
|
||||
COPY go.sum .
|
||||
RUN go mod download
|
||||
args:
|
||||
- GOLANG_VERSION=${GOLANG_VERSION}
|
||||
|
@ -34,32 +35,45 @@ services:
|
|||
- LOG_LEVEL=debug
|
||||
- TITLE=DEV
|
||||
- APP_VERSION=v0.0.1-dev
|
||||
- BUILD_TIME=2023-04-05T20:48:07Z
|
||||
volumes:
|
||||
- .:/app/
|
||||
ports:
|
||||
- 4000:4000
|
||||
- 2345:2345
|
||||
|
||||
templ:
|
||||
build:
|
||||
context: .
|
||||
dockerfile_inline: |
|
||||
ARG GOLANG_VERSION
|
||||
FROM golang:${GOLANG_VERSION}-alpine
|
||||
|
||||
RUN go install github.com/a-h/templ/cmd/templ@latest
|
||||
args:
|
||||
- GOLANG_VERSION=${GOLANG_VERSION}
|
||||
working_dir: /app
|
||||
command: templ generate --watch
|
||||
volumes:
|
||||
- .:/app/
|
||||
|
||||
frontend:
|
||||
tailwind:
|
||||
image: node:${NODE_VERSION}-alpine
|
||||
working_dir: /app/web
|
||||
command: yarn run tailwind:dev
|
||||
working_dir: /app
|
||||
command: yarn tw:dev
|
||||
tty: true
|
||||
volumes:
|
||||
- .:/app/
|
||||
|
||||
go:
|
||||
golang:
|
||||
profiles: [install]
|
||||
image: golang:${GOLANG_VERSION}-alpine
|
||||
working_dir: /app
|
||||
entrypoint: go
|
||||
volumes:
|
||||
- .:/app/
|
||||
|
||||
yarn:
|
||||
node:
|
||||
profiles: [install]
|
||||
image: node:${NODE_VERSION}-alpine
|
||||
working_dir: /app/web
|
||||
entrypoint: yarn
|
||||
working_dir: /app
|
||||
volumes:
|
||||
- .:/app/
|
||||
|
|
|
@ -1,45 +0,0 @@
|
|||
ARG GOLANG_VERSION
|
||||
ARG NODE_VERSION
|
||||
ARG ALPINE_VERSION
|
||||
FROM golang:${GOLANG_VERSION}-alpine AS goBuilder
|
||||
WORKDIR /app
|
||||
|
||||
COPY ./go.mod .
|
||||
COPY ./go.sum .
|
||||
RUN go mod download
|
||||
|
||||
COPY . .
|
||||
RUN go build -ldflags="-s -w" cmd/godash/godash.go
|
||||
|
||||
FROM node:${NODE_VERSION}-alpine AS nodeBuilder
|
||||
WORKDIR /web
|
||||
|
||||
COPY ./internal/router/templates.go /internal/router/templates.go
|
||||
COPY ./web .
|
||||
RUN yarn install --frozen-lockfile
|
||||
RUN yarn run tailwind:build
|
||||
|
||||
FROM alpine:${ALPINE_VERSION} AS logo
|
||||
RUN apk add figlet
|
||||
RUN figlet GoDash > logo.txt
|
||||
|
||||
FROM alpine:${ALPINE_VERSION} AS final
|
||||
RUN apk add tzdata
|
||||
|
||||
# GoDash
|
||||
WORKDIR /app
|
||||
COPY scripts/entrypoint.sh .
|
||||
|
||||
COPY --from=logo /logo.txt .
|
||||
COPY --from=nodeBuilder /web/static/ ./web/static/
|
||||
COPY --from=nodeBuilder /web/templates ./web/templates/
|
||||
COPY --from=goBuilder /app/internal/bookmarks/config.yaml .internal/bookmarks/config.yaml
|
||||
COPY --from=goBuilder /app/godash .
|
||||
|
||||
# Envs
|
||||
ARG APP_VERSION
|
||||
ENV APP_VERSION=$APP_VERSION
|
||||
ARG BUILD_TIME
|
||||
ENV BUILD_TIME=$BUILD_TIME
|
||||
|
||||
ENTRYPOINT ["/app/entrypoint.sh"]
|
48
go.mod
|
@ -1,55 +1,37 @@
|
|||
module gitlab.unjx.de/flohoss/godash
|
||||
|
||||
go 1.21
|
||||
go 1.22.0
|
||||
|
||||
require (
|
||||
github.com/Masterminds/sprig/v3 v3.2.3
|
||||
github.com/caarlos0/env/v8 v8.0.0
|
||||
github.com/a-h/templ v0.2.598
|
||||
github.com/caarlos0/env/v10 v10.0.0
|
||||
github.com/dariubs/percent v1.0.0
|
||||
github.com/fsnotify/fsnotify v1.7.0
|
||||
github.com/go-playground/validator/v10 v10.15.5
|
||||
github.com/labstack/echo/v4 v4.11.2
|
||||
github.com/lmittmann/tint v1.0.2
|
||||
github.com/go-playground/validator/v10 v10.19.0
|
||||
github.com/labstack/echo/v4 v4.11.4
|
||||
github.com/r3labs/sse/v2 v2.10.0
|
||||
github.com/shirou/gopsutil/v3 v3.23.9
|
||||
github.com/stretchr/testify v1.8.4
|
||||
github.com/unjx-de/go-folder v1.0.7
|
||||
github.com/shirou/gopsutil v3.21.11+incompatible
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.2.1 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
|
||||
github.com/go-ole/go-ole v1.3.0 // indirect
|
||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
|
||||
github.com/google/uuid v1.3.1 // indirect
|
||||
github.com/huandu/xstrings v1.4.0 // indirect
|
||||
github.com/imdario/mergo v0.3.16 // indirect
|
||||
github.com/labstack/gommon v0.4.0 // indirect
|
||||
github.com/leodido/go-urn v1.2.4 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20231016141302-07b5767bb0ed // indirect
|
||||
github.com/labstack/gommon v0.4.2 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect
|
||||
github.com/shoenig/go-m1cpu v0.1.6 // indirect
|
||||
github.com/shopspring/decimal v1.3.1 // indirect
|
||||
github.com/spf13/cast v1.5.1 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.12 // indirect
|
||||
github.com/tklauser/numcpus v0.6.1 // indirect
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
github.com/valyala/fasttemplate v1.2.2 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.3 // indirect
|
||||
golang.org/x/crypto v0.14.0 // indirect
|
||||
golang.org/x/net v0.17.0 // indirect
|
||||
golang.org/x/sys v0.13.0 // indirect
|
||||
golang.org/x/text v0.13.0 // indirect
|
||||
golang.org/x/time v0.3.0 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
||||
golang.org/x/crypto v0.19.0 // indirect
|
||||
golang.org/x/net v0.21.0 // indirect
|
||||
golang.org/x/sys v0.17.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/time v0.5.0 // indirect
|
||||
gopkg.in/cenkalti/backoff.v1 v1.1.0 // indirect
|
||||
)
|
||||
|
|
152
go.sum
|
@ -1,180 +1,82 @@
|
|||
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
|
||||
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
|
||||
github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
|
||||
github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0=
|
||||
github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
|
||||
github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA=
|
||||
github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM=
|
||||
github.com/caarlos0/env/v8 v8.0.0 h1:POhxHhSpuxrLMIdvTGARuZqR4Jjm8AYmoi/JKlcScs0=
|
||||
github.com/caarlos0/env/v8 v8.0.0/go.mod h1:7K4wMY9bH0esiXSSHlfHLX5xKGQMnkH5Fk4TDSSSzfo=
|
||||
github.com/a-h/templ v0.2.598 h1:6jMIHv6wQZvdPxTuv87erW4RqN/FPU0wk7ZHN5wVuuo=
|
||||
github.com/a-h/templ v0.2.598/go.mod h1:SA7mtYwVEajbIXFRh3vKdYm/4FYyLQAtPH1+KxzGPA8=
|
||||
github.com/caarlos0/env/v10 v10.0.0 h1:yIHUBZGsyqCnpTkbjk8asUlx6RFhhEs+h7TOBdgdzXA=
|
||||
github.com/caarlos0/env/v10 v10.0.0/go.mod h1:ZfulV76NvVPw3tm591U4SwL3Xx9ldzBP9aGxzeN7G18=
|
||||
github.com/dariubs/percent v1.0.0 h1:fY8q40FRYaCiFZ0gTOa73Cmp21hS32w+tSSmqbGnUzc=
|
||||
github.com/dariubs/percent v1.0.0/go.mod h1:NDZpkezJ8QqyIW/510MywB5T2KdC8v/0oTlEoPcMsRM=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
|
||||
github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
|
||||
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
|
||||
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
|
||||
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
|
||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||
github.com/go-playground/validator/v10 v10.15.5 h1:LEBecTWb/1j5TNY1YYG2RcOUN3R7NLylN+x8TTueE24=
|
||||
github.com/go-playground/validator/v10 v10.15.5/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
|
||||
github.com/go-playground/validator/v10 v10.19.0 h1:ol+5Fu+cSq9JD7SoSqe04GMI92cbn0+wvQ3bZ8b/AU4=
|
||||
github.com/go-playground/validator/v10 v10.19.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
|
||||
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
||||
github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU=
|
||||
github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
||||
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||
github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
|
||||
github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/labstack/echo/v4 v4.11.2 h1:T+cTLQxWCDfqDEoydYm5kCobjmHwOwcv4OJAPHilmdE=
|
||||
github.com/labstack/echo/v4 v4.11.2/go.mod h1:UcGuQ8V6ZNRmSweBIJkPvGfwCMIlFmiqrPqiEBfPYws=
|
||||
github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8=
|
||||
github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
|
||||
github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
|
||||
github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
|
||||
github.com/lmittmann/tint v1.0.2 h1:9XZ+JvEzjvd3VNVugYqo3j+dl0NRju8k9FquAusJExM=
|
||||
github.com/lmittmann/tint v1.0.2/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
|
||||
github.com/lufia/plan9stats v0.0.0-20231016141302-07b5767bb0ed h1:036IscGBfJsFIgJQzlui7nK1Ncm0tp2ktmPj8xO4N/0=
|
||||
github.com/lufia/plan9stats v0.0.0-20231016141302-07b5767bb0ed/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k=
|
||||
github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||
github.com/labstack/echo/v4 v4.11.4 h1:vDZmA+qNeh1pd/cCkEicDMrjtrnMGQ1QFI9gWN1zGq8=
|
||||
github.com/labstack/echo/v4 v4.11.4/go.mod h1:noh7EvLwqDsmh/X/HWKPUl1AjzJrhyptRyEbQJfxen8=
|
||||
github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
|
||||
github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU=
|
||||
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
|
||||
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
|
||||
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
|
||||
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
|
||||
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b h1:0LFwY6Q3gMACTjAbMZBjXAqTOzOwFaj2Ld6cjeQ7Rig=
|
||||
github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/r3labs/sse/v2 v2.10.0 h1:hFEkLLFY4LDifoHdiCN/LlGBAdVJYsANaLqNYa1l/v0=
|
||||
github.com/r3labs/sse/v2 v2.10.0/go.mod h1:Igau6Whc+F17QUgML1fYe1VPZzTV6EMCnYktEmkNJ7I=
|
||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/shirou/gopsutil/v3 v3.23.9 h1:ZI5bWVeu2ep4/DIxB4U9okeYJ7zp/QLTO4auRb/ty/E=
|
||||
github.com/shirou/gopsutil/v3 v3.23.9/go.mod h1:x/NWSb71eMcjFIO0vhyGW5nZ7oSIgVjrCnADckb85GA=
|
||||
github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
|
||||
github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
|
||||
github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
|
||||
github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
|
||||
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||
github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
|
||||
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA=
|
||||
github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48=
|
||||
github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
|
||||
github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
|
||||
github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
|
||||
github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
|
||||
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
|
||||
github.com/unjx-de/go-folder v1.0.7 h1:OVKvqjcVB0ASidVshYndRtkmlqS1h6MIhSr0vqX3Q6A=
|
||||
github.com/unjx-de/go-folder v1.0.7/go.mod h1:sbcRrRgLE49QI6CZqGBMdneRuNOOhoRU1gx9DYlyD2g=
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
|
||||
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw=
|
||||
github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
|
||||
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
|
||||
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/net v0.0.0-20191116160921-f9c825593386/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
|
||||
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
||||
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
gopkg.in/cenkalti/backoff.v1 v1.1.0 h1:Arh75ttbsvlpVA7WtVpH4u9h6Zl46xuptxqLxPiSo4Y=
|
||||
gopkg.in/cenkalti/backoff.v1 v1.1.0/go.mod h1:J6Vskwqd+OMVJl8C33mmtxTBs2gyzfv7UDAkHu8BrjI=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
|
42
handlers/app.handlers.go
Normal file
|
@ -0,0 +1,42 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"github.com/labstack/echo/v4"
|
||||
"gitlab.unjx.de/flohoss/godash/internal/env"
|
||||
"gitlab.unjx.de/flohoss/godash/services"
|
||||
"gitlab.unjx.de/flohoss/godash/views/home"
|
||||
)
|
||||
|
||||
type BookmarkService interface {
|
||||
GetAllBookmarks() *services.Bookmarks
|
||||
}
|
||||
|
||||
type SystemService interface {
|
||||
GetLiveInformation() *services.LiveInformation
|
||||
GetStaticInformation() *services.StaticInformation
|
||||
}
|
||||
|
||||
func NewAppHandler(env *env.Config, s SystemService, b BookmarkService) *AppHandler {
|
||||
|
||||
return &AppHandler{
|
||||
env: env,
|
||||
SystemService: s,
|
||||
BookmarkService: b,
|
||||
}
|
||||
}
|
||||
|
||||
type AppHandler struct {
|
||||
env *env.Config
|
||||
SystemService SystemService
|
||||
BookmarkService BookmarkService
|
||||
}
|
||||
|
||||
func (bh *AppHandler) appHandler(c echo.Context) error {
|
||||
bookmarks := bh.BookmarkService.GetAllBookmarks()
|
||||
staticSystem := bh.SystemService.GetStaticInformation()
|
||||
liveSystem := bh.SystemService.GetLiveInformation()
|
||||
|
||||
titlePage := bh.env.Title
|
||||
|
||||
return renderView(c, home.HomeIndex(titlePage, bh.env.Version, bookmarks, staticSystem, liveSystem, home.Home(titlePage, bookmarks, staticSystem, liveSystem)))
|
||||
}
|
20
handlers/routes.go
Normal file
|
@ -0,0 +1,20 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/a-h/templ"
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/r3labs/sse/v2"
|
||||
)
|
||||
|
||||
func SetupRoutes(e *echo.Echo, sse *sse.Server, bh *AppHandler) {
|
||||
e.GET("/", bh.appHandler)
|
||||
e.GET("/sse", echo.WrapHandler(http.HandlerFunc(sse.ServeHTTP)))
|
||||
}
|
||||
|
||||
func renderView(c echo.Context, cmp templ.Component) error {
|
||||
c.Response().Header().Set(echo.HeaderContentType, echo.MIMETextHTML)
|
||||
|
||||
return cmp.Render(c.Request().Context(), c.Response().Writer)
|
||||
}
|
|
@ -1,121 +0,0 @@
|
|||
package bookmarks
|
||||
|
||||
import (
|
||||
"io"
|
||||
"log/slog"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/fsnotify/fsnotify"
|
||||
folderCreate "github.com/unjx-de/go-folder"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
const StorageDir = "storage/"
|
||||
const IconsDir = StorageDir + "icons/"
|
||||
const bookmarksFolder = "internal/bookmarks/"
|
||||
const configFile = "config.yaml"
|
||||
|
||||
func NewBookmarkService() *Config {
|
||||
c := Config{}
|
||||
c.createFolderStructure()
|
||||
c.copyDefaultConfigIfNotExisting()
|
||||
c.parseBookmarks()
|
||||
go c.watchBookmarks()
|
||||
return &c
|
||||
}
|
||||
|
||||
func (c *Config) createFolderStructure() {
|
||||
folders := []string{StorageDir, IconsDir}
|
||||
err := folderCreate.CreateFolders(folders, 0755)
|
||||
if err != nil {
|
||||
slog.Error("cannot create folder", "err", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
slog.Debug("folders created", "folders", folders)
|
||||
}
|
||||
|
||||
func (c *Config) copyDefaultConfigIfNotExisting() {
|
||||
_, err := os.Open(StorageDir + configFile)
|
||||
if err != nil {
|
||||
slog.Debug(configFile + " not existing, creating...")
|
||||
source, _ := os.Open(bookmarksFolder + configFile)
|
||||
defer source.Close()
|
||||
destination, err := os.Create(StorageDir + configFile)
|
||||
if err != nil {
|
||||
slog.Error(err.Error())
|
||||
return
|
||||
}
|
||||
defer destination.Close()
|
||||
_, err = io.Copy(destination, source)
|
||||
if err != nil {
|
||||
slog.Error(err.Error())
|
||||
return
|
||||
}
|
||||
slog.Debug(configFile + " created")
|
||||
} else {
|
||||
slog.Debug(configFile + " existing, skipping creation")
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Config) readBookmarksFile() []byte {
|
||||
file, err := os.Open(StorageDir + configFile)
|
||||
if err != nil {
|
||||
slog.Error(err.Error())
|
||||
return nil
|
||||
}
|
||||
defer file.Close()
|
||||
byteValue, err := io.ReadAll(file)
|
||||
if err != nil {
|
||||
slog.Error(err.Error())
|
||||
return nil
|
||||
}
|
||||
return byteValue
|
||||
}
|
||||
|
||||
func (c *Config) replaceIconString() {
|
||||
for _, v := range c.Parsed.Applications {
|
||||
for i, bookmark := range v.Entries {
|
||||
if !strings.Contains(bookmark.Icon, "http") {
|
||||
v.Entries[i].Icon = "/" + IconsDir + bookmark.Icon
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Config) parseBookmarks() {
|
||||
byteValue := c.readBookmarksFile()
|
||||
err := yaml.Unmarshal(byteValue, &c.Parsed)
|
||||
if err != nil {
|
||||
slog.Error(err.Error())
|
||||
return
|
||||
}
|
||||
c.replaceIconString()
|
||||
}
|
||||
|
||||
func (c *Config) watchBookmarks() {
|
||||
watcher, err := fsnotify.NewWatcher()
|
||||
if err != nil {
|
||||
slog.Error(err.Error())
|
||||
}
|
||||
defer watcher.Close()
|
||||
done := make(chan bool)
|
||||
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-watcher.Events:
|
||||
c.parseBookmarks()
|
||||
slog.Debug("bookmarks changed", "applications", len(c.Parsed.Applications), "links", len(c.Parsed.Links))
|
||||
case err := <-watcher.Errors:
|
||||
slog.Error(err.Error())
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
if err := watcher.Add(StorageDir + configFile); err != nil {
|
||||
slog.Error("cannot add watcher")
|
||||
os.Exit(1)
|
||||
}
|
||||
<-done
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
links:
|
||||
- category: "Code"
|
||||
entries:
|
||||
- name: "Github"
|
||||
url: "https://github.com"
|
||||
- category: "CI/CD"
|
||||
entries:
|
||||
- name: "Jenkins"
|
||||
url: "https://www.jenkins.io/"
|
||||
- category: "Server"
|
||||
entries:
|
||||
- name: "bwCloud"
|
||||
url: "https://portal.bw-cloud.org"
|
||||
|
||||
applications:
|
||||
- category: "Code"
|
||||
entries:
|
||||
- name: "Github"
|
||||
icon: "https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png"
|
||||
url: "https://github.com"
|
||||
- category: ""
|
||||
entries:
|
||||
- name: "Jenkins"
|
||||
icon: "https://www.jenkins.io/images/logos/jenkins/Jenkins-stop-the-war.svg"
|
||||
url: "https://www.jenkins.io/"
|
||||
- category: "Server"
|
||||
entries:
|
||||
- name: "bwCloud"
|
||||
icon: "https://portal.bw-cloud.org/static/dashboard/img/logo-splash.svg"
|
||||
url: "https://portal.bw-cloud.org"
|
|
@ -1,22 +0,0 @@
|
|||
package bookmarks
|
||||
|
||||
type Config struct {
|
||||
Parsed struct {
|
||||
Links []struct {
|
||||
Category string
|
||||
Entries []struct {
|
||||
Name string
|
||||
URL string
|
||||
}
|
||||
}
|
||||
Applications []struct {
|
||||
Category string
|
||||
Entries []struct {
|
||||
Name string
|
||||
Icon string
|
||||
Background string
|
||||
URL string
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
package controller
|
||||
|
||||
import (
|
||||
"github.com/r3labs/sse/v2"
|
||||
"gitlab.unjx.de/flohoss/godash/internal/bookmarks"
|
||||
"gitlab.unjx.de/flohoss/godash/internal/env"
|
||||
"gitlab.unjx.de/flohoss/godash/internal/system"
|
||||
"gitlab.unjx.de/flohoss/godash/internal/weather"
|
||||
)
|
||||
|
||||
type Controller struct {
|
||||
ENV *env.Config
|
||||
SSE *sse.Server
|
||||
Info Info
|
||||
}
|
||||
|
||||
type Info struct {
|
||||
Weather *weather.Weather
|
||||
Bookmarks *bookmarks.Config
|
||||
System *system.System
|
||||
}
|
||||
|
||||
func NewController(env *env.Config) *Controller {
|
||||
ctrl := Controller{
|
||||
ENV: env,
|
||||
SSE: sse.New(),
|
||||
}
|
||||
ctrl.SSE.AutoReplay = false
|
||||
ctrl.SSE.CreateStream("system")
|
||||
ctrl.SSE.CreateStream("weather")
|
||||
|
||||
ctrl.Info = Info{
|
||||
Weather: weather.NewWeatherService(ctrl.SSE),
|
||||
Bookmarks: bookmarks.NewBookmarkService(),
|
||||
System: system.NewSystemService(ctrl.ENV.LiveSystem, ctrl.SSE),
|
||||
}
|
||||
return &ctrl
|
||||
}
|
20
internal/env/env.go
vendored
|
@ -2,19 +2,16 @@ package env
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/caarlos0/env/v8"
|
||||
"github.com/caarlos0/env/v10"
|
||||
"github.com/go-playground/validator/v10"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
TimeZone string `env:"TZ" envDefault:"Etc/UTC" validate:"timezone"`
|
||||
Title string `env:"TITLE" envDefault:"goDash"`
|
||||
Port int `env:"PORT" envDefault:"4000" validate:"min=1024,max=49151"`
|
||||
LogLevel string `env:"LOG_LEVEL" envDefault:"info" validate:"oneof=debug info warn error"`
|
||||
LiveSystem bool `env:"LIVE_SYSTEM" envDefault:"true"`
|
||||
TimeZone string `env:"TZ" envDefault:"Etc/UTC" validate:"timezone"`
|
||||
Title string `env:"TITLE" envDefault:"goDash"`
|
||||
Port int `env:"PORT" envDefault:"4000" validate:"min=1024,max=49151"`
|
||||
Version string `env:"APP_VERSION"`
|
||||
}
|
||||
|
||||
var errParse = errors.New("error parsing environment variables")
|
||||
|
@ -27,7 +24,6 @@ func Parse() (*Config, error) {
|
|||
if err := validateContent(cfg); err != nil {
|
||||
return cfg, err
|
||||
}
|
||||
setAllDefaultEnvs(cfg)
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
|
@ -46,9 +42,3 @@ func validateContent(cfg *Config) error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func setAllDefaultEnvs(cfg *Config) {
|
||||
os.Setenv("TZ", cfg.TimeZone)
|
||||
os.Setenv("PORT", fmt.Sprintf("%d", cfg.Port))
|
||||
os.Setenv("LOG_LEVEL", cfg.LogLevel)
|
||||
}
|
||||
|
|
56
internal/env/env_test.go
vendored
|
@ -1,56 +0,0 @@
|
|||
package env
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestPortParser(t *testing.T) {
|
||||
key := "PORT"
|
||||
var err error
|
||||
defer func() {
|
||||
os.Unsetenv(key)
|
||||
}()
|
||||
|
||||
os.Setenv(key, "1024")
|
||||
_, err = Parse()
|
||||
assert.Equal(t, err, nil, "Parsing should pass")
|
||||
|
||||
os.Setenv(key, "-12")
|
||||
_, err = Parse()
|
||||
assert.Equal(t, err.Error(), "Key: 'Config.Port' Error:Field validation for 'Port' failed on the 'min' tag", "Validation should fail")
|
||||
|
||||
os.Setenv(key, "60000")
|
||||
_, err = Parse()
|
||||
assert.Equal(t, err.Error(), "Key: 'Config.Port' Error:Field validation for 'Port' failed on the 'max' tag", "Validation should fail")
|
||||
|
||||
os.Setenv(key, "abc")
|
||||
_, err = Parse()
|
||||
assert.Equal(t, err.Error(), "env: parse error on field \"Port\" of type \"int\": strconv.ParseInt: parsing \"abc\": invalid syntax", "Parsing should fail")
|
||||
}
|
||||
|
||||
func TestTimeZoneParser(t *testing.T) {
|
||||
key := "TZ"
|
||||
var err error
|
||||
defer func() {
|
||||
os.Unsetenv(key)
|
||||
}()
|
||||
|
||||
os.Setenv(key, "Europe/Berlin")
|
||||
_, err = Parse()
|
||||
assert.Equal(t, err, nil, "Parsing should pass")
|
||||
|
||||
os.Setenv(key, "Etc/UTC")
|
||||
_, err = Parse()
|
||||
assert.Equal(t, err, nil, "Parsing should pass")
|
||||
|
||||
os.Setenv(key, "abc")
|
||||
_, err = Parse()
|
||||
assert.Equal(t, err.Error(), "Key: 'Config.TimeZone' Error:Field validation for 'TimeZone' failed on the 'timezone' tag", "Validation should fail")
|
||||
|
||||
os.Setenv(key, "-1")
|
||||
_, err = Parse()
|
||||
assert.Equal(t, err.Error(), "Key: 'Config.TimeZone' Error:Field validation for 'TimeZone' failed on the 'timezone' tag", "Validation should fail")
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
package logger
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/lmittmann/tint"
|
||||
)
|
||||
|
||||
func NewLogger(logLevel string) *slog.Logger {
|
||||
w := os.Stderr
|
||||
|
||||
lvl := new(slog.Level)
|
||||
level := slog.LevelInfo
|
||||
err := lvl.UnmarshalText([]byte(logLevel))
|
||||
if err == nil {
|
||||
level = *lvl
|
||||
}
|
||||
|
||||
return slog.New(tint.NewHandler(w, &tint.Options{
|
||||
Level: &level,
|
||||
TimeFormat: time.Kitchen,
|
||||
}))
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
package router
|
||||
|
||||
import "github.com/labstack/echo/v4"
|
||||
|
||||
func longCacheLifetime(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
c.Response().Header().Set(echo.HeaderCacheControl, "public, max-age=31536000")
|
||||
return next(c)
|
||||
}
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
package router
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/labstack/echo/v4/middleware"
|
||||
"gitlab.unjx.de/flohoss/godash/internal/controller"
|
||||
)
|
||||
|
||||
func InitRouter() *echo.Echo {
|
||||
e := echo.New()
|
||||
|
||||
e.HideBanner = true
|
||||
e.HidePort = true
|
||||
|
||||
e.Pre(middleware.RemoveTrailingSlash())
|
||||
e.Use(middleware.Recover())
|
||||
e.Use(middleware.GzipWithConfig(middleware.GzipConfig{
|
||||
Skipper: func(c echo.Context) bool {
|
||||
return strings.Contains(c.Path(), "sse")
|
||||
},
|
||||
}))
|
||||
|
||||
e.Renderer = initTemplates()
|
||||
|
||||
return e
|
||||
}
|
||||
|
||||
func SetupRoutes(e *echo.Echo, ctrl *controller.Controller) {
|
||||
static := e.Group("/static", longCacheLifetime)
|
||||
static.Static("/", "web/static")
|
||||
|
||||
storage := e.Group("/storage", longCacheLifetime)
|
||||
storage.Static("/icons", "storage/icons")
|
||||
|
||||
e.GET("/", func(c echo.Context) error {
|
||||
return c.Render(http.StatusOK, "index.html", map[string]interface{}{
|
||||
"Title": ctrl.ENV.Title,
|
||||
"Weather": ctrl.Info.Weather.CurrentWeather,
|
||||
"Parsed": ctrl.Info.Bookmarks.Parsed,
|
||||
"System": ctrl.Info.System,
|
||||
})
|
||||
})
|
||||
|
||||
e.GET("/sse", echo.WrapHandler(http.HandlerFunc(ctrl.SSE.ServeHTTP)))
|
||||
|
||||
e.GET("/robots.txt", func(ctx echo.Context) error {
|
||||
return ctx.String(http.StatusOK, "User-agent: *\nDisallow: /")
|
||||
})
|
||||
e.RouteNotFound("*", func(ctx echo.Context) error {
|
||||
return ctx.Redirect(http.StatusTemporaryRedirect, "/")
|
||||
})
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
package router
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
"io"
|
||||
|
||||
"github.com/Masterminds/sprig/v3"
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
func backgroundColor(config string) string {
|
||||
result := "p-[0.1rem] "
|
||||
switch config {
|
||||
case "dark":
|
||||
return result + "bg-black "
|
||||
case "light":
|
||||
return result + "bg-white "
|
||||
case "base":
|
||||
return result + "bg-base-300 "
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
type Template struct {
|
||||
templates *template.Template
|
||||
}
|
||||
|
||||
func (t *Template) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
|
||||
return t.templates.ExecuteTemplate(w, "layout.html", data)
|
||||
}
|
||||
|
||||
func initTemplates() *Template {
|
||||
return &Template{
|
||||
templates: template.Must(template.New("").Funcs(sprig.FuncMap()).Funcs(template.FuncMap{
|
||||
"backgroundColor": backgroundColor,
|
||||
}).ParseGlob("web/templates/*.html")),
|
||||
}
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
package system
|
||||
|
||||
import (
|
||||
"math"
|
||||
"runtime"
|
||||
"strconv"
|
||||
|
||||
"github.com/shirou/gopsutil/v3/cpu"
|
||||
)
|
||||
|
||||
func staticCpu() CPU {
|
||||
var p CPU
|
||||
p.Threads = strconv.Itoa(runtime.NumCPU()) + " threads"
|
||||
c, err := cpu.Info()
|
||||
if err == nil {
|
||||
p.Name = c[0].ModelName
|
||||
} else {
|
||||
p.Name = "none detected"
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
func (c *Config) liveCpu() {
|
||||
p, err := cpu.Percent(0, false)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
c.System.Live.CPU = math.RoundToEven(p[0])
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
package system
|
||||
|
||||
import (
|
||||
"math"
|
||||
"strconv"
|
||||
|
||||
"github.com/dariubs/percent"
|
||||
"github.com/shirou/gopsutil/v3/disk"
|
||||
)
|
||||
|
||||
func staticDisk() Disk {
|
||||
var result = Disk{}
|
||||
d, err := disk.Usage("/")
|
||||
if err != nil {
|
||||
return result
|
||||
}
|
||||
p, err := disk.Partitions(false)
|
||||
if err != nil {
|
||||
return result
|
||||
}
|
||||
result.Total = readableSize(d.Total)
|
||||
result.Partitions = strconv.Itoa(len(p)) + " partitions"
|
||||
return result
|
||||
}
|
||||
|
||||
func (c *Config) liveDisk() {
|
||||
d, err := disk.Usage("/")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
c.System.Live.Disk.Value = readableSize(d.Used)
|
||||
c.System.Live.Disk.Percentage = math.RoundToEven(percent.PercentOfFloat(float64(d.Used), float64(d.Total)))
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
package system
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
)
|
||||
|
||||
func staticHost() Host {
|
||||
var h Host
|
||||
h.Architecture = runtime.GOARCH
|
||||
return h
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
package system
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"github.com/dariubs/percent"
|
||||
"github.com/shirou/gopsutil/v3/mem"
|
||||
)
|
||||
|
||||
func staticRam() Ram {
|
||||
var result = Ram{}
|
||||
r, err := mem.VirtualMemory()
|
||||
if err != nil {
|
||||
return result
|
||||
}
|
||||
result.Total = readableSize(r.Total)
|
||||
if r.SwapTotal > 0 {
|
||||
result.Swap = readableSize(r.SwapTotal) + " swap"
|
||||
} else {
|
||||
result.Swap = "No swap"
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (c *Config) liveRam() {
|
||||
r, err := mem.VirtualMemory()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
c.System.Live.Ram.Value = readableSize(r.Used)
|
||||
c.System.Live.Ram.Percentage = math.RoundToEven(percent.PercentOfFloat(float64(r.Used), float64(r.Total)))
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
package system
|
||||
|
||||
import "fmt"
|
||||
|
||||
const (
|
||||
KiB uint64 = 1024
|
||||
MiB = KiB * 1024
|
||||
GiB = MiB * 1024
|
||||
TiB = GiB * 1024
|
||||
PiB = TiB * 1024
|
||||
EiB = PiB * 1024
|
||||
)
|
||||
|
||||
func amountString(size uint64) (uint64, string) {
|
||||
switch {
|
||||
case size < MiB:
|
||||
return KiB, "KiB"
|
||||
case size < GiB:
|
||||
return MiB, "MiB"
|
||||
case size < TiB:
|
||||
return GiB, "GiB"
|
||||
case size < PiB:
|
||||
return TiB, "TiB"
|
||||
case size < EiB:
|
||||
return PiB, "PiB"
|
||||
default:
|
||||
return EiB, "EiB"
|
||||
}
|
||||
}
|
||||
|
||||
func readableSize(size uint64) string {
|
||||
unit, unitStr := amountString(size)
|
||||
return fmt.Sprintf("%.2f %s", float64(size)/float64(unit), unitStr)
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
package system
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log/slog"
|
||||
"time"
|
||||
|
||||
"github.com/r3labs/sse/v2"
|
||||
)
|
||||
|
||||
func NewSystemService(enabled bool, sse *sse.Server) *System {
|
||||
var s Config
|
||||
if enabled {
|
||||
s = Config{sse: sse}
|
||||
s.Initialize()
|
||||
}
|
||||
return &s.System
|
||||
}
|
||||
|
||||
func (c *Config) UpdateLiveInformation() {
|
||||
for {
|
||||
c.liveCpu()
|
||||
c.liveRam()
|
||||
c.liveDisk()
|
||||
c.uptime()
|
||||
json, _ := json.Marshal(c.System.Live)
|
||||
c.sse.Publish("system", &sse.Event{Data: json})
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Config) Initialize() {
|
||||
c.System.Static.Host = staticHost()
|
||||
c.System.Static.CPU = staticCpu()
|
||||
c.System.Static.Ram = staticRam()
|
||||
c.System.Static.Disk = staticDisk()
|
||||
go c.UpdateLiveInformation()
|
||||
slog.Debug("system updated", "cpu", c.System.Static.CPU.Name, "arch", c.System.Static.Host.Architecture)
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
package system
|
||||
|
||||
import (
|
||||
"github.com/shirou/gopsutil/v3/host"
|
||||
)
|
||||
|
||||
func (c *Config) uptime() {
|
||||
i, err := host.Info()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
c.System.Live.Uptime.Days = i.Uptime / 84600
|
||||
c.System.Live.Uptime.Hours = uint16((i.Uptime % 86400) / 3600)
|
||||
c.System.Live.Uptime.Minutes = uint16(((i.Uptime % 86400) % 3600) / 60)
|
||||
c.System.Live.Uptime.Seconds = uint16(((i.Uptime % 86400) % 3600) % 60)
|
||||
c.System.Live.Uptime.Percentage = float32((c.System.Live.Uptime.Minutes*100)+c.System.Live.Uptime.Seconds) / 60
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
package weather
|
||||
|
||||
import (
|
||||
"github.com/r3labs/sse/v2"
|
||||
)
|
||||
|
||||
type Weather struct {
|
||||
CurrentWeather OpenWeather
|
||||
sse *sse.Server
|
||||
config config
|
||||
}
|
||||
|
||||
type config struct {
|
||||
Latitude float32 `env:"LOCATION_LATITUDE" envDefault:"48.780331609463815"`
|
||||
Longitude float32 `env:"LOCATION_LONGITUDE" envDefault:"9.177968320179422"`
|
||||
Key string `env:"WEATHER_KEY" envDefault:""`
|
||||
Units string `env:"WEATHER_UNITS" envDefault:"metric"`
|
||||
Lang string `env:"WEATHER_LANG" envDefault:"en"`
|
||||
Digits bool `env:"WEATHER_DIGITS" envDefault:"true"`
|
||||
}
|
||||
|
||||
type OpenWeather struct {
|
||||
Icon string `json:"icon"`
|
||||
Temp float64 `json:"temp"`
|
||||
Description string `json:"description"`
|
||||
Humidity uint8 `json:"humidity"`
|
||||
Sunrise string `json:"sunrise"`
|
||||
Sunset string `json:"sunset"`
|
||||
Units string `json:"units"`
|
||||
}
|
||||
|
||||
type OpenWeatherApiResponse struct {
|
||||
Weather []OpenWeatherApiWeather `json:"Weather"`
|
||||
Main OpenWeatherApiMain `json:"main"`
|
||||
Sys OpenWeatherApiSys `json:"sys"`
|
||||
}
|
||||
|
||||
type OpenWeatherApiWeather struct {
|
||||
Description string `json:"description"`
|
||||
Icon string `json:"icon"`
|
||||
}
|
||||
|
||||
type OpenWeatherApiMain struct {
|
||||
Temp float64 `json:"temp"`
|
||||
Humidity uint8 `json:"humidity"`
|
||||
}
|
||||
|
||||
type OpenWeatherApiSys struct {
|
||||
Sunrise int64 `json:"sunrise"`
|
||||
Sunset int64 `json:"sunset"`
|
||||
}
|
|
@ -1,77 +0,0 @@
|
|||
package weather
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log/slog"
|
||||
"math"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/caarlos0/env/v8"
|
||||
"github.com/r3labs/sse/v2"
|
||||
)
|
||||
|
||||
func NewWeatherService(sse *sse.Server) *Weather {
|
||||
var w = Weather{sse: sse}
|
||||
if err := env.Parse(&w.config); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if w.config.Key != "" {
|
||||
w.setWeatherUnits()
|
||||
go w.updateWeather(time.Second * 90)
|
||||
}
|
||||
return &w
|
||||
}
|
||||
|
||||
func (w *Weather) setWeatherUnits() {
|
||||
if w.config.Units == "imperial" {
|
||||
w.CurrentWeather.Units = "°F"
|
||||
} else {
|
||||
w.CurrentWeather.Units = "°C"
|
||||
}
|
||||
}
|
||||
|
||||
func (w *Weather) copyWeatherValues(weatherResp *OpenWeatherApiResponse) {
|
||||
myTime := time.Unix(weatherResp.Sys.Sunrise, 0)
|
||||
w.CurrentWeather.Sunrise = myTime.Format("15:04")
|
||||
myTime = time.Unix(weatherResp.Sys.Sunset, 0)
|
||||
w.CurrentWeather.Sunset = myTime.Format("15:04")
|
||||
w.CurrentWeather.Icon = weatherResp.Weather[0].Icon
|
||||
if w.config.Digits {
|
||||
w.CurrentWeather.Temp = weatherResp.Main.Temp
|
||||
} else {
|
||||
w.CurrentWeather.Temp = math.Round(weatherResp.Main.Temp)
|
||||
}
|
||||
w.CurrentWeather.Description = weatherResp.Weather[0].Description
|
||||
w.CurrentWeather.Humidity = weatherResp.Main.Humidity
|
||||
}
|
||||
|
||||
func (w *Weather) updateWeather(interval time.Duration) {
|
||||
var weatherResponse OpenWeatherApiResponse
|
||||
for {
|
||||
resp, err := http.Get(fmt.Sprintf("https://api.openweathermap.org/data/2.5/weather?lat=%f&lon=%f&appid=%s&units=%s&lang=%s",
|
||||
w.config.Latitude,
|
||||
w.config.Longitude,
|
||||
w.config.Key,
|
||||
w.config.Units,
|
||||
w.config.Lang))
|
||||
if err != nil || resp.StatusCode != 200 {
|
||||
slog.Error("weather cannot be updated, please check WEATHER_KEY")
|
||||
} else {
|
||||
body, _ := io.ReadAll(resp.Body)
|
||||
err = json.Unmarshal(body, &weatherResponse)
|
||||
if err != nil {
|
||||
slog.Error("weather cannot be processed")
|
||||
} else {
|
||||
w.copyWeatherValues(&weatherResponse)
|
||||
slog.Debug("weather updated", "temp", w.CurrentWeather.Temp)
|
||||
}
|
||||
resp.Body.Close()
|
||||
json, _ := json.Marshal(w.CurrentWeather)
|
||||
w.sse.Publish("weather", &sse.Event{Data: json})
|
||||
}
|
||||
time.Sleep(interval)
|
||||
}
|
||||
}
|
56
main.go
Normal file
|
@ -0,0 +1,56 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/labstack/echo/v4/middleware"
|
||||
"github.com/r3labs/sse/v2"
|
||||
"gitlab.unjx.de/flohoss/godash/handlers"
|
||||
"gitlab.unjx.de/flohoss/godash/internal/env"
|
||||
"gitlab.unjx.de/flohoss/godash/services"
|
||||
)
|
||||
|
||||
func main() {
|
||||
env, err := env.Parse()
|
||||
if err != nil {
|
||||
slog.Error("cannot parse environment variables", "err", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
e := echo.New()
|
||||
e.HideBanner = true
|
||||
e.HidePort = true
|
||||
e.Debug = true
|
||||
|
||||
e.Pre(middleware.RemoveTrailingSlash())
|
||||
e.Use(middleware.Recover())
|
||||
e.Use(middleware.GzipWithConfig(middleware.GzipConfig{
|
||||
Skipper: func(c echo.Context) bool {
|
||||
return strings.Contains(c.Path(), "sse")
|
||||
},
|
||||
}))
|
||||
|
||||
e.Static("/", "assets")
|
||||
e.Static("/storage/icons", "storage/icons")
|
||||
|
||||
sse := sse.New()
|
||||
sse.AutoReplay = false
|
||||
sse.CreateStream("weather")
|
||||
|
||||
s := services.NewSystemService(sse)
|
||||
b := services.NewBookmarkService()
|
||||
|
||||
ah := handlers.NewAppHandler(env, s, b)
|
||||
handlers.SetupRoutes(e, sse, ah)
|
||||
|
||||
slog.Info("starting server", "url", fmt.Sprintf("http://localhost:%d", env.Port))
|
||||
if err := e.Start(fmt.Sprintf(":%d", env.Port)); err != http.ErrServerClosed {
|
||||
slog.Error("cannot start server", "err", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
15
package.json
Normal file
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"license": "Apache-2.0",
|
||||
"scripts": {
|
||||
"tw:dev": "npx tailwindcss -i ./assets/css/tailwind.css -o ./assets/css/style.css --watch",
|
||||
"tw:build": "npx tailwindcss -i ./assets/css/tailwind.css -o ./assets/css/style.css --minify"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@iconify-json/bi": "^1.1.23",
|
||||
"@iconify-json/clarity": "^1.1.12",
|
||||
"@iconify-json/ri": "^1.1.20",
|
||||
"@iconify/tailwind": "^0.1.4",
|
||||
"daisyui": "^4.7.3",
|
||||
"tailwindcss": "^3.4.1"
|
||||
}
|
||||
}
|
4
scripts/.air.toml
Normal file
|
@ -0,0 +1,4 @@
|
|||
[build]
|
||||
bin = "tmp/app"
|
||||
cmd = "go build -o tmp/app main.go"
|
||||
exclude_dir = [".gitlab", "node_modules", "assets", "storage", "tmp"]
|
|
@ -1,22 +0,0 @@
|
|||
#!/bin/sh
|
||||
parse_yaml() {
|
||||
local prefix=$2
|
||||
local s='[[:space:]]*' w='[a-zA-Z0-9_]*' fs=$(echo @ | tr @ '\034')
|
||||
sed -ne "s|^\($s\)\($w\)$s:$s\"\(.*\)\"$s\$|\1$fs\2$fs\3|p" \
|
||||
-e "s|^\($s\)\($w\)$s:$s\(.*\)$s\$|\1$fs\2$fs\3|p" $1 |
|
||||
awk -F$fs '{
|
||||
indent = length($1)/2;
|
||||
vname[indent] = $2;
|
||||
for (i in vname) {if (i > indent) {delete vname[i]}}
|
||||
if (length($3) > 0) {
|
||||
vn=""; for (i=0; i<indent; i++) {vn=(vn)(vname[i])("_")}
|
||||
printf("%s%s%s=\"%s\"\n", "'$prefix'",vn, $2, $3);
|
||||
}
|
||||
}'
|
||||
}
|
||||
|
||||
eval $(parse_yaml .gitlab/_common.gitlab-ci.yml)
|
||||
|
||||
echo "GOLANG_VERSION="$variables_GOLANG_VERSION >.env
|
||||
echo "NODE_VERSION="$variables_NODE_VERSION >>.env
|
||||
echo "ALPINE_VERSION="$variables_ALPINE_VERSION >>.env
|
|
@ -4,31 +4,31 @@ cat logo.txt
|
|||
CMD=./godash
|
||||
|
||||
if [ -n "$PUID" ] || [ -n "$PGID" ]; then
|
||||
USER=appuser
|
||||
HOME=/app
|
||||
USER=appuser
|
||||
HOME=/app
|
||||
|
||||
if ! grep -q "$USER" /etc/passwd; then
|
||||
# Usage: addgroup [-g GID] [-S] [USER] GROUP
|
||||
#
|
||||
# Add a group or add a user to a group
|
||||
# -g GID Group id
|
||||
addgroup -g "$PGID" "$USER"
|
||||
if ! grep -q "$USER" /etc/passwd; then
|
||||
# Usage: addgroup [-g GID] [-S] [USER] GROUP
|
||||
#
|
||||
# Add a group or add a user to a group
|
||||
# -g GID Group id
|
||||
addgroup -g "$PGID" "$USER"
|
||||
|
||||
# Usage: adduser [OPTIONS] USER [GROUP]
|
||||
# Create new user, or add USER to GROUP
|
||||
# -h DIR Home directory
|
||||
# -g GECOS GECOS field
|
||||
# -G GRP Group
|
||||
# -D Don't assign a password
|
||||
# -H Don't create home directory
|
||||
# -u UID User id
|
||||
adduser -h "$HOME" -g "" -G "$USER" -D -H -u "$PUID" "$USER"
|
||||
fi
|
||||
# Usage: adduser [OPTIONS] USER [GROUP]
|
||||
# Create new user, or add USER to GROUP
|
||||
# -h DIR Home directory
|
||||
# -g GECOS GECOS field
|
||||
# -G GRP Group
|
||||
# -D Don't assign a password
|
||||
# -H Don't create home directory
|
||||
# -u UID User id
|
||||
adduser -h "$HOME" -g "" -G "$USER" -D -H -u "$PUID" "$USER"
|
||||
fi
|
||||
|
||||
chown "$USER":"$USER" "$HOME" -R
|
||||
printf "\nUID: %s GID: %s\n\n" "$PUID" "$PGID"
|
||||
exec su -c - $USER "$CMD"
|
||||
chown "$USER":"$USER" "$HOME" -R
|
||||
printf "\nUID: %s GID: %s\n\n" "$PUID" "$PGID"
|
||||
exec su -c - $USER "$CMD"
|
||||
else
|
||||
printf "\nWARNING: Running docker as root\n\n"
|
||||
exec "$CMD"
|
||||
printf "\nWARNING: Running docker as root\n\n"
|
||||
exec "$CMD"
|
||||
fi
|
||||
|
|
123
services/bookmark.services.go
Normal file
|
@ -0,0 +1,123 @@
|
|||
package services
|
||||
|
||||
import (
|
||||
"io"
|
||||
"log/slog"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
const storageDir = "storage/"
|
||||
const iconsDir = storageDir + "icons/"
|
||||
const bookmarkFile = storageDir + "bookmarks.yaml"
|
||||
const defaultConfig = `links:
|
||||
- category: "Code"
|
||||
entries:
|
||||
- name: "Github"
|
||||
url: "https://github.com"
|
||||
|
||||
applications:
|
||||
- category: "Code"
|
||||
entries:
|
||||
- name: "Github"
|
||||
icon: "https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png"
|
||||
url: "https://github.com"`
|
||||
|
||||
func init() {
|
||||
folders := []string{storageDir, iconsDir}
|
||||
for _, path := range folders {
|
||||
err := os.MkdirAll(path, 0755)
|
||||
if err != nil {
|
||||
slog.Error(err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
slog.Debug("folders created", "folders", folders)
|
||||
}
|
||||
|
||||
func NewBookmarkService() *BookmarkService {
|
||||
bs := BookmarkService{}
|
||||
bs.parseBookmarks()
|
||||
return &bs
|
||||
}
|
||||
|
||||
type BookmarkService struct {
|
||||
bookmarks Bookmarks
|
||||
}
|
||||
|
||||
type Bookmarks struct {
|
||||
Links []struct {
|
||||
Category string
|
||||
Entries []Link
|
||||
}
|
||||
Applications []struct {
|
||||
Category string
|
||||
Entries []Application
|
||||
}
|
||||
}
|
||||
|
||||
type Link struct {
|
||||
Name string
|
||||
URL string
|
||||
}
|
||||
|
||||
type Application struct {
|
||||
Name string
|
||||
Icon string
|
||||
Background string
|
||||
URL string
|
||||
}
|
||||
|
||||
func (bs *BookmarkService) GetAllBookmarks() *Bookmarks {
|
||||
return &bs.bookmarks
|
||||
}
|
||||
|
||||
func (bs *BookmarkService) createDefaultConfigFile() {
|
||||
slog.Info("Creating default config file: " + bookmarkFile)
|
||||
err := os.WriteFile(bookmarkFile, []byte(defaultConfig), 0755)
|
||||
if err != nil {
|
||||
slog.Error(err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func (bs *BookmarkService) readBookmarksFile() []byte {
|
||||
file, err := os.Open(bookmarkFile)
|
||||
if err != nil {
|
||||
bs.createDefaultConfigFile()
|
||||
file, err = os.Open(bookmarkFile)
|
||||
if err != nil {
|
||||
slog.Error(err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
defer file.Close()
|
||||
byteValue, err := io.ReadAll(file)
|
||||
if err != nil {
|
||||
slog.Error(err.Error())
|
||||
return nil
|
||||
}
|
||||
return byteValue
|
||||
}
|
||||
|
||||
func (bs *BookmarkService) replaceIconString() {
|
||||
for _, v := range bs.bookmarks.Applications {
|
||||
for i, bookmark := range v.Entries {
|
||||
if !strings.Contains(bookmark.Icon, "http") {
|
||||
v.Entries[i].Icon = "/" + iconsDir + bookmark.Icon
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (bs *BookmarkService) parseBookmarks() {
|
||||
byteValue := bs.readBookmarksFile()
|
||||
err := yaml.Unmarshal(byteValue, &bs.bookmarks)
|
||||
if err != nil {
|
||||
slog.Error(err.Error())
|
||||
return
|
||||
}
|
||||
bs.replaceIconString()
|
||||
}
|
138
services/system.services.go
Normal file
|
@ -0,0 +1,138 @@
|
|||
package services
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"math"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/dariubs/percent"
|
||||
"github.com/r3labs/sse/v2"
|
||||
"github.com/shirou/gopsutil/cpu"
|
||||
"github.com/shirou/gopsutil/disk"
|
||||
"github.com/shirou/gopsutil/host"
|
||||
"github.com/shirou/gopsutil/mem"
|
||||
"gitlab.unjx.de/flohoss/godash/internal/storage"
|
||||
)
|
||||
|
||||
func NewSystemService(sse *sse.Server) *SystemService {
|
||||
s := SystemService{
|
||||
sse: sse,
|
||||
Static: StaticInformation{
|
||||
CPU: staticCpu(),
|
||||
Ram: staticRam(),
|
||||
Disk: staticDisk(),
|
||||
Host: staticHost(),
|
||||
},
|
||||
}
|
||||
sse.CreateStream("system")
|
||||
go s.UpdateLiveInformation()
|
||||
return &s
|
||||
}
|
||||
|
||||
func (s *SystemService) GetLiveInformation() *LiveInformation {
|
||||
return &s.Live
|
||||
}
|
||||
|
||||
func (s *SystemService) GetStaticInformation() *StaticInformation {
|
||||
return &s.Static
|
||||
}
|
||||
|
||||
func (s *SystemService) UpdateLiveInformation() {
|
||||
for {
|
||||
s.liveCpu()
|
||||
s.liveRam()
|
||||
s.liveDisk()
|
||||
s.uptime()
|
||||
json, _ := json.Marshal(s.Live)
|
||||
s.sse.Publish("system", &sse.Event{Data: json})
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
func staticHost() Host {
|
||||
var h Host
|
||||
h.Architecture = runtime.GOARCH
|
||||
return h
|
||||
}
|
||||
|
||||
func staticCpu() CPU {
|
||||
var p CPU
|
||||
p.Threads = strconv.Itoa(runtime.NumCPU()) + " threads"
|
||||
c, err := cpu.Info()
|
||||
if err == nil {
|
||||
p.Name = c[0].ModelName
|
||||
} else {
|
||||
p.Name = "none detected"
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
func (s *SystemService) liveCpu() {
|
||||
p, err := cpu.Percent(0, false)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
s.Live.CPU = math.RoundToEven(p[0])
|
||||
}
|
||||
|
||||
func staticRam() Ram {
|
||||
var result = Ram{}
|
||||
r, err := mem.VirtualMemory()
|
||||
if err != nil {
|
||||
return result
|
||||
}
|
||||
result.Total = storage.ReadableSize(r.Total)
|
||||
if r.SwapTotal > 0 {
|
||||
result.Swap = storage.ReadableSize(r.SwapTotal) + " swap"
|
||||
} else {
|
||||
result.Swap = "no swap"
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (s *SystemService) liveRam() {
|
||||
r, err := mem.VirtualMemory()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
s.Live.Ram.Value = storage.ReadableSize(r.Used)
|
||||
s.Live.Ram.Percentage = math.RoundToEven(percent.PercentOfFloat(float64(r.Used), float64(r.Total)))
|
||||
}
|
||||
|
||||
func staticDisk() Disk {
|
||||
var result = Disk{}
|
||||
d, err := disk.Usage("/")
|
||||
if err != nil {
|
||||
return result
|
||||
}
|
||||
p, err := disk.Partitions(false)
|
||||
if err != nil {
|
||||
return result
|
||||
}
|
||||
result.Total = storage.ReadableSize(d.Total)
|
||||
result.Partitions = strconv.Itoa(len(p)) + " partitions"
|
||||
return result
|
||||
}
|
||||
|
||||
func (s *SystemService) liveDisk() {
|
||||
d, err := disk.Usage("/")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
s.Live.Disk.Value = storage.ReadableSize(d.Used)
|
||||
s.Live.Disk.Percentage = math.RoundToEven(percent.PercentOfFloat(float64(d.Used), float64(d.Total)))
|
||||
}
|
||||
|
||||
func (s *SystemService) uptime() {
|
||||
i, err := host.Info()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
s.Live.Uptime.Days = i.Uptime / 84600
|
||||
s.Live.Uptime.Hours = uint16((i.Uptime % 86400) / 3600)
|
||||
s.Live.Uptime.Minutes = uint16(((i.Uptime % 86400) % 3600) / 60)
|
||||
s.Live.Uptime.Seconds = uint16(((i.Uptime % 86400) % 3600) % 60)
|
||||
s.Live.Uptime.Percentage = float32((s.Live.Uptime.Minutes*100)+s.Live.Uptime.Seconds) / 60
|
||||
}
|
|
@ -1,15 +1,9 @@
|
|||
package system
|
||||
package services
|
||||
|
||||
import (
|
||||
"github.com/r3labs/sse/v2"
|
||||
)
|
||||
import "github.com/r3labs/sse/v2"
|
||||
|
||||
type Config struct {
|
||||
type SystemService struct {
|
||||
sse *sse.Server
|
||||
System System
|
||||
}
|
||||
|
||||
type System struct {
|
||||
Live LiveInformation `json:"live"`
|
||||
Static StaticInformation `json:"static"`
|
||||
}
|
|
@ -1,22 +1,24 @@
|
|||
const { addDynamicIconSelectors } = require('@iconify/tailwind');
|
||||
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
content: ["./templates/**/*.html", "../internal/router/templates.go"],
|
||||
content: ['./views/**/*.templ','./components/**/*.templ'],
|
||||
theme: {
|
||||
container: {
|
||||
center: true
|
||||
},
|
||||
},
|
||||
plugins: [require("daisyui")],
|
||||
plugins: [require('daisyui'), addDynamicIconSelectors()],
|
||||
daisyui: {
|
||||
themes: [
|
||||
{
|
||||
light: {
|
||||
...require("daisyui/src/theming/themes")["[data-theme=garden]"],
|
||||
...require("daisyui/src/theming/themes")["garden"],
|
||||
primary: "#f28c18",
|
||||
secondary: "rgba(70,70,70,0.7)",
|
||||
},
|
||||
dark: {
|
||||
...require("daisyui/src/theming/themes")["[data-theme=halloween]"],
|
||||
...require("daisyui/src/theming/themes")["halloween"],
|
||||
secondary: "#a0a0a0",
|
||||
},
|
||||
},
|
13
tbot.yaml
Normal file
|
@ -0,0 +1,13 @@
|
|||
version: v2
|
||||
auth_server: tp.unjx.de:443
|
||||
onboarding:
|
||||
join_method: gitlab
|
||||
token: gitlab
|
||||
oneshot: true
|
||||
storage:
|
||||
type: memory
|
||||
outputs:
|
||||
- type: identity
|
||||
destination:
|
||||
type: directory
|
||||
path: /tmp/machine-id
|
BIN
tmp/app
Executable file
116
views/home/home.templ
Normal file
|
@ -0,0 +1,116 @@
|
|||
package home
|
||||
|
||||
import "gitlab.unjx.de/flohoss/godash/services"
|
||||
import "gitlab.unjx.de/flohoss/godash/views/layout"
|
||||
import "gitlab.unjx.de/flohoss/godash/components"
|
||||
import "fmt"
|
||||
|
||||
templ Home(title string, bookmarks *services.Bookmarks, static *services.StaticInformation, live *services.LiveInformation) {
|
||||
<section class="grid gap-14">
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-4 gap-3 select-none">
|
||||
@components.System("icon-[bi--cpu]",static.CPU.Name,"",static.CPU.Threads,"systemCpuPercentage","",live.CPU)
|
||||
@components.System("icon-[bi--memory]",live.Ram.Value,fmt.Sprintf(" | %s", static.Ram.Total),static.Ram.Swap,"systemRamPercentage","systemRamValue",live.Ram.Percentage)
|
||||
@components.System("icon-[bi--nvme]",live.Disk.Value,fmt.Sprintf(" | %s", static.Disk.Total),static.Disk.Partitions,"systemDiskPercentage","systemDiskValue",live.Disk.Percentage)
|
||||
@components.Uptime(static.Host.Architecture,"systemUptimePercentage",live.Uptime)
|
||||
</div>
|
||||
<div class="grid gap-4">
|
||||
for _, app := range bookmarks.Applications {
|
||||
<div class="grid gap-2">
|
||||
if app.Category != "" {
|
||||
<div class="heading">{ app.Category }</div>
|
||||
}
|
||||
<div class="grid-apps">
|
||||
for _, entry := range app.Entries {
|
||||
@components.Application(entry)
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="grid-apps">
|
||||
for _, link := range bookmarks.Links {
|
||||
<div class="flex flex-col gap-2">
|
||||
if link.Category != "" {
|
||||
<div class="heading">{ link.Category }</div>
|
||||
}
|
||||
for _, entry := range link.Entries {
|
||||
@components.Link(entry)
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</section>
|
||||
<script>
|
||||
let systemSSESource = null;
|
||||
let weatherSSESource = null;
|
||||
addEventListener('beforeunload', () => {
|
||||
systemSSESource && systemSSESource.close();
|
||||
weatherSSESource && weatherSSESource.close();
|
||||
});
|
||||
systemSSESource = new EventSource('/sse?stream=system');
|
||||
systemSSESource.onmessage = (e) => {
|
||||
const parsed = JSON.parse(e.data);
|
||||
replaceSystem(parsed);
|
||||
};
|
||||
weatherSSESource = new EventSource('/sse?stream=weather');
|
||||
weatherSSESource.onmessage = (e) => {
|
||||
const parsed = JSON.parse(e.data);
|
||||
replaceWeather(parsed);
|
||||
};
|
||||
|
||||
// weather elements
|
||||
const weatherIcon = document.getElementById('weatherIcon');
|
||||
const weatherTemp = document.getElementById('weatherTemp');
|
||||
const weatherDescription = document.getElementById('weatherDescription');
|
||||
const weatherHumidity = document.getElementById('weatherHumidity');
|
||||
const weatherSunrise = document.getElementById('weatherSunrise');
|
||||
const weatherSunset = document.getElementById('weatherSunset');
|
||||
|
||||
// system elements
|
||||
const systemCpuPercentage = document.getElementById('systemCpuPercentage');
|
||||
const systemRamPercentage = document.getElementById('systemRamPercentage');
|
||||
const systemRamValue = document.getElementById('systemRamValue');
|
||||
const systemDiskPercentage = document.getElementById('systemDiskPercentage');
|
||||
const systemDiskValue = document.getElementById('systemDiskValue');
|
||||
const systemUptimePercentage = document.getElementById('systemUptimePercentage');
|
||||
const uptimeDays = document.getElementById('uptimeDays');
|
||||
const uptimeHours = document.getElementById('uptimeHours');
|
||||
const uptimeMinutes = document.getElementById('uptimeMinutes');
|
||||
const uptimeSeconds = document.getElementById('uptimeSeconds');
|
||||
|
||||
function replaceWeather(parsed) {
|
||||
weatherIcon.setAttribute('xlink:href', '#' + parsed.icon);
|
||||
weatherTemp.innerText = parsed.temp;
|
||||
weatherDescription.innerText = parsed.description;
|
||||
weatherHumidity.innerText = parsed.humidity + '%';
|
||||
weatherSunrise.innerText = parsed.sunrise;
|
||||
weatherSunset.innerText = parsed.sunset;
|
||||
}
|
||||
|
||||
function replaceSystem(parsed) {
|
||||
systemCpuPercentage.style = 'width:' + parsed.cpu + '%';
|
||||
systemRamPercentage.style = 'width:' + parsed.ram.percentage + '%';
|
||||
systemRamValue.innerText = parsed.ram.value;
|
||||
systemDiskPercentage.style = 'width:' + parsed.disk.percentage + '%';
|
||||
systemDiskValue.innerText = parsed.disk.value;
|
||||
systemUptimePercentage.style = 'width:' + parsed.uptime.percentage + '%';
|
||||
uptimeDays.style = '--value:' + parsed.uptime.days;
|
||||
uptimeHours.style = '--value:' + parsed.uptime.hours;
|
||||
uptimeMinutes.style = '--value:' + parsed.uptime.minutes;
|
||||
uptimeSeconds.style = '--value:' + parsed.uptime.seconds;
|
||||
}
|
||||
</script>
|
||||
}
|
||||
|
||||
templ HomeIndex(
|
||||
title,
|
||||
version string,
|
||||
bookmarks *services.Bookmarks,
|
||||
static *services.StaticInformation,
|
||||
live *services.LiveInformation,
|
||||
cmp templ.Component,
|
||||
) {
|
||||
@layout.Base(title, version) {
|
||||
@cmp
|
||||
}
|
||||
}
|
35
views/layout/base.layout.templ
Normal file
|
@ -0,0 +1,35 @@
|
|||
package layout
|
||||
|
||||
func getStyleSheet(version string) string {
|
||||
return "/css/style.css?v=" + version
|
||||
}
|
||||
|
||||
templ Base(title, version string) {
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8"/>
|
||||
<title>{ title }</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<meta name="description" content="A blazing fast start-page for services written in Go "/>
|
||||
<meta name="theme-color" content="#d07915"/>
|
||||
<link rel="icon" type="image/x-icon" href="/favicon/favicon.ico"/>
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/favicon/favicon-32x32.png"/>
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/favicon/favicon-16x16.png"/>
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/favicon/apple-touch-icon.png"/>
|
||||
<link rel="manifest" href="/favicon/site.webmanifest"/>
|
||||
<style>
|
||||
.bookmark-link:hover .img {
|
||||
opacity: 1;
|
||||
transition: opacity linear 0.15s;
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" href={ getStyleSheet(version) }/>
|
||||
</head>
|
||||
<body>
|
||||
<main class="p-4 sm:p-6 lg:p-8 xl:container xl:py-12">
|
||||
{ children... }
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
{
|
||||
"license": "Apache-2.0",
|
||||
"scripts": {
|
||||
"tailwind:dev": "npx tailwindcss -i ./static/css/tailwind.css -o ./static/css/style.css --watch",
|
||||
"tailwind:build": "npx tailwindcss -i ./static/css/tailwind.css -o ./static/css/style.css --minify"
|
||||
},
|
||||
"dependencies": {
|
||||
"autoprefixer": "^10.0.2",
|
||||
"daisyui": "^3.1.5",
|
||||
"postcss": "^8.1.6",
|
||||
"prettier": "^3.0.3",
|
||||
"prettier-plugin-go-template": "^0.0.15",
|
||||
"tailwindcss": "^3.2.7"
|
||||
},
|
||||
"prettier": {
|
||||
"printWidth": 160,
|
||||
"goTemplateBracketSpacing": true,
|
||||
"singleQuote": true,
|
||||
"plugins": ["prettier-plugin-go-template"],
|
||||
"overrides": [
|
||||
{
|
||||
"files": [
|
||||
"*.html"
|
||||
],
|
||||
"options": {
|
||||
"parser": "go-template"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -1,379 +0,0 @@
|
|||
{{ define "title" }}
|
||||
{{ .Title }}
|
||||
{{ end }}
|
||||
|
||||
{{ define "content" }}
|
||||
<div class="grid gap-10">
|
||||
{{ if .Weather.Icon }}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" style="display: none">
|
||||
<symbol id="01d" viewBox="0 0 16 16">
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M8 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM8 0a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 0zm0 13a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 13zm8-5a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2a.5.5 0 0 1 .5.5zM3 8a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2A.5.5 0 0 1 3 8zm10.657-5.657a.5.5 0 0 1 0 .707l-1.414 1.415a.5.5 0 1 1-.707-.708l1.414-1.414a.5.5 0 0 1 .707 0zm-9.193 9.193a.5.5 0 0 1 0 .707L3.05 13.657a.5.5 0 0 1-.707-.707l1.414-1.414a.5.5 0 0 1 .707 0zm9.193 2.121a.5.5 0 0 1-.707 0l-1.414-1.414a.5.5 0 0 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .707zM4.464 4.465a.5.5 0 0 1-.707 0L2.343 3.05a.5.5 0 1 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .708z"
|
||||
/>
|
||||
</symbol>
|
||||
<symbol id="01n" viewBox="0 0 16 16">
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M6 .278a.768.768 0 0 1 .08.858 7.208 7.208 0 0 0-.878 3.46c0 4.021 3.278 7.277 7.318 7.277.527 0 1.04-.055 1.533-.16a.787.787 0 0 1 .81.316.733.733 0 0 1-.031.893A8.349 8.349 0 0 1 8.344 16C3.734 16 0 12.286 0 7.71 0 4.266 2.114 1.312 5.124.06A.752.752 0 0 1 6 .278z"
|
||||
/>
|
||||
</symbol>
|
||||
<symbol id="02d" viewBox="0 0 16 16">
|
||||
<path fill="currentColor" d="M11.473 11a4.5 4.5 0 0 0-8.72-.99A3 3 0 0 0 3 16h8.5a2.5 2.5 0 0 0 0-5h-.027z" />
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M10.5 1.5a.5.5 0 0 0-1 0v1a.5.5 0 0 0 1 0v-1zm3.743 1.964a.5.5 0 1 0-.707-.707l-.708.707a.5.5 0 0 0 .708.708l.707-.708zm-7.779-.707a.5.5 0 0 0-.707.707l.707.708a.5.5 0 1 0 .708-.708l-.708-.707zm1.734 3.374a2 2 0 1 1 3.296 2.198c.199.281.372.582.516.898a3 3 0 1 0-4.84-3.225c.352.011.696.055 1.028.129zm4.484 4.074c.6.215 1.125.59 1.522 1.072a.5.5 0 0 0 .039-.742l-.707-.707a.5.5 0 0 0-.854.377zM14.5 6.5a.5.5 0 0 0 0 1h1a.5.5 0 0 0 0-1h-1z"
|
||||
/>
|
||||
</symbol>
|
||||
<symbol id="02n" viewBox="0 0 16 16">
|
||||
<path fill="currentColor" d="M11.473 11a4.5 4.5 0 0 0-8.72-.99A3 3 0 0 0 3 16h8.5a2.5 2.5 0 0 0 0-5h-.027z" />
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M11.286 1.778a.5.5 0 0 0-.565-.755 4.595 4.595 0 0 0-3.18 5.003 5.46 5.46 0 0 1 1.055.209A3.603 3.603 0 0 1 9.83 2.617a4.593 4.593 0 0 0 4.31 5.744 3.576 3.576 0 0 1-2.241.634c.162.317.295.652.394 1a4.59 4.59 0 0 0 3.624-2.04.5.5 0 0 0-.565-.755 3.593 3.593 0 0 1-4.065-5.422z"
|
||||
/>
|
||||
</symbol>
|
||||
<symbol id="03d" viewBox="0 0 16 16">
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M4.406 3.342A5.53 5.53 0 0 1 8 2c2.69 0 4.923 2 5.166 4.579C14.758 6.804 16 8.137 16 9.773 16 11.569 14.502 13 12.687 13H3.781C1.708 13 0 11.366 0 9.318c0-1.763 1.266-3.223 2.942-3.593.143-.863.698-1.723 1.464-2.383z"
|
||||
/>
|
||||
</symbol>
|
||||
<symbol id="03n" viewBox="0 0 16 16">
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M4.406 3.342A5.53 5.53 0 0 1 8 2c2.69 0 4.923 2 5.166 4.579C14.758 6.804 16 8.137 16 9.773 16 11.569 14.502 13 12.687 13H3.781C1.708 13 0 11.366 0 9.318c0-1.763 1.266-3.223 2.942-3.593.143-.863.698-1.723 1.464-2.383z"
|
||||
/>
|
||||
</symbol>
|
||||
<symbol id="04d" viewBox="0 0 16 16">
|
||||
<path fill="currentColor" d="M11.473 9a4.5 4.5 0 0 0-8.72-.99A3 3 0 0 0 3 14h8.5a2.5 2.5 0 1 0-.027-5z" />
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M14.544 9.772a3.506 3.506 0 0 0-2.225-1.676 5.502 5.502 0 0 0-6.337-4.002 4.002 4.002 0 0 1 7.392.91 2.5 2.5 0 0 1 1.17 4.769z"
|
||||
/>
|
||||
</symbol>
|
||||
<symbol id="04n" viewBox="0 0 16 16">
|
||||
<path fill="currentColor" d="M11.473 9a4.5 4.5 0 0 0-8.72-.99A3 3 0 0 0 3 14h8.5a2.5 2.5 0 1 0-.027-5z" />
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M14.544 9.772a3.506 3.506 0 0 0-2.225-1.676 5.502 5.502 0 0 0-6.337-4.002 4.002 4.002 0 0 1 7.392.91 2.5 2.5 0 0 1 1.17 4.769z"
|
||||
/>
|
||||
</symbol>
|
||||
<symbol id="09d" viewBox="0 0 16 16">
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M4.158 12.025a.5.5 0 0 1 .316.633l-.5 1.5a.5.5 0 0 1-.948-.316l.5-1.5a.5.5 0 0 1 .632-.317zm6 0a.5.5 0 0 1 .316.633l-.5 1.5a.5.5 0 0 1-.948-.316l.5-1.5a.5.5 0 0 1 .632-.317zm-3.5 1.5a.5.5 0 0 1 .316.633l-.5 1.5a.5.5 0 0 1-.948-.316l.5-1.5a.5.5 0 0 1 .632-.317zm6 0a.5.5 0 0 1 .316.633l-.5 1.5a.5.5 0 1 1-.948-.316l.5-1.5a.5.5 0 0 1 .632-.317zm.747-8.498a5.001 5.001 0 0 0-9.499-1.004A3.5 3.5 0 1 0 3.5 11H13a3 3 0 0 0 .405-5.973z"
|
||||
/>
|
||||
</symbol>
|
||||
<symbol id="09n" viewBox="0 0 16 16">
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M4.158 12.025a.5.5 0 0 1 .316.633l-.5 1.5a.5.5 0 0 1-.948-.316l.5-1.5a.5.5 0 0 1 .632-.317zm6 0a.5.5 0 0 1 .316.633l-.5 1.5a.5.5 0 0 1-.948-.316l.5-1.5a.5.5 0 0 1 .632-.317zm-3.5 1.5a.5.5 0 0 1 .316.633l-.5 1.5a.5.5 0 0 1-.948-.316l.5-1.5a.5.5 0 0 1 .632-.317zm6 0a.5.5 0 0 1 .316.633l-.5 1.5a.5.5 0 1 1-.948-.316l.5-1.5a.5.5 0 0 1 .632-.317zm.747-8.498a5.001 5.001 0 0 0-9.499-1.004A3.5 3.5 0 1 0 3.5 11H13a3 3 0 0 0 .405-5.973z"
|
||||
/>
|
||||
</symbol>
|
||||
<symbol id="10d" viewBox="0 0 16 16">
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M4.158 12.025a.5.5 0 0 1 .316.633l-.5 1.5a.5.5 0 1 1-.948-.316l.5-1.5a.5.5 0 0 1 .632-.317zm3 0a.5.5 0 0 1 .316.633l-1 3a.5.5 0 1 1-.948-.316l1-3a.5.5 0 0 1 .632-.317zm3 0a.5.5 0 0 1 .316.633l-.5 1.5a.5.5 0 1 1-.948-.316l.5-1.5a.5.5 0 0 1 .632-.317zm3 0a.5.5 0 0 1 .316.633l-1 3a.5.5 0 1 1-.948-.316l1-3a.5.5 0 0 1 .632-.317zm.247-6.998a5.001 5.001 0 0 0-9.499-1.004A3.5 3.5 0 1 0 3.5 11H13a3 3 0 0 0 .405-5.973z"
|
||||
/>
|
||||
</symbol>
|
||||
<symbol id="10n" viewBox="0 0 16 16">
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M4.158 12.025a.5.5 0 0 1 .316.633l-.5 1.5a.5.5 0 1 1-.948-.316l.5-1.5a.5.5 0 0 1 .632-.317zm3 0a.5.5 0 0 1 .316.633l-1 3a.5.5 0 1 1-.948-.316l1-3a.5.5 0 0 1 .632-.317zm3 0a.5.5 0 0 1 .316.633l-.5 1.5a.5.5 0 1 1-.948-.316l.5-1.5a.5.5 0 0 1 .632-.317zm3 0a.5.5 0 0 1 .316.633l-1 3a.5.5 0 1 1-.948-.316l1-3a.5.5 0 0 1 .632-.317zm.247-6.998a5.001 5.001 0 0 0-9.499-1.004A3.5 3.5 0 1 0 3.5 11H13a3 3 0 0 0 .405-5.973z"
|
||||
/>
|
||||
</symbol>
|
||||
<symbol id="11d" viewBox="0 0 16 16">
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M2.658 11.026a.5.5 0 0 1 .316.632l-.5 1.5a.5.5 0 1 1-.948-.316l.5-1.5a.5.5 0 0 1 .632-.316zm9.5 0a.5.5 0 0 1 .316.632l-.5 1.5a.5.5 0 0 1-.948-.316l.5-1.5a.5.5 0 0 1 .632-.316zm-7.5 1.5a.5.5 0 0 1 .316.632l-.5 1.5a.5.5 0 1 1-.948-.316l.5-1.5a.5.5 0 0 1 .632-.316zm9.5 0a.5.5 0 0 1 .316.632l-.5 1.5a.5.5 0 0 1-.948-.316l.5-1.5a.5.5 0 0 1 .632-.316zm-7.105-1.25A.5.5 0 0 1 7.5 11h1a.5.5 0 0 1 .474.658l-.28.842H9.5a.5.5 0 0 1 .39.812l-2 2.5a.5.5 0 0 1-.875-.433L7.36 14H6.5a.5.5 0 0 1-.447-.724l1-2zm6.352-7.249a5.001 5.001 0 0 0-9.499-1.004A3.5 3.5 0 1 0 3.5 10H13a3 3 0 0 0 .405-5.973z"
|
||||
/>
|
||||
</symbol>
|
||||
<symbol id="11n" viewBox="0 0 16 16">
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M2.658 11.026a.5.5 0 0 1 .316.632l-.5 1.5a.5.5 0 1 1-.948-.316l.5-1.5a.5.5 0 0 1 .632-.316zm9.5 0a.5.5 0 0 1 .316.632l-.5 1.5a.5.5 0 0 1-.948-.316l.5-1.5a.5.5 0 0 1 .632-.316zm-7.5 1.5a.5.5 0 0 1 .316.632l-.5 1.5a.5.5 0 1 1-.948-.316l.5-1.5a.5.5 0 0 1 .632-.316zm9.5 0a.5.5 0 0 1 .316.632l-.5 1.5a.5.5 0 0 1-.948-.316l.5-1.5a.5.5 0 0 1 .632-.316zm-7.105-1.25A.5.5 0 0 1 7.5 11h1a.5.5 0 0 1 .474.658l-.28.842H9.5a.5.5 0 0 1 .39.812l-2 2.5a.5.5 0 0 1-.875-.433L7.36 14H6.5a.5.5 0 0 1-.447-.724l1-2zm6.352-7.249a5.001 5.001 0 0 0-9.499-1.004A3.5 3.5 0 1 0 3.5 10H13a3 3 0 0 0 .405-5.973z"
|
||||
/>
|
||||
</symbol>
|
||||
<symbol id="13d" viewBox="0 0 16 16">
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M2.625 11.5a.25.25 0 0 1 .25.25v.57l.501-.287a.25.25 0 0 1 .248.434l-.495.283.495.283a.25.25 0 0 1-.248.434l-.501-.286v.569a.25.25 0 1 1-.5 0v-.57l-.501.287a.25.25 0 0 1-.248-.434l.495-.283-.495-.283a.25.25 0 0 1 .248-.434l.501.286v-.569a.25.25 0 0 1 .25-.25zm2.75 2a.25.25 0 0 1 .25.25v.57l.5-.287a.25.25 0 0 1 .249.434l-.495.283.495.283a.25.25 0 0 1-.248.434l-.501-.286v.569a.25.25 0 1 1-.5 0v-.57l-.501.287a.25.25 0 0 1-.248-.434l.495-.283-.495-.283a.25.25 0 0 1 .248-.434l.501.286v-.569a.25.25 0 0 1 .25-.25zm5.5 0a.25.25 0 0 1 .25.25v.57l.5-.287a.25.25 0 0 1 .249.434l-.495.283.495.283a.25.25 0 0 1-.248.434l-.501-.286v.569a.25.25 0 0 1-.5 0v-.57l-.501.287a.25.25 0 0 1-.248-.434l.495-.283-.495-.283a.25.25 0 0 1 .248-.434l.501.286v-.569a.25.25 0 0 1 .25-.25zm-2.75-2a.25.25 0 0 1 .25.25v.57l.5-.287a.25.25 0 0 1 .249.434l-.495.283.495.283a.25.25 0 0 1-.248.434l-.501-.286v.569a.25.25 0 1 1-.5 0v-.57l-.501.287a.25.25 0 0 1-.248-.434l.495-.283-.495-.283a.25.25 0 0 1 .248-.434l.501.286v-.569a.25.25 0 0 1 .25-.25zm5.5 0a.25.25 0 0 1 .25.25v.57l.5-.287a.25.25 0 0 1 .249.434l-.495.283.495.283a.25.25 0 0 1-.248.434l-.501-.286v.569a.25.25 0 0 1-.5 0v-.57l-.501.287a.25.25 0 1 1-.248-.434l.495-.283-.495-.283a.25.25 0 0 1 .248-.434l.501.286v-.569a.25.25 0 0 1 .25-.25zm-.22-7.223a5.001 5.001 0 0 0-9.499-1.004A3.5 3.5 0 1 0 3.5 10.25H13a3 3 0 0 0 .405-5.973z"
|
||||
/>
|
||||
</symbol>
|
||||
<symbol id="13n" viewBox="0 0 16 16">
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M2.625 11.5a.25.25 0 0 1 .25.25v.57l.501-.287a.25.25 0 0 1 .248.434l-.495.283.495.283a.25.25 0 0 1-.248.434l-.501-.286v.569a.25.25 0 1 1-.5 0v-.57l-.501.287a.25.25 0 0 1-.248-.434l.495-.283-.495-.283a.25.25 0 0 1 .248-.434l.501.286v-.569a.25.25 0 0 1 .25-.25zm2.75 2a.25.25 0 0 1 .25.25v.57l.5-.287a.25.25 0 0 1 .249.434l-.495.283.495.283a.25.25 0 0 1-.248.434l-.501-.286v.569a.25.25 0 1 1-.5 0v-.57l-.501.287a.25.25 0 0 1-.248-.434l.495-.283-.495-.283a.25.25 0 0 1 .248-.434l.501.286v-.569a.25.25 0 0 1 .25-.25zm5.5 0a.25.25 0 0 1 .25.25v.57l.5-.287a.25.25 0 0 1 .249.434l-.495.283.495.283a.25.25 0 0 1-.248.434l-.501-.286v.569a.25.25 0 0 1-.5 0v-.57l-.501.287a.25.25 0 0 1-.248-.434l.495-.283-.495-.283a.25.25 0 0 1 .248-.434l.501.286v-.569a.25.25 0 0 1 .25-.25zm-2.75-2a.25.25 0 0 1 .25.25v.57l.5-.287a.25.25 0 0 1 .249.434l-.495.283.495.283a.25.25 0 0 1-.248.434l-.501-.286v.569a.25.25 0 1 1-.5 0v-.57l-.501.287a.25.25 0 0 1-.248-.434l.495-.283-.495-.283a.25.25 0 0 1 .248-.434l.501.286v-.569a.25.25 0 0 1 .25-.25zm5.5 0a.25.25 0 0 1 .25.25v.57l.5-.287a.25.25 0 0 1 .249.434l-.495.283.495.283a.25.25 0 0 1-.248.434l-.501-.286v.569a.25.25 0 0 1-.5 0v-.57l-.501.287a.25.25 0 1 1-.248-.434l.495-.283-.495-.283a.25.25 0 0 1 .248-.434l.501.286v-.569a.25.25 0 0 1 .25-.25zm-.22-7.223a5.001 5.001 0 0 0-9.499-1.004A3.5 3.5 0 1 0 3.5 10.25H13a3 3 0 0 0 .405-5.973z"
|
||||
/>
|
||||
</symbol>
|
||||
<symbol id="50d" viewBox="0 0 16 16">
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M8.5 2a5.001 5.001 0 0 1 4.905 4.027A3 3 0 0 1 13 12H3.5A3.5 3.5 0 0 1 .035 9H5.5a.5.5 0 0 0 0-1H.035a3.5 3.5 0 0 1 3.871-2.977A5.001 5.001 0 0 1 8.5 2zm-6 8a.5.5 0 0 0 0 1h9a.5.5 0 0 0 0-1h-9zM0 13.5a.5.5 0 0 1 .5-.5h9a.5.5 0 0 1 0 1h-9a.5.5 0 0 1-.5-.5z"
|
||||
/>
|
||||
</symbol>
|
||||
<symbol id="50n" viewBox="0 0 16 16">
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M8.5 2a5.001 5.001 0 0 1 4.905 4.027A3 3 0 0 1 13 12H3.5A3.5 3.5 0 0 1 .035 9H5.5a.5.5 0 0 0 0-1H.035a3.5 3.5 0 0 1 3.871-2.977A5.001 5.001 0 0 1 8.5 2zm-6 8a.5.5 0 0 0 0 1h9a.5.5 0 0 0 0-1h-9zM0 13.5a.5.5 0 0 1 .5-.5h9a.5.5 0 0 1 0 1h-9a.5.5 0 0 1-.5-.5z"
|
||||
/>
|
||||
</symbol>
|
||||
<symbol id="sunset" viewBox="0 0 16 16">
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M7.646 4.854a.5.5 0 0 0 .708 0l1.5-1.5a.5.5 0 0 0-.708-.708l-.646.647V1.5a.5.5 0 0 0-1 0v1.793l-.646-.647a.5.5 0 1 0-.708.708l1.5 1.5zm-5.303-.51a.5.5 0 0 1 .707 0l1.414 1.413a.5.5 0 0 1-.707.707L2.343 5.05a.5.5 0 0 1 0-.707zm11.314 0a.5.5 0 0 1 0 .706l-1.414 1.414a.5.5 0 1 1-.707-.707l1.414-1.414a.5.5 0 0 1 .707 0zM11.709 11.5a4 4 0 1 0-7.418 0H.5a.5.5 0 0 0 0 1h15a.5.5 0 0 0 0-1h-3.79zM0 10a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 0 1h-2A.5.5 0 0 1 0 10zm13 0a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1-.5-.5z"
|
||||
/>
|
||||
</symbol>
|
||||
<symbol id="sunrise" viewBox="0 0 16 16">
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M7.646 1.146a.5.5 0 0 1 .708 0l1.5 1.5a.5.5 0 0 1-.708.708L8.5 2.707V4.5a.5.5 0 0 1-1 0V2.707l-.646.647a.5.5 0 1 1-.708-.708l1.5-1.5zM2.343 4.343a.5.5 0 0 1 .707 0l1.414 1.414a.5.5 0 0 1-.707.707L2.343 5.05a.5.5 0 0 1 0-.707zm11.314 0a.5.5 0 0 1 0 .707l-1.414 1.414a.5.5 0 1 1-.707-.707l1.414-1.414a.5.5 0 0 1 .707 0zM11.709 11.5a4 4 0 1 0-7.418 0H.5a.5.5 0 0 0 0 1h15a.5.5 0 0 0 0-1h-3.79zM0 10a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 0 1h-2A.5.5 0 0 1 0 10zm13 0a.5.5 0 0 1 .5-.5h2a.5.5 0 0 1 0 1h-2a.5.5 0 0 1-.5-.5z"
|
||||
/>
|
||||
</symbol>
|
||||
<symbol id="humidity" viewBox="0 0 16 16">
|
||||
<path
|
||||
fill="currentColor"
|
||||
fill-rule="evenodd"
|
||||
d="M7.21.8C7.69.295 8 0 8 0c.109.363.234.708.371 1.038.812 1.946 2.073 3.35 3.197 4.6C12.878 7.096 14 8.345 14 10a6 6 0 0 1-12 0C2 6.668 5.58 2.517 7.21.8zm.413 1.021A31.25 31.25 0 0 0 5.794 3.99c-.726.95-1.436 2.008-1.96 3.07C3.304 8.133 3 9.138 3 10c0 0 2.5 1.5 5 .5s5-.5 5-.5c0-1.201-.796-2.157-2.181-3.7l-.03-.032C9.75 5.11 8.5 3.72 7.623 1.82z"
|
||||
/>
|
||||
<path fill="currentColor" fill-rule="evenodd" d="M4.553 7.776c.82-1.641 1.717-2.753 2.093-3.13l.708.708c-.29.29-1.128 1.311-1.907 2.87l-.894-.448z" />
|
||||
</symbol>
|
||||
<symbol id="quote" viewBox="0 0 16 16">
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M16 8c0 3.866-3.582 7-8 7a9.06 9.06 0 0 1-2.347-.306c-.584.296-1.925.864-4.181 1.234-.2.032-.352-.176-.273-.362.354-.836.674-1.95.77-2.966C.744 11.37 0 9.76 0 8c0-3.866 3.582-7 8-7s8 3.134 8 7zM7.194 6.766a1.688 1.688 0 0 0-.227-.272 1.467 1.467 0 0 0-.469-.324l-.008-.004A1.785 1.785 0 0 0 5.734 6C4.776 6 4 6.746 4 7.667c0 .92.776 1.666 1.734 1.666.343 0 .662-.095.931-.26-.137.389-.39.804-.81 1.22a.405.405 0 0 0 .011.59c.173.16.447.155.614-.01 1.334-1.329 1.37-2.758.941-3.706a2.461 2.461 0 0 0-.227-.4zM11 9.073c-.136.389-.39.804-.81 1.22a.405.405 0 0 0 .012.59c.172.16.446.155.613-.01 1.334-1.329 1.37-2.758.942-3.706a2.466 2.466 0 0 0-.228-.4 1.686 1.686 0 0 0-.227-.273 1.466 1.466 0 0 0-.469-.324l-.008-.004A1.785 1.785 0 0 0 10.07 6c-.957 0-1.734.746-1.734 1.667 0 .92.777 1.666 1.734 1.666.343 0 .662-.095.931-.26z"
|
||||
/>
|
||||
</symbol>
|
||||
</svg>
|
||||
|
||||
<div class="flex items-center select-none">
|
||||
<svg class="h-12 w-12 shrink-0 mr-4 md:w-14 md:h-14">
|
||||
<use id="weatherIcon" xlink:href="#{{ .Weather.Icon }}"></use>
|
||||
</svg>
|
||||
<div>
|
||||
<div class="text-4xl md:text-4xl"><span id="weatherTemp">{{ .Weather.Temp }}</span> {{ .Weather.Units }}</div>
|
||||
<div class="flex items-center gap-5 text-xs">
|
||||
<div class="flex items-center">
|
||||
<svg class="extra-icon">
|
||||
<use xlink:href="#quote"></use>
|
||||
</svg>
|
||||
<div id="weatherDescription" class="extra-info">{{ .Weather.Description }}</div>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<svg class="extra-icon">
|
||||
<use xlink:href="#humidity"></use>
|
||||
</svg>
|
||||
<div id="weatherHumidity" class="extra-info">{{ .Weather.Humidity }}%</div>
|
||||
</div>
|
||||
<div class="hidden sm:flex items-center">
|
||||
<svg class="extra-sun-icon">
|
||||
<use xlink:href="#sunrise"></use>
|
||||
</svg>
|
||||
<div id="weatherSunrise" class="extra-info">{{ .Weather.Sunrise }}</div>
|
||||
</div>
|
||||
<div class="hidden sm:flex items-center">
|
||||
<svg class="extra-sun-icon">
|
||||
<use xlink:href="#sunset"></use>
|
||||
</svg>
|
||||
<div id="weatherSunset" class="extra-info">{{ .Weather.Sunset }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
{{ if .System.Static.Host.Architecture }}
|
||||
|
||||
<svg xmlns="http://www.w3.org/2000/svg" style="display: none">
|
||||
<symbol id="cpu" viewBox="0 0 16 16">
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M5 0a.5.5 0 0 1 .5.5V2h1V.5a.5.5 0 0 1 1 0V2h1V.5a.5.5 0 0 1 1 0V2h1V.5a.5.5 0 0 1 1 0V2A2.5 2.5 0 0 1 14 4.5h1.5a.5.5 0 0 1 0 1H14v1h1.5a.5.5 0 0 1 0 1H14v1h1.5a.5.5 0 0 1 0 1H14v1h1.5a.5.5 0 0 1 0 1H14a2.5 2.5 0 0 1-2.5 2.5v1.5a.5.5 0 0 1-1 0V14h-1v1.5a.5.5 0 0 1-1 0V14h-1v1.5a.5.5 0 0 1-1 0V14h-1v1.5a.5.5 0 0 1-1 0V14A2.5 2.5 0 0 1 2 11.5H.5a.5.5 0 0 1 0-1H2v-1H.5a.5.5 0 0 1 0-1H2v-1H.5a.5.5 0 0 1 0-1H2v-1H.5a.5.5 0 0 1 0-1H2A2.5 2.5 0 0 1 4.5 2V.5A.5.5 0 0 1 5 0zm-.5 3A1.5 1.5 0 0 0 3 4.5v7A1.5 1.5 0 0 0 4.5 13h7a1.5 1.5 0 0 0 1.5-1.5v-7A1.5 1.5 0 0 0 11.5 3h-7zM5 6.5A1.5 1.5 0 0 1 6.5 5h3A1.5 1.5 0 0 1 11 6.5v3A1.5 1.5 0 0 1 9.5 11h-3A1.5 1.5 0 0 1 5 9.5v-3zM6.5 6a.5.5 0 0 0-.5.5v3a.5.5 0 0 0 .5.5h3a.5.5 0 0 0 .5-.5v-3a.5.5 0 0 0-.5-.5h-3z"
|
||||
/>
|
||||
</symbol>
|
||||
<symbol id="ram" viewBox="0 0 16 16">
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M1 3a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h4.586a1 1 0 0 0 .707-.293l.353-.353a.5.5 0 0 1 .708 0l.353.353a1 1 0 0 0 .707.293H15a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H1Zm.5 1h3a.5.5 0 0 1 .5.5v4a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-4a.5.5 0 0 1 .5-.5Zm5 0h3a.5.5 0 0 1 .5.5v4a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-4a.5.5 0 0 1 .5-.5Zm4.5.5a.5.5 0 0 1 .5-.5h3a.5.5 0 0 1 .5.5v4a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-4ZM2 10v2H1v-2h1Zm2 0v2H3v-2h1Zm2 0v2H5v-2h1Zm3 0v2H8v-2h1Zm2 0v2h-1v-2h1Zm2 0v2h-1v-2h1Zm2 0v2h-1v-2h1Z"
|
||||
/>
|
||||
</symbol>
|
||||
<symbol id="disk" viewBox="0 0 16 16">
|
||||
<path fill="currentColor" d="M4.5 11a.5.5 0 1 0 0-1 .5.5 0 0 0 0 1zM3 10.5a.5.5 0 1 1-1 0 .5.5 0 0 1 1 0z" />
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M16 11a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V9.51c0-.418.105-.83.305-1.197l2.472-4.531A1.5 1.5 0 0 1 4.094 3h7.812a1.5 1.5 0 0 1 1.317.782l2.472 4.53c.2.368.305.78.305 1.198V11zM3.655 4.26 1.592 8.043C1.724 8.014 1.86 8 2 8h12c.14 0 .276.014.408.042L12.345 4.26a.5.5 0 0 0-.439-.26H4.094a.5.5 0 0 0-.44.26zM1 10v1a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-1a1 1 0 0 0-1-1H2a1 1 0 0 0-1 1z"
|
||||
/>
|
||||
</symbol>
|
||||
<symbol id="server" viewBox="0 0 16 16">
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M11.5 2a.5.5 0 0 1 .5.5v7a.5.5 0 0 1-1 0v-7a.5.5 0 0 1 .5-.5Zm2 0a.5.5 0 0 1 .5.5v7a.5.5 0 0 1-1 0v-7a.5.5 0 0 1 .5-.5Zm-10 8a.5.5 0 0 0 0 1h6a.5.5 0 0 0 0-1h-6Zm0 2a.5.5 0 0 0 0 1h6a.5.5 0 0 0 0-1h-6ZM5 3a1 1 0 0 0-1 1h-.5a.5.5 0 0 0 0 1H4v1h-.5a.5.5 0 0 0 0 1H4a1 1 0 0 0 1 1v.5a.5.5 0 0 0 1 0V8h1v.5a.5.5 0 0 0 1 0V8a1 1 0 0 0 1-1h.5a.5.5 0 0 0 0-1H9V5h.5a.5.5 0 0 0 0-1H9a1 1 0 0 0-1-1v-.5a.5.5 0 0 0-1 0V3H6v-.5a.5.5 0 0 0-1 0V3Zm0 1h3v3H5V4Zm6.5 7a.5.5 0 0 0-.5.5v1a.5.5 0 0 0 .5.5h2a.5.5 0 0 0 .5-.5v-1a.5.5 0 0 0-.5-.5h-2Z"
|
||||
/>
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M1 2a2 2 0 0 1 2-2h11a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2v-2H.5a.5.5 0 0 1-.5-.5v-1A.5.5 0 0 1 .5 9H1V8H.5a.5.5 0 0 1-.5-.5v-1A.5.5 0 0 1 .5 6H1V5H.5a.5.5 0 0 1-.5-.5v-2A.5.5 0 0 1 .5 2H1Zm1 11a1 1 0 0 0 1 1h11a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1v11Z"
|
||||
/>
|
||||
</symbol>
|
||||
</svg>
|
||||
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-4 gap-3 select-none">
|
||||
<div class="flex items-center">
|
||||
<svg class="system-icon">
|
||||
<use xlink:href="#cpu"></use>
|
||||
</svg>
|
||||
<div class="w-full truncate">
|
||||
<div class="extra-info">{{ .System.Static.CPU.Threads }}</div>
|
||||
<div class="truncate">{{ .System.Static.CPU.Name }}</div>
|
||||
<div class="progress-bar-wrapper">
|
||||
<div id="systemCpuPercentage" class="progress-bar" style="width: {{ .System.Live.CPU }}%"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<svg class="system-icon">
|
||||
<use xlink:href="#ram"></use>
|
||||
</svg>
|
||||
<div class="w-full truncate">
|
||||
<div class="extra-info">{{ .System.Static.Ram.Swap }}</div>
|
||||
<div class="truncate"><span id="systemRamValue">{{ .System.Live.Ram.Value }}</span> / {{ .System.Static.Ram.Total }}</div>
|
||||
<div class="progress-bar-wrapper">
|
||||
<div id="systemRamPercentage" class="progress-bar" style="width: {{ .System.Live.Ram.Percentage }}%"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<svg class="system-icon">
|
||||
<use xlink:href="#disk"></use>
|
||||
</svg>
|
||||
<div class="w-full truncate">
|
||||
<div class="extra-info">{{ .System.Static.Disk.Partitions }}</div>
|
||||
<div class="truncate"><span id="systemDiskValue">{{ .System.Live.Disk.Value }}</span> / {{ .System.Static.Disk.Total }}</div>
|
||||
<div class="progress-bar-wrapper">
|
||||
<div id="systemDiskPercentage" class="progress-bar" style="width: {{ .System.Live.Disk.Percentage }}%"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center">
|
||||
<svg class="system-icon">
|
||||
<use xlink:href="#server"></use>
|
||||
</svg>
|
||||
<div class="w-full truncate">
|
||||
<div class="extra-info">{{ .System.Static.Host.Architecture }}</div>
|
||||
<div class="flex items-center gap-2 truncate">
|
||||
<div class="truncate">
|
||||
<span><span id="uptimeDays">{{ .System.Live.Uptime.Days }}</span> days</span>
|
||||
<span class="countdown"><span id="uptimeHours" style="--value:{{ .System.Live.Uptime.Hours }};"></span></span> hours
|
||||
<span class="countdown"><span id="uptimeMinutes" style="--value:{{ .System.Live.Uptime.Minutes }};"></span></span> min
|
||||
<span class="countdown"><span id="uptimeSeconds" style="--value:{{ .System.Live.Uptime.Seconds }};"></span></span> sec
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress-bar-wrapper">
|
||||
<div id="systemUptimePercentage" class="progress-bar" style="width: {{ .System.Live.Uptime.Percentage }}%"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
|
||||
<div class="grid gap-4">
|
||||
{{ range .Parsed.Applications }}
|
||||
<div class="grid gap-2">
|
||||
{{ if .Category }}
|
||||
<div class="heading">{{ .Category }}</div>
|
||||
{{ end }}
|
||||
<div class="grid-apps">
|
||||
{{ range .Entries }}
|
||||
<a href="{{ .URL }}" class="bookmark-link flex items-center hover-effect">
|
||||
<div
|
||||
class="{{ backgroundColor .Background }}img rounded w-8 h-8 bg-contain bg-center bg-origin-content bg-no-repeat opacity-90"
|
||||
style="background-image: url({{ .Icon }})"
|
||||
></div>
|
||||
<div class="uppercase truncate ml-2">{{ .Name }}</div>
|
||||
</a>
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
|
||||
<div class="grid-apps">
|
||||
{{ range .Parsed.Links }}
|
||||
<div class="flex flex-col gap-2">
|
||||
{{ if .Category }}
|
||||
<div class="heading">{{ .Category }}</div>
|
||||
{{ end }}
|
||||
{{ range .Entries }}
|
||||
<a href="{{ .URL }}" class="hover-effect">
|
||||
<div class="uppercase truncate">{{ .Name }}</div>
|
||||
</a>
|
||||
{{ end }}
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ define "js" }}
|
||||
<script>
|
||||
let systemSSESource = null;
|
||||
let weatherSSESource = null;
|
||||
addEventListener('beforeunload', () => {
|
||||
systemSSESource && systemSSESource.close();
|
||||
weatherSSESource && weatherSSESource.close();
|
||||
});
|
||||
systemSSESource = new EventSource('/sse?stream=system');
|
||||
systemSSESource.onmessage = (e) => {
|
||||
const parsed = JSON.parse(e.data);
|
||||
replaceSystem(parsed);
|
||||
};
|
||||
weatherSSESource = new EventSource('/sse?stream=weather');
|
||||
weatherSSESource.onmessage = (e) => {
|
||||
const parsed = JSON.parse(e.data);
|
||||
replaceWeather(parsed);
|
||||
};
|
||||
|
||||
// weather elements
|
||||
const weatherIcon = document.getElementById('weatherIcon');
|
||||
const weatherTemp = document.getElementById('weatherTemp');
|
||||
const weatherDescription = document.getElementById('weatherDescription');
|
||||
const weatherHumidity = document.getElementById('weatherHumidity');
|
||||
const weatherSunrise = document.getElementById('weatherSunrise');
|
||||
const weatherSunset = document.getElementById('weatherSunset');
|
||||
|
||||
// system elements
|
||||
const systemCpuPercentage = document.getElementById('systemCpuPercentage');
|
||||
const systemRamPercentage = document.getElementById('systemRamPercentage');
|
||||
const systemRamValue = document.getElementById('systemRamValue');
|
||||
const systemDiskPercentage = document.getElementById('systemDiskPercentage');
|
||||
const systemDiskValue = document.getElementById('systemDiskValue');
|
||||
const systemUptimePercentage = document.getElementById('systemUptimePercentage');
|
||||
const uptimeDays = document.getElementById('uptimeDays');
|
||||
const uptimeHours = document.getElementById('uptimeHours');
|
||||
const uptimeMinutes = document.getElementById('uptimeMinutes');
|
||||
const uptimeSeconds = document.getElementById('uptimeSeconds');
|
||||
|
||||
function replaceWeather(parsed) {
|
||||
weatherIcon.setAttribute('xlink:href', '#' + parsed.icon);
|
||||
weatherTemp.innerText = parsed.temp;
|
||||
weatherDescription.innerText = parsed.description;
|
||||
weatherHumidity.innerText = parsed.humidity + '%';
|
||||
weatherSunrise.innerText = parsed.sunrise;
|
||||
weatherSunset.innerText = parsed.sunset;
|
||||
}
|
||||
|
||||
function replaceSystem(parsed) {
|
||||
systemCpuPercentage.style = 'width:' + parsed.cpu + '%';
|
||||
systemRamPercentage.style = 'width:' + parsed.ram.percentage + '%';
|
||||
systemRamValue.innerText = parsed.ram.value;
|
||||
systemDiskPercentage.style = 'width:' + parsed.disk.percentage + '%';
|
||||
systemDiskValue.innerText = parsed.disk.value;
|
||||
systemUptimePercentage.style = 'width:' + parsed.uptime.percentage + '%';
|
||||
uptimeDays.style = '--value:' + parsed.uptime.days;
|
||||
uptimeHours.style = '--value:' + parsed.uptime.hours;
|
||||
uptimeMinutes.style = '--value:' + parsed.uptime.minutes;
|
||||
uptimeSeconds.style = '--value:' + parsed.uptime.seconds;
|
||||
}
|
||||
</script>
|
||||
{{ end }}
|
|
@ -1,29 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>{{ block "title" . }}GoDash{{ end }}</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="description" content="A blazing fast start-page for services written in Go " />
|
||||
<meta name="theme-color" content="#d07915" />
|
||||
|
||||
<link rel="icon" type="image/x-icon" href="/static/favicon/favicon.ico" />
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/static/favicon/favicon-32x32.png" />
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/static/favicon/favicon-16x16.png" />
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/static/favicon/apple-touch-icon.png" />
|
||||
<link rel="manifest" href="/static/favicon/site.webmanifest" />
|
||||
<style>
|
||||
.bookmark-link:hover .img {
|
||||
opacity: 1;
|
||||
transition: opacity linear 0.15s;
|
||||
}
|
||||
</style>
|
||||
<link rel="stylesheet" href="/static/css/style.css?v={{ env "APP_VERSION" }}" />
|
||||
{{ block "style". }}{{ end }}
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="p-4 sm:p-6 lg:p-8 xl:container xl:py-12">{{ block "content" . }}{{ end }}</div>
|
||||
{{ block "js". }}{{ end }}
|
||||
</body>
|
||||
</html>
|
|
@ -7,34 +7,79 @@
|
|||
resolved "https://registry.yarnpkg.com/@alloc/quick-lru/-/quick-lru-5.2.0.tgz#7bf68b20c0a350f936915fcae06f58e32007ce30"
|
||||
integrity sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==
|
||||
|
||||
"@jridgewell/gen-mapping@^0.3.2":
|
||||
version "0.3.3"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098"
|
||||
integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==
|
||||
"@iconify-json/bi@^1.1.23":
|
||||
version "1.1.23"
|
||||
resolved "https://registry.yarnpkg.com/@iconify-json/bi/-/bi-1.1.23.tgz#e70433b04609e96c8e5152867a55f82988ae0e70"
|
||||
integrity sha512-1te+g9ZzI+PU1Lv6Xerd3XPXf4DE6g3TvDL2buIopTAfrauPHyXCHPFQMrzoQVNrVPCpN3rv3vBtJMPyBwJ9IA==
|
||||
dependencies:
|
||||
"@jridgewell/set-array" "^1.0.1"
|
||||
"@iconify/types" "*"
|
||||
|
||||
"@iconify-json/clarity@^1.1.12":
|
||||
version "1.1.12"
|
||||
resolved "https://registry.yarnpkg.com/@iconify-json/clarity/-/clarity-1.1.12.tgz#ef1c981324e6df074389eafde9895e14d400ab93"
|
||||
integrity sha512-Qho+7l2znCxMlmNfNRk3LFsXJZX1d8H8v9q+UIkzuiHuS4YI3tl5SpYrPQ4HdhGnzAJbOXhGBb1JPL+mgqc0Ow==
|
||||
dependencies:
|
||||
"@iconify/types" "*"
|
||||
|
||||
"@iconify-json/ri@^1.1.20":
|
||||
version "1.1.20"
|
||||
resolved "https://registry.yarnpkg.com/@iconify-json/ri/-/ri-1.1.20.tgz#6621dfc91fa119c1b941a0685d213f22480157ca"
|
||||
integrity sha512-yScIGjLFBCJKWKskQTWRjNI2Awoq+VRDkRxEsCQvSfdz41n+xkRtFG2K6J1OVI90ClRHfjFC8VJ2+WzxxyFjTQ==
|
||||
dependencies:
|
||||
"@iconify/types" "*"
|
||||
|
||||
"@iconify/tailwind@^0.1.4":
|
||||
version "0.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@iconify/tailwind/-/tailwind-0.1.4.tgz#c5baee6e863d01d7b1d5ff3f0c5cd4fc49b2c0c7"
|
||||
integrity sha512-U7RzcU2fkwOfMDsGQ3mtpLIaApSnqb+vgcJJknPPbg8/NF5s7tI1o5otEMfcpnLGk4PbYB8bxmKTz7IJVUlU2Q==
|
||||
dependencies:
|
||||
"@iconify/types" "^2.0.0"
|
||||
|
||||
"@iconify/types@*", "@iconify/types@^2.0.0":
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@iconify/types/-/types-2.0.0.tgz#ab0e9ea681d6c8a1214f30cd741fe3a20cc57f57"
|
||||
integrity sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==
|
||||
|
||||
"@isaacs/cliui@^8.0.2":
|
||||
version "8.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550"
|
||||
integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==
|
||||
dependencies:
|
||||
string-width "^5.1.2"
|
||||
string-width-cjs "npm:string-width@^4.2.0"
|
||||
strip-ansi "^7.0.1"
|
||||
strip-ansi-cjs "npm:strip-ansi@^6.0.1"
|
||||
wrap-ansi "^8.1.0"
|
||||
wrap-ansi-cjs "npm:wrap-ansi@^7.0.0"
|
||||
|
||||
"@jridgewell/gen-mapping@^0.3.2":
|
||||
version "0.3.5"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36"
|
||||
integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==
|
||||
dependencies:
|
||||
"@jridgewell/set-array" "^1.2.1"
|
||||
"@jridgewell/sourcemap-codec" "^1.4.10"
|
||||
"@jridgewell/trace-mapping" "^0.3.9"
|
||||
"@jridgewell/trace-mapping" "^0.3.24"
|
||||
|
||||
"@jridgewell/resolve-uri@^3.1.0":
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721"
|
||||
integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6"
|
||||
integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==
|
||||
|
||||
"@jridgewell/set-array@^1.0.1":
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72"
|
||||
integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==
|
||||
"@jridgewell/set-array@^1.2.1":
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280"
|
||||
integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==
|
||||
|
||||
"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14":
|
||||
version "1.4.15"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32"
|
||||
integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==
|
||||
|
||||
"@jridgewell/trace-mapping@^0.3.9":
|
||||
version "0.3.20"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz#72e45707cf240fa6b081d0366f8265b0cd10197f"
|
||||
integrity sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==
|
||||
"@jridgewell/trace-mapping@^0.3.24":
|
||||
version "0.3.25"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0"
|
||||
integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==
|
||||
dependencies:
|
||||
"@jridgewell/resolve-uri" "^3.1.0"
|
||||
"@jridgewell/sourcemap-codec" "^1.4.14"
|
||||
|
@ -60,6 +105,33 @@
|
|||
"@nodelib/fs.scandir" "2.1.5"
|
||||
fastq "^1.6.0"
|
||||
|
||||
"@pkgjs/parseargs@^0.11.0":
|
||||
version "0.11.0"
|
||||
resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33"
|
||||
integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==
|
||||
|
||||
ansi-regex@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
|
||||
integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
|
||||
|
||||
ansi-regex@^6.0.1:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a"
|
||||
integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==
|
||||
|
||||
ansi-styles@^4.0.0:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937"
|
||||
integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
|
||||
dependencies:
|
||||
color-convert "^2.0.1"
|
||||
|
||||
ansi-styles@^6.1.0:
|
||||
version "6.2.1"
|
||||
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5"
|
||||
integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==
|
||||
|
||||
any-promise@^1.0.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f"
|
||||
|
@ -78,18 +150,6 @@ arg@^5.0.2:
|
|||
resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c"
|
||||
integrity sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==
|
||||
|
||||
autoprefixer@^10.0.2:
|
||||
version "10.4.16"
|
||||
resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.16.tgz#fad1411024d8670880bdece3970aa72e3572feb8"
|
||||
integrity sha512-7vd3UC6xKp0HLfua5IjZlcXvGAGy7cBAXTg2lyQ/8WpNhd6SiZ8Be+xm3FyBSYJx5GKcpRCzBh7RH4/0dnY+uQ==
|
||||
dependencies:
|
||||
browserslist "^4.21.10"
|
||||
caniuse-lite "^1.0.30001538"
|
||||
fraction.js "^4.3.6"
|
||||
normalize-range "^0.1.2"
|
||||
picocolors "^1.0.0"
|
||||
postcss-value-parser "^4.2.0"
|
||||
|
||||
balanced-match@^1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
|
||||
|
@ -100,13 +160,12 @@ binary-extensions@^2.0.0:
|
|||
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
|
||||
integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
|
||||
|
||||
brace-expansion@^1.1.7:
|
||||
version "1.1.11"
|
||||
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
|
||||
integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
|
||||
brace-expansion@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae"
|
||||
integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==
|
||||
dependencies:
|
||||
balanced-match "^1.0.0"
|
||||
concat-map "0.0.1"
|
||||
|
||||
braces@^3.0.2, braces@~3.0.2:
|
||||
version "3.0.2"
|
||||
|
@ -115,30 +174,15 @@ braces@^3.0.2, braces@~3.0.2:
|
|||
dependencies:
|
||||
fill-range "^7.0.1"
|
||||
|
||||
browserslist@^4.21.10:
|
||||
version "4.22.1"
|
||||
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.22.1.tgz#ba91958d1a59b87dab6fed8dfbcb3da5e2e9c619"
|
||||
integrity sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==
|
||||
dependencies:
|
||||
caniuse-lite "^1.0.30001541"
|
||||
electron-to-chromium "^1.4.535"
|
||||
node-releases "^2.0.13"
|
||||
update-browserslist-db "^1.0.13"
|
||||
|
||||
camelcase-css@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5"
|
||||
integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==
|
||||
|
||||
caniuse-lite@^1.0.30001538, caniuse-lite@^1.0.30001541:
|
||||
version "1.0.30001554"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001554.tgz#ba80d88dff9acbc0cd4b7535fc30e0191c5e2e2a"
|
||||
integrity sha512-A2E3U//MBwbJVzebddm1YfNp7Nud5Ip+IPn4BozBmn4KqVX7AvluoIDFWjsv5OkGnKUXQVmMSoMKLa3ScCblcQ==
|
||||
|
||||
chokidar@^3.5.3:
|
||||
version "3.5.3"
|
||||
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd"
|
||||
integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b"
|
||||
integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==
|
||||
dependencies:
|
||||
anymatch "~3.1.2"
|
||||
braces "~3.0.2"
|
||||
|
@ -150,20 +194,31 @@ chokidar@^3.5.3:
|
|||
optionalDependencies:
|
||||
fsevents "~2.3.2"
|
||||
|
||||
colord@^2.9:
|
||||
version "2.9.3"
|
||||
resolved "https://registry.yarnpkg.com/colord/-/colord-2.9.3.tgz#4f8ce919de456f1d5c1c368c307fe20f3e59fb43"
|
||||
integrity sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==
|
||||
color-convert@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
|
||||
integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
|
||||
dependencies:
|
||||
color-name "~1.1.4"
|
||||
|
||||
color-name@~1.1.4:
|
||||
version "1.1.4"
|
||||
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
|
||||
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
|
||||
|
||||
commander@^4.0.0:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068"
|
||||
integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==
|
||||
|
||||
concat-map@0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||
integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
|
||||
cross-spawn@^7.0.0:
|
||||
version "7.0.3"
|
||||
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
|
||||
integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
|
||||
dependencies:
|
||||
path-key "^3.1.0"
|
||||
shebang-command "^2.0.0"
|
||||
which "^2.0.1"
|
||||
|
||||
css-selector-tokenizer@^0.8:
|
||||
version "0.8.0"
|
||||
|
@ -178,16 +233,20 @@ cssesc@^3.0.0:
|
|||
resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
|
||||
integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==
|
||||
|
||||
daisyui@^3.1.5:
|
||||
version "3.9.3"
|
||||
resolved "https://registry.yarnpkg.com/daisyui/-/daisyui-3.9.3.tgz#d8cd193feb57460d56a5fdf9e15063fd667842ec"
|
||||
integrity sha512-8li177QCu6dqlEOzE3h/dAV1y9Movbjx5bzJIO/hNqMNZtJkbHM0trjTzbDejV7N57eNGdjBvAGtxZYKzS4jow==
|
||||
culori@^3:
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/culori/-/culori-3.3.0.tgz#e33530adbd124d53bd6550394397e695eaaed739"
|
||||
integrity sha512-pHJg+jbuFsCjz9iclQBqyL3B2HLCBF71BwVNujUYEvCeQMvV97R59MNK3R2+jgJ3a1fcZgI9B3vYgz8lzr/BFQ==
|
||||
|
||||
daisyui@^4.7.3:
|
||||
version "4.7.3"
|
||||
resolved "https://registry.yarnpkg.com/daisyui/-/daisyui-4.7.3.tgz#2d75b71d1c52f643914dea9b12930acc51ed9f49"
|
||||
integrity sha512-R8jUpBMAUm4rSyxzGa9QqFdJTkzREtb1QahXdDoOfElGiF4VbSuu5bfqQoOro1kkSagPy+aTKu5WtSSXmH3u3g==
|
||||
dependencies:
|
||||
colord "^2.9"
|
||||
css-selector-tokenizer "^0.8"
|
||||
postcss "^8"
|
||||
culori "^3"
|
||||
picocolors "^1"
|
||||
postcss-js "^4"
|
||||
tailwindcss "^3.1"
|
||||
|
||||
didyoumean@^1.2.2:
|
||||
version "1.2.2"
|
||||
|
@ -199,20 +258,25 @@ dlv@^1.1.3:
|
|||
resolved "https://registry.yarnpkg.com/dlv/-/dlv-1.1.3.tgz#5c198a8a11453596e751494d49874bc7732f2e79"
|
||||
integrity sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==
|
||||
|
||||
electron-to-chromium@^1.4.535:
|
||||
version "1.4.567"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.567.tgz#c92e8fbc2bd15df3068d92571733a218a5413add"
|
||||
integrity sha512-8KR114CAYQ4/r5EIEsOmOMqQ9j0MRbJZR3aXD/KFA8RuKzyoUB4XrUCg+l8RUGqTVQgKNIgTpjaG8YHRPAbX2w==
|
||||
eastasianwidth@^0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb"
|
||||
integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==
|
||||
|
||||
escalade@^3.1.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
|
||||
integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==
|
||||
emoji-regex@^8.0.0:
|
||||
version "8.0.0"
|
||||
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
|
||||
integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
|
||||
|
||||
emoji-regex@^9.2.2:
|
||||
version "9.2.2"
|
||||
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72"
|
||||
integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==
|
||||
|
||||
fast-glob@^3.3.0:
|
||||
version "3.3.1"
|
||||
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.1.tgz#784b4e897340f3dbbef17413b3f11acf03c874c4"
|
||||
integrity sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==
|
||||
version "3.3.2"
|
||||
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129"
|
||||
integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==
|
||||
dependencies:
|
||||
"@nodelib/fs.stat" "^2.0.2"
|
||||
"@nodelib/fs.walk" "^1.2.3"
|
||||
|
@ -226,9 +290,9 @@ fastparse@^1.1.2:
|
|||
integrity sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==
|
||||
|
||||
fastq@^1.6.0:
|
||||
version "1.15.0"
|
||||
resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a"
|
||||
integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==
|
||||
version "1.17.1"
|
||||
resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47"
|
||||
integrity sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==
|
||||
dependencies:
|
||||
reusify "^1.0.4"
|
||||
|
||||
|
@ -239,15 +303,13 @@ fill-range@^7.0.1:
|
|||
dependencies:
|
||||
to-regex-range "^5.0.1"
|
||||
|
||||
fraction.js@^4.3.6:
|
||||
version "4.3.7"
|
||||
resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.3.7.tgz#06ca0085157e42fda7f9e726e79fefc4068840f7"
|
||||
integrity sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==
|
||||
|
||||
fs.realpath@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
||||
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
|
||||
foreground-child@^3.1.0:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.1.1.tgz#1d173e776d75d2772fed08efe4a0de1ea1b12d0d"
|
||||
integrity sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==
|
||||
dependencies:
|
||||
cross-spawn "^7.0.0"
|
||||
signal-exit "^4.0.1"
|
||||
|
||||
fsevents@~2.3.2:
|
||||
version "2.3.3"
|
||||
|
@ -273,38 +335,24 @@ glob-parent@^6.0.2:
|
|||
dependencies:
|
||||
is-glob "^4.0.3"
|
||||
|
||||
glob@7.1.6:
|
||||
version "7.1.6"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
|
||||
integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
|
||||
glob@^10.3.10:
|
||||
version "10.3.10"
|
||||
resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.10.tgz#0351ebb809fd187fe421ab96af83d3a70715df4b"
|
||||
integrity sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==
|
||||
dependencies:
|
||||
fs.realpath "^1.0.0"
|
||||
inflight "^1.0.4"
|
||||
inherits "2"
|
||||
minimatch "^3.0.4"
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
foreground-child "^3.1.0"
|
||||
jackspeak "^2.3.5"
|
||||
minimatch "^9.0.1"
|
||||
minipass "^5.0.0 || ^6.0.2 || ^7.0.0"
|
||||
path-scurry "^1.10.1"
|
||||
|
||||
hasown@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.0.tgz#f4c513d454a57b7c7e1650778de226b11700546c"
|
||||
integrity sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003"
|
||||
integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==
|
||||
dependencies:
|
||||
function-bind "^1.1.2"
|
||||
|
||||
inflight@^1.0.4:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
|
||||
integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==
|
||||
dependencies:
|
||||
once "^1.3.0"
|
||||
wrappy "1"
|
||||
|
||||
inherits@2:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||
|
||||
is-binary-path@~2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09"
|
||||
|
@ -324,6 +372,11 @@ is-extglob@^2.1.1:
|
|||
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
|
||||
integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==
|
||||
|
||||
is-fullwidth-code-point@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
|
||||
integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
|
||||
|
||||
is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084"
|
||||
|
@ -336,21 +389,45 @@ is-number@^7.0.0:
|
|||
resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
|
||||
integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
|
||||
|
||||
jiti@^1.19.1:
|
||||
version "1.20.0"
|
||||
resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.20.0.tgz#2d823b5852ee8963585c8dd8b7992ffc1ae83b42"
|
||||
integrity sha512-3TV69ZbrvV6U5DfQimop50jE9Dl6J8O1ja1dvBbMba/sZ3YBEQqJ2VZRoQPVnhlzjNtU1vaXRZVrVjU4qtm8yA==
|
||||
isexe@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
|
||||
integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==
|
||||
|
||||
lilconfig@^2.0.5, lilconfig@^2.1.0:
|
||||
jackspeak@^2.3.5:
|
||||
version "2.3.6"
|
||||
resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.3.6.tgz#647ecc472238aee4b06ac0e461acc21a8c505ca8"
|
||||
integrity sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==
|
||||
dependencies:
|
||||
"@isaacs/cliui" "^8.0.2"
|
||||
optionalDependencies:
|
||||
"@pkgjs/parseargs" "^0.11.0"
|
||||
|
||||
jiti@^1.19.1:
|
||||
version "1.21.0"
|
||||
resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.0.tgz#7c97f8fe045724e136a397f7340475244156105d"
|
||||
integrity sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==
|
||||
|
||||
lilconfig@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52"
|
||||
integrity sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==
|
||||
|
||||
lilconfig@^3.0.0:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-3.1.1.tgz#9d8a246fa753106cfc205fd2d77042faca56e5e3"
|
||||
integrity sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==
|
||||
|
||||
lines-and-columns@^1.1.6:
|
||||
version "1.2.4"
|
||||
resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632"
|
||||
integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==
|
||||
|
||||
"lru-cache@^9.1.1 || ^10.0.0":
|
||||
version "10.2.0"
|
||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.0.tgz#0bd445ca57363465900f4d1f9bd8db343a4d95c3"
|
||||
integrity sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==
|
||||
|
||||
merge2@^1.3.0:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
|
||||
|
@ -364,12 +441,17 @@ micromatch@^4.0.4, micromatch@^4.0.5:
|
|||
braces "^3.0.2"
|
||||
picomatch "^2.3.1"
|
||||
|
||||
minimatch@^3.0.4:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
|
||||
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
|
||||
minimatch@^9.0.1:
|
||||
version "9.0.3"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825"
|
||||
integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==
|
||||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
brace-expansion "^2.0.1"
|
||||
|
||||
"minipass@^5.0.0 || ^6.0.2 || ^7.0.0":
|
||||
version "7.0.4"
|
||||
resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.0.4.tgz#dbce03740f50a4786ba994c1fb908844d27b038c"
|
||||
integrity sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==
|
||||
|
||||
mz@^2.7.0:
|
||||
version "2.7.0"
|
||||
|
@ -380,26 +462,16 @@ mz@^2.7.0:
|
|||
object-assign "^4.0.1"
|
||||
thenify-all "^1.0.0"
|
||||
|
||||
nanoid@^3.3.6:
|
||||
version "3.3.6"
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c"
|
||||
integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==
|
||||
|
||||
node-releases@^2.0.13:
|
||||
version "2.0.13"
|
||||
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.13.tgz#d5ed1627c23e3461e819b02e57b75e4899b1c81d"
|
||||
integrity sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==
|
||||
nanoid@^3.3.7:
|
||||
version "3.3.7"
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8"
|
||||
integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==
|
||||
|
||||
normalize-path@^3.0.0, normalize-path@~3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
|
||||
integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
|
||||
|
||||
normalize-range@^0.1.2:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942"
|
||||
integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==
|
||||
|
||||
object-assign@^4.0.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||
|
@ -410,24 +482,25 @@ object-hash@^3.0.0:
|
|||
resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-3.0.0.tgz#73f97f753e7baffc0e2cc9d6e079079744ac82e9"
|
||||
integrity sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==
|
||||
|
||||
once@^1.3.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
|
||||
integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==
|
||||
dependencies:
|
||||
wrappy "1"
|
||||
|
||||
path-is-absolute@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
|
||||
integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==
|
||||
path-key@^3.1.0:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
|
||||
integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
|
||||
|
||||
path-parse@^1.0.7:
|
||||
version "1.0.7"
|
||||
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
|
||||
integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
|
||||
|
||||
picocolors@^1.0.0:
|
||||
path-scurry@^1.10.1:
|
||||
version "1.10.1"
|
||||
resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.10.1.tgz#9ba6bf5aa8500fe9fd67df4f0d9483b2b0bfc698"
|
||||
integrity sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==
|
||||
dependencies:
|
||||
lru-cache "^9.1.1 || ^10.0.0"
|
||||
minipass "^5.0.0 || ^6.0.2 || ^7.0.0"
|
||||
|
||||
picocolors@^1, picocolors@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
|
||||
integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
|
||||
|
@ -464,12 +537,12 @@ postcss-js@^4, postcss-js@^4.0.1:
|
|||
camelcase-css "^2.0.1"
|
||||
|
||||
postcss-load-config@^4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-4.0.1.tgz#152383f481c2758274404e4962743191d73875bd"
|
||||
integrity sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA==
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-4.0.2.tgz#7159dcf626118d33e299f485d6afe4aff7c4a3e3"
|
||||
integrity sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==
|
||||
dependencies:
|
||||
lilconfig "^2.0.5"
|
||||
yaml "^2.1.1"
|
||||
lilconfig "^3.0.0"
|
||||
yaml "^2.3.4"
|
||||
|
||||
postcss-nested@^6.0.1:
|
||||
version "6.0.1"
|
||||
|
@ -479,39 +552,27 @@ postcss-nested@^6.0.1:
|
|||
postcss-selector-parser "^6.0.11"
|
||||
|
||||
postcss-selector-parser@^6.0.11:
|
||||
version "6.0.13"
|
||||
resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz#d05d8d76b1e8e173257ef9d60b706a8e5e99bf1b"
|
||||
integrity sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==
|
||||
version "6.0.15"
|
||||
resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.15.tgz#11cc2b21eebc0b99ea374ffb9887174855a01535"
|
||||
integrity sha512-rEYkQOMUCEMhsKbK66tbEU9QVIxbhN18YiniAwA7XQYTVBqrBy+P2p5JcdqsHgKM2zWylp8d7J6eszocfds5Sw==
|
||||
dependencies:
|
||||
cssesc "^3.0.0"
|
||||
util-deprecate "^1.0.2"
|
||||
|
||||
postcss-value-parser@^4.0.0, postcss-value-parser@^4.2.0:
|
||||
postcss-value-parser@^4.0.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514"
|
||||
integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
|
||||
|
||||
postcss@^8, postcss@^8.1.6, postcss@^8.4.23:
|
||||
version "8.4.31"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.31.tgz#92b451050a9f914da6755af352bdc0192508656d"
|
||||
integrity sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==
|
||||
postcss@^8.4.23:
|
||||
version "8.4.35"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.35.tgz#60997775689ce09011edf083a549cea44aabe2f7"
|
||||
integrity sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==
|
||||
dependencies:
|
||||
nanoid "^3.3.6"
|
||||
nanoid "^3.3.7"
|
||||
picocolors "^1.0.0"
|
||||
source-map-js "^1.0.2"
|
||||
|
||||
prettier-plugin-go-template@^0.0.15:
|
||||
version "0.0.15"
|
||||
resolved "https://registry.yarnpkg.com/prettier-plugin-go-template/-/prettier-plugin-go-template-0.0.15.tgz#474952ed72405e528f70bf9cf3f50938c97d8f86"
|
||||
integrity sha512-WqU92E1NokWYNZ9mLE6ijoRg6LtIGdLMePt2C7UBDjXeDH9okcRI3zRqtnWR4s5AloiqyvZ66jNBAa9tmRY5EQ==
|
||||
dependencies:
|
||||
ulid "^2.3.0"
|
||||
|
||||
prettier@^3.0.3:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.0.3.tgz#432a51f7ba422d1469096c0fdc28e235db8f9643"
|
||||
integrity sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==
|
||||
|
||||
queue-microtask@^1.2.2:
|
||||
version "1.2.3"
|
||||
resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
|
||||
|
@ -552,19 +613,70 @@ run-parallel@^1.1.9:
|
|||
dependencies:
|
||||
queue-microtask "^1.2.2"
|
||||
|
||||
shebang-command@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"
|
||||
integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==
|
||||
dependencies:
|
||||
shebang-regex "^3.0.0"
|
||||
|
||||
shebang-regex@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
|
||||
integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
|
||||
|
||||
signal-exit@^4.0.1:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04"
|
||||
integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==
|
||||
|
||||
source-map-js@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
|
||||
integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
|
||||
|
||||
"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0:
|
||||
name string-width-cjs
|
||||
version "4.2.3"
|
||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
|
||||
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
|
||||
dependencies:
|
||||
emoji-regex "^8.0.0"
|
||||
is-fullwidth-code-point "^3.0.0"
|
||||
strip-ansi "^6.0.1"
|
||||
|
||||
string-width@^5.0.1, string-width@^5.1.2:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794"
|
||||
integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==
|
||||
dependencies:
|
||||
eastasianwidth "^0.2.0"
|
||||
emoji-regex "^9.2.2"
|
||||
strip-ansi "^7.0.1"
|
||||
|
||||
"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
|
||||
name strip-ansi-cjs
|
||||
version "6.0.1"
|
||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
|
||||
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
|
||||
dependencies:
|
||||
ansi-regex "^5.0.1"
|
||||
|
||||
strip-ansi@^7.0.1:
|
||||
version "7.1.0"
|
||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45"
|
||||
integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==
|
||||
dependencies:
|
||||
ansi-regex "^6.0.1"
|
||||
|
||||
sucrase@^3.32.0:
|
||||
version "3.34.0"
|
||||
resolved "https://registry.yarnpkg.com/sucrase/-/sucrase-3.34.0.tgz#1e0e2d8fcf07f8b9c3569067d92fbd8690fb576f"
|
||||
integrity sha512-70/LQEZ07TEcxiU2dz51FKaE6hCTWC6vr7FOk3Gr0U60C3shtAN+H+BFr9XlYe5xqf3RA8nrc+VIwzCfnxuXJw==
|
||||
version "3.35.0"
|
||||
resolved "https://registry.yarnpkg.com/sucrase/-/sucrase-3.35.0.tgz#57f17a3d7e19b36d8995f06679d121be914ae263"
|
||||
integrity sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==
|
||||
dependencies:
|
||||
"@jridgewell/gen-mapping" "^0.3.2"
|
||||
commander "^4.0.0"
|
||||
glob "7.1.6"
|
||||
glob "^10.3.10"
|
||||
lines-and-columns "^1.1.6"
|
||||
mz "^2.7.0"
|
||||
pirates "^4.0.1"
|
||||
|
@ -575,10 +687,10 @@ supports-preserve-symlinks-flag@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
|
||||
integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
|
||||
|
||||
tailwindcss@^3.1, tailwindcss@^3.2.7:
|
||||
version "3.3.5"
|
||||
resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.3.5.tgz#22a59e2fbe0ecb6660809d9cc5f3976b077be3b8"
|
||||
integrity sha512-5SEZU4J7pxZgSkv7FP1zY8i2TIAOooNZ1e/OGtxIEv6GltpoiXUqWvLy89+a10qYTB1N5Ifkuw9lqQkN9sscvA==
|
||||
tailwindcss@^3.4.1:
|
||||
version "3.4.1"
|
||||
resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.4.1.tgz#f512ca5d1dd4c9503c7d3d28a968f1ad8f5c839d"
|
||||
integrity sha512-qAYmXRfk3ENzuPBakNK0SRrUDipP8NQnEY6772uDhflcQz5EhRdD7JNZxyrFHVQNCwULPBn6FNPp9brpO7ctcA==
|
||||
dependencies:
|
||||
"@alloc/quick-lru" "^5.2.0"
|
||||
arg "^5.0.2"
|
||||
|
@ -629,30 +741,37 @@ ts-interface-checker@^0.1.9:
|
|||
resolved "https://registry.yarnpkg.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz#784fd3d679722bc103b1b4b8030bcddb5db2a699"
|
||||
integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==
|
||||
|
||||
ulid@^2.3.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/ulid/-/ulid-2.3.0.tgz#93063522771a9774121a84d126ecd3eb9804071f"
|
||||
integrity sha512-keqHubrlpvT6G2wH0OEfSW4mquYRcbe/J8NMmveoQOjUqmo+hXtO+ORCpWhdbZ7k72UtY61BL7haGxW6enBnjw==
|
||||
|
||||
update-browserslist-db@^1.0.13:
|
||||
version "1.0.13"
|
||||
resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz#3c5e4f5c083661bd38ef64b6328c26ed6c8248c4"
|
||||
integrity sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==
|
||||
dependencies:
|
||||
escalade "^3.1.1"
|
||||
picocolors "^1.0.0"
|
||||
|
||||
util-deprecate@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||
integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==
|
||||
|
||||
wrappy@1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
|
||||
integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==
|
||||
which@^2.0.1:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"
|
||||
integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==
|
||||
dependencies:
|
||||
isexe "^2.0.0"
|
||||
|
||||
yaml@^2.1.1:
|
||||
version "2.3.3"
|
||||
resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.3.tgz#01f6d18ef036446340007db8e016810e5d64aad9"
|
||||
integrity sha512-zw0VAJxgeZ6+++/su5AFoqBbZbrEakwu+X0M5HmcwUiBL7AzcuPKjj5we4xfQLp78LkEMpD0cOnUhmgOVy3KdQ==
|
||||
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
|
||||
version "7.0.0"
|
||||
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
|
||||
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
|
||||
dependencies:
|
||||
ansi-styles "^4.0.0"
|
||||
string-width "^4.1.0"
|
||||
strip-ansi "^6.0.0"
|
||||
|
||||
wrap-ansi@^8.1.0:
|
||||
version "8.1.0"
|
||||
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"
|
||||
integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==
|
||||
dependencies:
|
||||
ansi-styles "^6.1.0"
|
||||
string-width "^5.0.1"
|
||||
strip-ansi "^7.0.1"
|
||||
|
||||
yaml@^2.3.4:
|
||||
version "2.4.1"
|
||||
resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.4.1.tgz#2e57e0b5e995292c25c75d2658f0664765210eed"
|
||||
integrity sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==
|