class CCPMethodList2 extends HTMLElement{ #boot; #rootdoc; #data; #filtered; #dragged = null; #searchfield = null; #serviceurl; constructor(){ super() this.#boot = document.querySelector("d4s-boot-2") this.#serviceurl = this.getAttribute("serviceurl") this.#rootdoc = this.attachShadow({ "mode" : "open"}) this.render() this.fetchProcesses() } render(){ this.#rootdoc.innerHTML = `
Method list
    ` this.#rootdoc.querySelector("button[name=refresh]").addEventListener("click", ev=>{ this.fetchProcesses() }) this.#searchfield = this.#rootdoc.querySelector("input[name=search]") this.#searchfield.addEventListener("input", ev=>{ this.updateList() }) } connectedCallback(){ } fetchProcesses(){ console.log("Calling fetch processes") this.#boot.secureFetch(this.#serviceurl + "/methods"). then(resp=>{ console.log("Received resp for processes ", resp.status) return resp.json() }).then(data=>{ console.log("Processes parsed to json", data) this.#data = data this.updateList() return Promise.all(this.fetchRuntimes()) }).then(d => { this.updateList() }).catch(err=>{ alert("Error while downloading methods") console.error("Error while downloading methods: " + err) }) } fetchRuntimes(){ var promises = [] for(var d in this.#data ){ const m = this.#data[d] if(!m.links || m.links.length === 0) continue; const rts = m.links .filter(l => l.rel === "compatibleWith") .map( l => l.href.replace("runtimes/","")) .join(" ") const url = this.#serviceurl + "/infrastructures/runtimes?runtimes=" + rts promises.push( this.#boot.secureFetch(url). then(resp=>{ m["executable"] = resp.status === 200 if(resp.status === 404) return null; }).catch(err=>{ alert("Error while checking runtimes for method") console.error("Error while checking runtimes for method: " + err) }) ) } return promises } updateList(){ const filter = this.#searchfield.value if(filter === "" || filter == null || filter == undefined){ this.#filtered = this.#data }else{ const f = filter.toLowerCase() this.#filtered = this.#data.filter(d=>{ return false || (d.title.toLowerCase().indexOf(f) !== -1)|| (d.description.indexOf(f) !== -1) || (d.keywords.map(k=>k.toLowerCase()).filter(i=>i.indexOf(f) !== -1)).length }) } this.groupBy() BSS.apply(this.#process_list_bss, this.#rootdoc) } groupBy(){ this.#filtered = this.#filtered.reduce((catalog, meth)=>{ const category = meth.title catalog[category] = catalog[category] ?? [] catalog[category].push(meth) return catalog }, {}) } exportCategory(category){ Promise.all( this.#filtered[category].map(m=>this.exportMethod(m.id)) ) } exportMethod(method){ this.#boot.secureFetch(this.#serviceurl + "/methods/" + method + "/shareable").then( (resp)=>{ if(resp.status === 200){ return resp.json() }else throw "Error exporting sharable process: " + resp.status } ).then(data=>{ const filename = data.title + "-" + data.version + ".json" const datastr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(data)); var tmplnk = document.createElement("a") tmplnk.download = filename tmplnk.href = datastr document.body.appendChild(tmplnk) tmplnk.click() document.body.removeChild(tmplnk) }).catch(err=>{ console.log(err) }) } importMethods(files){ if(files && files.length) { let formdata = new FormData(); files.reduce((formdata, f)=>{ formdata.append("files[]", f) return formdata }, formdata) this.#boot.secureFetch(`${this.#serviceurl}/methods`, { body: formdata, method : "POST"}) .then(reply=>{ if (reply.status !== 200) { throw "Unable to import" }else return reply.text() }).then(data=>{ this.updateList() }).catch(err=>{ alert(err) }) } } #process_list_bss = { template : "#PROCESS_LIST_TEMPLATE", target : "ul[name=process_category_list]", "in" : this, on_dragover : (ev)=> ev.preventDefault(), on_dragenter : (ev)=> ev.target.classList.toggle("border-info"), on_dragleave : (ev)=> ev.target.classList.toggle("border-info"), on_drop : (ev)=>{ if(ev.dataTransfer && ev.dataTransfer.files && ev.dataTransfer.files.length){ const files = Array.prototype.slice.call(ev.dataTransfer.files) const jsons = files.filter(f=>f.type === "application/json") if(confirm("Confirm import of method files?")){ this.importMethods(files) } ev.preventDefault() ev.stopPropagation() } ev.target.classList.toggle("border-info") }, recurse : [ { target : "li.ccp-process-category", "in" : (e,d)=>Object.keys(this.#filtered), on_click : ev=>{ if(ev.target.getAttribute("name") === "export_category"){ this.exportCategory(ev.currentTarget.bss_input.data) } }, recurse : [ { target : "summary", apply : (e,d)=>{ const executables = this.#filtered[d].filter(m=>m.executable).length e.querySelector("h5").textContent = d e.querySelector("span[name=count_notexecutables]").textContent = this.#filtered[d].length - executables e.querySelector("span[name=count_executables]").textContent = executables } }, { target : "details ul[name=process_list]", in : (e,d)=>d, recurse: [ { target : "li.ccp-process", "in" : (e,d)=>this.#filtered[d], on_click : ev=>{ if(ev.target.getAttribute("name") === "export_method"){ this.exportMethod(ev.currentTarget.bss_input.data.id) } }, on_dragstart : ev=>{ ev.dataTransfer.effectAllowed = 'move' ev.dataTransfer.setData('text/html', ev.currentTarget.innerHTML) ev.dataTransfer.setData('text/plain+ccpmethod', ev.currentTarget.bss_input.data.id) ev.dataTransfer.setData('application/json+ccpmethod', JSON.stringify(ev.currentTarget.bss_input.data)) }, on_dragend : ev=>{ ev.preventDefault() }, recurse : [ { target: "span[name=version]", apply : (e,d)=>{ e.textContent = d.version } }, { target: "div[name=executable]", apply : (e,d)=>{ e.style.display = d.executable ? "revert" : "none" } }, { target : "span[name=author]", "in" : (e,d)=>d.metadata.filter(md=>md.role === "author"), apply : (e,d)=>{ e.textContent = d.title; e.alt = e.title = "author" } }, { target : "span[name=keyword]", "in" : (e,d)=>d.keywords, apply : (e,d)=>{ e.alt = e.title = e.textContent = d } }, { target : "p[name=description]", apply : (e,d)=>{ e.textContent = d.description } }, ] } ] } ] } ] } } window.customElements.define('d4s-ccp-methodlist2', CCPMethodList2);