Skip to content

Commit

Permalink
added custom css
Browse files Browse the repository at this point in the history
  • Loading branch information
dzonerzy committed May 5, 2024
1 parent 03432f4 commit 8843b2a
Show file tree
Hide file tree
Showing 7 changed files with 216 additions and 130 deletions.
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,28 @@ Example of a dark mode theme:
}
```

<p align="justify">
It is also possible to use a custom css file by providing the path to the file:
</p>

```json
"theme": {
"custom_css": "/path/to/custom.css"
}
```

<p align="justify">
Keep in mind, even if you provide a custom css file, the background and foreground colors will still be applied as long as you provide the correct templating keys in your custom css file like so:
</p>

```css
body {
background: {{.Background}};
color: {{.Foreground}};
}
```


#### YAML

```yml
Expand Down
25 changes: 25 additions & 0 deletions internal/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,3 +171,28 @@ func TestValidate(t *testing.T) {
t.Fatal()
}
}

func TestCustomCSS(t *testing.T) {
var config = `{
"addr": "0.0.0.0:8080",
"use_tls": false,
"cert_file": "",
"key_file": "",
"behind_proxy": false,
"title": "Easy Gate",
"theme": {
"custom_css": "tmp.css",
},
"groups": [],
"services": [],
"notes": []
}`
cfg, err := Unmarshal([]byte(config))
if err != nil {
t.Fatal(err)
}

if cfg.Theme.CustomCss != "tmp.css" {
t.Fatal()
}
}
12 changes: 12 additions & 0 deletions internal/config/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package config

import (
"fmt"
"os"
"regexp"
)

Expand Down Expand Up @@ -40,6 +41,17 @@ func validateConfig(cfg *Config) error {
return fmt.Errorf("invalid foreground color")
}

if cfg.Theme.CustomCss != "" {
fi, err := os.Stat(cfg.Theme.CustomCss)
if err != nil {
return fmt.Errorf("invalid custom CSS file path")
}

if fi.IsDir() {
return fmt.Errorf("custom CSS path is a directory")
}
}

for _, service := range cfg.Services {
if !isURL(service.URL) {
return fmt.Errorf("invalid URL for service %s", service.Name)
Expand Down
36 changes: 32 additions & 4 deletions internal/engine/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ package engine

import (
"embed"
"fmt"
"html/template"
"log"
"net/http"
"os"

"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/logger"
Expand Down Expand Up @@ -33,6 +36,17 @@ func (e Engine) Serve() {
status, _ := e.Routine.GetStatus()

htmlEngine := html.NewFileSystem(http.FS(templateFS), ".html")

var styleData []byte

if status.Theme.CustomCss != "" {
data, _ := os.ReadFile(status.Theme.CustomCss)
styleData = data
} else {
data, _ := staticFS.ReadFile("static/styles/style.css")
styleData = data
}

app := fiber.New(fiber.Config{
Views: htmlEngine,
DisableStartupMessage: true,
Expand Down Expand Up @@ -63,6 +77,20 @@ func (e Engine) Serve() {
return c.Send(data)
})

app.Get("/style.css", func(c *fiber.Ctx) error {

tmpl, err := template.New("").Parse(string(styleData))
if err != nil {
return c.SendStatus(http.StatusInternalServerError)
}

c.Set("Content-type", "text/css")
return tmpl.Execute(c, fiber.Map{
"Background": status.Theme.Background,
"Foreground": status.Theme.Foreground,
})
})

app.Get("/", func(c *fiber.Ctx) error {
status, err := e.Routine.GetStatus()
if err != nil {
Expand All @@ -73,11 +101,11 @@ func (e Engine) Serve() {
addr := getAddr(status, c)
data := getData(status, addr)

fmt.Println(data)

return c.Render("template/index", fiber.Map{
"Title": status.Title,
"Background": status.Theme.Background,
"Foreground": status.Theme.Foreground,
"Data": data,
"Title": status.Title,
"Data": data,
})
})

Expand Down
122 changes: 122 additions & 0 deletions internal/engine/static/styles/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
@font-face {
font-family: 'Roboto';
src: url('/roboto-regular.ttf') format('truetype');
}

body {
background-color: {{.Background}};
color: {{.Foreground}};
font-family: 'Roboto',
sans-serif;
}

a {
text-decoration: none;
color: inherit;
}

.main {
padding-top: 1.5rem;
padding-bottom: 1.5rem;
padding-left: 3rem;
padding-right: 3rem;
}

.category-title {
margin-left: 0.25rem;
}

.category-block {
display: grid;
grid-template-columns: repeat(1, minmax(0, 1fr));
margin-top: 0.5rem;
margin-bottom: 0.5rem;
}

.service-block {
padding: 0.3rem;
border-radius: 0.5rem;
box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.1);
cursor: pointer;
transition: box-shadow 0.2s ease;
margin: 0.25rem;
}

.service-block:hover {
box-shadow: 0 0.25rem 0.5rem rgba(0, 0, 0, 0.2);
}

.service-icon {
fill: {{.Foreground}};
margin: auto;
}

.service-title {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-weight: 600;
width: 83.33%;
}

.notes-block {
margin-top: 3rem;
margin-bottom: 0.5rem;
display: grid;
grid-template-columns: repeat(1, minmax(0, 1fr));
}

.note-block {
padding: 1rem;
border-radius: 0.25rem;
box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.1);
margin: 0.25rem;
}

.note-icon {
fill: {{.Foreground}};
margin-right: 0.5rem;
}

.note-title {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-weight: 600;
width: 83.33%;
}

.flex-center {
align-items: center;
display: flex;
}

@media (min-width: 768px) {
.category-block {
grid-template-columns: repeat(2, minmax(0, 1fr));
}

.notes-block {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}

@media (min-width: 1024px) {
.category-block {
grid-template-columns: repeat(4, minmax(0, 1fr));
}

.notes-block {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}

@media (min-width: 1280px) {
.category-block {
grid-template-columns: repeat(7, minmax(0, 1fr));
}

.notes-block {
grid-template-columns: repeat(4, minmax(0, 1fr));
}
}
Loading

0 comments on commit 8843b2a

Please sign in to comment.