From 0c9409fd4bc7346f46a127e780a32c3d83330a1f Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO <yohann.danello@gmail.com>
Date: Sat, 18 Apr 2020 03:27:12 +0200
Subject: [PATCH] Improve WEI UI

---
 apps/permission/views.py                | 27 ++++++++++++++++--
 apps/wei/models.py                      | 11 ++++++++
 apps/wei/urls.py                        |  3 +-
 apps/wei/views.py                       | 37 ++++++++++++++++++++++---
 templates/base.html                     |  2 +-
 templates/wei/weiclub_info.html         | 27 ++++++++++--------
 templates/wei/weiclub_tables.html       | 10 +++++++
 templates/wei/weiregistration_form.html | 10 +++++--
 8 files changed, 105 insertions(+), 22 deletions(-)

diff --git a/apps/permission/views.py b/apps/permission/views.py
index bbd9872f..2e41810d 100644
--- a/apps/permission/views.py
+++ b/apps/permission/views.py
@@ -1,11 +1,34 @@
 # Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
 # SPDX-License-Identifier: GPL-3.0-or-later
 
-from permission.backends import PermissionBackend
+from django.forms import HiddenInput
+from django.views.generic import UpdateView
+
+from .backends import PermissionBackend
 
 
 class ProtectQuerysetMixin:
+    """
+    Ensure that the user has the right to see or update objects.
+    Display 404 error if the user can't see an object, remove the fields the user can't
+    update on an update form (useful if the user can't change only specified fields).
+    """
     def get_queryset(self, **kwargs):
         qs = super().get_queryset(**kwargs)
-
         return qs.filter(PermissionBackend.filter_queryset(self.request.user, qs.model, "view"))
+
+    def get_form(self, form_class=None):
+        form = super().get_form(form_class)
+
+        if not isinstance(self, UpdateView):
+            return form
+
+        # If we are in an UpdateView, we display only the fields the user has right to see.
+        # No worry if the user change the hidden fields: a 403 error will be performed if the user tries to make
+        # a custom request.
+        # We could also delete the field, but some views might be affected.
+        for key in form.base_fields:
+            if not PermissionBackend.check_perm(self.request.user, "wei.change_weiregistration_" + key, self.object):
+                form.fields[key].widget = HiddenInput()
+
+        return form
diff --git a/apps/wei/models.py b/apps/wei/models.py
index b45f31c3..a4377acc 100644
--- a/apps/wei/models.py
+++ b/apps/wei/models.py
@@ -27,6 +27,10 @@ class WEIClub(Club):
         verbose_name=_("date end"),
     )
 
+    @property
+    def is_current_wei(self):
+        return not WEIClub.objects.filter(date_start__gt=self.date_start).exists()
+
     def update_membership_dates(self):
         """
         We can't join the WEI next years.
@@ -216,6 +220,13 @@ class WEIRegistration(models.Model):
         """
         self.information_json = json.dumps(information)
 
+    @property
+    def is_validated(self):
+        try:
+            return self.membership is not None
+        except KeyError:
+            return False
+
     def __str__(self):
         return str(self.user)
 
diff --git a/apps/wei/urls.py b/apps/wei/urls.py
index cf5b2c49..6f8ddbdc 100644
--- a/apps/wei/urls.py
+++ b/apps/wei/urls.py
@@ -3,13 +3,14 @@
 
 from django.urls import path
 
