Projet

Général

Profil

0001-manager-use-ajax-to-display-tar-format-site-export-s.patch

Nicolas Roche, 26 juillet 2020 15:47

Télécharger (7,84 ko)

Voir les différences:

Subject: [PATCH] manager: use ajax to display tar format site export size
 (#45466)

 combo/apps/assets/urls.py                     |  2 ++
 combo/apps/assets/views.py                    | 31 +++++++++++++++-
 combo/manager/forms.py                        |  4 ---
 .../manager/templates/combo/site_export.html  | 35 ++++++++++++++++++-
 combo/manager/views.py                        |  5 ++-
 5 files changed, 68 insertions(+), 9 deletions(-)
combo/apps/assets/urls.py
35 35

  
36 36
urlpatterns = [
37 37
    url(r'^assets/(?P<key>[\w_:-]+)$', views.serve_asset),
38 38
    url(r'^manage/assets/', decorated_includes(manager_required,
39 39
        include(assets_manager_urls))),
40 40

  
41 41
    url(r'^api/assets/set/(?P<key>[\w_:-]+)/$', api_views.view_set,
42 42
        name='api-assets-set'),
43
    url(r'^ajax/asset-disk-space-usage/$',
44
        views.ajax_disk_space_usage, name='combo-assets-ajax-disk-space-usage'),
43 45
]
combo/apps/assets/views.py
12 12
# GNU Affero General Public License for more details.
13 13
#
14 14
# You should have received a copy of the GNU Affero General Public License
15 15
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 16

  
17 17
import json
18 18
import tarfile
19 19
import os
20
import time
20 21

  
21 22
from django.conf import settings
22 23
from django.contrib import messages
23 24
from django.core.exceptions import ObjectDoesNotExist, PermissionDenied
24 25
from django.core.files.storage import default_storage
25 26
from django.urls import reverse, reverse_lazy
26
from django.http import Http404, HttpResponse
27
from django.http import Http404, HttpResponse, StreamingHttpResponse
27 28
from django.shortcuts import get_object_or_404
28 29
from django.shortcuts import redirect
29 30
from django.utils.six import BytesIO
30 31
from django.utils.translation import ugettext_lazy as _
31 32
from django.views.generic import TemplateView, ListView, FormView
32 33

  
33 34
import ckeditor
34 35
from sorl.thumbnail.shortcuts import get_thumbnail
......
372 373
        geometry_string += 'x%s' % height
373 374

  
374 375
    # no thumbnail whithout geometry_string or for a svg file
375 376
    if not geometry_string or asset.asset.name.endswith('svg'):
376 377
        return redirect(asset.asset.url)
377 378

  
378 379
    # get or create thumbnail and return url
379 380
    return redirect(get_thumbnail(asset.asset, geometry_string, **thumb_options).url)
381

  
382

  
383
def ajax_disk_space_usage(request):
384
    response = StreamingHttpResponse(ajax_disk_space_usage_generator())
385
    response['X-Accel-Buffering'] = 'no'
386
    return response
387

  
388

  
389
def ajax_disk_space_usage_generator():
390
    media_prefix = default_storage.path('')
391
    start = time.time()
392
    total = 0
393
    units = ['Bytes', 'Ko', 'Mo', 'Go']
394

  
395
    def get_message(size):
396
        unit = 0
397
        while unit < 3 and size > 1024:
398
            size = int(size / 1024)
399
            unit += 1
400
        return "<message>(%s %s)</message>" % (size, units[unit])
401

  
402
    for basedir, dirnames, filenames in os.walk(media_prefix):
403
        for filename in filenames:
404
            time.sleep(0.5)  # to test progression (to remove)
405
            total += os.stat(os.path.join(basedir, filename)).st_size
406
            if time.time() - start > 0.5:
407
                yield get_message(total)
408
    yield get_message(total)
combo/manager/forms.py
188 188
            self.instance.restricted_to_unlogged = True
189 189
            self.instance.groups.set(self.cleaned_data['groups'])
190 190
        self.instance.save()
191 191
        return self.instance
192 192

  
193 193

  
194 194
class SiteImportForm(forms.Form):
195 195
    site_file = forms.FileField(label=_('Site Export File'))
196

  
197

  
198
class SiteExportForm(forms.Form):
199
    include_asset = forms.BooleanField(label=_('Include assets into the export'), required=False)
combo/manager/templates/combo/site_export.html
3 3

  
4 4
{% block appbar %}
5 5
<h2>{% trans "Site Export" %}</h2>
6 6
{% endblock %}
7 7

  
8 8
{% block content %}
9 9
<form method="post">
10 10
  {% csrf_token %}
11
  {{ form.as_p }}
11
  <p>
12
    <input type="checkbox" name="include_asset" id="id_include_asset">
13
    {% trans 'Include assets into the export' %}
14
    <span id="asset-disk-space-usage-message"></span>
15
    </input>
16
  </p>
12 17
  <div class="buttons">
13 18
    <button>{% trans 'Export' %}</button>
14 19
    <a class="cancel" href="{% url 'combo-manager-homepage' %}">{% trans 'Cancel' %}</a>
15 20
  </div>
21
  <script>
22
    function renderMessage(text) {
23
      document.getElementById("asset-disk-space-usage-message").innerHTML = text;
24
    }
25

  
26
    $(document).ready(function() {
27
      var xhReq = new XMLHttpRequest();
28
      var nextReadPos = 0;
29

  
30
      function pollLatestResponse() {
31
        var allMessages = xhReq.responseText;
32
        do {
33
          var unprocessed = allMessages.substring(nextReadPos);
34
          var messageXMLEndIndex = unprocessed.indexOf("</message>");
35
          if (messageXMLEndIndex!=-1) {
36
            var endOfFirstMessageIndex = messageXMLEndIndex + "</message>".length;
37
            var anUpdate = unprocessed.substring(0, endOfFirstMessageIndex);
38
            renderMessage(anUpdate);
39
            nextReadPos += endOfFirstMessageIndex;
40
          }
41
        } while (messageXMLEndIndex != -1);
42
      }
43

  
44
      xhReq.open("GET", "{% url 'combo-assets-ajax-disk-space-usage' %}", true);
45
      xhReq.send(null);
46
      pollTimer = setInterval(pollLatestResponse, 500);
47
    })
48
  </script>
16 49
</form>
17 50
{% endblock %}
combo/manager/views.py
39 39
        CreateView, UpdateView, ListView, DeleteView, FormView, TemplateView)
