2023-01-30 16:28:52 +01:00
class CCPMethodList2 extends HTMLElement {
2023-01-30 19:22:44 +01:00
# 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 = `
< 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" >
< style >
. ccp - toolbar - header {
display : inline - flex ;
align - items : center ;
gap : 5 px ;
padding : 0.2 rem ;
min - width : 20 rem ;
}
. ccp - toolbar - right {
position : absolute ;
right : 1 rem ;
}
. ccp - toolbar - button {
font - weight : bold ;
padding : 0.3 rem ;
line - height : . 8 rem ;
cursor : pointer ;
}
. ccp - toolbar - button > svg {
width : 24 px ;
height : 24 px ;
fill : white ;
stroke : white ;
}
. ccp - process - category - list {
list - style : none ;
padding - left : 0 ;
}
. ccp - process - category {
user - select : none ;
}
. ccp - process - list {
list - style : none ;
}
. ccp - process {
}
< / s t y l e >
< template id = "PROCESS_LIST_TEMPLATE" >
< ul name = "process_category_list" class = "list-group ccp-process-category-list" >
< li class = "list-group-item list-group-item-dark ccp-process-category" >
< details >
< summary >
< h5 style = "display: inline" class = "text-primary" > < / h 5 >
< / s u m m a r y >
< ul name = "process_list" class = "list-group ccp-process-list" >
< li class = "list-group-item list-group-item-secondary ccp-process p-2 my-1" draggable = "true" >
< div >
< div name = "executable" alt = "Executable" title = "Executable" >
< svg viewBox = "0 0 48 48" style = "height:24px;width:24px; background-color:green;fill:white;position:absolute;right:5px;border-radius:50%;box-shadow:2px 2px 2px rgba(0,0,0,.5)" >
< path d = "M18.9 35.7 7.7 24.5l2.15-2.15 9.05 9.05 19.2-19.2 2.15 2.15Z" / >
< / s v g >
< / d i v >
< span name = "version" class = "badge badge-primary" > < / s p a n >
< span name = "author" class = "badge badge-warning" > < / s p a n >
< / d i v >
< p style = "margin-top:.5rem" class = "small" name = "description" > < / p >
< div >
< span name = "keyword" class = "badge badge-pill badge-light mr-1" style = "opacity:.6" > < / s p a n >
< / d i v >
< / l i >
< / u l >
< / d e t a i l s >
< / l i >
< / u l >
< / t e m p l a t e >
< div class = "card" >
< div class = "card-header" style = "padding:0.5rem" >
< div class = "ccp-toolbar-header" >
< div >
< span name = "header" class = "mr-2" > Method list < / s p a n >
< / d i v >
< div class = "ccp-toolbar-right" >
< button name = "refresh" class = "btn btn-primary ccp-toolbar-button" title = "Refresh" >
< svg viewBox = "0 0 48 48" > < path d = "M24 40q-6.65 0-11.325-4.675Q8 30.65 8 24q0-6.65 4.675-11.325Q17.35 8 24 8q4.25 0 7.45 1.725T37 14.45V8h3v12.7H27.3v-3h8.4q-1.9-3-4.85-4.85Q27.9 11 24 11q-5.45 0-9.225 3.775Q11 18.55 11 24q0 5.45 3.775 9.225Q18.55 37 24 37q4.15 0 7.6-2.375 3.45-2.375 4.8-6.275h3.1q-1.45 5.25-5.75 8.45Q29.45 40 24 40Z" / > < / s v g >
< / b u t t o n >
< / d i v >
< / d i v >
< / d i v >
< div class = "card-body" >
< div class = "mb-3" >
< input type = "text" name = "search" class = "form-control" placeholder = "Search" / >
< / d i v >
< div >
< ul name = "process_category_list" > < / u l >
< / d i v >
< / d i v >
< / d i v >
`
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
} , { } )
}
# 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 } < span style = "opacity:.6" title = "Number of versions" class = "badge badge-pill badge-light" > $ { this . # filtered [ d ] . length } < / s p a n >
< span style = "opacity:.6" title = "Number of executables" class = "badge badge-pill badge-success" > $ { this . # filtered [ d ] . filter ( m => m . executable ) . length } < / s p a n > ` }
} ,
{
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 : "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 }
} ,
]
}
]
}
]
}
]
}
}
2023-01-30 16:28:52 +01:00
window . customElements . define ( 'd4s-ccp-methodlist2' , CCPMethodList2 ) ;