manager: choose time period weekday indexes (#45159)
This commit is contained in:
parent
6c067790e1
commit
956c1fd183
|
@ -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
|
||||
|
@ -1288,11 +1289,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:
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -88,8 +88,7 @@
|
|||
</li>
|
||||
{% endif %}
|
||||
{% for time_period in desk.timeperiod_set.all %}
|
||||
<li><a rel="popup" href="{% url 'chrono-manager-time-period-edit' pk=time_period.id %}">
|
||||
{{time_period.weekday_str}} / {{time_period.start_time}} → {{time_period.end_time}}</a>
|
||||
<li><a rel="popup" href="{% url 'chrono-manager-time-period-edit' pk=time_period.id %}">{{ time_period }}</a>
|
||||
<a rel="popup" class="delete" href="{% url 'chrono-manager-time-period-delete' pk=time_period.id %}">{% trans "remove" %}</a>
|
||||
|
||||
</li>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{% extends "chrono/manager_agenda_view.html" %}
|
||||
{% load i18n %}
|
||||
{% load i18n gadjo %}
|
||||
|
||||
{% block extrascripts %}
|
||||
{{ block.super }}
|
||||
|
@ -30,10 +30,22 @@
|
|||
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
{{ form.as_p }}
|
||||
{{ form|with_template }}
|
||||
<div class="buttons">
|
||||
<button class="submit-button">{% trans "Save" %}</button>
|
||||
<a class="cancel" href="{% url 'chrono-manager-agenda-settings' pk=agenda.id %}">{% trans 'Cancel' %}</a>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$('input[type=radio][name=repeat]').change(function() {
|
||||
if(!this.checked)
|
||||
return;
|
||||
if(this.value == 'every-week') {
|
||||
$('select#id_weekday_indexes').hide();
|
||||
} else {
|
||||
$('select#id_weekday_indexes').show();
|
||||
}
|
||||
}).change();
|
||||
</script>
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
|
|
@ -66,8 +66,7 @@
|
|||
<div>
|
||||
<ul class="objects-list single-links">
|
||||
{% for time_period in agenda.excluded_timeperiods.all %}
|
||||
<li><a rel="popup" href="{% url 'chrono-manager-time-period-edit' pk=time_period.id %}">
|
||||
{{time_period.weekday_str}} / {{time_period.start_time}} → {{time_period.end_time}}</a>
|
||||
<li><a rel="popup" href="{% url 'chrono-manager-time-period-edit' pk=time_period.id %}">{{ time_period }}</a>
|
||||
<a rel="popup" class="delete" href="{% url 'chrono-manager-time-period-delete' pk=time_period.id %}">{% trans "remove" %}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
|
|
|
@ -2494,6 +2494,7 @@ def process_time_period_add_form(form, desk=None, agenda=None):
|
|||
weekday=weekday,
|
||||
start_time=form.cleaned_data['start_time'],
|
||||
end_time=form.cleaned_data['end_time'],
|
||||
weekday_indexes=form.cleaned_data['weekday_indexes'],
|
||||
)
|
||||
if desk:
|
||||
period.desk = desk
|
||||
|
|
|
@ -52,6 +52,7 @@ INSTALLED_APPS = (
|
|||
'django.contrib.sessions',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
'django.contrib.humanize',
|
||||
'gadjo',
|
||||
'chrono.agendas',
|
||||
'chrono.api',
|
||||
|
|
|
@ -25,6 +25,7 @@ def test_meetings_agenda_add_time_period(app, admin_user):
|
|||
assert TimePeriod.objects.get(desk=desk).start_time.minute == 0
|
||||
assert TimePeriod.objects.get(desk=desk).end_time.hour == 17
|
||||
assert TimePeriod.objects.get(desk=desk).end_time.minute == 0
|
||||
assert TimePeriod.objects.get(desk=desk).weekday_indexes is None
|
||||
assert desk2.timeperiod_set.exists() is False
|
||||
resp = resp.follow()
|
||||
|
||||
|
@ -33,9 +34,11 @@ def test_meetings_agenda_add_time_period(app, admin_user):
|
|||
resp.form.get('weekdays', index=0).checked = True
|
||||
resp.form['start_time'] = '10:00'
|
||||
resp.form['end_time'] = '13:00'
|
||||
resp.form['repeat'] = 'custom'
|
||||
resp.form['weekday_indexes'] = [1, 3]
|
||||
resp = resp.form.submit()
|
||||
resp = resp.follow()
|
||||
assert 'Monday / 10 a.m. → 1 p.m.' in resp.text
|
||||
assert 'Monday (1st, 3rd of the month) / 10 a.m. → 1 p.m.' in resp.text
|
||||
assert 'Wednesday / 10 a.m. → 5 p.m.' in resp.text
|
||||
assert resp.text.index('Monday') < resp.text.index('Wednesday')
|
||||
|
||||
|
@ -134,6 +137,19 @@ def test_meetings_agenda_edit_time_period(app, admin_user):
|
|||
time_period2.refresh_from_db()
|
||||
assert time_period2.start_time.hour == 9
|
||||
|
||||
resp = resp.click('Monday / 10 a.m. → noon')
|
||||
resp.form['repeat'] = 'custom'
|
||||
resp.form['weekday_indexes'] = [5]
|
||||
resp = resp.form.submit().follow()
|
||||
time_period.refresh_from_db()
|
||||
assert time_period.weekday_indexes == [5]
|
||||
|
||||
resp = resp.click('Monday \\(5th of the month\\) / 10 a.m. → noon')
|
||||
resp.form['repeat'] = 'every-week'
|
||||
resp = resp.form.submit().follow()
|
||||
time_period.refresh_from_db()
|
||||
assert time_period.weekday_indexes is None
|
||||
|
||||
# edit with inverted start/end
|
||||
resp2 = resp.click('Monday / 10 a.m. → noon')
|
||||
resp2.form['start_time'] = '18:00'
|
||||
|
|
Loading…
Reference in New Issue