Mercurial > libervia-web
view libervia/web/pages/_browser/file_uploader.py @ 1574:4ab4bc3ae462
browser: new `tools` module with a first method to detect touch devices
author | Goffi <goffi@goffi.org> |
---|---|
date | Wed, 22 Nov 2023 16:31:36 +0100 |
parents | 106945841fbc |
children |
line wrap: on
line source
import json from bridge import Bridge from browser import console as log, window import dialog from template import Template bridge = Bridge() log.warning = log.warn class FileUploader: """Class handling HTTP upload and progress display""" def __init__(self, files_service, template_file, files_path=None, on_delete_cb=None): self.files_service = files_service self.files_path = files_path self.item_tpl = Template(template_file) self.on_delete_cb = on_delete_cb self.uploaded = {} def on_progress(self, ev, item_elt): if ev.lengthComputable: percent = int(ev.loaded/ev.total*100) self.update_progress(item_elt, percent) def on_load(self, file_, item_elt): self.update_progress(item_elt, 100) item_elt.classList.add("progress_finished") item_elt.classList.remove("progress_started") if self.on_delete_cb is not None: delete_btn = item_elt.select_one('.action_delete') if delete_btn is not None: delete_btn.bind("click", self.on_delete_cb) log.info(f"file {file_.name} uploaded correctly") def on_error(self, failure, file_, item_elt): dialog.notification.show( f"can't upload {file_.name}: {failure}", level="error" ) def update_progress(self, item_elt, new_value): progress_elt = item_elt.select_one("progress") if progress_elt is not None: progress_elt.value = new_value progress_elt.text = f"{new_value}%" def on_slot_cb(self, file_, upload_slot, item_elt): put_url, get_url, headers = upload_slot xhr = window.XMLHttpRequest.new() xhr.open("PUT", put_url, True) xhr.upload.bind('progress', lambda ev: self.on_progress(ev, item_elt)) xhr.upload.bind('load', lambda ev: self.on_load(file_, item_elt)) xhr.upload.bind('error', lambda ev: self.on_error(xhr.response, file_, item_elt)) if self.files_path is not None: xhr.setRequestHeader( 'Xmpp-File-Path', window.encodeURIComponent(self.files_path) ) xhr.setRequestHeader('Xmpp-File-No-Http', "true") xhr.send(file_) # we update file data with the get URL file_data = json.loads(item_elt.getAttribute("data-file")) file_data["url"] = get_url item_elt.setAttribute("data-file", json.dumps(file_data)) def on_slot_eb(self, file_, failure, item_elt): dialog.notification.show( f"Can't get upload slot: {failure['message']}", level="error" ) item_elt.remove() def upload_files(self, files, container_elt): """Start file upload, and add item_tpl to container_elt""" log.info(f"uploading {len(files)} files") for file_ in files: url = window.URL.createObjectURL(file_) file_data = { "name": file_.name, "mime_type": file_.type, } template_file_data = file_data.copy() # we don't want to open the file on click, it's not yet the # uploaded URL template_file_data["url"] = url # we have no thumb yet, so we use the whole image # TODO: reduce image for preview template_file_data["thumb_url"] = url item_elt = self.item_tpl.get_elt({ "file": template_file_data, "uploading": True, }) item_elt.setAttribute("data-file", json.dumps(file_data)) item_elt.classList.add("progress_started") container_elt <= item_elt bridge.file_http_upload_get_slot( file_.name, file_.size, file_.type or '', self.files_service, callback=lambda upload_slot, file_=file_, item_elt=item_elt: self.on_slot_cb(file_, upload_slot, item_elt), errback=lambda failure, file_=file_, item_elt=item_elt: self.on_slot_eb(file_, failure, item_elt), )