1
0
mirror of https://gitlab.crans.org/bde/nk20 synced 2025-08-14 17:59:45 +02:00

Achievement unicity && management pop-up behaviour

This commit is contained in:
Ehouarn
2025-08-13 23:57:05 +02:00
parent 61057b71ba
commit 4d567cdcc7
6 changed files with 111 additions and 47 deletions

View File

@@ -75,13 +75,24 @@ class BatchAchievementsAPIView(APIView):
challenge_ids = request.data.get('challenges') challenge_ids = request.data.get('challenges')
families = Family.objects.filter(id__in=family_ids) families = Family.objects.filter(id__in=family_ids)
challenges = Challenge.objects.filter(id__in=challenge_ids) challenges = Challenge.objects.filter(id__in=challenge_ids)
results = []
for family in families: for family in families:
for challenge in challenges: for challenge in challenges:
a = Achievement(family=family, challenge=challenge) a, created = Achievement.objects.get_or_create(family=family, challenge=challenge)
a.save(update_score=False) if created:
results.append({
'family': family.name,
'challenge': challenge.name,
'status': 'created'
})
else:
results.append({
'family': family.name,
'challenge': challenge.name,
'status': 'error',
})
for family in families: for family in families:
family.update_score() family.update_score()
Family.update_ranking() Family.update_ranking()
return Response({'status': 'ok'}, status=status.HTTP_201_CREATED) return Response({'results': results}, status=status.HTTP_201_CREATED)

View File

@@ -0,0 +1,17 @@
# Generated by Django 5.2.4 on 2025-08-13 20:26
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('family', '0004_remove_challenge_obtained'),
]
operations = [
migrations.AlterUniqueTogether(
name='achievement',
unique_together={('challenge', 'family')},
),
]

View File

@@ -170,6 +170,7 @@ class Achievement(models.Model):
) )
class Meta: class Meta:
unique_together = ('challenge', 'family',)
verbose_name = _('achievement') verbose_name = _('achievement')
verbose_name_plural = _('achievements') verbose_name_plural = _('achievements')

View File

@@ -25,11 +25,6 @@ $(document).ready(function () {
location.hash = this.getAttribute('href') location.hash = this.getAttribute('href')
}) })
// Ensure we begin in single consumption. Fix issue with TurboLinks and BootstrapJS
document.getElementById("consume_all").addEventListener('click', consumeAll)
}) })
notes = [] notes = []
@@ -140,13 +135,25 @@ function consumeAll () {
headers: { headers: {
'X-CSRFToken': CSRF_TOKEN 'X-CSRFToken': CSRF_TOKEN
}, },
success: function () { success: function (data) {
reset() reset()
addMsg("Défis validés pour les familles!", 'success', 5000) data.results.forEach(function (result) {
}, if (result.status === 'created') {
error: function (e) { addMsg(
reset() interpolate(gettext('Invalid achievement for challenge %s ' +
addMsg("Erreur lors de la création des achievements.",'danger',5000) 'and family %s created.'), [result.challenge, result.family]),
'success',
5000
)
} else {
addMsg(
interpolate(gettext('An achievement for challenge %s ' +
'and family %s already exists.'), [result.challenge, result.family]),
'danger',
8000
)
}
})
} }
}) })
} }

View File

