Add a bus

This commit is contained in:
Yohann D'ANELLO 2020-04-13 05:02:16 +02:00
parent 6242e316ae
commit 822853be66
12 changed files with 218 additions and 29 deletions

View File

@ -3,7 +3,7 @@
from rest_framework import serializers from rest_framework import serializers
from ..models import WEIClub from ..models import WEIClub, Bus, BusTeam
class WEIClubSerializer(serializers.ModelSerializer): class WEIClubSerializer(serializers.ModelSerializer):
@ -15,3 +15,25 @@ class WEIClubSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = WEIClub model = WEIClub
fields = '__all__' 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__'

View File

@ -1,11 +1,13 @@
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay # Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from .views import WEIClubViewSet from .views import WEIClubViewSet, BusViewSet, BusTeamViewSet
def register_wei_urls(router, path): def register_wei_urls(router, path):
""" """
Configure router for Member REST API. 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)

View File

@ -4,8 +4,8 @@
from rest_framework.filters import SearchFilter from rest_framework.filters import SearchFilter
from api.viewsets import ReadProtectedModelViewSet from api.viewsets import ReadProtectedModelViewSet
from .serializers import WEIClubSerializer from .serializers import WEIClubSerializer, BusSerializer, BusTeamSerializer
from ..models import WEIClub from ..models import WEIClub, Bus, BusTeam
class WEIClubViewSet(ReadProtectedModelViewSet): class WEIClubViewSet(ReadProtectedModelViewSet):
@ -18,3 +18,27 @@ class WEIClubViewSet(ReadProtectedModelViewSet):
serializer_class = WEIClubSerializer serializer_class = WEIClubSerializer
filter_backends = [SearchFilter] filter_backends = [SearchFilter]
search_fields = ['$name', ] 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', ]

View File

@ -6,7 +6,7 @@ from django.contrib.auth.models import User
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from note_kfet.inputs import AmountInput, DatePickerInput, Autocomplete from note_kfet.inputs import AmountInput, DatePickerInput, Autocomplete
from .models import WEIClub, WEIRegistration from .models import WEIClub, WEIRegistration, Bus
class WEIForm(forms.ModelForm): class WEIForm(forms.ModelForm):
@ -43,3 +43,33 @@ class WEIRegistrationForm(forms.ModelForm):
), ),
"birth_date": DatePickerInput(), "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 ...',
},
),
}

View File

@ -6,7 +6,7 @@ from django.urls import reverse_lazy
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django_tables2 import A from django_tables2 import A
from .models import WEIClub, WEIRegistration from .models import WEIClub, WEIRegistration, Bus, BusTeam
class WEITable(tables.Table): 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: class Meta:
attrs = { attrs = {
'class': 'table table-condensed table-striped table-hover' 'class': 'table table-condensed table-striped table-hover'
} }
model = WEIRegistration model = WEIRegistration
template_name = 'django_tables2/bootstrap4.html' 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 = { row_attrs = {
'class': 'table-row', 'class': 'table-row',
'id': lambda record: "row-" + str(record.pk), 'id': lambda record: "row-" + str(record.pk),

View File

@ -3,7 +3,8 @@
from django.urls import path 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' app_name = 'wei'
@ -12,6 +13,7 @@ urlpatterns = [
path('create/', WEICreateView.as_view(), name="wei_create"), path('create/', WEICreateView.as_view(), name="wei_create"),
path('detail/<int:pk>/', WEIDetailView.as_view(), name="wei_detail"), path('detail/<int:pk>/', WEIDetailView.as_view(), name="wei_detail"),
path('update/<int:pk>/', WEIUpdateView.as_view(), name="wei_update"), path('update/<int:pk>/', WEIUpdateView.as_view(), name="wei_update"),
path('add-bus/<int:pk>/', BusCreateView.as_view(), name="add_bus"),
path('register/<int:wei_pk>/', WEIRegisterView.as_view(), name="wei_register"), path('register/<int:wei_pk>/', WEIRegisterView.as_view(), name="wei_register"),
path('edit_registration/<int:pk>/', WEIUpdateRegistrationView.as_view(), name="wei_update_registration"), path('edit-registration/<int:pk>/', WEIUpdateRegistrationView.as_view(), name="wei_update_registration"),
] ]

View File

@ -16,9 +16,9 @@ from note.tables import HistoryTable
from permission.backends import PermissionBackend from permission.backends import PermissionBackend
from permission.views import ProtectQuerysetMixin from permission.views import ProtectQuerysetMixin
from .models import WEIClub, WEIRegistration, WEIMembership from .models import WEIClub, WEIRegistration, WEIMembership, Bus
from .forms import WEIForm, WEIRegistrationForm from .forms import WEIForm, WEIRegistrationForm, BusForm
from .tables import WEITable, WEIRegistrationTable from .tables import WEITable, WEIRegistrationTable, BusTable
class WEIListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView): 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)) pre_registrations_table.paginate(per_page=20, page=self.request.GET.get('membership-page', 1))
context['pre_registrations'] = pre_registrations_table 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. # Check if the user has the right to create a membership, to display the button.
empty_membership = Membership( empty_membership = Membership(
club=club, club=club,
@ -117,6 +122,28 @@ class WEIUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
return reverse_lazy("wei:wei_detail", kwargs={"pk": self.object.pk}) 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): class WEIRegisterView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
""" """
Register to the WEI Register to the WEI

View File

@ -19,9 +19,11 @@
{% block extrajavascript %} {% block extrajavascript %}
<script> <script>
{% if object %}
function refreshHistory() { function refreshHistory() {
$("#history_list").load("{% url 'member:user_detail' pk=object.pk %} #history_list"); $("#history_list").load("{% url 'member:user_detail' pk=object.pk %} #history_list");
$("#profile_infos").load("{% url 'member:user_detail' pk=object.pk %} #profile_infos"); $("#profile_infos").load("{% url 'member:user_detail' pk=object.pk %} #profile_infos");
} }
{% endif %}
</script> </script>
{% endblock %} {% endblock %}

View File

@ -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 %}
<form method="post">
{% csrf_token %}
{{ form|crispy }}
<button class="btn btn-primary" type="submit">{% trans "Submit" %}</button>
</form>
{% endblock %}

