Mercurial > libervia-web
comparison libervia/web/pages/photos/album/_browser/__init__.py @ 1532:106945841fbc
_browser (album): moved code to upload file to a separate `file_uploader` module:
this way, uploading logic can be re-used elsewhere.
author | Goffi <goffi@goffi.org> |
---|---|
date | Thu, 22 Jun 2023 16:36:01 +0200 |
parents | d7c78722e4f8 |
children |
comparison
equal
deleted
inserted
replaced
1531:d7c78722e4f8 | 1532:106945841fbc |
---|---|
1 from browser import document, window, bind, html, DOMNode, aio | 1 import alt_media_player |
2 from bridge import AsyncBridge, Bridge | |
3 from browser import DOMNode, aio, bind, document, html, window | |
4 import dialog | |
5 from file_uploader import FileUploader | |
6 from invitation import InvitationManager | |
2 from javascript import JSON | 7 from javascript import JSON |
3 from bridge import Bridge, AsyncBridge | 8 import loading |
9 from slideshow import SlideShow | |
4 from template import Template | 10 from template import Template |
5 import dialog | |
6 from slideshow import SlideShow | |
7 from invitation import InvitationManager | |
8 import alt_media_player | |
9 # we use tmp_aio because `blob` is not handled in Brython's aio | |
10 import tmp_aio | 11 import tmp_aio |
11 import loading | |
12 | 12 |
13 | 13 |
14 cache_path = window.cache_path | 14 cache_path = window.cache_path |
15 files_service = window.files_service | 15 files_service = window.files_service |
16 files_path = window.files_path | 16 files_path = window.files_path |
26 photo_tpl = Template('photo/item.html') | 26 photo_tpl = Template('photo/item.html') |
27 player_tpl = Template('components/media_player.html') | 27 player_tpl = Template('components/media_player.html') |
28 | 28 |
29 # file upload | 29 # file upload |
30 | 30 |
31 def on_progress(ev, photo_elt): | 31 file_uploader = FileUploader(files_service, "photo/item.html", files_path) |
32 if ev.lengthComputable: | |
33 percent = int(ev.loaded/ev.total*100) | |
34 update_progress(photo_elt, percent) | |
35 | |
36 | |
37 def on_load(file_, photo_elt): | |
38 update_progress(photo_elt, 100) | |
39 photo_elt.classList.add("progress_finished") | |
40 photo_elt.classList.remove("progress_started") | |
41 photo_elt.select_one('.action_delete').bind("click", on_delete) | |
42 print(f"file {file_.name} uploaded correctly") | |
43 | |
44 | |
45 def on_error(failure, file_, photo_elt): | |
46 dialog.notification.show( | |
47 f"can't upload {file_.name}: {failure}", | |
48 level="error" | |
49 ) | |
50 | |
51 | |
52 def update_progress(photo_elt, new_value): | |
53 progress_elt = photo_elt.select_one("progress") | |
54 progress_elt.value = new_value | |
55 progress_elt.text = f"{new_value}%" | |
56 | |
57 | |
58 def on_slot_cb(file_, upload_slot, photo_elt): | |
59 put_url, get_url, headers = upload_slot | |
60 xhr = window.XMLHttpRequest.new() | |
61 xhr.open("PUT", put_url, True) | |
62 xhr.upload.bind('progress', lambda ev: on_progress(ev, photo_elt)) | |
63 xhr.upload.bind('load', lambda ev: on_load(file_, photo_elt)) | |
64 xhr.upload.bind('error', lambda ev: on_error(xhr.response, file_, photo_elt)) | |
65 xhr.setRequestHeader('Xmpp-File-Path', window.encodeURIComponent(files_path)) | |
66 xhr.setRequestHeader('Xmpp-File-No-Http', "true") | |
67 xhr.send(file_) | |
68 | |
69 | |
70 def on_slot_eb(file_, failure, photo_elt): | |
71 dialog.notification.show( | |
72 f"Can't get upload slot: {failure['message']}", | |
73 level="error" | |
74 ) | |
75 photo_elt.remove() | |
76 | |
77 | |
78 def upload_files(files): | |
79 print(f"uploading {len(files)} files") | |
80 album_items = document['album_items'] | |
81 for file_ in files: | |
82 url = window.URL.createObjectURL(file_) | |
83 photo_elt = photo_tpl.get_elt({ | |
84 "file": { | |
85 "name": file_.name, | |
86 # we don't want to open the file on click, it's not yet the | |
87 # uploaded URL | |
88 "url": url, | |
89 # we have no thumb yet, so we use the whole image | |
90 # TODO: reduce image for preview | |
91 "thumb_url": url, | |
92 }, | |
93 "uploading": True, | |
94 }) | |
95 photo_elt.classList.add("progress_started") | |
96 album_items <= photo_elt | |
97 | |
98 bridge.file_http_upload_get_slot( | |
99 file_.name, | |
100 file_.size, | |
101 file_.type or '', | |
102 files_service, | |
103 callback=lambda upload_slot, file_=file_, photo_elt=photo_elt: | |
104 on_slot_cb(file_, upload_slot, photo_elt), | |
105 errback=lambda failure, file_=file_, photo_elt=photo_elt: | |
106 on_slot_eb(file_, failure, photo_elt), | |
107 ) | |
108 | 32 |
109 | 33 |
110 @bind("#file_drop", "drop") | 34 @bind("#file_drop", "drop") |
111 def on_file_select(evt): | 35 def on_file_select(evt): |
112 evt.stopPropagation() | 36 evt.stopPropagation() |
113 evt.preventDefault() | 37 evt.preventDefault() |
114 files = evt.dataTransfer.files | 38 files = evt.dataTransfer.files |
115 upload_files(files) | 39 file_uploader.upload_files(files, document["album_items"]) |
116 | 40 |
117 | 41 |
118 @bind("#file_drop", "dragover") | 42 @bind("#file_drop", "dragover") |
119 def on_drag_over(evt): | 43 def on_drag_over(evt): |
120 evt.stopPropagation() | 44 evt.stopPropagation() |
123 | 47 |
124 | 48 |
125 @bind("#file_input", "change") | 49 @bind("#file_input", "change") |
126 def on_file_input_change(evt): | 50 def on_file_input_change(evt): |
127 files = evt.currentTarget.files | 51 files = evt.currentTarget.files |
128 upload_files(files) | 52 file_uploader.upload_files(files, document["album_items"]) |
129 | 53 |
130 # delete | 54 # delete |
131 | 55 |
132 def file_delete_cb(item_elt, item): | 56 def file_delete_cb(item_elt, item): |
133 item_elt.classList.add("state_deleted") | 57 item_elt.classList.add("state_deleted") |
170 ok_color="danger", | 94 ok_color="danger", |
171 ).show( | 95 ).show( |
172 ok_cb=lambda evt, notif_elt: delete_ok(evt, notif_elt, item_elt, item), | 96 ok_cb=lambda evt, notif_elt: delete_ok(evt, notif_elt, item_elt, item), |
173 cancel_cb=lambda evt, notif_elt: delete_cancel(evt, notif_elt, item_elt, item), | 97 cancel_cb=lambda evt, notif_elt: delete_cancel(evt, notif_elt, item_elt, item), |
174 ) | 98 ) |
99 | |
100 file_uploader.on_delete_cb = on_delete | |
175 | 101 |
176 # cover | 102 # cover |
177 | 103 |
178 async def cover_ok(evt, notif_elt, item_elt, item): | 104 async def cover_ok(evt, notif_elt, item_elt, item): |
179 # we first need to get a blob of the image | 105 # we first need to get a blob of the image |