-from .views import WEIListView, WEICreateView, WEIDetailView, WEIUpdateView,\
+from .views import CurrentWEIDetailView, WEIListView, WEICreateView, WEIDetailView, WEIUpdateView,\
     BusCreateView, BusManageView, BusUpdateView, BusTeamCreateView, BusTeamManageView, BusTeamUpdateView,\
     WEIRegister1AView, WEIRegister2AView, WEIUpdateRegistrationView, WEIValidateRegistrationView
 
 
 app_name = 'wei'
 urlpatterns = [
+    path('detail/', CurrentWEIDetailView.as_view(), name="current_wei_detail"),
     path('list/', WEIListView.as_view(), name="wei_list"),
     path('create/', WEICreateView.as_view(), name="wei_create"),
     path('detail/<int:pk>/', WEIDetailView.as_view(), name="wei_detail"),
diff --git a/apps/wei/views.py b/apps/wei/views.py
index 02153f22..11db686a 100644
--- a/apps/wei/views.py
+++ b/apps/wei/views.py
@@ -6,8 +6,9 @@ from datetime import datetime, date
 from django.contrib.auth.mixins import LoginRequiredMixin
 from django.contrib.auth.models import User
 from django.db.models import Q
+from django.shortcuts import redirect
 from django.urls import reverse_lazy
-from django.views.generic import DetailView, UpdateView, CreateView
+from django.views.generic import DetailView, UpdateView, CreateView, View
 from django.utils.translation import gettext_lazy as _
 from django_tables2 import SingleTableView
 from member.models import Membership, Club
@@ -21,12 +22,19 @@ from .forms import WEIForm, WEIRegistrationForm, BusForm, BusTeamForm, WEIMember
 from .tables import WEITable, WEIRegistrationTable, BusTable, BusTeamTable, WEIMembershipTable
 
 
+class CurrentWEIDetailView(LoginRequiredMixin, View):
+    def get(self, *args, **kwargs):
+        wei = WEIClub.objects.order_by('date_start').last()
+        return redirect(reverse_lazy('wei:wei_detail', args=(wei.pk,)))
+
+
 class WEIListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
     """
     List existing WEI
     """
     model = WEIClub
     table_class = WEITable
+    ordering = '-year'
 
 
 class WEICreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
@@ -85,6 +93,13 @@ class WEIDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
         pre_registrations_table.paginate(per_page=20, page=self.request.GET.get('membership-page', 1))
         context['pre_registrations'] = pre_registrations_table
 
+        my_registration = WEIRegistration.objects.filter(wei=club, user=self.request.user)
+        if my_registration.exists():
+            my_registration = my_registration.get()
+        else:
+            my_registration = None
+        context["my_registration"] = my_registration
+
         buses = Bus.objects.filter(PermissionBackend.filter_queryset(self.request.user, Bus, "view"))\
             .filter(wei=self.object)
         bus_table = BusTable(data=buses, prefix="bus-")
@@ -98,8 +113,14 @@ class WEIDetailView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
             date_end=datetime.now().date(),
             fee=0,
         )
-        context["can_add_members"] = PermissionBackend() \
-            .has_perm(self.request.user, "member.add_membership", empty_membership)
+        context["can_add_members"] = PermissionBackend \
+            .check_perm(self.request.user, "member.add_membership", empty_membership)
+
+        empty_bus = Bus(
+            wei=club,
+            name="",
+        )
+        context["can_add_bus"] = PermissionBackend.check_perm(self.request.user, "wei.add_bus", empty_bus)
 
         return context
 
@@ -261,6 +282,7 @@ class WEIRegister1AView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
     def get_context_data(self, **kwargs):
         context = super().get_context_data(**kwargs)
         context['title'] = _("Register 1A")
+        context['club'] = WEIClub.objects.get(pk=self.kwargs["wei_pk"])
         return context
 
     def get_form(self, form_class=None):
@@ -291,6 +313,7 @@ class WEIRegister2AView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
     def get_context_data(self, **kwargs):
         context = super().get_context_data(**kwargs)
         context['title'] = _("Register 2A+")
+        context['club'] = WEIClub.objects.get(pk=self.kwargs["wei_pk"])
         return context
 
     def get_form(self, form_class=None):
