diff --git a/datapoint.go b/datapoint.go index 0690bbd..2d2286e 100644 --- a/datapoint.go +++ b/datapoint.go @@ -162,6 +162,8 @@ func DatapointAdd[T any](name string, value T) (err error) { // {{{ return } + service.Db.Conn.Exec(`UPDATE datapoint SET last_value = NOW(), nodata_is_problem = false WHERE id=$1`, dpID) + return } // }}} @@ -170,19 +172,30 @@ func DatapointsRetrieve() (dps []Datapoint, err error) { // {{{ var rows *sqlx.Rows rows, err = service.Db.Conn.Queryx(` SELECT - id, name, datatype, last_value, "group", comment, nodata_problem_seconds, - last_value_id AS v_id, - CASE - WHEN last_value_id IS NULL THEN null - ELSE last_value - END AS ts, - last_value_int AS value_int, - last_value_string AS value_string, - last_value_datetime AS value_datetime - FROM datapoint + dp.id, + dp.name, + dp.datatype, + dp.last_value, + dp.group, + dp.comment, + dp.nodata_problem_seconds, + + dpv.id AS v_id, + dpv.ts, + dpv.value_int, + dpv.value_string, + dpv.value_datetime + + FROM public.datapoint dp + LEFT JOIN ( + SELECT + *, + row_number() OVER (PARTITION BY "datapoint_id" ORDER BY ts DESC) AS rn + FROM datapoint_value + ) dpv ON dpv.datapoint_id = dp.id AND rn = 1 ORDER BY - "group" ASC, - name ASC + dp.group ASC, + dp.name ASC `) if err != nil { err = werr.Wrap(err) @@ -242,11 +255,11 @@ func DatapointRetrieve(id int, name string) (dp Datapoint, err error) { // {{{ var query string var param any if id > 0 { - query = `SELECT id, "group", name, "datatype", comment, last_value, nodata_problem_seconds, nodata_is_problem, true AS found FROM public.datapoint WHERE id = $1` + query = `SELECT *, true AS found FROM datapoint WHERE id = $1` param = id dp.ID = id } else { - query = `SELECT id, "group", name, "datatype", comment, last_value, nodata_problem_seconds, nodata_is_problem, true AS found FROM public.datapoint WHERE name = $1` + query = `SELECT *, true AS found FROM datapoint WHERE name = $1` param = name } diff --git a/main.go b/main.go index d771363..76e4166 100644 --- a/main.go +++ b/main.go @@ -29,7 +29,7 @@ import ( "time" ) -const VERSION = "v41" +const VERSION = "v37" var ( logger *slog.Logger @@ -663,27 +663,6 @@ func pageDatapointEdit(w http.ResponseWriter, r *http.Request, _ *session.T) { / } } - /* Triggers using this datapoint is provided as a list to update - * if changing the datapoint name. Parsing expr and automatically - * changing it to renamed datapoints would be nice in the future. */ - var triggers []Trigger - triggers, err = TriggersRetrieveByDatapoint(datapoint.Name) - if err != nil { - httpError(w, werr.Wrap(err).Log()) - return - } - slices.SortFunc(triggers, func(a, b Trigger) int { - an := strings.ToUpper(a.Name) - bn := strings.ToUpper(b.Name) - if an < bn { - return -1 - } - if an > bn { - return 1 - } - return 0 - }) - page := Page{ LAYOUT: "main", PAGE: "datapoint_edit", @@ -695,7 +674,6 @@ func pageDatapointEdit(w http.ResponseWriter, r *http.Request, _ *session.T) { / page.Data = map[string]any{ "Datapoint": datapoint, - "Triggers": triggers, } page.Render(w, r) return @@ -711,15 +689,8 @@ func actionDatapointUpdate(w http.ResponseWriter, r *http.Request, _ *session.T) var nodataSeconds int nodataSeconds, _ = strconv.Atoi(r.FormValue("nodata_seconds")) - // Datapoint needs to be retrieved from database for the name. - // If name has changed, trigger expressions needs to be updated. var dp Datapoint - dp, err = DatapointRetrieve(id, "") - if err != nil { - httpError(w, werr.Wrap(err).WithData(id).Log()) - return - } - prevDatapointName := dp.Name + dp.ID = id dp.Group = r.FormValue("group") dp.Name = r.FormValue("name") dp.Datatype = DatapointType(r.FormValue("datatype")) @@ -731,29 +702,6 @@ func actionDatapointUpdate(w http.ResponseWriter, r *http.Request, _ *session.T) return } - // Update the trigger expressions using this - // datapoint name if changed. - if prevDatapointName != dp.Name { - var triggers []Trigger - triggers, err = TriggersRetrieveByDatapoint(dp.Name) - if err != nil { - httpError(w, werr.Wrap(err).WithData(dp.Name)) - return - } - for _, trigger := range triggers { - err = trigger.RenameDatapoint(prevDatapointName, dp.Name) - if err != nil { - httpError(w, werr.Wrap(err).WithData([]string{prevDatapointName, dp.Name})) - return - } - err = trigger.Update() - if err != nil { - httpError(w, werr.Wrap(err).WithData([]string{prevDatapointName, dp.Name, trigger.Name})) - return - } - } - } - w.Header().Add("Location", "/datapoints") w.WriteHeader(302) } // }}} diff --git a/notification/ntfy.go b/notification/ntfy.go index 8132d08..0e94516 100644 --- a/notification/ntfy.go +++ b/notification/ntfy.go @@ -81,7 +81,7 @@ func (ntfy NTFY) Send(problemID int, msg []byte) (err error) { ackURL := fmt.Sprintf("http, OK, %s/notification/ack?problemID=%d", ntfy.AcknowledgeURL, problemID) req.Header.Add("X-Actions", ackURL) - req.Header.Add("X-Priority", "5") + req.Header.Add("X-Priority", "4") // XXX: should be 5 req.Header.Add("X-Tags", "calendar") res, err = http.DefaultClient.Do(req) diff --git a/sql/00026.sql b/sql/00026.sql deleted file mode 100644 index 364ccaa..0000000 --- a/sql/00026.sql +++ /dev/null @@ -1,62 +0,0 @@ -/* Adding last values to the datapoint table since they are a regularly used value. */ -ALTER TABLE public.datapoint ADD COLUMN last_value_id int4 NULL; -ALTER TABLE public.datapoint ADD COLUMN last_value_int int8 NULL; -ALTER TABLE public.datapoint ADD COLUMN last_value_string varchar NULL; -ALTER TABLE public.datapoint ADD COLUMN last_value_datetime timestamptz NULL; - - - -/* Once-run query to update it to the latest, to avoid user having to wait for the next entry. */ -UPDATE public.datapoint AS dp -SET - last_value_id = dpv.id, - last_value_int = dpv.value_int, - last_value_string = dpv.value_string, - last_value_datetime = dpv.value_datetime -FROM ( - SELECT - dp.id AS datapoint_id, - dpv.id, - dpv.value_int, - dpv.value_string, - dpv.value_datetime - FROM public.datapoint dp - LEFT JOIN ( - SELECT - *, - row_number() OVER (PARTITION BY "datapoint_id" ORDER BY ts DESC) AS rn - FROM datapoint_value - ) dpv ON dpv.datapoint_id = dp.id AND rn = 1 -) AS dpv -WHERE - dpv.datapoint_id = dp.id; - - - -/* A trigger keeps the value current without bugs introduced in software missing the entry. */ -CREATE OR REPLACE FUNCTION datapoint_entry() - RETURNS TRIGGER - LANGUAGE PLPGSQL - AS -$$ -BEGIN - UPDATE public.datapoint - SET - nodata_is_problem = false, - last_value = NEW.ts, - last_value_id = NEW.id, - last_value_int = NEW.value_int, - last_value_string = NEW.value_string, - last_value_datetime = NEW.value_datetime - WHERE - id = NEW.datapoint_id; - - RETURN NEW; -END; -$$; - -CREATE TRIGGER datapoint_entry - AFTER INSERT - ON public.datapoint_value - FOR EACH ROW - EXECUTE PROCEDURE datapoint_entry(); diff --git a/sql/00027.sql b/sql/00027.sql deleted file mode 100644 index 83a5625..0000000 --- a/sql/00027.sql +++ /dev/null @@ -1,22 +0,0 @@ -/* Updating a datapoint name also updates the jsonb array entry */ -CREATE OR REPLACE FUNCTION update_triggers_datapoint_name() - RETURNS TRIGGER - LANGUAGE PLPGSQL - AS -$$ -BEGIN -UPDATE "trigger" - SET - datapoints = (datapoints - OLD.name) || jsonb_build_array(NEW.name) - WHERE - datapoints ? OLD.name; - - RETURN NEW; -END; -$$; - -CREATE TRIGGER datapoint_renamed - AFTER UPDATE - ON public.datapoint - FOR EACH ROW - EXECUTE PROCEDURE update_triggers_datapoint_name(); diff --git a/static/js/datapoint_edit.mjs b/static/js/datapoint_edit.mjs index e9906e0..dfe5e9c 100644 --- a/static/js/datapoint_edit.mjs +++ b/static/js/datapoint_edit.mjs @@ -1,6 +1,5 @@ export class UI { - constructor(datapointData) { - this.datapoint = datapointData + constructor() { document.addEventListener('keydown', evt=>this.keyHandler(evt)) document.querySelector('input[name="group"]').focus() } diff --git a/trigger.go b/trigger.go index d663564..85f792f 100644 --- a/trigger.go +++ b/trigger.go @@ -4,8 +4,6 @@ import ( // External werr "git.gibonuddevalla.se/go/wrappederror" "github.com/expr-lang/expr" - "github.com/expr-lang/expr/ast" - "github.com/expr-lang/expr/parser" "github.com/lib/pq" // Standard @@ -24,17 +22,6 @@ type Trigger struct { DatapointValues map[string]any } -type ExprRenamePatcher struct { - OldName string - NewName string -} - -func (p ExprRenamePatcher) Visit(node *ast.Node) { - if n, ok := (*node).(*ast.IdentifierNode); ok && n.Value == p.OldName { - ast.Patch(node, &ast.IdentifierNode{Value: p.NewName}) - } -} - func TriggerCreate(sectionID int, name string) (t Trigger, err error) { // {{{ t.SectionID = sectionID t.Name = name @@ -140,14 +127,6 @@ func TriggerRetrieve(id int) (trigger Trigger, err error) { // {{{ err = json.Unmarshal(jsonData, &trigger) return } // }}} -func TriggerDelete(id int) (err error) { // {{{ - _, err = service.Db.Conn.Exec(`DELETE FROM public.trigger WHERE id=$1`, id) - if err != nil { - return werr.Wrap(err).WithData(id) - } - return -} // }}} - func (t *Trigger) Validate() (ok bool, err error) { // {{{ if strings.TrimSpace(t.Name) == "" { err = fmt.Errorf("Name can't be empty") @@ -233,6 +212,14 @@ func (t *Trigger) Update() (err error) { // {{{ } return } // }}} +func TriggerDelete(id int) (err error) { // {{{ + _, err = service.Db.Conn.Exec(`DELETE FROM public.trigger WHERE id=$1`, id) + if err != nil { + return werr.Wrap(err).WithData(id) + } + return +} // }}} + func (t *Trigger) Run() (output any, err error) { // {{{ datapoints := make(map[string]Datapoint) for _, dpname := range t.Datapoints { @@ -261,14 +248,3 @@ func (t *Trigger) Run() (output any, err error) { // {{{ } return } // }}} -func (t *Trigger) RenameDatapoint(from, to string) error { // {{{ - tree, err := parser.Parse(t.Expression) - if err != nil { - return werr.Wrap(err).WithData(t.Expression) - } - - ast.Walk(&tree.Node, ExprRenamePatcher{from, to}) - t.Expression = tree.Node.String() - - return nil -} // }}} diff --git a/views/pages/datapoint_edit.gotmpl b/views/pages/datapoint_edit.gotmpl index 9bb05f8..e4a138b 100644 --- a/views/pages/datapoint_edit.gotmpl +++ b/views/pages/datapoint_edit.gotmpl @@ -3,59 +3,48 @@ {{ block "page_label" . }}{{end}}
-
-
Group
-
+
+
Group
+
-
Name
-
+
Name
+
+ +
Datatype
+
+ +
-
Datatype
-
- -
+
No data
problem time
(seconds)
+
+ +
A problem is raised and notified if an entry isn't made within this time.
+
Set to 0 to disable.
+
-
No data
problem time
(seconds)
-
- -
A problem is raised and notified if an entry isn't made within this time.
-
Set to 0 to disable.
-
- -
Comment
-
- -
+
Comment
+
+ +
-
-
- {{ if eq .Data.Datapoint.ID 0 }} - - {{ else }} - - {{ end }} -
- -
-
- Used in the following triggers: -
    - {{ range .Data.Triggers }} -
  • {{ .Name }}
  • - {{ end }} -
-
+
+
+ {{ if eq .Data.Datapoint.ID 0 }} + + {{ else }} + + {{ end }}