From 2a04cba42ae9bbadb7c0d40b87f630a8b52b5381 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20=C3=85hall?= Date: Thu, 7 Aug 2025 15:51:15 +0200 Subject: [PATCH] More work on hooks --- node.go | 19 +++++++++++++++++- static/css/main.css | 36 +++++++++++++++++++++++++++++++++ static/js/app.mjs | 43 ++++++++++++++++++++++++++++++++++++++-- static/less/main.less | 46 ++++++++++++++++++++++++++++++++++++++++++- webserver.go | 24 ++++++++++++++++++++++ 5 files changed, 164 insertions(+), 4 deletions(-) diff --git a/node.go b/node.go index 1fa8388..bac98bf 100644 --- a/node.go +++ b/node.go @@ -84,7 +84,24 @@ func GetNode(nodeID int) (node Node, err error) { // {{{ ) AS res ) , '[]'::jsonb - ) AS ConnectedNodes + ) AS ConnectedNodes, + + COALESCE( + ( + SELECT jsonb_agg(res) + FROM ( + SELECT + h.id, + to_jsonb(s) AS script, + ssh + FROM hook h + INNER JOIN public.script s ON h.script_id = s.id + WHERE + h.node_id = n.id + ) AS res + ) + , '[]'::jsonb + ) AS ScriptHooks FROM public.node n INNER JOIN public.type t ON n.type_id = t.id diff --git a/static/css/main.css b/static/css/main.css index 5e62d57..b87e152 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -220,6 +220,7 @@ select:focus { } #connected-nodes > .add img { height: 24px; + cursor: pointer; } #connected-nodes .connected-nodes { display: flex; @@ -245,6 +246,41 @@ select:focus { display: block; height: 24px; } +#script-hooks .scripts-grid { + display: grid; + grid-template-columns: repeat(4, min-content); + align-items: center; + grid-gap: 4px 0px; +} +#script-hooks .scripts-grid .header { + font-weight: bold; + margin-right: 8px; +} +#script-hooks .scripts-grid div { + white-space: nowrap; +} +#script-hooks .scripts-grid .script-icon { + margin-right: 4px; +} +#script-hooks .scripts-grid .script-icon img, +#script-hooks .scripts-grid .script-unhook img { + display: block; + height: 24px; +} +#script-hooks .scripts-grid .script-name, +#script-hooks .scripts-grid .script-ssh { + margin-right: 16px; +} +#script-hooks .scripts-grid .script-ssh { + cursor: pointer; +} +#script-hooks > .add { + margin-bottom: 8px; +} +#script-hooks > .add img { + height: 24px; + cursor: pointer; +} #script-hooks > .label { color: var(--section-color); font-weight: bold; diff --git a/static/js/app.mjs b/static/js/app.mjs index 06828a0..503ffc4 100644 --- a/static/js/app.mjs +++ b/static/js/app.mjs @@ -973,19 +973,58 @@ class ConnectedNode { } class ScriptHooks extends Component { - constructor() { + constructor(hooks) { super() + this.hooks = hooks } renderComponent() { const div = document.createElement('div') div.innerHTML = `
Script hooks
-
hum
+
+
+
Script
+
SSH
+
` + + div.querySelector('.add').addEventListener('click', ()=>{ + alert('FIXME') + }) + + const scriptsGrid = div.querySelector('.scripts-grid') + for(const hook of this.hooks) { + const h = new ScriptHook(hook) + scriptsGrid.append(h.render()) + } + return div.children } } +class ScriptHook extends Component { + constructor(hook) {// {{{ + super() + this.hook = hook + }// }}} + renderComponent() {// {{{ + const tmpl = document.createElement('template') + tmpl.innerHTML = ` +
+
${this.hook.Script.Name}
+
${this.hook.SSH}
+
+ ` + + tmpl.content.querySelector('.script-ssh').addEventListener('click', () => { + prompt('SSH', this.hook.SSH) + //new ConnectionDataDialog(this.hook, () => _app.edit(_app.currentNode.ID)).render() + }) + + return tmpl.content + }// }}} +} + class ScriptsList extends Component { constructor() {// {{{ super() diff --git a/static/less/main.less b/static/less/main.less index 2af627a..c0a303b 100644 --- a/static/less/main.less +++ b/static/less/main.less @@ -292,9 +292,9 @@ select:focus { & > .add { margin-bottom: 8px; - img { height: 24px; + cursor: pointer; } } @@ -330,12 +330,56 @@ select:focus { } #script-hooks { + .scripts-grid { + .header { + font-weight: bold; + margin-right: 8px; + } + + display: grid; + grid-template-columns: repeat(4, min-content); + align-items: center; + grid-gap: 4px 0px; + + div { + white-space: nowrap; + } + + .script-icon { + margin-right: 4px; + } + + .script-icon, .script-unhook { + img { + display: block; + height: 24px; + } + } + + .script-name, .script-ssh { + margin-right: 16px; + } + + .script-ssh { + cursor: pointer; + } + } + + & > .add { + margin-bottom: 8px; + img { + height: 24px; + cursor: pointer; + } + } + & > .label { color: var(--section-color); font-weight: bold; font-size: 1.25em; margin-bottom: 8px; } + } #select-node { diff --git a/webserver.go b/webserver.go index 85659c2..cd8d9b3 100644 --- a/webserver.go +++ b/webserver.go @@ -50,6 +50,7 @@ func initWebserver() (err error) { http.HandleFunc("/scripts/", actionScripts) http.HandleFunc("/scripts/update/{scriptID}", actionScriptUpdate) http.HandleFunc("/scripts/delete/{scriptID}", actionScriptDelete) + http.HandleFunc("/hooks/update/{hookID}", actionHookUpdate) err = http.ListenAndServe(address, nil) return @@ -621,4 +622,27 @@ func actionScriptDelete(w http.ResponseWriter, r *http.Request) { // {{{ w.Write(j) } // }}} +func actionHookUpdate(w http.ResponseWriter, r *http.Request) { // {{{ + hookID := 0 + hookIDStr := r.PathValue("hookID") + hookID, _ = strconv.Atoi(hookIDStr) + + // XXX - here + + err := UpdateHook(hook) + if err != nil { + err = werr.Wrap(err) + httpError(w, err) + return + } + + out := struct { + OK bool + }{ + true, + } + j, _ := json.Marshal(out) + w.Write(j) +} // }}} + // vim: foldmethod=marker