@@ -177,25 +177,27 @@ SPDX-License-Identifier: GPL-3.0-or-later
<div class="modal-dialog modal-dialog-centered" role="document"> <div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content border-success"> <div class="modal-content border-success">
<div class="modal-header bg-success text-white"> <div class="modal-header bg-success text-white">
<h5 class="modal-title" id="validationModalLabel">{% trans "Challenge validated" %}</h5> <h5 class="modal-title" id="validationModalLabel">{% trans "Confirmation" %}</h5>
<button type="button" class="close text-white" data-dismiss="modal" aria-label="Close"> <button type="button" class="close text-white" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span> <span aria-hidden="true">&times;</span>
</button> </button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<p><strong>Are you sure you want to validate this challenge?</strong></p> <p><strong>{% trans "Are you sure you want to validate this challenge?" %}</strong></p>
<p>To have your challenge officially validated, please send a message with:</p> <p>{% trans "To have your challenge officially validated, please send a message with:" %}</p>
<ul> <ul>
<li>The name of the family</li> <li>{% trans "The name of the family" %}</li>
<li>The name of the challenge</li> <li>{% trans "The name of the challenge" %}</li>
<li>A photo or video as proof</li> <li>{% trans "A photo or video as proof" %}</li>
</ul> </ul>
<p> <p>
<strong>Send it via WhatsApp to: <strong>{% trans "Send it via WhatsApp to:" %}</strong>
{% for num in phone_numbers %} {% if phone_numbers %}"
<a href="https://wa.me/{{ num }}" target="_blank">{{ num }}</a>{% if not forloop.last %}, {% endif %} {% for num in phone_numbers %}
{% endfor %} <a href="https://wa.me/{{ num }}" target="_blank">{{ num }}</a>{% if not forloop.last %}, {% endif %}
</p> {% endfor %}
{% endif %}
</p>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal">{% trans "OK" %}</button> <button type="button" class="btn btn-primary" data-dismiss="modal">{% trans "OK" %}</button>
@@ -228,6 +230,10 @@ SPDX-License-Identifier: GPL-3.0-or-later
$('#validationModal').modal('show'); $('#validationModal').modal('show');
}); });
$('#validationModal .btn-primary').on('click', function () {
consumeAll();
});
{% if user_family %} {% if user_family %}
document.getElementById("select_my_family").addEventListener("click", function () { document.getElementById("select_my_family").addEventListener("click", function () {
// Simulate selecting the user's family // Simulate selecting the user's family

View File

@@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: \n" "Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-08-13 16:21+0200\n" "POT-Creation-Date: 2025-08-13 23:48+0200\n"
"PO-Revision-Date: 2022-04-11 22:05+0200\n" "PO-Revision-Date: 2022-04-11 22:05+0200\n"
"Last-Translator: ehouarn <ehouarn@crans.org>\n" "Last-Translator: ehouarn <ehouarn@crans.org>\n"
"Language-Team: French <http://translate.ynerant.fr/projects/nk20/nk20/fr/>\n" "Language-Team: French <http://translate.ynerant.fr/projects/nk20/nk20/fr/>\n"
@@ -589,7 +589,6 @@ msgstr "adhésions"
#: apps/family/models.py:108 #: apps/family/models.py:108
#, python-brace-format #, python-brace-format
#| msgid "Membership of {user} for the club {club}"
msgid "Family membership of {user} to {family}" msgid "Family membership of {user} to {family}"
msgstr "Adhésion de {user} à la famille {family}" msgstr "Adhésion de {user} à la famille {family}"
@@ -610,15 +609,15 @@ msgstr "défis"
msgid "obtained at" msgid "obtained at"
msgstr "réalisé le" msgstr "réalisé le"
#: apps/family/models.py:173 #: apps/family/models.py:174
msgid "achievement" msgid "achievement"
msgstr "succès" msgstr "succès"
#: apps/family/models.py:174 #: apps/family/models.py:175
msgid "achievements" msgid "achievements"
msgstr "succès" msgstr "succès"
#: apps/family/models.py:177 #: apps/family/models.py:178
#, python-brace-format #, python-brace-format
msgid "Challenge {challenge} carried out by Family {family}" msgid "Challenge {challenge} carried out by Family {family}"
msgstr "Défi {challenge} réalisé par la famille {family}" msgstr "Défi {challenge} réalisé par la famille {family}"
@@ -655,15 +654,12 @@ msgid "Delete achievement"
msgstr "Supprimer le succès" msgstr "Supprimer le succès"
#: apps/family/templates/family/achievement_confirm_delete.html:14 #: apps/family/templates/family/achievement_confirm_delete.html:14
#, fuzzy
#| msgid ""
#| "Are you sure you want to delete this invoice? This action can't be undone."
msgid "" msgid ""
"Are you sure you want to delete this achievement? This action can't be " "Are you sure you want to delete this achievement? This action can't be "
"undone." "undone."
msgstr "" msgstr ""
"Êtes-vous sûr⋅e de vouloir supprimer cette facture ? Cette action ne pourra " "Êtes-vous sûr⋅e de vouloir supprimer ce succès ? Cette action ne pourra pas "
"pas être annulée." "être annulée."
#: apps/family/templates/family/achievement_confirm_delete.html:20 #: apps/family/templates/family/achievement_confirm_delete.html:20
#: apps/family/templates/family/achievement_confirm_validate.html:20 #: apps/family/templates/family/achievement_confirm_validate.html:20
@@ -675,15 +671,12 @@ msgid "Validate achievement"
msgstr "Valider le succès" msgstr "Valider le succès"
#: apps/family/templates/family/achievement_confirm_validate.html:14 #: apps/family/templates/family/achievement_confirm_validate.html:14
#, fuzzy
#| msgid ""
#| "Are you sure you want to delete this invoice? This action can't be undone."
msgid "" msgid ""
"Are you sure you want to validate this achievement? This action can't be " "Are you sure you want to validate this achievement? This action can't be "
"undone." "undone."
msgstr "" msgstr ""
"Êtes-vous sûr⋅e de vouloir supprimer cette facture ? Cette action ne pourra " "Êtes-vous sûr⋅e de vouloir valider ce succès ? Cette action ne pourra pas "
"pas être annulée." "être annulée."
#: apps/family/templates/family/achievement_list.html:13 #: apps/family/templates/family/achievement_list.html:13
msgid "Invalid achievements history" msgid "Invalid achievements history"
@@ -801,10 +794,36 @@ msgid "Recent achievements history"
msgstr "Historique des derniers succès" msgstr "Historique des derniers succès"
#: apps/family/templates/family/manage.html:180 #: apps/family/templates/family/manage.html:180
msgid "Challenge validated" msgid "Confirmation"
msgstr "Défi validé" msgstr "Confirmation"
#: apps/family/templates/family/manage.html:201 #: apps/family/templates/family/manage.html:186
msgid "Are you sure you want to validate this challenge?"
msgstr "Êtes-vous sûr⋅e de vouloir valider ce défi ?"
#: apps/family/templates/family/manage.html:187
msgid ""
"To have your challenge officially validated, please send a message with:"
msgstr ""
"Pour que le défi soit officiellement validé, envoyez un message contenant :"
#: apps/family/templates/family/manage.html:189
msgid "The name of the family"
msgstr "Le nom de la famille"
#: apps/family/templates/family/manage.html:190
msgid "The name of the challenge"
msgstr "Le nom du défi"
#: apps/family/templates/family/manage.html:191
msgid "A photo or video as proof"
msgstr "Une preuve photo ou vidéo"
#: apps/family/templates/family/manage.html:194
msgid "Send it via WhatsApp to:"
msgstr "Envoyez le via WhasApp au :"
#: apps/family/templates/family/manage.html:202
msgid "OK" msgid "OK"
msgstr "OK" msgstr "OK"
@@ -4641,6 +4660,9 @@ msgstr ""
"d'adhésion. Vous devez également valider votre adresse email en suivant le " "d'adhésion. Vous devez également valider votre adresse email en suivant le "
"lien que vous avez reçu." "lien que vous avez reçu."
#~ msgid "Challenge validated"
#~ msgstr "Défi validé"
#~ msgid "Deposit amount" #~ msgid "Deposit amount"
#~ msgstr "Caution" #~ msgstr "Caution"