diff --git a/src/ecodash/config.go b/src/ecodash/config.go
index 2856159..efa5841 100644
--- a/src/ecodash/config.go
+++ b/src/ecodash/config.go
@@ -4,6 +4,7 @@ import (
"database/sql"
"encoding/json"
"errors"
+ "html/template"
"os"
"reflect"
"regexp"
@@ -37,10 +38,17 @@ type Administrator struct {
PasswordHash string `json:"password_hash"`
}
type Dashboard struct {
- Name string `json:"name"`
- Theme string `json:"theme"`
- FooterLinks []Link `json:"footer_links"`
- HeaderLinks []Link `json:"header_links"`
+ Name string `json:"name"`
+ Theme string `json:"theme"`
+ FooterLinks []Link `json:"footer_links"`
+ HeaderLinks []Link `json:"header_links"`
+ MOTD *MessageCard `json:"motd"`
+}
+
+type MessageCard struct {
+ Title string `json:"title"`
+ Content template.HTML `json:"content"`
+ Style string `json:"style"`
}
var errBadHAFormat = errors.New("HomeAssistant base URL is badly formatted")
diff --git a/src/ecodash/http.go b/src/ecodash/http.go
index bd17c71..8cce565 100644
--- a/src/ecodash/http.go
+++ b/src/ecodash/http.go
@@ -47,16 +47,17 @@ func (config *Config) AdminEndpoint(c *fiber.Ctx) error {
if config.IsAuthorized(c) { // here the user is submitting the form to change configuration
err := config.saveAdminForm(c)
if err != nil {
- return config.RenderAdminPanel(c, Warning{
- Header: "An error occurred!",
- Body: html.EscapeString(err.Error()),
+ return config.RenderAdminPanel(c, &MessageCard{
+ Title: "An error occurred!",
+ Content: template.HTML(html.EscapeString(err.Error())),
+ Style: "error",
})
}
- return config.RenderAdminPanel(c, Warning{
- Header: "Settings applied",
- Body: "Your settings have been tested and applied successfully.
" +
+ return config.RenderAdminPanel(c, &MessageCard{
+ Title: "Settings applied",
+ Content: "Your settings have been tested and applied successfully.
" +
"You can continue using EcoDash on the Home.",
- IsSuccess: true,
+ Style: "success",
})
}
@@ -64,38 +65,28 @@ func (config *Config) AdminEndpoint(c *fiber.Ctx) error {
if c.FormValue("username") == config.Administrator.Username && tools.Hash(c.FormValue("password")) == config.Administrator.PasswordHash {
c.Cookie(&fiber.Cookie{Name: "admin_username", Value: c.FormValue("username")})
c.Cookie(&fiber.Cookie{Name: "admin_password_hash", Value: tools.Hash(c.FormValue("password"))})
- return config.RenderAdminPanel(c)
+ return config.RenderAdminPanel(c, nil)
}
return c.Render("login", fiber.Map{"Defaults": config.getTemplateDefaults(), "Failed": true}, "base")
}
if config.IsAuthorized(c) {
- return config.RenderAdminPanel(c)
+ return config.RenderAdminPanel(c, nil)
}
return c.Render("login", config.TemplateDefaultsMap(), "base")
}
-func (config *Config) RenderAdminPanel(c *fiber.Ctx, warning ...Warning) error {
+func (config *Config) RenderAdminPanel(c *fiber.Ctx, message *MessageCard) error {
dirs, err := os.ReadDir("./templates")
if err != nil {
return err
}
- if len(warning) > 0 {
- // #nosec // TODO this is dangerous, even if we're escaping the only place where we're passing a non-literal
- warning[0].BodyHTML = template.HTML(warning[0].Body)
- return c.Render("admin", fiber.Map{
- "Defaults": config.getTemplateDefaults(),
- "Themes": dirs,
- "Config": config,
- "Warning": warning[0],
- }, "base")
- }
-
return c.Render("admin", fiber.Map{
"Defaults": config.getTemplateDefaults(),
"Themes": dirs,
"Config": config,
+ "Message": message,
}, "base")
}
@@ -121,7 +112,7 @@ func (config *Config) saveAdminForm(c *fiber.Ctx) error {
HomeAssistant: HomeAssistant{ /*BaseURL to be filled later*/ APIKey: c.FormValue("api_key"), InstallationDate: dayStart(parsedTime)},
Sensors: Sensors{PolledSmartEnergySummation: c.FormValue("polled_smart_energy_summation"), FossilPercentage: c.FormValue("fossil_percentage")},
Administrator: Administrator{Username: c.FormValue("username") /*PasswordHash to be filled later*/},
- Dashboard: Dashboard{Theme: c.FormValue("theme"), Name: c.FormValue("name"), HeaderLinks: config.Dashboard.HeaderLinks, FooterLinks: config.Dashboard.FooterLinks},
+ Dashboard: Dashboard{Theme: c.FormValue("theme"), Name: c.FormValue("name"), HeaderLinks: config.Dashboard.HeaderLinks, FooterLinks: config.Dashboard.FooterLinks /*MessageCard to be filled later*/},
}
if c.FormValue("keep_old_password") == "" {
@@ -130,6 +121,14 @@ func (config *Config) saveAdminForm(c *fiber.Ctx) error {
form.Administrator.PasswordHash = config.Administrator.PasswordHash
}
+ if c.FormValue("motd_title") != "" || c.FormValue("motd_content") != "" {
+ form.Dashboard.MOTD = &MessageCard{
+ Title: c.FormValue("motd_title"),
+ Content: template.HTML(c.FormValue("motd_content")),
+ Style: c.FormValue("motd_style"),
+ }
+ }
+
fmtURL, err := formatURL(c.FormValue("base_url"))
if err != nil {
return err
@@ -202,5 +201,6 @@ func (config *Config) RenderIndex(c *fiber.Ctx) error {
"EnergyConsumptions": energyConsumptions,
"GreenEnergyPercent": averageExcludingCurrentDay(greenEnergyPercents),
"PerDayUsage": perDayUsage,
+ "MOTD": config.Dashboard.MOTD,
}, "base")
}
diff --git a/src/main/main.go b/src/main/main.go
index 4b4c4aa..29ae004 100644
--- a/src/main/main.go
+++ b/src/main/main.go
@@ -38,7 +38,7 @@ func main() {
if config.Administrator.Username == "" || config.Administrator.PasswordHash == "" {
c.Cookie(&fiber.Cookie{Name: "admin_username", Value: ""})
c.Cookie(&fiber.Cookie{Name: "admin_password_hash", Value: tools.Hash("")})
- return config.RenderAdminPanel(c)
+ return config.RenderAdminPanel(c, nil)
}
return config.RenderIndex(c)
})
diff --git a/templates/default/admin.html b/templates/default/admin.html
index 14654a2..d1e889f 100644
--- a/templates/default/admin.html
+++ b/templates/default/admin.html
@@ -4,15 +4,15 @@
Documentation