From 822853be6643e2a8fac6b987e1a7c84fdf8e5ae3 Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Mon, 13 Apr 2020 05:02:16 +0200 Subject: [PATCH] Add a bus --- apps/wei/api/serializers.py | 24 +++++++++++++- apps/wei/api/urls.py | 6 ++-- apps/wei/api/views.py | 28 ++++++++++++++-- apps/wei/forms.py | 32 +++++++++++++++++- apps/wei/tables.py | 45 ++++++++++++++++++++++++-- apps/wei/urls.py | 6 ++-- apps/wei/views.py | 33 +++++++++++++++++-- templates/member/noteowner_detail.html | 10 +++--- templates/wei/bus_form.html | 17 ++++++++++ templates/wei/weiclub_form.html | 24 ++++++++------ templates/wei/weiclub_info.html | 9 ++++-- templates/wei/weiclub_tables.html | 13 ++++++++ 12 files changed, 218 insertions(+), 29 deletions(-) create mode 100644 templates/wei/bus_form.html diff --git a/apps/wei/api/serializers.py b/apps/wei/api/serializers.py index 5b91e2b1..3312c87a 100644 --- a/apps/wei/api/serializers.py +++ b/apps/wei/api/serializers.py @@ -3,7 +3,7 @@ from rest_framework import serializers -from ..models import WEIClub +from ..models import WEIClub, Bus, BusTeam class WEIClubSerializer(serializers.ModelSerializer): @@ -15,3 +15,25 @@ class WEIClubSerializer(serializers.ModelSerializer): class Meta: model = WEIClub fields = '__all__' + + +class BusSerializer(serializers.ModelSerializer): + """ + REST API Serializer for Bus. + The djangorestframework plugin will analyse the model `Bus` and parse all fields in the API. + """ + + class Meta: + model = Bus + fields = '__all__' + + +class BusTeamSerializer(serializers.ModelSerializer): + """ + REST API Serializer for Bus teams. + The djangorestframework plugin will analyse the model `BusTeam` and parse all fields in the API. + """ + + class Meta: + model = BusTeam + fields = '__all__' diff --git a/apps/wei/api/urls.py b/apps/wei/api/urls.py index 7d39e8da..74279695 100644 --- a/apps/wei/api/urls.py +++ b/apps/wei/api/urls.py @@ -1,11 +1,13 @@ # Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # SPDX-License-Identifier: GPL-3.0-or-later -from .views import WEIClubViewSet +from .views import WEIClubViewSet, BusViewSet, BusTeamViewSet def register_wei_urls(router, path): """ Configure router for Member REST API. """ - router.register(path + '/club/', WEIClubViewSet) + router.register(path + '/club', WEIClubViewSet) + router.register(path + '/bus', BusViewSet) + router.register(path + '/team', BusTeamViewSet) diff --git a/apps/wei/api/views.py b/apps/wei/api/views.py index c93512e2..9ab3a139 100644 --- a/apps/wei/api/views.py +++ b/apps/wei/api/views.py @@ -4,8 +4,8 @@ from rest_framework.filters import SearchFilter from api.viewsets import ReadProtectedModelViewSet -from .serializers import WEIClubSerializer -from ..models import WEIClub +from .serializers import WEIClubSerializer, BusSerializer, BusTeamSerializer +from ..models import WEIClub, Bus, BusTeam class WEIClubViewSet(ReadProtectedModelViewSet): @@ -18,3 +18,27 @@ class WEIClubViewSet(ReadProtectedModelViewSet): serializer_class = WEIClubSerializer filter_backends = [SearchFilter] search_fields = ['$name', ] + + +class BusViewSet(ReadProtectedModelViewSet): + """ + REST API View set. + The djangorestframework plugin will get all `Bus` objects, serialize it to JSON with the given serializer, + then render it on /api/wei/bus/ + """ + queryset = Bus.objects.all() + serializer_class = BusSerializer + filter_backends = [SearchFilter] + search_fields = ['$name', ] + + +class BusTeamViewSet(ReadProtectedModelViewSet): + """ + REST API View set. + The djangorestframework plugin will get all `BusTeam` objects, serialize it to JSON with the given serializer, + then render it on /api/wei/team/ + """ + queryset = BusTeam.objects.all() + serializer_class = BusTeamSerializer + filter_backends = [SearchFilter] + search_fields = ['$name', ] diff --git a/apps/wei/forms.py b/apps/wei/forms.py index e8cd39fe..6fb7af04 100644 --- a/apps/wei/forms.py +++ b/apps/wei/forms.py @@ -6,7 +6,7 @@ from django.contrib.auth.models import User from django.utils.translation import ugettext_lazy as _ from note_kfet.inputs import AmountInput, DatePickerInput, Autocomplete -from .models import WEIClub, WEIRegistration +from .models import WEIClub, WEIRegistration, Bus class WEIForm(forms.ModelForm): @@ -43,3 +43,33 @@ class WEIRegistrationForm(forms.ModelForm): ), "birth_date": DatePickerInput(), } + + +class BusForm(forms.ModelForm): + class Meta: + model = Bus + fields = '__all__' + widgets = { + "wei": Autocomplete( + WEIClub, + attrs={ + 'api_url': '/api/wei/club/', + 'placeholder': 'WEI ...', + }, + ), + } + + +class BusTeamForm(forms.ModelForm): + class Meta: + model = Bus + fields = '__all__' + widgets = { + "bus": Autocomplete( + Bus, + attrs={ + 'api_url': '/api/wei/bus/', + 'placeholder': 'Bus ...', + }, + ), + } diff --git a/apps/wei/tables.py b/apps/wei/tables.py index f0541cd0..e0e40d0d 100644 --- a/apps/wei/tables.py +++ b/apps/wei/tables.py @@ -6,7 +6,7 @@ from django.urls import reverse_lazy from django.utils.translation import gettext_lazy as _ from django_tables2 import A -from .models import WEIClub, WEIRegistration +from .models import WEIClub, WEIRegistration, Bus, BusTeam class WEITable(tables.Table): @@ -71,13 +71,54 @@ class WEIRegistrationTable(tables.Table): }, ) + def render_is_first_year(self, value): + return _("yes") if value else _("no") + class Meta: attrs = { 'class': 'table table-condensed table-striped table-hover' } model = WEIRegistration template_name = 'django_tables2/bootstrap4.html' - fields = ('user',) + fields = ('user', 'is_first_year',) + row_attrs = { + 'class': 'table-row', + 'id': lambda record: "row-" + str(record.pk), + 'data-href': lambda record: record.pk + } + + +class BusTable(tables.Table): + class Meta: + attrs = { + 'class': 'table table-condensed table-striped table-hover' + } + model = Bus + template_name = 'django_tables2/bootstrap4.html' + fields = ('name', 'teams',) + row_attrs = { + 'class': 'table-row', + 'id': lambda record: "row-" + str(record.pk), + 'data-href': lambda record: record.pk + } + + +class BusTeamTable(tables.Table): + color = tables.Column( + attrs={ + "td": { + "style": lambda record: "background-color: #" + "".format(record.color) + ";" + } + } + ) + + class Meta: + attrs = { + 'class': 'table table-condensed table-striped table-hover' + } + model = BusTeam + template_name = 'django_tables2/bootstrap4.html' + fields = ('name', 'color', 'team',) row_attrs = { 'class': 'table-row', 'id': lambda record: "row-" + str(record.pk), diff --git a/apps/wei/urls.py b/apps/wei/urls.py index 3d3be0f0..331cb4db 100644 --- a/apps/wei/urls.py +++ b/apps/wei/urls.py @@ -3,7 +3,8 @@ from django.urls import path -from .views import WEIListView, WEICreateView, WEIDetailView, WEIUpdateView, WEIRegisterView, WEIUpdateRegistrationView +from .views import WEIListView, WEICreateView, WEIDetailView, WEIUpdateView, BusCreateView,\ + WEIRegisterView, WEIUpdateRegistrationView app_name = 'wei' @@ -12,6 +13,7 @@ urlpatterns = [ path('create/', WEICreateView.as_view(), name="wei_create"), path('detail//', WEIDetailView.as_view(), name="wei_detail"), path('update//', WEIUpdateView.as_view(), name="wei_update"), + path('add-bus//', BusCreateView.as_view(), name="add_bus"), path('register//', WEIRegisterView.as_view(), name="wei_register"), - path('edit_registration//', WEIUpdateRegistrationView.as_view(), name="wei_update_registration"), + path('edit-registration//', WEIUpdateRegistrationView.as_view(), name="wei_update_registration"), ] diff --git a/apps/wei/views.py b/apps/wei/views.py index 60f0a164..cf7c9ca8 100644 --- a/apps/wei/views.py +++ b/apps/wei/views.py @@ -16,9 +16,9 @@ from note.tables import HistoryTable from permission.backends import PermissionBackend from permission.views import ProtectQuerysetMixin -from .models import WEIClub, WEIRegistration, WEIMembership -from .forms import WEIForm, WEIRegistrationForm -from .tables import WEITable, WEIRegistrationTable +from .models import WEIClub, WEIRegistration, WEIMembership, Bus +from .forms import WEIForm, WEIRegistrationForm, BusForm +from .tables import WEITable, WEIRegistrationTable, BusTable class WEIListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView): @@ -91,6 +91,11 @@ 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 + buses = Bus.objects.filter(PermissionBackend.filter_queryset(self.request.user, Bus, "view"))\ + .filter(wei=self.object) + bus_table = BusTable(data=buses, prefix="bus-") + context['buses'] = bus_table + # Check if the user has the right to create a membership, to display the button. empty_membership = Membership( club=club, @@ -117,6 +122,28 @@ class WEIUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView): return reverse_lazy("wei:wei_detail", kwargs={"pk": self.object.pk}) +class BusCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView): + """ + Create Bus + """ + model = Bus + form_class = BusForm + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["club"] = WEIClub.objects.get(pk=self.kwargs["pk"]) + return context + + def get_form(self, form_class=None): + form = super().get_form(form_class) + form.fields["wei"].initial = WEIClub.objects.get(pk=self.kwargs["pk"]) + return form + + def get_success_url(self): + self.object.refresh_from_db() + return reverse_lazy("wei:wei_detail", kwargs={"pk": self.object.wei.pk}) + + class WEIRegisterView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView): """ Register to the WEI diff --git a/templates/member/noteowner_detail.html b/templates/member/noteowner_detail.html index 2a377140..93ba19ef 100644 --- a/templates/member/noteowner_detail.html +++ b/templates/member/noteowner_detail.html @@ -19,9 +19,11 @@ {% block extrajavascript %} {% endblock %} diff --git a/templates/wei/bus_form.html b/templates/wei/bus_form.html new file mode 100644 index 00000000..7fa2b01c --- /dev/null +++ b/templates/wei/bus_form.html @@ -0,0 +1,17 @@ +{% extends "member/noteowner_detail.html" %} +{% load crispy_forms_tags %} +{% load i18n %} + +{% block profile_info %} + {% if club %} + {% include "wei/weiclub_info.html" %} + {% endif %} +{% endblock %} + +{% block profile_content %} +
+{% csrf_token %} +{{ form|crispy }} + +
+{% endblock %} diff --git a/templates/wei/weiclub_form.html b/templates/wei/weiclub_form.html index ea29d966..64edf798 100644 --- a/templates/wei/weiclub_form.html +++ b/templates/wei/weiclub_form.html @@ -1,11 +1,17 @@ -{% extends "base.html" %} -{% load static %} -{% load i18n %} +{% extends "member/noteowner_detail.html" %} {% load crispy_forms_tags %} -{% block content %} -
-{% csrf_token %} -{{ form|crispy }} - -
+{% load i18n %} + +{% block profile_info %} + {% if club %} + {% include "wei/weiclub_info.html" %} + {% endif %} +{% endblock %} + +{% block profile_content %} +
+ {% csrf_token %} + {{ form|crispy }} + +
{% endblock %} diff --git a/templates/wei/weiclub_info.html b/templates/wei/weiclub_info.html index 16f2527d..5e62fe29 100644 --- a/templates/wei/weiclub_info.html +++ b/templates/wei/weiclub_info.html @@ -37,12 +37,12 @@ {% if "note.view_note"|has_perm:club.note %}
{% trans 'balance'|capfirst %}
-
{{ object.note.balance | pretty_money }}
+
{{ club.note.balance | pretty_money }}
{% endif %} {% if "note.change_alias"|has_perm:club.note.alias_set.first %}
{% trans 'aliases'|capfirst %}
-
{{ object.note.alias_set.all|join:", " }}
+
{{ club.note.alias_set.all|join:", " }}
{% endif %}
{% trans 'email'|capfirst %}
@@ -56,9 +56,12 @@ {% if ".change_"|has_perm:club %} {% trans "Edit" %} {% endif %} + {% if True %} + {% trans "Add bus" %} + {% endif %} {% url 'wei:wei_detail' club.pk as club_detail_url %} {%if request.path_info != club_detail_url %} - {% trans 'View WEI' %} + {% trans 'View WEI' %} {% endif %} diff --git a/templates/wei/weiclub_tables.html b/templates/wei/weiclub_tables.html index b1e54c7c..50fb1a81 100644 --- a/templates/wei/weiclub_tables.html +++ b/templates/wei/weiclub_tables.html @@ -59,6 +59,19 @@
+{% if buses.data or True %} +
+ + {% render_table buses %} +
+ +
+{% endif %} + {% if member_list.data %}