Hooking
This commit is contained in:
parent
38eef01e34
commit
df4cee56af
7 changed files with 292 additions and 74 deletions
|
|
@ -29,6 +29,7 @@ export class App {
|
|||
'NODE_EDIT_NAME',
|
||||
'NODE_MOVE',
|
||||
'NODE_SELECTED',
|
||||
'NODE_HOOKED',
|
||||
'SCRIPT_CREATED',
|
||||
'SCRIPT_DELETED',
|
||||
'SCRIPT_EDIT',
|
||||
|
|
@ -86,6 +87,10 @@ export class App {
|
|||
this.nodeDelete(this.currentNode.ID)
|
||||
break
|
||||
|
||||
case 'NODE_HOOKED':
|
||||
this.edit(event.detail)
|
||||
break
|
||||
|
||||
case 'NODE_MOVE':
|
||||
const nodes = this.tree.markedNodes()
|
||||
if (!confirm(`Are you sure you want to move ${nodes.length} nodes here?`))
|
||||
|
|
@ -433,6 +438,29 @@ export class App {
|
|||
|
||||
return 0
|
||||
}// }}}
|
||||
async query(path, data) {// {{{
|
||||
return new Promise((resolve, reject) => {
|
||||
let request = {}
|
||||
|
||||
if (data !== undefined) {
|
||||
request.method = 'POST'
|
||||
request.body = JSON.stringify(data)
|
||||
}
|
||||
|
||||
fetch(path, request)
|
||||
.then(data => data.json())
|
||||
.then(json => {
|
||||
if (!json.OK) {
|
||||
reject(json.Error)
|
||||
return
|
||||
}
|
||||
resolve(json)
|
||||
})
|
||||
.catch(err => {
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
}// }}}
|
||||
}
|
||||
|
||||
class NodeCreateDialog {
|
||||
|
|
@ -921,8 +949,10 @@ class ConnectedNodes {
|
|||
render() {// {{{
|
||||
const div = document.createElement('template')
|
||||
div.innerHTML = `
|
||||
<div class="label">Connected nodes</div>
|
||||
<div class="add"><img src="/images/${_VERSION}/node_modules/@mdi/svg/svg/plus-box.svg" /></div>
|
||||
<div class="label">
|
||||
<div style="white-space: nowrap">Connected nodes</div>
|
||||
<img class="add" src="/images/${_VERSION}/node_modules/@mdi/svg/svg/plus-box.svg" />
|
||||
</div>
|
||||
<div class="connected-nodes"></div>
|
||||
`
|
||||
|
||||
|
|
@ -977,18 +1007,14 @@ class ScriptHooks extends Component {
|
|||
super()
|
||||
this.hooks = hooks
|
||||
this.scriptGrid = null
|
||||
|
||||
mbus.subscribe('hook_deleted', event => {
|
||||
const deletedHook = event.detail
|
||||
this.hooks = this.hooks.filter(h => h.ID !== deletedHook.ID)
|
||||
this.renderHooks()
|
||||
})
|
||||
}// }}}
|
||||
renderComponent() {// {{{
|
||||
const div = document.createElement('div')
|
||||
div.innerHTML = `
|
||||
<div class="label">Script hooks</div>
|
||||
<div class="add"><img src="/images/${_VERSION}/node_modules/@mdi/svg/svg/plus-box.svg" /></div>
|
||||
<div class="label">
|
||||
<div style="white-space: nowrap">Script hooks</div>
|
||||
<img class="add" src="/images/${_VERSION}/node_modules/@mdi/svg/svg/plus-box.svg" />
|
||||
</div>
|
||||
<div class="scripts-grid">
|
||||
<div class="header" style="grid-column: 1 / 3;">Script</div>
|
||||
<div class="header" style="grid-column: 3 / 5;">SSH</div>
|
||||
|
|
@ -996,7 +1022,10 @@ class ScriptHooks extends Component {
|
|||
`
|
||||
|
||||
div.querySelector('.add').addEventListener('click', () => {
|
||||
alert('FIXME')
|
||||
const dlg = new ScriptSelectDialog(s => {
|
||||
this.hookScript(s)
|
||||
})
|
||||
dlg.render()
|
||||
})
|
||||
|
||||
this.scriptGrid = div.querySelector('.scripts-grid')
|
||||
|
|
@ -1004,31 +1033,53 @@ class ScriptHooks extends Component {
|
|||
|
||||
return div.children
|
||||
}// }}}
|
||||
hookDeleted(deletedHookID) {// {{{
|
||||
this.hooks = this.hooks.filter(h => h.ID !== deletedHookID)
|
||||
this.renderHooks()
|
||||
}// }}}
|
||||
renderHooks() {// {{{
|
||||
this.scriptGrid.innerHTML = ''
|
||||
|
||||
let prevGroup = null
|
||||
for (const hook of this.hooks) {
|
||||
const h = new ScriptHook(hook)
|
||||
if (hook.Script.Group !== prevGroup) {
|
||||
const g = document.createElement('div')
|
||||
g.classList.add('script-group')
|
||||
g.innerText = hook.Script.Group
|
||||
this.scriptGrid.append(g)
|
||||
prevGroup = hook.Script.Group
|
||||
}
|
||||
|
||||
const h = new ScriptHook(hook, this)
|
||||
this.scriptGrid.append(h.render())
|
||||
}
|
||||
}// }}}
|
||||
hookScript(script) {// {{{
|
||||
_app.query(`/nodes/hook`, {
|
||||
NodeID: _app.currentNode.ID,
|
||||
ScriptID: script.ID,
|
||||
})
|
||||
.then(()=>mbus.dispatch('NODE_HOOKED', _app.currentNode.ID))
|
||||
.catch(err => showError(err))
|
||||
}// }}}
|
||||
}
|
||||
|
||||
class ScriptHook extends Component {
|
||||
constructor(hook) {// {{{
|
||||
constructor(hook, parentList) {// {{{
|
||||
super()
|
||||
this.hook = hook
|
||||
this.parentList = parentList
|
||||
this.element_ssh = null
|
||||
}// }}}
|
||||
renderComponent() {// {{{
|
||||
const tmpl = document.createElement('template')
|
||||
tmpl.innerHTML = `
|
||||
<div class="script-icon"><img src="/images/${_VERSION}/node_modules/@mdi/svg/svg/bash.svg" /></div>
|
||||
<div class="script-name">${this.hook.Script.Name}</div>
|
||||
<div class="script-ssh">${this.hook.SSH}</div>
|
||||
<div class="script-ssh"></div>
|
||||
<div class="script-unhook"><img src="/images/${_VERSION}/node_modules/@mdi/svg/svg/trash-can.svg" /></div>
|
||||
`
|
||||
this.element_ssh = tmpl.content.querySelector('.script-ssh')
|
||||
this.element_ssh.innerText = this.hook.SSH
|
||||
|
||||
tmpl.content.querySelector('.script-ssh').addEventListener('click', () => this.update())
|
||||
tmpl.content.querySelector('.script-unhook').addEventListener('click', () => this.delete())
|
||||
|
|
@ -1075,7 +1126,7 @@ class ScriptHook extends Component {
|
|||
showError(json.Error)
|
||||
return
|
||||
}
|
||||
mbus.dispatch('hook_deleted', this.hook)
|
||||
this.parentList.hookDeleted(this.hook.ID)
|
||||
})
|
||||
.catch(err => showError(err))
|
||||
}// }}}
|
||||
|
|
@ -1294,4 +1345,80 @@ class ScriptEditor extends Component {
|
|||
}// }}}
|
||||
}
|
||||
|
||||
class ScriptSelectDialog extends Component {
|
||||
constructor(callback) {// {{{
|
||||
super()
|
||||
this.dlg = document.createElement('dialog')
|
||||
this.dlg.id = 'script-select-dialog'
|
||||
this.dlg.addEventListener('close', () => this.dlg.remove())
|
||||
this.searchFor = null
|
||||
this.scripts = null
|
||||
this.callback = callback
|
||||
}// }}}
|
||||
renderComponent() {// {{{
|
||||
const div = document.createElement('div')
|
||||
div.innerHTML = `
|
||||
<div class="header">Search for script</div>
|
||||
<div><input class="search-for" type="text" value="%"></div>
|
||||
<div><button>Search</button></div>
|
||||
<div class="scripts"></div>
|
||||
`
|
||||
|
||||
this.searchFor = div.querySelector('.search-for')
|
||||
this.scripts = div.querySelector('.scripts')
|
||||
const button = div.querySelector('button')
|
||||
this.searchFor.addEventListener('keydown', event => {
|
||||
if (event.key == 'Enter')
|
||||
this.searchScripts()
|
||||
})
|
||||
button.addEventListener('click', () => this.searchScripts())
|
||||
|
||||
this.dlg.append(...div.children)
|
||||
document.body.append(this.dlg)
|
||||
this.dlg.showModal()
|
||||
|
||||
return []
|
||||
}// }}}
|
||||
searchScripts() {// {{{
|
||||
fetch('/scripts/search', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
Search: this.searchFor.value,
|
||||
}),
|
||||
})
|
||||
.then(data => data.json())
|
||||
.then(json => {
|
||||
if (!json.OK) {
|
||||
showError(json.Error)
|
||||
return
|
||||
}
|
||||
this.populateScripts(json.Scripts)
|
||||
})
|
||||
.catch(err => showError(err))
|
||||
}// }}}
|
||||
populateScripts(scripts) {// {{{
|
||||
this.scripts.innerHTML = ''
|
||||
|
||||
let prevGroup = null
|
||||
for (const s of scripts) {
|
||||
if (s.Group !== prevGroup) {
|
||||
const group = document.createElement('div')
|
||||
group.classList.add('group')
|
||||
group.innerText = s.Group
|
||||
this.scripts.append(group)
|
||||
prevGroup = s.Group
|
||||
}
|
||||
|
||||
const div = document.createElement('div')
|
||||
div.innerText = s.Name
|
||||
div.classList.add('script')
|
||||
div.addEventListener('click', () => {
|
||||
this.dlg.close()
|
||||
this.callback(s)
|
||||
})
|
||||
this.scripts.append(div)
|
||||
}
|
||||
}// }}}
|
||||
}
|
||||
|
||||
// vim: foldmethod=marker
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue