From e68a66f5ce54d5e8d00cf8a0ab66fec75b52ee06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20=C3=85hall?= Date: Sun, 23 Aug 2026 10:18:00 +0200 Subject: [PATCH] Selectable dashboards --- dashboard.go | 17 ++++++++ main.go | 15 ++++++- static/js/dashboard.mjs | 90 +++++++++++++++++++++++++++++++--------- views/pages/index.gotmpl | 2 + 4 files changed, 102 insertions(+), 22 deletions(-) diff --git a/dashboard.go b/dashboard.go index dfb29a9..3103fe3 100644 --- a/dashboard.go +++ b/dashboard.go @@ -34,6 +34,23 @@ type Dashboard struct { Widgets []Widget } +func Dashboards() (dashboards []Dashboard, err error) { + var rows pgx.Rows + rows, err = db.Query(context.Background(), `SELECT * FROM dashboard ORDER BY name ASC`) + if err != nil { + err = werr.Wrap(err) + return + } + + dashboards, err = pgx.CollectRows(rows, pgx.RowToStructByNameLax[Dashboard]) + if err != nil { + err = werr.Wrap(err) + return + } + + return +} + func DashboardGet(name string) (dashboard Dashboard, err error) { var rows pgx.Rows rows, err = db.Query(context.Background(), `SELECT * FROM dashboard WHERE name = $1`, name) diff --git a/main.go b/main.go index 4094aec..b59f715 100644 --- a/main.go +++ b/main.go @@ -409,13 +409,24 @@ func pageIndex(w http.ResponseWriter, r *http.Request) { // {{{ CONFIG: smonConfig.Settings, } - dashboard, err := DashboardGet("start") + dashboards, err := Dashboards() if err != nil { logger.Error("dashboard", "error", err) } + dbname := r.URL.Query().Get("dashboard") + var start Dashboard + var names []string + for _, dash := range dashboards { + if (dbname == "" && dash.Name == "start") || (dbname != "" && dash.Name == dbname) { + start = dash + } + names = append(names, dash.Name) + } + data := make(map[string]any) - data["Dashboard"] = dashboard + data["Dashboard"] = start + data["Dashboards"] = names page.Data = data page.Render(w, r) } // }}} diff --git a/static/js/dashboard.mjs b/static/js/dashboard.mjs index a6655ef..e2d5316 100644 --- a/static/js/dashboard.mjs +++ b/static/js/dashboard.mjs @@ -46,6 +46,14 @@ export class SmonDashboard extends CustomHTMLElement {// {{{ } } + .header { + & > select, & > button { + height: 36px; + padding: 0px 16px; + } + + } + .el-error { display: none; margin-bottom: 16px; @@ -68,6 +76,7 @@ export class SmonDashboard extends CustomHTMLElement {// {{{ grid-auto-flow: column; grid-auto-columns: min-content; width: min-content; + margin-top: 16px; smon-widget-empty { display: none; @@ -110,13 +119,13 @@ export class SmonDashboard extends CustomHTMLElement {// {{{ -
+
+ + - -
@@ -124,29 +133,45 @@ export class SmonDashboard extends CustomHTMLElement {// {{{
-
Cell operations
-
+
- - - - +
Cell operations
+
+
+ + + + +
+ +
+ + + + +
+ +
+ + + +
+
- - - - +
+
Datapoint
+ +
+
+
Trigger
+ +
- -
- - - -
-
+ +
@@ -164,7 +189,10 @@ export class SmonDashboard extends CustomHTMLElement {// {{{ this.addRows = 0 this.editedWidget = null this.widgetsEdited = false + this.dashboards = this.getDashboardNames() + this.selectedDashboard = this.getSelectedDashboardName() + this.elDashboards.addEventListener('change', ()=>this.chooseDashboard()) this.elEditDashboard.addEventListener('click', () => this.classList.toggle('edit')) this.elGridAddEmptyColumns.addEventListener('click', () => { this.addColumns += 5; this.render() }) this.elGridAddEmptyRows.addEventListener('click', () => { this.addRows += 5; this.render() }) @@ -189,8 +217,27 @@ export class SmonDashboard extends CustomHTMLElement {// {{{ this.fetchData() // Retrieve one as fast as possible since setInterval doesn't run before an interval. setInterval(() => this.fetchData(), 10000) }// }}} + getSelectedDashboardName() {// {{{ + // Selected dashboard comes from a query parameter. + const params = new URLSearchParams(window.location.search) + return params.get('dashboard') || 'start' + }// }}} + getDashboardNames() {// {{{ + return JSON.parse(document.getElementById('dashboards').textContent) + }// }}} render() {// {{{ + // Dashboard list for selection. + for (const name of this.dashboards) { + const db = document.createElement('option') + db.innerText = name + if (this.selectedDashboard === name) + db.selected = true + this.elDashboards.append(db) + } + + + // Render the actual dashboard const widgets = [] this.widgets = new Map() this.occupiedCells = new Map() @@ -244,6 +291,9 @@ export class SmonDashboard extends CustomHTMLElement {// {{{ else this.elError.classList.add('show') }// }}} + chooseDashboard() {// {{{ + location.href = `/?dashboard=${this.elDashboards.value}` + }// }}} async editUpdate() {// {{{ const changes = await this.editedWidget.editUpdate() this.widgetsEdited = true diff --git a/views/pages/index.gotmpl b/views/pages/index.gotmpl index 8d1ead5..a0cb0e1 100644 --- a/views/pages/index.gotmpl +++ b/views/pages/index.gotmpl @@ -16,4 +16,6 @@ + + {{ end }}