1
0
mirror of https://gitlab.crans.org/bde/nk20 synced 2025-07-19 23:51:25 +02:00

Achievement delete

This commit is contained in:
Ehouarn
2025-07-18 22:11:43 +02:00
parent 67b936ae98
commit 9e700fd3de
9 changed files with 119 additions and 22 deletions

View File

@ -1,6 +1,7 @@
# Copyright (C) 2018-2025 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later
from django.urls import path
from .views import FamilyViewSet, FamilyMembershipViewSet, ChallengeViewSet, AchievementViewSet, BatchAchievementsAPIView
@ -13,6 +14,7 @@ def register_family_urls(router, path):
router.register(path + '/challenge', ChallengeViewSet)
router.register(path + '/achievement', AchievementViewSet)
urlpatterns = [
path('achievements/batch/', BatchAchievementsAPIView.as_view(), name='batch_achievements')
]

View File

@ -8,10 +8,6 @@ from rest_framework.views import APIView
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework import status
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_POST
from django.http import JsonResponse
import json
from .serializers import FamilySerializer, FamilyMembershipSerializer, ChallengeSerializer, AchievementSerializer
from ..models import Family, FamilyMembership, Challenge, Achievement
@ -71,6 +67,7 @@ class AchievementViewSet(ReadProtectedModelViewSet):
class BatchAchievementsAPIView(APIView):
permission_classes = [IsAuthenticated]
def post(self, request, format=None):
print("POST de la view spéciale")
family_ids = request.data.get('families', [])

View File

@ -3,6 +3,8 @@
import django_tables2 as tables
from django.urls import reverse
from django.utils.translation import gettext_lazy as _
from django_tables2 import A
from .models import Family, Challenge, FamilyMembership, Achievement
@ -63,11 +65,28 @@ class AchievementTable(tables.Table):
"""
List recent achievements.
"""
delete = tables.LinkColumn(
'family:achievement_delete',
args=[A('id')],
verbose_name=_("Delete"),
text=_("Delete"),
orderable=False,
attrs={
'th': {
'id': 'delete-membership-header'
},
'a': {
'class': 'btn btn-danger',
'data-type': 'delete-membership'
}
},
)
class Meta:
attrs = {
'class': 'table table-condensed table-striped table-hover'
}
model = Achievement
fields = ('family', 'challenge', 'obtained_at', )
fields = ('family', 'challenge', 'challenge__points', 'obtained_at', )
template_name = 'django_tables2/bootstrap4.html'
orderable = False
order_by = ('-obtained_at',)

View File

@ -0,0 +1,27 @@
{% extends "base.html" %}
{% comment %}
SPDX-License-Identifier: GPL-3.0-or-later
{% endcomment %}
{% load i18n crispy_forms_tags %}
{% block content %}
<div class="card bg-light">
<div class="card-header text-center">
<h4>{% trans "Delete achievement" %}</h4>
</div>
<div class="card-body">
<div class="alert alert-warning">
{% blocktrans %}Are you sure you want to delete this achievement? This action can't be undone.{% endblocktrans %}
</div>
</div>
<div class="card-footer text-center">
<form method="post">
{% csrf_token %}
<a class="btn btn-primary" href="{% url 'family:achievement_list' %}">{% trans "Return to achievements list" %}</a>
{% if not object.locked %}
<button class="btn btn-danger" type="submit">{% trans "Delete" %}</button>
{% endif %}
</form>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,22 @@
{% extends "base.html" %}
{% comment %}
Copyright (C) 2018-2025 by BDE ENS Paris-Saclay
SPDX-License-Identifier: GPL-3.0-or-later
{% endcomment %}
{% load i18n django_tables2 %}
{% block content %}
<div class="card mb-4" id="history">
<div class="card-header">
<p class="card-text font-weight-bold">
{% trans "Recent achievements history" %}
</p>
<a class="btn btn-sm btn-primary mx-2" href="{% url "family:manage" %}">
{% trans "Return to management page" %}
</a>
</div>
{% render_table table %}
</div>
{% endblock %}

View File

@ -143,25 +143,22 @@ SPDX-License-Identifier: GPL-3.0-or-later
</div>
</div>
{# Mode switch #}
<div class="card-footer border-primary">
<a class="btn btn-sm btn-secondary float-left" href="{% url 'note:template_list' %}">
<i class="fa fa-edit"></i> {% trans "Edit" %}
</a>
</div>
</div>
</div>
</div>
{# transaction history #}
<div class="card mb-4" id="history">
<div class="card-header">
<p class="card-text font-weight-bold">
<div class="card">
<div class="card-header position-relative" id="historyListHeading">
<a class="stretched-link font-weight-bold"
href="{% url 'family:achievement_list' %}" >
{% trans "Recent achievements history" %}
</p>
</a>
</div>
<div id="history_list">
{% render_table table %}
</div>
</div>
{% endblock %}

View File

@ -18,5 +18,7 @@ urlpatterns = [
path('challenge/detail/<int:pk>/', views.ChallengeDetailView.as_view(), name="challenge_detail"),
path('challenge/update/<int:pk>/', views.ChallengeUpdateView.as_view(), name="challenge_update"),
path('manage/', views.FamilyManageView.as_view(), name="manage"),
path('achievements/', views.AchievementsView.as_view(), name="achievement_list"),
path('achievement/delete/<int:pk>/', views.AchievementDeleteView.as_view(), name="achievement_delete"),
path('api/family/', include('family.api.urls')),
]

View File

@ -7,6 +7,7 @@ from django.conf import settings
from django.contrib.auth.mixins import LoginRequiredMixin
from django.db import transaction
from django.views.generic import DetailView, UpdateView
from django.views.generic.edit import DeleteView
from django.utils.translation import gettext_lazy as _
from django_tables2 import SingleTableView
from permission.backends import PermissionBackend
@ -195,7 +196,7 @@ class ChallengeCreateView(ProtectQuerysetMixin, ProtectedCreateView):
)
def get_success_url(self):
return reverse_lazy('family:challenge_list')
return reverse_lazy('family:manage')
class ChallengeListView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
@ -264,7 +265,7 @@ class FamilyManageView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView
# retrieves only Transaction that user has the right to see.
return Achievement.objects.filter(
PermissionBackend.filter_queryset(self.request, Achievement, "view")
).order_by("-obtained_at").all()[:20]
).order_by("-obtained_at").all()
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
@ -277,3 +278,33 @@ class FamilyManageView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView
context["can_add_challenge"] = PermissionBackend.check_perm(self.request, "family.add_challenge")
return context
def get_table(self, **kwargs):
table = super().get_table(**kwargs)
table.exclude = ('delete',)
table.orderable = False
return table
class AchievementsView(ProtectQuerysetMixin, LoginRequiredMixin, SingleTableView):
"""
List all achievements
"""
model = Achievement
table_class = AchievementTable
extra_context = {'title': _('Achievement list')}
def get_table(self, **kwargs):
table = super().get_table(**kwargs)
table.orderable = True
return table
class AchievementDeleteView(ProtectQuerysetMixin, LoginRequiredMixin, DeleteView):
"""
Delete an Achievement
"""
model = Achievement
def get_success_url(self):
return reverse_lazy('family:achievement_list')

View File

@ -168,7 +168,7 @@ class InvoiceUpdateView(ProtectQuerysetMixin, LoginRequiredMixin, UpdateView):
class InvoiceDeleteView(ProtectQuerysetMixin, LoginRequiredMixin, DeleteView):
"""
Delete a non-validated WEI registration
Delete a non-locked Invoice
"""
model = Invoice
extra_context = {"title": _("Delete invoice")}