- `
- }
-
- addExecution(execution){
- this.#executions.push(execution)
- this.refreshExecution(execution)
- }
-
- refreshExecution(execution){
- this.#boot.secureFetch(`${this.#serviceurl}/executions/${execution.jobID}`).then(reply =>{
- if(reply.status === 200) return reply.json();
- else throw "Unable to load job links"
- }).then(data=>{
- execution.links = data
- BSS.apply(this.execution_list_bss, this.#rootdoc)
- }).catch(err=>{ console.error(err)})
- }
-
- 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.jobID === data.jobID)[0]
- if(exec){
- exec.events.push(data)
- if(!exec.self) exec.self = data.links[0].href;
- this.refreshExecution(exec)
- }
- }
- this.#interval = window.setInterval( ()=>{
- if(this.#socket.readyState === 3){
- this.#socket.close()
- window.clearInterval(this.#interval)
- this.connectBroadcast()
- }else{
- 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)=>{
- if(d.events && d.events.length > 0){
- e.alt = e.title = (new Date(d.events[d.events.length - 1].updated)).toLocaleString()
- }
- },
- recurse : [
- {
- target : "h5",
- apply : (e,d)=>{
- e.textContent = d.method
- }
- },
- {
- target : "span[name=status]",
- apply : (e,d)=>{
- if(d.events && d.events.length > 0){
- const status = d.events[d.events.length - 1].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 : ".status-message",
- apply : (e,d)=>{
- if(d.events && d.events.length > 0){
- e.textContent = d.events[d.events.length - 1].message
- }
- }
- },
- {
- target : "ul",
- recurse : [
- {
- target : "li",
- "in" : (e,d)=>{
- return d.links.map(l=>{
- return { href : this.#serviceurl + "/executions/" + d.jobID + "/" + 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 = `
`
- }
- }
- ]
- }
- ]
- }
- ]
- }
-}
-window.customElements.define('d4s-ccp-executionmonitor', CCPExecutionMonitor);
diff --git a/ccp/js/methodlistcontroller.js b/ccp/js/methodlistcontroller.js
index 1c19c73..771953d 100644
--- a/ccp/js/methodlistcontroller.js
+++ b/ccp/js/methodlistcontroller.js
@@ -1,230 +1,361 @@
class CCPMethodList extends HTMLElement{
- #boot;
- #rootdoc;
- #data;
- #filtered;
- #dragged = null;
+ #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()
+ }
- #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 = `
-
+ render(){
+ this.#rootdoc.innerHTML = `
+
+
-
- -
-
-
-
-
+
+ -
+
+
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
- `
- }
-
- 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.showList()
- }).catch(err=>{
- alert("Error while downloading methods: ", err)
- })
- }
-
- showList(){
- this.enableSearch()
- this.updateList()
- }
-
- updateList(filter){
- if(filter === "" || filter == null || filter == undefined){
- this.#filtered = []
- }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()).indexOf(f) !== -1)
+ `
+
+ 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()
})
}
- BSS.apply(this.#process_list_bss, this.#rootdoc)
- }
- enableSearch(){
- const search = this.#rootdoc.querySelector("input[name=search]")
- search.addEventListener("input", ev=>{
- this.updateList(ev.currentTarget.value)
- })
- }
+ connectedCallback(){
+
+ }
- #process_list_bss = {
- template : "#PROCESS_LIST_TEMPLATE",
- target : "ul[name=process_list]",
- "in" : this,
- recurse : [
- {
- target : "li",
- "in" : (e,d)=>this.#filtered,
- 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 : "h4",
- apply : (e,d)=>{ e.textContent = `${d.title} v. ${d.version}` }
- },
- {
- target : "i",
- apply : (e,d)=>{ e.textContent = d.description }
- },
- {
- target : "ul[name=authors]",
- recurse : {
- target : "li",
- "in" : (e,d)=>d.metadata.filter(md=>md.role === "author"),
- apply : (e,d)=>{ e.textContent = d.title }
- }
- },
- {
- target : "ul[name=keywords]",
- recurse : {
- target : "li",
- "in" : (e,d)=>d.keywords,
- apply : (e,d)=>{ e.alt = e.title = e.textContent = d }
- }
+ 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 this.fetchInfrastructures()
+ }).then(d => {
+ this.updateList()
+ }).catch(err=>{
+ alert("Error while downloading methods")
+ console.error("Error while downloading methods: " + err)
+ })
+ }
+
+ fetchInfrastructures(){
+ const url = this.#serviceurl + "/infrastructures"
+ this.#boot.secureFetch(url).
+ then(resp=>{
+ if(resp.status !== 200) throw "Unable to fetch infrastructures " + resp.status;
+ else return resp.json()
+ }).then(infras=>{
+ for(let m=0; m < this.#data.length; m++){
+ const method = this.#data[m]
+ method["executable"] = false
+ for(let i=0; i < infras.length; i++){
+ const infra = infras[i]
+ const matches = method.links.filter(l => l.rel === "compatibleWith" && l.href === "infrastructures/" + infra.id)
+ if(matches.length > 0){
+ method["executable"] = true
+ break
+ }
}
- ]
- }
- ]
+ }
+ this.updateList()
+ }).catch(err=>{
+ alert("Error while checking runtimes for method")
+ console.error("Error while checking runtimes for method: " + err)
+ })
+ }
+
+ 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.fetchProcesses()
+ }).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",
+ apply : (e,d)=>{
+ e.alt = e.title = d
+ if(sessionStorage.getItem(d) === "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 : "details ul[name=process_list]",
+ in : (e,d)=>d,
+ recurse: [
+ {
+ target : "li.ccp-process",
+ "in" : (e,d)=>this.#filtered[d],
+ on_click : ev=>{
+ const id = ev.currentTarget.bss_input.data.id
+ if(ev.target.getAttribute("name") === "export_method"){
+ this.exportMethod(id)
+ }else if(ev.target.getAttribute("name") === "executable"){
+ const event = new CustomEvent('newexecutionrequest', { detail: id });
+ document.dispatchEvent(event)
+ }else if(ev.target.getAttribute("name") === "edit"){
+ const event = new CustomEvent('neweditrequest', { detail: ev.currentTarget.bss_input.data });
+ document.dispatchEvent(event)
+ }
+ },
+ 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: "button[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 : "span[name=infrastructures]",
+ "in" : (e,d)=>d.links.filter(md=>md.rel === "compatibleWith"),
+ apply : (e,d)=>{ e.alt = e.title = e.textContent = d.title }
+ },
+ {
+ target : "p[name=description]",
+ apply : (e,d)=>{ e.textContent = d.description }
+ },
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
}
-
-}
-
+
window.customElements.define('d4s-ccp-methodlist', CCPMethodList);
diff --git a/ccp/js/methodlistcontroller2.js b/ccp/js/methodlistcontroller2.js
deleted file mode 100644
index 22817c3..0000000
--- a/ccp/js/methodlistcontroller2.js
+++ /dev/null
@@ -1,361 +0,0 @@
-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 = `
-
-
-
-
-
- -
-
-
-
-
-
-
- -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- `
-
- 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 this.fetchInfrastructures()
- }).then(d => {
- this.updateList()
- }).catch(err=>{
- alert("Error while downloading methods")
- console.error("Error while downloading methods: " + err)
- })
- }
-
- fetchInfrastructures(){
- const url = this.#serviceurl + "/infrastructures"
- this.#boot.secureFetch(url).
- then(resp=>{
- if(resp.status !== 200) throw "Unable to fetch infrastructures " + resp.status;
- else return resp.json()
- }).then(infras=>{
- for(let m=0; m < this.#data.length; m++){
- const method = this.#data[m]
- method["executable"] = false
- for(let i=0; i < infras.length; i++){
- const infra = infras[i]
- const matches = method.links.filter(l => l.rel === "compatibleWith" && l.href === "infrastructures/" + infra.id)
- if(matches.length > 0){
- method["executable"] = true
- break
- }
- }
- }
- this.updateList()
- }).catch(err=>{
- alert("Error while checking runtimes for method")
- console.error("Error while checking runtimes for method: " + err)
- })
- }
-
- 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.fetchProcesses()
- }).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",
- apply : (e,d)=>{
- e.alt = e.title = d
- if(sessionStorage.getItem(d) === "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 : "details ul[name=process_list]",
- in : (e,d)=>d,
- recurse: [
- {
- target : "li.ccp-process",
- "in" : (e,d)=>this.#filtered[d],
- on_click : ev=>{
- const id = ev.currentTarget.bss_input.data.id
- if(ev.target.getAttribute("name") === "export_method"){
- this.exportMethod(id)
- }else if(ev.target.getAttribute("name") === "executable"){
- const event = new CustomEvent('newexecutionrequest', { detail: id });
- document.dispatchEvent(event)
- }else if(ev.target.getAttribute("name") === "edit"){
- const event = new CustomEvent('neweditrequest', { detail: ev.currentTarget.bss_input.data });
- document.dispatchEvent(event)
- }
- },
- 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: "button[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 : "span[name=infrastructures]",
- "in" : (e,d)=>d.links.filter(md=>md.rel === "compatibleWith"),
- apply : (e,d)=>{ e.alt = e.title = e.textContent = d.title }
- },
- {
- target : "p[name=description]",
- apply : (e,d)=>{ e.textContent = d.description }
- },
- ]
- }
- ]
- }
- ]
- }
- ]
- }
- }
-
-window.customElements.define('d4s-ccp-methodlist2', CCPMethodList2);