diff --git a/main.go b/main.go index 6e368a1..7424767 100644 --- a/main.go +++ b/main.go @@ -25,7 +25,6 @@ import ( "slices" "sort" "strconv" - "strings" "time" ) @@ -153,8 +152,6 @@ func main() { // {{{ service.Register("/configuration", false, false, pageConfiguration) service.Register("/configuration/theme", false, false, actionConfigurationTheme) service.Register("/configuration/timezone", false, false, actionConfigurationTimezone) - service.Register("/configuration/notification", false, false, pageConfigurationNotification) - service.Register("/configuration/notification/update/{prio}", false, false, actionConfigurationNotificationUpdate) service.Register("/entry/{datapoint}", false, false, actionEntryDatapoint) go nodataLoop() @@ -382,9 +379,9 @@ func getPage(layout, page string) (tmpl *template.Template, err error) { // {{{ filenames = append(filenames, componentFilenames...) logger.Info("template", "op", "parse", "layout", layout, "page", page, "filenames", filenames) if flagDev { - tmpl, err = template.New(layout+".gotmpl").Funcs(funcMap).ParseFS(os.DirFS("."), filenames...) + tmpl, err = template.New("main.gotmpl").Funcs(funcMap).ParseFS(os.DirFS("."), filenames...) } else { - tmpl, err = template.New(layout+".gotmpl").Funcs(funcMap).ParseFS(viewFS, filenames...) + tmpl, err = template.New("main.gotmpl").Funcs(funcMap).ParseFS(viewFS, filenames...) } if err != nil { err = werr.Wrap(err).Log() @@ -1039,9 +1036,7 @@ func pageConfiguration(w http.ResponseWriter, r *http.Request, _ *session.T) { / PAGE: "configuration", CONFIG: smonConfig.Settings, Data: map[string]any{ - "Areas": areas, - "NotificationServices": notificationManager.Services(), - "AvailableServices": notification.AvailableServices(), + "Areas": areas, }, } @@ -1076,105 +1071,3 @@ func actionConfigurationTimezone(w http.ResponseWriter, r *http.Request, _ *sess w.Header().Add("Location", "/configuration") w.WriteHeader(302) } // }}} -func pageConfigurationNotification(w http.ResponseWriter, r *http.Request, _ *session.T) { // {{{ - // This function is either receiving a type when creating a new service, - // or a prio when editing an existing. - notificationType := r.URL.Query().Get("type") - prioStr := r.URL.Query().Get("prio") - - var service notification.Service - if notificationType != "" { - // Create a new instance of the selected notification type. - service = notification.GetInstance(notificationType) - } else { - // Find the existing service for editing. - prio, err := strconv.Atoi(prioStr) - if err != nil { - httpError(w, werr.Wrap(err).Log()) - return - } - service = *notificationManager.GetService(prio) - } - - if service == nil { - data := struct { - typ string - prio string - }{notificationType, prioStr} - err := fmt.Errorf("Invalid service") - pageError(w, "/configuration", werr.Wrap(err).WithData(data).Log()) - return - } - - // Make it easier for the user by initiating the prio field - // for new notifications to the highest prio + 1. - if notificationType != "" { - prio := 0 - for _, svc := range notificationManager.Services() { - prio = max(prio, svc.GetPrio()+1) - } - service.SetPrio(prio) - } - - page := Page{ - LAYOUT: "notification", - PAGE: "notification/" + strings.ToLower(service.GetType()), - CONFIG: smonConfig.Settings, - Data: map[string]any{ - "Service": service, - }, - } - - page.Render(w, r) -} // }}} -func actionConfigurationNotificationUpdate(w http.ResponseWriter, r *http.Request, _ *session.T) { // {{{ - prioStr := r.PathValue("prio") - prio, err := strconv.Atoi(prioStr) - if err != nil { - pageError(w, "/configuration", werr.Wrap(err).Log()) - return - } - - // prio -1 means a new service, not existing in database. - var svc *notification.Service - if prio == -1 { - emptyService := notification.GetInstance(r.PostFormValue("type")) - svc = &emptyService - } else { - svc = notificationManager.GetService(prio) - if svc == nil { - pageError(w, "/configuration", werr.New("Service with prio %d not found", prio).Log()) - return - } - } - - // The service is given all data to give it a chance to - // validate and throwing errors. - err = r.ParseForm() - if err != nil { - pageError(w, "/configuration", werr.Wrap(err).Log()) - return - } - - err = (*svc).Update(r.PostForm) - if err != nil { - pageError(w, "/configuration", werr.Wrap(err).Log()) - return - } - - var created bool - created, err = UpdateNotificationService(*svc) - if err != nil { - pageError(w, "/configuration", werr.Wrap(err).Log()) - return - } - - (*svc).Commit() - - if created { - notificationManager.AddService(*svc) - } - - w.Header().Add("Location", "/configuration") - w.WriteHeader(302) -} // }}} diff --git a/notification/factory.go b/notification/factory.go index 4c7e25f..90c5cfe 100644 --- a/notification/factory.go +++ b/notification/factory.go @@ -6,12 +6,6 @@ import ( // Standard "log/slog" - "slices" - "strings" -) - -var ( - allServices []Service ) func ServiceFactory(t string, config []byte, prio int, ackURL string, logger *slog.Logger) (Service, error) { @@ -36,25 +30,3 @@ func ServiceFactory(t string, config []byte, prio int, ackURL string, logger *sl return nil, werr.New("Unknown notification service, '%s'", t).WithCode("002-0000") } - -func GetInstance(typ string) Service { - for _, svc := range allServices { - if strings.ToLower(svc.GetType()) == strings.ToLower(typ) { - return svc - } - } - return nil -} - -func AvailableServices() []Service { - slices.SortFunc(allServices, func(a, b Service) int { - if a.GetType() < b.GetType() { - return -1 - } - if a.GetType() > b.GetType() { - return 1 - } - return 0 - }) - return allServices -} diff --git a/notification/ntfy.go b/notification/ntfy.go index 0e94516..51b5896 100644 --- a/notification/ntfy.go +++ b/notification/ntfy.go @@ -11,9 +11,6 @@ import ( "io" "log/slog" "net/http" - "net/url" - "strconv" - "strings" ) type NTFY struct { @@ -21,13 +18,6 @@ type NTFY struct { Prio int AcknowledgeURL string logger *slog.Logger - - exists bool - updated Service -} - -func init() { - allServices = append(allServices, &NTFY{}) } func NewNTFY(config []byte, prio int, ackURL string) (instance *NTFY, err error) { @@ -54,22 +44,6 @@ func (ntfy *NTFY) GetPrio() int { return ntfy.Prio } -func (ntfy *NTFY) SetPrio(prio int) { - ntfy.Prio = prio -} - -func (ntfy *NTFY) SetExists(exists bool) { - ntfy.exists = exists -} - -func (ntfy NTFY) Exists() bool { - return ntfy.exists -} - -func (ntfy *NTFY) String() string { - return ntfy.URL -} - func (ntfy NTFY) Send(problemID int, msg []byte) (err error) { var req *http.Request var res *http.Response @@ -107,40 +81,3 @@ func (ntfy NTFY) Send(problemID int, msg []byte) (err error) { return } - -func (ntfy *NTFY) Update(values url.Values) (err error) { - updated := NTFY{} - ntfy.updated = &updated - - updated.Prio, err = strconv.Atoi(values.Get("prio")) - if err != nil { - return werr.Wrap(err) - } - - givenURL := values.Get("url") - if strings.TrimSpace(givenURL) == "" { - return werr.New("URL cannot be empty") - } - updated.URL = strings.TrimSpace(givenURL) - return -} - -func (ntfy *NTFY) Updated() Service { - return ntfy.updated -} - -func (ntfy *NTFY) Commit() { - updatedNTFY := ntfy.updated.(*NTFY) - ntfy.Prio = updatedNTFY.Prio - ntfy.URL = updatedNTFY.URL -} - -func (ntfy NTFY) JSON() []byte { - data := struct { - URL string `json:"url"` - }{ - ntfy.URL, - } - j, _ := json.Marshal(data) - return j -} diff --git a/notification/pkg.go b/notification/pkg.go index dba9747..cc8bbcc 100644 --- a/notification/pkg.go +++ b/notification/pkg.go @@ -6,7 +6,6 @@ import ( // Standard "log/slog" - "net/url" "slices" ) @@ -14,15 +13,7 @@ type Service interface { SetLogger(*slog.Logger) GetPrio() int GetType() string - SetPrio(int) - SetExists(bool) // Exists in database - Exists() bool // Exists in database - String() string Send(int, []byte) error - Update(url.Values) error - Updated() Service - Commit() - JSON() []byte } type Manager struct { @@ -37,7 +28,6 @@ func NewManager(logger *slog.Logger) (nm Manager) { } func (nm *Manager) AddService(service Service) { - service.SetExists(true) nm.services = append(nm.services, service) slices.SortFunc(nm.services, func(a, b Service) int { if a.GetPrio() < b.GetPrio() { @@ -50,16 +40,6 @@ func (nm *Manager) AddService(service Service) { }) } -func (nm *Manager) GetService(prio int) *Service { - for _, svc := range nm.services { - if svc.GetPrio() == prio { - return &svc - } - } - - return nil -} - func (nm *Manager) Send(problemID int, msg []byte, fn func(*Service, error)) (err error) { for i, service := range nm.services { nm.logger.Info("notification", "service", service.GetType(), "prio", service.GetPrio()) @@ -69,7 +49,7 @@ func (nm *Manager) Send(problemID int, msg []byte, fn func(*Service, error)) (er } else { data := struct { ProblemID int - Msg []byte + Msg []byte }{ problemID, msg, @@ -81,7 +61,3 @@ func (nm *Manager) Send(problemID int, msg []byte, fn func(*Service, error)) (er return } - -func (nm *Manager) Services() (services []Service) { - return nm.services -} diff --git a/notification/script.go b/notification/script.go index ab6492f..1e8fcca 100644 --- a/notification/script.go +++ b/notification/script.go @@ -7,7 +7,6 @@ import ( // Standard "encoding/json" "log/slog" - "net/url" "os/exec" "strconv" "strings" @@ -18,13 +17,6 @@ type Script struct { Prio int AcknowledgeURL string logger *slog.Logger - - exists bool - updated Service -} - -func init() { - allServices = append(allServices, &Script{}) } func NewScript(config []byte, prio int, ackURL string) (instance *Script, err error) { @@ -51,22 +43,6 @@ func (script *Script) GetPrio() int { return script.Prio } -func (script *Script) SetPrio(prio int) { - script.Prio = prio -} - -func (script *Script) SetExists(exists bool) { - script.exists = exists -} - -func (script Script) Exists() bool { - return script.exists -} - -func (script *Script) String() string { - return script.Filename -} - func (script Script) Send(problemID int, msg []byte) (err error) { var errbuf strings.Builder cmd := exec.Command(script.Filename, strconv.Itoa(problemID), script.AcknowledgeURL, string(msg)) @@ -92,40 +68,3 @@ func (script Script) Send(problemID int, msg []byte) (err error) { return } - -func (script *Script) Update(values url.Values) (err error) { - updated := Script{} - updated.Prio, err = strconv.Atoi(values.Get("prio")) - if err != nil { - return werr.Wrap(err) - } - - givenFilename := values.Get("filename") - if strings.TrimSpace(givenFilename) == "" { - return werr.New("Filename cannot be empty") - } - updated.Filename = strings.TrimSpace(givenFilename) - - script.updated = &updated - return -} - -func (script *Script) Updated() Service { - return script.updated -} - -func (script *Script) Commit() { - updated := script.updated.(*Script) - script.Prio = updated.Prio - script.Filename = updated.Filename -} - -func (script Script) JSON() []byte { - data := struct { - Filename string `json:"filename"` - }{ - script.Filename, - } - j, _ := json.Marshal(data) - return j -} diff --git a/notification_manager.go b/notification_manager.go index 74b2691..328819b 100644 --- a/notification_manager.go +++ b/notification_manager.go @@ -3,7 +3,6 @@ package main import ( // External werr "git.gibonuddevalla.se/go/wrappederror" - "github.com/lib/pq" // Internal "smon/notification" @@ -68,61 +67,13 @@ func InitNotificationManager() (nm notification.Manager, err error) { // {{{ return } // }}} -func UpdateNotificationService(svc notification.Service) (created bool, err error) { // {{{ - if svc.Exists() { - _, err = service.Db.Conn.Exec( - ` - UPDATE public.notification - SET - prio=$2, - configuration=$3 - WHERE - prio=$1 - `, - svc.GetPrio(), - svc.Updated().GetPrio(), - svc.Updated().JSON(), - ) - } else { - _, err = service.Db.Conn.Exec( - ` - INSERT INTO public.notification(prio, configuration, service) - VALUES($1, $2, $3) - - `, - svc.Updated().GetPrio(), - svc.Updated().JSON(), - svc.GetType(), - ) - created = true - } - - if err != nil { - // Check if this is just a duplicated prio, which isn't allowed. - pgErr, isPgErr := err.(*pq.Error) - if isPgErr && pgErr.Code == "23505" { - return false, werr.New("Prio %d is already used by another service", svc.GetPrio()) - } - - return false, werr.Wrap(err).WithData( - struct { - Prio int - Configuration []byte - }{ - svc.GetPrio(), - svc.JSON(), - }, - ) - } - return -} // }}} func AcknowledgeNotification(uuid string) (err error) { // {{{ /* - _, err = service.Db.Conn.Exec(`UPDATE schedule SET acknowledged=true WHERE schedule_uuid=$1`, uuid) - if err != nil { - err = werr.Wrap(err).WithData(uuid) - } + _, err = service.Db.Conn.Exec(`UPDATE schedule SET acknowledged=true WHERE schedule_uuid=$1`, uuid) + if err != nil { + err = werr.Wrap(err).WithData(uuid) + } */ return } // }}} diff --git a/static/css/default_light/configuration.css b/static/css/default_light/configuration.css index 715f085..83a9658 100644 --- a/static/css/default_light/configuration.css +++ b/static/css/default_light/configuration.css @@ -24,20 +24,3 @@ #areas .area .section.configuration img { height: 16px; } -#services { - display: grid; - grid-template-columns: repeat(3, min-content); - gap: 10px 24px; - background-color: #2979b8; - width: min-content; - padding: 16px; - border-top-left-radius: 8px; - border-top-right-radius: 8px; - margin-top: 16px; -} -#services .header { - font-weight: bold; -} -#services div { - white-space: nowrap; -} diff --git a/static/css/default_light/default_light.css b/static/css/default_light/default_light.css index 57e3f8c..7b269fc 100644 --- a/static/css/default_light/default_light.css +++ b/static/css/default_light/default_light.css @@ -43,8 +43,7 @@ button:focus { #datapoints, #problems-list, #acknowledged-list, -#values, -#services { +#values { background-color: #fff !important; border: 1px solid #ddd; box-shadow: 5px 5px 8px 0px rgba(0, 0, 0, 0.25); diff --git a/static/css/default_light/gruvbox.css b/static/css/default_light/gruvbox.css index 54b45b4..621bb00 100644 --- a/static/css/default_light/gruvbox.css +++ b/static/css/default_light/gruvbox.css @@ -4,9 +4,3 @@ body { #areas .area { box-shadow: 5px 5px 15px 0px rgba(0, 0, 0, 0.5); } -#page-error { - border: unset; - color: #fff; - background-color: #a00; - text-align: center; -} diff --git a/static/css/gruvbox/configuration.css b/static/css/gruvbox/configuration.css index 063f37d..83a9658 100644 --- a/static/css/gruvbox/configuration.css +++ b/static/css/gruvbox/configuration.css @@ -24,20 +24,3 @@ #areas .area .section.configuration img { height: 16px; } -#services { - display: grid; - grid-template-columns: repeat(3, min-content); - gap: 10px 24px; - background-color: #333; - width: min-content; - padding: 16px; - border-top-left-radius: 8px; - border-top-right-radius: 8px; - margin-top: 16px; -} -#services .header { - font-weight: bold; -} -#services div { - white-space: nowrap; -} diff --git a/static/css/gruvbox/default_light.css b/static/css/gruvbox/default_light.css index 3361608..dd367fa 100644 --- a/static/css/gruvbox/default_light.css +++ b/static/css/gruvbox/default_light.css @@ -43,8 +43,7 @@ button:focus { #datapoints, #problems-list, #acknowledged-list, -#values, -#services { +#values { background-color: #fff !important; border: 1px solid #ddd; box-shadow: 5px 5px 8px 0px rgba(0, 0, 0, 0.25); diff --git a/static/css/gruvbox/gruvbox.css b/static/css/gruvbox/gruvbox.css index 54b45b4..621bb00 100644 --- a/static/css/gruvbox/gruvbox.css +++ b/static/css/gruvbox/gruvbox.css @@ -4,9 +4,3 @@ body { #areas .area { box-shadow: 5px 5px 15px 0px rgba(0, 0, 0, 0.5); } -#page-error { - border: unset; - color: #fff; - background-color: #a00; - text-align: center; -} diff --git a/static/js/datapoint_values.js b/static/js/datapoint_values.js index b05af39..3d6e80d 100644 --- a/static/js/datapoint_values.js +++ b/static/js/datapoint_values.js @@ -17,7 +17,6 @@ class Graph { const values = [{ x: this.dataset.xValues(), y: this.dataset.yValues(), - mode: 'scatter', }] this.layout = { @@ -27,11 +26,7 @@ class Graph { }, } - this.config = { - displayModeBar: true, - } - - Plotly.react(this.graphValues, values, this.layout, this.config); + Plotly.react(this.graphValues, values, this.layout); this.graphValues.on('plotly_relayout', attr => this.relayoutHandler(attr)) } @@ -44,7 +39,6 @@ class Graph { const values = [{ x: this.dataset.xValues(), y: this.dataset.yValues(), - mode: 'scatter', }] Plotly.react(this.graphValues, values, this.layout) }) diff --git a/static/less/configuration.less b/static/less/configuration.less index b1c41fd..33a8323 100644 --- a/static/less/configuration.less +++ b/static/less/configuration.less @@ -36,23 +36,3 @@ } } } - -#services { - display: grid; - grid-template-columns: repeat(3, min-content); - gap: 10px 24px; - background-color: @bg3; - width: min-content; - padding: 16px; - border-top-left-radius: 8px; - border-top-right-radius: 8px; - margin-top: 16px; - - .header { - font-weight: bold; - } - - div { - white-space: nowrap; - } -} diff --git a/static/less/default_light.less b/static/less/default_light.less index 542a083..27d85a9 100644 --- a/static/less/default_light.less +++ b/static/less/default_light.less @@ -58,7 +58,7 @@ button { } } -#datapoints, #problems-list, #acknowledged-list, #values, #services { +#datapoints, #problems-list, #acknowledged-list, #values { background-color: #fff !important; border: 1px solid #ddd; box-shadow: 5px 5px 8px 0px rgba(0,0,0,0.25); diff --git a/static/less/gruvbox.less b/static/less/gruvbox.less index cce1dc3..6beb230 100644 --- a/static/less/gruvbox.less +++ b/static/less/gruvbox.less @@ -9,10 +9,3 @@ body { box-shadow: 5px 5px 15px 0px rgba(0,0,0,0.5); } } - -#page-error { - border: unset; - color: #fff; - background-color: #a00; - text-align: center; -} diff --git a/views/layouts/main.gotmpl b/views/layouts/main.gotmpl index b82b49f..956a25d 100644 --- a/views/layouts/main.gotmpl +++ b/views/layouts/main.gotmpl @@ -6,6 +6,18 @@ {{ template "fonts" }} + + + + + +
diff --git a/views/layouts/notification.gotmpl b/views/layouts/notification.gotmpl deleted file mode 100644 index 62d95a8..0000000 --- a/views/layouts/notification.gotmpl +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - {{ template "fonts" }} - - - - -
-
- {{ .ERROR }} -
-
- {{ block "page" . }}{{ end }} -
- - diff --git a/views/pages/configuration.gotmpl b/views/pages/configuration.gotmpl index aab74c3..3a9de49 100644 --- a/views/pages/configuration.gotmpl +++ b/views/pages/configuration.gotmpl @@ -62,12 +62,6 @@ return location.href = `/section/delete/${id}` } - - function newNotification() { - const select = document.getElementById('notification-create-type') - const nType = select.value - location.href = `/configuration/notification?type=${nType}` - } {{ block "page_label" . }}{{end}} @@ -114,24 +108,4 @@ -

Notifications

- - - -
-
Prio
-
Type
-
Target
-
- {{ range .Data.NotificationServices }} -
{{ .GetPrio }}
-
{{ .GetType }}
-
{{ .String }}
- {{ end }} -
- {{ end }} diff --git a/views/pages/notification/ntfy.gotmpl b/views/pages/notification/ntfy.gotmpl deleted file mode 100644 index 8408272..0000000 --- a/views/pages/notification/ntfy.gotmpl +++ /dev/null @@ -1,34 +0,0 @@ -{{ define "page" }} -

NTFY

- - -
- -
-
Prio:
- - -
URL:
- - - -
-
-{{ end }} diff --git a/views/pages/notification/script.gotmpl b/views/pages/notification/script.gotmpl deleted file mode 100644 index a408d4a..0000000 --- a/views/pages/notification/script.gotmpl +++ /dev/null @@ -1,34 +0,0 @@ -{{ define "page" }} -

Script

- - -
- -
-
Prio:
- - -
Filename:
- - - -
-
-{{ end }}