mirror of
https://gitlab.crans.org/bde/nk20
synced 2025-10-14 17:48:33 +02:00
Compare commits
1 Commits
cb2fb2b273
...
959131780e
Author | SHA1 | Date | |
---|---|---|---|
|
959131780e |
@@ -37,11 +37,6 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||||||
<div id="guests_table">
|
<div id="guests_table">
|
||||||
{% render_table guests %}
|
{% render_table guests %}
|
||||||
</div>
|
</div>
|
||||||
<div class="card-footer text-center">
|
|
||||||
<button class="btn btn-block btn-primary mb-3" onclick="window.location.href='?_export=1&table=guests'">
|
|
||||||
{% trans "Export to CSV" %}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@@ -136,19 +136,12 @@ class ActivityDetailView(ProtectQuerysetMixin, LoginRequiredMixin, MultiTableMix
|
|||||||
model = Activity
|
model = Activity
|
||||||
context_object_name = "activity"
|
context_object_name = "activity"
|
||||||
extra_context = {"title": _("Activity detail")}
|
extra_context = {"title": _("Activity detail")}
|
||||||
export_formats = ["csv"]
|
|
||||||
|
|
||||||
tables = [
|
tables = [
|
||||||
GuestTable,
|
lambda data: GuestTable(data, prefix="guests-"),
|
||||||
OpenerTable,
|
lambda data: OpenerTable(data, prefix="opener-"),
|
||||||
]
|
]
|
||||||
|
|
||||||
def get_tables(self):
|
|
||||||
tables = super().get_tables()
|
|
||||||
tables[0].prefix = "guests"
|
|
||||||
tables[1].prefix = "opener"
|
|
||||||
return tables
|
|
||||||
|
|
||||||
def get_tables_data(self):
|
def get_tables_data(self):
|
||||||
return [
|
return [
|
||||||
Guest.objects.filter(activity=self.object)
|
Guest.objects.filter(activity=self.object)
|
||||||
@@ -157,51 +150,6 @@ class ActivityDetailView(ProtectQuerysetMixin, LoginRequiredMixin, MultiTableMix
|
|||||||
.filter(PermissionBackend.filter_queryset(self.request, Opener, "view")),
|
.filter(PermissionBackend.filter_queryset(self.request, Opener, "view")),
|
||||||
]
|
]
|
||||||
|
|
||||||
def render_to_response(self, context, **response_kwargs):
|
|
||||||
"""
|
|
||||||
Gère l'export CSV manuel pour MultiTableMixin.
|
|
||||||
"""
|
|
||||||
if "_export" in self.request.GET:
|
|
||||||
import tablib
|
|
||||||
table_name = self.request.GET.get("table")
|
|
||||||
if table_name:
|
|
||||||
tables = self.get_tables()
|
|
||||||
data_list = self.get_tables_data()
|
|
||||||
|
|
||||||
for t, d in zip(tables, data_list):
|
|
||||||
if t.prefix == table_name:
|
|
||||||
# Préparer le CSV
|
|
||||||
dataset = tablib.Dataset()
|
|
||||||
columns = list(t.base_columns) # noms des colonnes
|
|
||||||
dataset.headers = columns
|
|
||||||
|
|
||||||
for row in d:
|
|
||||||
values = []
|
|
||||||
for col in columns:
|
|
||||||
try:
|
|
||||||
val = getattr(row, col, "")
|
|
||||||
# Gestion spéciale pour la colonne 'entry'
|
|
||||||
if col == "entry":
|
|
||||||
if getattr(row, "has_entry", False):
|
|
||||||
val = timezone.localtime(row.entry.time).strftime("%Y-%m-%d %H:%M:%S")
|
|
||||||
else:
|
|
||||||
val = ""
|
|
||||||
values.append(str(val) if val is not None else "")
|
|
||||||
except Exception: # RelatedObjectDoesNotExist ou autre
|
|
||||||
values.append("")
|
|
||||||
dataset.append(values)
|
|
||||||
|
|
||||||
csv_bytes = dataset.export("csv")
|
|
||||||
if isinstance(csv_bytes, str):
|
|
||||||
csv_bytes = csv_bytes.encode("utf-8")
|
|
||||||
|
|
||||||
response = HttpResponse(csv_bytes, content_type="text/csv")
|
|
||||||
response["Content-Disposition"] = f'attachment; filename="{table_name}.csv"'
|
|
||||||
return response
|
|
||||||
|
|
||||||
# Sinon rendu normal
|
|
||||||
return super().render_to_response(context, **response_kwargs)
|
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super().get_context_data()
|
context = super().get_context_data()
|
||||||
|
|
||||||
|
@@ -92,20 +92,6 @@ class MembershipTable(tables.Table):
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
user_email = tables.Column(
|
|
||||||
verbose_name="Email",
|
|
||||||
accessor="user.email",
|
|
||||||
orderable=False,
|
|
||||||
visible=False,
|
|
||||||
)
|
|
||||||
|
|
||||||
user_full_name = tables.Column(
|
|
||||||
verbose_name=_("Full name"),
|
|
||||||
accessor="user.get_full_name",
|
|
||||||
orderable=False,
|
|
||||||
visible=False,
|
|
||||||
)
|
|
||||||
|
|
||||||
def render_user(self, value):
|
def render_user(self, value):
|
||||||
# If the user has the right, link the displayed user with the page of its detail.
|
# If the user has the right, link the displayed user with the page of its detail.
|
||||||
s = value.username
|
s = value.username
|
||||||
@@ -163,16 +149,6 @@ class MembershipTable(tables.Table):
|
|||||||
+ "'>" + s + "</a>")
|
+ "'>" + s + "</a>")
|
||||||
return s
|
return s
|
||||||
|
|
||||||
def value_user(self, record):
|
|
||||||
return record.user.username if record.user else ""
|
|
||||||
|
|
||||||
def value_club(self, record):
|
|
||||||
return record.club.name if record.club else ""
|
|
||||||
|
|
||||||
def value_roles(self, record):
|
|
||||||
roles = record.roles.all()
|
|
||||||
return ", ".join(str(role) for role in roles)
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
attrs = {
|
attrs = {
|
||||||
'class': 'table table-condensed table-striped',
|
'class': 'table table-condensed table-striped',
|
||||||
|
@@ -36,13 +36,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||||||
{% trans "There is no membership found with this pattern." %}
|
{% trans "There is no membership found with this pattern." %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="card-footer text-center">
|
|
||||||
<button class="btn btn-block btn-primary mb-3" onclick="window.location.href='?_export=csv'">
|
|
||||||
{% trans "Export to CSV" %}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
@@ -17,7 +17,6 @@ from django.utils.translation import gettext_lazy as _
|
|||||||
from django.views.generic import DetailView, UpdateView, TemplateView
|
from django.views.generic import DetailView, UpdateView, TemplateView
|
||||||
from django.views.generic.edit import FormMixin
|
from django.views.generic.edit import FormMixin
|
||||||
from django_tables2.views import MultiTableMixin, SingleTableMixin, SingleTableView
|
from django_tables2.views import MultiTableMixin, SingleTableMixin, SingleTableView
|
||||||
from django_tables2.export.views import ExportMixin
|
|
||||||
from rest_framework.authtoken.models import Token
|
from rest_framework.authtoken.models import Token
|
||||||
from api.viewsets import is_regex
|
from api.viewsets import is_regex
|
||||||
from note.models import Alias, NoteClub, NoteUser, Trust
|
from note.models import Alias, NoteClub, NoteUser, Trust
|
||||||
@@ -959,12 +958,11 @@ class ClubManageRolesView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
|
|||||||
return reverse_lazy('member:user_detail', kwargs={'pk': self.object.user.id})
|
return reverse_lazy('member:user_detail', kwargs={'pk': self.object.user.id})
|
||||||
|
|
||||||
|
|
||||||
class ClubMembersListView(ExportMixin, ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
|
class ClubMembersListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
|
||||||
model = Membership
|
model = Membership
|
||||||
table_class = MembershipTable
|
table_class = MembershipTable
|
||||||
template_name = "member/club_members.html"
|
template_name = "member/club_members.html"
|
||||||
extra_context = {"title": _("Members of the club")}
|
extra_context = {"title": _("Members of the club")}
|
||||||
export_formats = ["csv"]
|
|
||||||
|
|
||||||
def get_queryset(self, **kwargs):
|
def get_queryset(self, **kwargs):
|
||||||
qs = super().get_queryset().filter(club_id=self.kwargs["pk"])
|
qs = super().get_queryset().filter(club_id=self.kwargs["pk"])
|
||||||
@@ -996,14 +994,6 @@ class ClubMembersListView(ExportMixin, ProtectQuerysetMixin, LoginRequiredMixin,
|
|||||||
|
|
||||||
return qs.distinct()
|
return qs.distinct()
|
||||||
|
|
||||||
def get_export_filename(self, export_format):
|
|
||||||
return "members.csv"
|
|
||||||
|
|
||||||
def get_export_content_type(self, export_format):
|
|
||||||
if export_format == "csv":
|
|
||||||
return "text/csv"
|
|
||||||
return super().get_export_content_type(export_format)
|
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
club = Club.objects.filter(
|
club = Club.objects.filter(
|
||||||
|
@@ -4702,22 +4702,6 @@
|
|||||||
"description": "Supprimer un succès"
|
"description": "Supprimer un succès"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"model": "permission.permission",
|
|
||||||
"pk": 330,
|
|
||||||
"fields": {
|
|
||||||
"model": [
|
|
||||||
"auth",
|
|
||||||
"user"
|
|
||||||
],
|
|
||||||
"query": "{\"memberships__club\": [\"club\"]}",
|
|
||||||
"type": "view",
|
|
||||||
"mask": 2,
|
|
||||||
"field": "email",
|
|
||||||
"permanent": false,
|
|
||||||
"description": "Voir l'adresse mail des membres de son club"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"model": "permission.role",
|
"model": "permission.role",
|
||||||
"pk": 1,
|
"pk": 1,
|
||||||
@@ -4868,8 +4852,7 @@
|
|||||||
259,
|
259,
|
||||||
260,
|
260,
|
||||||
263,
|
263,
|
||||||
265,
|
265
|
||||||
330
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -5218,7 +5201,6 @@
|
|||||||
"permissions": [
|
"permissions": [
|
||||||
37,
|
37,
|
||||||
41,
|
41,
|
||||||
42,
|
|
||||||
53,
|
53,
|
||||||
54,
|
54,
|
||||||
55,
|
55,
|
||||||
|
@@ -18,5 +18,4 @@ django-rest-polymorphic~=0.1.10
|
|||||||
django-tables2~=2.7.5
|
django-tables2~=2.7.5
|
||||||
python-memcached~=1.62
|
python-memcached~=1.62
|
||||||
phonenumbers~=9.0.8
|
phonenumbers~=9.0.8
|
||||||
tablib~=3.8.0
|
|
||||||
Pillow>=11.3.0
|
Pillow>=11.3.0
|
||||||
|
Reference in New Issue
Block a user