From 4c908f48919a8b2a155412e7bd1ce06385735285 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20=C3=85hall?= Date: Thu, 4 Jul 2024 09:25:34 +0200 Subject: [PATCH 1/4] Renamed to werr for wrapped error library --- problem.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/problem.go b/problem.go index 944942c..5e4252e 100644 --- a/problem.go +++ b/problem.go @@ -2,7 +2,7 @@ package main import ( // External - we "git.gibonuddevalla.se/go/wrappederror" + werr "git.gibonuddevalla.se/go/wrappederror" // Standard "database/sql" @@ -77,7 +77,7 @@ func ProblemsRetrieve() (problems []Problem, err error) { // {{{ var jsonBody []byte err = row.Scan(&jsonBody) if err != nil { - err = we.Wrap(err) + err = werr.Wrap(err) return } @@ -87,7 +87,7 @@ func ProblemsRetrieve() (problems []Problem, err error) { // {{{ err = json.Unmarshal(jsonBody, &problems) if err != nil { - err = we.Wrap(err) + err = werr.Wrap(err) } return } // }}} @@ -105,7 +105,7 @@ func ProblemStart(trigger Trigger) (problemID int, err error) { // {{{ var openProblems int err = row.Scan(&openProblems) if err != nil && err != sql.ErrNoRows { - err = we.Wrap(err).WithData(trigger.ID) + err = werr.Wrap(err).WithData(trigger.ID) return } @@ -115,7 +115,7 @@ func ProblemStart(trigger Trigger) (problemID int, err error) { // {{{ row = service.Db.Conn.QueryRow(`INSERT INTO problem(trigger_id, datapoints) VALUES($1, $2) RETURNING id`, trigger.ID, datapointValuesJson) err = row.Scan(&problemID) if err != nil { - err = we.Wrap(err).WithData(trigger) + err = werr.Wrap(err).WithData(trigger) } } return @@ -130,7 +130,7 @@ func ProblemClose(trigger Trigger) (problemID int, err error) { // {{{ } if err != nil { - err = we.Wrap(err).WithData(trigger) + err = werr.Wrap(err).WithData(trigger) return } return @@ -138,13 +138,13 @@ func ProblemClose(trigger Trigger) (problemID int, err error) { // {{{ func ProblemAcknowledge(id int, state bool) (err error) { // {{{ _, err = service.Db.Conn.Exec(`UPDATE problem SET "acknowledged"=$2 WHERE id=$1`, id, state) if err != nil { - err = we.Wrap(err).WithData(id) + err = werr.Wrap(err).WithData(id) return } return } // }}} -func (p Problem) FormattedValues() string { +func (p Problem) FormattedValues() string {// {{{ out := []string{} for key, val := range p.DatapointValues { var keyval string @@ -174,4 +174,4 @@ func (p Problem) FormattedValues() string { sort.Strings(out) return strings.Join(out, "\n") -} +}// }}} From 9700bc9d3c785e83b182ae2c786a4b7038c4e7b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20=C3=85hall?= Date: Thu, 4 Jul 2024 13:29:39 +0200 Subject: [PATCH 2/4] Refactored time filter. --- helper.go | 4 +- main.go | 75 ++++++++-------------- sql/00023.sql | 1 + static/css/default_light/datapoints.css | 22 ------- static/css/default_light/main.css | 34 ++++++++++ static/css/default_light/notifications.css | 34 ---------- static/css/gruvbox/datapoints.css | 22 ------- static/css/gruvbox/main.css | 34 ++++++++++ static/css/gruvbox/notifications.css | 34 ---------- static/js/datapoint_values.js | 20 +++--- static/less/datapoints.less | 27 -------- static/less/main.less | 43 +++++++++++++ static/less/notifications.less | 42 ------------ timefilter.go | 41 ++++++++++++ views/components/timefilter.gotmpl | 61 ++++++++++++++++++ views/pages/notifications.gotmpl | 54 +--------------- 16 files changed, 252 insertions(+), 296 deletions(-) create mode 100644 sql/00023.sql create mode 100644 timefilter.go create mode 100644 views/components/timefilter.gotmpl diff --git a/helper.go b/helper.go index 99541ba..e8fcbe0 100644 --- a/helper.go +++ b/helper.go @@ -63,7 +63,7 @@ func applyTimeOffset(t time.Time, duration time.Duration, amountStr string) time return t.Add(duration * time.Duration(amount)) } // }}} -func presetTimeInterval(duration time.Duration, presetStr string, timeFrom, timeTo *time.Time) () { +func presetTimeInterval(duration time.Duration, presetStr string, timeFrom, timeTo *time.Time) () {// {{{ if presetStr == "" { return } @@ -73,4 +73,4 @@ func presetTimeInterval(duration time.Duration, presetStr string, timeFrom, time (*timeFrom) = now.Add(duration * -1 * time.Duration(presetTime)) (*timeTo) = now return -} +}// }}} diff --git a/main.go b/main.go index 583ff95..5aa3192 100644 --- a/main.go +++ b/main.go @@ -709,31 +709,14 @@ func pageDatapointValues(w http.ResponseWriter, r *http.Request, _ *session.T) { return } - // GET parameters. - display := r.URL.Query().Get("display") - if display == "" && datapoint.Datatype == INT { - display = "graph" - } - + // Manage the values from the timefilter component 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).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).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). - timeFrom = applyTimeOffset(timeFrom, time.Second, r.URL.Query().Get("offset-time")) - timeTo = applyTimeOffset(timeTo, time.Second, r.URL.Query().Get("offset-time")) + timeFrom, timeTo, err = timefilterParse( + r.URL.Query().Get("time-f"), + r.URL.Query().Get("time-t"), + r.URL.Query().Get("time-offset"), + r.URL.Query().Get("time-preset"), + ) // Fetch data point values according to the times. var values []DatapointValue @@ -743,6 +726,12 @@ func pageDatapointValues(w http.ResponseWriter, r *http.Request, _ *session.T) { return } + // GET parameters. + display := r.URL.Query().Get("display") + if display == "" && datapoint.Datatype == INT { + display = "graph" + } + page := Page{ LAYOUT: "main", PAGE: "datapoint_values", @@ -755,9 +744,11 @@ func pageDatapointValues(w http.ResponseWriter, r *http.Request, _ *session.T) { page.Data = map[string]any{ "Datapoint": datapoint, "Values": values, - "TimeFrom": timeFrom.Format("2006-01-02T15:04:05"), - "TimeTo": timeTo.Format("2006-01-02T15:04:05"), "Display": display, + + "TimeSubmit": "/datapoint/values/" + strconv.Itoa(datapoint.ID), + "TimeFrom": timeFrom.Format("2006-01-02T15:04:05"), + "TimeTo": timeTo.Format("2006-01-02T15:04:05"), } page.Render(w, r) return @@ -770,14 +761,14 @@ func actionDatapointJson(w http.ResponseWriter, r *http.Request, _ *session.T) { return } - fromStr := r.URL.Query().Get("f") + fromStr := r.URL.Query().Get("time-f") from, err := time.ParseInLocation("2006-01-02 15:04:05", fromStr[0:min(19, len(fromStr))], smonConfig.Timezone()) if err != nil { httpError(w, werr.Wrap(err).Log()) return } - toStr := r.URL.Query().Get("t") + toStr := r.URL.Query().Get("time-t") to, err := time.ParseInLocation("2006-01-02 15:04:05", toStr[0:min(19, len(toStr))], smonConfig.Timezone()) if err != nil { httpError(w, werr.Wrap(err).Log()) @@ -1198,27 +1189,14 @@ func actionConfigurationNotificationDelete(w http.ResponseWriter, r *http.Reques func pageNotifications(w http.ResponseWriter, r *http.Request, _ *session.T) { // {{{ var err error - // GET parameters. + // Manage the values from the timefilter component var timeFrom, timeTo time.Time - lastWeek := time.Now().Add(time.Duration(-7 * 24 * time.Hour)) - - timeFrom, err = parseHTMLDateTime(r.URL.Query().Get("f"), lastWeek) - if err != nil { - httpError(w, werr.Wrap(err).Log()) - return - } - - timeTo, err = parseHTMLDateTime(r.URL.Query().Get("t"), time.Now()) - if err != nil { - httpError(w, werr.Wrap(err).Log()) - return - } - - presetTimeInterval(time.Hour, r.URL.Query().Get("preset"), &timeFrom, &timeTo) - - // Apply an optionally set offset (in seconds). - timeFrom = applyTimeOffset(timeFrom, time.Second, r.URL.Query().Get("offset-time")) - timeTo = applyTimeOffset(timeTo, time.Second, r.URL.Query().Get("offset-time")) + timeFrom, timeTo, err = timefilterParse( + r.URL.Query().Get("time-f"), + r.URL.Query().Get("time-t"), + r.URL.Query().Get("time-offset"), + r.URL.Query().Get("time-preset"), + ) nss, err := notificationsSent(timeFrom, timeTo) if err != nil { @@ -1231,6 +1209,7 @@ func pageNotifications(w http.ResponseWriter, r *http.Request, _ *session.T) { / CONFIG: smonConfig.Settings, Data: map[string]any{ "Notifications": nss, + "TimeSubmit": "/notifications", "TimeFrom": timeFrom.Format("2006-01-02T15:04:05"), "TimeTo": timeTo.Format("2006-01-02T15:04:05"), }, diff --git a/sql/00023.sql b/sql/00023.sql new file mode 100644 index 0000000..b29ea09 --- /dev/null +++ b/sql/00023.sql @@ -0,0 +1 @@ +ALTER TABLE public.problem ADD COLUMN trigger_expression VARCHAR NOT NULL DEFAULT ''; diff --git a/static/css/default_light/datapoints.css b/static/css/default_light/datapoints.css index a534d2d..14a1aa5 100644 --- a/static/css/default_light/datapoints.css +++ b/static/css/default_light/datapoints.css @@ -99,25 +99,3 @@ .graph #graph-values { height: calc(100vh - 416px); } -.time-offset { - display: grid; - grid-template-columns: min-content repeat(3, min-content); - grid-gap: 16px; - margin-top: 16px; - align-items: center; - justify-items: center; -} -.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/main.css b/static/css/default_light/main.css index 10baf58..4bae369 100644 --- a/static/css/default_light/main.css +++ b/static/css/default_light/main.css @@ -226,3 +226,37 @@ label { width: min-content; border-radius: 8px; } +#time-selector { + display: grid; + grid-template-columns: min-content min-content; + grid-gap: 6px 16px; + width: min-content; + border-radius: 6px; +} +#time-selector button { + width: 100px; + margin-top: 12px; + justify-self: end; +} +#time-selector #time-filter { + display: grid; + grid-template-columns: min-content repeat(3, min-content); + grid-gap: 16px; + margin-top: 16px; + align-items: center; + justify-items: center; +} +#time-selector #time-filter .header-1 { + font-weight: bold; + justify-self: start; +} +#time-selector #time-filter .header-2 { + font-weight: bold; + justify-self: start; + grid-column: 2 / -1; +} +#time-selector #time-filter .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 c747e0d..9dee5c0 100644 --- a/static/css/default_light/notifications.css +++ b/static/css/default_light/notifications.css @@ -1,37 +1,3 @@ -#time-select { - display: grid; - grid-template-columns: min-content min-content; - grid-gap: 6px 16px; - width: min-content; - border-radius: 6px; -} -#time-select button { - width: 100px; - margin-top: 12px; - justify-self: end; -} -#time-select #time-offsets { - display: grid; - grid-template-columns: min-content repeat(3, min-content); - grid-gap: 16px; - margin-top: 16px; - align-items: center; - justify-items: center; -} -#time-select #time-offsets .header-1 { - font-weight: bold; - justify-self: start; -} -#time-select #time-offsets .header-2 { - font-weight: bold; - justify-self: start; - grid-column: 2 / -1; -} -#time-select #time-offsets .preset { - white-space: nowrap; - justify-self: start; - padding-right: 32px; -} input[type="datetime-local"] { padding: 6px; } diff --git a/static/css/gruvbox/datapoints.css b/static/css/gruvbox/datapoints.css index c948a85..fdc0124 100644 --- a/static/css/gruvbox/datapoints.css +++ b/static/css/gruvbox/datapoints.css @@ -99,25 +99,3 @@ .graph #graph-values { height: calc(100vh - 416px); } -.time-offset { - display: grid; - grid-template-columns: min-content repeat(3, min-content); - grid-gap: 16px; - margin-top: 16px; - align-items: center; - justify-items: center; -} -.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/main.css b/static/css/gruvbox/main.css index 98f785f..727b671 100644 --- a/static/css/gruvbox/main.css +++ b/static/css/gruvbox/main.css @@ -226,3 +226,37 @@ label { width: min-content; border-radius: 8px; } +#time-selector { + display: grid; + grid-template-columns: min-content min-content; + grid-gap: 6px 16px; + width: min-content; + border-radius: 6px; +} +#time-selector button { + width: 100px; + margin-top: 12px; + justify-self: end; +} +#time-selector #time-filter { + display: grid; + grid-template-columns: min-content repeat(3, min-content); + grid-gap: 16px; + margin-top: 16px; + align-items: center; + justify-items: center; +} +#time-selector #time-filter .header-1 { + font-weight: bold; + justify-self: start; +} +#time-selector #time-filter .header-2 { + font-weight: bold; + justify-self: start; + grid-column: 2 / -1; +} +#time-selector #time-filter .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 60db03b..1cc900e 100644 --- a/static/css/gruvbox/notifications.css +++ b/static/css/gruvbox/notifications.css @@ -1,37 +1,3 @@ -#time-select { - display: grid; - grid-template-columns: min-content min-content; - grid-gap: 6px 16px; - width: min-content; - border-radius: 6px; -} -#time-select button { - width: 100px; - margin-top: 12px; - justify-self: end; -} -#time-select #time-offsets { - display: grid; - grid-template-columns: min-content repeat(3, min-content); - grid-gap: 16px; - margin-top: 16px; - align-items: center; - justify-items: center; -} -#time-select #time-offsets .header-1 { - font-weight: bold; - justify-self: start; -} -#time-select #time-offsets .header-2 { - font-weight: bold; - justify-self: start; - grid-column: 2 / -1; -} -#time-select #time-offsets .preset { - white-space: nowrap; - justify-self: start; - padding-right: 32px; -} input[type="datetime-local"] { padding: 6px; } diff --git a/static/js/datapoint_values.js b/static/js/datapoint_values.js index 20d0e54..82b0ff7 100644 --- a/static/js/datapoint_values.js +++ b/static/js/datapoint_values.js @@ -1,13 +1,7 @@ -function preset(hours) { - const inputPreset = document.querySelector('input[name="preset"]') - inputPreset.value = hours - inputPreset.form.submit() -} - -function offsetTime(seconds) { - const inputPreset = document.querySelector('input[name="offset-time"]') - inputPreset.value = seconds - inputPreset.form.submit() +function selectDisplay(display) { + const inputDisplay = document.getElementById('input-display') + inputDisplay.value = display + inputDisplay.form.submit() } class Graph { @@ -61,7 +55,9 @@ class Dataset { constructor(id, initialData) { this.datapointID = id this.values = {} - initialData.forEach(v=>this.values[v.ID] = v) + if (initialData === null) + return + initialData.forEach(v => this.values[v.ID] = v) } xValues() { @@ -76,7 +72,7 @@ class Dataset { return fetch(`/datapoint/json/${this.datapointID}?f=${from}&t=${to}`) .then(data => data.json()) .then(datapointValues => { - datapointValues.forEach(dp=>{ + datapointValues.forEach(dp => { this.values[dp.ID] = dp }) document.getElementById('num-values').innerText = Object.keys(this.values).length diff --git a/static/less/datapoints.less b/static/less/datapoints.less index 8391a00..8491560 100644 --- a/static/less/datapoints.less +++ b/static/less/datapoints.less @@ -120,30 +120,3 @@ height: calc(100vh - 416px); } } - -.time-offset { - display: grid; - grid-template-columns: min-content repeat(3, min-content); - grid-gap: 16px; - margin-top: 16px; - - align-items: center; - justify-items: center; - - .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/main.less b/static/less/main.less index aa11833..689ca8f 100644 --- a/static/less/main.less +++ b/static/less/main.less @@ -280,3 +280,46 @@ label { width: min-content; border-radius: 8px; } + +#time-selector { + display: grid; + grid-template-columns: min-content min-content; + grid-gap: 6px 16px; + + width: min-content; + border-radius: 6px; + + button { + width: 100px; + margin-top: 12px; + justify-self: end; + } + + #time-filter { + display: grid; + grid-template-columns: min-content repeat(3, min-content); + grid-gap: 16px; + margin-top: 16px; + + align-items: center; + justify-items: center; + + .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 00f7db7..48a9614 100644 --- a/static/less/notifications.less +++ b/static/less/notifications.less @@ -1,47 +1,5 @@ @import "theme-@{THEME}.less"; -#time-select { - display: grid; - grid-template-columns: min-content min-content; - grid-gap: 6px 16px; - - width: min-content; - border-radius: 6px; - - button { - width: 100px; - margin-top: 12px; - justify-self: end; - } - - #time-offsets { - display: grid; - grid-template-columns: min-content repeat(3, min-content); - grid-gap: 16px; - margin-top: 16px; - - align-items: center; - justify-items: center; - - .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; - } - } -} - input[type="datetime-local"] { padding: 6px; } diff --git a/timefilter.go b/timefilter.go new file mode 100644 index 0000000..8d221db --- /dev/null +++ b/timefilter.go @@ -0,0 +1,41 @@ +package main + +import ( + // External + werr "git.gibonuddevalla.se/go/wrappederror" + + // Standard + "time" +) + +func timefilterParse(timeFromStr, timeToStr, offset, preset string) (timeFrom, timeTo time.Time, err error) { + if preset != "" { + presetTimeInterval(time.Hour, preset, &timeFrom, &timeTo) + return + } + + yesterday := time.Now().Add(time.Duration(-24 * time.Hour)) + timeFrom, err = parseHTMLDateTime(timeFromStr, yesterday) + if err != nil { + err = werr.Wrap(err).WithData(timeFromStr) + return + } + + timeTo, err = parseHTMLDateTime(timeToStr, time.Now()) + if err != nil { + err = werr.Wrap(err).WithData(timeToStr) + return + } + + // Protect the user from switching from/to dates, leading to + // zero matching values from the database. + if timeFrom.After(timeTo) { + timeFrom, timeTo = timeTo, timeFrom + } + + // Apply an optionally set offset (in seconds). + timeFrom = applyTimeOffset(timeFrom, time.Second, offset) + timeTo = applyTimeOffset(timeTo, time.Second, offset) + + return +} diff --git a/views/components/timefilter.gotmpl b/views/components/timefilter.gotmpl new file mode 100644 index 0000000..8742015 --- /dev/null +++ b/views/components/timefilter.gotmpl @@ -0,0 +1,61 @@ +{{ define "timefilter" }} + + + +
+ + + +
+
From
+
To
+ + + + + +
+
Presets
+
Offsets
+ + + + +
Hour
+ + + + + +
Day
+ + + + + +
Week
+ + + + + +
Month
+ +
+ + +
+
+{{ end }} diff --git a/views/pages/notifications.gotmpl b/views/pages/notifications.gotmpl index 2bf8e8a..d99776a 100644 --- a/views/pages/notifications.gotmpl +++ b/views/pages/notifications.gotmpl @@ -10,61 +10,9 @@ evt.target.close() } } - - function preset(hours) { - const inputPreset = document.querySelector('input[name="preset"]') - inputPreset.value = hours - inputPreset.form.submit() - } - - function offsetTime(seconds) { - const el = document.querySelector('input[name="offset-time"]') - el.value = seconds - el.form.submit() - } -
- - - -
-
From
-
To
- - - -
-
Presets
-
Offsets
- - - - -
Hour
- - - - - -
Day
- - - - - -
Week
- - - - - -
Month
- -
- -
-
+ {{ block "timefilter" . }}{{ end }}
Sent
From f7dcb4a07943b0b9876ace1b7796e072138c33d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20=C3=85hall?= Date: Thu, 4 Jul 2024 13:37:06 +0200 Subject: [PATCH 3/4] Added timefilter to problems --- main.go | 20 +++++++++- problem.go | 37 ++++++++++++----- views/pages/datapoint_values.gotmpl | 61 ++++++----------------------- views/pages/problems.gotmpl | 6 ++- 4 files changed, 62 insertions(+), 62 deletions(-) diff --git a/main.go b/main.go index 5aa3192..6f25660 100644 --- a/main.go +++ b/main.go @@ -521,7 +521,21 @@ func pageProblems(w http.ResponseWriter, r *http.Request, _ *session.T) { // {{{ CONFIG: smonConfig.Settings, } - problems, err := ProblemsRetrieve() + // Manage the values from the timefilter component + var err error + var timeFrom, timeTo time.Time + timeFrom, timeTo, err = timefilterParse( + r.URL.Query().Get("time-f"), + r.URL.Query().Get("time-t"), + r.URL.Query().Get("time-offset"), + r.URL.Query().Get("time-preset"), + ) + if err != nil { + httpError(w, err) + return + } + + problems, err := ProblemsRetrieve(true, timeFrom, timeTo) if err != nil { httpError(w, werr.Wrap(err).Log()) return @@ -546,6 +560,10 @@ func pageProblems(w http.ResponseWriter, r *http.Request, _ *session.T) { // {{{ page.Data = map[string]any{ "Problems": problems, "ProblemsGrouped": problemsGrouped, + + "TimeSubmit": "/problems", + "TimeFrom": timeFrom.Format("2006-01-02T15:04:05"), + "TimeTo": timeTo.Format("2006-01-02T15:04:05"), } page.Render(w, r) return diff --git a/problem.go b/problem.go index 5e4252e..24f8151 100644 --- a/problem.go +++ b/problem.go @@ -16,7 +16,7 @@ import ( type Problem struct { // {{{ ID int Start time.Time - End sql.NullTime + End time.Time Acknowledged bool Datapoints map[string]any DatapointValues map[string]any `json:"datapoints"` @@ -26,7 +26,7 @@ type Problem struct { // {{{ SectionName string `json:"section_name"` } // }}} -func ProblemsRetrieve() (problems []Problem, err error) { // {{{ +func ProblemsRetrieve(archived bool, from, to time.Time) (problems []Problem, err error) { // {{{ problems = []Problem{} row := service.Db.Conn.QueryRow(` SELECT @@ -35,7 +35,7 @@ func ProblemsRetrieve() (problems []Problem, err error) { // {{{ (SELECT p.id, p.start, - p.end, + TO_CHAR(p.end, 'YYYY-MM-DD"T"HH24:MI:SSTZH:TZM') AS end, p.acknowledged, p.datapoints, t.id AS trigger_id, @@ -47,12 +47,18 @@ func ProblemsRetrieve() (problems []Problem, err error) { // {{{ INNER JOIN section s ON t.section_id = s.id INNER JOIN area a ON s.area_id = a.id WHERE - p.end IS NULL + CASE + WHEN $1 THEN true + WHEN NOT $1 THEN p.end IS NULL + END AND + p.start >= $2 AND + p.end <= $3 + ORDER BY p.start DESC) UNION ALL - + (SELECT -1 AS id, null, @@ -71,8 +77,11 @@ func ProblemsRetrieve() (problems []Problem, err error) { // {{{ dp.nodata_is_problem ORDER BY dp.name ASC) - ) AS problems - `) + ) AS problems`, + archived, + from, + to, + ) var jsonBody []byte err = row.Scan(&jsonBody) @@ -112,7 +121,12 @@ func ProblemStart(trigger Trigger) (problemID int, err error) { // {{{ // Open up a new problem if no open exists. if openProblems == 0 { datapointValuesJson, _ := json.Marshal(trigger.DatapointValues) - row = service.Db.Conn.QueryRow(`INSERT INTO problem(trigger_id, datapoints) VALUES($1, $2) RETURNING id`, trigger.ID, datapointValuesJson) + row = service.Db.Conn.QueryRow( + `INSERT INTO problem(trigger_id, datapoints, trigger_expression) VALUES($1, $2, $3) RETURNING id`, + trigger.ID, + datapointValuesJson, + trigger.Expression, + ) err = row.Scan(&problemID) if err != nil { err = werr.Wrap(err).WithData(trigger) @@ -144,7 +158,7 @@ func ProblemAcknowledge(id int, state bool) (err error) { // {{{ return } // }}} -func (p Problem) FormattedValues() string {// {{{ +func (p Problem) FormattedValues() string { // {{{ out := []string{} for key, val := range p.DatapointValues { var keyval string @@ -174,4 +188,7 @@ func (p Problem) FormattedValues() string {// {{{ sort.Strings(out) return strings.Join(out, "\n") -}// }}} +} // }}} +func (p Problem) IsArchived() bool { // {{{ + return !p.End.IsZero() +} // }}} diff --git a/views/pages/datapoint_values.gotmpl b/views/pages/datapoint_values.gotmpl index c7d1bc8..40895ae 100644 --- a/views/pages/datapoint_values.gotmpl +++ b/views/pages/datapoint_values.gotmpl @@ -7,56 +7,20 @@ {{ block "page_label" . }}{{end}} -
- - +
+ + +
- {{ if eq .Data.Datapoint.Datatype "INT" }} -
- - -
- {{ end }} + {{ block "timefilter" . }}{{ end }} -
-
Values from
-
Values to
- - - - -
-
Presets
-
Offsets
- - - - -
Hour
- - - - - -
Day
- - - - - -
Week
- - - - - -
Month
- -
- -
- -
+ {{ if $graph }}
@@ -72,7 +36,6 @@ {{ .Data.Datapoint.ID }}, {{ .Data.Values }}, ) - {{ else }}
diff --git a/views/pages/problems.gotmpl b/views/pages/problems.gotmpl index 6076e94..a258601 100644 --- a/views/pages/problems.gotmpl +++ b/views/pages/problems.gotmpl @@ -8,13 +8,15 @@ - {{ block "page_label" . }}{{end}} + {{ block "page_label" . }}{{ end }} -
+
+ {{ block "timefilter" . }}{{ end }} +