class CCPInfrastructureList extends HTMLElement{ #boot; #socket; #interval = null; #infrastructures; #runtimes; #rootdoc; #style = ` `; #serviceurl; #broadcasturl; constructor(){ super() this.#boot = document.querySelector("d4s-boot-2") 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.#rootdoc = this.attachShadow({ "mode" : "open"}) } connectedCallback(){ this.connectBroadcast() this.fetchInfrastructures() } fetchInfrastructures(){ const prom1 = this.#boot.secureFetch(this.#serviceurl + "/infrastructures/cache"). then(resp=>{ if(resp.status !== 200) throw "Unable to fetch infrastructure cache"; return resp.json() }).then(data=>{ this.#infrastructures = data this.showList() }).catch(err=>{ alert(err) }) /*const prom2 = this.#boot.secureFetch(this.#serviceurl + "/runtimes"). then(resp=>{ if(resp.status !== 200) throw "Unable to fetch runtimes"; return resp.json() }).then(data=>{ this.#runtimes = data }).catch(err=>{ alert(err) }) Promise.all([prom1, prom2]).then(results=>{ this.showList() })*/ } refreshInfrastructures(){ this.#boot.secureFetch(this.#serviceurl + "/infrastructures/cache", { method : "HEAD"}) } showList(){ if(this.getAttribute("render") !== "true") { this.#rootdoc.innerHTML = "" return; } this.#rootdoc.innerHTML = `
${this.#style} ${this.toolbar()}
` this.#rootdoc.querySelector(".ccp_infrastructure_toolbar").addEventListener("click", ev=>{ const evname = ev.target.getAttribute("name") switch(evname){ case "refresh": this.refreshInfrastructures(); break; } }) const forms = Array.prototype.slice.call(this.#rootdoc.querySelectorAll(".ccp_runtime_builder")) forms.forEach(f=>{ f.addEventListener("submit", ev=>{ ev.stopPropagation() ev.preventDefault() const sel = ev.target.querySelector("select") let url = ev.target.action + sel.value this.#boot.secureFetch(url, { method : ev.target.method}) return false }) }) } toolbar(){ return `
` } showInfrastructures(){ return this.#infrastructures.map(i => { return `
  • ${i.name} ${this.showAge(i)} ${this.showType(i)} ${this.showDeployableRuntimes(i)}
  • ` }).join("\n") } showDeployableRuntimes(infra){ const alreadydeployed = infra.runtimes.map(r=>r["descriptor-id"]) infra.available_runtimes = infra.available_runtimes ? infra.available_runtimes : [] const options = infra.available_runtimes.filter(r=>{ return infra.type === r.type && alreadydeployed.indexOf(r.id) === -1 }).map(r=>{ return `` }).join("\n") return `
    ` } showRuntimes(infra){ return infra.runtimes.map(r =>{ return `
  • ${r.name}
  • ` }).join("\n") } showInstances(runtime){ return runtime.instances.map(i =>{ return `
  • ${i.name}
  • ` }).join("\n") } showAge(infra){ const age = Math.floor(((new Date()) - (new Date(infra.date))) / 3600000) var cls = "badge-success" var agetext = "fresh" if(age > 24){ cls = "badge-warning"; agetext = "aged" } else if (age > 72){ cls = "badge-secondary" agetext = "old" } return `${agetext}` } showType(infra){ return `${infra.type}` } connectBroadcast(){ this.#socket = new WebSocket(this.#broadcasturl + "/infrastructures"); this.#socket.onmessage = event=>{ this.fetchInfrastructures() } this.#interval = window.setInterval( ()=>{ if(this.#socket.readyState === 3){ this.#socket.close() window.clearInterval(this.#interval) this.connectBroadcast() }else{ this.#socket.send("ping") } }, 30000) } getCompatibleRuntimes(rts){ const available = Object.keys(this.#infrastructures).reduce((acc, i) => { const compatiblerts = this.#infrastructures[i].runtimes. filter(r=>rts.indexOf(r["descriptor-id"]) >= 0). map(cr=>{ return { runtime : cr, infrastructure : this.#infrastructures[i] } }) return acc.concat(compatiblerts) }, []) return available } } window.customElements.define('d4s-ccp-infrastructurelist', CCPInfrastructureList);