BREAKING: Use yaml for bookmarks

This commit is contained in:
Florian Hoss 2022-12-20 12:37:57 +01:00
parent 39d91f4d14
commit c9820499cf
20 changed files with 311 additions and 305 deletions

2
Jenkinsfile vendored
View file

@ -1,6 +1,6 @@
pipeline {
environment {
VERSION = "v2.0.0"
VERSION = "v2.0.1"
PROJECT_NAME = JOB_NAME.split('/')
IMAGE_NAME = "unjxde/${PROJECT_NAME[0]}"
IMAGE = ''

View file

@ -32,52 +32,45 @@ Please refer to the available options as shown in the docker-compose example.
### Example of the bookmarks.json
All Bookmarks are read from a file called `bookmarks.json` located inside the `./storage` folder.
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.
**bookmarks.json example:**
```json
[
{
"CATEGORY": "First",
"ENTRIES": [
{
"NAME": "Github",
"ICON": "https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png",
"URL": "https://github.com"
},
{
"NAME": "Jenkins",
"ICON": "jenkins.webp",
"URL": "https://www.jenkins.io/"
}
]
},
{
"CATEGORY": "",
"ENTRIES": [
{
"NAME": "Github",
"ICON": "https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png",
"URL": "https://github.com"
}
]
},
{
"CATEGORY": "Third",
"ENTRIES": [
{
"NAME": "Github",
"ICON": "https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png",
"URL": "https://github.com"
}
]
}
]
**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

View file

@ -1,10 +1,10 @@
package bookmarks
import (
"encoding/json"
"github.com/fsnotify/fsnotify"
folderCreate "github.com/unjx-de/go-folder"
"go.uber.org/zap"
"gopkg.in/yaml.v3"
"io"
"os"
"strings"
@ -13,60 +13,60 @@ import (
const StorageDir = "storage/"
const IconsDir = StorageDir + "icons/"
const bookmarksFolder = "bookmarks/"
const bookmarksFile = "bookmarks.json"
const bookmarksFile = "config.yaml"
func NewBookmarkService(logging *zap.SugaredLogger) *Bookmarks {
b := Bookmarks{log: logging}
func NewBookmarkService(logging *zap.SugaredLogger) *Config {
b := Config{log: logging}
b.createFolderStructure()
b.parseBookmarks()
go b.watchBookmarks()
return &b
}
func (b *Bookmarks) createFolderStructure() {
func (c *Config) createFolderStructure() {
folders := []string{StorageDir, IconsDir}
err := folderCreate.CreateFolders(folders, 0755)
if err != nil {
b.log.Fatal(err)
c.log.Fatal(err)
}
b.log.Debug("folders created")
c.log.Debugw("folders created", "folders", folders)
}
func (b *Bookmarks) copyDefaultBookmarks() {
func (c *Config) copyDefaultBookmarks() {
source, _ := os.Open(bookmarksFolder + bookmarksFile)
defer source.Close()
destination, err := os.Create(StorageDir + bookmarksFile)
if err != nil {
b.log.Error(err)
c.log.Error(err)
}
defer destination.Close()
_, err = io.Copy(destination, source)
if err != nil {
b.log.Error(err)
c.log.Error(err)
}
}
func (b *Bookmarks) readBookmarksFile() []byte {
jsonFile, err := os.Open(StorageDir + bookmarksFile)
func (c *Config) readBookmarksFile() []byte {
file, err := os.Open(StorageDir + bookmarksFile)
if err != nil {
b.copyDefaultBookmarks()
jsonFile, err = os.Open(StorageDir + bookmarksFile)
c.copyDefaultBookmarks()
file, err = os.Open(StorageDir + bookmarksFile)
if err != nil {
b.log.Error(err)
c.log.Error(err)
return nil
}
}
defer jsonFile.Close()
byteValue, err := io.ReadAll(jsonFile)
defer file.Close()
byteValue, err := io.ReadAll(file)
if err != nil {
b.log.Error(err)
c.log.Error(err)
return nil
}
return byteValue
}
func (b *Bookmarks) replaceIconString() {
for _, v := range b.Categories {
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
@ -75,20 +75,20 @@ func (b *Bookmarks) replaceIconString() {
}
}
func (b *Bookmarks) parseBookmarks() {
byteValue := b.readBookmarksFile()
err := json.Unmarshal(byteValue, &b.Categories)
func (c *Config) parseBookmarks() {
byteValue := c.readBookmarksFile()
err := yaml.Unmarshal(byteValue, &c.Parsed)
if err != nil {
b.log.Error(err)
c.log.Error(err)
return
}
b.replaceIconString()
c.replaceIconString()
}
func (b *Bookmarks) watchBookmarks() {
func (c *Config) watchBookmarks() {
watcher, err := fsnotify.NewWatcher()
if err != nil {
b.log.Error(err)
c.log.Error(err)
}
defer watcher.Close()
done := make(chan bool)
@ -96,23 +96,17 @@ func (b *Bookmarks) watchBookmarks() {
go func() {
for {
select {
case err, ok := <-watcher.Errors:
if !ok {
return
}
b.log.Error(err)
case _, ok := <-watcher.Events:
if !ok {
return
}
b.parseBookmarks()
b.log.Debug("bookmarks changed", "categories", len(b.Categories))
case err, _ := <-watcher.Errors:
c.log.Error(err)
case _, _ = <-watcher.Events:
c.parseBookmarks()
c.log.Debug("bookmarks changed", "applications", len(c.Parsed.Applications), "links", len(c.Parsed.Links))
}
}
}()
if err := watcher.Add(StorageDir + bookmarksFile); err != nil {
b.log.Fatal()
c.log.Fatal()
}
<-done
}

View file

@ -1,32 +0,0 @@
[
{
"CATEGORY": "First",
"ENTRIES": [
{
"NAME": "Github",
"ICON": "https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png",
"URL": "https://github.com"
}
]
},
{
"CATEGORY": "",
"ENTRIES": [
{
"NAME": "Github",
"ICON": "https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png",
"URL": "https://github.com"
}
]
},
{
"CATEGORY": "Third",
"ENTRIES": [
{
"NAME": "Github",
"ICON": "https://github.githubassets.com/images/modules/logos_page/GitHub-Mark.png",
"URL": "https://github.com"
}
]
}
]

30
bookmarks/config.yaml Normal file
View file

@ -0,0 +1,30 @@
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"

View file

@ -2,18 +2,23 @@ package bookmarks
import "go.uber.org/zap"
type Bookmarks struct {
log *zap.SugaredLogger
Categories []Category
}
type Category struct {
Category string `json:"category"`
Entries []Entry `json:"entries"`
}
type Entry struct {
Name string `json:"name"`
Icon string `json:"icon"`
Url string `json:"url"`
type Config struct {
log *zap.SugaredLogger
Parsed struct {
Links []struct {
Category string
Entries []struct {
Name string
URL string
}
}
Applications []struct {
Category string
Entries []struct {
Name string
Icon string
URL string
}
}
}
}

1
go.mod
View file

@ -11,6 +11,7 @@ require (
github.com/shirou/gopsutil/v3 v3.22.11
github.com/unjx-de/go-folder v1.0.7
go.uber.org/zap v1.24.0
gopkg.in/yaml.v3 v3.0.1
)
require (

12
go.sum
View file

@ -22,7 +22,6 @@ github.com/labstack/echo/v4 v4.9.1 h1:GliPYSpzGKlyOhqIbG8nmHBo3i1saKWFOgh41AN3b+
github.com/labstack/echo/v4 v4.9.1/go.mod h1:Pop5HLc+xoc4qhTZ1ip6C0RtP7Z+4VzRLWZZFKqbbjo=
github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8=
github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
github.com/lufia/plan9stats v0.0.0-20220913051719-115f729f3c8c h1:VtwQ41oftZwlMnOEbMWQtSEUgU64U4s+GHk7hZK+jtY=
github.com/lufia/plan9stats v0.0.0-20220913051719-115f729f3c8c/go.mod h1:JKx41uQRwqlTZabZc+kILPrO/3jlKnQ2Z8b7YiVw5cE=
@ -36,7 +35,6 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
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 h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
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=
@ -45,7 +43,6 @@ github.com/shirou/gopsutil/v3 v3.22.11/go.mod h1:xl0EeL4vXJ+hQMAGN8B9VFpxukEMA0X
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.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
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=
@ -59,24 +56,18 @@ github.com/unjx-de/go-folder v1.0.7 h1:OVKvqjcVB0ASidVshYndRtkmlqS1h6MIhSr0vqX3Q
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 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4=
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/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8=
go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU=
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
golang.org/x/crypto v0.4.0 h1:UVQgzMY87xqpKNgb+kDsll2Igd33HszWHFLmpaRMq/8=
golang.org/x/crypto v0.4.0/go.mod h1:3quD/ATkf6oY+rnes5c3ExXTbLc8mueNue5/DoinL80=
golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU=
@ -93,11 +84,10 @@ golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM=
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/time v0.1.0 h1:xYY+Bajn2a7VBmTM5GikTmnK8ZuX8YgnQCqZpbBNtmA=
golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
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/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
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.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=

View file

@ -27,7 +27,7 @@ type goDash struct {
type info struct {
weather *weather.Weather
bookmarks *bookmarks.Bookmarks
bookmarks *bookmarks.Config
system *system.System
}
@ -63,6 +63,8 @@ func main() {
panic(err)
}
g.router.Debug = true
g.setupLogger()
defer func(logger *zap.SugaredLogger) {
_ = logger.Sync()

View file

@ -13,10 +13,10 @@ var (
func (g *goDash) index(c echo.Context) error {
return c.Render(http.StatusOK, "index.gohtml", map[string]interface{}{
"Title": g.config.Title,
"Weather": g.info.weather.CurrentWeather,
"Categories": g.info.bookmarks.Categories,
"System": g.info.system.CurrentSystem,
"Title": g.config.Title,
"Weather": g.info.weather.CurrentWeather,
"Parsed": g.info.bookmarks.Parsed,
"System": g.info.system,
})
}

View file

@ -10,7 +10,7 @@
@apply bg-primary-content h-1 rounded-full mt-1;
}
.system-icon {
@apply h-8 w-8 shrink-0 mr-3 opacity-90 text-secondary;
@apply h-8 w-8 shrink-0 mr-3 opacity-90;
}
.extra-icon {
@apply h-3 w-3 shrink-0 mr-2 text-primary;
@ -18,7 +18,16 @@
.extra-sun-icon {
@apply h-4 w-4 shrink-0 -mb-1 mr-2 text-primary;
}
.extra-system-info {
.extra-info {
@apply text-xs truncate text-secondary;
}
.grid-apps {
@apply grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 xl:grid-cols-6 gap-4
}
.hover-effect {
@apply no-underline md:hover:underline underline-offset-2 decoration-primary text-sm text-slate-700 dark:text-slate-300 hover:text-slate-900 dark:hover:text-slate-50 transition-all ease-linear duration-150
}
.heading{
@apply text-lg text-secondary select-none truncate underline decoration-primary underline-offset-4
}
}

View file

@ -19,10 +19,10 @@ func staticCpu() CPU {
return p
}
func (s *System) liveCpu() {
func (c *Config) liveCpu() {
p, err := cpu.Percent(0, false)
if err != nil {
return
}
s.CurrentSystem.Live.CPU = math.RoundToEven(p[0])
c.System.Live.CPU = math.RoundToEven(p[0])
}

View file

@ -19,11 +19,11 @@ func staticDisk() Disk {
return result
}
func (s *System) liveDisk() {
func (c *Config) liveDisk() {
d, err := disk.Usage("/")
if err != nil {
return
}
s.CurrentSystem.Live.Disk.Value = readableSize(d.Used)
s.CurrentSystem.Live.Disk.Percentage = math.RoundToEven(percent.PercentOfFloat(float64(d.Used), float64(d.Total)))
c.System.Live.Disk.Value = readableSize(d.Used)
c.System.Live.Disk.Percentage = math.RoundToEven(percent.PercentOfFloat(float64(d.Used), float64(d.Total)))
}

View file

@ -21,11 +21,11 @@ func staticRam() Ram {
return result
}
func (s *System) liveRam() {
func (c *Config) liveRam() {
r, err := mem.VirtualMemory()
if err != nil {
return
}
s.CurrentSystem.Live.Ram.Value = readableSize(r.Used)
s.CurrentSystem.Live.Ram.Percentage = math.RoundToEven(percent.PercentOfFloat(float64(r.Used), float64(r.Total)))
c.System.Live.Ram.Value = readableSize(r.Used)
c.System.Live.Ram.Percentage = math.RoundToEven(percent.PercentOfFloat(float64(r.Used), float64(r.Total)))
}

View file

@ -7,30 +7,30 @@ import (
)
func NewSystemService(enabled bool, logging *zap.SugaredLogger, hub *hub.Hub) *System {
var s System
var s Config
if enabled {
s = System{log: logging, hub: hub}
s = Config{log: logging, hub: hub}
s.Initialize()
}
return &s
return &s.System
}
func (s *System) UpdateLiveInformation() {
func (c *Config) UpdateLiveInformation() {
for {
s.liveCpu()
s.liveRam()
s.liveDisk()
s.uptime()
s.hub.LiveInformationCh <- hub.Message{WsType: hub.System, Message: s.CurrentSystem.Live}
c.liveCpu()
c.liveRam()
c.liveDisk()
c.uptime()
c.hub.LiveInformationCh <- hub.Message{WsType: hub.System, Message: c.System.Live}
time.Sleep(1 * time.Second)
}
}
func (s *System) Initialize() {
s.CurrentSystem.Static.Host = staticHost()
s.CurrentSystem.Static.CPU = staticCpu()
s.CurrentSystem.Static.Ram = staticRam()
s.CurrentSystem.Static.Disk = staticDisk()
go s.UpdateLiveInformation()
s.log.Debugw("system updated", "cpu", s.CurrentSystem.Static.CPU.Name, "arch", s.CurrentSystem.Static.Host.Architecture)
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()
c.log.Debugw("system updated", "cpu", c.System.Static.CPU.Name, "arch", c.System.Static.Host.Architecture)
}

View file

@ -5,13 +5,13 @@ import (
"godash/hub"
)
type System struct {
hub *hub.Hub
log *zap.SugaredLogger
CurrentSystem CurrentSystem
type Config struct {
hub *hub.Hub
log *zap.SugaredLogger
System System
}
type CurrentSystem struct {
type System struct {
Live LiveInformation `json:"live"`
Static StaticInformation `json:"static"`
}

View file

@ -4,14 +4,14 @@ import (
"github.com/shirou/gopsutil/v3/host"
)
func (s *System) uptime() {
func (c *Config) uptime() {
i, err := host.Info()
if err != nil {
return
}
s.CurrentSystem.Live.Uptime.Days = i.Uptime / 84600
s.CurrentSystem.Live.Uptime.Hours = uint16((i.Uptime % 86400) / 3600)
s.CurrentSystem.Live.Uptime.Minutes = uint16(((i.Uptime % 86400) % 3600) / 60)
s.CurrentSystem.Live.Uptime.Seconds = uint16(((i.Uptime % 86400) % 3600) % 60)
s.CurrentSystem.Live.Uptime.Percentage = float32((s.CurrentSystem.Live.Uptime.Minutes*100)+s.CurrentSystem.Live.Uptime.Seconds) / 60
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
}

View file

@ -15,7 +15,7 @@ module.exports = {
},
dark: {
...require("daisyui/src/colors/themes")["[data-theme=halloween]"],
secondary: "#b9b9b9",
secondary: "#a0a0a0",
},
},
],

View file

@ -24,7 +24,7 @@
</head>
<body>
<div class="mx-auto container px-5 lg:px-8 my-3 md:my-10 lg:my-14 xl:my-20">{{ template "content" . }}</div>
<div class="mx-auto container px-5 lg:px-8 my-3 md:my-6 lg:my-10 xl:my-14">{{ template "content" . }}</div>
</body>
</html>
{{ end }}

View file

@ -6,138 +6,152 @@
{{ define "content" }}
{{ if .Weather.Icon }}
{{ template "weatherIcons" . }}
<div class="grid gap-10">
{{ if .Weather.Icon }}
{{ template "weatherIcons" . }}
<div class="flex items-center mb-6 md:mb-10 select-none">
<svg class="h-12 w-12 shrink-0 mr-4 md:w-14 md:h-14">
<use id="weatherIcon" class="text-secondary" 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">{{ .Weather.Description }}</div>
</div>
<div class="flex items-center">
<svg class="extra-icon">
<use xlink:href="#humidity"></use>
</svg>
<div id="weatherHumidity">{{ .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">{{ .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">{{ .Weather.Sunset }}</div>
</div>
</div>
</div>
</div>
{{ end }}
{{ if .System.Static.Host.Architecture }}
{{ template "systemIcons" . }}
<div class="grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-4 gap-3 mb-6 md:mb-10 select-none">
<div class="flex items-center">
<svg class="system-icon">
<use xlink:href="#cpu"></use>
<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 class="w-full truncate">
<div class="extra-system-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 class="text-4xl md:text-4xl">
<span id="weatherTemp">{{ .Weather.Temp }}</span> {{ .Weather.Units }}
</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-system-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-system-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-system-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 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 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 .Categories }}
<div class="grid gap-1">
{{ if .Category }}
<div class="text-lg text-secondary select-none truncate">{{ .Category }}</div>
{{ end }}
<div class="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 xl:grid-cols-6 gap-4">
{{ range .Entries }}
<a
href="{{ .Url }}"
class="bookmark-link flex items-center no-underline md:hover:underline underline-offset-2 decoration-primary text-sm text-slate-700 dark:text-slate-300 hover:text-slate-900 dark:hover:text-slate-50 transition-all ease-linear duration-150"
>
<div class="img rounded-md w-8 h-8 bg-cover bg-center opacity-90" style="background-image: url({{ .Icon }})"></div>
<div class="uppercase truncate ml-2">{{ .Name }}</div>
</a>
{{ end }}
</div>
</div>
{{ end }}
{{ if .System.Static.Host.Architecture }}
{{ template "systemIcons" . }}
<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-1">
{{ 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="img rounded-md w-8 h-8 bg-cover bg-center 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-1">
{{ 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 }}