diff --git a/ccp/js/methodlistcontroller2.js b/ccp/js/methodlistcontroller2.js
new file mode 100644
index 0000000..881945b
--- /dev/null
+++ b/ccp/js/methodlistcontroller2.js
@@ -0,0 +1,229 @@
+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()
+ }).catch(err=>{
+ alert("Error while downloading methods: ", err)
+ })
+ }
+
+ showList(){
+ this.updateList()
+ }
+
+ 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
+ }, {})
+ console.log(this.#filtered)
+ }
+
+ #process_list_bss = {
+ template : "#PROCESS_LIST_TEMPLATE",
+ target : "ul[name=process_category_list]",
+ "in" : this,
+ recurse : [
+ {
+ target : "li",
+ "in" : (e,d)=>Object.keys(this.#filtered),
+ recurse : [
+ {
+ target : "summary > h5",
+ apply : (e,d)=>{
+ e.innerHTML =
+ `${d} ${this.#filtered[d].length}` }
+ },
+ {
+ target : "details ul[name=process_list]",
+ in : (e,d)=>d,
+ recurse: [
+ {
+ target : "li.ccp-process",
+ "in" : (e,d)=>this.#filtered[d],
+ 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 : "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);