Compare commits

...

5 Commits

10 changed files with 921 additions and 724 deletions

View File

@ -124,14 +124,14 @@ window.customElements.define('d4s-boot-2', class extends HTMLElement {
}).then(token => { }).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 //transform all queued requests to fetches
console.log("All pending requests to promises") //console.log("All pending requests to promises")
let promises = this.#queue.map(r => { let promises = this.#queue.map(r => {
r.request.headers["Authorization"] = "Bearer " + token r.request.headers["Authorization"] = "Bearer " + token
return r.resolve( fetch(r.url, r.request) ) return r.resolve( fetch(r.url, r.request) )
}) })
//clear queue //clear queue
this.#queue = [] this.#queue = []
console.log("Resolving all fetches") //console.log("Resolving all fetches")
return Promise.all(promises) return Promise.all(promises)
}).catch(err => console.error("Unable to make calls: " + err)) // Sometimes throws: Unable to make calls: TypeError: Cannot read properties of undefined (reading 'split') }).catch(err => console.error("Unable to make calls: " + err)) // Sometimes throws: Unable to make calls: TypeError: Cannot read properties of undefined (reading 'split')
@ -177,7 +177,7 @@ window.customElements.define('d4s-boot-2', class extends HTMLElement {
} else { } else {
req.headers = { "Authorization" : null} req.headers = { "Authorization" : null}
} }
console.log("Queued request to url ", url) //console.log("Queued request to url ", url)
this.#queue.push({ url : url, request : req, resolve : resolve, reject : reject}) this.#queue.push({ url : url, request : req, resolve : resolve, reject : reject})
}) })
return p return p
@ -202,7 +202,7 @@ window.customElements.define('d4s-boot-2', class extends HTMLElement {
.then(response => response.json()) .then(response => response.json())
.then(json => { .then(json => {
this.#config = json this.#config = json
console.log("Keycloak uma2 configuration loaded") //console.log("Keycloak uma2 configuration loaded")
resolve(true) resolve(true)
}) })
.catch(err => reject("Failed to fetch uma2-configuration from server: " + err)) .catch(err => reject("Failed to fetch uma2-configuration from server: " + err))

33
ccp/index.html Normal file
View File

@ -0,0 +1,33 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<script src="js/methodlistcontroller.js"></script>
<script src="js/methodeditorcontroller.js"></script>
<script src="js/inputwidgeteditorcontroller.js"></script>
<script src="js/outputwidgeteditorcontroller.js"></script>
<script src="js/executionformcontroller.js"></script>
<script src="js/inputwidgetcontroller.js"></script>
<script src="js/outputwidgetcontroller.js"></script>
<link href="css/common.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<script src="https://cdn.cloud-dev.d4science.org/common/js/bss-min-1.2.6.js"></script>
<script src="https://cdn.cloud-dev.d4science.org/storage/d4s-storage.js"></script>
</head>
<body class="m-4">
<d4s-boot-2 clientid="https://next.dev.d4science.org" context="%2Fgcube%2Fdevsec%2FCCP" gateway="next.dev.d4science.org" redirect-url="http://localhost:8080/ccp/index.html" url="https://accounts.dev.d4science.org/auth"> <script src="https://cdn.dev.d4science.org/boot/d4s-boot.js"></script> </d4s-boot-2>
<div class="row">
<div class="col">
<d4s-ccp-methodlist serviceurl="https://ccp.cloud-dev.d4science.org"></d4s-ccp-methodlist>
</div>
<div class="col">
<d4s-ccp-methodeditor serviceurl="https://ccp.cloud-dev.d4science.org"></d4s-ccp-methodeditor>
</div>
<div class="col">
<d4s-ccp-executionform serviceurl="https://ccp.cloud-dev.d4science.org"></d4s-ccp-executionform>
</div>
</div>
</body>
</html>

View File

@ -55,6 +55,7 @@ class CCPExecutionForm extends HTMLElement{
render(){ render(){
this.#rootdoc.innerHTML = ` this.#rootdoc.innerHTML = `
<div> <div>
<link rel="canonical" href="https://getbootstrap.com/docs/5.0/components/modal/">
<link rel="stylesheet" href="https://cdn.dev.d4science.org/ccp/css/common.css"></link> <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"> <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>

View File

@ -2,115 +2,135 @@ class CCPInputWidgetController extends HTMLElement {
#data = null; #data = null;
constructor(){ constructor() {
super() super()
} }
connectedCallback(){ connectedCallback() {
this.#data = JSON.parse(atob(this.getAttribute("input"))) this.#data = JSON.parse(atob(this.getAttribute("input")))
if(this.isChecklist()){ if (this.isChecklist()) {
const opts = this.#data.schema.enum.join(",") const opts = this.#data.schema.enum.join(",")
this.innerHTML += `<d4s-ccp-input-checklist readonly="${this.#data.schema.readOnly}" options="${opts}" default="${this.#data.schema.default||''}" maxOccurs="${this.#data.maxOccurs||1}" minOccurs="${this.#data.minOccurs||1}" name="${this.#data.id}" description="${btoa(this.#data.description)}" title="${this.#data.title}"></d4s-ccp-input-checklist>` this.innerHTML += `<d4s-ccp-input-checklist readonly="${this.#data.schema.readOnly}" options="${opts}" default="${this.#data.schema.default}" maxOccurs="${this.#data.maxOccurs}" minOccurs="${this.#data.minOccurs}" name="${this.#data.id}" description="${btoa(this.#data.description)}" title="${this.#data.title}"></d4s-ccp-input-checklist>`
this.querySelector("d4s-ccp-input-checklist").default = this.#data.schema.default
} else if(this.isEnum()){ } else if (this.isEnum()) {
const opts = this.#data.schema.enum.join(",") const opts = this.#data.schema.enum.join(",")
this.innerHTML += `<d4s-ccp-input-enum readonly="${this.#data.schema.readOnly}" options="${opts}" default="${this.#data.schema.default||''}" maxOccurs="${this.#data.maxOccurs||1}" minOccurs="${this.#data.minOccurs||1}" name="${this.#data.id}" description="${btoa(this.#data.description)}" title="${this.#data.title}"></d4s-ccp-input-enum>` this.innerHTML += `<d4s-ccp-input-enum readonly="${this.#data.schema.readOnly}" options="${opts}" default="${this.#data.schema.default}" maxOccurs="${this.#data.maxOccurs}" minOccurs="${this.#data.minOccurs}" name="${this.#data.id}" description="${btoa(this.#data.description)}" title="${this.#data.title}"></d4s-ccp-input-enum>`
}else if(this.isCode()){ this.querySelector("d4s-ccp-input-enum").default = this.#data.schema.default
this.innerHTML += `<d4s-ccp-input-textarea readonly="${this.#data.schema.readOnly}" default="${this.#data.schema.default||''}" maxOccurs="${this.#data.maxOccurs||1}" minOccurs="${this.#data.minOccurs||1}" name="${this.#data.id}" description="${btoa(this.#data.description)}" title="${this.#data.title}"></d4s-ccp-input-textarea>`
} else if (this.isCode()) {
this.innerHTML += `<d4s-ccp-input-textarea readonly="${this.#data.schema.readOnly}" default="${this.#data.schema.default}" maxOccurs="${this.#data.maxOccurs}" minOccurs="${this.#data.minOccurs}" name="${this.#data.id}" description="${btoa(this.#data.description)}" title="${this.#data.title}"></d4s-ccp-input-textarea>`
this.querySelector("d4s-ccp-input-textarea").default = this.#data.schema.default
} else if (this.isDateTime()) {
}else if(this.isDateTime()){
const t = this.#data.schema.format.toLowerCase() === "datetime" ? const t = this.#data.schema.format.toLowerCase() === "datetime" ?
"datetime-local" : this.#data.schema.format.toLowerCase() "datetime-local" : this.#data.schema.format.toLowerCase()
this.innerHTML += `<d4s-ccp-input-simple type="${t}" readonly="${this.#data.schema.readOnly}" default="${this.#data.schema.default||''}" maxOccurs="${this.#data.maxOccurs||1}" minOccurs="${this.#data.minOccurs||1}" name="${this.#data.id}" description="${btoa(this.#data.description)}" title="${this.#data.title}"></d4s-ccp-input-simple>` this.innerHTML += `<d4s-ccp-input-simple type="${t}" readonly="${this.#data.schema.readOnly}" default="${this.#data.schema.default}" maxOccurs="${this.#data.maxOccurs}" minOccurs="${this.#data.minOccurs}" name="${this.#data.id}" description="${btoa(this.#data.description)}" title="${this.#data.title}"></d4s-ccp-input-simple>`
this.querySelector("d4s-ccp-input-simple").default = this.#data.schema.default
}else if(this.isFile()){ } else if (this.isFile()) {
this.innerHTML += `<d4s-ccp-input-file readonly="${this.#data.schema.readOnly}" default="${this.#data.schema.default||''}" maxOccurs="${this.#data.maxOccurs||1}" minOccurs="${this.#data.minOccurs||1}" name="${this.#data.id}" description="${btoa(this.#data.description)}" title="${this.#data.title}"></d4s-ccp-input-file>`
}else if(this.isRemoteFile()){ this.innerHTML += `<d4s-ccp-input-file readonly="${this.#data.schema.readOnly}" default="${this.#data.schema.default}" maxOccurs="${this.#data.maxOccurs}" minOccurs="${this.#data.minOccurs}" name="${this.#data.id}" description="${btoa(this.#data.description)}" title="${this.#data.title}"></d4s-ccp-input-file>`
this.innerHTML += `<d4s-ccp-input-remotefile readonly="${this.#data.schema.readOnly}" default="${this.#data.schema.default||''}" maxOccurs="${this.#data.maxOccurs||1}" minOccurs="${this.#data.minOccurs||1}" name="${this.#data.id}" description="${btoa(this.#data.description)}" title="${this.#data.title}"></d4s-ccp-input-remotefile>` this.querySelector("d4s-ccp-input-file").default = this.#data.schema.default
}else if(this.isSecret()){ } else if (this.isRemoteFile()) {
this.innerHTML += `<d4s-ccp-input-secret readonly="${this.#data.schema.readOnly}" default="${this.#data.schema.default||''}" maxOccurs="${this.#data.maxOccurs||1}" minOccurs="${this.#data.minOccurs||1}" name="${this.#data.id}" description="${btoa(this.#data.description)}" title="${this.#data.title}"></d4s-ccp-input-secret>`
}else if(this.isBoolean()){ this.innerHTML += `<d4s-ccp-input-remotefile readonly="${this.#data.schema.readOnly}" default="${this.#data.schema.default}" maxOccurs="${this.#data.maxOccurs}" minOccurs="${this.#data.minOccurs}" name="${this.#data.id}" description="${btoa(this.#data.description)}" title="${this.#data.title}"></d4s-ccp-input-remotefile>`
this.innerHTML += `<d4s-ccp-input-boolean readonly="${this.#data.schema.readOnly}" default="${this.#data.schema.default||''}" maxOccurs="${this.#data.maxOccurs||1}" minOccurs="${this.#data.minOccurs||1}" name="${this.#data.id}" description="${btoa(this.#data.description)}" title="${this.#data.title}"></d4s-ccp-input-boolean>` this.querySelector("d4s-ccp-input-remotefile").default = this.#data.schema.default
}else if(this.isNumber()){ } else if (this.isSecret()) {
this.innerHTML += `<d4s-ccp-input-simple type="number" readonly="${this.#data.schema.readOnly}" default="${this.#data.schema.default||''}" maxOccurs="${this.#data.maxOccurs||1}" minOccurs="${this.#data.minOccurs||1}" name="${this.#data.id}" description="${btoa(this.#data.description)}" title="${this.#data.title}"></d4s-ccp-input-simple>`
this.innerHTML += `<d4s-ccp-input-secret readonly="${this.#data.schema.readOnly}" default="${this.#data.schema.default}" maxOccurs="${this.#data.maxOccurs}" minOccurs="${this.#data.minOccurs }" name="${this.#data.id}" description="${btoa(this.#data.description)}" title="${this.#data.title}"></d4s-ccp-input-secret>`
this.querySelector("d4s-ccp-input-secret").default = this.#data.schema.default
} else if (this.isBoolean()) {
this.innerHTML += `<d4s-ccp-input-boolean readonly="${this.#data.schema.readOnly}" default="${this.#data.schema.default}" maxOccurs="${this.#data.maxOccurs}" minOccurs="${this.#data.minOccurs}" name="${this.#data.id}" description="${btoa(this.#data.description)}" title="${this.#data.title}"></d4s-ccp-input-boolean>`
this.querySelector("d4s-ccp-input-boolean").default = this.#data.schema.default
} else if (this.isNumber()) {
this.innerHTML += `<d4s-ccp-input-simple type="number" readonly="${this.#data.schema.readOnly}" default="${this.#data.schema.default}" maxOccurs="${this.#data.maxOccurs}" minOccurs="${this.#data.minOccurs}" name="${this.#data.id}" description="${btoa(this.#data.description)}" title="${this.#data.title}"></d4s-ccp-input-simple>`
this.querySelector("d4s-ccp-input-simple").default = this.#data.schema.default
} else {
this.innerHTML += `<d4s-ccp-input-simple readonly="${this.#data.schema.readOnly}" default="${this.#data.schema.default}" maxOccurs="${this.#data.maxOccurs}" minOccurs="${this.#data.minOccurs}" name="${this.#data.id}" description="${btoa(this.#data.description)}" title="${this.#data.title}"></d4s-ccp-input-simple>`
this.querySelector("d4s-ccp-input-simple").default = this.#data.schema.default
}else{
this.innerHTML += `<d4s-ccp-input-simple readonly="${this.#data.schema.readOnly}" default="${this.#data.schema.default||''}" maxOccurs="${this.#data.maxOccurs||1}" minOccurs="${this.#data.minOccurs||1}" name="${this.#data.id}" description="${btoa(this.#data.description)}" title="${this.#data.title}"></d4s-ccp-input-simple>`
} }
} }
set value(value){ set value(value) {
this.firstElementChild.value = value this.firstElementChild.value = value
} }
get value(){ get value() {
return this.firstElementChild.value.length === 1 ? return this.firstElementChild.value.length === 1 ?
this.firstElementChild.value[0] : this.firstElementChild.value[0] :
this.firstElementChild.value this.firstElementChild.value
} }
get name(){ get name() {
return this.firstElementChild.name return this.firstElementChild.name
} }
isChecklist(){ isChecklist() {
return this.isEnum() && (this.#data.schema.format === "checklist") return this.isEnum() && (this.#data.schema.format === "checklist")
} }
isNumber(){ isNumber() {
return (this.#data.schema.type === "string") && return (this.#data.schema.type === "string") &&
("format" in this.#data.schema) && ("format" in this.#data.schema) &&
(this.#data.schema.format != null) && (this.#data.schema.format != null) &&
(this.#data.schema.format.toLowerCase() === "number") (this.#data.schema.format.toLowerCase() === "number")
} }
isBoolean(){ isBoolean() {
return (this.#data.schema.type === "string") && return (this.#data.schema.type === "string") &&
("format" in this.#data.schema) && ("format" in this.#data.schema) &&
(this.#data.schema.format != null) && (this.#data.schema.format != null) &&
(this.#data.schema.format.toLowerCase() === "boolean") (this.#data.schema.format.toLowerCase() === "boolean")
} }
isEnum(){ isEnum() {
return (this.#data.schema.type === "string") && ("enum" in this.#data.schema) return (this.#data.schema.type === "string") && ("enum" in this.#data.schema)
} }
isSecret(){ isSecret() {
return (this.#data.schema.type === "string") && return (this.#data.schema.type === "string") &&
("format" in this.#data.schema) && ("format" in this.#data.schema) &&
(this.#data.schema.format != null) && (this.#data.schema.format != null) &&
(this.#data.schema.format.toLowerCase() === "secret") (this.#data.schema.format.toLowerCase() === "secret")
} }
isCode(){ isCode() {
return (this.#data.schema.type === "string") && return (this.#data.schema.type === "string") &&
("format" in this.#data.schema) && ("format" in this.#data.schema) &&
(this.#data.schema.format != null) && (this.#data.schema.format != null) &&
(this.#data.schema.format.toLowerCase() === "code") (this.#data.schema.format.toLowerCase() === "code")
} }
isFile(){ isFile() {
return (this.#data.schema.type === "string") && return (this.#data.schema.type === "string") &&
("format" in this.#data.schema) && ("format" in this.#data.schema) &&
(this.#data.schema.format != null) && (this.#data.schema.format != null) &&
(this.#data.schema.format.toLowerCase() === "file") (this.#data.schema.format.toLowerCase() === "file")
} }
isRemoteFile(){ isRemoteFile() {
return (this.#data.schema.type === "string") && return (this.#data.schema.type === "string") &&
("format" in this.#data.schema) && ("format" in this.#data.schema) &&
(this.#data.schema.format != null) && (this.#data.schema.format != null) &&
(this.#data.schema.format.toLowerCase() === "remotefile") (this.#data.schema.format.toLowerCase() === "remotefile")
} }
isDateTime(){ isDateTime() {
return (this.#data.schema.type === "string") && return (this.#data.schema.type === "string") &&
("format" in this.#data.schema) && ("format" in this.#data.schema) &&
(this.#data.schema.format != null) && (this.#data.schema.format != null) &&
@ -119,7 +139,7 @@ class CCPInputWidgetController extends HTMLElement {
} }
window.customElements.define('d4s-ccp-input', CCPInputWidgetController); window.customElements.define('d4s-ccp-input', CCPInputWidgetController);
class CCPBaseInputWidgetController extends HTMLElement{ class CCPBaseInputWidgetController extends HTMLElement {
#rootdoc = null; #rootdoc = null;
#minOccurs = 1; #minOccurs = 1;
#maxOccurs = 1; #maxOccurs = 1;
@ -136,15 +156,16 @@ class CCPBaseInputWidgetController extends HTMLElement{
#count = 1 #count = 1
constructor(){ constructor() {
super() super()
this.#rootdoc = this//this.attachShadow({ mode: "open" }); this.#rootdoc = this//this.attachShadow({ mode: "open" });
this.#name = this.getAttribute("name") this.#name = this.getAttribute("name")
this.#title = this.getAttribute("title") this.#title = this.getAttribute("title")
this.#description = this.getAttribute("description") this.#description = this.getAttribute("description")
this.#default = this.getAttribute("default") //this.#default = this.getAttribute("default")
this.#minOccurs = Number(this.getAttribute("minoccurs") ? this.getAttribute("minoccurs") : 1) this.#minOccurs = Number(this.getAttribute("minoccurs") ? this.getAttribute("minoccurs") : 1)
this.#maxOccurs = Number(this.getAttribute("maxoccurs") ? this.getAttribute("maxoccurs") : 1) this.#maxOccurs = Number(this.getAttribute("maxoccurs") ? this.getAttribute("maxoccurs") : 1)
this.#maxOccurs = Math.max(this.#minOccurs, this.#maxOccurs)
this.#readonly = this.getAttribute("readonly") === "true" this.#readonly = this.getAttribute("readonly") === "true"
// coalesce all basic input types // coalesce all basic input types
@ -153,91 +174,102 @@ class CCPBaseInputWidgetController extends HTMLElement{
// Handle enum case // Handle enum case
this.#options = (this.getAttribute("options") ? this.getAttribute("options").split(",") : null) this.#options = (this.getAttribute("options") ? this.getAttribute("options").split(",") : null)
this.value = Array(Math.max(this.#minOccurs,1)).fill(this.#default) //this.value = Array(Math.max(this.#minOccurs, 1)).fill(this.#default)
} }
setValue(v){ set default(def){
this.#default = def
const defarr = Array.isArray(def) ? def : [def]
const min = Math.max(this.#minOccurs, 1)
var v = []
for(let j=0; j < this.#maxOccurs; j++){
if(j < defarr.length){
v.push(defarr[j])
}else if(j < min){
v.push(defarr[defarr.length - 1])
}
}
this.value = v
}
setValue(v) {
this.#value = v this.#value = v
this.render() this.render()
} }
set value(v){ set value(v) {
const actual = Array.isArray(v) ? v : [v] const actual = Array.isArray(v) ? v : [v]
if(actual.length < this.#minOccurs || actual.length > this.#maxOccurs){ if (actual.length < this.#minOccurs || actual.length > this.#maxOccurs) {
throw `Value with length ${v.length} does not respect bounds [${this.minOccurs},${this.maxOccurs}]` throw `Value with length ${v.length} does not respect bounds [${this.minOccurs},${this.maxOccurs}]`
} }
this.#value = actual this.#value = actual
this.render() this.render()
} }
get value(){ get value() {
return this.#value return this.#value
} }
get rootdoc(){ get rootdoc() {
return this.#rootdoc return this.#rootdoc
} }
get required(){ get required() {
return this.#minOccurs > 0 return this.#minOccurs > 0
} }
get readonly(){ get readonly() {
return this.#readonly return this.#readonly
} }
isIncrementable(){ isIncrementable() {
return this.#value.length < this.#maxOccurs return this.#value.length < this.#maxOccurs
} }
isDecrementable(){ isDecrementable() {
return this.#value.length > this.#minOccurs && this.#value.length > 1 return this.#value.length > this.#minOccurs && this.#value.length > 1
} }
get count(){ get count() {
return this.#count return this.#count
} }
get name(){ get name() {
return this.#name return this.#name
} }
get title(){ get title() {
return this.#title return this.#title
} }
get description(){ get description() {
return this.#description return this.#description
} }
get default(){ get default() {
return this.#default return this.#default
} }
get options(){ get options() {
return this.#options return this.#options
} }
set default(v){ get type() {
this.#default = v
}
get type(){
return this.#type return this.#type
} }
renderPlusMinus(){ renderPlusMinus() {
this.rootdoc.querySelector("div[name=plusminus]").innerHTML = ` this.rootdoc.querySelector("div[name=plusminus]").innerHTML = `
${this.isIncrementable() ? `<span name="plus" title="add one" class="badge text-success border-success btn">+</span>` : ``} ${this.isIncrementable() ? `<span name="plus" title="add one" class="badge text-success border-success btn">+</span>` : ``}
${this.isDecrementable() ? `<span name="minus" title="remove one" class="badge border border-danger text-danger btn">-</span>` : ``} ${this.isDecrementable() ? `<span name="minus" title="remove one" class="badge border border-danger text-danger btn">-</span>` : ``}
` `
} }
renderContent(){ renderContent() {
this.rootdoc.querySelector("div[name=content]").innerHTML = this.content() this.rootdoc.querySelector("div[name=content]").innerHTML = this.content()
} }
render(){ render() {
this.rootdoc.innerHTML = ` this.rootdoc.innerHTML = `
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0/dist/css/bootstrap.min.css" rel="stylesheet"> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0/dist/css/bootstrap.min.css" rel="stylesheet">
<div name="root" class="my-3 ccp-input-widget form-field row"> <div name="root" class="my-3 ccp-input-widget form-field row">
@ -264,42 +296,44 @@ class CCPBaseInputWidgetController extends HTMLElement{
this.renderPlusMinus() this.renderPlusMinus()
this.renderContent() this.renderContent()
this.#rootdoc.querySelector("div[name=root]").addEventListener("click", ev=>{ this.#rootdoc.querySelector("div[name=root]").addEventListener("click", ev => {
const src = ev.target.getAttribute("name") const src = ev.target.getAttribute("name")
if(src === "plus"){ if (src === "plus") {
this.#value.push(this.#default) this.#value.push(this.#value[this.#value.length - 1])
this.renderPlusMinus() this.renderPlusMinus()
this.renderContent() this.renderContent()
}else if(src === "minus"){ ev.preventDefault()
} else if (src === "minus") {
this.#value.pop() this.#value.pop()
this.renderPlusMinus() this.renderPlusMinus()
this.renderContent() this.renderContent()
ev.preventDefault()
} }
}) })
} }
} }
class CCPSimpleInputWidgetController extends CCPBaseInputWidgetController{ class CCPSimpleInputWidgetController extends CCPBaseInputWidgetController {
constructor(){ constructor() {
super() super()
} }
connectedCallback(){ connectedCallback() {
this.rootdoc.addEventListener("input", ev=>{ this.rootdoc.addEventListener("input", ev => {
if(ev.target.getAttribute("name") === this.name){ if (ev.target.getAttribute("name") === this.name) {
const index = Number(ev.target.getAttribute("data-index")) const index = Number(ev.target.getAttribute("data-index"))
this.value[index] = ev.target.value this.value[index] = ev.target.value
} }
}) })
} }
content(){ content() {
if(this.value.length <= 1){ if (this.value.length <= 1) {
return `<input data-index="0" value="${this.value.length ? this.value[0] : ''}" class="my-2 form-control" placeholder="${this.title}" type="${this.type}" name="${this.name}" ${this.readonly ? 'readonly' : ''} ${this.required ? 'required' : ''}/>` return `<input data-index="0" value="${this.value.length ? this.value[0] : ''}" class="my-2 form-control" placeholder="${this.title}" type="${this.type}" name="${this.name}" ${this.readonly ? 'readonly' : ''} ${this.required ? 'required' : ''}/>`
} }
var out = var out =
this.value.map((c,i)=>{ this.value.map((c, i) => {
return ` return `
<input name="${this.name}" value="${c}" data-index="${i}" class="ccp-input my-2 form-control" placeholder="${this.title}" type="${this.type}" name="${this.name}" ${this.readonly ? 'readonly' : ''} ${this.required ? 'required' : ''}/> <input name="${this.name}" value="${c}" data-index="${i}" class="ccp-input my-2 form-control" placeholder="${this.title}" type="${this.type}" name="${this.name}" ${this.readonly ? 'readonly' : ''} ${this.required ? 'required' : ''}/>
` `
@ -309,31 +343,35 @@ class CCPSimpleInputWidgetController extends CCPBaseInputWidgetController{
} }
window.customElements.define('d4s-ccp-input-simple', CCPSimpleInputWidgetController); window.customElements.define('d4s-ccp-input-simple', CCPSimpleInputWidgetController);
class CCPEnumInputWidgetController extends CCPBaseInputWidgetController{ class CCPEnumInputWidgetController extends CCPBaseInputWidgetController {
constructor(){ constructor() {
super() super()
} }
connectedCallback(){ connectedCallback() {
this.rootdoc.addEventListener("change", ev=>{ this.rootdoc.addEventListener("change", ev => {
if(ev.target.getAttribute("name") === this.name){ if (ev.target.getAttribute("name") === this.name) {
const index = Number(ev.target.getAttribute("data-index")) const index = Number(ev.target.getAttribute("data-index"))
this.value[index] = ev.target.value this.value[index] = ev.target.value
} }
}) })
} }
content(){ content() {
if(this.value.length <= 1){ if (this.value.length <= 1) {
const opts = this.options.map(o=>`<option value="${o}" ${ this.value.length && o === this.value[0] ? 'selected' : ''}>${o}</option>`).join("\n") const opts = this.options ?
this.options.map(o => `<option value="${o}" ${this.value.length && o === this.value[0] ? 'selected' : ''}>${o}</option>`).join("\n") :
''
return `<select data-index="0" value="${this.value.length ? this.value[0] : ''}" class="my-2 form-control" placeholder="${this.title}" name="${this.name}" ${this.readonly ? 'disabled' : ''} ${this.required ? 'required' : ''}>${opts}</select>` return `<select data-index="0" value="${this.value.length ? this.value[0] : ''}" class="my-2 form-control" placeholder="${this.title}" name="${this.name}" ${this.readonly ? 'disabled' : ''} ${this.required ? 'required' : ''}>${opts}</select>`
} }
var out = var out =
this.value.map((c,i)=>{ this.value.map((v, i) => {
const opts = this.options.map(o=>`<option value="${o}" ${ this.value.length >= i && c === this.value[i] ? 'selected' : ''}>${o}</option>`).join("\n") const opts = this.options ?
this.options.map(o => `<option value="${o}" ${o === v ? 'selected' : ''}>${o}</option>`).join("\n") :
''
return ` return `
<select data-index="${i}" value="${this.value.length ? this.value[0] : ''}" class="my-2 form-control" placeholder="${this.title}" name="${this.name}" ${this.readonly ? 'disabled' : ''} ${this.required ? 'required' : ''}>${opts}</select> <select data-index="${i}" value="${v}" class="my-2 form-control" placeholder="${this.title}" name="${this.name}" ${this.readonly ? 'disabled' : ''} ${this.required ? 'required' : ''}>${opts}</select>
` `
}).join("\n") }).join("\n")
return out return out
@ -341,34 +379,39 @@ class CCPEnumInputWidgetController extends CCPBaseInputWidgetController{
} }
window.customElements.define('d4s-ccp-input-enum', CCPEnumInputWidgetController); window.customElements.define('d4s-ccp-input-enum', CCPEnumInputWidgetController);
class CCPChecklistInputWidgetController extends CCPBaseInputWidgetController{ class CCPChecklistInputWidgetController extends CCPBaseInputWidgetController {
constructor(){ constructor() {
super() super()
} }
connectedCallback(){ connectedCallback() {
this.rootdoc.addEventListener("change", ev=>{ this.rootdoc.addEventListener("change", ev => {
if(ev.target.getAttribute("name") === this.name){ if (ev.target.getAttribute("name") === this.name) {
const index = Number(ev.target.getAttribute("data-index")) const index = Number(ev.target.getAttribute("data-index"))
const elems = Array.prototype.slice.call(ev.currentTarget.querySelectorAll(`input[name='${this.name}'][data-index='${index}']`)) const elems = Array.prototype.slice.call(ev.currentTarget.querySelectorAll(`input[name='${this.name}'][data-index='${index}']`))
this.value[index] = elems.filter(e=>e.checked).map(e=>e.value).join(",") this.value[index] = elems.filter(e => e.checked).map(e => e.value).join(",")
} }
}) })
} }
buildOpts(index, selections){ buildOpts(index, selections) {
return this.options.map(o=>` return this.options ? this.options.map(o => `
<div class="form-check form-switch form-check-inline"> <div class="form-check form-switch form-check-inline">
<label>${o}</label> <label>${o}</label>
<input data-index="${index}" class="form-check-input" type="checkbox" name="${this.name}" value="${o}" ${this.readonly ? 'readonly' : ''} ${selections.indexOf(o) > -1 ? 'checked' : ''}/></div> <input data-index="${index}" class="form-check-input" type="checkbox" name="${this.name}" value="${o}" ${this.readonly ? 'readonly' : ''} ${selections.indexOf(o) > -1 ? 'checked' : ''}/></div>
`).join("\n") `).join("\n") :
`
<div class="form-check form-switch form-check-inline">
<span class="muted text-danger">No options supplied</span>
</div>
`
} }
content(){ content() {
if(this.value.length === 1){ if (this.value.length === 1) {
const opts = this.buildOpts(0, this.value.length ? this.value[0].split(",") : []) const opts = this.buildOpts(0, this.value.length ? this.value[0].split(",") : [])
return ` return `
<div class="my-2"> <div class="my-2">
@ -377,7 +420,7 @@ class CCPChecklistInputWidgetController extends CCPBaseInputWidgetController{
` `
} }
var out = var out =
this.value.map((c,i)=>{ this.value.map((c, i) => {
const opts = this.buildOpts(i, c.split(",")) const opts = this.buildOpts(i, c.split(","))
return ` return `
<div class="my-2"> <div class="my-2">
@ -390,35 +433,34 @@ class CCPChecklistInputWidgetController extends CCPBaseInputWidgetController{
} }
window.customElements.define('d4s-ccp-input-checklist', CCPChecklistInputWidgetController); window.customElements.define('d4s-ccp-input-checklist', CCPChecklistInputWidgetController);
class CCPBooleanInputWidgetController extends CCPBaseInputWidgetController{ class CCPBooleanInputWidgetController extends CCPBaseInputWidgetController {
constructor(){ constructor() {
super() super()
} }
connectedCallback(){ connectedCallback() {
this.value.forEach((v,i)=>{ this.value[i] = v === "" ? false : v}) this.rootdoc.addEventListener("input", ev => {
this.rootdoc.addEventListener("input", ev=>{ if (ev.target.getAttribute("name") === this.name) {
if(ev.target.getAttribute("name") === this.name){
const index = Number(ev.target.getAttribute("data-index")) const index = Number(ev.target.getAttribute("data-index"))
this.value[index] = ev.target.checked this.value[index] = ev.target.checked
} }
}) })
} }
content(){ content() {
if(this.value.length <= 1){ if (this.value.length <= 1) {
return ` return `
<div class="my-2 form-check form-switch form-check-inline"> <div class="my-2 form-check form-switch form-check-inline">
<input data-index="0" value="${this.value.length ? this.value[0] : false}" class="my-2 form-check-input" type="checkbox" name="${this.name}" ${this.readonly ? 'readonly' : ''} ${this.value[0] == "true" ? 'checked' : ''} value="${ this.value[0]}"/> <input data-index="0" value="${this.value.length ? this.value[0] : false}" class="my-2 form-check-input" type="checkbox" name="${this.name}" ${this.readonly ? 'readonly' : ''} ${this.value[0] === "true" || this.value[0] === true ? 'checked' : ''} value="${this.value[0]}"/>
</div> </div>
` `
} }
var out = var out =
this.value.map((c,i)=>{ this.value.map((c, i) => {
return ` return `
<div class="my-2 form-check form-switch form-check-inline"> <div class="my-2 form-check form-switch form-check-inline">
<input data-index="${i}" value="${c}" class="my-2 form-check-input" type="checkbox" name="${this.name}" ${this.readonly ? 'readonly' : ''} ${c == "true" ? 'checked' : ''} value="${this.value[i]}"/> <input data-index="${i}" value="${c}" class="my-2 form-check-input" type="checkbox" name="${this.name}" ${this.readonly ? 'readonly' : ''} ${c === "true" || c === true ? 'checked' : ''}/>
</div> </div>
` `
}).join("\n") }).join("\n")
@ -427,27 +469,27 @@ class CCPBooleanInputWidgetController extends CCPBaseInputWidgetController{
} }
window.customElements.define('d4s-ccp-input-boolean', CCPBooleanInputWidgetController); window.customElements.define('d4s-ccp-input-boolean', CCPBooleanInputWidgetController);
class CCPTextAreaWidgetController extends CCPBaseInputWidgetController{ class CCPTextAreaWidgetController extends CCPBaseInputWidgetController {
constructor(){ constructor() {
super() super()
} }
connectedCallback(){ connectedCallback() {
this.rootdoc.addEventListener("input", ev=>{ this.rootdoc.addEventListener("input", ev => {
if(ev.target.getAttribute("name") === this.name){ if (ev.target.getAttribute("name") === this.name) {
const index = Number(ev.target.getAttribute("data-index")) const index = Number(ev.target.getAttribute("data-index"))
this.value[index] = ev.target.value this.value[index] = ev.target.value
} }
}) })
} }
content(){ content() {
if(this.value.length <= 1){ if (this.value.length <= 1) {
return `<textarea data-index="0" class="my-2 form-control" placeholder="${this.title}" type="${this.type}" name="${this.name}" rows="5" ${this.readonly ? 'readonly' : ''} ${this.required ? 'required' : ''}>${this.value.length ? this.value[0] : ''}</textarea>` return `<textarea data-index="0" class="my-2 form-control" placeholder="${this.title}" type="${this.type}" name="${this.name}" rows="5" ${this.readonly ? 'readonly' : ''} ${this.required ? 'required' : ''}>${this.value.length ? this.value[0] : ''}</textarea>`
} }
var out = var out =
this.value.map((c,i)=>{ this.value.map((c, i) => {
return ` return `
<textarea name="${this.name}" data-index="${i}" class="ccp-input my-2 form-control" placeholder="${this.title}" type="${this.type}" name="${this.name}" rows="5" ${this.readonly ? 'readonly' : ''} ${this.required ? 'required' : ''}>${c}</textarea> <textarea name="${this.name}" data-index="${i}" class="ccp-input my-2 form-control" placeholder="${this.title}" type="${this.type}" name="${this.name}" rows="5" ${this.readonly ? 'readonly' : ''} ${this.required ? 'required' : ''}>${c}</textarea>
` `
@ -457,19 +499,19 @@ class CCPTextAreaWidgetController extends CCPBaseInputWidgetController{
} }
window.customElements.define('d4s-ccp-input-textarea', CCPTextAreaWidgetController); window.customElements.define('d4s-ccp-input-textarea', CCPTextAreaWidgetController);
class CCPFileInputWidgetController extends CCPBaseInputWidgetController{ class CCPFileInputWidgetController extends CCPBaseInputWidgetController {
constructor(){ constructor() {
super() super()
} }
connectedCallback(){ connectedCallback() {
this.rootdoc.addEventListener("change", ev=>{ this.rootdoc.addEventListener("change", ev => {
const tgt = ev.target const tgt = ev.target
if(tgt.getAttribute("name") === this.name){ if (tgt.getAttribute("name") === this.name) {
const index = Number(tgt.getAttribute("data-index")) const index = Number(tgt.getAttribute("data-index"))
const file = ev.target.files[0] const file = ev.target.files[0]
if(file.size > 100*1024){ if (file.size > 100 * 1024) {
alert("This input allows only small files (100K). Use references instead ") alert("This input allows only small files (100K). Use references instead ")
ev.stopPropagation() ev.stopPropagation()
ev.preventDefault() ev.preventDefault()
@ -477,32 +519,34 @@ class CCPFileInputWidgetController extends CCPBaseInputWidgetController{
return false return false
} }
const reader = new FileReader() const reader = new FileReader()
reader.addEventListener('load', ev=>{ reader.addEventListener('load', ev => {
let encoded = ev.target.result.toString().replace(/^data:(.*,)?/, ''); let encoded = ev.target.result.toString().replace(/^data:(.*,)?/, '');
if ((encoded.length % 4) > 0) { if ((encoded.length % 4) > 0) {
encoded += '='.repeat(4 - (encoded.length % 4)); encoded += '='.repeat(4 - (encoded.length % 4));
} }
this.value[index] = encoded this.value[index] = encoded
this.querySelector("small[name=preview]").textContent = encoded.substr(0,5) + "..." + encoded.substr(encoded.length-5) this.querySelector("small[name=preview]").textContent = encoded.substr(0, 5) + "..." + encoded.substr(encoded.length - 5)
}) })
reader.readAsDataURL(file) reader.readAsDataURL(file)
} }
}) })
} }
content(){ content() {
if(this.value.length <= 1){ if (this.value.length <= 1) {
const v = this.value.length ? this.value[0] : '' const v = this.value.length ? this.value[0] : ''
return ` const preview = typeof(v) === "string" ? v.substring(0, 5) + "..." + v.substring(v.length - 5) : ""
return `
<input type="file" data-index="0" class="my-2 form-control" placeholder="${this.title}" name="${this.name}" ${this.readonly ? 'readonly' : ''} ${this.required && !v ? 'required' : ''} value="${v}"/> <input type="file" data-index="0" class="my-2 form-control" placeholder="${this.title}" name="${this.name}" ${this.readonly ? 'readonly' : ''} ${this.required && !v ? 'required' : ''} value="${v}"/>
<small name ="preview" class="form-text text-muted">${v.substr(0,5) + "..." + v.substr(v.length-5)}</small> <small name ="preview" class="form-text text-muted">${preview}</small>
` `
} }
var out = var out =
this.value.map((c,i)=>{ this.value.map((c, i) => {
const preview = typeof(v) === "string" ? c.substring(0, 5) + "..." + c.substring(v.length - 5) : ""
return ` return `
<input type="file" data-index="${i}" class="my-2 form-control" placeholder="${this.title}" name="${this.name}" ${this.readonly ? 'readonly' : ''} ${this.required ? 'required' : ''} value="${c}"/> <input type="file" data-index="${i}" class="my-2 form-control" placeholder="${this.title}" name="${this.name}" ${this.readonly ? 'readonly' : ''} ${this.required ? 'required' : ''} value="${c}"/>
<small name ="preview" class="form-text text-muted">${c.substr(0,5) + "..." + c.substr(s.length-5)}</small> <small name ="preview" class="form-text text-muted">${preview}</small>
` `
}).join("\n") }).join("\n")
return out return out
@ -510,27 +554,41 @@ class CCPFileInputWidgetController extends CCPBaseInputWidgetController{
} }
window.customElements.define('d4s-ccp-input-file', CCPFileInputWidgetController); window.customElements.define('d4s-ccp-input-file', CCPFileInputWidgetController);
class CCPRemoteFileInputWidgetController extends CCPBaseInputWidgetController{ class CCPRemoteFileInputWidgetController extends CCPBaseInputWidgetController {
constructor(){ #publicorprotected_dialog = null;
#target = null
#publiclink = null;
#protectedlink = null;
#index = null;
constructor() {
super() super()
} }
connectedCallback(){ async setPublicLink(l){
this.rootdoc.addEventListener("input", ev=>{ const b = document.querySelector("d4s-boot-2")
if(ev.target.getAttribute("name") === this.name){ const link = await b.secureFetch(l)
const index = Number(ev.target.getAttribute("data-index")) if(link.ok){
this.value[index] = ev.target.value const result = await link.json()
} this.#target.value = this.value[this.#index] = result
}) this.#publicorprotected_dialog.style.display = "none"
this.#publicorprotected_dialog.classList.remove("show")
this.#publiclink = this.#protectedlink = this.#target = this.#index = null
const newev = new Event("input", { bubbles : true})
this.dispatchEvent(newev)
}else{
alert("Unable to get public link for item")
this.#target.value = this.value[this.#index] = ""
}
} }
addToolContent(){ addToolContent() {
const iss = document.querySelector("d4s-boot-2").loginToken.iss; const iss = document.querySelector("d4s-boot-2").loginToken.iss;
const addresses = { const addresses = {
"https://accounts.dev.d4science.org/auth/realms/d4science" : "https://workspace-repository.dev.d4science.org/storagehub/workspace", "https://accounts.dev.d4science.org/auth/realms/d4science": "https://workspace-repository.dev.d4science.org/storagehub/workspace",
"https://accounts.pre.d4science.org/auth/realms/d4science" : "https://pre.d4science.org/workspace", "https://accounts.pre.d4science.org/auth/realms/d4science": "https://pre.d4science.org/workspace",
"https://accounts.d4science.org/auth/realms/d4science" : "https://api.d4science.org/workspace" "https://accounts.d4science.org/auth/realms/d4science": "https://api.d4science.org/workspace"
}; };
this.rootdoc.querySelector("div[name=tools]").innerHTML += ` this.rootdoc.querySelector("div[name=tools]").innerHTML += `
<svg name="trigger" style="width:24;height:24;fill:#007bff; cursor:pointer" viewBox="0 -960 960 960"> <svg name="trigger" style="width:24;height:24;fill:#007bff; cursor:pointer" viewBox="0 -960 960 960">
@ -549,42 +607,84 @@ class CCPRemoteFileInputWidgetController extends CCPBaseInputWidgetController{
allow-drag="true"/> allow-drag="true"/>
</div> </div>
</div> </div>
<div class="modal fade" style="background-color:rgba(0,0,0,0.3)" name="publicorprotected" tabindex="-1" role="dialog">
<div class="modal-dialog" role= this.#publicorprivate =
"document">
<div class="modal-content shadow-lg border-primary">
<div class="modal-body">
Choose whether you want to use the public link or the protected link (requires authentication and authorization).
</div>
<div class="modal-footer">
<button name="public" type="button" class="btn btn-info">Public link</button>
<button name="protected" type="button" class="btn btn-primary">Protected link</button>
</div>
</div>
</div>
</div>
` `
const ws = this.rootdoc.querySelector("div[name=ws]") this.#publicorprotected_dialog = this.rootdoc.querySelector("div.modal[name=publicorprotected]")
this.rootdoc.querySelector("svg[name=trigger]").addEventListener("click", ev=>{ this.#publicorprotected_dialog.addEventListener("click", ev => {
ws.classList.toggle("d-none")
})
this.rootdoc.querySelector("span[name=closebtn]").addEventListener("click", ev=>{
ws.classList.add("d-none")
})
this.addEventListener("dragover", ev=>{
ev.preventDefault()
})
this.addEventListener("drop", ev=>{
ev.stopPropagation() ev.stopPropagation()
if(ev.target.getAttribute("name") == this.name && ev.target.getAttribute("data-index") != null){ ev.preventDefault()
const index = Number(ev.target.getAttribute("data-index")) const name = ev.target.getAttribute("name")
ev.target.value = ev.dataTransfer.getData("text/plain+downloadlink") if(this.#index != null && this.#target != null){
this.value[index] = ev.target.value if(name === "public") {
this.setPublicLink(this.#publiclink);
}
else if(name === "protected"){
this.#target.value = this.value[this.#index] = this.#protectedlink;
this.#publicorprotected_dialog.style.display = "none"
this.#publicorprotected_dialog.classList.remove("show")
this.#publiclink = this.#protectedlink = this.#target = this.#index = null
const newev = new Event("input", { bubbles : true})
this.dispatchEvent(newev)
}
else return;
} }
}) })
document.addEventListener("keydown", ev=>{ const ws = this.rootdoc.querySelector("div[name=ws]")
if(ev.code == 'Escape' ) ws.classList.add("d-none"); this.rootdoc.querySelector("svg[name=trigger]").addEventListener("click", ev => {
ws.classList.toggle("d-none")
ev.preventDefault()
ev.stopPropagation()
})
this.rootdoc.querySelector("span[name=closebtn]").addEventListener("click", ev => {
ws.classList.add("d-none")
ev.preventDefault()
ev.stopPropagation()
})
this.addEventListener("dragover", ev => {
ev.preventDefault()
})
this.addEventListener("drop", ev => {
ev.stopPropagation()
if (ev.target.getAttribute("name") == this.name && ev.target.getAttribute("data-index") != null) {
this.#publicorprotected_dialog.style.display = "block"
this.#publicorprotected_dialog.classList.add("show")
this.#target = ev.target
this.#index = Number(ev.target.getAttribute("data-index"))
this.#publiclink = ev.dataTransfer.getData("text/plain+publiclink")
this.#protectedlink = ev.dataTransfer.getData("text/plain+downloadlink")
}
})
document.addEventListener("keydown", ev => {
if (ev.code == 'Escape') ws.classList.add("d-none");
}) })
} }
content(){ content() {
this.addToolContent() if(!this.readonly && !this.querySelector("div[name=ws]")) this.addToolContent();
if(this.value.length <= 1){ if (this.value.length <= 1) {
return ` return `
<input data-index="0" value="${this.value.length ? this.value[0] : ''}" class="my-2 form-control" placeholder="${this.title}" type="${this.type}" name="${this.name}" ${this.readonly ? 'readonly' : ''} ${this.required ? 'required' : ''}/>` <input data-index="0" value="${this.value.length ? this.value[0] : ''}" class="my-2 form-control" placeholder="${this.title}" type="${this.type}" name="${this.name}" ${this.readonly ? 'readonly' : ''} ${this.required ? 'required' : ''}/>`
} }
var out = var out =
this.value.map((c,i)=>{ this.value.map((c, i) => {
return ` return `
<input name="${this.name}" value="${c}" data-index="${i}" class="ccp-input my-2 form-control" placeholder="${this.title}" type="${this.type}" name="${this.name}" ${this.readonly ? 'readonly' : ''} ${this.required ? 'required' : ''}/> <input name="${this.name}" value="${c}" data-index="${i}" class="ccp-input my-2 form-control" placeholder="${this.title}" type="${this.type}" name="${this.name}" ${this.readonly ? 'readonly' : ''} ${this.required ? 'required' : ''}/>
` `
@ -594,32 +694,32 @@ class CCPRemoteFileInputWidgetController extends CCPBaseInputWidgetController{
} }
window.customElements.define('d4s-ccp-input-remotefile', CCPRemoteFileInputWidgetController); window.customElements.define('d4s-ccp-input-remotefile', CCPRemoteFileInputWidgetController);
class CCPSecretInputWidgetController extends CCPBaseInputWidgetController{ class CCPSecretInputWidgetController extends CCPBaseInputWidgetController {
constructor(){ constructor() {
super() super()
} }
connectedCallback(){ connectedCallback() {
this.rootdoc.addEventListener("input", ev=>{ this.rootdoc.addEventListener("input", ev => {
if(ev.target.getAttribute("name") === this.name){ if (ev.target.getAttribute("name") === this.name) {
const index = Number(ev.target.getAttribute("data-index")) const index = Number(ev.target.getAttribute("data-index"))
this.value[index] = ev.target.value this.value[index] = ev.target.value
} }
}) })
this.rootdoc.addEventListener("click", ev=>{ this.rootdoc.addEventListener("click", ev => {
if(ev.target.getAttribute("name") === "password_toggle"){ if (ev.target.getAttribute("name") === "password_toggle") {
const index = Number(ev.target.getAttribute("data-index")) const index = Number(ev.target.getAttribute("data-index"))
const field = this.rootdoc.querySelector(`input[data-index='${index}']`) const field = this.rootdoc.querySelector(`input[data-index='${index}']`)
if(field.type === "text") field.type="password"; if (field.type === "text") field.type = "password";
else field.type = "text"; else field.type = "text";
} }
}) })
} }
content(){ content() {
if(this.value.length <= 1){ if (this.value.length <= 1) {
return ` return `
<div style="position:relative"> <div style="position:relative">
<input data-index="0" value="${this.value.length ? this.value[0] : ''}" class="my-2 form-control" placeholder="${this.title}" type="password" name="${this.name}" ${this.readonly ? 'readonly' : ''} ${this.required ? 'required' : ''}/> <input data-index="0" value="${this.value.length ? this.value[0] : ''}" class="my-2 form-control" placeholder="${this.title}" type="password" name="${this.name}" ${this.readonly ? 'readonly' : ''} ${this.required ? 'required' : ''}/>
@ -628,7 +728,7 @@ class CCPSecretInputWidgetController extends CCPBaseInputWidgetController{
` `
} }
var out = var out =
this.value.map((c,i)=>{ this.value.map((c, i) => {
return ` return `
<div style="position:relative"> <div style="position:relative">
<input name="${this.name}" value="${c}" data-index="${i}" class="ccp-input my-2 form-control" placeholder="${this.title}" type="password" name="${this.name}" ${this.readonly ? 'readonly' : ''} ${this.required ? 'required' : ''}/> <input name="${this.name}" value="${c}" data-index="${i}" class="ccp-input my-2 form-control" placeholder="${this.title}" type="password" name="${this.name}" ${this.readonly ? 'readonly' : ''} ${this.required ? 'required' : ''}/>

View File

@ -23,7 +23,7 @@ class CCPInputWidgetEditorController extends HTMLElement{
return this.#index return this.#index
} }
computeDefaultInputType(){ /*computeDefaultInputType(){
if(this.#input.schema.format === "secret"){ if(this.#input.schema.format === "secret"){
return "password" return "password"
}else if(this.#input.schema.format === "date"){ }else if(this.#input.schema.format === "date"){
@ -34,14 +34,15 @@ class CCPInputWidgetEditorController extends HTMLElement{
return "datetime-local" return "datetime-local"
} }
return "text" return "text"
} }*/
isSelectedFormat(fmt){ isSelectedFormat(fmt){
return this.#input.schema.format === fmt return this.#input.schema.format === fmt
} }
renderDefaultByType(){ renderDefaultByType(){
if(this.#input.schema.format === "code"){ return `<d4s-ccp-input name="default" input="${btoa(JSON.stringify(this.#input))}"></d4s-ccp-input>`
/*if(this.#input.schema.format === "code"){
return ` return `
<textarea rows="5" name="default" class="form-control" placeholder="default">${this.#input.schema.default}</textarea> <textarea rows="5" name="default" class="form-control" placeholder="default">${this.#input.schema.default}</textarea>
` `
@ -49,7 +50,7 @@ class CCPInputWidgetEditorController extends HTMLElement{
return ` return `
<input type="${this.computeDefaultInputType()}" value="${this.#input.schema.default}" name="default" class="form-control" placeholder="default"/> <input type="${this.computeDefaultInputType()}" value="${this.#input.schema.default}" name="default" class="form-control" placeholder="default"/>
` `
} }*/
} }
renderDeleteButton(){ renderDeleteButton(){
@ -62,6 +63,8 @@ class CCPInputWidgetEditorController extends HTMLElement{
this.#index = i this.#index = i
this.#input = input this.#input = input
this.#type = input.schema.enum ? "enum" : "string" this.#type = input.schema.enum ? "enum" : "string"
const minOccurs = input.minOccurs = Number(input.minOccurs) ? Number(input.minOccurs) : 0
const maxOccurs = input.maxOccurs = Number(input.maxOccurs) ? Number(input.maxOccurs) : 0
this.innerHTML = ` this.innerHTML = `
<details ${ reopen ? 'open' : ''}> <details ${ reopen ? 'open' : ''}>
<summary class="mb-3"> <summary class="mb-3">
@ -85,22 +88,22 @@ class CCPInputWidgetEditorController extends HTMLElement{
<div class="col-3"> <div class="col-3">
<div class="form-field" title="Type"> <div class="form-field" title="Type">
<label>Type</label> <label>Type</label>
<select name="type" class="form-control" placeholder="type" value="${this.#type}" ${ input.id === 'ccpimage' ? 'readonly' : ''}> <select name="type" class="form-control" placeholder="type" value="${this.#type}">
<option value="string" ${this.#type === "string" ? "selected" : ""}>String</option> <option value="string" ${this.#type === "string" ? "selected" : ""}>String</option>
<option value="enum" ${this.#type === "enum" ? "selected" : ""}>Enum</option> ${ input.id === 'ccpimage' ? '' : `<option value="enum" ${this.#type === "enum" ? "selected" : ""}>Enum</option>` }
</select> </select>
</div> </div>
</div> </div>
<div class="col"> <div class="col">
<div class="form-field" title="Minimum occurrences"> <div class="form-field" title="Minimum occurrences">
<label>Min occurs</label> <label>Min occurs</label>
<input value="${input.minOccurs}" type="number" min="0" step="1" name="minOccurs" value="${input.minOccurs}" required="required" class="form-control" placeholder="minOccurs" ${ input.id === 'ccpimage' ? 'readonly' : ''}/> <input value="${minOccurs}" type="number" min="0" step="1" name="minOccurs" value="${minOccurs}" required="required" class="form-control" placeholder="minOccurs" ${ input.id === 'ccpimage' ? 'readonly' : ''}/>
</div> </div>
</div> </div>
<div class="col"> <div class="col">
<div class="form-field" title="Maximum occurrences"> <div class="form-field" title="Maximum occurrences">
<label>Max occurs</label> <label>Max occurs</label>
<input value="${input.maxOccurs}" type="number" min="0" step="1" name="maxOccurs" value="${input.maxOccurs}" required="required" class="form-control" placeholder="maxOccurs" ${ input.id === 'ccpimage' ? 'readonly' : ''}/> <input value="${maxOccurs}" type="number" min="0" step="1" name="maxOccurs" value="${maxOccurs}" required="required" class="form-control" placeholder="maxOccurs" ${ input.id === 'ccpimage' ? 'readonly' : ''}/>
</div> </div>
</div> </div>
<div class="col" title="Read only"> <div class="col" title="Read only">
@ -123,7 +126,7 @@ class CCPInputWidgetEditorController extends HTMLElement{
<option value="boolean" ${this.isSelectedFormat('boolean') ? "selected" : ""}>True/False</option> <option value="boolean" ${this.isSelectedFormat('boolean') ? "selected" : ""}>True/False</option>
<option value="code" ${this.isSelectedFormat('code') ? "selected" : ""}>Code</option> <option value="code" ${this.isSelectedFormat('code') ? "selected" : ""}>Code</option>
<option value="file" ${this.isSelectedFormat('file') ? "selected" : ""}>File</option> <option value="file" ${this.isSelectedFormat('file') ? "selected" : ""}>File</option>
<option value="remotefile" ${this.isSelectedFormat('remotefile') ? "selected" : ""}>Remote file</option> <option value="remotefile" ${this.isSelectedFormat('remotefile') ? "selected" : ""}>Workspace file</option>
<option value="secret" ${this.isSelectedFormat('secret') ? "selected" : ""}>Secret</option> <option value="secret" ${this.isSelectedFormat('secret') ? "selected" : ""}>Secret</option>
<option value="url" ${this.isSelectedFormat('url') ? "selected" : ""}>Url</option> <option value="url" ${this.isSelectedFormat('url') ? "selected" : ""}>Url</option>
</select> </select>
@ -150,8 +153,9 @@ class CCPInputWidgetEditorController extends HTMLElement{
</div> </div>
</div> </div>
<div name="input-default" class="mb-3"> <div name="input-default" class="mb-3">
<div class="form-field" title="Default value"> <label>Default value</label>
${this.renderDefaultByType()} <div class="form-field border border-info px-2 py-1" style="background-color:#0dcaf022" title="Default value">
<div name="default-container">${this.renderDefaultByType()}</div>
<span style="user-select:none;position:relative;top:-1.6rem;float:right;cursor:pointer" name="password_toggle" class="${this.isSelectedFormat('secret') ? 'inline' : 'd-none'}">&#128065;</span> <span style="user-select:none;position:relative;top:-1.6rem;float:right;cursor:pointer" name="password_toggle" class="${this.isSelectedFormat('secret') ? 'inline' : 'd-none'}">&#128065;</span>
</div> </div>
</div> </div>
@ -167,53 +171,63 @@ class CCPInputWidgetEditorController extends HTMLElement{
} }
}) })
const defaultinp = this.querySelector("div[name='input-default']")
defaultinp.addEventListener("input", ev=>{
const inp = this.querySelector("d4s-ccp-input")
this.#input.schema.default = inp.value
})
defaultinp.addEventListener("change", ev=>{
const inp = this.querySelector("d4s-ccp-input")
this.#input.schema.default = inp.value
})
defaultinp.addEventListener("click", ev=>{
const src = ev.target.getAttribute("name")
if (src === "plus" || src === "minus") {
const inp = this.querySelector("d4s-ccp-input")
this.#input.schema.default = inp.value
}
})
this.addEventListener("input", ev=>{ this.addEventListener("input", ev=>{
const val = ev.target.value const val = ev.target.value
const ename = ev.target.getAttribute("name") const ename = ev.target.getAttribute("name")
const display = this.querySelector("div[name='default-container']")
if(ename === "id"){ if(ename === "id"){
this.#input.id = val this.#input.id = val
} }
else if(ename === "title"){ else if(ename === "title"){
this.#input.title = val this.#input.title = val
display.innerHTML = this.renderDefaultByType()
} }
else if(ename === "description"){ else if(ename === "description"){
this.#input.description = val this.#input.description = val
display.innerHTML = this.renderDefaultByType()
} }
else if(ename === "minOccurs"){ else if(ename === "minOccurs"){
this.#input.minOccurs = val this.#input.minOccurs = Number(val) ? Number(val) : 0
display.innerHTML = this.renderDefaultByType()
} }
else if(ename === "maxOccurs"){ else if(ename === "maxOccurs"){
this.#input.maxOccurs = val this.#input.maxOccurs = Number(val) ? Number(val) : 0
display.innerHTML = this.renderDefaultByType()
} }
else if(ename === "format"){ else if(ename === "format"){
this.#input.schema.format = val this.#input.schema.format = val
//this.render(this.#input, this.#index, true) display.innerHTML = this.renderDefaultByType()
/*this.querySelector("div[name=input-default] span[name=password_toggle]").classList.add("d-none")
this.querySelector("div[name=input-default] input[name=default]").type = ""
if(this.#input.schema.format === "secret"){
this.querySelector("div[name=input-default] input[name=default]").type = "password"
this.querySelector("div[name=input-default] span[name=password_toggle]").classList.remove("d-none")
}else if(this.#input.schema.format === "date"){
this.querySelector("div[name=input-default] input[name=default]").type = "date"
}else if(this.#input.schema.format === "time"){
this.querySelector("div[name=input-default] input[name=default]").type = "time"
}else if(this.#input.schema.format === "dateTime"){
this.querySelector("div[name=input-default] input[name=default]").type = "dateTime"
}else if(this.#input.schema.format === "file"){
this.querySelector("div[name=input-default] input[name=default]").type = "file"
}*/
} }
else if(ename === "contentMediaType"){ else if(ename === "contentMediaType"){
this.#input.schema.contentMediaType = val this.#input.schema.contentMediaType = val
display.innerHTML = this.renderDefaultByType()
} }
else if(ename === "options"){ else if(ename === "options"){
this.#input.schema.enum = val.split(",") this.#input.schema.enum = val.split(",")
} display.innerHTML = this.renderDefaultByType()
else if(ename === "default"){
this.#input.schema.default = val
} }
else if(ename === "readonly"){ else if(ename === "readonly"){
this.#input.schema.readOnly = ev.target.checked this.#input.schema.readOnly = ev.target.checked
display.innerHTML = this.renderDefaultByType()
} }
else if(ename === "type"){ else if(ename === "type"){
this.#type = ev.target.value this.#type = ev.target.value
@ -226,9 +240,9 @@ class CCPInputWidgetEditorController extends HTMLElement{
this.querySelector("div[name=string-input]").classList.remove("d-none") this.querySelector("div[name=string-input]").classList.remove("d-none")
delete this.#input.schema['enum'] delete this.#input.schema['enum']
} }
display.innerHTML = this.renderDefaultByType()
} }
}) })
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -220,9 +220,9 @@ class CCPMethodList extends HTMLElement{
const f = filter.toLowerCase() const f = filter.toLowerCase()
this.#filtered = this.#data.filter(d=>{ this.#filtered = this.#data.filter(d=>{
return false || return false ||
(d.title.toLowerCase().indexOf(f) !== -1)|| (d.title && d.title.toLowerCase().indexOf(f) !== -1)||
(d.description.indexOf(f) !== -1) || (d.description && d.description.indexOf(f) !== -1) ||
(d.keywords.map(k=>k.toLowerCase()).filter(i=>i.indexOf(f) !== -1)).length (Array.isArray(d.keywords) && d.keywords.map(k=>k.toLowerCase()).filter(i=>i.indexOf(f) !== -1)).length
}) })
} }
this.groupBy() this.groupBy()

View File

@ -12,10 +12,13 @@
<h3>CDN sandbox</h3> <h3>CDN sandbox</h3>
<p>Select the section you want to enter</p> <p>Select the section you want to enter</p>
</header> </header>
<div class="d-flex"> <div class="d-flex flex-column">
<div class="d-inline-block"> <div class="d-inline-block">
<a href="storage/index.html">D4S Workspace</a> (OIDC protected) <a href="storage/index.html">D4S Workspace</a> (OIDC protected)
</div> </div>
<div class="d-inline-block">
<a href="ccp/index.html">CCP</a> (OIDC protected)
</div>
</div> </div>
</body> </body>

View File

@ -442,6 +442,7 @@ class D4SStorageTree extends D4SStorageHtmlElement {
li.addEventListener('click', (ev) => { li.addEventListener('click', (ev) => {
ev.stopPropagation(); ev.stopPropagation();
ev.preventDefault()
this.select(ev.currentTarget.getAttribute(D4SStorageTree.dataid_attr)); this.select(ev.currentTarget.getAttribute(D4SStorageTree.dataid_attr));
}); });
@ -668,6 +669,7 @@ class D4SStorageFolder extends D4SStorageHtmlElement {
const isFolder = item['@class'].includes('FolderItem') const isFolder = item['@class'].includes('FolderItem')
filename.addEventListener('click', (ev) => { filename.addEventListener('click', (ev) => {
ev.stopPropagation() ev.stopPropagation()
ev.preventDefault()
if (isFolder) { if (isFolder) {
const span = ev.currentTarget.querySelector(':nth-child(2)') const span = ev.currentTarget.querySelector(':nth-child(2)')
if (span) { if (span) {

View File

@ -10,7 +10,7 @@
<body class="m-4"> <body class="m-4">
<d4s-boot-2 context="%2Fgcube%2Fdevsec%2FdevVRE" <d4s-boot-2 context="%2Fgcube%2Fdevsec%2FdevVRE"
gateway="next.d4science.org" gateway="next.dev.d4science.org"
redirect-url="https://cdn.dev.d4science.org/storage/" redirect-url="https://cdn.dev.d4science.org/storage/"
url="https://accounts.dev.d4science.org/auth"> url="https://accounts.dev.d4science.org/auth">
<!-- redirect-url="http://localhost:8080/storage/" --> <!-- redirect-url="http://localhost:8080/storage/" -->