Django

Code

Ticket #4165: 5343_javascript_and_admin.diff

File 5343_javascript_and_admin.diff, 15.9 kB (added by Michael Axiak <axiak@mit.edu>, 1 year ago)

New batch of JavaScript? and Admin interaction

  • django/contrib/admin/media/js/UploadProgress.js

    old new  
     1 
     2var upload_progress_failures = 0; 
     3var TOTAL_UPLOAD_PROGRESS_FAILURES = 10; 
     4var upload_progress_num__IE = 0; 
     5var show_progress = false; 
     6/* below is the url from admin to the upload progress. 
     7   e.g. upload_progress/ 
     8*/ 
     9var progress_url  = "upload_progress/"; 
     10 
     11var split_path = location.pathname.split('/'); 
     12 
     13var new_array = new Array(); 
     14 
     15var j=0; 
     16for (var i=0; i<split_path.length; i++) { 
     17    if (split_path[i] != '') { 
     18        new_array[j] = split_path[i]; 
     19        j++; 
     20    } 
     21} 
     22 
     23admin_root = '/'; 
     24if (new_array.length > 3) { 
     25    for (var i=0; i<new_array.length-3; i++) { 
     26        admin_root += new_array[i]+'/'; 
     27    } 
     28} 
     29 
     30progress_url = admin_root + progress_url; 
     31 
     32function getxy(){ 
     33    var x,y; 
     34    if (self.innerHeight) // all except Explorer 
     35        { 
     36        x = self.innerWidth; 
     37        y = self.innerHeight; 
     38        } 
     39    else if (document.documentElement && document.documentElement.clientHeight) 
     40        // Explorer 6 Strict Mode 
     41        { 
     42        x = document.documentElement.clientWidth; 
     43        y = document.documentElement.clientHeight; 
     44        } 
     45    else if (document.body) // other Explorers 
     46        { 
     47        x = document.body.clientWidth; 
     48        y = document.body.clientHeight; 
     49        } 
     50    return {'x':x,'y':y} 
     51    } 
     52 
     53 
     54function upload_ajax_problem() { 
     55    /* If there's a problem, will cancel after 
     56       TOTAL_UPLOAD_PROGRESS_FAILURES tries.   */ 
     57 
     58    var progress_wrap2 = document.getElementById('progress_wrap'); 
     59    upload_progress_failures++; 
     60    if (upload_progress_failures >= TOTAL_UPLOAD_PROGRESS_FAILURES){ 
     61      window.clearTimeout(interval); 
     62    }  
     63    progress_wrap2.style.display = 'none'; 
     64    progress_wrap2.style.visibility = 'hidden'; 
     65} 
     66 
     67var humanvalue = ['B','KB','MB','GB'] 
     68function humanize(bytes) { 
     69  curbytes = bytes; 
     70  iterations = 0; 
     71  if (!curbytes) { 
     72     return ''; 
     73  } 
     74  while (curbytes>1024) { 
     75    iterations++; 
     76    curbytes=curbytes/1024; 
     77  } 
     78  return curbytes.toFixed(1) + ' ' + humanvalue[iterations]; 
     79} 
     80 
     81interval = null; 
     82function fetch(uuid) { 
     83  /* no ajax here */ 
     84  if (!xmlhttp) { 
     85    upload_ajax_problem(); 
     86    return; 
     87  } 
     88 
     89  req = xmlhttp; 
     90  req.open("GET", progress_url+"?" + upload_progress_num__IE, true); 
     91  upload_progress_num__IE++; // IE Hack 
     92  req.onreadystatechange = function () { 
     93    var progress_wrap2 = document.getElementById('progress_wrap'); 
     94    var progress_bar2  = document.getElementById('progress_bar'); 
     95    var bar_txt = document.getElementById('progress_text'); 
     96 
     97    if (req.readyState == 4) { 
     98      try { 
     99        request_status = req.status; 
     100      } catch (e) { 
     101        /* Really bad. */ 
     102        request_status = -1; 
     103      } 
     104      if (request_status == 200) { 
     105        var upload = new Function(" return "+req.responseText)(); 
     106        if (upload) { 
     107 
     108          if (!upload.state) { 
     109             progress_wrap2.style.visibility = 'hidden'; 
     110             progress_wrap2.style.display    = 'none'; 
     111             return; 
     112          } else if (upload.state == 'done') { 
     113             window.clearTimeout(interval); 
     114             progress_wrap2.style.visibility = 'hidden'; 
     115             progress_wrap2.style.display    = 'none'; 
     116             return;    
     117          } else { 
     118             if (show_progress) { 
     119                 progress_wrap2.style.visibility = 'visible'; 
     120                 progress_wrap2.style.display    = 'block'; 
     121             } 
     122             move_to_center(progress_wrap2); 
     123             bar_txt.innerHTML = ((upload.received / upload.size) * 100).toFixed(1) 
     124                     + '% - ' + humanize(upload.received) + ' of '  
     125                     + humanize(upload.size); 
     126             var bar_width__px = 400 * upload.received / upload.size; 
     127             progress_bar2.style.width = bar_width__px + 'px'; 
     128          } 
     129        } else { 
     130          upload_ajax_problem(); 
     131        } 
     132      } else { 
     133        upload_ajax_problem(); 
     134      } 
     135    } 
     136  }; 
     137  try { 
     138    req.setRequestHeader("X-Upload-Id", uuid); 
     139  } catch (e) { 
     140    /* couldn't set the header, the request is broken. */ 
     141    req.abort(); 
     142  } 
     143  req.send(null);  
     144 
     145} 
     146 
     147function move_to_center(progress_wrap) { 
     148    pos = getxy(); 
     149    posx = parseInt((pos.x/2)-(420/2), 10); 
     150    posy = parseInt((pos.y/2)-(50/2), 10); 
     151 
     152    progress_wrap.style.top  = posy + 'px'; 
     153    progress_wrap.style.left = posx + 'px';    
     154} 
     155 
     156function close_progress() { 
     157    var progress_wrap2 = document.getElementById('progress_wrap'); 
     158    progress_wrap2.style.display = 'none'; 
     159    progress_wrap2.style.visibility = 'hidden'; 
     160    show_progress = false; 
     161    // don't want to follow a link. 
     162    return false; 
     163} 
     164 
     165 
     166function openprogress(e) { 
     167 
     168    show_progress = true; 
     169    upload_progress_failures = 0; 
     170    uuid = ""; 
     171    for (i = 0; i < 32; i++) { 
     172        uuid += Math.floor(Math.random() * 16).toString(16); 
     173        } 
     174    frm = e.target||e.srcElement; 
     175 
     176    /* 
     177    var progress_wrap2 = document.getElementById('progress_wrap'); 
     178    move_to_center(progress_wrap2); 
     179    progress_wrap2.style.display = 'block'; 
     180    progress_wrap2.style.visibility = 'visible'; 
     181    */ 
     182 
     183    if (frm.action.indexOf('?') == -1) { 
     184       frm.action=frm.action+"?progress_id=" + uuid 
     185    } else { 
     186       frm.action=frm.action+"&progress_id=" + uuid; 
     187    } 
     188 
     189    interval = window.setInterval( 
     190        function () { 
     191            fetch(uuid); 
     192            }, 
     193        1000 
     194        ); 
     195} 
     196 
     197addEvent(window, 'load', function() { 
     198        frms = document.getElementsByTagName('form'); 
     199        for (var i=0; i<frms.length; i++) { 
     200           if (frms[i].encoding.toLowerCase() == 'multipart/form-data') { 
     201              addEvent(frms[i], 'submit',  openprogress); 
     202              return; 
     203           } 
     204        } 
     205    }); 
  • django/contrib/admin/urls.py

    old new  
    1010    ('^$', 'django.contrib.admin.views.main.index'), 
    1111    ('^r/(\d+)/(.*)/$', 'django.views.defaults.shortcut'), 
    1212    ('^jsi18n/$', i18n_view, {'packages': 'django.conf'}), 
     13    ('^upload_progress/$', 'django.contrib.admin.views.main.upload_progress'), 
    1314    ('^logout/$', 'django.contrib.auth.views.logout'), 
    1415    ('^password_change/$', 'django.contrib.auth.views.password_change'), 
    1516    ('^password_change/done/$', 'django.contrib.auth.views.password_change_done'), 
  • django/contrib/admin/views/main.py

    old new  
    99from django.shortcuts import get_object_or_404, render_to_response 
    1010from django.db import models 
    1111from django.db.models.query import handle_legacy_orderlist, QuerySet 
    12 from django.http import Http404, HttpResponse, HttpResponseRedirect 
     12from django.http import Http404, HttpResponse, HttpResponseRedirect, HttpResponseServerError 
    1313from django.utils.html import escape 
    1414from django.utils.text import capfirst, get_text_list 
    1515import operator 
     
    8181def get_javascript_imports(opts, auto_populated_fields, field_sets): 
    8282# Put in any necessary JavaScript imports. 
    8383    js = ['js/core.js', 'js/admin/RelatedObjectLookups.js'] 
     84    if opts.has_field_type(models.FileField) and settings.FILE_UPLOAD_DIR: 
     85        js.append('js/UploadProgress.js') 
    8486    if auto_populated_fields: 
    8587        js.append('js/urlify.js') 
    8688    if opts.has_field_type(models.DateTimeField) or opts.has_field_type(models.TimeField) or opts.has_field_type(models.DateField): 
     
    777779                               'admin/%s/change_list.html' % app_label, 
    778780                               'admin/change_list.html'], context_instance=c) 
    779781change_list = staff_member_required(never_cache(change_list)) 
     782 
     783def upload_progress(request): 
     784    """ 
     785    Given this request, returns a JSON 
     786    object that has information on a file upload progress. 
     787    If there is no file upload in progress, returns an 
     788    empty dictionary, '{}'. 
     789    """ 
     790    from django.utils import simplejson 
     791 
     792    content = simplejson.dumps(request.file_progress) 
     793 
     794    if content.strip() == '{}': 
     795        return HttpResponseServerError('') 
     796    else: 
     797        return HttpResponse(content=content, mimetype='text/plain') 
  • django/contrib/admin/templates/admin/change_form.html

    old new  
    6565   {% auto_populated_field_script auto_populated_fields change %} 
    6666   </script> 
    6767{% endif %} 
     68 
     69{% if has_file_field %} 
     70<div id="progress_wrap" style="position: absolute; background: white; z-index: 9040; display: none; visibility: hidden; width: 420px; height: 50px padding: 10px; border: solid 1px #ddd;"> 
     71   <a href="#" onclick="close_progress();return false" title="Close Progress Bar"  
     72      style="color: #c00; font-size: 1.5em; font-weight: bold; float: right; padding: 0; position: relative; top: -2px; left: -2px;">X</a> 
     73   <h1>Upload progress</h1> 
     74 
     75   <div id="progress_bar" style="top: 0; left: 0; width: 0; z-index: 9049; height: 4px;" class="submit-row"></div> 
     76   <div id="progress_text" style="color: black;">0%</div> 
    6877</div> 
     78{% endif %} 
     79 
     80</div> 
    6981</form></div> 
    7082{% endblock %} 
  • django/contrib/uploadprogress/models.py

    old new  
     1""" 
     2Models file for a simple file upload progress application. 
     3This cause the file progress to be stored in the database. 
     4To activate: 
     51) Add 'django.contrib.uploadprogress.middleware.FileProgressDB' 
     6   to your MIDDLEWARE_CLASSES setting. 
     72) Add 'django.contrib.uploadprogress' to your INSTALLED_APPS. 
     8 
     9""" 
     10 
     11from django.db import models 
     12import datetime 
     13 
     14try: 
     15    import cPickle as pickle 
     16except ImportError: 
     17    import pickle 
     18 
     19class FileProgress(models.Model): 
     20 
     21    remote_addr = models.CharField(maxlength=64) 
     22    progress_id = models.CharField(maxlength=32) 
     23    progress_text = models.TextField(editable = False) 
     24    last_ts     = models.DateTimeField() 
     25 
     26    class Meta: 
     27        verbose_name_plural = 'File Progresses' 
     28        unique_together = (('remote_addr', 
     29                           'progress_id', 
     30                           ), 
     31                           ) 
     32 
     33    class Admin: 
     34        pass 
     35 
     36    def __str__(self): 
     37        return 'File Progress for "%s" and IP "%s".' % (self.progress_id, self.remote_addr) 
     38 
     39    def _get_dict(self): 
     40        """ 
     41        Returns a dictionary object. 
     42        """ 
     43        if hasattr(self, '_progress_dict'): 
     44            return self._progress_dict 
     45         
     46        if not self.progress_text: 
     47            self._progress_dict = {} 
     48            return {} 
     49 
     50        try: 
     51            self._progress_dict = pickle.loads(self.progress_text) 
     52        except: 
     53            self._progress_dict = {} 
     54 
     55        return self._progress_dict 
     56 
     57    def _set_dict(self, dict): 
     58        """ 
     59        Sets a dictionary object. 
     60        """ 
     61        self._progress_dict = dict 
     62 
     63    progress = property(_get_dict, _set_dict) 
     64 
     65    def save(self, *args, **kwargs): 
     66        """ 
     67        Pickles the dictionary representation 
     68        of the progress. 
     69        """ 
     70        try: 
     71            self.progress_text = pickle.dumps(self.progress) 
     72        except: 
     73            pass 
     74 
     75        self.last_ts = datetime.datetime.now() 
     76 
     77        return super(FileProgress, self).save(*args, **kwargs) 
  • django/contrib/uploadprogress/middleware/uploadcache.py

    old new  
     1""" 
     2 
     3Middleware to track file progress using the cache framework. 
     4To use, just add 
     5    'django.contrib.uploadprogress.middleware.FileProgressCached' 
     6to your ``MIDDLEWARE_SETTINGS``. 
     7 
     8If your cache framework does not work, this will not work either. 
     9 
     10""" 
     11from django.core.cache import cache 
     12from django.conf import settings 
     13from django.http.multipartparser import MultiPartParserError 
     14 
     15UPLOAD_CACHE_PREFIX = getattr(settings, 'UPLOAD_CACHE_PREFIX', 'UPLOAD_PROGRESS_') 
     16 
     17class FileProgressStore(object): 
     18 
     19    def _get_key(self, request): 
     20        """ 
     21        Returns the cache prefix for any cache key. 
     22        Uses the IP Address as well as the randomly generated uuid. 
     23        """ 
     24         
     25        if hasattr(self, '_cache_key'): 
     26            return self._cache_key 
     27         
     28        self._cache_key = '%s__%s__%s' % \ 
     29                           (UPLOAD_CACHE_PREFIX, 
     30                            request.META['REMOTE_ADDR'], 
     31                            request.META['UPLOAD_PROGRESS_ID'],) 
     32 
     33        return self._cache_key 
     34 
     35    def __get__(self, request, HttpRequest): 
     36        return cache.get(self._get_key(request), {}) 
     37 
     38    def __set__(self, request, new_val): 
     39        received_size = total_size = -1 
     40        try: 
     41            total_size = int(new_val['size']) 
     42        except: 
     43            pass 
     44 
     45        try: 
     46            received_size = int(new_val['received']) 
     47        except: 
     48            pass 
     49         
     50        cache.set(self._get_key(request), new_val) 
     51 
     52    def __delete__(self, request): 
     53        cache.delete(self._get_key(request)) 
     54 
     55class FileProgressCached(object): 
     56 
     57    def process_request(self, request): 
     58        # set the request.file_progress descriptor 
     59        request.__class__.file_progress = FileProgressStore() 
  • django/contrib/uploadprogress/middleware/uploaddb.py

    old new  
     1""" 
     2 
     3Middleware to hold fileupload progress state in a database. 
     4To install, simply add 
     5    'django.contrib.uploadprogress.middleware.FileProgressDB' 
     6     
     7to your ``MIDDLEWARE_SETTINGS`` and 
     8    'django.contrib.uploadprogress' 
     9to your ``INSTALLED_APPS``. 
     10 
     11Then run ``./manage.py syncdb`` as you normally would. 
     12 
     13""" 
     14from django.contrib.uploadprogress.models import FileProgress 
     15from django.http.multipartparser import MultiPartParserError 
     16from django.conf import settings 
     17 
     18try: 
     19    import cPickle as pickle 
     20except ImportError: 
     21    import pickle 
     22 
     23class FileProgressDBStore(object): 
     24 
     25    def _get_db_row(self, request): 
     26        if not hasattr(self, '_db_row'): 
     27            self._db_row, created = FileProgress.objects.get_or_create( 
     28                                                 remote_addr = request.META['REMOTE_ADDR'], 
     29                                                 progress_id = request.META['UPLOAD_PROGRESS_ID']) 
     30 
     31        return self._db_row 
     32 
     33    def __get__(self, request, HttpRequest): 
     34        return self._get_db_row(request).progress 
     35 
     36    def __set__(self, request, new_val): 
     37        row = self._get_db_row(request) 
     38        row.progress = new_val 
     39        row.save() 
     40 
     41    def __delete__(self, request): 
     42        self._get_db_row(request).delete() 
     43 
     44class FileProgressDB(object): 
     45 
     46    def process_request(self, request): 
     47        request.__class__.file_progress = FileProgressDBStore() 
  • django/contrib/uploadprogress/middleware/__init__.py

    old new  
     1from django.contrib.uploadprogress.middleware.uploaddb import FileProgressDB 
     2from django.contrib.uploadprogress.middleware.uploadcache import FileProgressCached 
     3