Projet

Général

Profil

0001-manager-add-site-export-48100.patch

Valentin Deniaud, 17 novembre 2020 17:44

Télécharger (8,03 ko)

Voir les différences:

Subject: [PATCH] manager: add site export (#48100)

 chrono/manager/forms.py                       |  7 +++++
 .../templates/chrono/agendas_export.html      | 22 +++++++++++++
 .../templates/chrono/manager_home.html        |  6 +++-
 chrono/manager/urls.py                        |  1 +
 chrono/manager/utils.py                       | 12 ++++---
 chrono/manager/views.py                       | 25 ++++++++++++++-
 tests/test_manager.py                         | 31 +++++++++++++++++++
 7 files changed, 97 insertions(+), 7 deletions(-)
 create mode 100644 chrono/manager/templates/chrono/agendas_export.html
chrono/manager/forms.py
596 596
        if cleaned_data['days'] and not (cleaned_data['send_email'] or cleaned_data.get('send_sms')):
597 597
            raise ValidationError(_('Select at least one notification medium.'))
598 598
        return cleaned_data
599

  
600

  
601
class AgendasExportForm(forms.Form):
602
    agendas = forms.BooleanField(label=_('Agendas'), required=False, initial=True)
603
    unavailability_calendars = forms.BooleanField(
604
        label=_('Unavailability calendars'), required=False, initial=True
605
    )
chrono/manager/templates/chrono/agendas_export.html
1
{% extends "chrono/manager_home.html" %}
2
{% load i18n %}
3

  
4
{% block breadcrumb %}
5
{{ block.super }}
6
<a href="{% url 'chrono-manager-agendas-import' %}">{% trans 'Export' %}</a>
7
{% endblock %}
8

  
9
{% block appbar %}
10
<h2>{% trans "Export" %}</h2>
11
{% endblock %}
12

  
13
{% block content %}
14
<form method="post" enctype="multipart/form-data">
15
  {% csrf_token %}
16
  {{ form.as_p }}
17
  <div class="buttons">
18
    <button class="submit-button">{% trans "Export" %}</button>
19
    <a class="cancel" href="{% url 'chrono-manager-homepage' %}">{% trans 'Cancel' %}</a>
20
  </div>
21
</form>
22
{% endblock %}
chrono/manager/templates/chrono/manager_home.html
5 5
<h2>{% trans 'Agendas' %}</h2>
6 6
<span class="actions">
7 7
{% if user.is_staff %}
8
  <a class="extra-actions-menu-opener"></a>
9
  <ul class="extra-actions-menu">
10
    <li><a rel="popup" href="{% url 'chrono-manager-agendas-import' %}">{% trans 'Import' %}</a></li>
11
    <li><a rel="popup" href="{% url 'chrono-manager-agendas-export' %}">{% trans 'Export' %}</a></li>
12
  </ul>
8 13
<a href="{% url 'chrono-manager-category-list' %}">{% trans 'Categories' %}</a>
9 14
{% endif %}
10 15
<a href="{% url 'chrono-manager-unavailability-calendar-list' %}">{% trans 'Unavailability calendars' %}</a>
11 16
{% if user.is_staff %}
12 17
<a href="{% url 'chrono-manager-resource-list' %}">{% trans 'Resources' %}</a>
13
<a rel="popup" href="{% url 'chrono-manager-agendas-import' %}">{% trans 'Import' %}</a>
14 18
<a rel="popup" href="{% url 'chrono-manager-agenda-add' %}">{% trans 'New' %}</a>
15 19
{% endif %}
16 20
</span>
chrono/manager/urls.py
81 81
    url(r'^category/(?P<pk>\d+)/delete/$', views.category_delete, name='chrono-manager-category-delete'),
82 82
    url(r'^agendas/add/$', views.agenda_add, name='chrono-manager-agenda-add'),
83 83
    url(r'^agendas/import/$', views.agendas_import, name='chrono-manager-agendas-import'),
84
    url(r'^agendas/export/$', views.agendas_export, name='chrono-manager-agendas-export'),
84 85
    url(r'^agendas/(?P<pk>\d+)/$', views.agenda_view, name='chrono-manager-agenda-view'),
85 86
    url(
86 87
        r'^agendas/(?P<pk>\d+)/month/$',
chrono/manager/utils.py
24 24
from chrono.agendas.models import Agenda, AgendaImportError, UnavailabilityCalendar
25 25

  
26 26

  
27
def export_site():
27
def export_site(agendas=True, unavailability_calendars=True):
28 28
    '''Dump site objects to JSON-dumpable dictionnary'''
29 29
    data = collections.OrderedDict()
30
    data['unavailability_calendars'] = [x.export_json() for x in UnavailabilityCalendar.objects.all()]
31
    qs1 = Agenda.objects.filter(~Q(kind='virtual'))
32
    qs2 = Agenda.objects.filter(kind='virtual')
33
    data['agendas'] = [x.export_json() for x in itertools.chain(qs1, qs2)]
30
    if unavailability_calendars:
31
        data['unavailability_calendars'] = [x.export_json() for x in UnavailabilityCalendar.objects.all()]
32
    if agendas:
33
        qs1 = Agenda.objects.filter(~Q(kind='virtual'))
34
        qs2 = Agenda.objects.filter(kind='virtual')
35
        data['agendas'] = [x.export_json() for x in itertools.chain(qs1, qs2)]
34 36
    return data
35 37

  
36 38

  
chrono/manager/views.py
98 98
    AgendaReminderForm,
99 99
    UnavailabilityCalendarAddForm,
100 100
    UnavailabilityCalendarEditForm,
101
    AgendasExportForm,
101 102
)
102
from .utils import import_site
103
from .utils import import_site, export_site
103 104

  
104 105
FUTURE_BOOKING_ERROR_MSG = _('This cannot be removed as there are bookings for a future date.')
105 106

  
......
119 120
homepage = HomepageView.as_view()
120 121

  
121 122

  
123
class AgendasExportView(FormView):
124
    form_class = AgendasExportForm
125
    template_name = 'chrono/agendas_export.html'
126

  
127
    def dispatch(self, request, *args, **kwargs):
128
        if not request.user.is_staff:
129
            raise PermissionDenied()
130
        return super().dispatch(request, *args, **kwargs)
131

  
132
    def form_valid(self, form):
133
        response = HttpResponse(content_type='application/json')
134
        today = datetime.date.today()
135
        response['Content-Disposition'] = 'attachment; filename="export_agendas_{}.json"'.format(
136
            today.strftime('%Y%m%d')
137
        )
138
        json.dump(export_site(**form.cleaned_data), response, indent=2)
139
        return response
140

  
141

  
142
agendas_export = AgendasExportView.as_view()
143

  
144

  
122 145
class ResourceListView(ListView):
123 146
    template_name = 'chrono/manager_resource_list.html'
124 147
    model = Resource
tests/test_manager.py
5072 5072
    unavailability_calendar.edit_role = group
5073 5073
    unavailability_calendar.save()
5074 5074
    app.get(url)
5075

  
5076

  
5077
def test_export_site(app, admin_user):
5078
    login(app)
5079
    resp = app.get('/manage/')
5080
    resp = resp.click('Export')
5081

  
5082
    with freezegun.freeze_time('2020-06-15'):
5083
        resp = resp.form.submit()
5084
    assert resp.headers['content-type'] == 'application/json'
5085
    assert resp.headers['content-disposition'] == 'attachment; filename="export_agendas_20200615.json"'
5086

  
5087
    site_json = json.loads(resp.text)
5088
    assert site_json == {'unavailability_calendars': [], 'agendas': []}
5089

  
5090
    agenda = Agenda.objects.create(label=u'Foo Bar', kind='events')
5091
    unavailability_calendar = UnavailabilityCalendar.objects.create(label='Calendar 1')
5092
    resp = app.get('/manage/agendas/export/')
5093
    resp = resp.form.submit()
5094

  
5095
    site_json = json.loads(resp.text)
5096
    assert len(site_json['agendas']) == 1
5097
    assert len(site_json['unavailability_calendars']) == 1
5098

  
5099
    resp = app.get('/manage/agendas/export/')
5100
    resp.form['agendas'] = False
5101
    resp = resp.form.submit()
5102

  
5103
    site_json = json.loads(resp.text)
5104
    assert 'agendas' not in site_json
5105
    assert 'unavailability_calendars' in site_json
5075
-