manager: add site export (#48100)

This commit is contained in:
Valentin Deniaud 2020-11-04 17:26:16 +01:00
parent f8c8415126
commit 3c344d80be
7 changed files with 97 additions and 7 deletions

View File

@ -596,3 +596,10 @@ class AgendaReminderForm(forms.ModelForm):
if cleaned_data['days'] and not (cleaned_data['send_email'] or cleaned_data.get('send_sms')):
raise ValidationError(_('Select at least one notification medium.'))
return cleaned_data
class AgendasExportForm(forms.Form):
agendas = forms.BooleanField(label=_('Agendas'), required=False, initial=True)
unavailability_calendars = forms.BooleanField(
label=_('Unavailability calendars'), required=False, initial=True
)

View File

@ -0,0 +1,22 @@
{% extends "chrono/manager_home.html" %}
{% load i18n %}
{% block breadcrumb %}
{{ block.super }}
<a href="{% url 'chrono-manager-agendas-import' %}">{% trans 'Export' %}</a>
{% endblock %}
{% block appbar %}
<h2>{% trans "Export" %}</h2>
{% endblock %}
{% block content %}
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<div class="buttons">
<button class="submit-button">{% trans "Export" %}</button>
<a class="cancel" href="{% url 'chrono-manager-homepage' %}">{% trans 'Cancel' %}</a>
</div>
</form>
{% endblock %}

View File

@ -5,12 +5,16 @@
<h2>{% trans 'Agendas' %}</h2>
<span class="actions">
{% if user.is_staff %}
<a class="extra-actions-menu-opener"></a>
<ul class="extra-actions-menu">
<li><a rel="popup" href="{% url 'chrono-manager-agendas-import' %}">{% trans 'Import' %}</a></li>
<li><a rel="popup" href="{% url 'chrono-manager-agendas-export' %}">{% trans 'Export' %}</a></li>
</ul>
<a href="{% url 'chrono-manager-category-list' %}">{% trans 'Categories' %}</a>
{% endif %}
<a href="{% url 'chrono-manager-unavailability-calendar-list' %}">{% trans 'Unavailability calendars' %}</a>
{% if user.is_staff %}
<a href="{% url 'chrono-manager-resource-list' %}">{% trans 'Resources' %}</a>
<a rel="popup" href="{% url 'chrono-manager-agendas-import' %}">{% trans 'Import' %}</a>
<a rel="popup" href="{% url 'chrono-manager-agenda-add' %}">{% trans 'New' %}</a>
{% endif %}
</span>

View File

@ -81,6 +81,7 @@ urlpatterns = [
url(r'^category/(?P<pk>\d+)/delete/$', views.category_delete, name='chrono-manager-category-delete'),
url(r'^agendas/add/$', views.agenda_add, name='chrono-manager-agenda-add'),
url(r'^agendas/import/$', views.agendas_import, name='chrono-manager-agendas-import'),
url(r'^agendas/export/$', views.agendas_export, name='chrono-manager-agendas-export'),
url(r'^agendas/(?P<pk>\d+)/$', views.agenda_view, name='chrono-manager-agenda-view'),
url(
r'^agendas/(?P<pk>\d+)/month/$',

View File

@ -24,13 +24,15 @@ from django.db.models import Q
from chrono.agendas.models import Agenda, AgendaImportError, UnavailabilityCalendar
def export_site():
def export_site(agendas=True, unavailability_calendars=True):
'''Dump site objects to JSON-dumpable dictionnary'''
data = collections.OrderedDict()
data['unavailability_calendars'] = [x.export_json() for x in UnavailabilityCalendar.objects.all()]
qs1 = Agenda.objects.filter(~Q(kind='virtual'))
qs2 = Agenda.objects.filter(kind='virtual')
data['agendas'] = [x.export_json() for x in itertools.chain(qs1, qs2)]
if unavailability_calendars:
data['unavailability_calendars'] = [x.export_json() for x in UnavailabilityCalendar.objects.all()]
if agendas:
qs1 = Agenda.objects.filter(~Q(kind='virtual'))
qs2 = Agenda.objects.filter(kind='virtual')
data['agendas'] = [x.export_json() for x in itertools.chain(qs1, qs2)]
return data

View File

@ -98,8 +98,9 @@ from .forms import (
AgendaReminderForm,
UnavailabilityCalendarAddForm,
UnavailabilityCalendarEditForm,
AgendasExportForm,
)
from .utils import import_site
from .utils import import_site, export_site
FUTURE_BOOKING_ERROR_MSG = _('This cannot be removed as there are bookings for a future date.')
@ -119,6 +120,28 @@ class HomepageView(ListView):
homepage = HomepageView.as_view()
class AgendasExportView(FormView):
form_class = AgendasExportForm
template_name = 'chrono/agendas_export.html'
def dispatch(self, request, *args, **kwargs):
if not request.user.is_staff:
raise PermissionDenied()
return super().dispatch(request, *args, **kwargs)
def form_valid(self, form):
response = HttpResponse(content_type='application/json')
today = datetime.date.today()
response['Content-Disposition'] = 'attachment; filename="export_agendas_{}.json"'.format(
today.strftime('%Y%m%d')
)
json.dump(export_site(**form.cleaned_data), response, indent=2)
return response
agendas_export = AgendasExportView.as_view()
class ResourceListView(ListView):
template_name = 'chrono/manager_resource_list.html'
model = Resource

View File

@ -5072,3 +5072,34 @@ def test_unavailability_calendar_delete_unavailability_permissions(app, manager_
unavailability_calendar.edit_role = group
unavailability_calendar.save()
app.get(url)
def test_export_site(app, admin_user):
login(app)
resp = app.get('/manage/')
resp = resp.click('Export')
with freezegun.freeze_time('2020-06-15'):
resp = resp.form.submit()
assert resp.headers['content-type'] == 'application/json'
assert resp.headers['content-disposition'] == 'attachment; filename="export_agendas_20200615.json"'
site_json = json.loads(resp.text)
assert site_json == {'unavailability_calendars': [], 'agendas': []}
agenda = Agenda.objects.create(label=u'Foo Bar', kind='events')
unavailability_calendar = UnavailabilityCalendar.objects.create(label='Calendar 1')
resp = app.get('/manage/agendas/export/')
resp = resp.form.submit()
site_json = json.loads(resp.text)
assert len(site_json['agendas']) == 1
assert len(site_json['unavailability_calendars']) == 1
resp = app.get('/manage/agendas/export/')
resp.form['agendas'] = False
resp = resp.form.submit()
site_json = json.loads(resp.text)
assert 'agendas' not in site_json
assert 'unavailability_calendars' in site_json