class CCPInputWidgetController extends HTMLElement { #data = null; constructor(){ super() } connectedCallback(){ this.#data = JSON.parse(this.getAttribute("input")) if(this.isChecklist()){ const opts = this.#data.schema.enum.join(",") this.innerHTML += `` } else if(this.isEnum()){ const opts = this.#data.schema.enum.join(",") this.innerHTML += `` }else if(this.isCode()){ this.innerHTML += `` }else if(this.isDateTime()){ const t = this.#data.schema.format.toLowerCase() === "datetime" ? "datetime-local" : this.#data.schema.format.toLowerCase() this.innerHTML += `` }else if(this.isFile()){ this.innerHTML += `` }else if(this.isRemoteFile()){ this.innerHTML += `` }else if(this.isSecret()){ this.innerHTML += `` }else if(this.isBoolean()){ this.innerHTML += `` }else if(this.isNumber()){ this.innerHTML += `` }else{ this.innerHTML += `` } } set value(value){ this.firstElementChild.value = value } get value(){ return this.firstElementChild.value.length === 1 ? this.firstElementChild.value[0] : this.firstElementChild.value } get name(){ return this.firstElementChild.name } isChecklist(){ return this.isEnum() && (this.#data.schema.format === "checklist") } isNumber(){ return (this.#data.schema.type === "string") && ("format" in this.#data.schema) && (this.#data.schema.format != null) && (this.#data.schema.format.toLowerCase() === "number") } isBoolean(){ return (this.#data.schema.type === "string") && ("format" in this.#data.schema) && (this.#data.schema.format != null) && (this.#data.schema.format.toLowerCase() === "boolean") } isEnum(){ return (this.#data.schema.type === "string") && ("enum" in this.#data.schema) } isSecret(){ return (this.#data.schema.type === "string") && ("format" in this.#data.schema) && (this.#data.schema.format != null) && (this.#data.schema.format.toLowerCase() === "secret") } isCode(){ return (this.#data.schema.type === "string") && ("format" in this.#data.schema) && (this.#data.schema.format != null) && (this.#data.schema.format.toLowerCase() === "code") } isFile(){ return (this.#data.schema.type === "string") && ("format" in this.#data.schema) && (this.#data.schema.format != null) && (this.#data.schema.format.toLowerCase() === "file") } isRemoteFile(){ return (this.#data.schema.type === "string") && ("format" in this.#data.schema) && (this.#data.schema.format != null) && (this.#data.schema.format.toLowerCase() === "remotefile") } isDateTime(){ return (this.#data.schema.type === "string") && ("format" in this.#data.schema) && (this.#data.schema.format != null) && (["date", "time", "datetime"].indexOf(this.#data.schema.format.toLowerCase()) !== -1) } } window.customElements.define('d4s-ccp-input', CCPInputWidgetController); class CCPBaseInputWidgetController extends HTMLElement{ #rootdoc = null; #minOccurs = 1; #maxOccurs = 1; #description = "" #title = "" #name = "" #default = null #options = null #value = null #readonly = false //useful to avoid having a custom element for every basic input type #type = null #count = 1 constructor(){ super() this.#rootdoc = this//this.attachShadow({ mode: "open" }); this.#name = this.getAttribute("name") this.#title = this.getAttribute("title") this.#description = this.getAttribute("description") this.#default = this.getAttribute("default") this.#minOccurs = Number(this.getAttribute("minoccurs") ? this.getAttribute("minoccurs") : 1) this.#maxOccurs = Number(this.getAttribute("maxoccurs") ? this.getAttribute("maxoccurs") : 1) this.#readonly = this.getAttribute("readonly") === "true" // coalesce all basic input types this.#type = this.getAttribute("type") // Handle enum case this.#options = (this.getAttribute("options") ? this.getAttribute("options").split(",") : null) this.value = Array(Math.max(this.#minOccurs,1)).fill(this.#default) } setValue(v){ this.#value = v this.render() } set value(v){ const actual = Array.isArray(v) ? v : [v] if(actual.length < this.#minOccurs || actual.length > this.#maxOccurs){ throw `Value with length ${v.length} does not respect bounds [${this.minOccurs},${this.maxOccurs}]` } this.#value = actual this.render() } get value(){ return this.#value } get rootdoc(){ return this.#rootdoc } get required(){ return this.#minOccurs > 0 } get readonly(){ return this.#readonly } isIncrementable(){ return this.#value.length < this.#maxOccurs } isDecrementable(){ return this.#value.length > this.#minOccurs && this.#value.length > 1 } get count(){ return this.#count } get name(){ return this.#name } get title(){ return this.#title } get description(){ return this.#description } get default(){ return this.#default } get options(){ return this.#options } set default(v){ this.#default = v } get type(){ return this.#type } renderPlusMinus(){ this.rootdoc.querySelector("div[name=plusminus]").innerHTML = ` ${this.isIncrementable() ? `+` : ``} ${this.isDecrementable() ? `-` : ``} ` } renderContent(){ this.rootdoc.querySelector("div[name=content]").innerHTML = this.content() } render(){ this.rootdoc.innerHTML = `
` this.renderPlusMinus() this.renderContent() this.#rootdoc.querySelector("div[name=root]").addEventListener("click", ev=>{ const src = ev.target.getAttribute("name") if(src === "plus"){ this.#value.push(this.#default) this.renderPlusMinus() this.renderContent() }else if(src === "minus"){ this.#value.pop() this.renderPlusMinus() this.renderContent() } }) } } class CCPSimpleInputWidgetController extends CCPBaseInputWidgetController{ constructor(){ super() } connectedCallback(){ this.rootdoc.addEventListener("input", ev=>{ if(ev.target.getAttribute("name") === this.name){ const index = Number(ev.target.getAttribute("data-index")) this.value[index] = ev.target.value } }) } content(){ if(this.value.length <= 1){ return `` } var out = this.value.map((c,i)=>{ return ` ` }).join("\n") return out } } window.customElements.define('d4s-ccp-input-simple', CCPSimpleInputWidgetController); class CCPEnumInputWidgetController extends CCPBaseInputWidgetController{ constructor(){ super() } connectedCallback(){ this.rootdoc.addEventListener("change", ev=>{ if(ev.target.getAttribute("name") === this.name){ const index = Number(ev.target.getAttribute("data-index")) this.value[index] = ev.target.value } }) } content(){ const opts = this.options.map(o=>``).join("\n") if(this.value.length <= 1){ return `` } var out = this.value.map((c,i)=>{ return ` ` }).join("\n") return out } } window.customElements.define('d4s-ccp-input-enum', CCPEnumInputWidgetController); class CCPChecklistInputWidgetController extends CCPBaseInputWidgetController{ constructor(){ super() } connectedCallback(){ this.rootdoc.addEventListener("change", ev=>{ if(ev.target.getAttribute("name") === this.name){ const index = Number(ev.target.getAttribute("data-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(",") } }) } buildOpts(index, selections){ return this.options.map(o=>`
-1 ? 'checked' : ''}/>
`).join("\n") } content(){ if(this.value.length === 1){ const opts = this.buildOpts(0, this.value.length ? this.value[0].split(",") : []) return `
${opts}
` } var out = this.value.map((c,i)=>{ const opts = this.buildOpts(i, c.split(",")) return `
${opts}
` }).join("\n") return out } } window.customElements.define('d4s-ccp-input-checklist', CCPChecklistInputWidgetController); class CCPBooleanInputWidgetController extends CCPBaseInputWidgetController{ constructor(){ super() } connectedCallback(){ this.value.forEach((v,i)=>{ this.value[i] = v === "" ? false : v}) this.rootdoc.addEventListener("input", ev=>{ if(ev.target.getAttribute("name") === this.name){ const index = Number(ev.target.getAttribute("data-index")) this.value[index] = ev.target.checked } }) } content(){ if(this.value.length <= 1){ return `
` } var out = this.value.map((c,i)=>{ return `
` }).join("\n") return out } } window.customElements.define('d4s-ccp-input-boolean', CCPBooleanInputWidgetController); class CCPTextAreaWidgetController extends CCPBaseInputWidgetController{ constructor(){ super() } connectedCallback(){ this.rootdoc.addEventListener("input", ev=>{ if(ev.target.getAttribute("name") === this.name){ const index = Number(ev.target.getAttribute("data-index")) this.value[index] = ev.target.value } }) } content(){ if(this.value.length <= 1){ return `` } var out = this.value.map((c,i)=>{ return ` ` }).join("\n") return out } } window.customElements.define('d4s-ccp-input-textarea', CCPTextAreaWidgetController); class CCPFileInputWidgetController extends CCPBaseInputWidgetController{ constructor(){ super() } connectedCallback(){ this.rootdoc.addEventListener("change", ev=>{ const tgt = ev.target if(tgt.getAttribute("name") === this.name){ const index = Number(tgt.getAttribute("data-index")) const file = ev.target.files[0] if(file.size > 100*1024){ alert("This input allows only small files (100K). Use references instead ") ev.stopPropagation() ev.preventDefault() tgt.value = null return false } const reader = new FileReader() reader.addEventListener('load', ev=>{ let encoded = ev.target.result.toString().replace(/^data:(.*,)?/, ''); if ((encoded.length % 4) > 0) { encoded += '='.repeat(4 - (encoded.length % 4)); } this.value[index] = encoded this.querySelector("small[name=preview]").textContent = encoded.substr(0,5) + "..." + encoded.substr(encoded.length-5) }) reader.readAsDataURL(file) } }) } content(){ if(this.value.length <= 1){ const v = this.value.length ? this.value[0] : '' return ` ${v.substr(0,5) + "..." + v.substr(v.length-5)} ` } var out = this.value.map((c,i)=>{ return ` ${c.substr(0,5) + "..." + c.substr(s.length-5)} ` }).join("\n") return out } } window.customElements.define('d4s-ccp-input-file', CCPFileInputWidgetController); class CCPRemoteFileInputWidgetController extends CCPBaseInputWidgetController{ constructor(){ super() } connectedCallback(){ this.rootdoc.addEventListener("input", ev=>{ if(ev.target.getAttribute("name") === this.name){ const index = Number(ev.target.getAttribute("data-index")) this.value[index] = ev.target.value } }) } addToolContent(){ const iss = document.querySelector("d4s-boot-2").loginToken.iss; const addresses = { "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.d4science.org/auth/realms/d4science" : "https://api.d4science.org/workspace" }; this.rootdoc.querySelector("div[name=tools]").innerHTML += `
Access your workspace
x
` const ws = this.rootdoc.querySelector("div[name=ws]") this.rootdoc.querySelector("svg[name=trigger]").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() if(ev.target.getAttribute("name") == this.name && ev.target.getAttribute("data-index") != null){ const index = Number(ev.target.getAttribute("data-index")) ev.target.value = ev.dataTransfer.getData("text/plain+downloadlink") this.value[index] = ev.target.value } }) document.addEventListener("keydown", ev=>{ if(ev.code == 'Escape' ) ws.classList.add("d-none"); }) } content(){ this.addToolContent() if(this.value.length <= 1){ return ` ` } var out = this.value.map((c,i)=>{ return ` ` }).join("\n") return out } } window.customElements.define('d4s-ccp-input-remotefile', CCPRemoteFileInputWidgetController); class CCPSecretInputWidgetController extends CCPBaseInputWidgetController{ constructor(){ super() } connectedCallback(){ this.rootdoc.addEventListener("input", ev=>{ if(ev.target.getAttribute("name") === this.name){ const index = Number(ev.target.getAttribute("data-index")) this.value[index] = ev.target.value } }) this.rootdoc.addEventListener("click", ev=>{ if(ev.target.getAttribute("name") === "password_toggle"){ const index = Number(ev.target.getAttribute("data-index")) const field = this.rootdoc.querySelector(`input[data-index='${index}']`) if(field.type === "text") field.type="password"; else field.type = "text"; } }) } content(){ if(this.value.length <= 1){ return `
👁
` } var out = this.value.map((c,i)=>{ return `
👁
` }).join("\n") return out } } window.customElements.define('d4s-ccp-input-secret', CCPSecretInputWidgetController);