Code

Ticket #4165: 5116_new_admin_progress_bar.diff

File 5116_new_admin_progress_bar.diff, 10.3 KB (added by Michael Axiak <axiak@…>, 7 years ago)

New and improved version!

Line 
1Index: django/contrib/admin/media/js/UploadProgress.js
2===================================================================
3--- django/contrib/admin/media/js/UploadProgress.js     (revision 0)
4+++ django/contrib/admin/media/js/UploadProgress.js     (revision 0)
5@@ -0,0 +1,264 @@
6+function getxy(){
7+    var x,y;
8+    if (self.innerHeight) // all except Explorer
9+        {
10+        x = self.innerWidth;
11+        y = self.innerHeight;
12+        }
13+    else if (document.documentElement && document.documentElement.clientHeight)
14+        // Explorer 6 Strict Mode
15+        {
16+        x = document.documentElement.clientWidth;
17+        y = document.documentElement.clientHeight;
18+        }
19+    else if (document.body) // other Explorers
20+        {
21+        x = document.body.clientWidth;
22+        y = document.body.clientHeight;
23+        }
24+    return {'x':x,'y':y}
25+    }
26+
27+var humanvalue = ['B','KB','MB','GB']
28+function humanize(bytes) {
29+    curbytes = bytes
30+    iterations = 0
31+    while (curbytes>1024) {
32+        iterations++
33+        curbytes=curbytes/1024
34+        }
35+    return curbytes.toFixed(1) + ' ' + humanvalue[iterations]
36+    }
37+
38+interval = null;
39+function fetch(uuid) {
40+    req = xmlhttp
41+    req.open("GET", "/admin/upload_progress/", 1);
42+    req.setRequestHeader("X-Progress-Id", uuid);
43+    req.onreadystatechange = function () {
44+    if (req.readyState == 4) {
45+        if (req.status == 200) {
46+
47+            var upload = eval( '(' + req.responseText + ')' );
48+
49+            if (upload.state == 'done' || upload.state == 'uploading')
50+                bar = document.getElementById('progress_bar');
51+                progress_wrap = document.getElementById('progress_wrap');
52+                if (upload.state == 'done') {
53+                    window.clearTimeout(interval);
54+                   progress_wrap.style.visibility = 'hidden';
55+                    return;   
56+                }
57+                bar_txt = document.getElementById('progress_text')
58+                bar_txt.innerHTML = ((upload.received / upload.size) * 100).toFixed(1) + '% - ' +
59+                    humanize(upload.received) + ' of ' + humanize(upload.size)
60+                w = 400 * upload.received / upload.size;
61+                bar.style.width = w + 'px';
62+
63+                }
64+            }
65+        }
66+    req.send(null);
67+
68+    }
69+
70+function closeprogress() {
71+
72+
73+
74+}
75+
76+function openprogress(e) {
77+
78+    uuid = "";
79+    for (i = 0; i < 32; i++) {
80+        uuid += Math.floor(Math.random() * 16).toString(16);
81+        }
82+    frm = e.target||e.srcElement;
83+
84+    if (frm.action.indexOf('?') == -1) {
85+       frm.action=frm.action+"?progress_id=" + uuid;
86+    } else {
87+       frm.action=frm.action+"&progress_id=" + uuid;
88+    }
89+
90+    if (document.getElementById('progress_wrap')) {
91+        document.getElementById('progress_wrap').style.visibility = 'visible';
92+        document.getElementById('progress_bar').style.width = '0';
93+        document.getElementById('progress_text').innerHTML = '0%';
94+
95+        interval = window.setInterval(
96+        function () {
97+            fetch(uuid);
98+            },
99+        1000
100+        );
101+        return;
102+    }
103+
104+    pos = getxy()
105+    posx = parseInt((pos.x/2)-(420/2), 10)
106+    posy = parseInt((pos.y/2)-(50/2), 10)
107+
108+    progress_wrap = quickElement('div', document.body, '', 'style',
109+        'position: absolute; top: '+posy+'px; left: '+posx+'px; height: 50px; ' +
110+        'padding: 10px; width: 420px; background: #ffffff; ' +
111+        'border: solid 1px #dddddd;', 'id', 'progress_wrap')
112+
113+    progress_label = quickElement('h1', progress_wrap, 'Upload progress')
114+
115+    progress = quickElement('div', progress_wrap, '', 'style',
116+        'top: 0; left: 0; width: 0px; ', 'id', 'progress_bar', 'class', 'submit-row')
117+
118+    progress_text = quickElement('div', progress_wrap, '0%', 'style',
119+        'color: #000000; ', 'id', 'progress_text')
120+
121+    interval = window.setInterval(
122+        function () {
123+            fetch(uuid);
124+            },
125+        1000
126+        );
127+    }
128+
129+addEvent(window, 'load', function() {
130+        frms = document.getElementsByTagName('form');
131+        for (var i=0; i<frms.length; i++) {
132+           if (frms[i].encoding.toLowerCase() == 'multipart/form-data') {
133+              addEvent(frms[i], 'submit',  openprogress);
134+              return;
135+           }
136+        }
137+    });
138+function getxy(){
139+    var x,y;
140+    if (self.innerHeight) // all except Explorer
141+        {
142+        x = self.innerWidth;
143+        y = self.innerHeight;
144+        }
145+    else if (document.documentElement && document.documentElement.clientHeight)
146+        // Explorer 6 Strict Mode
147+        {
148+        x = document.documentElement.clientWidth;
149+        y = document.documentElement.clientHeight;
150+        }
151+    else if (document.body) // other Explorers
152+        {
153+        x = document.body.clientWidth;
154+        y = document.body.clientHeight;
155+        }
156+    return {'x':x,'y':y}
157+    }
158+
159+var humanvalue = ['B','KB','MB','GB']
160+function humanize(bytes) {
161+    curbytes = bytes
162+    iterations = 0
163+    while (curbytes>1024) {
164+        iterations++
165+        curbytes=curbytes/1024
166+        }
167+    return curbytes.toFixed(1) + ' ' + humanvalue[iterations]
168+    }
169+
170+interval = null;
171+function fetch(uuid) {
172+    req = xmlhttp
173+    req.open("GET", "/admin/upload_progress/", 1);
174+    req.setRequestHeader("X-Progress-Id", uuid);
175+    req.onreadystatechange = function () {
176+    if (req.readyState == 4) {
177+        if (req.status == 200) {
178+
179+            var upload = eval( '(' + req.responseText + ')' );
180+
181+            if (upload.state == 'done' || upload.state == 'uploading')
182+                bar = document.getElementById('progress_bar');
183+                progress_wrap = document.getElementById('progress_wrap');
184+                if (upload.state == 'done') {
185+                    window.clearTimeout(interval);
186+                   progress_wrap.style.visibility = 'hidden';
187+                    return;   
188+                }
189+                bar_txt = document.getElementById('progress_text')
190+                bar_txt.innerHTML = ((upload.received / upload.size) * 100).toFixed(1) + '% - ' +
191+                    humanize(upload.received) + ' of ' + humanize(upload.size)
192+                w = 400 * upload.received / upload.size;
193+                bar.style.width = w + 'px';
194+
195+                }
196+            }
197+        }
198+    req.send(null);
199+
200+    }
201+
202+function closeprogress() {
203+
204+
205+
206+}
207+
208+function openprogress(e) {
209+
210+    uuid = "";
211+    for (i = 0; i < 32; i++) {
212+        uuid += Math.floor(Math.random() * 16).toString(16);
213+        }
214+    frm = e.target||e.srcElement;
215+
216+    if (frm.action.indexOf('?') == -1) {
217+       frm.action=frm.action+"?progress_id=" + uuid;
218+    } else {
219+       frm.action=frm.action+"&progress_id=" + uuid;
220+    }
221+
222+    if (document.getElementById('progress_wrap')) {
223+        document.getElementById('progress_wrap').style.visibility = 'visible';
224+        document.getElementById('progress_bar').style.width = '0';
225+        document.getElementById('progress_text').innerHTML = '0%';
226+
227+        interval = window.setInterval(
228+        function () {
229+            fetch(uuid);
230+            },
231+        1000
232+        );
233+        return;
234+    }
235+
236+    pos = getxy()
237+    posx = parseInt((pos.x/2)-(420/2), 10)
238+    posy = parseInt((pos.y/2)-(50/2), 10)
239+
240+    progress_wrap = quickElement('div', document.body, '', 'style',
241+        'position: absolute; top: '+posy+'px; left: '+posx+'px; height: 50px; ' +
242+        'padding: 10px; width: 420px; background: #ffffff; ' +
243+        'border: solid 1px #dddddd;', 'id', 'progress_wrap')
244+
245+    progress_label = quickElement('h1', progress_wrap, 'Upload progress')
246+
247+    progress = quickElement('div', progress_wrap, '', 'style',
248+        'top: 0; left: 0; width: 0px; ', 'id', 'progress_bar', 'class', 'submit-row')
249+
250+    progress_text = quickElement('div', progress_wrap, '0%', 'style',
251+        'color: #000000; ', 'id', 'progress_text')
252+
253+    interval = window.setInterval(
254+        function () {
255+            fetch(uuid);
256+            },
257+        1000
258+        );
259+    }
260+
261+addEvent(window, 'load', function() {
262+        frms = document.getElementsByTagName('form');
263+        for (var i=0; i<frms.length; i++) {
264+           if (frms[i].encoding.toLowerCase() == 'multipart/form-data') {
265+              addEvent(frms[i], 'submit',  openprogress);
266+              return;
267+           }
268+        }
269+    });
270\ No newline at end of file
271Index: django/contrib/admin/urls.py
272===================================================================
273--- django/contrib/admin/urls.py        (revision 5116)
274+++ django/contrib/admin/urls.py        (working copy)
275@@ -10,6 +10,7 @@
276     ('^$', 'django.contrib.admin.views.main.index'),
277     ('^r/(\d+)/(.*)/$', 'django.views.defaults.shortcut'),
278     ('^jsi18n/$', i18n_view, {'packages': 'django.conf'}),
279+    ('^upload_progress/$', 'django.contrib.admin.views.main.upload_progress'),
280     ('^logout/$', 'django.contrib.auth.views.logout'),
281     ('^password_change/$', 'django.contrib.auth.views.password_change'),
282     ('^password_change/done/$', 'django.contrib.auth.views.password_change_done'),
283Index: django/contrib/admin/views/main.py
284===================================================================
285--- django/contrib/admin/views/main.py  (revision 5116)
286+++ django/contrib/admin/views/main.py  (working copy)
287@@ -81,6 +81,8 @@
288 def get_javascript_imports(opts, auto_populated_fields, field_sets):
289 # Put in any necessary JavaScript imports.
290     js = ['js/core.js', 'js/admin/RelatedObjectLookups.js']
291+    if opts.has_field_type(models.FileField):
292+        js.append('js/UploadProgress.js')
293     if auto_populated_fields:
294         js.append('js/urlify.js')
295     if opts.has_field_type(models.DateTimeField) or opts.has_field_type(models.TimeField) or opts.has_field_type(models.DateField):
296@@ -777,3 +779,17 @@
297                                'admin/%s/change_list.html' % app_label,
298                                'admin/change_list.html'], context_instance=c)
299 change_list = staff_member_required(never_cache(change_list))
300+
301+def upload_progress(request):
302+    """
303+    Given this request, returns a JSON
304+    object that has information on a file upload progress.
305+    If there is no file upload in progress, returns an
306+    empty dictionary, '{}'.
307+    """
308+
309+    from django.utils import simplejson
310+
311+    content = simplejson.dumps(request.file_progress)
312+
313+    return HttpResponse(content=content, mimetype='text/plain')