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
+
+
+
+
+
`
+
+ 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