Compare commits

..

7 Commits

Author SHA1 Message Date
Yann Weber 3680938041 manager: fix agenda's role edition when partial booking enabled (#85999)
gitea/chrono/pipeline/head There was a failure building this commit Details
2024-01-30 09:40:34 +01:00
Frédéric Péters 9a1b37a5f7 translation update
gitea/chrono/pipeline/head This commit looks good Details
2024-01-23 14:21:30 +01:00
Frédéric Péters 5204fcda47 trivial: adjust spelling and typography (#85974) 2024-01-23 14:21:14 +01:00
Yann Weber 9945568a57 manager: add error when deleting an EventType linked to an Agenda (#85974)
gitea/chrono/pipeline/head This commit looks good Details
2024-01-23 14:14:46 +01:00
Yann Weber d428ef8385 agendas: change on_delete for Agenda -> EventsType to SET_NULL (#85974) 2024-01-23 14:14:46 +01:00
Frédéric Péters 9c660e7a1e misc: adjust title of meeting type deletion confirmation dialog (#85773)
gitea/chrono/pipeline/head This commit looks good Details
2024-01-18 20:26:38 +01:00
Yann Weber 47e7558298 manager: add __str__ to MeetingType, translating deletion popup (#85718)
gitea/chrono/pipeline/head This commit looks good Details
2024-01-17 11:23:18 +01:00
6 changed files with 133 additions and 7 deletions

View File

@ -0,0 +1,25 @@
# Generated by Django 3.2.18 on 2024-01-22 10:55
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('agendas', '0169_urlfield_maxlength_increase'),
]
operations = [
migrations.AlterField(
model_name='agenda',
name='events_type',
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name='agendas',
to='agendas.eventstype',
verbose_name='Events type',
),
),
]

View File

@ -278,7 +278,7 @@ class Agenda(models.Model):
events_type = models.ForeignKey(
'agendas.EventsType',
verbose_name=_('Events type'),
on_delete=models.CASCADE,
on_delete=models.SET_NULL,
related_name='agendas',
null=True,
blank=True,
@ -2009,6 +2009,10 @@ class MeetingType(models.Model):
class Meta:
ordering = ['duration', 'label']
unique_together = ['agenda', 'slug']
verbose_name = _('Meeting type')
def __str__(self):
return '%s - %s' % (self._meta.verbose_name, self.label)
def save(self, *args, **kwargs):
assert self.agenda.kind != 'virtual', "a meetingtype can't reference a virtual agenda"

View File

@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: chrono 0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-12-22 10:50+0000\n"
"PO-Revision-Date: 2023-12-22 11:50+0100\n"
"POT-Creation-Date: 2024-01-23 13:18+0000\n"
"PO-Revision-Date: 2024-01-23 14:20+0100\n"
"Last-Translator: Frederic Peters <fpeters@entrouvert.com>\n"
"Language: French\n"
"MIME-Version: 1.0\n"
@ -404,6 +404,10 @@ msgstr "Durée (en minutes)"
msgid "Deleted"
msgstr "Supprimé"
#: agendas/models.py
msgid "Meeting type"
msgstr "Type de rendez-vous"
#: agendas/models.py manager/forms.py
msgid "Every week"
msgstr "Toutes les semaines"
@ -1401,14 +1405,14 @@ msgstr "il nest pas possible de modifier la valeur de user_external_id"
msgid "missing param user_external_id"
msgstr "paramètre manquant user_external_id"
#: api/views.py
msgid "booking is cancelled"
msgstr "la réservation est annulée"
#: api/views.py
msgid "secondary booking"
msgstr "réservation secondaire"
#: api/views.py
msgid "booking is cancelled"
msgstr "la réservation est annulée"
#: api/views.py
msgid "booking is in waiting list"
msgstr "la réservation est dans la liste dattente"
@ -3797,6 +3801,15 @@ msgstr "Se connecter"
msgid "Week %s"
msgstr "Semaine %s"
#: manager/views.py
#, python-format
msgid "Cannot delete event type \"%(event_type_name)s\""
msgstr "Impossible de supprimer le type dévènement « %(event_type_name)s »"
#: manager/views.py
msgid "Following agendas are still using this event type:"
msgstr "Ces agendas utilisent ce type dévènement :"
#: manager/views.py
msgid "File is not in the expected JSON format."
msgstr "Le fichier nest pas dans le format JSON attendu."

View File

@ -44,6 +44,7 @@ from django.utils.encoding import force_str
from django.utils.formats import date_format
from django.utils.functional import cached_property
from django.utils.html import format_html
from django.utils.safestring import SafeString
from django.utils.translation import gettext_lazy as _
from django.utils.translation import ngettext
from django.views.generic import (
@ -884,6 +885,41 @@ class EventsTypeDeleteView(DeleteView):
raise PermissionDenied()
return super().dispatch(request, *args, **kwargs)
def can_be_deleted(self):
return self.get_object().agendas.count() == 0
def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs)
if self.can_be_deleted():
return ctx
obj = self.get_object()
ctx['cannot_delete'] = True
title = '<h3>%(title)s</h3>' % {
'title': _('Cannot delete event type "%(event_type_name)s"') % {'event_type_name': obj}
}
msg = _('Following agendas are still using this event type:')
lst = '<ul><li>%(agendas)s</li></ul>' % {
'agendas': '</li><li>'.join(
[
'<a href="%s">%s</a>'
% (reverse('chrono-manager-agenda-view', kwargs={'pk': agenda.pk}), agenda)
for agenda in obj.agendas.all()
]
)
}
ctx['cannot_delete_msg'] = SafeString(
'%(title)s %(msg)s %(agendas)s' % {'title': title, 'msg': msg, 'agendas': lst}
)
return ctx
def post(self, *args, **kwargs):
if self.can_be_deleted():
return super().post(*args, **kwargs)
raise PermissionDenied()
def get_success_url(self):
return reverse('chrono-manager-events-type-list')

View File

@ -3206,6 +3206,15 @@ def test_cant_modify_meetingtype_used_by_virtual_agenda(app, admin_user):
assert mt.label == 'MTT'
def test_meetingtype_delete_popup_translation(app, admin_user):
meeting_agenda_1 = Agenda.objects.create(label='Meeting agenda 1', kind='meetings')
mt = MeetingType.objects.create(agenda=meeting_agenda_1, label='MT', slug='mt', duration=10)
app = login(app)
resp = app.get('/manage/meetingtypes/%s/delete' % mt.pk)
assert f'Meeting type - {mt.label}' in resp.text
def test_cant_add_meetingtype_if_virtual_agenda(app, admin_user):
agenda = Agenda.objects.create(label='My Virtual agenda', kind='virtual')
meeting_agenda_1 = Agenda.objects.create(label='Meeting agenda 1', kind='meetings')

View File

@ -162,6 +162,45 @@ def test_delete_events_type(app, admin_user):
assert EventsType.objects.exists() is False
def test_delete_referenced_events_type(app):
events_type = EventsType.objects.create(label='Foobar')
agenda = Agenda.objects.create(label='Foo Bar', events_type=events_type)
events_type.delete()
agenda = Agenda.objects.get(pk=agenda.pk)
assert agenda
assert agenda.events_type is None
def test_delete_referenced_events_type_error(app, admin_user):
events_type = EventsType.objects.create(label='Foobar')
agenda = Agenda.objects.create(label='Foo Bar', events_type=events_type)
app = login(app)
resp = app.get('/manage/events-types/', status=200)
resp = resp.click(href='/manage/events-type/%s/delete/' % events_type.pk)
resp.form.submit(status=403)
assert EventsType.objects.get(pk=events_type.pk)
assert 'Cannot delete event type "' in resp
assert '<a href="/manage/agendas/%s/">%s</a>' % (agenda.pk, agenda) in resp
agenda.delete()
# Now deletion should be OK
resp = app.get('/manage/events-types/', status=200)
resp = resp.click(href='/manage/events-type/%s/delete/' % events_type.pk)
assert 'Cannot delete event type "' not in resp
assert '<a href="/manage/agendas/%s/">%s</a>' % (agenda.pk, agenda) not in resp
resp.form.submit()
assert EventsType.objects.exists() is False
def test_delete_events_type_as_manager(app, manager_user):
agenda = Agenda(label='Foo Bar')
agenda.view_role = manager_user.groups.all()[0]