manager: user_block used also in event detail page (#63915)
This commit is contained in:
parent
0b7ff2444d
commit
50963bb083
|
@ -15,7 +15,6 @@ class Migration(migrations.Migration):
|
|||
name='booking_user_block_template',
|
||||
field=models.TextField(
|
||||
blank=True,
|
||||
help_text='Displayed for each booking in event check page',
|
||||
verbose_name='User block template',
|
||||
validators=[chrono.agendas.models.django_template_validator],
|
||||
),
|
||||
|
|
|
@ -45,6 +45,7 @@ from django.utils.dates import WEEKDAYS
|
|||
from django.utils.encoding import force_text
|
||||
from django.utils.formats import date_format
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.html import escape
|
||||
from django.utils.module_loading import import_string
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.utils.text import slugify
|
||||
|
@ -226,7 +227,6 @@ class Agenda(models.Model):
|
|||
)
|
||||
booking_user_block_template = models.TextField(
|
||||
_('User block template'),
|
||||
help_text=_('Displayed for each booking in event check page'),
|
||||
blank=True,
|
||||
validators=[django_template_validator],
|
||||
)
|
||||
|
@ -2016,14 +2016,14 @@ class Booking(models.Model):
|
|||
self.event.set_is_checked()
|
||||
|
||||
def get_user_block(self):
|
||||
template_vars = Context(settings.TEMPLATE_VARS)
|
||||
template_vars = Context(settings.TEMPLATE_VARS, autoescape=False)
|
||||
template_vars.update(
|
||||
{
|
||||
'booking': self,
|
||||
}
|
||||
)
|
||||
try:
|
||||
return Template(self.event.agenda.get_booking_user_block_template()).render(template_vars)
|
||||
return escape(Template(self.event.agenda.get_booking_user_block_template()).render(template_vars))
|
||||
except (VariableDoesNotExist, TemplateSyntaxError):
|
||||
return
|
||||
|
||||
|
@ -3161,14 +3161,14 @@ class Subscription(models.Model):
|
|||
return _('Subscription')
|
||||
|
||||
def get_user_block(self):
|
||||
template_vars = Context(settings.TEMPLATE_VARS)
|
||||
template_vars = Context(settings.TEMPLATE_VARS, autoescape=False)
|
||||
template_vars.update(
|
||||
{
|
||||
'booking': self,
|
||||
}
|
||||
)
|
||||
try:
|
||||
return Template(self.agenda.get_booking_user_block_template()).render(template_vars)
|
||||
return escape(Template(self.agenda.get_booking_user_block_template()).render(template_vars))
|
||||
except (VariableDoesNotExist, TemplateSyntaxError):
|
||||
return
|
||||
|
||||
|
|
|
@ -116,7 +116,6 @@ class AgendaEditForm(forms.ModelForm):
|
|||
'anonymize_delay',
|
||||
'default_view',
|
||||
'booking_form_url',
|
||||
'event_display_template',
|
||||
'events_type',
|
||||
]
|
||||
|
||||
|
@ -124,7 +123,6 @@ class AgendaEditForm(forms.ModelForm):
|
|||
super().__init__(*args, **kwargs)
|
||||
if kwargs['instance'].kind != 'events':
|
||||
del self.fields['booking_form_url']
|
||||
del self.fields['event_display_template']
|
||||
del self.fields['events_type']
|
||||
self.fields['default_view'].choices = [
|
||||
(k, v) for k, v in self.fields['default_view'].choices if k != 'open_events'
|
||||
|
@ -1288,17 +1286,31 @@ class EventCancelForm(forms.ModelForm):
|
|||
fields = []
|
||||
|
||||
|
||||
class AgendaDisplaySettingsForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Agenda
|
||||
fields = [
|
||||
'event_display_template',
|
||||
'booking_user_block_template',
|
||||
]
|
||||
widgets = {'booking_user_block_template': forms.Textarea(attrs={'rows': 3})}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.fields['booking_user_block_template'].help_text = (
|
||||
_('Displayed for each booking in event page and check page'),
|
||||
)
|
||||
|
||||
|
||||
class AgendaBookingCheckSettingsForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Agenda
|
||||
fields = [
|
||||
'check_type_group',
|
||||
'booking_check_filters',
|
||||
'booking_user_block_template',
|
||||
'mark_event_checked_auto',
|
||||
'disable_check_update',
|
||||
]
|
||||
widgets = {'booking_user_block_template': forms.Textarea(attrs={'rows': 3})}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
<ul class="objects-list single-links">
|
||||
{% for booking in booked %}
|
||||
<li>
|
||||
<a {% if booking.get_backoffice_url %}href="{{ booking.get_backoffice_url }}"{% endif %}>{{ booking.events_display }}</a>
|
||||
<a {% if booking.get_backoffice_url %}href="{{ booking.get_backoffice_url }}"{% endif %}>{{ booking.get_user_block }}, {{ booking.creation_datetime|date:"DATETIME_FORMAT" }}</a>
|
||||
{% if not booking.primary_booking %}
|
||||
<a rel="popup" class="delete" href="{% url 'chrono-manager-booking-cancel' pk=agenda.id booking_pk=booking.id %}?next={{ request.path }}">{% trans "Cancel" %}</a>
|
||||
{% else %}
|
||||
|
@ -53,7 +53,7 @@
|
|||
<div>
|
||||
<ul class="objects-list single-links">
|
||||
{% for booking in waiting %}
|
||||
<li><a {% if booking.get_backoffice_url %}href="{{ booking.get_backoffice_url }}"{% endif %}>{{ booking.events_display }}</a></li>
|
||||
<li><a {% if booking.get_backoffice_url %}href="{{ booking.get_backoffice_url }}"{% endif %}>{{ booking.get_user_block }}, {{ booking.creation_datetime|date:"DATETIME_FORMAT" }}</a></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
|
|
|
@ -30,6 +30,28 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<h3>{% trans "Display options" %}
|
||||
<a rel="popup" class="button" href="{% url 'chrono-manager-agenda-display-settings' pk=object.pk %}">{% trans 'Configure' %}</a>
|
||||
</h3>
|
||||
<div>
|
||||
<ul>
|
||||
<li>
|
||||
{% if agenda.event_display_template %}
|
||||
{% trans "Event display template:" %}
|
||||
<pre>{{ agenda.event_display_template }}</pre>
|
||||
{% else %}
|
||||
{% trans "No event display template configured for this agenda." %}
|
||||
{% endif %}
|
||||
</li>
|
||||
<li>
|
||||
{% trans "Booking display template:" %}
|
||||
<pre>{{ agenda.get_booking_user_block_template }}</pre>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<h3>{% trans "Booking check options" %}
|
||||
<a rel="popup" class="button" href="{% url 'chrono-manager-agenda-booking-check-settings' pk=object.pk %}">{% trans 'Configure' %}</a>
|
||||
|
@ -79,11 +101,6 @@
|
|||
{% endif %}
|
||||
{% endwith %}
|
||||
|
||||
<li>
|
||||
{% trans "User block template:" %}
|
||||
<pre>{{ agenda.get_booking_user_block_template }}</pre>
|
||||
</li>
|
||||
|
||||
<li>{% trans "Automatically mark event as checked when all bookings have been checked:" %} {{ agenda.mark_event_checked_auto|yesno }}</li>
|
||||
<li>{% trans "Prevent the check of bookings when event was marked as checked:" %} {{ agenda.disable_check_update|yesno }}</li>
|
||||
</ul>
|
||||
|
|
|
@ -166,6 +166,11 @@ urlpatterns = [
|
|||
name='chrono-manager-agenda-booking-delays',
|
||||
),
|
||||
url(r'^agendas/(?P<pk>\d+)/roles$', views.agenda_roles, name='chrono-manager-agenda-roles'),
|
||||
url(
|
||||
r'^agendas/(?P<pk>\d+)/display-options$',
|
||||
views.agenda_display_settings,
|
||||
name='chrono-manager-agenda-display-settings',
|
||||
),
|
||||
url(
|
||||
r'^agendas/(?P<pk>\d+)/check-options$',
|
||||
views.agenda_booking_check_settings,
|
||||
|
|
|
@ -92,6 +92,7 @@ from .forms import (
|
|||
AgendaAddForm,
|
||||
AgendaBookingCheckSettingsForm,
|
||||
AgendaBookingDelaysForm,
|
||||
AgendaDisplaySettingsForm,
|
||||
AgendaDuplicateForm,
|
||||
AgendaEditForm,
|
||||
AgendaNotificationsForm,
|
||||
|
@ -1194,6 +1195,20 @@ class AgendaRolesView(AgendaEditView):
|
|||
agenda_roles = AgendaRolesView.as_view()
|
||||
|
||||
|
||||
class AgendaDisplaySettingsView(AgendaEditView):
|
||||
form_class = AgendaDisplaySettingsForm
|
||||
title = _("Configure display options")
|
||||
|
||||
def set_agenda(self, **kwargs):
|
||||
self.agenda = get_object_or_404(Agenda, pk=kwargs.get('pk'), kind='events')
|
||||
|
||||
def get_initial(self):
|
||||
return {'booking_user_block_template': self.agenda.get_booking_user_block_template()}
|
||||
|
||||
|
||||
agenda_display_settings = AgendaDisplaySettingsView.as_view()
|
||||
|
||||
|
||||
class AgendaBookingCheckSettingsView(AgendaEditView):
|
||||
form_class = AgendaBookingCheckSettingsForm
|
||||
title = _("Configure booking check options")
|
||||
|
|
|
@ -386,7 +386,6 @@ def test_options_agenda(app, admin_user):
|
|||
assert resp.context['form'].initial['default_view'] == 'month'
|
||||
assert 'open_events' in [k for k, v in resp.context['form'].fields['default_view'].choices]
|
||||
assert 'booking_form_url' in resp.context['form'].fields
|
||||
assert 'event_display_template' in resp.context['form'].fields
|
||||
resp = resp.form.submit()
|
||||
assert resp.location.endswith('/manage/agendas/%s/settings' % agenda_events.pk)
|
||||
resp = resp.follow()
|
||||
|
@ -400,7 +399,6 @@ def test_options_agenda(app, admin_user):
|
|||
assert 'default_view' in resp.context['form'].fields
|
||||
assert 'open_events' not in [k for k, v in resp.context['form'].fields['default_view'].choices]
|
||||
assert 'booking_form_url' not in resp.context['form'].fields
|
||||
assert 'event_display_template' not in resp.context['form'].fields
|
||||
|
||||
resp.form['default_view'] = 'month'
|
||||
resp.form.submit()
|
||||
|
@ -415,7 +413,6 @@ def test_options_agenda(app, admin_user):
|
|||
assert 'default_view' in resp.context['form'].fields
|
||||
assert 'open_events' not in [k for k, v in resp.context['form'].fields['default_view'].choices]
|
||||
assert 'booking_form_url' not in resp.context['form'].fields
|
||||
assert 'event_display_template' not in resp.context['form'].fields
|
||||
|
||||
|
||||
def test_options_events_agenda_events_type(app, admin_user):
|
||||
|
@ -478,9 +475,11 @@ def test_options_virtual_agenda_delays(app, admin_user):
|
|||
assert agenda.maximal_booking_delay is None
|
||||
|
||||
|
||||
def test_options_agenda_booking_check_options(app, admin_user):
|
||||
def test_options_agenda_booking_display_options(app, admin_user):
|
||||
agenda = Agenda.objects.create(label='Foo bar', kind='events')
|
||||
|
||||
app = login(app)
|
||||
|
||||
# check user template
|
||||
assert agenda.booking_user_block_template == ''
|
||||
assert (
|
||||
|
@ -488,8 +487,7 @@ def test_options_agenda_booking_check_options(app, admin_user):
|
|||
== '{{ booking.user_name|default:booking.label|default:"Anonymous" }}'
|
||||
)
|
||||
|
||||
app = login(app)
|
||||
url = '/manage/agendas/%s/check-options' % agenda.pk
|
||||
url = '/manage/agendas/%s/display-options' % agenda.pk
|
||||
resp = app.get(url)
|
||||
resp.form['booking_user_block_template'] = '{{ booking.user_name }} Foo Bar'
|
||||
resp = resp.form.submit()
|
||||
|
@ -507,10 +505,44 @@ def test_options_agenda_booking_check_options(app, admin_user):
|
|||
== '{{ booking.user_name|default:booking.label|default:"Anonymous" }}'
|
||||
)
|
||||
|
||||
resp = app.get(url)
|
||||
valid_template = '{{ event.label|default:event.slug }} - {{ event.remaining_places|add:"5" }} / {{ event.start_datetime|date }} - {{ event.agenda.name }}'
|
||||
resp.form['event_display_template'] = valid_template
|
||||
resp = resp.form.submit().follow()
|
||||
|
||||
agenda.refresh_from_db()
|
||||
assert agenda.event_display_template == valid_template
|
||||
|
||||
invalid_templates = [
|
||||
'{{ syntax error }}',
|
||||
'{{ event.label|invalidfilter }}',
|
||||
'{{ event.label|default:notexist }}',
|
||||
]
|
||||
for template in invalid_templates:
|
||||
resp = app.get(url)
|
||||
resp.form['event_display_template'] = template
|
||||
resp = resp.form.submit()
|
||||
assert 'syntax error' in resp.text
|
||||
|
||||
# check kind
|
||||
agenda.kind = 'meetings'
|
||||
agenda.save()
|
||||
app.get(url, status=404)
|
||||
agenda.kind = 'virtual'
|
||||
agenda.save()
|
||||
app.get(url, status=404)
|
||||
|
||||
|
||||
def test_options_agenda_booking_check_options(app, admin_user):
|
||||
agenda = Agenda.objects.create(label='Foo bar', kind='events')
|
||||
|
||||
app = login(app)
|
||||
|
||||
# check filters
|
||||
assert agenda.booking_check_filters == ''
|
||||
assert agenda.get_booking_check_filters() == []
|
||||
|
||||
url = '/manage/agendas/%s/check-options' % agenda.pk
|
||||
resp = app.get(url)
|
||||
resp.form['booking_check_filters'] = 'foo,bar,baz'
|
||||
resp = resp.form.submit()
|
||||
|
@ -543,30 +575,6 @@ def test_options_agenda_booking_check_options(app, admin_user):
|
|||
app.get(url, status=404)
|
||||
|
||||
|
||||
def test_options_agenda_event_display_template(app, admin_user):
|
||||
agenda = Agenda.objects.create(label='Foo bar', kind='events')
|
||||
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
|
||||
app = login(app)
|
||||
resp = app.get('/manage/agendas/%s/edit' % agenda.pk)
|
||||
valid_template = '{{ event.label|default:event.slug }} - {{ event.remaining_places|add:"5" }} / {{ event.start_datetime|date }} - {{ event.agenda.name }}'
|
||||
resp.form['event_display_template'] = valid_template
|
||||
resp = resp.form.submit().follow()
|
||||
|
||||
agenda.refresh_from_db()
|
||||
assert agenda.event_display_template == valid_template
|
||||
|
||||
invalid_templates = [
|
||||
'{{ syntax error }}',
|
||||
'{{ event.label|invalidfilter }}',
|
||||
'{{ event.label|default:notexist }}',
|
||||
]
|
||||
for template in invalid_templates:
|
||||
resp = app.get('/manage/agendas/%s/edit' % agenda.pk)
|
||||
resp.form['event_display_template'] = template
|
||||
resp = resp.form.submit()
|
||||
assert 'syntax error' in resp.text
|
||||
|
||||
|
||||
def test_options_agenda_as_manager(app, manager_user):
|
||||
agenda = Agenda(label='Foo bar')
|
||||
agenda.view_role = manager_user.groups.all()[0]
|
||||
|
|
|
@ -1112,6 +1112,35 @@ def test_import_events_wrong_kind(app, admin_user):
|
|||
app.get('/manage/agendas/%s/import-events' % agenda.id, status=404)
|
||||
|
||||
|
||||
@pytest.mark.freeze_time('2022-05-24')
|
||||
def test_event_detail(app, admin_user):
|
||||
agenda = Agenda.objects.create(label='Events', kind='events')
|
||||
event = Event.objects.create(
|
||||
label='xyz',
|
||||
start_datetime=now() + datetime.timedelta(days=1),
|
||||
places=10,
|
||||
waiting_list_places=2,
|
||||
agenda=agenda,
|
||||
)
|
||||
Booking.objects.create(event=event, user_last_name="User's 1")
|
||||
Booking.objects.create(event=event, user_last_name='User 2', in_waiting_list=True)
|
||||
|
||||
login(app)
|
||||
resp = app.get('/manage/agendas/%d/events/%d/' % (agenda.pk, event.pk))
|
||||
assert 'Bookings (1/10)' in resp.text
|
||||
assert 'User's 1, May 24, 2022, 2 a.m.' in resp.text
|
||||
assert 'Waiting List (1/2): 1 remaining place' in resp.text
|
||||
assert 'User 2, May 24, 2022, 2 a.m.' in resp.text
|
||||
|
||||
agenda.booking_user_block_template = '<b>{{ booking.user_name }}</b> Foo Bar'
|
||||
agenda.save()
|
||||
resp = app.get('/manage/agendas/%d/events/%d/' % (agenda.pk, event.pk))
|
||||
assert 'Bookings (1/10)' in resp.text
|
||||
assert '<b>User's 1</b> Foo Bar, May 24, 2022, 2 a.m.' in resp.text
|
||||
assert 'Waiting List (1/2): 1 remaining place' in resp.text
|
||||
assert '<b>User 2</b> Foo Bar, May 24, 2022, 2 a.m.' in resp.text
|
||||
|
||||
|
||||
def test_event_cancellation(app, admin_user):
|
||||
agenda = Agenda.objects.create(label='Events', kind='events')
|
||||
event = Event.objects.create(
|
||||
|
@ -1125,8 +1154,8 @@ def test_event_cancellation(app, admin_user):
|
|||
resp = resp.click('Cancel', href='/cancel')
|
||||
assert 'related bookings' not in resp.text
|
||||
|
||||
Booking.objects.create(event=event)
|
||||
Booking.objects.create(event=event)
|
||||
Booking.objects.create(event=event, user_last_name='User 1')
|
||||
Booking.objects.create(event=event, user_last_name='User 2')
|
||||
|
||||
resp = app.get('/manage/agendas/%d/events/%d/' % (agenda.pk, event.pk))
|
||||
assert 'Bookings (2/10)' in resp.text
|
||||
|
@ -1366,7 +1395,7 @@ def test_event_check(app, admin_user):
|
|||
event=event, user_external_id='user:1', user_first_name='User', user_last_name='42'
|
||||
)
|
||||
Booking.objects.create(
|
||||
event=event, user_external_id='user:2', user_first_name='User', user_last_name='01'
|
||||
event=event, user_external_id='user:2', user_first_name="User's", user_last_name='01'
|
||||
)
|
||||
Booking.objects.create(
|
||||
event=event, user_external_id='user:3', user_first_name='User', user_last_name='17'
|
||||
|
@ -1424,7 +1453,7 @@ def test_event_check(app, admin_user):
|
|||
resp = resp.click('Check')
|
||||
assert (
|
||||
resp.text.index('Bookings (6/10)')
|
||||
< resp.text.index('User 01')
|
||||
< resp.text.index("User's 01")
|
||||
< resp.text.index('User 05')
|
||||
< resp.text.index('User 17')
|
||||
< resp.text.index('User 35')
|
||||
|
@ -1486,7 +1515,7 @@ def test_event_check(app, admin_user):
|
|||
resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk))
|
||||
assert (
|
||||
resp.text.index('Bookings (6/10)')
|
||||
< resp.text.index('User 01')
|
||||
< resp.text.index("User's 01")
|
||||
< resp.text.index('User 05')
|
||||
< resp.text.index('User 12 Cancelled')
|
||||
< resp.text.index('Subscription 14')
|
||||
|
@ -1504,12 +1533,12 @@ def test_event_check(app, admin_user):
|
|||
assert 'Subscription too soon' not in resp
|
||||
assert 'Subscription too late' not in resp
|
||||
|
||||
agenda.booking_user_block_template = '{{ booking.user_name }} Foo Bar'
|
||||
agenda.booking_user_block_template = '<b>{{ booking.user_name }}</b> Foo Bar'
|
||||
agenda.save()
|
||||
resp = app.get('/manage/agendas/%s/events/%s/check' % (agenda.pk, event.pk))
|
||||
assert 'User 01 Foo Bar' in resp
|
||||
assert 'Subscription 14 Foo Bar' in resp
|
||||
assert 'User Waiting Foo Bar' in resp
|
||||
assert '<b>User's 01</b> Foo Bar' in resp
|
||||
assert '<b>Subscription 14</b> Foo Bar' in resp
|
||||
assert '<b>User Waiting</b> Foo Bar' in resp
|
||||
|
||||
# cancelled booking
|
||||
token = resp.context['csrf_token']
|
||||
|
|
Loading…
Reference in New Issue