40 40

  
41 41
from combo.data.models import Page, CellBase, ParentContentCell, PageSnapshot, LinkListCell
42 42
from combo.data.library import get_cell_class
43 43
from combo.data.utils import (export_site, export_site_tar, import_site, import_site_tar,
44 44
        ImportSiteError, MissingGroups)
45 45
from combo import plugins
46 46

  
47
from .forms import (PageEditTitleForm, PageVisibilityForm, SiteImportForm, SiteExportForm,
47
from .forms import (PageEditTitleForm, PageVisibilityForm, SiteImportForm,
48 48
        PageEditRedirectionForm, PageSelectTemplateForm, PageEditSlugForm,
49 49
        PageEditPictureForm, PageEditIncludeInNavigationForm,
50 50
        PageEditDescriptionForm, CellVisibilityForm, PageDuplicateForm)
51 51

  
52 52

  
53 53
class HomepageView(ListView):
54 54
    model = Page
55 55
    template_name = 'combo/manager_home.html'
......
60 60
        context['extra_actions'] = plugins.get_extra_manager_actions()
61 61
        context['collapse_pages'] = settings.COMBO_MANAGE_HOME_COLLAPSE_PAGES
62 62
        return context
63 63

  
64 64

  
65 65
homepage = HomepageView.as_view()
66 66

  
67 67

  
68
class SiteExportView(FormView):
69
    form_class = SiteExportForm
68
class SiteExportView(TemplateView):
70 69
    template_name = 'combo/site_export.html'
71 70

  
72 71
    def post(self, request, *args, **kwargs):
73 72
        if request.POST.get('include_asset'):
74 73
            fd = BytesIO()
75 74
            export_site_tar(fd)
76 75
            response = HttpResponse(content=fd.getvalue(), content_type='application/x-tar')
77 76
            response['Content-Disposition'] = 'attachment; filename="site-export.tar"'
78
-