From 1827621cf5c8807a2b7ded0e50959d7f062e444c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laur=C3=A9line=20Gu=C3=A9rin?= <zebuline@entrouvert.com>
Date: Tue, 26 Jan 2021 11:34:10 +0100
Subject: [PATCH 06/11] manager: add button to switch desk management mode
 (#48924)

---
 .../chrono/manager_agenda_settings.html       |  1 +
 .../manager_meetings_agenda_settings.html     |  8 +++
 chrono/manager/urls.py                        |  5 ++
 chrono/manager/views.py                       | 29 +++++++++
 tests/test_manager.py                         | 59 ++++++++++++++++++-
 5 files changed, 101 insertions(+), 1 deletion(-)

diff --git a/chrono/manager/templates/chrono/manager_agenda_settings.html b/chrono/manager/templates/chrono/manager_agenda_settings.html
index c86ac70..5a04f4e 100644
--- a/chrono/manager/templates/chrono/manager_agenda_settings.html
+++ b/chrono/manager/templates/chrono/manager_agenda_settings.html
@@ -28,6 +28,7 @@
     {% if user.is_staff %}
       <li><a rel="popup" href="{% url 'chrono-manager-agenda-delete' pk=object.id %}">{% trans 'Delete' %}</a></li>
     {% endif %}
+    {% block agenda-extra-menu-actions %}{% endblock %}
   </ul>
 </span>
 {% endblock %}
diff --git a/chrono/manager/templates/chrono/manager_meetings_agenda_settings.html b/chrono/manager/templates/chrono/manager_meetings_agenda_settings.html
index 6af0775..eeb3d5b 100644
--- a/chrono/manager/templates/chrono/manager_meetings_agenda_settings.html
+++ b/chrono/manager/templates/chrono/manager_meetings_agenda_settings.html
@@ -18,6 +18,14 @@
   <a rel="popup" href="{% url 'chrono-manager-agenda-add-desk' pk=object.id %}">{% trans 'New Desk' %}</a>
 {% endblock %}
 
+{% block agenda-extra-menu-actions %}
+  {% if object.desk_simple_management %}
+  <li><a href="{% url 'chrono-manager-agenda-desk-management-toggle-view' pk=object.pk %}">{% trans 'Switch to invididual desk management' %}</a></li>
+  {% elif agenda_is_available_for_simple_management %}
+  <li><a href="{% url 'chrono-manager-agenda-desk-management-toggle-view' pk=object.pk %}">{% trans 'Switch to global desk management' %}</a></li>
+  {% endif %}
+{% endblock %}
+
 {% block agenda-settings %}
 
 <div class="section">
diff --git a/chrono/manager/urls.py b/chrono/manager/urls.py
index 80eb888..d122a39 100644
--- a/chrono/manager/urls.py
+++ b/chrono/manager/urls.py
@@ -115,6 +115,11 @@ urlpatterns = [
     url(r'^agendas/(?P<pk>\d+)/export$', views.agenda_export, name='chrono-manager-agenda-export'),
     url(r'^agendas/(?P<pk>\d+)/add-event$', views.agenda_add_event, name='chrono-manager-agenda-add-event'),
     url(r'^agendas/(?P<pk>\d+)/duplicate$', views.agenda_duplicate, name='chrono-manager-agenda-duplicate'),
+    url(
+        r'^agendas/(?P<pk>\d+)/desk-management-toggle$',
+        views.agenda_desk_management_toggle_view,
+        name='chrono-manager-agenda-desk-management-toggle-view',
+    ),
     url(
         r'^agendas/(?P<pk>\d+)/import-events$',
         views.agenda_import_events,
diff --git a/chrono/manager/views.py b/chrono/manager/views.py
index 1ba86d7..63fca93 100644
--- a/chrono/manager/views.py
+++ b/chrono/manager/views.py
@@ -1374,6 +1374,11 @@ class AgendaSettings(ManagedAgendaMixin, DetailView):
         if self.agenda.kind == 'meetings':
             context['has_resources'] = Resource.objects.exists()
             context['has_unavailability_calendars'] = UnavailabilityCalendar.objects.exists()
+            context['agenda_is_available_for_simple_management'] = (
+                self.object.is_available_for_simple_management()
+                if not self.object.desk_simple_management
+                else False
+            )
         return context
 
     def get_events(self):
@@ -1530,6 +1535,30 @@ class AgendaExportEventsView(ManagedAgendaMixin, View):
 agenda_export_events = AgendaExportEventsView.as_view()
 
 
+class AgendaDeskManagementToggleView(ManagedAgendaMixin, View):
+    agenda = None
+
+    def set_agenda(self, **kwargs):
+        self.agenda = get_object_or_404(Agenda, pk=kwargs.get('pk'), kind='meetings')
+
+    def get(self, request, *args, **kwargs):
+        message = None
+        if self.agenda.desk_simple_management:
+            self.agenda.desk_simple_management = False
+            self.agenda.save()
+            message = _('Desk individual management enabled.')
+        elif self.agenda.is_available_for_simple_management():
+            self.agenda.desk_simple_management = True
+            self.agenda.save()
+            message = _('Desk global management enabled.')
+        if message:
+            messages.info(self.request, message)
+        return HttpResponseRedirect(reverse('chrono-manager-agenda-settings', kwargs={'pk': self.agenda.pk}))
+
+
+agenda_desk_management_toggle_view = AgendaDeskManagementToggleView.as_view()
+
+
 class AgendaNotificationsSettingsView(ManagedAgendaMixin, UpdateView):
     template_name = 'chrono/manager_agenda_notifications_form.html'
     model = AgendaNotificationsSettings
diff --git a/tests/test_manager.py b/tests/test_manager.py
index 1ef3a6a..ec77755 100644
--- a/tests/test_manager.py
+++ b/tests/test_manager.py
@@ -1075,7 +1075,64 @@ def test_options_meetings_agenda_num_queries(app, admin_user, managers_group):
     app = login(app)
     with CaptureQueriesContext(connection) as ctx:
         app.get('/manage/agendas/%s/settings' % agenda.pk)
-        assert len(ctx.captured_queries) == 12
+        assert len(ctx.captured_queries) == 19
+
+
+@mock.patch('chrono.agendas.models.Agenda.is_available_for_simple_management')
+def test_agenda_options_desk_simple_management(available_mock, app, admin_user):
+    agenda = Agenda.objects.create(label=u'Foo bar', kind='meetings')
+    app = login(app)
+
+    available_mock.return_value = True
+    assert agenda.desk_simple_management is False
+    resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
+    assert '/manage/agendas/%s/desk-management-toggle' % agenda.pk in resp.text
+    agenda.desk_simple_management = True
+    agenda.save()
+    resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
+    assert '/manage/agendas/%s/desk-management-toggle' % agenda.pk in resp.text
+
+    available_mock.return_value = False
+    agenda.desk_simple_management = False
+    agenda.save()
+    resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
+    assert '/manage/agendas/%s/desk-management-toggle' % agenda.pk not in resp.text
+    agenda.desk_simple_management = True
+    agenda.save()
+    # always possible to disable this flag
+    resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
+    assert '/manage/agendas/%s/desk-management-toggle' % agenda.pk in resp.text
+
+    available_mock.return_value = True
+    for old_value in [True, False]:
+        agenda.desk_simple_management = old_value
+        agenda.save()
+        resp = app.get('/manage/agendas/%s/desk-management-toggle' % agenda.pk)
+        assert resp.location.endswith('/manage/agendas/%s/settings' % agenda.pk)
+        agenda.refresh_from_db()
+        # was changed
+        assert agenda.desk_simple_management is not old_value
+
+    available_mock.return_value = False
+    for old_value in [True, False]:
+        agenda.desk_simple_management = old_value
+        agenda.save()
+        resp = app.get('/manage/agendas/%s/desk-management-toggle' % agenda.pk)
+        assert resp.location.endswith('/manage/agendas/%s/settings' % agenda.pk)
+        agenda.refresh_from_db()
+        # not possible to enable flag
+        assert agenda.desk_simple_management is False
+
+    # unknown pk
+    app.get('/manage/agendas/0/desk-management-toggle', status=404)
+
+    # check kind
+    agenda.kind = 'events'
+    agenda.save()
+    app.get('/manage/agendas/%s/desk-management-toggle' % agenda.pk, status=404)
+    agenda.kind = 'virtual'
+    agenda.save()
+    app.get('/manage/agendas/%s/desk-management-toggle' % agenda.pk, status=404)
 
 
 def test_agenda_resources(app, admin_user):
-- 
2.29.2

