2024-04-16 13:07:23 +02:00
class CCPMethodEditorController extends HTMLElement {
2022-06-27 18:52:48 +02:00
# boot ;
# rootdoc ;
2022-07-18 18:08:53 +02:00
# serviceurl ;
2023-03-29 12:32:20 +02:00
# infrastructures ;
2022-06-27 18:52:48 +02:00
# locked = false ;
2024-04-16 13:07:23 +02:00
2022-07-18 18:08:53 +02:00
# isupdate = false ;
2022-09-08 16:03:28 +02:00
# cloneornew _dialog = null ;
# dragging _method = null ;
2024-04-16 13:07:23 +02:00
2022-06-27 18:52:48 +02:00
# tmp _inputs = [ ]
# tmp _outputs = [ ]
# current = null ;
# method _template = {
2024-04-16 13:07:23 +02:00
id : "" ,
title : "New Method" ,
description : "New empty method" ,
version : "1.0.0" ,
jobControlOptions : "async-execute" ,
metadata : [ ] ,
inputs : { } ,
outputs : { } ,
additionalParameters : {
parameters : [
2022-06-27 18:52:48 +02:00
{
2024-04-16 13:07:23 +02:00
name : "deploy-script" ,
value : [ ]
2022-06-27 18:52:48 +02:00
} ,
{
2024-04-16 13:07:23 +02:00
name : "execute-script" ,
value : [ ]
2022-06-27 18:52:48 +02:00
} ,
{
2024-04-16 13:07:23 +02:00
name : "undeploy-script" ,
value : [ ]
2022-06-27 18:52:48 +02:00
}
]
} ,
2024-04-16 13:07:23 +02:00
links : [ ]
2022-06-27 18:52:48 +02:00
}
2024-04-16 13:07:23 +02:00
2024-06-07 17:39:35 +02:00
# messages = {
"en" : {
"clone" : "Clone" ,
"clone_help" : "All setting will be cloned but no relation to cloned method will be kept" ,
"derive" : "Derive" ,
"derive_help" : "All settings will be cloned and a relation to the originating method will be kept" ,
"edit" : "Edit" ,
"edit_help" : "Edit this method" ,
"edit_clone_derive_help" : "Choose whether you want to clone this method or edit it" ,
"save_help" : "Save this method definition" ,
"reset_help" : "Reset all fields" ,
"delete_help" : "Permanently delete this method" ,
"title" : "Title" ,
"title_help" : "The title for the method" ,
"version" : "Version" ,
"version_help" : "The version of the method" ,
"description" : "Description" ,
"description_help" : "The description of this method" ,
"keywords" : "Keywords" ,
"keywords_help" : "Keywords that can be used to search for the method. Write and add by hitting enter." ,
"categories" : "Categories" ,
"categories_help" : "Categories to classify the method. Select one from the list or type a new one. Add by pressing enter." ,
"compatible_infrastructures" : "Compatible infrastructures" ,
"compatible_infrastructures_help" : "Select the infrastructures that are able to execute your method" ,
"inputs" : "Inputs" ,
"outputs" : "Outputs" ,
"scripts" : "Scripts" ,
"scripts_help" : "Deploy and execute scripts configure the deployment and execution life cycle of the method on the selected infrastructures. Use {{input_id}} notation to expand the inputs with their default values." ,
"add-input_help" : "Add an input to this method" ,
"add-output_help" : "Add an output to this method" ,
"add_ccpnote_help" : "Add ccpnote annotation for this method. This helps in identifying executions." ,
"add_stdout_help" : "Add standard outout" ,
"add_stderr_help" : "Add standard error" ,
"preview" : "Preview" ,
"err_fetch_infrastructures" : "Unable to fetch insfrastructures" ,
"err_save_method" : "Unable to save method" ,
"err_load_method" : "Unable to load method" ,
"err_delete_method" : "Unable to delete method" ,
"confirm_reset" : "All unsaved data will be lost. Proceed?" ,
"confirm_save" : "Confirm updating of method" ,
2024-10-11 13:12:30 +02:00
"confirm_delete" : "Confirm deletion of method" ,
"execute-script" : "Execute script" ,
"deploy-script" : "Deploy script" ,
2024-06-07 17:39:35 +02:00
}
}
2022-06-27 18:52:48 +02:00
# style = `
2024-07-01 12:06:55 +02:00
< link rel = "stylesheet" href = "https://cdn.cloud.d4science.org/ccp/css/common.css" > < / l i n k >
2024-04-17 17:47:28 +02:00
< link href = "https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel = "stylesheet" crossorigin = "anonymous" >
2022-09-08 16:03:28 +02:00
2022-06-27 18:52:48 +02:00
< style >
. ccp - method - editor {
position : relative ;
}
. ccp - option {
background - color : # eeffff ;
color : # 0099 CC ;
border : solid 1 px # 0099 CC ;
2023-03-29 12:32:20 +02:00
display : inline - flex ;
flex - direction : row ;
justify - content : space - between ;
align - items : center ;
gap : 1 rem ;
font - size : 1 rem ;
2022-06-27 18:52:48 +02:00
}
2023-03-29 12:32:20 +02:00
. ccp - option > . btn {
padding : 0 ;
2022-06-27 18:52:48 +02:00
}
2022-07-21 15:42:55 +02:00
2022-09-13 15:40:17 +02:00
ul . author _list , ul . context _list {
2022-07-21 15:42:55 +02:00
list - style : none ;
display : flex ;
flex - direction : row ;
gap : 2 px ;
font - size : small ;
font - weight : 300 ;
}
li . author _list _item {
display : inline - block ;
padding : 0.25 em 0.4 em ;
line - height : 1 ;
text - align : center ;
white - space : nowrap ;
vertical - align : baseline ;
border - radius : 0.25 rem ;
background - color : # eeffff ;
color : # 9900 CC ;
border : solid 1 px # 9900 CC ;
}
2022-09-13 15:40:17 +02:00
li . context _list _item {
display : inline - block ;
padding : 0.25 em 0.4 em ;
line - height : 1 ;
text - align : center ;
white - space : nowrap ;
vertical - align : baseline ;
border - radius : 0.25 rem ;
background - color : # eeffff ;
color : # 0099 CC ;
border : solid 1 px # 0099 CC ;
}
2023-04-06 16:41:10 +02:00
li . category _list _item {
display : inline - block ;
padding : 0.25 em 0.4 em ;
line - height : 1 ;
text - align : center ;
white - space : nowrap ;
vertical - align : baseline ;
border - radius : 0.25 rem ;
background - color : # eeffff ;
color : # 0099 CC ;
border : solid 1 px # 0099 CC ;
}
2022-06-27 18:52:48 +02:00
< / s t y l e >
`
# erase _icon = `
< svg viewBox = "0 0 24 24" >
< path d = "M16.24,3.56L21.19,8.5C21.97,9.29 21.97,10.55 21.19,11.34L12,20.53C10.44,22.09 7.91,22.09 6.34,20.53L2.81,17C2.03,16.21 2.03,14.95 2.81,14.16L13.41,3.56C14.2,2.78 15.46,2.78 16.24,3.56M4.22,15.58L7.76,19.11C8.54,19.9 9.8,19.9 10.59,19.11L14.12,15.58L9.17,10.63L4.22,15.58Z" / >
`
2024-04-16 13:07:23 +02:00
2022-06-27 18:52:48 +02:00
# plus _icon = `
< svg viewBox = "0 0 24 24" >
< path d = "M19,13H13V19H11V13H5V11H11V5H13V11H19V13Z" / >
< / s v g >
`
# disc _icon = `
< svg viewBox = "0 0 24 24" >
< path d = "M15,9H5V5H15M12,19A3,3 0 0,1 9,16A3,3 0 0,1 12,13A3,3 0 0,1 15,16A3,3 0 0,1 12,19M17,3H5C3.89,3 3,3.9 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V7L17,3Z" / >
< / s v g >
`
# output _icon = `
< svg viewBox = "0 0 24 24" >
< path d = "M23,12L19,8V11H10V13H19V16M1,18V6C1,4.89 1.9,4 3,4H15A2,2 0 0,1 17,6V9H15V6H3V18H15V15H17V18A2,2 0 0,1 15,20H3A2,2 0 0,1 1,18Z" / >
< / s v g >
`
2022-07-18 18:08:53 +02:00
# delete _icon = `
2023-02-09 12:21:39 +01:00
< svg viewBox = "0 0 24 24" >
2022-07-18 18:08:53 +02:00
< path d = "M19,4H15.5L14.5,3H9.5L8.5,4H5V6H19M6,19A2,2 0 0,0 8,21H16A2,2 0 0,0 18,19V7H6V19Z" / >
< / s v g >
`
2024-04-16 13:07:23 +02:00
2023-05-24 14:49:40 +02:00
# annotation _input _icon = `
< svg viewBox = "0 -960 960 960" >
< path d = "M450-234h60v-129h130v-60H510v-130h-60v130H320v60h130v129ZM220-80q-24 0-42-18t-18-42v-680q0-24 18-42t42-18h361l219 219v521q0 24-18 42t-42 18H220Zm331-554v-186H220v680h520v-494H551ZM220-820v186-186 680-680Z" / >
< / s v g >
`
2024-04-16 13:07:23 +02:00
2024-06-07 17:39:35 +02:00
getLabel ( key , localehint ) {
const locale = localehint ? localehint : navigator . language
const actlocale = this . # messages [ locale ] ? locale : "en"
const msg = this . # messages [ actlocale ] [ key ]
return msg == null || msg == undefined ? key : this . # messages [ actlocale ] [ key ]
}
2024-04-16 13:07:23 +02:00
constructor ( ) {
2022-06-27 18:52:48 +02:00
super ( ) ;
this . # boot = document . querySelector ( "d4s-boot-2" )
2024-04-16 13:07:23 +02:00
this . # rootdoc = this . attachShadow ( { "mode" : "open" } )
2024-04-11 17:25:41 +02:00
}
2024-04-16 13:07:23 +02:00
connectedCallback ( ) {
2022-07-18 18:08:53 +02:00
this . # serviceurl = this . getAttribute ( "serviceurl" )
this . initMethod ( )
2023-03-29 12:32:20 +02:00
this . fetchInfrastructures ( )
this . connectNewEditRequest ( )
2022-06-27 18:52:48 +02:00
}
2024-04-16 13:07:23 +02:00
connectNewEditRequest ( ) {
document . addEventListener ( "neweditrequest" , ev => {
2023-03-29 12:32:20 +02:00
this . cloneOrEditMethod ( ev . detail )
} )
}
2022-06-27 18:52:48 +02:00
2024-04-16 13:07:23 +02:00
isInfrastructureRegistered ( infra ) {
return ( this . # infrastructures . filter ( i => i . id === infra . id ) ) . length > 0
2022-09-08 16:03:28 +02:00
}
2024-04-16 13:07:23 +02:00
fetchInfrastructures ( ) {
2023-03-29 12:32:20 +02:00
this . # boot . secureFetch ( this . # serviceurl + "/infrastructures" ) .
2024-04-16 13:07:23 +02:00
then ( resp => {
2024-06-07 17:39:35 +02:00
if ( resp . status !== 200 ) throw this . getLabel ( "err_fetch_infrastructures" ) ;
2022-06-27 18:52:48 +02:00
return resp . json ( )
2024-04-16 13:07:23 +02:00
} ) . then ( data => {
2023-03-29 12:32:20 +02:00
this . # infrastructures = data
2022-06-27 18:52:48 +02:00
this . render ( )
2024-04-16 13:07:23 +02:00
} ) . catch ( err => {
2022-06-27 18:52:48 +02:00
alert ( err )
2022-07-21 12:35:07 +02:00
} )
2022-06-27 18:52:48 +02:00
}
2024-04-16 13:07:23 +02:00
saveMethod ( ) {
if ( this . # locked ) return ;
if ( this . # current != null ) {
2022-06-27 18:52:48 +02:00
this . adoptTemporaries ( )
2024-06-07 17:39:35 +02:00
const text = this . getLabel ( "confirm_save" ) + ` ${ this . # current . title } v. ${ this . # current . version } `
2024-04-16 13:07:23 +02:00
if ( window . confirm ( text ) ) {
2022-07-18 18:08:53 +02:00
this . lockRender ( )
const url = this . # serviceurl + "/methods"
2024-04-16 13:07:23 +02:00
const args = {
body : JSON . stringify ( this . # current ) ,
method : this . # isupdate ? "PUT" : "POST" ,
headers : { "Content-type" : "application/json" }
2022-07-18 18:08:53 +02:00
}
this . # boot . secureFetch ( url , args ) . then (
2024-04-16 13:07:23 +02:00
( resp ) => {
if ( resp . ok ) {
2022-07-18 18:08:53 +02:00
return resp . text ( )
2024-06-07 17:39:35 +02:00
} else throw this . getLabel ( "err_save_method" ) + resp . status
2024-04-16 13:07:23 +02:00
} ) . then ( data => {
if ( ! this . # isupdate ) {
this . # current = JSON . parse ( data )
this . # isupdate = true
this . # tmp _inputs = Object . keys ( this . # current . inputs ) . map ( k => this . # current . inputs [ k ] )
this . # tmp _outputs = Object . keys ( this . # current . outputs ) . map ( k => this . # current . outputs [ k ] )
}
this . unlockRender ( )
} ) . catch ( err => {
alert ( err )
this . unlockRender ( )
} )
2022-07-18 18:08:53 +02:00
}
}
}
2024-04-16 13:07:23 +02:00
deleteMethod ( ) {
if ( this . # locked ) return ;
if ( this . # current != null ) {
2024-06-07 17:39:35 +02:00
const text = this . getLabel ( "confirm_delete" ) + ` ${ this . # current . title } v. ${ this . # current . version } `
2024-04-16 13:07:23 +02:00
if ( window . confirm ( text ) ) {
2022-07-18 18:08:53 +02:00
this . lockRender ( )
const url = this . # serviceurl + "/methods/" + this . # current . id
2024-04-16 13:07:23 +02:00
const args = {
method : "DELETE"
2022-07-18 18:08:53 +02:00
}
this . # boot . secureFetch ( url , args ) . then (
2024-04-16 13:07:23 +02:00
( resp ) => {
if ( resp . status === 404 || resp . status === 204 ) {
2022-07-18 18:08:53 +02:00
return null
2024-06-07 17:39:35 +02:00
} else throw this . getLabel ( "err_delete_method" ) + ": " + resp . status
2024-04-16 13:07:23 +02:00
} ) . then ( data => {
this . # isupdate = false
this . initMethod ( )
this . unlockRender ( )
} ) . catch ( err => {
alert ( err )
this . unlockRender ( )
} )
2022-07-18 18:08:53 +02:00
}
2022-06-27 18:52:48 +02:00
}
}
2024-04-16 13:07:23 +02:00
initMethod ( ) {
2022-07-18 18:08:53 +02:00
this . # current = JSON . parse ( JSON . stringify ( this . # method _template ) )
2024-04-16 13:07:23 +02:00
this . # current . id = Math . abs ( ( Math . random ( ) * 10e11 ) | 0 )
2022-07-21 12:35:07 +02:00
this . # current . metadata = [ ]
2023-03-29 12:32:20 +02:00
this . # tmp _inputs = [
{
2024-04-16 13:07:23 +02:00
id : "ccpimage" ,
title : "Runtime" ,
description : "The image of the runtime to use for method execution. This depends on the infrastructure specific protocol for interacting with registries." ,
minOccurs : 1 ,
maxOccurs : 1 ,
schema : {
type : "string" ,
format : "url" ,
contentMediaType : "text/plain" ,
default : "" ,
2024-04-23 12:50:58 +02:00
readOnly : true ,
2023-03-29 12:32:20 +02:00
}
}
]
2022-07-18 18:08:53 +02:00
this . # tmp _outputs = [ ]
}
2024-04-16 13:07:23 +02:00
resetMethod ( ) {
2022-07-18 18:08:53 +02:00
this . initMethod ( )
2022-07-21 12:35:07 +02:00
this . render ( )
2022-07-18 18:08:53 +02:00
}
2024-04-16 13:07:23 +02:00
cloneOrEditMethod ( method ) {
2022-07-21 18:58:14 +02:00
const subject = this . # boot . subject
2024-04-16 13:07:23 +02:00
const matchingauthors = method . metadata ? method . metadata . filter ( md => md . role === "author" && md . href . endsWith ( "/" + subject ) ) . length : 0
if ( matchingauthors === 0 ) this . cloneMethod ( method . id , true ) ;
else {
2022-09-08 16:03:28 +02:00
this . # dragging _method = method . id
this . # cloneornew _dialog . style . display = "block"
this . # cloneornew _dialog . classList . add ( "show" )
}
2022-07-21 18:58:14 +02:00
}
2024-04-16 13:07:23 +02:00
cloneMethod ( method , derivation ) {
if ( this . # locked ) return ;
2022-06-27 18:52:48 +02:00
this . lockRender ( )
2023-11-16 13:57:26 +01:00
const derive = derivation ? "?derive=true" : ""
this . # boot . secureFetch ( this . # serviceurl + "/methods/" + method + "/clone" + derive ) . then (
2024-04-16 13:07:23 +02:00
( resp ) => {
if ( resp . status === 200 ) {
2022-06-27 18:52:48 +02:00
return resp . json ( )
2024-06-07 17:39:35 +02:00
} else throw this . getLabel ( "err_load_method" ) + ": " + resp . status
2022-06-27 18:52:48 +02:00
}
2024-04-16 13:07:23 +02:00
) . then ( data => {
2022-06-27 18:52:48 +02:00
this . # current = data
2022-07-18 18:08:53 +02:00
this . # isupdate = false
2024-04-16 13:07:23 +02:00
this . # tmp _inputs = Object . keys ( this . # current . inputs ) . map ( k => this . # current . inputs [ k ] )
this . # tmp _outputs = Object . keys ( this . # current . outputs ) . map ( k => this . # current . outputs [ k ] )
2022-07-18 18:08:53 +02:00
this . unlockRender ( )
2024-04-16 13:07:23 +02:00
} ) . catch ( err => {
2022-07-18 18:08:53 +02:00
this . unlockRender ( )
} )
}
2024-04-16 13:07:23 +02:00
editMethod ( method ) {
if ( this . # locked ) return ;
2022-07-18 18:08:53 +02:00
this . lockRender ( )
2022-07-21 15:42:55 +02:00
this . # boot . secureFetch ( this . # serviceurl + "/methods/" + method + "/updatable" ) . then (
2024-04-16 13:07:23 +02:00
( resp ) => {
if ( resp . status === 200 ) {
2022-07-18 18:08:53 +02:00
return resp . json ( )
2024-06-07 17:39:35 +02:00
} else throw this . getLabel ( "err_load_method" ) + ": " + resp . status
2022-07-18 18:08:53 +02:00
}
2024-04-16 13:07:23 +02:00
) . then ( data => {
2022-07-18 18:08:53 +02:00
this . # current = data
this . # isupdate = true
2024-04-16 13:07:23 +02:00
this . # tmp _inputs = Object . keys ( this . # current . inputs ) . map ( k => this . # current . inputs [ k ] )
this . # tmp _outputs = Object . keys ( this . # current . outputs ) . map ( k => this . # current . outputs [ k ] )
2022-06-27 18:52:48 +02:00
this . unlockRender ( )
2024-04-16 13:07:23 +02:00
} ) . catch ( err => {
2022-06-27 18:52:48 +02:00
this . unlockRender ( )
} )
}
2024-04-16 13:07:23 +02:00
adoptTemporaries ( ) {
2022-06-27 18:52:48 +02:00
this . # current . inputs = { }
2024-04-16 13:07:23 +02:00
this . # tmp _inputs . forEach ( t => {
2022-06-27 18:52:48 +02:00
this . # current . inputs [ t . id ] = t
} )
this . # current . outputs = { }
2024-04-16 13:07:23 +02:00
this . # tmp _outputs . forEach ( t => {
2022-06-27 18:52:48 +02:00
this . # current . outputs [ t . id ] = t
} )
}
2024-04-16 13:07:23 +02:00
getInputAt ( i ) {
2022-06-27 18:52:48 +02:00
return this . # tmp _inputs [ i ]
}
2024-04-16 13:07:23 +02:00
deleteTmpInputAt ( i ) {
this . # tmp _inputs . splice ( i , 1 )
2022-06-27 18:52:48 +02:00
}
2024-04-16 13:07:23 +02:00
deleteTmpOutputAt ( i ) {
this . # tmp _outputs . splice ( i , 1 )
2022-06-27 18:52:48 +02:00
}
2024-04-16 13:07:23 +02:00
lockRender ( ) {
2022-06-27 18:52:48 +02:00
this . # locked = true
this . # rootdoc . querySelector ( ".plexiglass" ) . classList . toggle ( "d-none" )
}
2024-04-16 13:07:23 +02:00
unlockRender ( ) {
2022-06-27 18:52:48 +02:00
this . # rootdoc . querySelector ( ".plexiglass" ) . classList . toggle ( "d-none" )
this . render ( )
this . # locked = false
2024-04-16 13:07:23 +02:00
if ( this . parentElement ) this . parentElement . scrollIntoViewIfNeeded ( ) ;
2022-06-27 18:52:48 +02:00
}
2024-04-16 13:07:23 +02:00
render ( ) {
2022-06-27 18:52:48 +02:00
this . # rootdoc . innerHTML = `
2022-09-08 16:03:28 +02:00
<!-- Modal -- >
< div class = "modal fade" style = "background-color:rgba(0,0,0,0.3)" id = "cloneornew" tabindex = "-1" role = "dialog" >
< div class = "modal-dialog" role = "document" >
< div class = "modal-content shadow-lg border-primary" >
< div class = "modal-body" >
2024-06-07 17:39:35 +02:00
$ { this . getLabel ( "edit_clone_derive_help" ) }
2022-09-08 16:03:28 +02:00
< / d i v >
< div class = "modal-footer" >
2024-06-07 17:39:35 +02:00
< button name = "clone" title = "${this.getLabel(" clone _help ")}" type = "button" class = "btn btn-info" > $ { this . getLabel ( "clone" ) } < / b u t t o n >
< button name = "edit" title = "${this.getLabel(" edit _help ")}" type = "button" class = "btn btn-primary" > $ { this . getLabel ( "edit" ) } < / b u t t o n >
< button name = "derive" title = "${this.getLabel(" derive _help ")}" type = "button" class = "btn btn-secondary" > $ { this . getLabel ( "derive" ) } < / b u t t o n >
2022-09-08 16:03:28 +02:00
< / d i v >
< / d i v >
< / d i v >
< / d i v >
2022-06-27 18:52:48 +02:00
< div class = "ccp-method-editor" >
< div class = "d-none plexiglass" >
< svg class = "spinner" viewBox = "0 0 66 66" >
< circle class = "path" fill = "none" stroke - width = "6" stroke - linecap = "round" cx = "33" cy = "33" r = "30" > < / c i r c l e >
< / s v g >
< / d i v >
$ { this . # style }
< div class = "ccp-method-editor-form" >
< div class = "card" >
< div class = "card-header" >
2022-07-18 18:08:53 +02:00
< div class = "ccp-toolbar-header" >
< div >
< span name = "header" class = "mr-2" > $ { this . # current . title } < / s p a n >
< / d i v >
< div class = "ccp-toolbar-right" >
$ { this . renderSaveButton ( ) }
$ { this . renderResetButton ( ) }
2024-04-16 13:07:23 +02:00
$ { this . # isupdate ? this . renderDeleteButton ( ) : "" }
2022-07-18 18:08:53 +02:00
< / d i v >
2022-06-27 18:52:48 +02:00
< / d i v >
< / d i v >
< div class = "card-body" >
2022-07-21 15:42:55 +02:00
< div class = "mb-3 row" >
$ { this . renderAuthors ( ) }
< / d i v >
2023-04-06 15:31:42 +02:00
<!-- div class = "mb-3 row" >
2022-09-13 15:40:17 +02:00
$ { this . renderContexts ( ) }
2023-04-06 15:31:42 +02:00
< / d i v - - >
2022-06-27 18:52:48 +02:00
< div class = "mb-3 row" >
2024-06-07 17:39:35 +02:00
< div class = "col" title = "${this.getLabel(" title _help ")}" >
< label class = "form-label" > $ { this . getLabel ( "title" ) } < / l a b e l >
2022-06-27 18:52:48 +02:00
< input name = "title" class = "form-control" type = "text" required = "required" value = "${this.#current.title}" / >
< / d i v >
2024-06-07 17:39:35 +02:00
< div class = "col" title = "${this.getLabel(" version _help ")}" >
< label class = "form-label" > $ { this . getLabel ( "version" ) } < / l a b e l >
2022-06-27 18:52:48 +02:00
< input name = "version" class = "form-control" type = "text" required = "required" value = "${this.#current.version}" / >
< / d i v >
< / d i v >
2024-06-07 17:39:35 +02:00
< div class = "mb-3" title = "${this.getLabel(" description _help ")}" >
< label class = "form-label" > $ { this . getLabel ( "description" ) } < / l a b e l >
2024-10-11 13:12:30 +02:00
<!-- input name = "description" class = "form-control" type = "text" required = "required" value = "${this.#current.description}" / -- >
< textarea name = "description" class = "form-control" required = "required" rows = "5" > $ { this . # current . description } < / t e x t a r e a >
2022-06-27 18:52:48 +02:00
< / d i v >
2023-04-06 16:27:14 +02:00
< div class = "row" >
2024-06-07 17:39:35 +02:00
< div class = "col mb-3" title = "${this.getLabel(" keywords _help ")}" >
< label class = "form-label" > $ { this . getLabel ( "keywords" ) } < / l a b e l >
2023-04-06 16:27:14 +02:00
< input name = "keyword-input" class = "form-control" type = "text" / >
< div name = "keyword-list" class = "form-text" >
$ { this . renderKeywords ( ) }
< / d i v >
< / d i v >
2024-06-07 17:39:35 +02:00
< div class = "col mb-3" title = "${this.getLabel(" categories _help ")}" >
< label class = "form-label" > $ { this . getLabel ( "categories" ) } < / l a b e l >
2023-04-06 16:43:46 +02:00
< input list = "categoryhints" name = "category-input" class = "form-control" type = "text" / >
2023-04-06 16:30:44 +02:00
$ { this . renderCategoryHints ( ) }
2023-04-06 16:27:14 +02:00
< div name = "category-list" class = "form-text" >
$ { this . renderCategories ( ) }
< / d i v >
2022-06-27 18:52:48 +02:00
< / d i v >
< / d i v >
2024-06-07 17:39:35 +02:00
< div name = "infrastructures" class = "mb-3" title = "${this.getLabel(" compatible _infrastructures _help ")}" >
< label class = "form-label" > $ { this . getLabel ( "compatible_infrastructures" ) } < / l a b e l >
2023-03-29 12:32:20 +02:00
< select name = "infrastructure-input" class = "form-control" >
$ { this . renderInfrastructureOptions ( ) }
2022-06-27 18:52:48 +02:00
< / s e l e c t >
2023-03-29 12:32:20 +02:00
< div name = "infrastructure-list" class = "form-text" >
$ { this . renderInfrastructures ( ) }
2022-06-27 18:52:48 +02:00
< / d i v >
< / d i v >
< / d i v >
< / d i v >
< details class = "card" >
< summary class = "card-header" >
2022-07-18 18:08:53 +02:00
< div class = "ccp-toolbar-header" >
< div >
2024-06-07 17:39:35 +02:00
< span class = "mr-2" > $ { this . getLabel ( "inputs" ) } < / s p a n >
2022-07-18 18:08:53 +02:00
< / d i v >
< div class = "ccp-toolbar-right" >
2023-05-24 14:49:40 +02:00
$ { this . renderStandardInputButtons ( ) }
2022-07-18 18:08:53 +02:00
$ { this . renderPlusButton ( "add-input" ) }
< / d i v >
< / d i v >
2022-06-27 18:52:48 +02:00
< / s u m m a r y >
< div class = "card-body" name = "input-list" >
< / d i v >
< / d e t a i l s >
< details class = "card" >
< summary class = "card-header" name = "output-buttons" >
2022-07-18 18:08:53 +02:00
< div class = "ccp-toolbar-header" >
< div >
2024-06-07 17:39:35 +02:00
< span class = "mr-2" > $ { this . getLabel ( "outputs" ) } < / s p a n >
2022-07-18 18:08:53 +02:00
< / d i v >
< div class = "ccp-toolbar-right" >
$ { this . renderStandardOutputButtons ( ) }
$ { this . renderPlusButton ( "add-output" ) }
< / d i v >
< / d i v >
2022-06-27 18:52:48 +02:00
< / s u m m a r y >
< div class = "card-body" name = "output-list" >
< d4s - ccp - output - editor > < / d 4 s - c c p - o u t p u t - e d i t o r >
< / d i v >
< / d i v >
2024-10-11 13:12:30 +02:00
< div name = "scripts_container" >
$ { this . renderScripts ( ) }
2022-06-27 18:52:48 +02:00
< / d i v >
< / d i v >
< / d i v >
`
this . renderInputs ( )
this . renderOutputs ( )
2024-04-16 13:07:23 +02:00
2022-09-08 16:03:28 +02:00
this . # cloneornew _dialog = this . # rootdoc . querySelector ( "#cloneornew" )
2024-04-16 13:07:23 +02:00
this . # rootdoc . querySelector ( "#cloneornew button[name=clone]" ) . addEventListener ( "click" , ev => {
2022-09-08 16:03:28 +02:00
this . # cloneornew _dialog . classList . remove ( "show" )
this . # cloneornew _dialog . style . display = "none"
this . cloneMethod ( this . # dragging _method )
this . # dragging _method = null
} )
2024-04-16 13:07:23 +02:00
this . # rootdoc . querySelector ( "#cloneornew button[name=derive]" ) . addEventListener ( "click" , ev => {
2023-11-16 13:45:24 +01:00
this . # cloneornew _dialog . classList . remove ( "show" )
this . # cloneornew _dialog . style . display = "none"
this . cloneMethod ( this . # dragging _method , true )
this . # dragging _method = null
} )
2024-04-16 13:07:23 +02:00
this . # rootdoc . querySelector ( "#cloneornew button[name=edit]" ) . addEventListener ( "click" , ev => {
2022-09-08 16:03:28 +02:00
this . # cloneornew _dialog . classList . remove ( "show" )
this . # cloneornew _dialog . style . display = "none"
this . editMethod ( this . # dragging _method )
this . # dragging _method = null
} )
2024-04-16 13:07:23 +02:00
this . # rootdoc . querySelector ( "input[name=title]" ) . addEventListener ( "input" , ev => {
2022-07-18 18:08:53 +02:00
this . # current . title = ev . currentTarget . value
this . # rootdoc . querySelector ( "span[name=header]" ) . innerText = this . # current . title
} )
2024-04-16 13:07:23 +02:00
this . # rootdoc . querySelector ( "input[name=version]" ) . addEventListener ( "input" , ev => {
2022-07-18 18:08:53 +02:00
this . # current . version = ev . currentTarget . value
} )
2024-04-16 13:07:23 +02:00
2024-10-11 13:12:30 +02:00
this . # rootdoc . querySelector ( "textarea[name=description]" ) . addEventListener ( "input" , ev => {
2022-07-18 18:08:53 +02:00
this . # current . description = ev . currentTarget . value
} )
2024-04-16 13:07:23 +02:00
this . # rootdoc . addEventListener ( "drop" , ev => {
if ( ev . dataTransfer && ev . dataTransfer . getData ( 'text/plain+ccpmethod' ) ) {
2023-02-09 13:22:38 +01:00
const method = JSON . parse ( ev . dataTransfer . getData ( 'application/json+ccpmethod' ) )
ev . stopImmediatePropagation ( )
ev . preventDefault ( )
ev . stopPropagation ( )
this . cloneOrEditMethod ( method )
}
2022-06-27 18:52:48 +02:00
} )
2024-04-16 13:07:23 +02:00
this . # rootdoc . addEventListener ( "dragover" , ev => {
2022-06-27 18:52:48 +02:00
ev . preventDefault ( )
} )
2024-04-16 13:07:23 +02:00
this . # rootdoc . querySelector ( "button[name=reset]" ) . addEventListener ( "click" , ev => {
2024-06-07 17:39:35 +02:00
if ( window . confirm ( this . getLabel ( "confirm_reset" ) ) ) {
2024-04-16 13:07:23 +02:00
this . resetMethod ( )
2022-07-18 18:08:53 +02:00
}
2022-06-27 18:52:48 +02:00
ev . preventDefault ( )
ev . stopPropagation ( )
} )
2024-04-16 13:07:23 +02:00
this . # rootdoc . querySelector ( "button[name=save]" ) . addEventListener ( "click" , ev => {
2022-06-27 18:52:48 +02:00
ev . preventDefault ( )
ev . stopPropagation ( )
2024-04-16 13:07:23 +02:00
this . saveMethod ( )
2022-06-27 18:52:48 +02:00
} )
2024-04-16 13:07:23 +02:00
if ( this . # isupdate ) {
this . # rootdoc . querySelector ( "button[name=delete]" ) . addEventListener ( "click" , ev => {
2022-07-18 18:08:53 +02:00
ev . preventDefault ( )
ev . stopPropagation ( )
this . deleteMethod ( )
2024-04-16 13:07:23 +02:00
} )
2022-07-18 18:08:53 +02:00
}
2024-04-16 13:07:23 +02:00
this . # rootdoc . querySelector ( "input[name=keyword-input]" ) . addEventListener ( "keypress" , ev => {
if ( ev . key === "Enter" || ev . which === 13 ) {
2022-06-27 18:52:48 +02:00
ev . preventDefault ( )
ev . stopPropagation ( )
const val = ev . target . value
ev . target . value = null
2024-04-16 13:07:23 +02:00
if ( ! this . # current . keywords ) {
2022-06-27 18:52:48 +02:00
this . # current . keywords = [ val ]
2024-04-16 13:07:23 +02:00
} else {
2022-06-27 18:52:48 +02:00
this . # current . keywords . push ( val )
}
this . reRenderKeywords ( )
}
} )
2024-04-16 13:07:23 +02:00
this . # rootdoc . querySelector ( "div[name=keyword-list]" ) . addEventListener ( "click" , ev => {
2022-06-27 18:52:48 +02:00
ev . preventDefault ( )
ev . stopPropagation ( )
2024-04-16 13:07:23 +02:00
if ( ev . target . getAttribute ( 'name' ) === "delete-keyword" ) {
2022-06-27 18:52:48 +02:00
const index = ev . target . getAttribute ( "data-index" )
this . # current . keywords . splice ( index , 1 )
this . reRenderKeywords ( )
this . # rootdoc . querySelector ( "input[name=keyword-input]" ) . focus ( )
}
} )
2024-04-16 13:07:23 +02:00
this . # rootdoc . querySelector ( "input[name=category-input]" ) . addEventListener ( "keypress" , ev => {
if ( ev . key === "Enter" || ev . which === 13 ) {
2023-04-06 16:41:10 +02:00
ev . preventDefault ( )
ev . stopPropagation ( )
const val = ev . target . value
ev . target . value = null
2024-04-16 13:07:23 +02:00
if ( this . # current . metadata . filter ( md => md . role === "category" && md . title === val ) . length === 0 ) {
this . # current . metadata . push ( { role : "category" , title : val } )
2023-04-06 16:47:32 +02:00
this . reRenderCategories ( )
2023-04-06 16:41:10 +02:00
}
}
} )
2024-04-16 13:07:23 +02:00
this . # rootdoc . querySelector ( "div[name=category-list]" ) . addEventListener ( "click" , ev => {
2023-04-06 16:41:10 +02:00
ev . preventDefault ( )
ev . stopPropagation ( )
2024-04-16 13:07:23 +02:00
if ( ev . target . getAttribute ( 'name' ) === "delete-category" ) {
2023-04-06 17:25:33 +02:00
const val = ev . target . parentElement . title
2024-04-16 13:07:23 +02:00
this . # current . metadata = this . # current . metadata . filter ( md => md . role !== "category" || md . title !== val )
2023-04-06 16:41:10 +02:00
this . reRenderCategories ( )
this . # rootdoc . querySelector ( "input[name=category-input]" ) . focus ( )
}
} )
2024-04-16 13:07:23 +02:00
this . # rootdoc . querySelector ( "div[name=infrastructures]" ) . addEventListener ( "change" , ev => {
if ( ev . target . getAttribute ( "name" ) === "infrastructure-input" && ev . target . value ) {
2022-06-27 18:52:48 +02:00
ev . preventDefault ( )
ev . stopPropagation ( )
const id = ev . target . value
const display = ev . target . options [ ev . target . selectedIndex ] . text
let link = {
2024-04-16 13:07:23 +02:00
rel : "compatibleWith" , title : display , href : "infrastructures/" + id
2022-06-27 18:52:48 +02:00
}
2024-04-16 13:07:23 +02:00
if ( ! this . # current . links ) {
2022-06-27 18:52:48 +02:00
this . # current . links = [ link ]
2024-04-16 13:07:23 +02:00
} else {
2022-06-27 18:52:48 +02:00
this . # current . links . push ( link )
}
2023-03-29 12:32:20 +02:00
this . reRenderInfrastructures ( ev . currentTarget )
2022-06-27 18:52:48 +02:00
}
} )
2024-04-16 13:07:23 +02:00
this . # rootdoc . querySelector ( "div[name=infrastructure-list]" ) . addEventListener ( "click" , ev => {
2022-06-27 18:52:48 +02:00
ev . preventDefault ( )
ev . stopPropagation ( )
2024-04-16 13:07:23 +02:00
if ( ev . target . getAttribute ( 'name' ) === "delete-infrastructure" ) {
2022-06-27 18:52:48 +02:00
const index = ev . target . getAttribute ( "data-index" )
this . # current . links . splice ( index , 1 )
2023-03-29 12:32:20 +02:00
this . reRenderInfrastructures ( )
2022-06-27 18:52:48 +02:00
}
} )
2024-04-16 13:07:23 +02:00
this . # rootdoc . querySelector ( "button[name=add-input]" ) . addEventListener ( "click" , ev => {
2022-06-27 18:52:48 +02:00
ev . preventDefault ( )
ev . stopPropagation ( )
this . # tmp _inputs . push (
{
2024-04-16 13:07:23 +02:00
id : "new_input" ,
title : "New input" ,
description : "A new input field" ,
minOccurs : 1 ,
maxOccurs : 1 ,
schema : {
type : "string" ,
format : null ,
contentMediaType : "text/plain" ,
default : ""
2022-06-27 18:52:48 +02:00
}
}
)
this . renderInputs ( )
2024-04-16 13:07:23 +02:00
this . reRenderScripts ( )
2022-06-27 18:52:48 +02:00
} )
2024-04-16 13:07:23 +02:00
this . # rootdoc . querySelector ( "button[name=add-ccpannotation]" ) . addEventListener ( "click" , ev => {
2023-05-24 14:49:40 +02:00
ev . preventDefault ( )
ev . stopPropagation ( )
this . # tmp _inputs . push (
{
2024-04-16 13:07:23 +02:00
id : "ccpnote" ,
title : "Annotations for execution" ,
description : "The value of this parameter will be associated as annotation to the execution" ,
minOccurs : 1 ,
maxOccurs : 1 ,
schema : {
type : "string" ,
format : null ,
contentMediaType : "text/plain" ,
default : ""
2023-05-24 14:49:40 +02:00
}
}
)
this . renderInputs ( )
2024-04-16 13:07:23 +02:00
this . reRenderScripts ( )
2023-05-24 14:49:40 +02:00
} )
2024-04-16 13:07:23 +02:00
this . # rootdoc . querySelector ( "div[name=input-list]" ) . addEventListener ( "click" , ev => {
2022-06-27 18:52:48 +02:00
const evname = ev . target . getAttribute ( 'name' )
2024-04-16 13:07:23 +02:00
if ( evname === "delete-input" ) {
2022-06-27 18:52:48 +02:00
ev . preventDefault ( )
ev . stopPropagation ( )
const index = Number ( ev . target . getAttribute ( "data-index" ) )
console . log ( "deleting input at index" , index )
this . deleteTmpInputAt ( index )
this . renderInputs ( )
2024-04-16 13:07:23 +02:00
this . reRenderScripts ( )
}
} )
//when any input changes update scripts so that possibly variable get re-expanded
this . # rootdoc . querySelector ( "div[name=input-list]" ) . addEventListener ( "input" , ev => {
this . reRenderScripts ( )
} )
this . # rootdoc . querySelector ( "div[name=input-list]" ) . addEventListener ( "change" , ev => {
this . reRenderScripts ( )
} )
this . # rootdoc . querySelector ( "div[name=input-list]" ) . addEventListener ( "click" , ev => {
const src = ev . target . getAttribute ( "name" )
if ( src === "plus" || src === "minus" || src === "maxOccurs" || src === "minOccurs" ) {
this . reRenderScripts ( )
}
2022-06-27 18:52:48 +02:00
} )
2024-04-16 13:07:23 +02:00
this . # rootdoc . querySelector ( "button[name=add-output]" ) . addEventListener ( "click" , ev => {
2022-06-27 18:52:48 +02:00
ev . preventDefault ( )
ev . stopPropagation ( )
this . # tmp _outputs . push (
{
2024-04-16 13:07:23 +02:00
id : "new_output" ,
title : "New ouput" ,
description : "A new output field" ,
minOccurs : 1 ,
maxOccurs : 1 ,
metadata : [
2022-09-13 15:12:26 +02:00
{
2024-04-16 13:07:23 +02:00
"role" : "file" ,
"title" : "newoutput.txt" ,
"href" : "newoutput.txt"
2022-09-13 15:12:26 +02:00
}
] ,
2024-04-16 13:07:23 +02:00
schema : {
type : "string" ,
contentMediaType : "text/plain"
2022-06-27 18:52:48 +02:00
}
}
)
this . renderOutputs ( )
} )
2024-04-16 13:07:23 +02:00
this . # rootdoc . querySelector ( "button[name=add-stdout]" ) . addEventListener ( "click" , ev => {
2022-06-27 18:52:48 +02:00
ev . preventDefault ( )
ev . stopPropagation ( )
this . # tmp _outputs . push (
{
2024-04-16 13:07:23 +02:00
id : "stdout" ,
title : "Standard output" ,
description : "Standard output channel" ,
minOccurs : 1 ,
maxOccurs : 1 ,
metadata : [
2022-09-13 15:12:26 +02:00
{
2024-04-16 13:07:23 +02:00
"role" : "file" ,
"title" : "stdout" ,
"href" : "stdout"
2022-09-13 15:12:26 +02:00
}
] ,
2024-04-16 13:07:23 +02:00
schema : {
type : "string" ,
contentMediaType : "text/plain"
2022-06-27 18:52:48 +02:00
}
}
)
this . renderOutputs ( )
} )
2024-04-16 13:07:23 +02:00
this . # rootdoc . querySelector ( "button[name=add-stderr]" ) . addEventListener ( "click" , ev => {
2022-06-27 18:52:48 +02:00
ev . preventDefault ( )
ev . stopPropagation ( )
this . # tmp _outputs . push (
{
2024-04-16 13:07:23 +02:00
id : "stderr" ,
title : "Standard error" ,
description : "Standard error channel" ,
minOccurs : 1 ,
maxOccurs : 1 ,
metadata : [
2022-09-13 15:12:26 +02:00
{
2024-04-16 13:07:23 +02:00
"role" : "file" ,
"title" : "stderr" ,
"href" : "stderr"
2022-09-13 15:12:26 +02:00
}
] ,
2024-04-16 13:07:23 +02:00
schema : {
type : "string" ,
contentMediaType : "text/plain"
2022-06-27 18:52:48 +02:00
}
}
)
this . renderOutputs ( )
} )
2024-04-16 13:07:23 +02:00
this . # rootdoc . querySelector ( "div[name=output-list]" ) . addEventListener ( "click" , ev => {
2022-06-27 18:52:48 +02:00
const evname = ev . target . getAttribute ( 'name' )
2024-04-16 13:07:23 +02:00
if ( evname === "delete-output" ) {
2022-06-27 18:52:48 +02:00
ev . preventDefault ( )
ev . stopPropagation ( )
const index = Number ( ev . target . getAttribute ( "data-index" ) )
console . log ( "deleting output at index" , index )
this . deleteTmpOutputAt ( index )
this . renderOutputs ( )
2024-04-16 13:07:23 +02:00
}
2022-06-27 18:52:48 +02:00
} )
2024-04-16 13:07:23 +02:00
this . # rootdoc . querySelector ( "div[name=scripts_container]" ) . addEventListener ( "input" , ev => {
2022-06-27 18:52:48 +02:00
ev . preventDefault ( )
ev . stopPropagation ( )
2024-10-11 13:12:30 +02:00
const scriptname = ev . target . getAttribute ( "name" )
2024-04-16 13:07:23 +02:00
const script = this . # current . additionalParameters . parameters . find ( p => p . name === scriptname )
if ( script ) script . value = ev . target . value . split ( /\r?\n/ ) ;
2024-10-11 13:12:30 +02:00
this . reRenderScripts ( )
2022-06-27 18:52:48 +02:00
} )
}
2024-04-16 13:07:23 +02:00
renderAuthors ( ) {
2022-07-21 15:42:55 +02:00
return `
< ul class = "author_list" >
2024-04-16 13:07:23 +02:00
$ { this . # current . metadata .
filter ( md => md . role === "author" ) .
map ( a => ` <li class="badge bg-warning text-dark" title="Author: ${ a . title } "> ${ a . title } </li> ` ) . join ( ) }
2022-09-13 15:40:17 +02:00
< / u l >
`
}
2024-04-16 13:07:23 +02:00
renderCategoryHints ( ) {
2023-04-06 16:06:08 +02:00
const ml = document . querySelector ( "d4s-ccp-methodlist" )
2023-04-06 16:15:17 +02:00
const cats = ml . getCategoryHints ( )
2024-04-16 13:07:23 +02:00
if ( cats . indexOf ( "Uncategorised" ) === - 1 ) cats . push ( "Uncategorised" )
2023-04-06 15:20:31 +02:00
return `
< datalist id = "categoryhints" >
2024-04-16 13:07:23 +02:00
$ { cats . map ( c => ` <option value=" ${ c } "> ${ c } </option> ` ) }
2023-04-06 15:20:31 +02:00
< / d a t a l i s t >
`
}
2024-04-16 13:07:23 +02:00
renderContexts ( ) {
2022-09-13 15:40:17 +02:00
return `
< ul class = "context_list" >
2024-04-16 13:07:23 +02:00
$ { this . # current . metadata .
filter ( md => md . role === "context" ) .
map ( c => ` <li class="context_list_item" title=" ${ c . title } "> ${ c . title } </li> ` ) . join ( "" ) }
2022-07-21 15:42:55 +02:00
< / u l >
`
}
2024-04-16 13:07:23 +02:00
renderSaveButton ( ) {
2022-06-27 18:52:48 +02:00
return `
2024-06-07 17:39:35 +02:00
< button title = "${this.getLabel(" save _help ")}" name = "save" class = "btn btn-primary ccp-toolbar-button" >
2022-06-27 18:52:48 +02:00
$ { this . # disc _icon }
< / b u t t o n >
`
}
2024-04-16 13:07:23 +02:00
renderDeleteButton ( ) {
2022-07-18 18:08:53 +02:00
return `
2024-06-07 17:39:35 +02:00
< button title = "${this.getLabel(" delete _help ")}" name = "delete" class = "btn btn-danger ccp-toolbar-button" >
2022-07-18 18:08:53 +02:00
$ { this . # delete _icon }
< / b u t t o n >
`
}
2024-04-16 13:07:23 +02:00
renderResetButton ( ) {
2022-06-27 18:52:48 +02:00
return `
2024-06-07 17:39:35 +02:00
< button name = "reset" title = "${this.getLabel(" reset _help ")}" class = "btn btn-primary ccp-toolbar-button" >
2022-06-27 18:52:48 +02:00
< svg viewBox = "0 0 24 24" >
$ { this . # erase _icon }
< / s v g >
< / b u t t o n >
2024-04-16 13:07:23 +02:00
`
2022-06-27 18:52:48 +02:00
}
2024-04-16 13:07:23 +02:00
renderPlusButton ( name ) {
2022-06-27 18:52:48 +02:00
return `
2024-06-07 17:39:35 +02:00
< button name = "${name}" title = "${this.getLabel(name + " _help ")}" class = "btn btn-primary ccp-toolbar-button" >
2022-06-27 18:52:48 +02:00
$ { this . # plus _icon }
< / b u t t o n >
`
}
2024-04-16 13:07:23 +02:00
renderStandardInputButtons ( ) {
2023-05-24 14:49:40 +02:00
return `
2024-06-07 17:39:35 +02:00
< button name = "add-ccpannotation" title = "${this.getLabel(" add _ccpnote _help ")}" class = "btn btn-info ccp-toolbar-button" >
2023-05-24 14:49:40 +02:00
$ { this . # annotation _input _icon }
< / b u t t o n >
`
}
2024-04-16 13:07:23 +02:00
renderStandardOutputButtons ( ) {
2022-06-27 18:52:48 +02:00
return `
2024-06-07 17:39:35 +02:00
< button name = "add-stdout" title = "${this.getLabel(" add _stdout _help ")}" class = "btn btn-success ccp-toolbar-button" >
2022-06-27 18:52:48 +02:00
$ { this . # output _icon }
< / b u t t o n >
2024-06-07 17:39:35 +02:00
< button name = "add-stderr" title = "${this.getLabel(" add _stderr _help ")}" class = "btn btn-danger ccp-toolbar-button" >
2022-06-27 18:52:48 +02:00
$ { this . # output _icon }
< / b u t t o n >
`
}
2024-04-16 13:07:23 +02:00
reRenderKeywords ( ) {
2022-06-27 18:52:48 +02:00
this . # rootdoc . querySelector ( "div[name=keyword-list]" ) . innerHTML = this . renderKeywords ( )
}
2024-04-16 13:07:23 +02:00
renderKeywords ( ) {
if ( this . # current . keywords ) {
return this . # current . keywords . map ( ( k , i ) => {
2022-06-27 18:52:48 +02:00
return `
2023-03-29 12:32:20 +02:00
< div class = "ccp-option badge ccp-keyword" title = "${k}" alt = "${k}" >
2022-06-27 18:52:48 +02:00
< span > $ { k } < / s p a n >
< span class = "btn text-danger ccp-toolbar-button" name = "delete-keyword" data - index = "${i}" > x < / s p a n >
< / d i v >
`
} ) . join ( "\n" )
2024-04-16 13:07:23 +02:00
} else {
2022-06-27 18:52:48 +02:00
return ""
}
}
2024-04-16 13:07:23 +02:00
reRenderCategories ( ) {
2023-04-06 16:41:10 +02:00
this . # rootdoc . querySelector ( "div[name=category-list]" ) . innerHTML = this . renderCategories ( )
}
2024-04-16 13:07:23 +02:00
renderCategories ( ) {
if ( this . # current . metadata ) {
return this . # current . metadata . filter ( md => md . role === "category" ) . map ( ( k , i ) => {
2023-04-06 16:41:10 +02:00
return `
2023-04-06 16:52:27 +02:00
< div class = "ccp-option badge ccp-category" title = "${k.title}" alt = "${k.title}" >
< span > $ { k . title } < / s p a n >
2023-04-06 16:41:10 +02:00
< span class = "btn text-danger ccp-toolbar-button" name = "delete-category" data - index = "${i}" > x < / s p a n >
< / d i v >
`
} ) . join ( "\n" )
2024-04-16 13:07:23 +02:00
} else {
2023-04-06 16:41:10 +02:00
return ""
}
2024-04-16 13:07:23 +02:00
}
reRenderInfrastructures ( ) {
2023-03-29 12:32:20 +02:00
this . # rootdoc . querySelector ( "select[name=infrastructure-input]" ) . innerHTML = this . renderInfrastructureOptions ( )
this . # rootdoc . querySelector ( "div[name=infrastructure-list]" ) . innerHTML = this . renderInfrastructures ( )
2022-06-27 18:52:48 +02:00
}
2024-04-16 13:07:23 +02:00
renderInfrastructureOptions ( ) {
const selectedinfras = this . # current . links . filter ( l => l . rel === "compatibleWith" ) . map ( i => i . href . split ( "/" ) [ 1 ] )
const available = this . # infrastructures . filter ( i => { return selectedinfras . indexOf ( i . id ) === - 1 } )
2022-06-27 18:52:48 +02:00
return `
< option > < / o p t i o n >
2024-04-16 13:07:23 +02:00
$ { available . map ( infra => {
return `
2023-03-29 12:32:20 +02:00
< option value = "${infra.id}" title = "${infra.description}" > $ { infra . name } < / o p t i o n >
2022-06-27 18:52:48 +02:00
`
2024-04-16 13:07:23 +02:00
} ) . join ( "\n" )
2022-06-27 18:52:48 +02:00
}
`
}
2024-04-16 13:07:23 +02:00
renderInfrastructures ( ) {
return this . # current . links . filter ( l => l . rel === "compatibleWith" ) . map ( ( l , i ) => {
2022-06-27 18:52:48 +02:00
return `
2023-03-29 12:32:20 +02:00
< div class = "ccp-option badge ccp-keyword" title = "${l.title}" alt = "${l.title}" >
2022-06-27 18:52:48 +02:00
< span > $ { l . title } < / s p a n >
2023-03-29 12:32:20 +02:00
< span class = "btn text-danger ccp-toolbar-button" name = "delete-infrastructure" data - index = "${i}" > x < / s p a n >
2022-06-27 18:52:48 +02:00
< / d i v >
`
} ) . join ( "\n" )
}
2024-04-16 13:07:23 +02:00
renderInputs ( ) {
2022-06-27 18:52:48 +02:00
const parent = this . # rootdoc . querySelector ( "div[name=input-list]" )
2024-04-16 13:07:23 +02:00
parent . innerHTML = ""
return this . # tmp _inputs . map ( ( inp , i ) => {
2022-06-27 18:52:48 +02:00
const c = document . createElement ( "d4s-ccp-input-editor" ) ;
parent . appendChild ( c )
2024-04-16 13:07:23 +02:00
c . render ( inp , i )
2022-06-27 18:52:48 +02:00
} )
}
2024-04-16 13:07:23 +02:00
renderOutputs ( ) {
2022-06-27 18:52:48 +02:00
const parent = this . # rootdoc . querySelector ( "div[name=output-list]" )
2024-04-16 13:07:23 +02:00
parent . innerHTML = ""
return this . # tmp _outputs . map ( ( outp , i ) => {
2022-06-27 18:52:48 +02:00
const c = document . createElement ( "d4s-ccp-output-editor" ) ;
parent . appendChild ( c )
2024-04-16 13:07:23 +02:00
c . render ( outp , i )
} )
}
codeToPreview ( code ) {
return this . # tmp _inputs . reduce ( ( acc , i ) => {
const r = new RegExp ( ` {{ \\ s* ${ i . id } \\ s*}} ` , 'g' ) ;
var def = i . schema . default
if ( i . schema . format === "secret" ) {
def = Array . isArray ( def ) ? def : [ def ]
def = def . map ( v => "***" )
}
if ( i . schema . format === "file" ) {
def = Array . isArray ( def ) ? def : [ def ]
2024-04-23 16:46:47 +02:00
def = def . map ( v => v . length > 15 ? v . substring ( 0 , 5 ) + "..." + v . substring ( v . length - 5 ) : v )
2024-04-16 13:07:23 +02:00
}
return acc . replaceAll ( r , def )
} , code )
}
2024-10-11 13:12:30 +02:00
reRenderScripts ( scriptname ) {
const container = this . # rootdoc . querySelector ( "div[name=scripts_container]" )
const scripts = [ "deploy-script" , "execute-script" ]
scripts . forEach ( sname => {
const script = this . # current . additionalParameters . parameters . find ( s => s . name === sname )
const code = script . value && script . value . length ? script . value . join ( "\r\n" ) : ""
const preview = container . querySelector ( ` details[name= ${ sname } ] textarea[name=preview] ` )
preview . value = this . codeToPreview ( code )
} )
2024-04-16 13:07:23 +02:00
}
2024-10-11 13:12:30 +02:00
renderScriptContent ( scriptname ) {
const script = this . # current . additionalParameters . parameters . find ( s => s . name === scriptname )
2024-04-16 13:07:23 +02:00
if ( ! script ) return '' ;
const code = script . value && script . value . length ? script . value . join ( "\r\n" ) : ""
return `
2024-10-11 13:12:30 +02:00
< div class = "script-area" name = "${script.name}" >
< textarea name = "${script.name}" rows = "5" class = "form-control" > $ { code } < / t e x t a r e a >
2024-04-16 13:07:23 +02:00
< span name = "preview" class = "d-inline-block fst-italic text-muted position-absolute m-0 end-0 px-4 py-2 pe-none" > Preview < / s p a n >
< textarea rows = "5" name = "preview" class = "script-area form-control my-1 text-muted border-0" readonly > $ { this . codeToPreview ( code ) } < / t e x t a r e a >
< / d i v >
`
}
2024-10-11 13:12:30 +02:00
renderScripts ( ) {
const scripts = [ "deploy-script" , "execute-script" ]
const html = scripts . map ( sname => {
return `
< details class = "card" name = "${sname}" title = "${this.getLabel(" scripts _help ")}" >
< summary class = "card-header" >
< div class = "ccp-toolbar-header" >
< div >
< span > $ { this . getLabel ( sname ) } < / s p a n >
< / d i v >
< / d i v >
< / s u m m a r y >
< div class = "card-body" >
$ { this . renderScriptContent ( sname ) }
< / d i v >
< / d e t a i l s >
`
} ) . join ( "" )
return html
2022-06-27 18:52:48 +02:00
}
}
window . customElements . define ( 'd4s-ccp-methodeditor' , CCPMethodEditorController ) ;