Mercurial > libervia-web
comparison libervia/pages/photos/album/_browser/__init__.py @ 1300:6e110baa707f
browser (photos/album): photo(s) upload and deletion
author | Goffi <goffi@goffi.org> |
---|---|
date | Fri, 19 Jun 2020 16:47:51 +0200 |
parents | |
children | 7a4a92cf5b2b |
comparison
equal
deleted
inserted
replaced
1299:053141849206 | 1300:6e110baa707f |
---|---|
1 from browser import document, window, bind, html, DOMNode | |
2 from browser import aio | |
3 from browser import timer | |
4 from javascript import JSON | |
5 from interpreter import Inspector | |
6 from bridge import Bridge | |
7 from template import Template | |
8 import dialog | |
9 | |
10 files_service = window.files_service | |
11 files_path = window.files_path | |
12 bridge = Bridge() | |
13 | |
14 | |
15 def on_progress(ev, photo_elt): | |
16 if ev.lengthComputable: | |
17 percent = int(ev.loaded/ev.total*100) | |
18 update_progress(photo_elt, percent) | |
19 | |
20 | |
21 def on_load(file_, photo_elt): | |
22 update_progress(photo_elt, 100) | |
23 photo_elt.classList.add("progress_finished") | |
24 photo_elt.classList.remove("progress_started") | |
25 photo_elt.select_one('.action_delete').bind("click", on_delete) | |
26 print(f"file {file_.name} uploaded correctly") | |
27 | |
28 | |
29 def on_error(failure, file_, photo_elt): | |
30 # TODO: cleaner error notification | |
31 window.alert(f"can't upload {file_.name}: failure") | |
32 | |
33 | |
34 def update_progress(photo_elt, new_value): | |
35 progress_elt = photo_elt.select_one("progress") | |
36 progress_elt.value = new_value | |
37 progress_elt.text = f"{new_value}%" | |
38 | |
39 | |
40 def on_slot_cb(file_, upload_slot, photo_elt): | |
41 put_url, get_url, headers = upload_slot | |
42 xhr = window.XMLHttpRequest.new() | |
43 xhr.open("PUT", put_url, True) | |
44 xhr.upload.bind('progress', lambda ev: on_progress(ev, photo_elt)) | |
45 xhr.upload.bind('load', lambda ev: on_load(file_, photo_elt)) | |
46 xhr.upload.bind('error', lambda ev: on_error(xhr.response, file_, photo_elt)) | |
47 xhr.setRequestHeader('Xmpp-File-Path', window.encodeURIComponent(files_path)) | |
48 xhr.setRequestHeader('Xmpp-File-No-Http', "true") | |
49 xhr.send(file_) | |
50 | |
51 | |
52 def on_slot_eb(file_, failure, photo_elt): | |
53 breakpoint() | |
54 | |
55 | |
56 def upload_files(files): | |
57 print(f"uploading {len(files)} files") | |
58 photo_tpl = Template('photo/item.html') | |
59 album_items = document['album_items'] | |
60 for file_ in files: | |
61 url = window.URL.createObjectURL(file_) | |
62 photo_elt = photo_tpl.get_elt({ | |
63 "file": { | |
64 "name": file_.name, | |
65 # we don't want to open the file on click, it's not yet the | |
66 # uploaded URL | |
67 "url": url, | |
68 # we have no thumb yet, so we use the whole image | |
69 # TODO: reduce image for preview | |
70 "thumb_url": url, | |
71 }, | |
72 "uploading": True, | |
73 }) | |
74 photo_elt.classList.add("progress_started") | |
75 print(photo_elt.outerHTML) | |
76 album_items <= photo_elt | |
77 # timer.set_timeout(lambda photo_elt=photo_elt: fake_finish(photo_elt), 5000) | |
78 | |
79 bridge.fileHTTPUploadGetSlot( | |
80 file_.name, | |
81 file_.size, | |
82 file_.type or '', | |
83 files_service, | |
84 callback=lambda upload_slot, file_=file_, photo_elt=photo_elt: | |
85 on_slot_cb(file_, upload_slot, photo_elt), | |
86 errback=lambda failure, file_=file_, photo_elt=photo_elt: | |
87 on_slot_eb(file_, failure, photo_elt), | |
88 ) | |
89 | |
90 | |
91 @bind("#file_drop", "drop") | |
92 def on_file_select(evt): | |
93 evt.stopPropagation() | |
94 evt.preventDefault() | |
95 files = evt.dataTransfer.files | |
96 upload_files(files) | |
97 | |
98 | |
99 @bind("#file_drop", "dragover") | |
100 def on_drag_over(evt): | |
101 evt.stopPropagation() | |
102 evt.preventDefault() | |
103 evt.dataTransfer.dropEffect = 'copy' | |
104 | |
105 | |
106 @bind("#file_input", "change") | |
107 def on_file_input_change(evt): | |
108 files = evt.currentTarget.files | |
109 upload_files(files) | |
110 | |
111 | |
112 def file_delete_cb(item_elt, item): | |
113 item_elt.classList.add("state_deleted") | |
114 item_elt.bind("transitionend", lambda evt: item_elt.remove()) | |
115 print(f"deleted {item['name']}") | |
116 | |
117 | |
118 def file_delete_eb(failure, item_elt, item): | |
119 # TODO: cleaner error notification | |
120 window.alert(f"error while deleting {item['name']}: failure") | |
121 | |
122 | |
123 def delete_ok(evt, notif_elt, item_elt, item): | |
124 file_path = f"{files_path.rstrip('/')}/{item['name']}" | |
125 bridge.fileSharingDelete( | |
126 files_service, | |
127 file_path, | |
128 "", | |
129 callback=lambda : file_delete_cb(item_elt, item), | |
130 errback=lambda failure: file_delete_eb(failure, item_elt, item), | |
131 ) | |
132 | |
133 | |
134 def delete_cancel(evt, notif_elt, item_elt, item): | |
135 notif_elt.remove() | |
136 item_elt.classList.remove("selected_for_deletion") | |
137 | |
138 | |
139 def on_delete(evt): | |
140 evt.stopPropagation() | |
141 target = evt.currentTarget | |
142 item_elt = DOMNode(target.elt.closest('.item')) | |
143 item_elt.classList.add("selected_for_deletion") | |
144 item = JSON.parse(item_elt.dataset.item) | |
145 dialog.Confirm( | |
146 f"{item['name']!r} will be deleted, are you sure?", | |
147 ok_label="delete", | |
148 ).show( | |
149 ok_cb=lambda evt, notif_elt: delete_ok(evt, notif_elt, item_elt, item), | |
150 cancel_cb=lambda evt, notif_elt: delete_cancel(evt, notif_elt, item_elt, item), | |
151 ) | |
152 | |
153 | |
154 for elt in document.select('.action_delete'): | |
155 elt.bind("click", on_delete) |