cdn-experiments/ccp/js/executionformcontroller.js

298 lines
8.8 KiB
JavaScript
Raw Normal View History

2022-03-25 15:39:39 +01:00
class CCPExecutionForm extends HTMLElement{
#boot;
#rootdoc;
#data;
#method;
2022-05-05 12:19:06 +02:00
#executionmonitor;
2022-03-25 15:39:39 +01:00
#serviceurl;
2022-03-25 15:39:39 +01:00
constructor(){
super()
this.#boot = document.querySelector("d4s-boot-2")
this.#serviceurl = this.getAttribute("serviceurl")
2022-03-25 15:39:39 +01:00
this.#rootdoc = this.attachShadow({ "mode" : "open"})
this.render()
this.showMethod()
2022-03-25 15:39:39 +01:00
}
static get observedAttributes() {
2022-05-05 12:19:06 +02:00
return ["method"];
2022-03-25 15:39:39 +01:00
}
attributeChangedCallback(name, oldValue, newValue) {
if((oldValue != newValue) && (name === "method")){
this.#method = newValue
this.loadMethod()
}
}
render(){
this.#rootdoc.innerHTML = `
<div>
<link rel="stylesheet" href="https://cdn.dev.d4science.org/ccp/css/common.css"></link>
<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>
</style>
<template id="EXECUTION_FORM_TEMPLATE">
<div class="ccp-execution-form" name="execution_form">
<h5 class="ccp-method-title"></h5>
<p class="description font-italic font-weight-lighter"></p>
<div name="plexiglass" class="ccp-invisible">
<span name="status"></span>
<span class="fas fa-spinner fa-spin"></span>
</div>
<form name="execution_form" class="d-flex flex-column gap-3" style="gap:5px">
<div class="card">
<div class="card-header">
<h5>Inputs</h5>
</div>
<div class="card-body ccp-inputs">
<div class="card-body">
<div class="form-group"></div>
</div>
</div>
</div>
<div class="card">
<div class="card-header">
<h5>Outputs</h5>
</div>
<div class="card-body">
<div class="form-row ccp-outputs">
<div class="col form-group"></div>
</div>
</div>
</div>
<!--div class="card">
<div class="card-header">
<h5>Runtimes <span alt="refresh" title="refresh" style="cursor:pointer" name="refresh-runtimes" class="text-info">&#8634;</span></h5>
</div>
<div class="card-body">
<div class="ccp-runtimes">
<div class="form-row">
<select class="form-control">
</select>
</div>
</div>
</div>
</div-->
<button id="execute_method_button" class="btn btn-info">Execute</button>
</form>
</div>
</template>
<template id="EXECUTION_FORM_EMPTY_TEMPLATE">
<div name="execution_form">
<i style="padding:3rem">Select a method</i>
</div>
</template>
<div name="execution_form"></div>
</div>
`
2022-03-25 15:39:39 +01:00
}
loadMethod(){
2022-04-12 19:51:38 +02:00
this.#boot.secureFetch(this.#serviceurl + "/processes/" + this.#method).then(
2022-03-25 15:39:39 +01:00
(resp)=>{
2022-04-12 19:51:38 +02:00
if(resp.status === 200){
return resp.json()
}else throw "Error retrieving process"
}
).then(data=>{
this.#data = data
2022-05-05 12:19:06 +02:00
const rts =
this.#data.links
.filter(l => l.rel === "compatibleWith")
.map(l=>l.href.replace("runtimes/",""))
.join(" ")
return this.#boot.secureFetch(this.#serviceurl + "/infrastructures/runtimes?runtimes=" + rts)
}).then(resp=>{
this.#data.executable = resp.status === 200
}).then(()=>{
2022-04-12 19:51:38 +02:00
this.showMethod()
}).catch(err=>alert(err))
2022-03-25 15:39:39 +01:00
}
showEmpty(resp){
BSS.apply(this.#empty_executionform_bss, this.#rootdoc)
}
showMethod(){
if(this.#method == null) this.showEmpty();
else{
console.log(this.#data)
BSS.apply(this.#executionform_bss, this.#rootdoc)
}
}
2022-04-12 19:51:38 +02:00
sendExecutionRequest(){
const url = this.#serviceurl + "/processes/" + this.#method + "/execution"
2022-05-05 12:19:06 +02:00
const req = this.buildRequest()
2022-04-12 19:51:38 +02:00
this.#boot.secureFetch(
2022-05-05 12:19:06 +02:00
url, { method : "POST", body : JSON.stringify(req), headers : { "Content-Type" : "application/json"}}
2022-04-12 19:51:38 +02:00
).then(reply=>{
if(reply.status !== 200 && reply.status !== 201){
throw "Error while requesting resource"
}
2022-05-05 12:19:06 +02:00
return reply.json()
}).then(data=>{
if(data.status !== "accepted"){
throw "Execution has not been accepted by server"
}
this.#executionmonitor = document.querySelector("d4s-ccp-executionmonitor")
if(this.#executionmonitor){
this.#executionmonitor.addExecution( { self : data.links[0].href, events : [data], jobID : data.jobID, method : this.#data.title})
}
}).catch(err => alert("Unable to call execute: " + err))
}
buildRequest(){
let request = { inputs : {}, outputs : {}, response : "raw"}
//fill inputs
const inputs = this.getInputs()
inputs.forEach(i=>{
request.inputs[i.name] = i.value
})
//fill outputs
const outputs = this.getOutputs()
outputs.forEach(o=>{
if(o.enabled) request.outputs[o.name] = { transmissionMode : "value" };
})
return request
}
getInputs(){
return Array.prototype.slice.call(this.#rootdoc.querySelectorAll("d4s-ccp-input"))
}
getOutputs(){
return Array.prototype.slice.call(this.#rootdoc.querySelectorAll("d4s-ccp-output"))
2022-04-12 19:51:38 +02:00
}
2022-03-25 15:39:39 +01:00
#empty_executionform_bss = {
template : "#EXECUTION_FORM_EMPTY_TEMPLATE",
2022-03-28 16:42:02 +02:00
target : "div[name=execution_form]",
2022-03-25 15:39:39 +01:00
on_drop : ev=>{
2022-03-28 16:42:02 +02:00
if(ev.dataTransfer && ev.dataTransfer.getData('text/plain+ccpmethod')){
const id = ev.dataTransfer.getData('text/plain+ccpmethod')
2022-03-25 15:39:39 +01:00
this.setAttribute("method", id);
ev.preventDefault()
ev.stopPropagation()
ev.currentTarget.style.backgroundColor = "white"
}
},
on_dragover : ev=>{
ev.preventDefault()
},
}
#executionform_bss = {
template : "#EXECUTION_FORM_TEMPLATE",
2022-03-28 16:52:09 +02:00
target : "div[name=execution_form]",
2022-03-25 15:39:39 +01:00
in : ()=>this.#data,
on_drop : ev=>{
2022-03-28 16:42:02 +02:00
if(ev.dataTransfer && ev.dataTransfer.getData('text/plain+ccpmethod')){
const id = ev.dataTransfer.getData('text/plain+ccpmethod');
2022-03-25 15:39:39 +01:00
this.setAttribute("method", id);
ev.preventDefault()
ev.stopPropagation()
}
},
on_dragover : ev=>{
ev.preventDefault()
},
recurse : [
{
2022-05-05 16:51:47 +02:00
target: ".ccp-method-title",
2022-03-25 15:39:39 +01:00
apply : (e,d)=>e.textContent = d.title + " (v. " + d.version + ")"
},
{
target: "p.description",
apply : (e,d)=>e.textContent = d.description
},
{
target: "div.ccp-inputs",
in : (e,d)=>d,
recurse : [
{
"in" : (e,d)=>{ return Object.values(d.inputs) },
target : "div",
apply : (e,d)=>{
e.innerHTML = `<d4s-ccp-input input='${JSON.stringify(d)}'></d4s-ccp-input>`
}
}
]
2022-04-12 19:51:38 +02:00
},
{
target: "div.ccp-outputs",
in : (e,d)=>d,
recurse : [
{
"in" : (e,d)=>{ return Object.values(d.outputs) },
target : "div",
apply : (e,d)=>{
e.innerHTML = `<d4s-ccp-output output='${JSON.stringify(d)}'></d4s-ccp-output>`
}
}
]
},
{
target: "div.ccp-runtimes *[name=refresh-runtimes]",
on_click : ev=>{
BSS.apply(this.#executionform_bss)
}
},
{
target: "#execute_method_button",
on_click : ev=>{
ev.preventDefault()
ev.stopPropagation()
2022-05-05 12:19:06 +02:00
if(this.#data.executable) this.sendExecutionRequest();
else alert("This method has no compatible runtimes available")
2022-04-12 19:51:38 +02:00
return false;
}
},
2022-03-25 15:39:39 +01:00
]
}
}
window.customElements.define('d4s-ccp-executionform', CCPExecutionForm);
2022-05-05 12:19:06 +02:00
class CCPExecutionEnvironmentOption extends HTMLOptionElement{
#infrastructure;
#runtime;
constructor(runtime, infrastructure){
super(`${runtime.name} [${infrastructure.name}]`, runtime["descriptor-id"])
this.#runtime = runtime
this.#infrastructure = infrastructure
this.textContent = `${runtime.name} [${infrastructure.name}]`
this.value = this.runtimeId
}
get infrastructureName(){
return this.#infrastructure.name
}
get infrastructureId(){
return this.#infrastructure.id
}
get runtimeName(){
return this.#runtime.name
}
get runtimeId(){
return this.#runtime["descriptor-id"]
}
}
window.customElements.define('d4s-ccp-environment-option', CCPExecutionEnvironmentOption, {extends:'option'});