Selectable dashboards
This commit is contained in:
parent
d8a5c6d6c9
commit
e68a66f5ce
4 changed files with 102 additions and 22 deletions
17
dashboard.go
17
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)
|
||||
|
|
|
|||
15
main.go
15
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)
|
||||
} // }}}
|
||||
|
|
|
|||
|
|
@ -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 {// {{{
|
|||
|
||||
</style>
|
||||
|
||||
<div style="display: flex; gap: 8px;">
|
||||
<div style="display: flex; gap: 8px;" class="header">
|
||||
<select data-el="dashboards"></select>
|
||||
<button data-el="edit-dashboard">Edit dashboard</button>
|
||||
<button class="only-on-edit" data-el="update-dashboard">Update dashboard</button>
|
||||
|
||||
<svg class="only-on-edit" data-el="grid-add-empty-columns" style="width: 36px; height: 36px; cursor: pointer;"><use href="/images/${_VERSION}/grid_management.svg#add-empty-columns" /></svg>
|
||||
<svg class="only-on-edit" data-el="grid-add-empty-rows" style="width: 36px; height: 36px; cursor: pointer;"><use href="/images/${_VERSION}/grid_management.svg#add-empty-rows" /></svg>
|
||||
|
||||
<button class="only-on-edit" data-el="update-dashboard">Update dashboard</button>
|
||||
</div>
|
||||
|
||||
<div data-el="error"></div>
|
||||
|
|
@ -124,6 +133,8 @@ export class SmonDashboard extends CustomHTMLElement {// {{{
|
|||
</div>
|
||||
|
||||
<dialog data-el="edit">
|
||||
<div style="display: flex; gap: 48px;">
|
||||
<div>
|
||||
<div style="font-weight: bold;">Cell operations</div>
|
||||
<div style="margin-top: 8px; margin-bottom: 16px;">
|
||||
<div>
|
||||
|
|
@ -145,8 +156,22 @@ export class SmonDashboard extends CustomHTMLElement {// {{{
|
|||
<svg data-el="grid-remove-move-left" style="width: 36px; height: 36px;"><use href="/images/${_VERSION}/grid_management.svg#remove-move-left" /></svg>
|
||||
<svg data-el="grid-remove-move-up" style="width: 36px; height: 36px;"><use href="/images/${_VERSION}/grid_management.svg#remove-move-up" /></svg>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div>
|
||||
<div style="font-weight: bold;">Datapoint</div>
|
||||
<button style="margin-top: 8px">Choose</button>
|
||||
</div>
|
||||
<div>
|
||||
<div style="font-weight: bold; margin-top: 16px;">Trigger</div>
|
||||
<button style="margin-top: 8px">Choose</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div data-el="edit-components"></div>
|
||||
<div style="display: flex; gap: 8px; margin-top: 16px;">
|
||||
<button data-el="edit-update">Update</button>
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -16,4 +16,6 @@
|
|||
<smon-dashboard style="margin-top: 32px">
|
||||
<script type="application/json">{{ .Data.Dashboard }}</script>
|
||||
</smon-dashboard>
|
||||
|
||||
<script id="dashboards" type="application/json">{{ .Data.Dashboards }}</script>
|
||||
{{ end }}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue