diff --git a/boot/d4s-boot.js b/boot/d4s-boot.js
index f0a174a..21c3a8d 100644
--- a/boot/d4s-boot.js
+++ b/boot/d4s-boot.js
@@ -107,14 +107,14 @@ window.customElements.define('d4s-boot-2', class extends HTMLElement {
startStateChecker() {
this.#interval = window.setInterval(() => {
if (this.#locked) {
- console.log("Still locked. Currently has " + this.#queue.length + " pending requests.")
+ //console.log("Still locked. Currently has " + this.#queue.length + " pending requests.")
} else if (!this.authenticated) {
window.alert("Not authorized!")
} else {
if (this.#queue.length > 0) {
this.#keycloak.updateToken(30).then(() => {
if (this.#audience) {
- console.log("Checking entitlement for audience", this.#audience)
+ //console.log("Checking entitlement for audience", this.#audience)
const audience = encodeURIComponent(this.#audience)
return this.entitlement(audience)
} else {
@@ -122,7 +122,7 @@ window.customElements.define('d4s-boot-2', class extends HTMLElement {
}
}).then(token => {
- console.log("Authorized. Token exp: " + this.expirationDate(this.parseJwt(token).exp))
+ //console.log("Authorized. Token exp: " + this.expirationDate(this.parseJwt(token).exp))
//transform all queued requests to fetches
//console.log("All pending requests to promises")
let promises = this.#queue.map(r => {
diff --git a/ccp/index.html b/ccp/index.html
index 1d9d6ee..a8e5cf6 100644
--- a/ccp/index.html
+++ b/ccp/index.html
@@ -2,6 +2,7 @@
+ `
+ }
+
+ async refreshArchivedExecutions(){
+ this.showLoading(this.#rootdoc.querySelector("ul[name=ccp_archived_execution_list]"))
+ await this.initWorkspace()
+ if(this.#execfolderid){
+ const folders = await this.#ws.listFolder(this.#execfolderid)
+ this.#archived = {}
+ for(let i=0; i < folders.length; i++){
+ const methodfolder = folders[i]
+ const executionfolders = await this.#ws.listFolder(methodfolder.id)
+ for(let j=0; j < executionfolders.length; j++){
+ const metadatafolder = await this.#ws.findByName(executionfolders[j].id, "metadata")
+ if(metadatafolder.length === 1){
+ //parse all metada content that is useful to build up an entry
+ const metadata = await this.#ws.download(metadatafolder[0].id, null, true)
+ const zip = new JSZip()
+ const req = JSON.parse(await (zip.loadAsync(metadata).then(z=>z.file("metadata/request.json").async("string"))))
+ const status = JSON.parse(await (zip.loadAsync(metadata).then(z=>z.file("metadata/jobStatus.json").async("string"))))
+ const meth = JSON.parse(await (zip.loadAsync(metadata).then(z=>z.file("metadata/method.json").async("string"))))
+ const infra = JSON.parse(await (zip.loadAsync(metadata).then(z=>z.file("metadata/infrastructure.json").async("string"))))
+ const parser = new DOMParser()
+ // Fasted way to get context is from prov-o. If it doesn't match the context in boot skip this execution
+ const provo = parser.parseFromString(await zip.loadAsync(metadata).then(z=>z.file("metadata/prov-o.xml").async("string")), "text/xml")
+ const context = provo.querySelector("entity[*|id='d4s:VRE']>value").textContent
+ if(context !== this.#boot.context && context.replaceAll("/", "%2F") !== this.#boot.context) continue;
+ //build entry from downloaded data
+ const entry = {
+ id : req.id,
+ status : status.status,
+ created : status.created,
+ started : status.started,
+ updated : status.updated,
+ message : status.message,
+ method : meth.title,
+ methodversion : meth.version,
+ infrastructure: infra.name,
+ infrastructuretype : infra.type,
+ ccpnote : req.inputs.ccpnote ? req.inputs.ccpnote : "",
+ runtime : req.inputs.ccpimage,
+ replicas : req.inputs.ccpreplicas ? req.inputs.ccpreplicas : 1,
+ href : `items/${executionfolders[j].id}/download`,
+ wsid : executionfolders[j].id,
+ fullrequest : req,
+ fullmethod : meth,
+ fullinfrastructure : infra
+ }
+ if(this.#archived[entry.method]) this.#archived[entry.method].push(entry);
+ else this.#archived[entry.method] = [entry]
+ }
+ }
+ }
+ }
+ BSS.apply(this.#archived_execution_list_bss, this.#rootdoc)
+ }
#execution_list_bss = {
template : "#EXECUTIOM_LIST_TEMPLATE",
@@ -582,19 +826,19 @@ class CCPExecutionHistory extends HTMLElement {
this.export(id, "application/prov-o+xml", id + ".xml")
}
if(ev.target.getAttribute("name") === "reexecute1"){
- if(window.confirm("Please confirm re-execution?")){
+ if(window.confirm(this.getLabel("confirm_reexecution"))){
const id = ev.currentTarget.getAttribute("data-index")
this.reexecute(id, 1)
}
}
if(ev.target.getAttribute("name") === "archive"){
- if(confirm(" Please confirm archiving of execution to workspace folder?")){
+ if(confirm(this.getLabel("confirm_archive_execution"))){
const id = ev.currentTarget.getAttribute("data-index")
this.toArchiveFolder(id)
}
}
if(ev.target.getAttribute("name") === "archiveoutputs"){
- if(confirm(" Please confirm archiving of execution outputs to workspace folder?")){
+ if(confirm(this.getLabel("confirm_archive_outputs"))){
const id = ev.currentTarget.getAttribute("data-index")
this.toOutputsArchiveFolder(id)
}
@@ -686,7 +930,8 @@ class CCPExecutionHistory extends HTMLElement {
e.textContent = rt + (d.replicas && d.replicas !== "1" ? ' x ' + d.replicas : '')
const t = infratype.match(/docker/i) ? "docker" : null
const t2 = !t && infratype.match(/lxd/i) ? "lxd" : t
- e.classList.add(t2)
+ const t3 = !t2 && infratype.match(/galaxy/i) ? "galaxy" : t
+ e.classList.add(t3)
}
},
{
@@ -737,5 +982,150 @@ class CCPExecutionHistory extends HTMLElement {
}
]
}
+
+ #archived_execution_list_bss = {
+ template : "#ARCHIVED_EXECUTION_LIST_TEMPLATE",
+ target : "ul[name=ccp_archived_execution_list]",
+ in : ()=>this,
+ recurse:[
+ {
+ target : "li.ccp-method-item",
+ "in" : (e,d)=>Object.keys(this.#archived),
+ recurse: [
+ {
+ target : "details[name=level1]",
+ apply : (e,d)=>{
+ e.alt = e.title = d
+ if(sessionStorage.getItem("arch_" + d) === "open") e.open = "open";
+ else e.removeAttribute("open");
+ },
+ on_toggle : ev=>{
+ if(ev.target.open){
+ sessionStorage.setItem("arch_" + ev.currentTarget.alt, 'open')
+ }else{
+ sessionStorage.removeItem("arch_" + ev.currentTarget.alt)
+ }
+ },
+ },
+ {
+ target : "summary.ccp-method-item-header h5",
+ apply : (e,d) => { e.textContent = d }
+ },
+ {
+ target : "li.ccp-execution-item",
+ "in" : (e,d)=>this.#archived[d],
+ apply : (e,d)=>{
+ e.setAttribute("data-index", d.id)
+ e.setAttribute("data-href", d.href)
+ e.setAttribute("data-wsid", d.wsid)
+ },
+ on_dragstart : ev=>{
+ ev.dataTransfer.effectAllowed = 'move'
+ ev.dataTransfer.setData('text/html', ev.currentTarget.innerHTML)
+ ev.dataTransfer.setData('text/plain+ccpexecution', ev.currentTarget.getAttribute("data-index"))
+ ev.dataTransfer.setData('application/json+ccpexecution', JSON.stringify(ev.currentTarget.bss_input.data))
+ },
+ on_dragend : ev=>{
+ ev.preventDefault()
+ },
+ on_click: ev=>{
+ if(ev.target.getAttribute("name") === "restore"){
+ if(window.confirm(this.getLabel("confirm_restore_execution"))){
+ const href = ev.currentTarget.getAttribute("data-href")
+ this.fromArchiveFolder(href)
+ }
+ }else if(ev.target.getAttribute("name") === "delete"){
+ if(window.confirm(this.getLabel("confirm_delete_archived_execution"))){
+ const wsid = ev.currentTarget.getAttribute("data-wsid")
+ this.deleteArchiveFolder(wsid)
+ }
+ }else if(ev.target.getAttribute("name") === "reexecute2"){
+ if(window.confirm(this.getLabel("confirm_reexecution"))){
+ this.reexecuteArchived(ev.currentTarget.bss_input.data, 1)
+ }
+ }
+
+ },
+ recurse : [
+ {
+ target : "span[name=version]",
+ apply : (e,d)=>{
+ if(d.ccpnote){
+ e.textContent = `${d.ccpnote} (${d.methodversion})`
+ }else{
+ e.textContent = `${d.methodversion}`
+ }
+ }
+ },
+ {
+ target : "span[name=status]",
+ apply : (e,d)=>{
+ if(d.status){
+ const status = d.status
+ e.textContent = status
+ if (status === "running") e.classList.add("badge-primary");
+ else if (status === "successful") e.classList.add("badge-success");
+ else if (status === "failed") e.classList.add("badge-danger");
+ else e.classList.add("badge-secondary");
+ }
+ }
+ },
+ {
+ target : "span[name=created]",
+ apply : (e,d)=>{
+ if(d.created){
+ const dt = new Date(d.created)
+ e.textContent = `Accepted ${dt.toLocaleDateString()} @ ${dt.toLocaleTimeString()}`
+ }
+ }
+ },
+ {
+ target : "span[name=started]",
+ apply : (e,d)=>{
+ if(d.started){
+ const dt = new Date(d.started)
+ e.textContent = `Started ${dt.toLocaleDateString()} @ ${dt.toLocaleTimeString()}`
+ }
+ }
+ },
+ {
+ target : "span[name=updated]",
+ apply : (e,d)=>{
+ const dt = new Date(d.updated)
+ e.textContent = `Last update ${dt.toLocaleDateString()} @ ${dt.toLocaleTimeString()}`
+ }
+ },
+ {
+ target : "span[name=message]",
+ apply : (e,d)=>{
+ if(d.message){
+ e.textContent = d.message
+ }
+ }
+ },
+ {
+ target : "span[name=infrastructure]",
+ apply : (e,d)=>{
+ e.textContent = d.infrastructure
+ }
+ },
+ {
+ target : "span[name=runtime]",
+ apply : (e,d)=>{
+ const rt = d.runtime ? d.runtime : ""
+ const infratype = d.infrastructuretype ? d.infrastructuretype : ""
+ e.textContent = rt + (d.replicas && d.replicas !== "1" ? ' x ' + d.replicas : '')
+ const t = infratype.match(/docker/i) ? "docker" : null
+ const t2 = !t && infratype.match(/lxd/i) ? "lxd" : t
+ const t3 = !t2 && infratype.match(/galaxy/i) ? "galaxy" : t
+ e.classList.add(t3)
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
}
window.customElements.define('d4s-ccp-executionhistory', CCPExecutionHistory);
diff --git a/ccp/js/inputwidgetcontroller.js b/ccp/js/inputwidgetcontroller.js
index 4eb48a9..95a2c10 100644
--- a/ccp/js/inputwidgetcontroller.js
+++ b/ccp/js/inputwidgetcontroller.js
@@ -709,7 +709,6 @@ class CCPRemoteFileInputWidgetController extends CCPBaseInputWidgetController {
})
this.addEventListener("input", ev => {
- ev.stopPropagation()
if (ev.target.getAttribute("name") == this.name && ev.target.getAttribute("data-index") != null) {
this.value[Number(ev.target.getAttribute("data-index"))] = ev.target.value
}
@@ -808,7 +807,7 @@ class CCPGeoInputWidgetController extends CCPBaseInputWidgetController {
-
+
@@ -825,7 +824,7 @@ class CCPGeoInputWidgetController extends CCPBaseInputWidgetController {
Draw and export geometry
-