Add teams

This commit is contained in:
Yohann D'ANELLO 2020-04-13 06:01:27 +02:00
parent 822853be66
commit 840376a4f5
15 changed files with 2054 additions and 16 deletions

View File

@ -4,9 +4,9 @@
from django import forms from django import forms
from django.contrib.auth.models import User 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, ColorWidget
from .models import WEIClub, WEIRegistration, Bus from .models import WEIClub, WEIRegistration, Bus, BusTeam
class WEIForm(forms.ModelForm): class WEIForm(forms.ModelForm):
@ -62,7 +62,7 @@ class BusForm(forms.ModelForm):
class BusTeamForm(forms.ModelForm): class BusTeamForm(forms.ModelForm):
class Meta: class Meta:
model = Bus model = BusTeam
fields = '__all__' fields = '__all__'
widgets = { widgets = {
"bus": Autocomplete( "bus": Autocomplete(
@ -72,4 +72,5 @@ class BusTeamForm(forms.ModelForm):
'placeholder': 'Bus ...', 'placeholder': 'Bus ...',
}, },
), ),
"color": ColorWidget(),
} }

View File

@ -50,6 +50,12 @@ class Bus(models.Model):
verbose_name=_("name"), verbose_name=_("name"),
) )
description = models.TextField(
blank=True,
default="",
verbose_name=_("description"),
)
def __str__(self): def __str__(self):
return self.name return self.name
@ -77,6 +83,12 @@ class BusTeam(models.Model):
help_text=_("The color of the T-Shirt, stored with its number equivalent"), help_text=_("The color of the T-Shirt, stored with its number equivalent"),
) )
description = models.TextField(
blank=True,
default="",
verbose_name=_("description"),
)
def __str__(self): def __str__(self):
return self.name + " (" + str(self.bus) + ")" return self.name + " (" + str(self.bus) + ")"

View File

