added execution history controller
This commit is contained in:
parent
90b8348d8c
commit
2c4352c7c5
|
@ -0,0 +1,261 @@
|
|||
class CCPExecutionHistory extends HTMLElement {
|
||||
|
||||
#boot = null;
|
||||
#rootdoc = null;
|
||||
#serviceurl = null;
|
||||
#broadcasturl = null;
|
||||
#executions = [];
|
||||
#socket = null;
|
||||
|
||||
constructor(){
|
||||
super()
|
||||
this.#boot = document.querySelector("d4s-boot-2")
|
||||
this.#rootdoc = this.attachShadow({ "mode" : "open"})
|
||||
this.#serviceurl = this.getAttribute("serviceurl")
|
||||
this.#broadcasturl = this.getAttribute("broadcasturl")
|
||||
if(!this.#broadcasturl){
|
||||
this.#broadcasturl = this.#serviceurl.replace(/^http/, "ws")
|
||||
}
|
||||
this.#broadcasturl = this.#broadcasturl + "/ws/notification"
|
||||
this.connectNewExecution()
|
||||
this.connectBroadcast()
|
||||
}
|
||||
|
||||
connectedCallback(){
|
||||
this.#rootdoc.innerHTML = this.render()
|
||||
this.refreshExecutions()
|
||||
}
|
||||
|
||||
render(){
|
||||
return `
|
||||
<style>
|
||||
.noselect{
|
||||
user-select: none;
|
||||
}
|
||||
.lxd{
|
||||
background-color: #dd4814;
|
||||
color: white;
|
||||
}
|
||||
.docker{
|
||||
color: white;
|
||||
background-color: #2496ed;
|
||||
}
|
||||
.ccp-toolbar-button {
|
||||
font-weight: bold;
|
||||
padding: 0.3rem !important;
|
||||
line-height: .8rem !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
.ccp-toolbar-button svg {
|
||||
fill: white;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
pointer-events: none;
|
||||
}
|
||||
</style>
|
||||
<template id="EXECUTIOM_LIST_TEMPLATE">
|
||||
<ol name="ccp_execution_list" class="ccp-execution-list list-group">
|
||||
<li class="ccp-execution-item list-group-item" style="border: none">
|
||||
<details open>
|
||||
<summary class="noselect">
|
||||
<span name="runtime" class="badge"></span>
|
||||
<h5 style="display:inline"></h5>
|
||||
<span name="status" class="badge"></span>
|
||||
<button data-index="0" name="delete" title="Delete" class="btn btn-danger ccp-toolbar-button">
|
||||
<svg viewBox="0 0 24 24">
|
||||
<path d="M19,4H15.5L14.5,3H9.5L8.5,4H5V6H19M6,19A2,2 0 0,0 8,21H16A2,2 0 0,0 18,19V7H6V19Z"></path>
|
||||
</svg>
|
||||
</button>
|
||||
</summary>
|
||||
<p name="message" class="font-weight-light font-italic" style="margin-top:revert">
|
||||
<span name="updated"></span>:
|
||||
<span name="message" class="ml-1"></span>
|
||||
</p>
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item" style="border: none"></li>
|
||||
</ul>
|
||||
</details>
|
||||
</li>
|
||||
</ol>
|
||||
</template>
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.0.0/dist/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
|
||||
<ol name="ccp_execution_list" style="display:none"></ol>
|
||||
`
|
||||
}
|
||||
|
||||
refreshExecution(id){
|
||||
this.#boot.secureFetch(`${this.#serviceurl}/executions?id=${id}`).then(reply =>{
|
||||
if(reply.status === 200) return reply.json();
|
||||
else throw `Unable to load execution ${id}`
|
||||
}).then(data=>{
|
||||
const exec = data[0]
|
||||
for(var i=0; i < this.#executions.length; i++){
|
||||
if(this.#executions[i].id == exec.id){
|
||||
this.#executions[i] = exec
|
||||
break
|
||||
}
|
||||
if(i === this.#executions.length){
|
||||
this.#executions = data.concat(this.#executions)
|
||||
}
|
||||
}
|
||||
BSS.apply(this.execution_list_bss, this.#rootdoc)
|
||||
}).catch(err=>{ console.error(err)})
|
||||
}
|
||||
|
||||
deleteExecution(id){
|
||||
this.#boot.secureFetch(`${this.#serviceurl}/executions/${id}`, { method: "DELETE"}).then(reply =>{
|
||||
if(reply.status === 200) this.refreshExecutions();
|
||||
else throw `Unable to delete execution ${id}`
|
||||
}).catch(err=>{ console.error(err)})
|
||||
}
|
||||
|
||||
refreshExecutions(){
|
||||
this.#boot.secureFetch(`${this.#serviceurl}/executions`).then(reply =>{
|
||||
if(reply.status === 200) return reply.json();
|
||||
else throw "Unable to load executions"
|
||||
}).then(data=>{
|
||||
this.#executions = data
|
||||
BSS.apply(this.execution_list_bss, this.#rootdoc)
|
||||
}).catch(err=>{ console.error(err)})
|
||||
}
|
||||
|
||||
connectNewExecution(){
|
||||
document.addEventListener("newexecution", ev=>{
|
||||
this.#executions = [ {id: ev.detail } ].concat(this.#executions)
|
||||
})
|
||||
}
|
||||
|
||||
connectBroadcast(){
|
||||
this.#socket = new WebSocket(this.#broadcasturl + "/executions");
|
||||
this.#socket.onmessage = event=>{
|
||||
const data = JSON.parse(event.data)
|
||||
let exec = this.#executions.filter(e=>e.id === data.jobID)[0]
|
||||
if(exec){
|
||||
this.refreshExecution(exec.id)
|
||||
}
|
||||
}
|
||||
window.setInterval( ()=>this.#socket.send("ping"), 30000)
|
||||
}
|
||||
|
||||
download(url, name) {
|
||||
this.#boot.secureFetch(url).then(reply => {
|
||||
if (reply.status !== 200) {
|
||||
throw "Unable to download"
|
||||
}
|
||||
return reply.blob()
|
||||
|
||||
}).then(blob => {
|
||||
const objectURL = URL.createObjectURL(blob)
|
||||
var tmplnk = document.createElement("a")
|
||||
tmplnk.download = name
|
||||
tmplnk.href = objectURL
|
||||
//tmplnk.target="_blank"
|
||||
document.body.appendChild(tmplnk)
|
||||
tmplnk.click()
|
||||
document.body.removeChild(tmplnk)
|
||||
|
||||
}).catch(err => console.error(err))
|
||||
}
|
||||
|
||||
execution_list_bss = {
|
||||
template : "#EXECUTIOM_LIST_TEMPLATE",
|
||||
target : "ol[name=ccp_execution_list]",
|
||||
in : ()=>{ return {executions : this.#executions} },
|
||||
recurse:[
|
||||
{
|
||||
target : "li",
|
||||
in : (e,d)=>d.executions,
|
||||
apply: (e,d,i)=>e.setAttribute("data-index", i),
|
||||
on_click: ev=>{
|
||||
if(ev.target.getAttribute("name") === "delete"){
|
||||
if(window.confirm("Confirm deletion of this execution?")){
|
||||
const index = Number(ev.target.getAttribute("data-index"))
|
||||
this.deleteExecution(this.#executions[index].id)
|
||||
}
|
||||
}
|
||||
},
|
||||
recurse : [
|
||||
{
|
||||
target : "details",
|
||||
apply : (e,d)=>{
|
||||
e.alt = e.title = d.id
|
||||
if(sessionStorage.getItem(d.id) === "open") e.open = "open";
|
||||
else e.removeAttribute("open");
|
||||
},
|
||||
on_toggle : ev=>{
|
||||
if(ev.target.open){
|
||||
sessionStorage.setItem(ev.currentTarget.alt, 'open')
|
||||
}else{
|
||||
sessionStorage.removeItem(ev.currentTarget.alt)
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
target : "span[name=runtime]",
|
||||
apply : (e,d)=>{
|
||||
e.classList.add(d.infrastructuretype)
|
||||
e.title = e.alt = `${d.runtime} (image: ${d.runtimeimage}) on ${d.infrastructure}`
|
||||
e.textContent = d.runtime
|
||||
}
|
||||
},
|
||||
{
|
||||
target : "h5",
|
||||
apply : (e,d)=>{
|
||||
e.textContent = `${d.method} v. ${d.methodversion}`
|
||||
}
|
||||
},
|
||||
{
|
||||
target : "span[name=updated]",
|
||||
apply : (e,d)=>{
|
||||
const dt = new Date(d.updated)
|
||||
e.textContent = `Last update ${dt.toLocaleDateString()} @ ${dt.toLocaleTimeString()}`
|
||||
}
|
||||
},
|
||||
{
|
||||
target : "span[name=status]",
|
||||
apply : (e,d)=>{
|
||||
if(d.status){
|
||||
const status = d.status
|
||||
e.textContent = status
|
||||
if (status === "running") e.classList.add("badge-primary");
|
||||
else if (status === "successful") e.classList.add("badge-success");
|
||||
else if (status === "failure") e.classList.add("badge-danger");
|
||||
else e.classList.add("badge-secondary");
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
target : "span[name=message]",
|
||||
apply : (e,d)=>{
|
||||
if(d.message){
|
||||
e.textContent = d.message
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
target : "ul",
|
||||
recurse : [
|
||||
{
|
||||
target : "li",
|
||||
"in" : (e,d)=>{
|
||||
return d.resources.map(l=>{
|
||||
return { href : this.#serviceurl + "/executions/" + d.id + "/" + l.path, path : l.path}
|
||||
})
|
||||
},
|
||||
on_click : ev=>{
|
||||
const href = ev.currentTarget.bss_input.data.href
|
||||
const name = ev.currentTarget.bss_input.data.path
|
||||
this.download(href, name)
|
||||
},
|
||||
apply : (e,d)=>{
|
||||
e.innerHTML = `<a href="${d.href}" onclick="event.preventDefault()">${d.path}</a>`
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
window.customElements.define('d4s-ccp-executionhistory', CCPExecutionHistory);
|
Loading…
Reference in New Issue