From b62722dce99154ce5192ff87ddb80e2533dfa1af Mon Sep 17 00:00:00 2001 From: Valentin Deniaud Date: Thu, 10 Mar 2022 15:03:54 +0100 Subject: [PATCH 3/5] manager: choose time period weekday indexes (#45159) --- chrono/agendas/models.py | 13 ++++- chrono/manager/forms.py | 49 ++++++++++++++----- .../manager_meetings_agenda_settings.html | 3 +- .../chrono/manager_time_period_form.html | 16 +++++- .../manager_virtual_agenda_settings.html | 3 +- chrono/manager/views.py | 1 + chrono/settings.py | 1 + tests/manager/test_timeperiod.py | 18 ++++++- 8 files changed, 83 insertions(+), 21 deletions(-) diff --git a/chrono/agendas/models.py b/chrono/agendas/models.py index b6007286..9a353ea6 100644 --- a/chrono/agendas/models.py +++ b/chrono/agendas/models.py @@ -30,6 +30,7 @@ import vobject from dateutil.rrule import DAILY, WEEKLY, rrule, rruleset from django.conf import settings from django.contrib.auth.models import Group +from django.contrib.humanize.templatetags.humanize import ordinal from django.contrib.postgres.fields import ArrayField, JSONField from django.core.exceptions import FieldDoesNotExist, ValidationError from django.core.validators import MaxValueValidator, MinValueValidator @@ -1218,11 +1219,19 @@ class TimePeriod(models.Model): ordering = ['weekday', 'start_time'] def __str__(self): - return '%s / %s → %s' % ( - force_text(WEEKDAYS[self.weekday]), + label = force_text(WEEKDAYS[self.weekday]) + if self.weekday_indexes: + label = _('%(weekday)s (%(ordinals)s of the month)') % { + 'weekday': label, + 'ordinals': ', '.join(ordinal(i) for i in self.weekday_indexes), + } + + label = '%s / %s → %s' % ( + label, date_format(self.start_time, 'TIME_FORMAT'), date_format(self.end_time, 'TIME_FORMAT'), ) + return mark_safe(label) def save(self, *args, **kwargs): if self.agenda: diff --git a/chrono/manager/forms.py b/chrono/manager/forms.py index 6fa20e30..0b9c1122 100644 --- a/chrono/manager/forms.py +++ b/chrono/manager/forms.py @@ -36,6 +36,7 @@ from django.utils.timezone import localtime, make_aware, now from django.utils.translation import ugettext_lazy as _ from chrono.agendas.models import ( + WEEK_CHOICES, WEEKDAY_CHOICES, WEEKDAYS_LIST, AbsenceReason, @@ -699,27 +700,53 @@ class MeetingTypeForm(forms.ModelForm): ) -class TimePeriodAddForm(forms.Form): +class TimePeriodFormBase(forms.Form): + repeat = forms.ChoiceField( + label=_('Repeat'), + widget=forms.RadioSelect, + choices=( + ('every-week', _('Every week')), + ('custom', _('Custom')), + ), + initial='every-week', + ) + weekday_indexes = forms.TypedMultipleChoiceField( + choices=WEEK_CHOICES, + coerce=int, + required=False, + label='', + ) + + def clean(self): + cleaned_data = super().clean() + + if cleaned_data['end_time'] <= cleaned_data['start_time']: + raise ValidationError(_('End time must come after start time.')) + + if cleaned_data['repeat'] == 'every-week': + cleaned_data['weekday_indexes'] = None + + return cleaned_data + + +class TimePeriodAddForm(TimePeriodFormBase): + field_order = ['weekdays', 'start_time', 'end_time', 'repeat', 'weekday_indexes'] + weekdays = forms.MultipleChoiceField( label=_('Days'), widget=forms.CheckboxSelectMultiple(), choices=WEEKDAYS_LIST ) start_time = forms.TimeField(label=_('Start Time'), widget=widgets.TimeWidget()) end_time = forms.TimeField(label=_('End Time'), widget=widgets.TimeWidget()) - def clean_end_time(self): - if self.cleaned_data['end_time'] <= self.cleaned_data['start_time']: - raise ValidationError(_('End time must come after start time.')) - return self.cleaned_data['end_time'] - -class TimePeriodForm(forms.ModelForm): +class TimePeriodForm(TimePeriodFormBase, forms.ModelForm): class Meta: model = TimePeriod widgets = { 'start_time': widgets.TimeWidget(), 'end_time': widgets.TimeWidget(), } - exclude = ['agenda', 'desk'] + fields = ['weekday', 'start_time', 'end_time', 'repeat', 'weekday_indexes'] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -727,10 +754,8 @@ class TimePeriodForm(forms.ModelForm): self.old_start_time = self.instance.start_time self.old_end_time = self.instance.end_time - def clean_end_time(self): - if self.cleaned_data['end_time'] <= self.cleaned_data['start_time']: - raise ValidationError(_('End time must come after start time.')) - return self.cleaned_data['end_time'] + if self.instance.weekday_indexes: + self.fields['repeat'].initial = 'custom' def save(self): super().save() diff --git a/chrono/manager/templates/chrono/manager_meetings_agenda_settings.html b/chrono/manager/templates/chrono/manager_meetings_agenda_settings.html index d258c57d..7499a69c 100644 --- a/chrono/manager/templates/chrono/manager_meetings_agenda_settings.html +++ b/chrono/manager/templates/chrono/manager_meetings_agenda_settings.html @@ -88,8 +88,7 @@ {% endif %} {% for time_period in desk.timeperiod_set.all %} -
  • - {{time_period.weekday_str}} / {{time_period.start_time}} → {{time_period.end_time}} +
  • {{ time_period }} {% trans "remove" %}
  • diff --git a/chrono/manager/templates/chrono/manager_time_period_form.html b/chrono/manager/templates/chrono/manager_time_period_form.html index da2ba2b5..53eceb87 100644 --- a/chrono/manager/templates/chrono/manager_time_period_form.html +++ b/chrono/manager/templates/chrono/manager_time_period_form.html @@ -1,5 +1,5 @@ {% extends "chrono/manager_agenda_view.html" %} -{% load i18n %} +{% load i18n gadjo %} {% block extrascripts %} {{ block.super }} @@ -30,10 +30,22 @@
    {% csrf_token %} - {{ form.as_p }} + {{ form|with_template }}
    {% trans 'Cancel' %}
    + +
    {% endblock %} diff --git a/chrono/manager/templates/chrono/manager_virtual_agenda_settings.html b/chrono/manager/templates/chrono/manager_virtual_agenda_settings.html index ba34d09a..006c981c 100644 --- a/chrono/manager/templates/chrono/manager_virtual_agenda_settings.html +++ b/chrono/manager/templates/chrono/manager_virtual_agenda_settings.html @@ -66,8 +66,7 @@