mirror of
https://gitlab.crans.org/bde/nk20
synced 2024-12-22 23:42:25 +00:00
List wei
This commit is contained in:
parent
a186ccbb26
commit
31d2224b8f
@ -15,6 +15,7 @@ from note.api.urls import register_note_urls
|
||||
from treasury.api.urls import register_treasury_urls
|
||||
from logs.api.urls import register_logs_urls
|
||||
from permission.api.urls import register_permission_urls
|
||||
from wei.api.urls import register_wei_urls
|
||||
|
||||
|
||||
class UserSerializer(serializers.ModelSerializer):
|
||||
@ -78,6 +79,7 @@ register_note_urls(router, 'note')
|
||||
register_treasury_urls(router, 'treasury')
|
||||
register_permission_urls(router, 'permission')
|
||||
register_logs_urls(router, 'logs')
|
||||
register_wei_urls(router, 'wei')
|
||||
|
||||
app_name = 'api'
|
||||
|
||||
|
0
apps/wei/api/__init__.py
Normal file
0
apps/wei/api/__init__.py
Normal file
17
apps/wei/api/serializers.py
Normal file
17
apps/wei/api/serializers.py
Normal file
@ -0,0 +1,17 @@
|
||||
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from rest_framework import serializers
|
||||
|
||||
from ..models import WEIClub
|
||||
|
||||
|
||||
class WEIClubSerializer(serializers.ModelSerializer):
|
||||
"""
|
||||
REST API Serializer for Clubs.
|
||||
The djangorestframework plugin will analyse the model `WEIClub` and parse all fields in the API.
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = WEIClub
|
||||
fields = '__all__'
|
11
apps/wei/api/urls.py
Normal file
11
apps/wei/api/urls.py
Normal file
@ -0,0 +1,11 @@
|
||||
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from .views import WEIClubViewSet
|
||||
|
||||
|
||||
def register_wei_urls(router, path):
|
||||
"""
|
||||
Configure router for Member REST API.
|
||||
"""
|
||||
router.register(path + '/club', WEIClubViewSet)
|
20
apps/wei/api/views.py
Normal file
20
apps/wei/api/views.py
Normal file
@ -0,0 +1,20 @@
|
||||
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from rest_framework.filters import SearchFilter
|
||||
from api.viewsets import ReadProtectedModelViewSet
|
||||
|
||||
from .serializers import WEIClubSerializer
|
||||
from ..models import WEIClub
|
||||
|
||||
|
||||
class WEIClubViewSet(ReadProtectedModelViewSet):
|
||||
"""
|
||||
REST API View set.
|
||||
The djangorestframework plugin will get all `WEIClub` objects, serialize it to JSON with the given serializer,
|
||||
then render it on /api/wei/club/
|
||||
"""
|
||||
queryset = WEIClub.objects.all()
|
||||
serializer_class = WEIClubSerializer
|
||||
filter_backends = [SearchFilter]
|
||||
search_fields = ['$name', ]
|
76
apps/wei/fixtures/initial.json
Normal file
76
apps/wei/fixtures/initial.json
Normal file
@ -0,0 +1,76 @@
|
||||
[
|
||||
{
|
||||
"model": "member.club",
|
||||
"pk": 3,
|
||||
"fields": {
|
||||
"name": "A[WEI] from Home",
|
||||
"email": "gc.wei@example.com",
|
||||
"parent_club": 2,
|
||||
"require_memberships": true,
|
||||
"membership_fee_paid": 16500,
|
||||
"membership_fee_unpaid": 9500,
|
||||
"membership_duration": 30,
|
||||
"membership_start": "2019-09-01",
|
||||
"membership_end": "2019-09-16"
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "wei.weiclub",
|
||||
"pk": 1,
|
||||
"fields": {
|
||||
"club_ptr_id": 3,
|
||||
"year": 2019,
|
||||
"date_start": "2019-09-14",
|
||||
"date_end": "2019-09-16"
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "note.note",
|
||||
"pk": 7,
|
||||
"fields": {
|
||||
"polymorphic_ctype": [
|
||||
"note",
|
||||
"noteclub"
|
||||
],
|
||||
"balance": 0,
|
||||
"last_negative": null,
|
||||
"is_active": true,
|
||||
"display_image": "pic/default.png",
|
||||
"created_at": "2020-02-20T20:16:14.753Z"
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "note.noteclub",
|
||||
"pk": 7,
|
||||
"fields": {
|
||||
"club": 3
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "note.alias",
|
||||
"pk": 7,
|
||||
"fields": {
|
||||
"name": "A[WEI] from Home",
|
||||
"normalized_name": "aweifromhome",
|
||||
"note": 7
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "note.alias",
|
||||
"pk": 8,
|
||||
"fields": {
|
||||
"name": "WEI 2019",
|
||||
"normalized_name": "wei2019",
|
||||
"note": 7
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "note.alias",
|
||||
"pk": 9,
|
||||
"fields": {
|
||||
"name": "WEI",
|
||||
"normalized_name": "wei",
|
||||
"note": 7
|
||||
}
|
||||
}
|
||||
]
|
@ -1,23 +1,32 @@
|
||||
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
import json
|
||||
|
||||
from django.contrib.auth.models import User
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from member.models import Role, Club, Membership
|
||||
from note.models import NoteSpecial
|
||||
|
||||
|
||||
class WEIClub(Club):
|
||||
"""
|
||||
The WEI is a club. Register to the WEI is equivalent than be member of the club.
|
||||
"""
|
||||
year = models.PositiveIntegerField(
|
||||
unique=True,
|
||||
verbose_name=_("year"),
|
||||
)
|
||||
|
||||
date_start = models.DateField(
|
||||
verbose_name=_("date start"),
|
||||
)
|
||||
|
||||
date_end = models.DateField(
|
||||
verbose_name=_("date end"),
|
||||
)
|
||||
|
||||
def update_membership_dates(self):
|
||||
"""
|
||||
We can't join the WEI next years.
|
||||
@ -84,6 +93,8 @@ class WEIRole(Role):
|
||||
bus = models.ForeignKey(
|
||||
Bus,
|
||||
on_delete=models.CASCADE,
|
||||
null=True,
|
||||
default=None,
|
||||
related_name="roles",
|
||||
verbose_name=_("bus"),
|
||||
)
|
||||
|
25
apps/wei/tables.py
Normal file
25
apps/wei/tables.py
Normal file
@ -0,0 +1,25 @@
|
||||
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
import django_tables2 as tables
|
||||
from django.urls import reverse_lazy
|
||||
|
||||
from wei.models import WEIClub
|
||||
|
||||
|
||||
class WEITable(tables.Table):
|
||||
"""
|
||||
List all clubs.
|
||||
"""
|
||||
class Meta:
|
||||
attrs = {
|
||||
'class': 'table table-condensed table-striped table-hover'
|
||||
}
|
||||
model = WEIClub
|
||||
template_name = 'django_tables2/bootstrap4.html'
|
||||
fields = ('name', 'year', 'date_start', 'date_end',)
|
||||
row_attrs = {
|
||||
'class': 'table-row',
|
||||
'id': lambda record: "row-" + str(record.pk),
|
||||
'data-href': lambda record: reverse_lazy('member:club_detail', args=(record.pk,))
|
||||
}
|
@ -3,7 +3,10 @@
|
||||
|
||||
from django.urls import path
|
||||
|
||||
from .views import WEIListView
|
||||
|
||||
|
||||
app_name = 'wei'
|
||||
urlpatterns = [
|
||||
path('list/', WEIListView.as_view(), name="wei_list"),
|
||||
]
|
||||
|
@ -1,5 +1,17 @@
|
||||
# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from django.shortcuts import render
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django_tables2 import SingleTableView
|
||||
from permission.views import ProtectQuerysetMixin
|
||||
from wei.models import WEIClub
|
||||
|
||||
from .tables import WEITable
|
||||
|
||||
|
||||
class WEIListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
|
||||
"""
|
||||
List existing WEI
|
||||
"""
|
||||
model = WEIClub
|
||||
table_class = WEITable
|
||||
|
@ -312,7 +312,7 @@ function in_validate(id, validated) {
|
||||
else
|
||||
invalidity_reason = null;
|
||||
|
||||
$("#validate_" + id).html("<strong style=\"font-size: 16pt;\">⟳ ...</strong>");
|
||||
$("#validate_" + id).html("<i class='fa fa-spinner'></i>");
|
||||
|
||||
// Perform a PATCH request to the API in order to update the transaction
|
||||
// If the user has insuffisent rights, an error message will appear
|
||||
|
@ -108,9 +108,12 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
||||
{% endif %}
|
||||
{% if "treasury.invoice"|not_empty_model_change_list %}
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="{% url 'treasury:invoice_list' %}"><i class="fa fa-money"></i>{% trans 'Treasury' %} </a>
|
||||
<a class="nav-link" href="{% url 'treasury:invoice_list' %}"><i class="fa fa-money"></i> {% trans 'Treasury' %}</a>
|
||||
</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>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="navbar-nav ml-auto">
|
||||
{% if user.is_authenticated %}
|
||||
|
@ -43,8 +43,8 @@
|
||||
<dt class="col-xl-6"><a href="{% url 'member:club_alias' club.pk %}">{% trans 'aliases'|capfirst %}</a></dt>
|
||||
<dd class="col-xl-6 text-truncate">{{ object.note.alias_set.all|join:", " }}</dd>
|
||||
|
||||
<dt class="col-xl-3">{% trans 'email'|capfirst %}</dt>
|
||||
<dd class="col-xl-9"><a href="mailto:{{ club.email }}">{{ club.email }}</a></dd>
|
||||
<dt class="col-xl-4">{% trans 'email'|capfirst %}</dt>
|
||||
<dd class="col-xl-8"><a href="mailto:{{ club.email }}">{{ club.email }}</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
<div class="card-footer text-center">
|
||||
|
70
templates/wei/weiclub_list.html
Normal file
70
templates/wei/weiclub_list.html
Normal file
@ -0,0 +1,70 @@
|
||||
{% extends "base.html" %}
|
||||
{% load render_table from django_tables2 %}
|
||||
{% load i18n %}
|
||||
{% block content %}
|
||||
<div class="row justify-content-center mb-4">
|
||||
<div class="col-md-10 text-center">
|
||||
<h4>
|
||||
{% trans "search WEI" %}
|
||||
</h4>
|
||||
<input class="form-control mx-auto w-25" type="text" onkeyup="search_field_moved()" id="search_field"/>
|
||||
<hr>
|
||||
<a class="btn btn-primary text-center my-4" href="{% url 'member:club_create' %}">{% trans "Create WEI" %}</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-10">
|
||||
<div class="card card-border shadow">
|
||||
<div class="card-header text-center">
|
||||
<h5> {% trans "WEI listing "%}</h5>
|
||||
</div>
|
||||
<div class="card-body px-0 py-0" id="club_table">
|
||||
{% render_table table %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
{% block extrajavascript %}
|
||||
<script type="text/javascript">
|
||||
|
||||
function getInfo() {
|
||||
var asked = $("#search_field").val();
|
||||
/* on ne fait la requête que si on a au moins un caractère pour chercher */
|
||||
var sel = $(".table-row");
|
||||
if (asked.length >= 1) {
|
||||
$.getJSON("/api/wei/club/?format=json&search="+asked, function(buttons){
|
||||
let selected_id = buttons.results.map((a => "#row-"+a.id));
|
||||
$(".table-row,"+selected_id.join()).show();
|
||||
$(".table-row").not(selected_id.join()).hide();
|
||||
|
||||
});
|
||||
}else{
|
||||
// show everything
|
||||
$('table tr').show();
|
||||
}
|
||||
}
|
||||
var timer;
|
||||
var timer_on;
|
||||
/* Fontion appelée quand le texte change (délenche le timer) */
|
||||
function search_field_moved(secondfield) {
|
||||
if (timer_on) { // Si le timer a déjà été lancé, on réinitialise le compteur.
|
||||
clearTimeout(timer);
|
||||
timer = setTimeout("getInfo(" + secondfield + ")", 300);
|
||||
}
|
||||
else { // Sinon, on le lance et on enregistre le fait qu'il tourne.
|
||||
timer = setTimeout("getInfo(" + secondfield + ")", 300);
|
||||
timer_on = true;
|
||||
}
|
||||
}
|
||||
|
||||
// clickable row
|
||||
$(document).ready(function($) {
|
||||
$(".table-row").click(function() {
|
||||
window.document.location = $(this).data("href");
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
{% endblock %}
|
2
tox.ini
2
tox.ini
@ -30,7 +30,7 @@ deps =
|
||||
pep8-naming
|
||||
pyflakes
|
||||
commands =
|
||||
flake8 apps/activity apps/api apps/logs apps/member apps/note apps/permission apps/treasury
|
||||
flake8 apps/activity apps/api apps/logs apps/member apps/note apps/permission apps/treasury apps/wei
|
||||
|
||||
[flake8]
|
||||
# Ignore too many errors, should be reduced in the future
|
||||
|
Loading…
Reference in New Issue
Block a user