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

-{{if .Warning}} -
-
-

{{.Warning.Header}}

-
- -
+{{if .Message}} +
+
+

{{.Message.Title}}

+
+ +
{{end}}
@@ -45,6 +45,16 @@ + + +
diff --git a/templates/default/assets/custom.css b/templates/default/assets/custom.css index 1184003..c80367c 100644 --- a/templates/default/assets/custom.css +++ b/templates/default/assets/custom.css @@ -46,4 +46,14 @@ svg, footer img { width: 100% } fill: white; } +} + +.success { + background-color: #008000; color: white +} +.warning { + background-color: #807a00; color: white +} +.error { + background-color: #800000; color: white } \ No newline at end of file diff --git a/templates/default/index.html b/templates/default/index.html index 5115c01..cafaa3e 100644 --- a/templates/default/index.html +++ b/templates/default/index.html @@ -1,5 +1,16 @@ +{{if .MOTD}} +
+
+

{{.MOTD.Title}}

+
+ +
+{{end}} +

Green report

@@ -7,7 +18,6 @@ This server's energy statistics for the last eight days (current day included)

-