From d35fcf6f41d21dd2110e5d9a396c58de4f03c897 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laur=C3=A9line=20Gu=C3=A9rin?= <zebuline@entrouvert.com>
Date: Mon, 20 Jun 2022 17:37:18 +0200
Subject: [PATCH] manager: use sidetabs in shared custody agenda settings
 (#66409)

---
 ...anager_shared_custody_agenda_settings.html | 140 +++++++++---------
 chrono/manager/views.py                       |  12 +-
 tests/manager/test_shared_custody_agenda.py   |  36 +++--
 3 files changed, 112 insertions(+), 76 deletions(-)

diff --git a/chrono/manager/templates/chrono/manager_shared_custody_agenda_settings.html b/chrono/manager/templates/chrono/manager_shared_custody_agenda_settings.html
index 7c035d80..56960971 100644
--- a/chrono/manager/templates/chrono/manager_shared_custody_agenda_settings.html
+++ b/chrono/manager/templates/chrono/manager_shared_custody_agenda_settings.html
@@ -18,84 +18,92 @@
 {% endblock %}
 
 {% block content %}
+
 {% if not agenda.is_complete %}
 <div class="warningnotice">
 <p>{% trans "Custody rules are not complete." %}</p>
 </div>
 {% endif %}
-<div class="section">
-  <h3>{% trans "Custody rules" %}</h3>
-  <div>
-    {% if agenda.rules.all %}
-    <ul class="objects-list single-links">
-      {% for rule in agenda.rules.all %}
-      <li><a rel="popup" href="{% url 'chrono-manager-shared-custody-agenda-edit-rule' pk=agenda.pk rule_pk=rule.pk %}">
-          <span class="rule-info">
-            {{ rule.guardian }}, {{ rule.label }}
-          </span>
-        </a>
-        <a rel="popup" class="delete" href="{% url 'chrono-manager-shared-custody-agenda-delete-rule' pk=agenda.pk rule_pk=rule.pk %}?next=settings">{% trans "remove" %}</a>
-      </li>
-      {% endfor %}
-    </ul>
-    {% else %}
-    <div class="big-msg-info">
-      {% blocktrans trimmed %}
-      This agenda doesn't have any custody rules yet.
-      {% endblocktrans %}
-    </div>
+
+<div class="section agenda-settings">
+<div class="pk-tabs">
+  <div class="pk-tabs--tab-list" role="tablist">
+    <button aria-controls="panel-rules" aria-selected="true" id="tab-rules" role="tab" tabindex="0">{% trans "Custody rules" %}</button>
+    {% if has_holidays %}
+    <button aria-controls="panel-holidays" aria-selected="false" id="tab-holidays" role="tab" tabindex="-1">{% trans "Custody rules during holidays" %}</button>
     {% endif %}
+    <button aria-controls="panel-time-periods" aria-selected="false" id="tab-time-periods" role="tab" tabindex="-1">{% trans "Exceptional custody periods" %}</button>
   </div>
-</div>
+  <div class="pk-tabs--container">
 
-{% if has_holidays %}
-<div class="section">
-  <h3>{% trans "Custody rules during holidays" %}</h3>
-  <div>
-    {% if agenda.holiday_rules.all %}
-    <ul class="objects-list single-links">
-      {% for rule in agenda.holiday_rules.all %}
-      <li><a rel="popup" href="{% url 'chrono-manager-shared-custody-agenda-edit-holiday-rule' pk=agenda.pk rule_pk=rule.pk %}">
-          <span class="rule-info">
-            {{ rule.guardian }}, {{ rule.label }}
-          </span>
-        </a>
-        <a rel="popup" class="delete" href="{% url 'chrono-manager-shared-custody-agenda-delete-holiday-rule' pk=agenda.pk rule_pk=rule.pk %}?next=settings">{% trans "remove" %}</a>
-      </li>
-      {% endfor %}
-    </ul>
-    {% else %}
-    <div class="big-msg-info">
-      {% blocktrans trimmed %}
-      This agenda doesn't specify any custody rules during holidays. It means normal rules will be applied.
-      {% endblocktrans %}
+    <div aria-labelledby="tab-rules" id="panel-rules" role="tabpanel" tabindex="0">
+      {% if agenda.rules.all %}
+      <ul class="objects-list single-links">
+        {% for rule in agenda.rules.all %}
+        <li><a rel="popup" href="{% url 'chrono-manager-shared-custody-agenda-edit-rule' pk=agenda.pk rule_pk=rule.pk %}">
+            <span class="rule-info">
+              {{ rule.guardian }}, {{ rule.label }}
+            </span>
+          </a>
+          <a rel="popup" class="delete" href="{% url 'chrono-manager-shared-custody-agenda-delete-rule' pk=agenda.pk rule_pk=rule.pk %}?next=settings">{% trans "remove" %}</a>
+        </li>
+        {% endfor %}
+      </ul>
+      {% else %}
+      <div class="big-msg-info">
+        {% blocktrans trimmed %}
+        This agenda doesn't have any custody rules yet.
+        {% endblocktrans %}
+      </div>
+      {% endif %}
     </div>
-    {% endif %}
-  </div>
-</div>
-{% endif %}
 
-<div class="section">
-  <h3>{% trans "Exceptional custody periods" %}</h3>
-  <div>
-    {% if exceptional_periods %}
-    <ul class="objects-list single-links">
-      {% for period in exceptional_periods %}
-      <li>
-        <a rel="popup" href="{% url 'chrono-manager-shared-custody-agenda-edit-period' pk=agenda.pk period_pk=period.pk %}">
-          {{ period }}
-          <a rel="popup" class="delete" href="{% url 'chrono-manager-shared-custody-agenda-delete-period' pk=agenda.pk period_pk=period.pk %}?next=settings">{% trans "remove" %}</a>
-        </a>
-      </li>
-      {% endfor %}
-    </ul>
-    {% else %}
-    <div class="big-msg-info">
-      {% blocktrans trimmed %}
-      This agenda doesn't have any custody period. They can be used to specify explicit moments when one of the guardian should have custody, regardless of global rules.
-      {% endblocktrans %}
+    {% if has_holidays %}
+    <div aria-labelledby="tab-holidays" hidden="" id="panel-holidays" role="tabpanel" tabindex="0">
+      {% if agenda.holiday_rules.all %}
+      <ul class="objects-list single-links">
+        {% for rule in agenda.holiday_rules.all %}
+        <li><a rel="popup" href="{% url 'chrono-manager-shared-custody-agenda-edit-holiday-rule' pk=agenda.pk rule_pk=rule.pk %}">
+            <span class="rule-info">
+              {{ rule.guardian }}, {{ rule.label }}
+            </span>
+          </a>
+          <a rel="popup" class="delete" href="{% url 'chrono-manager-shared-custody-agenda-delete-holiday-rule' pk=agenda.pk rule_pk=rule.pk %}?next=settings">{% trans "remove" %}</a>
+        </li>
+        {% endfor %}
+      </ul>
+      {% else %}
+      <div class="big-msg-info">
+        {% blocktrans trimmed %}
+        This agenda doesn't specify any custody rules during holidays. It means normal rules will be applied.
+        {% endblocktrans %}
+      </div>
+      {% endif %}
     </div>
     {% endif %}
+
+    <div aria-labelledby="tab-time-periods" hidden="" id="panel-time-periods" role="tabpanel" tabindex="0">
+      {% if exceptional_periods %}
+      <ul class="objects-list single-links">
+        {% for period in exceptional_periods %}
+        <li>
+          <a rel="popup" href="{% url 'chrono-manager-shared-custody-agenda-edit-period' pk=agenda.pk period_pk=period.pk %}">
+            {{ period }}
+            <a rel="popup" class="delete" href="{% url 'chrono-manager-shared-custody-agenda-delete-period' pk=agenda.pk period_pk=period.pk %}?next=settings">{% trans "remove" %}</a>
+          </a>
+        </li>
+        {% endfor %}
+      </ul>
+      {% else %}
+      <div class="big-msg-info">
+        {% blocktrans trimmed %}
+        This agenda doesn't have any custody period. They can be used to specify explicit moments when one of the guardian should have custody, regardless of global rules.
+        {% endblocktrans %}
+      </div>
+      {% endif %}
+    </div>
+
   </div>
 </div>
+</div>
 {% endblock %}
diff --git a/chrono/manager/views.py b/chrono/manager/views.py
index 282abd49..3a776e85 100644
--- a/chrono/manager/views.py
+++ b/chrono/manager/views.py
@@ -3674,6 +3674,7 @@ unavailability_calendar_import_unavailabilities = UnavailabilityCalendarImportUn
 
 class SharedCustodyAgendaMixin:
     agenda = None
+    tab_anchor = None
 
     def set_agenda(self, **kwargs):
         self.agenda = get_object_or_404(SharedCustodyAgenda, id=kwargs.get('pk'))
@@ -3701,7 +3702,10 @@ class SharedCustodyAgendaMixin:
         return kwargs
 
     def get_success_url(self):
-        return reverse('chrono-manager-shared-custody-agenda-settings', kwargs={'pk': self.agenda.id})
+        url = reverse('chrono-manager-shared-custody-agenda-settings', kwargs={'pk': self.agenda.id})
+        if self.tab_anchor:
+            url += '#open:%s' % self.tab_anchor
+        return url
 
 
 class SharedCustodyAgendaView(SharedCustodyAgendaMixin, RedirectView):
@@ -3808,6 +3812,7 @@ class SharedCustodyAgendaAddHolidayRuleView(SharedCustodyAgendaMixin, CreateView
     template_name = 'chrono/manager_agenda_form.html'
     form_class = SharedCustodyHolidayRuleForm
     model = SharedCustodyHolidayRule
+    tab_anchor = 'holidays'
 
 
 shared_custody_agenda_add_holiday_rule = SharedCustodyAgendaAddHolidayRuleView.as_view()
@@ -3819,6 +3824,7 @@ class SharedCustodyAgendaEditHolidayRuleView(SharedCustodyAgendaMixin, UpdateVie
     form_class = SharedCustodyHolidayRuleForm
     model = SharedCustodyHolidayRule
     pk_url_kwarg = 'rule_pk'
+    tab_anchor = 'holidays'
 
 
 shared_custody_agenda_edit_holiday_rule = SharedCustodyAgendaEditHolidayRuleView.as_view()
@@ -3828,6 +3834,7 @@ class SharedCustodyAgendaDeleteHolidayRuleView(SharedCustodyAgendaMixin, DeleteV
     template_name = 'chrono/manager_confirm_delete.html'
     model = SharedCustodyHolidayRule
     pk_url_kwarg = 'rule_pk'
+    tab_anchor = 'holidays'
 
 
 shared_custody_agenda_delete_holiday_rule = SharedCustodyAgendaDeleteHolidayRuleView.as_view()
@@ -3838,6 +3845,7 @@ class SharedCustodyAgendaAddPeriodView(SharedCustodyAgendaMixin, CreateView):
     template_name = 'chrono/manager_agenda_form.html'
     form_class = SharedCustodyPeriodForm
     model = SharedCustodyPeriod
+    tab_anchor = 'time-periods'
 
 
 shared_custody_agenda_add_period = SharedCustodyAgendaAddPeriodView.as_view()
@@ -3849,6 +3857,7 @@ class SharedCustodyAgendaEditPeriodView(SharedCustodyAgendaMixin, UpdateView):
     form_class = SharedCustodyPeriodForm
     model = SharedCustodyPeriod
     pk_url_kwarg = 'period_pk'
+    tab_anchor = 'time-periods'
 
 
 shared_custody_agenda_edit_period = SharedCustodyAgendaEditPeriodView.as_view()
@@ -3858,6 +3867,7 @@ class SharedCustodyAgendaDeletePeriodView(SharedCustodyAgendaMixin, DeleteView):
     template_name = 'chrono/manager_confirm_delete.html'
     model = SharedCustodyPeriod
     pk_url_kwarg = 'period_pk'
+    tab_anchor = 'time-periods'
 
 
 shared_custody_agenda_delete_period = SharedCustodyAgendaDeletePeriodView.as_view()
diff --git a/tests/manager/test_shared_custody_agenda.py b/tests/manager/test_shared_custody_agenda.py
index b2ab2a54..10c30452 100644
--- a/tests/manager/test_shared_custody_agenda.py
+++ b/tests/manager/test_shared_custody_agenda.py
@@ -40,7 +40,9 @@ def test_shared_custody_agenda_settings_rules(app, admin_user):
     resp.form['guardian'] = father.pk
     resp.form['days'] = list(range(7))
     resp.form['weeks'] = 'even'
-    resp = resp.form.submit().follow()
+    resp = resp.form.submit()
+    assert resp.location.endswith('/manage/shared-custody/%s/settings/' % agenda.pk)
+    resp = resp.follow()
     assert 'Custody rules are not complete.' in resp.text
     assert 'John Doe, daily, on even weeks' in resp.text
 
@@ -55,7 +57,9 @@ def test_shared_custody_agenda_settings_rules(app, admin_user):
 
     resp = resp.click('John Doe, daily, on even weeks')
     resp.form['days'] = list(range(6))
-    resp = resp.form.submit().follow()
+    resp = resp.form.submit()
+    assert resp.location.endswith('/manage/shared-custody/%s/settings/' % agenda.pk)
+    resp = resp.follow()
     assert 'Custody rules are not complete.' in resp.text
 
     resp = resp.click('John Doe, from Monday to Saturday, on even weeks')
@@ -68,7 +72,9 @@ def test_shared_custody_agenda_settings_rules(app, admin_user):
     resp = resp.form.submit().follow()
 
     resp = resp.click('remove', index=1)
-    resp = resp.form.submit().follow()
+    resp = resp.form.submit()
+    assert resp.location.endswith('/manage/shared-custody/%s/settings/' % agenda.pk)
+    resp = resp.follow()
     assert SharedCustodyRule.objects.count() == 1
 
 
@@ -86,13 +92,17 @@ def test_shared_custody_agenda_settings_periods(app, admin_user):
     resp.form['guardian'] = father.pk
     resp.form['date_start'] = '2022-03-01'
     resp.form['date_end'] = '2022-03-03'
-    resp = resp.form.submit().follow()
+    resp = resp.form.submit()
+    assert resp.location.endswith('/manage/shared-custody/%s/settings/#open:time-periods' % agenda.pk)
+    resp = resp.follow()
     assert 'This agenda doesn\'t have any custody period.' not in resp.text
     assert 'John Doe, 03/01/2022 → 03/03/2022' in resp.text
 
     resp = resp.click('John Doe, 03/01/2022 → 03/03/2022')
     resp.form['guardian'] = mother.pk
-    resp = resp.form.submit().follow()
+    resp = resp.form.submit()
+    assert resp.location.endswith('/manage/shared-custody/%s/settings/#open:time-periods' % agenda.pk)
+    resp = resp.follow()
     assert 'Jane Doe, 03/01/2022 → 03/03/2022' in resp.text
 
     resp = resp.click('Add custody period')
@@ -109,7 +119,9 @@ def test_shared_custody_agenda_settings_periods(app, admin_user):
 
     resp = app.get('/manage/shared-custody/%s/settings/' % agenda.pk)
     resp = resp.click('remove', href='delete')
-    resp = resp.form.submit().follow()
+    resp = resp.form.submit()
+    assert resp.location.endswith('/manage/shared-custody/%s/settings/#open:time-periods' % agenda.pk)
+    resp = resp.follow()
     assert not SharedCustodyPeriod.objects.exists()
 
 
@@ -229,14 +241,18 @@ def test_shared_custody_agenda_holiday_rules(app, admin_user):
     resp.form['holiday'].select(text='Vacances de Noël')
     resp.form['years'] = 'odd'
     resp.form['periodicity'] = 'first-half'
-    resp = resp.form.submit().follow()
+    resp = resp.form.submit()
+    assert resp.location.endswith('/manage/shared-custody/%s/settings/#open:holidays' % agenda.pk)
+    resp = resp.follow()
     assert SharedCustodyHolidayRule.objects.count() == 1
     assert SharedCustodyPeriod.objects.count() == 3
     assert 'This agenda doesn\'t have any custody period.' in resp.text
 
     resp = resp.click('John Doe, Vacances de Noël, the first half, on odd years')
     resp.form['years'] = ''
-    resp = resp.form.submit().follow()
+    resp = resp.form.submit()
+    assert resp.location.endswith('/manage/shared-custody/%s/settings/#open:holidays' % agenda.pk)
+    resp = resp.follow()
     assert 'John Doe, Vacances de Noël, the first half' in resp.text
     assert SharedCustodyHolidayRule.objects.count() == 1
     assert SharedCustodyPeriod.objects.count() == 6
@@ -256,7 +272,9 @@ def test_shared_custody_agenda_holiday_rules(app, admin_user):
     assert SharedCustodyPeriod.objects.count() == 12
 
     resp = resp.click('remove', index=1)
-    resp = resp.form.submit().follow()
+    resp = resp.form.submit()
+    assert resp.location.endswith('/manage/shared-custody/%s/settings/#open:holidays' % agenda.pk)
+    resp = resp.follow()
     assert SharedCustodyHolidayRule.objects.count() == 1
     assert SharedCustodyPeriod.objects.count() == 6
 
-- 
2.35.1

