mirror of
https://gitlab.crans.org/bde/nk20
synced 2025-08-14 09:56:38 +02:00
Achievement unicity && management pop-up behaviour
This commit is contained in:
@@ -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)
|
||||||
|
@@ -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')},
|
||||||
|
),
|
||||||
|
]
|
@@ -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')
|
||||||
|
|
||||||
|
@@ -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
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@@ -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">×</span>
|
<span aria-hidden="true">×</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>
|
||||||
@@ -227,6 +229,10 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
|||||||
document.getElementById("consume_all").addEventListener("click", function () {
|
document.getElementById("consume_all").addEventListener("click", function () {
|
||||||
$('#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 () {
|
||||||
|
@@ -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"
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user