mirror of
https://gitlab.crans.org/bde/nk20
synced 2024-11-26 18:37:12 +00:00
Add teams
This commit is contained in:
parent
822853be66
commit
840376a4f5
@ -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(),
|
||||||
}
|
}
|
||||||
|
@ -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) + ")"
|
||||||
|
|
||||||
|
@ -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),
|
||||||
|
@ -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"),
|
||||||
]
|
]
|
||||||
|
@ -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})
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
12
static/colorfield/colorfield.js
Normal file
12
static/colorfield/colorfield.js
Normal 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));
|
||||||
|
}
|
||||||
|
};
|
1855
static/colorfield/jscolor/jscolor.js
Executable file
1855
static/colorfield/jscolor/jscolor.js
Executable file
File diff suppressed because it is too large
Load Diff
1
static/colorfield/jscolor/jscolor.min.js
vendored
Executable file
1
static/colorfield/jscolor/jscolor.min.js
vendored
Executable file
File diff suppressed because one or more lines are too long
8
templates/colorfield/color.html
Executable file
8
templates/colorfield/color.html
Executable 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 %} />
|
9
templates/wei/bus_detail.html
Normal file
9
templates/wei/bus_detail.html
Normal 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 %}
|
@ -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 %}
|
||||||
|
33
templates/wei/bus_tables.html
Normal file
33
templates/wei/bus_tables.html
Normal 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 %}
|
15
templates/wei/busteam_form.html
Normal file
15
templates/wei/busteam_form.html
Normal 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 %}
|
@ -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">
|
||||||
|
Loading…
Reference in New Issue
Block a user