@@ -319,9 +342,15 @@ class WEIUpdateRegistrationView(ProtectQuerysetMixin, LoginRequiredMixin, Update
     model = WEIRegistration
     form_class = WEIRegistrationForm
 
+    def get_context_data(self, **kwargs):
+        context = super().get_context_data(**kwargs)
+        context["club"] = self.object.wei
+        return context
+
     def get_form(self, form_class=None):
         form = super().get_form(form_class)
-        del form.fields["user"]
+        if "user" in form.fields:
+            del form.fields["user"]
         return form
 
     def get_success_url(self):
diff --git a/templates/base.html b/templates/base.html
index 810927f9..f39f9bad 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -112,7 +112,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
                     </li>
                 {% endif %}
                 <li class="nav-item active">
-                    <a class="nav-link" href="{% url 'wei:wei_list' %}"><i class="fa fa-bus"></i> {% trans 'WEI' %}</a>
+                    <a class="nav-link" href="{% url 'wei:current_wei_detail' %}"><i class="fa fa-bus"></i> {% trans 'WEI' %}</a>
                 </li>
             </ul>
             <ul class="navbar-nav ml-auto">
diff --git a/templates/wei/weiclub_info.html b/templates/wei/weiclub_info.html
index 94bde15d..7f1803d9 100644
--- a/templates/wei/weiclub_info.html
+++ b/templates/wei/weiclub_info.html
@@ -54,19 +54,24 @@
         </dl>
     </div>
     <div class="card-footer text-center">
-        {% if can_add_members %}
-            <a class="btn btn-primary btn-sm my-1" href="{% url 'wei:wei_register_1A' wei_pk=club.pk %}"> {% trans "Register 1A" %}</a>
-            <a class="btn btn-primary btn-sm my-1" href="{% url 'wei:wei_register_2A' wei_pk=club.pk %}"> {% trans "Register 2A+" %}</a>
-        {% endif %}
-        {% if ".change_"|has_perm:club %}
-            <a class="btn btn-primary btn-sm my-1" href="{% url 'wei:wei_update' pk=club.pk %}"> {% trans "Edit" %}</a>
-        {% endif %}
         {% if True %}
-            <a class="btn btn-primary btn-sm my-1" href="{% url 'wei:add_bus' pk=club.pk %}"> {% trans "Add bus" %}</a>
+            <a class="btn btn-primary btn-sm my-1" href="{% url 'wei:wei_list' %}"> {% trans "WEI list" %}</a>
+        {% endif %}
+        {% if club.is_current_wei %}
+            {% if can_add_members %}
+                <a class="btn btn-primary btn-sm my-1" href="{% url 'wei:wei_register_1A' wei_pk=club.pk %}"> {% trans "Register 1A" %}</a>
+                <a class="btn btn-primary btn-sm my-1" href="{% url 'wei:wei_register_2A' wei_pk=club.pk %}"> {% trans "Register 2A+" %}</a>
+            {% endif %}
+            {% if "wei.change_"|has_perm:club %}
+                <a class="btn btn-primary btn-sm my-1" href="{% url 'wei:wei_update' pk=club.pk %}"> {% trans "Edit" %}</a>
+            {% endif %}
+            {% if can_add_bus %}
+                <a class="btn btn-primary btn-sm my-1" href="{% url 'wei:add_bus' pk=club.pk %}"> {% trans "Add bus" %}</a>
+            {% endif %}
+            {% url 'wei:wei_detail' club.pk as club_detail_url %}
+            {%if request.path_info != club_detail_url %}
+                <a class="btn btn-primary btn-sm my-1" href="{{ club_detail_url }}">{% trans 'View WEI' %}</a>
         {% endif %}
-        {% url 'wei:wei_detail' club.pk as club_detail_url %}
-        {%if request.path_info != club_detail_url %}
-            <a class="btn btn-primary btn-sm my-1" href="{{ club_detail_url }}">{% trans 'View WEI' %}</a>
         {% endif %}
     </div>
 </div>
diff --git a/templates/wei/weiclub_tables.html b/templates/wei/weiclub_tables.html
index 4dd2a0de..7f59a0b6 100644
--- a/templates/wei/weiclub_tables.html
+++ b/templates/wei/weiclub_tables.html
@@ -55,6 +55,16 @@
             in iaculis. Neque gravida in fermentum et sollicitudin ac orci.
         </p>
     </div>
+
+    {% if club.is_current_wei %}
+        <div class="card-footer text-center">
+            {% if not my_registration %}
+                <a href="{% url "wei:wei_register_1A" wei_pk=club.pk %}"><button class="btn btn-success">{% trans "Register to the WEI!" %}</button></a>
+            {% elif my_registration.is_validated %}
+                <a href="{% url "wei:wei_update_registration" pk=user.pk %}"><button class="btn btn-warning">{% trans "Update my registration" %}</button></a>
+            {% endif %}
+        </div>
+    {% endif %}
 </div>
 
 <hr>
diff --git a/templates/wei/weiregistration_form.html b/templates/wei/weiregistration_form.html
index ea29d966..21f57a77 100644
--- a/templates/wei/weiregistration_form.html
+++ b/templates/wei/weiregistration_form.html
@@ -1,8 +1,12 @@
-{% extends "base.html" %}
-{% load static %}
+{% extends "member/noteowner_detail.html" %}
 {% load i18n %}
 {% load crispy_forms_tags %}
-{% block content %}
+
+{% block profile_info %}
+{% include "wei/weiclub_info.html" %}
+{% endblock %}
+
+{% block profile_content %}
 <form method="post">
 {% csrf_token %}
 {{ form|crispy }}
-- 
GitLab