diff --git a/helper.go b/helper.go index 9b11f15..99541ba 100644 --- a/helper.go +++ b/helper.go @@ -5,8 +5,9 @@ import ( werr "git.gibonuddevalla.se/go/wrappederror" // Standard - "time" "regexp" + "strconv" + "time" ) var rxpTimezone *regexp.Regexp @@ -15,7 +16,7 @@ func init() { rxpTimezone = regexp.MustCompile(`(\d\d)(\d\d)$`) } -func stringToTime(strTime string) (t time.Time, err error) {// {{{ +func stringToTime(strTime string) (t time.Time, err error) { // {{{ // `date` command %z gives timezone like +0200 instead of +02:00. // This can easily be fixed here, not requiring all scripts to be fixed. t, err = time.Parse(time.RFC3339, strTime) @@ -37,8 +38,8 @@ func stringToTime(strTime string) (t time.Time, err error) {// {{{ } return -}// }}} -func parseHTMLDateTime(str string, dflt time.Time) (t time.Time, err error) { +} // }}} +func parseHTMLDateTime(str string, dflt time.Time) (t time.Time, err error) { // {{{ // Browser sending 2024-06-27T10:43 (16 characters) when seconds is 00. if len(str) == 16 { str += ":00" @@ -52,4 +53,24 @@ func parseHTMLDateTime(str string, dflt time.Time) (t time.Time, err error) { } } return +} // }}} + +func applyTimeOffset(t time.Time, duration time.Duration, amountStr string) time.Time { // {{{ + amount, err := strconv.Atoi(amountStr) + if err != nil { + return t + } + + return t.Add(duration * time.Duration(amount)) +} // }}} +func presetTimeInterval(duration time.Duration, presetStr string, timeFrom, timeTo *time.Time) () { + if presetStr == "" { + return + } + + now := time.Now() + presetTime, _ := strconv.Atoi(presetStr) + (*timeFrom) = now.Add(duration * -1 * time.Duration(presetTime)) + (*timeTo) = now + return } diff --git a/main.go b/main.go index 3f69f5d..0466a41 100644 --- a/main.go +++ b/main.go @@ -717,25 +717,23 @@ func pageDatapointValues(w http.ResponseWriter, r *http.Request, _ *session.T) { var timeFrom, timeTo time.Time yesterday := time.Now().Add(time.Duration(-24 * time.Hour)) - timeFrom, err = parseHTMLDateTime(r.URL.Query().Get("f"), yesterday) if err != nil { - httpError(w, werr.Wrap(err).Log()) + httpError(w, werr.Wrap(err).WithData(r.URL.Query().Get("f")).Log()) return } timeTo, err = parseHTMLDateTime(r.URL.Query().Get("t"), time.Now()) if err != nil { - httpError(w, werr.Wrap(err).Log()) + httpError(w, werr.Wrap(err).WithData(r.URL.Query().Get("t")).Log()) return } + presetTimeInterval(time.Hour, r.URL.Query().Get("preset"), &timeFrom, &timeTo) + // Apply an optionally set offset (in seconds). - var offsetTime int - offsetTimeStr := r.URL.Query().Get("offset-time") - offsetTime, err = strconv.Atoi(offsetTimeStr) - timeFrom = timeFrom.Add(time.Second * time.Duration(offsetTime)) - timeTo = timeTo.Add(time.Second * time.Duration(offsetTime)) + timeFrom = applyTimeOffset(timeFrom, time.Second, r.URL.Query().Get("offset-time")) + timeTo = applyTimeOffset(timeTo, time.Second, r.URL.Query().Get("offset-time")) // Fetch data point values according to the times. var values []DatapointValue @@ -1216,25 +1214,11 @@ func pageNotifications(w http.ResponseWriter, r *http.Request, _ *session.T) { / return } - var presetTime int - now := time.Now() - presetStr := r.URL.Query().Get("preset") - if presetStr != "" { - presetTime, err = strconv.Atoi(presetStr) - if err != nil { - pageError(w, "/notifications", werr.Wrap(err).WithData(presetStr).Log()) - return - } - timeFrom = now.Add(time.Hour * -1 * time.Duration(presetTime)) - timeTo = now - } + presetTimeInterval(time.Hour, r.URL.Query().Get("preset"), &timeFrom, &timeTo) // Apply an optionally set offset (in seconds). - var offsetTime int - offsetTimeStr := r.URL.Query().Get("offset-time") - offsetTime, err = strconv.Atoi(offsetTimeStr) - timeFrom = timeFrom.Add(time.Second * time.Duration(offsetTime)) - timeTo = timeTo.Add(time.Second * time.Duration(offsetTime)) + timeFrom = applyTimeOffset(timeFrom, time.Second, r.URL.Query().Get("offset-time")) + timeTo = applyTimeOffset(timeTo, time.Second, r.URL.Query().Get("offset-time")) nss, err := notificationsSent(timeFrom, timeTo) if err != nil { diff --git a/notification_log.go b/notification_log.go index 5445833..e1f7c2a 100644 --- a/notification_log.go +++ b/notification_log.go @@ -48,7 +48,7 @@ func notificationsSent(from, to time.Time) (nss []NotificationSend, err error) { n.prio, n.service, - COALESCE(t.name, '') AS trigger_name, + COALESCE(t.name, '[NODATA]') AS trigger_name, ns.id, ns.uuid, diff --git a/static/css/default_light/datapoints.css b/static/css/default_light/datapoints.css index 5de69e1..c2e4a29 100644 --- a/static/css/default_light/datapoints.css +++ b/static/css/default_light/datapoints.css @@ -85,8 +85,8 @@ } .value-selector button { width: 100px; - align-self: end; justify-self: end; + margin-top: 16px; } .graph { width: 99%; @@ -98,9 +98,23 @@ } .time-offset { display: grid; - grid-template-columns: repeat(3, min-content); - gap: 6px 12px; + grid-template-columns: min-content repeat(3, min-content); + grid-gap: 16px; + margin-top: 16px; align-items: center; justify-items: center; - margin-top: 8px; +} +.time-offset .header-1 { + font-weight: bold; + justify-self: start; +} +.time-offset .header-2 { + font-weight: bold; + justify-self: start; + grid-column: 2 / -1; +} +.time-offset .preset { + white-space: nowrap; + justify-self: start; + padding-right: 32px; } diff --git a/static/css/default_light/notifications.css b/static/css/default_light/notifications.css index a39d982..c747e0d 100644 --- a/static/css/default_light/notifications.css +++ b/static/css/default_light/notifications.css @@ -2,8 +2,6 @@ display: grid; grid-template-columns: min-content min-content; grid-gap: 6px 16px; - padding: 16px; - border: 1px solid #7bb8eb; width: min-content; border-radius: 6px; } diff --git a/static/css/gruvbox/datapoints.css b/static/css/gruvbox/datapoints.css index 9be5ce8..3cc0ac3 100644 --- a/static/css/gruvbox/datapoints.css +++ b/static/css/gruvbox/datapoints.css @@ -85,8 +85,8 @@ } .value-selector button { width: 100px; - align-self: end; justify-self: end; + margin-top: 16px; } .graph { width: 99%; @@ -98,9 +98,23 @@ } .time-offset { display: grid; - grid-template-columns: repeat(3, min-content); - gap: 6px 12px; + grid-template-columns: min-content repeat(3, min-content); + grid-gap: 16px; + margin-top: 16px; align-items: center; justify-items: center; - margin-top: 8px; +} +.time-offset .header-1 { + font-weight: bold; + justify-self: start; +} +.time-offset .header-2 { + font-weight: bold; + justify-self: start; + grid-column: 2 / -1; +} +.time-offset .preset { + white-space: nowrap; + justify-self: start; + padding-right: 32px; } diff --git a/static/css/gruvbox/notifications.css b/static/css/gruvbox/notifications.css index aaeab41..60db03b 100644 --- a/static/css/gruvbox/notifications.css +++ b/static/css/gruvbox/notifications.css @@ -2,8 +2,6 @@ display: grid; grid-template-columns: min-content min-content; grid-gap: 6px 16px; - padding: 16px; - border: 1px solid #777; width: min-content; border-radius: 6px; } diff --git a/static/js/datapoint_values.js b/static/js/datapoint_values.js index b05af39..20d0e54 100644 --- a/static/js/datapoint_values.js +++ b/static/js/datapoint_values.js @@ -1,7 +1,13 @@ +function preset(hours) { + const inputPreset = document.querySelector('input[name="preset"]') + inputPreset.value = hours + inputPreset.form.submit() +} + function offsetTime(seconds) { - const el = document.getElementById('offset-time') - el.value = seconds - el.form.submit() + const inputPreset = document.querySelector('input[name="offset-time"]') + inputPreset.value = seconds + inputPreset.form.submit() } class Graph { diff --git a/static/less/datapoints.less b/static/less/datapoints.less index faa13a4..d1486aa 100644 --- a/static/less/datapoints.less +++ b/static/less/datapoints.less @@ -102,8 +102,8 @@ button { width: 100px; - align-self: end; justify-self: end; + margin-top: 16px; } } @@ -119,9 +119,27 @@ .time-offset { display: grid; - grid-template-columns: repeat(3, min-content); - gap: 6px 12px; + grid-template-columns: min-content repeat(3, min-content); + grid-gap: 16px; + margin-top: 16px; + align-items: center; justify-items: center; - margin-top: 8px; + + .header-1 { + font-weight: bold; + justify-self: start; + } + + .header-2 { + font-weight: bold; + justify-self: start; + grid-column: ~"2 / -1"; + } + + .preset { + white-space: nowrap; + justify-self: start; + padding-right: 32px; + } } diff --git a/static/less/notifications.less b/static/less/notifications.less index 62037d6..00f7db7 100644 --- a/static/less/notifications.less +++ b/static/less/notifications.less @@ -5,13 +5,10 @@ grid-template-columns: min-content min-content; grid-gap: 6px 16px; - padding: 16px; - border: 1px solid @text3; width: min-content; border-radius: 6px; button { - //grid-column: ~"1 / -1"; width: 100px; margin-top: 12px; justify-self: end; diff --git a/views/pages/datapoint_values.gotmpl b/views/pages/datapoint_values.gotmpl index 30b5afa..c7d1bc8 100644 --- a/views/pages/datapoint_values.gotmpl +++ b/views/pages/datapoint_values.gotmpl @@ -8,7 +8,8 @@ {{ block "page_label" . }}{{end}}
- + + {{ if eq .Data.Datapoint.Datatype "INT" }}
@@ -25,17 +26,32 @@
+
Presets
+
Offsets
+ + +
Hour
+ +
Day
-
+ + +
Week
-
+
+ + + +
+
Month
+
diff --git a/views/pages/notifications.gotmpl b/views/pages/notifications.gotmpl index afe39b3..2bf8e8a 100644 --- a/views/pages/notifications.gotmpl +++ b/views/pages/notifications.gotmpl @@ -56,7 +56,7 @@
Week
-
Last 31 days
+
Last 31 days
Month