Explorar o código

update ui.upload

Falko Schindler %!s(int64=2) %!d(string=hai) anos
pai
achega
3d2e3ad143

+ 2 - 2
api_docs_and_examples.py

@@ -206,9 +206,9 @@ def create_full() -> None:
         picker = ui.color_picker(on_pick=lambda e: button.style(f'background-color:{e.color}!important'))
         button = ui.button(on_click=picker.open).props('icon=colorize')
 
-    # @example(ui.upload)
+    @example(ui.upload, skip=False)
     def upload_example():
-        ui.upload(on_upload=lambda e: ui.notify(f'{len(e.files[0])} bytes'))
+        ui.upload(on_upload=lambda e: ui.notify(f'{e.files[0].size} bytes'))
 
     h3('Markdown and HTML')
 

+ 0 - 47
nicegui/elements/old/upload.py

@@ -1,47 +0,0 @@
-import base64
-import traceback
-from typing import Callable, Optional
-
-import justpy as jp
-
-from ..events import UploadEventArguments, handle_event
-from .element import Element
-
-
-class Upload(Element):
-
-    def __init__(self, *,
-                 multiple: bool = False,
-                 on_upload: Optional[Callable] = None,
-                 upload_button_text: str = 'Upload') -> None:
-        """File Upload
-
-        :param multiple: allow uploading multiple files at once (default: `False`)
-        :param on_upload: callback to execute when a file is uploaded (list of bytearrays)
-        :param upload_button_text: text for the upload button
-        """
-        self.upload_handler = on_upload
-        view = jp.Form(
-            enctype='multipart/form-data',
-            classes='flex gap-4 items-center',
-            submit=lambda sender, msg: self.submit(sender, msg),
-            temp=False,
-        )
-        jp.Input(type='file', multiple=multiple, change=lambda *_: False, a=view, temp=False)
-        jp.QBtn(type='submit', text=upload_button_text, color='primary', a=view, temp=False)
-
-        super().__init__(view)
-
-    def submit(self, _, msg) -> Optional[bool]:
-        try:
-            page_update = False
-            for form_data in msg.form_data:
-                if form_data.type == 'file':
-                    files = [base64.b64decode(f.file_content) for f in form_data.files]
-                    names = [f.name for f in form_data.files]
-                    arguments = UploadEventArguments(sender=self, socket=msg.websocket, files=files, names=names)
-                    if handle_event(self.upload_handler, arguments):
-                        page_update = None
-            return page_update
-        except Exception:
-            traceback.print_exc()

+ 42 - 0
nicegui/elements/upload.py

@@ -0,0 +1,42 @@
+from typing import Callable, Dict, Optional
+
+from ..element import Element
+from ..events import UploadEventArguments, UploadFile, handle_event
+from ..vue import register_component
+
+register_component('upload', __file__, 'upload.vue')
+
+
+class Upload(Element):
+
+    def __init__(self, *,
+                 multiple: bool = False,
+                 on_upload: Optional[Callable] = None,
+                 file_picker_label: str = '',
+                 upload_button_icon: str = 'file_upload') -> None:
+        """File Upload
+
+        :param multiple: allow uploading multiple files at once (default: `False`)
+        :param on_upload: callback to execute when a file is uploaded (list of bytearrays)
+        :param file_picker_label: label for the file picker element
+        :param upload_button_icon: icon for the upload button
+        """
+        super().__init__('upload')
+        self.classes('row items-baseline gap-2')
+        self._props['multiple'] = multiple
+        self._props['file_picker_label'] = file_picker_label
+        self._props['upload_button_icon'] = upload_button_icon
+
+        def upload(msg: Dict) -> None:
+            files = [
+                UploadFile(
+                    name=file['name'],
+                    lastModified=file['lastModified'],
+                    lastModifiedDate=file['lastModifiedDate'],
+                    size=file['size'],
+                    type=file['type'],
+                )
+                for file in msg['args']
+            ]
+            handle_event(on_upload, UploadEventArguments(sender=self, client=self.client, files=files))
+        self.on('upload', upload, ['*'])

+ 39 - 0
nicegui/elements/upload.vue

@@ -0,0 +1,39 @@
+<template>
+  <div>
+    <q-file :label="file_picker_label" v-model="file" :multiple="multiple" />
+    <q-btn :icon="upload_button_icon" @click="upload" size="sm" round color="primary" />
+  </div>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      file: undefined,
+    };
+  },
+  methods: {
+    upload() {
+      if (!this.file) return;
+      const files = this.multiple ? this.file : [this.file];
+      const args = files.map((file) => ({
+        name: file.name,
+        lastModified: file.lastModified / 1000,
+        lastModifiedDate: file.lastModifiedDate,
+        size: file.size,
+        type: file.type,
+        content: file,
+      }));
+      this.$emit("upload", args);
+    },
+  },
+  props: {
+    multiple: Boolean,
+    file_picker_label: String,
+    upload_button_text: String,
+    upload_button_icon: String,
+  },
+};
+</script>
+
+<style scoped></style>

+ 10 - 2
nicegui/events.py

@@ -37,10 +37,18 @@ class MouseEventArguments(EventArguments):
     image_y: float
 
 
+@dataclass
+class UploadFile:
+    name: str
+    lastModified: float
+    lastModifiedDate: str
+    size: int
+    type: str
+
+
 @dataclass
 class UploadEventArguments(EventArguments):
-    files: List[bytes]
-    names: List[str]
+    files: List[UploadFile]
 
 
 @dataclass

+ 1 - 0
nicegui/ui.py

@@ -37,6 +37,7 @@ from .elements.switch import Switch as switch
 from .elements.toggle import Toggle as toggle
 from .elements.tooltip import Tooltip as tooltip
 from .elements.tree import Tree as tree
+from .elements.upload import Upload as upload
 from .notify import notify
 from .page import page
 from .run import run