View File

@ -1,8 +1,14 @@
{% extends "base.html" %} {% extends "member/noteowner_detail.html" %}
{% load static %}
{% load i18n %}
{% load crispy_forms_tags %} {% load crispy_forms_tags %}
{% block content %} {% load i18n %}
{% block profile_info %}
{% if club %}
{% include "wei/weiclub_info.html" %}
{% endif %}
{% endblock %}
{% block profile_content %}
<form method="post"> <form method="post">
{% csrf_token %} {% csrf_token %}
{{ form|crispy }} {{ form|crispy }}

View File

@ -37,12 +37,12 @@
{% if "note.view_note"|has_perm:club.note %} {% if "note.view_note"|has_perm:club.note %}
<dt class="col-xl-6">{% trans 'balance'|capfirst %}</dt> <dt class="col-xl-6">{% trans 'balance'|capfirst %}</dt>
<dd class="col-xl-6">{{ object.note.balance | pretty_money }}</dd> <dd class="col-xl-6">{{ club.note.balance | pretty_money }}</dd>
{% endif %} {% endif %}
{% if "note.change_alias"|has_perm:club.note.alias_set.first %} {% if "note.change_alias"|has_perm:club.note.alias_set.first %}
<dt class="col-xl-4"><a href="{% url 'member:club_alias' club.pk %}">{% trans 'aliases'|capfirst %}</a></dt> <dt class="col-xl-4"><a href="{% url 'member:club_alias' club.pk %}">{% trans 'aliases'|capfirst %}</a></dt>
<dd class="col-xl-8 text-truncate">{{ object.note.alias_set.all|join:", " }}</dd> <dd class="col-xl-8 text-truncate">{{ club.note.alias_set.all|join:", " }}</dd>
{% endif %} {% endif %}
<dt class="col-xl-4">{% trans 'email'|capfirst %}</dt> <dt class="col-xl-4">{% trans 'email'|capfirst %}</dt>
@ -56,6 +56,9 @@
{% if ".change_"|has_perm:club %} {% 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> <a class="btn btn-primary btn-sm my-1" href="{% url 'wei:wei_update' pk=club.pk %}"> {% trans "Edit" %}</a>
{% endif %} {% endif %}
{% if True %}
<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 %} {% url 'wei:wei_detail' club.pk as club_detail_url %}
{%if request.path_info != 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> <a class="btn btn-primary btn-sm my-1" href="{{ club_detail_url }}">{% trans 'View WEI' %}</a>

View File

@ -59,6 +59,19 @@
<hr> <hr>
{% if buses.data or True %}
<div class="card">
<div class="card-header position-relative" id="clubListHeading">
<a class="btn btn-link stretched-link font-weight-bold">
<i class="fa fa-bus"></i> {% trans "Buses" %}
</a>
</div>
{% render_table buses %}
</div>
<hr>
{% endif %}
{% if member_list.data %} {% if member_list.data %}
<div class="card"> <div class="card">
<div class="card-header position-relative" id="clubListHeading"> <div class="card-header position-relative" id="clubListHeading">