@ -107,18 +107,22 @@ class BusTeamTable(tables.Table):
color = tables.Column( color = tables.Column(
attrs={ attrs={
"td": { "td": {
"style": lambda record: "background-color: #" + "".format(record.color) + ";" "style": lambda record: "background-color: #{:06X}; color: #{:06X};"
.format(record.color, 0xFFFFFF - record.color, )
} }
} }
) )
def render_color(self, value):
return "#{:06X}".format(value)
class Meta: class Meta:
attrs = { attrs = {
'class': 'table table-condensed table-striped table-hover' 'class': 'table table-condensed table-striped table-hover'
} }
model = BusTeam model = BusTeam
template_name = 'django_tables2/bootstrap4.html' template_name = 'django_tables2/bootstrap4.html'
fields = ('name', 'color', 'team',) fields = ('name', 'color',)
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, BusCreateView,\ from .views import WEIListView, WEICreateView, WEIDetailView, WEIUpdateView,\
BusCreateView, BusManageView, BusUpdateView, BusTeamCreateView,\
WEIRegisterView, WEIUpdateRegistrationView WEIRegisterView, WEIUpdateRegistrationView
@ -14,6 +15,9 @@ urlpatterns = [
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('add-bus/<int:pk>/', BusCreateView.as_view(), name="add_bus"),
path('manage-bus/<int:pk>/', BusManageView.as_view(), name="manage_bus"),
path('update-bus/<int:pk>/', BusUpdateView.as_view(), name="update_bus"),
path('add-bus-team/<int:pk>/', BusTeamCreateView.as_view(), name="add_team"),
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, Bus from .models import WEIClub, WEIRegistration, WEIMembership, Bus, BusTeam
from .forms import WEIForm, WEIRegistrationForm, BusForm from .forms import WEIForm, WEIRegistrationForm, BusForm, BusTeamForm
from .tables import WEITable, WEIRegistrationTable, BusTable from .tables import WEITable, WEIRegistrationTable, BusTable, BusTeamTable
class WEIListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView): class WEIListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
@ -141,7 +141,71 @@ class BusCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
def get_success_url(self): def get_success_url(self):
self.object.refresh_from_db() self.object.refresh_from_db()
return reverse_lazy("wei:wei_detail", kwargs={"pk": self.object.wei.pk}) return reverse_lazy("wei:manage_bus", kwargs={"pk": self.object.pk})
class BusUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
"""
Update Bus
"""
model = Bus
form_class = BusForm
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)
form.fields["wei"].disabled = True
return form
def get_success_url(self):
self.object.refresh_from_db()
return reverse_lazy("wei:manage_bus", kwargs={"pk": self.object.pk})
class BusManageView(ProtectQuerysetMixin, LoginRequiredMixin, DetailView):
"""
Manage Bus
"""
model = Bus
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["club"] = self.object.wei
bus = self.object
teams = BusTeam.objects.filter(PermissionBackend.filter_queryset(self.request.user, BusTeam, "view"))\
.filter(bus=bus)
teams_table = BusTeamTable(data=teams, prefix="teams-")
context["teams"] = teams_table
return context
class BusTeamCreateView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
"""
Create BusTeam
"""
model = BusTeam
form_class = BusTeamForm
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
bus = Bus.objects.get(pk=self.kwargs["pk"])
context["club"] = bus.wei
return context
def get_form(self, form_class=None):
form = super().get_form(form_class)
form.fields["bus"].initial = Bus.objects.get(pk=self.kwargs["pk"])
return form
def get_success_url(self):
self.object.refresh_from_db()
return reverse_lazy("wei:manage_bus", kwargs={"pk": self.object.bus.pk})
class WEIRegisterView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView): class WEIRegisterView(ProtectQuerysetMixin, LoginRequiredMixin, CreateView):
@ -180,4 +244,3 @@ class WEIUpdateRegistrationView(ProtectQuerysetMixin, LoginRequiredMixin, Update
def get_success_url(self): def get_success_url(self):
self.object.refresh_from_db() self.object.refresh_from_db()
return reverse_lazy("wei:wei_detail", kwargs={"pk": self.object.wei.pk}) return reverse_lazy("wei:wei_detail", kwargs={"pk": self.object.wei.pk})

View File

@ -3,7 +3,7 @@
from json import dumps as json_dumps from json import dumps as json_dumps
from django.forms.widgets import DateTimeBaseInput, NumberInput, TextInput from django.forms.widgets import DateTimeBaseInput, NumberInput, TextInput, Widget
class AmountInput(NumberInput): class AmountInput(NumberInput):
@ -41,6 +41,29 @@ class Autocomplete(TextInput):
return "" return ""
class ColorWidget(Widget):
"""
Pulled from django-colorfield.
Select a color.
"""
template_name = 'colorfield/color.html'
class Media:
js = [
'colorfield/jscolor/jscolor.min.js',
'colorfield/colorfield.js',
]
def format_value(self, value):
if value is None:
value = 0xFFFFFF
return "#{:06X}".format(value)
def value_from_datadict(self, data, files, name):
val = super().value_from_datadict(data, files, name)
return int(val[1:], 16)
""" """
The remaining of this file comes from the project `django-bootstrap-datepicker-plus` available on Github: The remaining of this file comes from the project `django-bootstrap-datepicker-plus` available on Github:
https://github.com/monim67/django-bootstrap-datepicker-plus https://github.com/monim67/django-bootstrap-datepicker-plus

View File

@ -0,0 +1,12 @@
/** global: django */
window.onload = function() {
if (typeof(django) !== 'undefined' && typeof(django.jQuery) !== 'undefined') {
(function($) {
// add colopicker to inlines added dynamically
$(document).on('formset:added', function onFormsetAdded(event, row) {
jscolor.installByClassName('jscolor');
});
}(django.jQuery));
}
};

File diff suppressed because it is too large Load Diff

1
static/colorfield/jscolor/jscolor.min.js vendored Executable file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,8 @@
<input type="text"
id="{{ widget.attrs.id }}"
class="form-control colorfield_field jscolor"
name="{{ widget.name }}"
value="{% firstof widget.value widget.attrs.default '' %}"
placeholder="{% firstof widget.value widget.attrs.default '' %}"
data-jscolor="{hash:true,width:225,height:150,required:{% if widget.attrs.required %}true{% else %}false{% endif %}}"
{% if widget.attrs.required %}required{% endif %} />

View File

@ -0,0 +1,9 @@
{% extends "member/noteowner_detail.html" %}
{% block profile_info %}
{% include "wei/weiclub_info.html" %}
{% endblock %}
{% block profile_content %}
{% include "wei/bus_tables.html" %}
{% endblock %}

View File

@ -3,9 +3,7 @@
{% load i18n %} {% load i18n %}
{% block profile_info %} {% block profile_info %}
{% if club %} {% include "wei/weiclub_info.html" %}
{% include "wei/weiclub_info.html" %}
{% endif %}
{% endblock %} {% endblock %}
{% block profile_content %} {% block profile_content %}

View File

@ -0,0 +1,33 @@
{% load render_table from django_tables2 %}
{% load i18n %}
<div class="card">
<div class="card-header text-center">
<h4>{{ object.name }}</h4>
</div>
<div class="card-body">
{{ object.description }}
</div>
<div class="card-footer text-center">
<a class="btn btn-primary btn-sm my-1" href="{% url 'wei:update_bus' pk=object.pk %}">{% trans "Edit" %}</a>
<a class="btn btn-primary btn-sm my-1" href="{% url 'wei:add_team' pk=object.pk %}">{% trans "Add team" %}</a>
</div>
</div>
<hr>
{% if teams.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 "Teams" %}
</a>
</div>
{% render_table teams %}
</div>
<hr>
{% endif %}

View File

@ -0,0 +1,15 @@
{% extends "member/noteowner_detail.html" %}
{% load crispy_forms_tags %}
{% load i18n %}
{% block profile_info %}
{% include "wei/weiclub_info.html" %}
{% 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

@ -59,7 +59,7 @@
<hr> <hr>
{% if buses.data or True %} {% if buses.data %}
<div class="card"> <div class="card">
<div class="card-header position-relative" id="clubListHeading"> <div class="card-header position-relative" id="clubListHeading">
<a class="btn btn-link stretched-link font-weight-bold"> <a class="btn btn-link stretched-link font-weight-bold">