diff --git a/ccp/js/inputwidgetcontroller.js b/ccp/js/inputwidgetcontroller.js index 86ef9f6..cd057c5 100644 --- a/ccp/js/inputwidgetcontroller.js +++ b/ccp/js/inputwidgetcontroller.js @@ -74,6 +74,9 @@ class Renderer{ if(this.isSecret(input)){ return new SecretInputRenderer(input) } + if(this.isFile(input)){ + return new FileInputRenderer(input) + } return new SimpleInputRenderer(input) } @@ -94,6 +97,13 @@ class Renderer{ (input.schema.format != null) && (input.schema.format.toLowerCase() === "code") } + + static isFile(input){ + return (input.schema.type === "string") && + ("format" in input.schema) && + (input.schema.format != null) && + (input.schema.format.toLowerCase() === "file") + } static isDateTime(input){ return (input.schema.type === "string") && @@ -132,6 +142,68 @@ class SimpleInputRenderer extends Renderer{ } } +class FileInputRenderer extends Renderer{ + + #html = null; + #content = null; + + constructor(input){ + super(input) + } + + connectedCallback(controller){ + controller.querySelector(`input[name=${this.name}]`).addEventListener("change", ev=>{ + const tgt = ev.target + const ename = tgt.getAttribute("name") + if(ename === this.name){ + const file = ev.target.files[0] + if(file.type !== this.schema.contentMediaType){ + alert("Unsupported media type. Must be " + this.schema.contentMediaType) + ev.stopPropagation() + ev.preventDefault() + tgt.value = null + return false + } + 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.#content = encoded + }) + reader.readAsDataURL(file) + } + }) + } + + getValue(parent){ + return this.#content + } + + render(){ + let required = this.required ? 'required="required"' : "" + let readonly = this.readOnly ? 'readonly="readOnly"' : "" + this.#html = ` +
+ + +
+ ` + return this.#html + } +} + class SecretInputRenderer extends Renderer{ #html = null; diff --git a/ccp/js/inputwidgeteditorcontroller.js b/ccp/js/inputwidgeteditorcontroller.js index 9a68a4a..eca77ea 100644 --- a/ccp/js/inputwidgeteditorcontroller.js +++ b/ccp/js/inputwidgeteditorcontroller.js @@ -98,7 +98,8 @@ class CCPInputWidgetEditorController extends HTMLElement{ - + + @@ -164,6 +165,8 @@ class CCPInputWidgetEditorController extends HTMLElement{ 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"){