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)