diff --git a/main.go b/main.go index 98a57bc..8a950fc 100644 --- a/main.go +++ b/main.go @@ -138,6 +138,7 @@ func main() { // {{{ service.Register("/datapoint/update/{id}", false, false, actionDatapointUpdate) service.Register("/datapoint/delete/{id}", false, false, actionDatapointDelete) service.Register("/datapoint/values/{id}", false, false, pageDatapointValues) + service.Register("/datapoint/json/{id}", false, false, actionDatapointJson) service.Register("/triggers", false, false, pageTriggers) service.Register("/trigger/create/{sectionID}/{name}", false, false, actionTriggerCreate) @@ -750,6 +751,37 @@ func pageDatapointValues(w http.ResponseWriter, r *http.Request, _ *session.T) { page.Render(w, r) return } // }}} +func actionDatapointJson(w http.ResponseWriter, r *http.Request, _ *session.T) { // {{{ + idStr := r.PathValue("id") + id, err := strconv.Atoi(idStr) + if err != nil { + httpError(w, werr.Wrap(err).Log()) + return + } + + fromStr := r.URL.Query().Get("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") + 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()) + return + } + + values, err := DatapointValues(id, from, to) + if err != nil { + httpError(w, werr.Wrap(err).Log()) + return + } + + j, _ := json.Marshal(values) + w.Write(j) +} // }}} func pageTriggers(w http.ResponseWriter, r *http.Request, _ *session.T) { // {{{ areas, err := TriggersRetrieve() diff --git a/sql/00021.sql b/sql/00021.sql new file mode 100644 index 0000000..44b3afc --- /dev/null +++ b/sql/00021.sql @@ -0,0 +1 @@ +CREATE INDEX datapoint_value_ts_idx ON public.datapoint_value (ts); diff --git a/static/js/datapoint_values.js b/static/js/datapoint_values.js new file mode 100644 index 0000000..3d6e80d --- /dev/null +++ b/static/js/datapoint_values.js @@ -0,0 +1,73 @@ +function offsetTime(seconds) { + const el = document.getElementById('offset-time') + el.value = seconds + el.form.submit() +} + +class Graph { + constructor(datapointID, initialData) { + this.dataset = new Dataset(datapointID, initialData) + + this.createGraph() + } + + async createGraph() { + this.graphValues = document.getElementById('graph-values'); + + const values = [{ + x: this.dataset.xValues(), + y: this.dataset.yValues(), + }] + + this.layout = { + margin: { + t: 24, + r: 0, + }, + } + + Plotly.react(this.graphValues, values, this.layout); + this.graphValues.on('plotly_relayout', attr => this.relayoutHandler(attr)) + } + + async relayoutHandler(attr) { + if (!attr.hasOwnProperty('xaxis.range[0]') || !attr.hasOwnProperty('xaxis.range[1]')) + return + + this.dataset.extend(attr['xaxis.range[0]'], attr['xaxis.range[1]']) + .then(() => { + const values = [{ + x: this.dataset.xValues(), + y: this.dataset.yValues(), + }] + Plotly.react(this.graphValues, values, this.layout) + }) + } +} + +class Dataset { + constructor(id, initialData) { + this.datapointID = id + this.values = {} + initialData.forEach(v=>this.values[v.ID] = v) + } + + xValues() { + return Object.keys(this.values).map(dpID => this.values[dpID].Ts) + } + + yValues() { + return Object.keys(this.values).map(dpID => this.values[dpID].ValueInt.Int64) + } + + async extend(from, to) { + return fetch(`/datapoint/json/${this.datapointID}?f=${from}&t=${to}`) + .then(data => data.json()) + .then(datapointValues => { + datapointValues.forEach(dp=>{ + this.values[dp.ID] = dp + }) + document.getElementById('num-values').innerText = Object.keys(this.values).length + }) + } +} diff --git a/views/pages/datapoint_values.gotmpl b/views/pages/datapoint_values.gotmpl index 8d49b7b..e645665 100644 --- a/views/pages/datapoint_values.gotmpl +++ b/views/pages/datapoint_values.gotmpl @@ -7,6 +7,7 @@ {{ block "page_label" . }}{{end}}
+ {{ if eq .Data.Datapoint.Datatype "INT" }}
@@ -17,6 +18,7 @@ +

@@ -24,22 +26,17 @@
+ +
+ Number of values: + {{ len .Data.Values }} +
{{ else }}
@@ -48,7 +45,7 @@
{{ range .Data.Values }}
{{ format_time .Ts }}
-
{{ format_time .Value }}
+
{{ .Value }}
{{ end }}
{{ end }}