WIP: avoir un rôle d'administration (#66019) #252
|
@ -20,7 +20,7 @@ class Migration(migrations.Migration):
|
|||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
related_name='+',
|
||||
to='auth.Group',
|
||||
verbose_name='Edit Role',
|
||||
verbose_name='Admin Role',
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
|
|
|
@ -4,6 +4,8 @@ import django.contrib.postgres.fields
|
|||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
import chrono
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
|
@ -22,11 +24,7 @@ class Migration(migrations.Migration):
|
|||
'almost_full_event',
|
||||
models.CharField(
|
||||
blank=True,
|
||||
choices=[
|
||||
('edit-role', 'Edit Role'),
|
||||
('view-role', 'View Role'),
|
||||
('use-email-field', 'Specify email addresses manually'),
|
||||
],
|
||||
choices=chrono.agendas.models.AgendaNotificationsSettings.CHOICES,
|
||||
max_length=16,
|
||||
verbose_name='Almost full event (90%)',
|
||||
),
|
||||
|
@ -41,11 +39,7 @@ class Migration(migrations.Migration):
|
|||
'full_event',
|
||||
models.CharField(
|
||||
blank=True,
|
||||
choices=[
|
||||
('edit-role', 'Edit Role'),
|
||||
('view-role', 'View Role'),
|
||||
('use-email-field', 'Specify email addresses manually'),
|
||||
],
|
||||
choices=chrono.agendas.models.AgendaNotificationsSettings.CHOICES,
|
||||
max_length=16,
|
||||
verbose_name='Full event',
|
||||
),
|
||||
|
@ -60,11 +54,7 @@ class Migration(migrations.Migration):
|
|||
'cancelled_event',
|
||||
models.CharField(
|
||||
blank=True,
|
||||
choices=[
|
||||
('edit-role', 'Edit Role'),
|
||||
('view-role', 'View Role'),
|
||||
('use-email-field', 'Specify email addresses manually'),
|
||||
],
|
||||
choices=chrono.agendas.models.AgendaNotificationsSettings.CHOICES,
|
||||
max_length=16,
|
||||
verbose_name='Cancelled event',
|
||||
),
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
# Generated by Django 3.2.18 on 2024-04-24 08:02
|
||||
|
||||
import django
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('agendas', '0171_snapshot_models'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='agenda',
|
||||
name='edit_role',
|
||||
field=models.ForeignKey(
|
||||
# remove db_index as RenameField will not do it
|
||||
# https://code.djangoproject.com/ticket/23577
|
||||
db_index=False,
|
||||
blank=True,
|
||||
default=None,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
related_name='+',
|
||||
to='auth.group',
|
||||
verbose_name='Admin Role',
|
||||
),
|
||||
),
|
||||
migrations.RenameField(
|
||||
model_name='agenda',
|
||||
old_name='edit_role',
|
||||
new_name='admin_role',
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='agenda',
|
||||
name='admin_role',
|
||||
field=models.ForeignKey(
|
||||
blank=True,
|
||||
default=None,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
related_name='+',
|
||||
to='auth.group',
|
||||
verbose_name='Admin Role',
|
||||
),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,41 @@
|
|||
# Generated by Django 3.2.18 on 2024-04-24 13:20
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
def migrate_notification_settings_role(apps, schema_editor):
|
||||
AgendaNotificationsSettings = apps.get_model('agendas', 'AgendaNotificationsSettings')
|
||||
|
||||
AgendaNotificationsSettings.objects.filter(almost_full_event='edit-role').update(
|
||||
almost_full_event='admin-role',
|
||||
)
|
||||
AgendaNotificationsSettings.objects.filter(full_event='edit-role').update(
|
||||
full_event='admin-role',
|
||||
)
|
||||
AgendaNotificationsSettings.objects.filter(cancelled_event='edit-role').update(
|
||||
cancelled_event='admin-role',
|
||||
)
|
||||
|
||||
|
||||
def reverse_migrate_notification_settings_role(apps, schema_editor):
|
||||
AgendaNotificationsSettings = apps.get_model('agendas', 'AgendaNotificationsSettings')
|
||||
|
||||
AgendaNotificationsSettings.objects.filter(almost_full_event='admin-role').update(
|
||||
almost_full_event='edit-role',
|
||||
)
|
||||
AgendaNotificationsSettings.objects.filter(full_event='admin-role').update(
|
||||
full_event='edit-role',
|
||||
)
|
||||
AgendaNotificationsSettings.objects.filter(cancelled_event='admin-role').update(
|
||||
cancelled_event='edit-role',
|
||||
)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('agendas', '0172_rename_edit_role_agenda_admin_role'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(migrate_notification_settings_role, reverse_migrate_notification_settings_role),
|
||||
]
|
|
@ -0,0 +1,27 @@
|
|||
# Generated by Django 3.2.18 on 2024-04-24 13:20
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('auth', '0012_alter_user_first_name_max_length'),
|
||||
('agendas', '0173_migrate_notification_settings_role'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='agenda',
|
||||
name='edit_role',
|
||||
field=models.ForeignKey(
|
||||
blank=True,
|
||||
default=None,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
related_name='+',
|
||||
to='auth.group',
|
||||
verbose_name='Edit Role',
|
||||
),
|
||||
),
|
||||
]
|
|
@ -250,6 +250,15 @@ class Agenda(WithSnapshotMixin, WithApplicationMixin, WithInspectMixin, models.M
|
|||
through='VirtualMember',
|
||||
through_fields=('virtual_agenda', 'real_agenda'),
|
||||
)
|
||||
admin_role = models.ForeignKey(
|
||||
Group,
|
||||
blank=True,
|
||||
null=True,
|
||||
default=None,
|
||||
related_name='+',
|
||||
verbose_name=_('Admin Role'),
|
||||
on_delete=models.SET_NULL,
|
||||
)
|
||||
edit_role = models.ForeignKey(
|
||||
Group,
|
||||
blank=True,
|
||||
|
@ -407,10 +416,16 @@ class Agenda(WithSnapshotMixin, WithApplicationMixin, WithInspectMixin, models.M
|
|||
if user.is_staff:
|
||||
return True
|
||||
group_ids = [x.id for x in user.groups.all()]
|
||||
return bool(self.admin_role_id in group_ids)
|
||||
|
||||
def can_be_edited(self, user):
|
||||
if self.can_be_managed(user):
|
||||
return True
|
||||
group_ids = [x.id for x in user.groups.all()]
|
||||
return bool(self.edit_role_id in group_ids)
|
||||
|
||||
def can_be_viewed(self, user):
|
||||
if self.can_be_managed(user):
|
||||
if self.can_be_edited(user):
|
||||
return True
|
||||
group_ids = [x.id for x in user.groups.all()]
|
||||
return bool(self.view_role_id in group_ids)
|
||||
|
@ -491,6 +506,7 @@ class Agenda(WithSnapshotMixin, WithApplicationMixin, WithInspectMixin, models.M
|
|||
|
||||
def get_dependencies(self):
|
||||
yield self.view_role
|
||||
yield self.admin_role
|
||||
yield self.edit_role
|
||||
yield self.category
|
||||
if self.kind == 'virtual':
|
||||
|
@ -515,6 +531,7 @@ class Agenda(WithSnapshotMixin, WithApplicationMixin, WithInspectMixin, models.M
|
|||
'permissions': {
|
||||
'view': self.view_role.name if self.view_role else None,
|
||||
'edit': self.edit_role.name if self.edit_role else None,
|
||||
'admin': self.admin_role.name if self.admin_role else None,
|
||||
},
|
||||
'default_view': self.default_view,
|
||||
}
|
||||
|
@ -564,11 +581,9 @@ class Agenda(WithSnapshotMixin, WithApplicationMixin, WithInspectMixin, models.M
|
|||
elif data['kind'] == 'virtual':
|
||||
excluded_timeperiods = data.pop('excluded_timeperiods')
|
||||
real_agendas = data.pop('real_agendas')
|
||||
for permission in ('view', 'edit'):
|
||||
for permission in ('view', 'admin', 'edit'):
|
||||
if permissions.get(permission):
|
||||
data[permission + '_role'] = Group.objects.get(name=permissions[permission])
|
||||
if permissions.get('admin'):
|
||||
data['edit_role'] = Group.objects.get(name=permissions['admin'])
|
||||
resources_slug = data.pop('resources', [])
|
||||
resources_by_slug = {r.slug: r for r in Resource.objects.filter(slug__in=resources_slug)}
|
||||
for resource_slug in resources_slug:
|
||||
|
@ -663,7 +678,7 @@ class Agenda(WithSnapshotMixin, WithApplicationMixin, WithInspectMixin, models.M
|
|||
return keys
|
||||
|
||||
def get_permissions_inspect_fields(self):
|
||||
yield from self.get_inspect_fields(keys=['edit_role', 'view_role'])
|
||||
yield from self.get_inspect_fields(keys=['admin_role', 'edit_role', 'view_role'])
|
||||
|
||||
def get_display_inspect_fields(self):
|
||||
keys = []
|
||||
|
@ -3729,7 +3744,7 @@ class Resource(WithSnapshotMixin, WithApplicationMixin, WithInspectMixin, models
|
|||
if user.is_staff:
|
||||
return True
|
||||
group_ids = [x.id for x in user.groups.all()]
|
||||
return self.agenda_set.filter(edit_role_id__in=group_ids).exists()
|
||||
return self.agenda_set.filter(admin_role_id__in=group_ids).exists()
|
||||
|
||||
def get_dependencies(self):
|
||||
return []
|
||||
|
@ -4469,11 +4484,13 @@ class NotificationType:
|
|||
class AgendaNotificationsSettings(WithInspectMixin, models.Model):
|
||||
EMAIL_FIELD = 'use-email-field'
|
||||
VIEW_ROLE = 'view-role'
|
||||
ADMIN_ROLE = 'admin-role'
|
||||
EDIT_ROLE = 'edit-role'
|
||||
|
||||
CHOICES = [
|
||||
(EDIT_ROLE, _('Edit Role')),
|
||||
(ADMIN_ROLE, _('Admin Role')),
|
||||
(VIEW_ROLE, _('View Role')),
|
||||
(EDIT_ROLE, _('Edit Role')),
|
||||
(EMAIL_FIELD, _('Specify email addresses manually')),
|
||||
]
|
||||
|
||||
|
@ -4509,10 +4526,12 @@ class AgendaNotificationsSettings(WithInspectMixin, models.Model):
|
|||
yield notification_type
|
||||
|
||||
def get_role_from_choice(self, choice):
|
||||
if choice == self.EDIT_ROLE:
|
||||
return self.agenda.edit_role
|
||||
if choice == self.ADMIN_ROLE:
|
||||
return self.agenda.admin_role
|
||||
elif choice == self.VIEW_ROLE:
|
||||
return self.agenda.view_role
|
||||
elif choice == self.EDIT_ROLE:
|
||||
return self.agenda.edit_role
|
||||
|
||||
@classmethod
|
||||
def import_json(cls, data):
|
||||
|
|
|
@ -679,6 +679,7 @@ class EventSerializer(serializers.ModelSerializer):
|
|||
|
||||
|
||||
class AgendaSerializer(serializers.ModelSerializer):
|
||||
admin_role = serializers.CharField(required=False, max_length=150)
|
||||
edit_role = serializers.CharField(required=False, max_length=150)
|
||||
view_role = serializers.CharField(required=False, max_length=150)
|
||||
category = serializers.SlugField(required=False, max_length=160)
|
||||
|
@ -696,6 +697,7 @@ class AgendaSerializer(serializers.ModelSerializer):
|
|||
'maximal_booking_delay',
|
||||
'minimal_booking_time',
|
||||
'anonymize_delay',
|
||||
'admin_role',
|
||||
'edit_role',
|
||||
'view_role',
|
||||
'category',
|
||||
|
@ -712,6 +714,9 @@ class AgendaSerializer(serializers.ModelSerializer):
|
|||
except Group.DoesNotExist:
|
||||
raise serializers.ValidationError(_('unknown role: %s' % value))
|
||||
|
||||
def validate_admin_role(self, value):
|
||||
return self.get_role(value)
|
||||
|
||||
def validate_edit_role(self, value):
|
||||
return self.get_role(value)
|
||||
|
||||
|
|
|
@ -79,6 +79,7 @@ def get_agenda_detail(request, agenda, check_events=False):
|
|||
'minimal_booking_delay': agenda.minimal_booking_delay,
|
||||
'maximal_booking_delay': agenda.maximal_booking_delay,
|
||||
'minimal_booking_time': agenda.minimal_booking_time,
|
||||
'admin_role': agenda.admin_role.name if agenda.admin_role else None,
|
||||
'edit_role': agenda.edit_role.name if agenda.edit_role else None,
|
||||
'view_role': agenda.view_role.name if agenda.view_role else None,
|
||||
'category': agenda.category.slug if agenda.category else None,
|
||||
|
@ -550,7 +551,7 @@ class Agendas(APIView):
|
|||
def get(self, request, format=None):
|
||||
agendas_queryset = (
|
||||
Agenda.objects.all()
|
||||
.select_related('category', 'edit_role', 'view_role', 'events_type')
|
||||
.select_related('category', 'admin_role', 'edit_role', 'view_role', 'events_type')
|
||||
.prefetch_related('resources')
|
||||
.order_by('label')
|
||||
)
|
||||
|
|
|
@ -77,6 +77,7 @@ from .widgets import SplitDateTimeField, WeekdaysWidget
|
|||
|
||||
|
||||
class AgendaAddForm(forms.ModelForm):
|
||||
admin_role = forms.ModelChoiceField(label=_('Admin Role'), required=False, queryset=get_role_queryset())
|
||||
edit_role = forms.ModelChoiceField(label=_('Edit Role'), required=False, queryset=get_role_queryset())
|
||||
view_role = forms.ModelChoiceField(label=_('View Role'), required=False, queryset=get_role_queryset())
|
||||
|
||||
|
@ -87,7 +88,7 @@ class AgendaAddForm(forms.ModelForm):
|
|||
|
||||
class Meta:
|
||||
model = Agenda
|
||||
fields = ['label', 'kind', 'category', 'edit_role', 'view_role']
|
||||
fields = ['label', 'kind', 'category', 'admin_role', 'edit_role', 'view_role']
|
||||
|
||||
def clean(self):
|
||||
super().clean()
|
||||
|
@ -164,6 +165,7 @@ class AgendaRolesForm(AgendaAddForm):
|
|||
class Meta:
|
||||
model = Agenda
|
||||
fields = [
|
||||
'admin_role',
|
||||
'edit_role',
|
||||
'view_role',
|
||||
]
|
||||
|
@ -1672,7 +1674,7 @@ class AgendaNotificationsForm(forms.ModelForm):
|
|||
def update_choices(choices, settings):
|
||||
new_choices = []
|
||||
for choice in choices:
|
||||
if choice[0] in (settings.EDIT_ROLE, settings.VIEW_ROLE):
|
||||
if choice[0] in (settings.ADMIN_ROLE, settings.EDIT_ROLE, settings.VIEW_ROLE):
|
||||
role = settings.get_role_from_choice(choice[0]) or _('undefined')
|
||||
choice = (choice[0], '%s (%s)' % (choice[1], role))
|
||||
new_choices.append(choice)
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<span class="actions">
|
||||
<a class="extra-actions-menu-opener"></a>
|
||||
<ul class="extra-actions-menu">
|
||||
{% if user_can_manage %}
|
||||
{% if user_can_edit %}
|
||||
<li><a href="{{ agenda.get_settings_url }}">{% trans 'Settings' %}</a></li>
|
||||
{% endif %}
|
||||
{% block agenda-extra-menu-actions %}{% endblock %}
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div aria-labelledby="tab-settings" hidden id="panel-settings" role="tabpanel" tabindex="0">
|
||||
<div aria-labelledby="tab-settings" id="panel-settings" role="tabpanel" tabindex="0">
|
||||
<div class="section">
|
||||
|
||||
{% if object.kind != 'virtual' %}
|
||||
|
@ -106,7 +106,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div aria-labelledby="tab-permissions" hidden id="panel-permissions" role="tabpanel" tabindex="0">
|
||||
<div aria-labelledby="tab-permissions" id="panel-permissions" role="tabpanel" tabindex="0">
|
||||
<div class="section">
|
||||
<ul>
|
||||
{% for label, value in object.get_permissions_inspect_fields %}
|
||||
|
@ -121,7 +121,7 @@
|
|||
|
||||
{% if object.kind == 'events' %}
|
||||
|
||||
<div aria-labelledby="tab-events" hidden id="panel-events" role="tabpanel" tabindex="0">
|
||||
<div aria-labelledby="tab-events" id="panel-events" role="tabpanel" tabindex="0">
|
||||
<div class="section">
|
||||
{% for event in object.event_set.all %}
|
||||
<h4>{{ event }}</h4>
|
||||
|
@ -150,7 +150,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div aria-labelledby="tab-exceptions" hidden id="panel-exceptions" role="tabpanel" tabindex="0">
|
||||
<div aria-labelledby="tab-exceptions" id="panel-exceptions" role="tabpanel" tabindex="0">
|
||||
<div class="section">
|
||||
{% for desk in object.desk_set.all %}{% if desk.slug == '_exceptions_holder' %}
|
||||
<h4>{% trans "Unavailability calendars" %}</h4>
|
||||
|
@ -193,7 +193,7 @@
|
|||
|
||||
{% elif object.kind == 'meetings' %}
|
||||
|
||||
<div aria-labelledby="tab-meeting-types" hidden id="panel-meeting-types" role="tabpanel" tabindex="0">
|
||||
<div aria-labelledby="tab-meeting-types" id="panel-meeting-types" role="tabpanel" tabindex="0">
|
||||
<div class="section">
|
||||
{% for meeting_type in object.meetingtype_set.all %}
|
||||
<h4>{{ meeting_type }}</h4>
|
||||
|
@ -209,7 +209,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div aria-labelledby="tab-desks" hidden id="panel-desks" role="tabpanel" tabindex="0">
|
||||
<div aria-labelledby="tab-desks" id="panel-desks" role="tabpanel" tabindex="0">
|
||||
<div class="section">
|
||||
{% for desk in object.desk_set.all %}
|
||||
<h4>{{ desk }}</h4>
|
||||
|
@ -274,7 +274,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div aria-labelledby="tab-resources" hidden id="panel-resources" role="tabpanel" tabindex="0">
|
||||
<div aria-labelledby="tab-resources" id="panel-resources" role="tabpanel" tabindex="0">
|
||||
<div class="section">
|
||||
<ul>
|
||||
{% for resource in object.resources.all %}
|
||||
|
@ -288,7 +288,7 @@
|
|||
|
||||
{% elif object.kind == "virtual" %}
|
||||
|
||||
<div aria-labelledby="tab-agendas" hidden id="panel-agendas" role="tabpanel" tabindex="0">
|
||||
<div aria-labelledby="tab-agendas" id="panel-agendas" role="tabpanel" tabindex="0">
|
||||
<div class="section">
|
||||
<ul>
|
||||
{% for agenda in object.real_agendas.all %}
|
||||
|
@ -300,7 +300,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div aria-labelledby="tab-time-periods" hidden id="panel-time-periods" role="tabpanel" tabindex="0">
|
||||
<div aria-labelledby="tab-time-periods" id="panel-time-periods" role="tabpanel" tabindex="0">
|
||||
<div class="section">
|
||||
{% for time_period in object.excluded_timeperiods.all %}
|
||||
<h4>{{ time_period }}</h4>
|
||||
|
|
|
@ -14,19 +14,21 @@
|
|||
<h2>{% trans "Settings" %}
|
||||
<span class="identifier">[{% trans "identifier:" %} {{object.slug}}]</span>
|
||||
</h2>
|
||||
<span class="actions">
|
||||
<a class="extra-actions-menu-opener"></a>
|
||||
<ul class="extra-actions-menu">
|
||||
{% block agenda-extra-menu-actions %}{% endblock %}
|
||||
<li><a download href="{% url 'chrono-manager-agenda-export' pk=object.id %}">{% trans 'Export Configuration (JSON)' %}</a></li>
|
||||
{% if object.kind == 'events' %}
|
||||
<li><a download href="{% url 'chrono-manager-agenda-export-events' pk=object.pk %}">{% trans 'Export Events (CSV)' %}</a></li>
|
||||
{% endif %}
|
||||
{% if user.is_staff %}
|
||||
<li><a rel="popup" href="{% url 'chrono-manager-agenda-delete' pk=object.id %}">{% trans 'Delete' %}</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</span>
|
||||
{% if user_can_manage %}
|
||||
<span class="actions">
|
||||
<a class="extra-actions-menu-opener"></a>
|
||||
<ul class="extra-actions-menu">
|
||||
{% block agenda-extra-menu-actions %}{% endblock %}
|
||||
<li><a download href="{% url 'chrono-manager-agenda-export' pk=object.id %}">{% trans 'Export Configuration (JSON)' %}</a></li>
|
||||
{% if object.kind == 'events' %}
|
||||
<li><a download href="{% url 'chrono-manager-agenda-export-events' pk=object.pk %}">{% trans 'Export Events (CSV)' %}</a></li>
|
||||
{% endif %}
|
||||
{% if user.is_staff %}
|
||||
<li><a rel="popup" href="{% url 'chrono-manager-agenda-delete' pk=object.id %}">{% trans 'Delete' %}</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</span>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
@ -39,14 +41,16 @@
|
|||
<button aria-controls="panel-reminders" aria-selected="false" id="tab-reminders" role="tab" tabindex="-1">{% trans "Booking reminders" %}</button>
|
||||
{% endif %}
|
||||
<button aria-controls="panel-delays" aria-selected="false" id="tab-delays" role="tab" tabindex="-1">{% trans "Booking Delays" %}</button>
|
||||
<button aria-controls="panel-permissions" aria-selected="false" id="tab-permissions" role="tab" tabindex="-1">{% trans "Permissions" %}</button>
|
||||
{% if user_can_manage %}
|
||||
<button aria-controls="panel-permissions" aria-selected="false" id="tab-permissions" role="tab" tabindex="-1">{% trans "Permissions" %}</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="pk-tabs--container">
|
||||
|
||||
{% block agenda-settings-extra-tab-list %}{% endblock %}
|
||||
|
||||
{% if object.kind != 'virtual' and not object.partial_bookings %}
|
||||
<div aria-labelledby="tab-reminders" id="panel-reminders" role="tabpanel" tabindex="0" hidden="">
|
||||
<div aria-labelledby="tab-reminders" id="panel-reminders" role="tabpanel" tabindex="0" "">
|
||||
{% for info in agenda.reminder_settings.display_info %}
|
||||
<p>{{ info }}</p>
|
||||
{% empty %}
|
||||
|
@ -71,7 +75,7 @@
|
|||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div aria-labelledby="tab-delays" hidden="" id="panel-delays" role="tabpanel" tabindex="0">
|
||||
<div aria-labelledby="tab-delays" "" id="panel-delays" role="tabpanel" tabindex="0">
|
||||
<ul>
|
||||
<li>{% trans "Minimal booking delay:" %}
|
||||
{% if agenda.minimal_booking_delay is not None %}
|
||||
|
@ -95,15 +99,18 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div aria-labelledby="tab-permissions" hidden="" id="panel-permissions" role="tabpanel" tabindex="0">
|
||||
<ul>
|
||||
<li>{% trans "Edit Role:" %} {% if agenda.edit_role %}{{ agenda.edit_role }}{% else %}<i>{% trans "undefined" %}</i>{% endif %}</li>
|
||||
<li>{% trans "View Role:" %} {% if agenda.view_role %}{{ agenda.view_role }}{% else %}<i>{% trans "undefined" %}</i>{% endif %}</li>
|
||||
</ul>
|
||||
<div class="panel--buttons">
|
||||
<a rel="popup" class="button" href="{% url 'chrono-manager-agenda-roles' pk=object.id %}">{% trans 'Configure' %}</a>
|
||||
{% if user_can_manage %}
|
||||
<div aria-labelledby="tab-permissions" "" id="panel-permissions" role="tabpanel" tabindex="0">
|
||||
<ul>
|
||||
<li>{% trans "Admin Role:" %} {% if agenda.admin_role %}{{ agenda.admin_role }}{% else %}<i>{% trans "undefined" %}</i>{% endif %}</li>
|
||||
<li>{% trans "Edit Role:" %} {% if agenda.edit_role %}{{ agenda.edit_role }}{% else %}<i>{% trans "undefined" %}</i>{% endif %}</li>
|
||||
<li>{% trans "View Role:" %} {% if agenda.view_role %}{{ agenda.view_role }}{% else %}<i>{% trans "undefined" %}</i>{% endif %}</li>
|
||||
</ul>
|
||||
<div class="panel--buttons">
|
||||
<a rel="popup" class="button" href="{% url 'chrono-manager-agenda-roles' pk=object.id %}">{% trans 'Configure' %}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
@ -112,22 +119,27 @@
|
|||
|
||||
{% block sidebar %}
|
||||
<aside id="sidebar">
|
||||
|
||||
<h3>{% trans "Actions" %}</h3>
|
||||
{% block agenda-extra-management-actions %}{% endblock %}
|
||||
<a class="button button-paragraph" rel="popup" href="{% url 'chrono-manager-agenda-edit' pk=object.id %}">{% trans 'Options' %}</a>
|
||||
{% if user_can_manage %}
|
||||
<a class="button button-paragraph" rel="popup" href="{% url 'chrono-manager-agenda-edit' pk=object.id %}">{% trans 'Options' %}</a>
|
||||
{% endif %}
|
||||
{% if user.is_staff %}
|
||||
<a class="button button-paragraph" rel="popup" class="action-duplicate" href="{% url 'chrono-manager-agenda-duplicate' pk=object.pk %}">{% trans 'Duplicate' %}</a>
|
||||
{% endif %}
|
||||
|
||||
<h3>{% trans "Navigation" %}</h3>
|
||||
{% if show_history %}
|
||||
<a class="button button-paragraph" href="{% url 'chrono-manager-agenda-history' pk=agenda.pk %}">{% trans 'History' %}</a>
|
||||
{% if user_can_manage %}
|
||||
{% if show_history %}
|
||||
<a class="button button-paragraph" href="{% url 'chrono-manager-agenda-history' pk=agenda.pk %}">{% trans 'History' %}</a>
|
||||
{% endif %}
|
||||
<a class="button button-paragraph" href="{% url 'chrono-manager-agenda-inspect' pk=agenda.pk %}">{% trans 'Inspect' %}</a>
|
||||
{% endif %}
|
||||
<a class="button button-paragraph" href="{% url 'chrono-manager-agenda-inspect' pk=agenda.pk %}">{% trans 'Inspect' %}</a>
|
||||
{% block agenda-extra-navigation-actions %}{% endblock %}
|
||||
|
||||
{% url 'chrono-manager-homepage' as object_list_url %}
|
||||
{% include 'chrono/includes/application_detail_fragment.html' %}
|
||||
{% if user_can_manage %}
|
||||
{% url 'chrono-manager-homepage' as object_list_url %}
|
||||
{% include 'chrono/includes/application_detail_fragment.html' %}
|
||||
{% endif %}
|
||||
</aside>
|
||||
{% endblock %}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<h2>{{ object.label }}</h2>
|
||||
<span class="actions">
|
||||
{% block actions %}
|
||||
{% if user_can_manage %}
|
||||
{% if user_can_edit %}
|
||||
<a href="{{ object.get_settings_url }}">{% trans 'Settings' %}</a>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
|
|
@ -2,14 +2,18 @@
|
|||
{% load i18n %}
|
||||
|
||||
{% block agenda-extra-management-actions %}
|
||||
<a class="button button-paragraph" rel="popup" href="{% url 'chrono-manager-agenda-import-events' pk=object.id %}">{% trans 'Import Events' %}</a>
|
||||
{% if user_can_manage %}
|
||||
<a class="button button-paragraph" rel="popup" href="{% url 'chrono-manager-agenda-import-events' pk=object.id %}">{% trans 'Import Events' %}</a>
|
||||
{% endif %}
|
||||
<a class="button button-paragraph" rel="popup" href="{% url 'chrono-manager-agenda-add-event' pk=object.id %}">{% trans 'New Event' %}</a>
|
||||
{% endblock %}
|
||||
|
||||
{% block agenda-extra-navigation-actions %}
|
||||
{% with lingo_url=object.get_lingo_url %}{% if lingo_url %}
|
||||
<a class="button button-paragraph" href="{{ lingo_url }}">{% trans 'Pricing' context 'pricing' %}</a>
|
||||
{% endif %}{% endwith %}
|
||||
{% if user_can_manage %}
|
||||
{% with lingo_url=object.get_lingo_url %}{% if lingo_url %}
|
||||
<a class="button button-paragraph" href="{{ lingo_url }}">{% trans 'Pricing' context 'pricing' %}</a>
|
||||
{% endif %}{% endwith %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block agenda-settings-extra-tab-buttons %}
|
||||
|
@ -17,9 +21,11 @@
|
|||
{% if has_recurring_events %}
|
||||
<button aria-controls="panel-time-periods" aria-selected="false" id="tab-time-periods" role="tab" tabindex="-1">{% trans "Recurrence exceptions" %}</button>
|
||||
{% endif %}
|
||||
<button aria-controls="panel-display-options" aria-selected="false" id="tab-display-options" role="tab" tabindex="-1">{% trans "Display options" %}</button>
|
||||
<button aria-controls="panel-booking-check-options" aria-selected="false" id="tab-booking-check-options" role="tab" tabindex="-1">{% trans "Booking check options" %}</button>
|
||||
{% if agenda.partial_bookings %}
|
||||
{% if user_can_manage %}
|
||||
<button aria-controls="panel-display-options" aria-selected="false" id="tab-display-options" role="tab" tabindex="-1">{% trans "Display options" %}</button>
|
||||
<button aria-controls="panel-booking-check-options" aria-selected="false" id="tab-booking-check-options" role="tab" tabindex="-1">{% trans "Booking check options" %}</button>
|
||||
{% endif %}
|
||||
{% if agenda.partial_bookings and user_can_manage %}
|
||||
<button aria-controls="panel-invoicing-options" aria-selected="false" id="tab-invoicing-options" role="tab" tabindex="-1">{% trans "Invoicing options" %}</button>
|
||||
{% else %}
|
||||
<button aria-controls="panel-notifications" aria-selected="false" id="tab-notifications" role="tab" tabindex="-1">{% trans "Management notifications" %}</button>
|
||||
|
@ -48,7 +54,7 @@
|
|||
</div>
|
||||
|
||||
{% if has_recurring_events %}
|
||||
<div aria-labelledby="tab-time-periods" hidden="" id="panel-time-periods" role="tabpanel" tabindex="0">
|
||||
<div aria-labelledby="tab-time-periods" "" id="panel-time-periods" role="tabpanel" tabindex="0">
|
||||
{% if object.recurrence_exceptions_report.events.exists %}
|
||||
<div class="warningnotice">
|
||||
<p>{% trans "The following events exist despite exceptions because they have active bookings:" %}</p>
|
||||
|
@ -80,60 +86,62 @@
|
|||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div aria-labelledby="tab-display-options" hidden="" id="panel-display-options" role="tabpanel" tabindex="0">
|
||||
<ul>
|
||||
<li>
|
||||
{% if agenda.event_display_template %}
|
||||
{% trans "Event display template:" %}
|
||||
{% if user_can_manage %}
|
||||
<div aria-labelledby="tab-display-options" "" id="panel-display-options" role="tabpanel" tabindex="0">
|
||||
<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>
|
||||
{% if not agenda.partial_bookings %}
|
||||
<li>
|
||||
{% trans "Booking display template:" %}
|
||||
{% else %}
|
||||
{% trans "No event display template configured for this agenda." %}
|
||||
{% endif %}
|
||||
</li>
|
||||
{% if not agenda.partial_bookings %}
|
||||
<li>
|
||||
{% trans "Booking display template:" %}
|
||||
<pre>{{ agenda.get_booking_user_block_template }}</pre>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
<div class="panel--buttons">
|
||||
<a rel="popup" class="button" href="{% url 'chrono-manager-agenda-display-settings' pk=object.pk %}">{% trans 'Configure' %}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div aria-labelledby="tab-booking-check-options" hidden="" id="panel-booking-check-options" role="tabpanel" tabindex="0">
|
||||
<ul>
|
||||
{% with agenda.get_booking_check_filters as check_filters %}
|
||||
{% if check_filters %}
|
||||
<li>{% trans "Filters:" %}
|
||||
<ul>
|
||||
{% for key in check_filters %}
|
||||
<li>{{ key }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</li>
|
||||
{% else %}
|
||||
<li>{% trans "No filters configured for this agenda." %}</li>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
<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>
|
||||
{% if not agenda.partial_bookings %}
|
||||
<li>{% trans "Enable the check of bookings when event has not passed:" %} {{ agenda.enable_check_for_future_events|yesno }}</li>
|
||||
<li>
|
||||
{% trans "Extra user block template:" %}
|
||||
<pre>{{ agenda.booking_extra_user_block_template }}</pre>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
<div class="panel--buttons">
|
||||
<a rel="popup" class="button" href="{% url 'chrono-manager-agenda-booking-check-settings' pk=object.pk %}">{% trans 'Configure' %}</a>
|
||||
</ul>
|
||||
<div class="panel--buttons">
|
||||
<a rel="popup" class="button" href="{% url 'chrono-manager-agenda-display-settings' pk=object.pk %}">{% trans 'Configure' %}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if agenda.partial_bookings %}
|
||||
<div aria-labelledby="tab-invoicing-options" hidden="" id="panel-invoicing-options" role="tabpanel" tabindex="0">
|
||||
<div aria-labelledby="tab-booking-check-options" "" id="panel-booking-check-options" role="tabpanel" tabindex="0">
|
||||
<ul>
|
||||
{% with agenda.get_booking_check_filters as check_filters %}
|
||||
{% if check_filters %}
|
||||
<li>{% trans "Filters:" %}
|
||||
<ul>
|
||||
{% for key in check_filters %}
|
||||
<li>{{ key }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</li>
|
||||
{% else %}
|
||||
<li>{% trans "No filters configured for this agenda." %}</li>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
<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>
|
||||
{% if not agenda.partial_bookings %}
|
||||
<li>{% trans "Enable the check of bookings when event has not passed:" %} {{ agenda.enable_check_for_future_events|yesno }}</li>
|
||||
<li>
|
||||
{% trans "Extra user block template:" %}
|
||||
<pre>{{ agenda.booking_extra_user_block_template }}</pre>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
<div class="panel--buttons">
|
||||
<a rel="popup" class="button" href="{% url 'chrono-manager-agenda-booking-check-settings' pk=object.pk %}">{% trans 'Configure' %}</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if agenda.partial_bookings and user_can_manage %}
|
||||
<div aria-labelledby="tab-invoicing-options" "" id="panel-invoicing-options" role="tabpanel" tabindex="0">
|
||||
<ul>
|
||||
<li>{% trans "Invoicing:" %} {{ agenda.get_invoicing_unit_display }}</li>
|
||||
<li>{% trans "Tolerance:" %} {% blocktrans count num=agenda.invoicing_tolerance %}{{ num }} minute{% plural %}{{ num }} minutes{% endblocktrans %}</li>
|
||||
|
@ -145,7 +153,7 @@
|
|||
{% endif %}
|
||||
|
||||
{% if not agenda.partial_bookings %}
|
||||
<div aria-labelledby="tab-notifications" hidden="" id="panel-notifications" role="tabpanel" tabindex="0">
|
||||
<div aria-labelledby="tab-notifications" "" id="panel-notifications" role="tabpanel" tabindex="0">
|
||||
{% for notification_type in object.notifications_settings.get_notification_types %}
|
||||
{% if forloop.first %}<ul>{% endif %}
|
||||
<li>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div aria-labelledby="tab-custom-fields" hidden id="panel-custom-fields" role="tabpanel" tabindex="0">
|
||||
<div aria-labelledby="tab-custom-fields" id="panel-custom-fields" role="tabpanel" tabindex="0">
|
||||
<div class="section">
|
||||
{% for value in object.get_custom_fields %}
|
||||
<h4>{{ value.label }}</h4>
|
||||
|
|
|
@ -12,20 +12,31 @@
|
|||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block sidebar %}
|
||||
{% if user_can_manage %}
|
||||
{# show sidebar only if admin user #}
|
||||
{{ block.super }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block agenda-extra-menu-actions %}
|
||||
{% if object.desk_simple_management %}
|
||||
<li><a href="{% url 'chrono-manager-agenda-desk-management-toggle-view' pk=object.pk %}">{% trans 'Switch to invididual desk management' %}</a></li>
|
||||
{% elif agenda_is_available_for_simple_management %}
|
||||
<li><a href="{% url 'chrono-manager-agenda-desk-management-toggle-view' pk=object.pk %}">{% trans 'Switch to global desk management' %}</a></li>
|
||||
{% if user_can_manage %}
|
||||
{% if object.desk_simple_management %}
|
||||
<li><a href="{% url 'chrono-manager-agenda-desk-management-toggle-view' pk=object.pk %}">{% trans 'Switch to invididual desk management' %}</a></li>
|
||||
{% elif agenda_is_available_for_simple_management %}
|
||||
<li><a href="{% url 'chrono-manager-agenda-desk-management-toggle-view' pk=object.pk %}">{% trans 'Switch to global desk management' %}</a></li>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block agenda-settings-extra-tab-buttons %}
|
||||
<button aria-controls="panel-meeting-types"
|
||||
aria-selected="{{meeting_types|yesno:"false,true"}}"
|
||||
id="tab-meeting-types" role="tab"
|
||||
tabindex="{{meeting_types|yesno:"-1,0"}}"
|
||||
>{% trans "Meeting Types" %}</button>
|
||||
{% if user_can_manage %}
|
||||
<button aria-controls="panel-meeting-types"
|
||||
aria-selected="{{meeting_types|yesno:"false,true"}}"
|
||||
id="tab-meeting-types" role="tab"
|
||||
tabindex="{{meeting_types|yesno:"-1,0"}}"
|
||||
>{% trans "Meeting Types" %}</button>
|
||||
{% endif %}
|
||||
{% if object.desk_simple_management %}
|
||||
<button aria-controls="panel-desks" aria-selected="false" id="tab-desks" role="tab" tabindex="-1">{% trans "Desks" %}</button>
|
||||
{% endif %}
|
||||
|
@ -34,44 +45,48 @@
|
|||
id="tab-time-periods" role="tab"
|
||||
tabindex="{{meeting_types|yesno:"0"}}"
|
||||
>{% trans "Opening hours" %}</button>
|
||||
{% if has_resources %}
|
||||
{% if has_resources and user_can_manage %}
|
||||
<button aria-controls="panel-resources" aria-selected="false" id="tab-resources" role="tab" tabindex="-1">{% trans "Resources" %}</button>
|
||||
{% endif %}
|
||||
<button aria-controls="panel-display-options" aria-selected="false" id="tab-display-options" role="tab" tabindex="-1">{% trans "Display options" %}</button>
|
||||
{% if user_can_manage %}
|
||||
<button aria-controls="panel-display-options" aria-selected="false" id="tab-display-options" role="tab" tabindex="-1">{% trans "Display options" %}</button>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block agenda-settings-extra-tab-list %}
|
||||
|
||||
<div aria-labelledby="tab-meeting-types" id="panel-meeting-types" role="tabpanel" tabindex="0"
|
||||
{% if meeting_types %}hidden{% endif %}>
|
||||
{% if meeting_types %}
|
||||
<ul class="objects-list single-links">
|
||||
{% for meeting_type in meeting_types %}
|
||||
<li>
|
||||
<a rel="popup" href="{% url 'chrono-manager-meeting-type-edit' pk=meeting_type.id %}">
|
||||
{{meeting_type.label}}
|
||||
<span class="duration">({{meeting_type.duration}} {% trans "minutes" %})</span>
|
||||
<span class="identifier">[{% trans "identifier:" %} {{meeting_type.slug}}]</span>
|
||||
</a>
|
||||
<a rel="popup" class="delete" href="{% url 'chrono-manager-meeting-type-delete' pk=meeting_type.id %}">{% trans "remove" %}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% else %}
|
||||
<div class="big-msg-info">
|
||||
{% blocktrans trimmed %}
|
||||
This agenda doesn't have any meeting type yet. Click on the "New Meeting Type" button to add a first one.
|
||||
{% endblocktrans %}
|
||||
{% if user_can_manage %}
|
||||
<div aria-labelledby="tab-meeting-types" id="panel-meeting-types" role="tabpanel" tabindex="0"
|
||||
{% if meeting_types %}hidden{% endif %}>
|
||||
{% if meeting_types %}
|
||||
<ul class="objects-list single-links">
|
||||
{% for meeting_type in meeting_types %}
|
||||
<li>
|
||||
<a rel="popup" href="{% url 'chrono-manager-meeting-type-edit' pk=meeting_type.id %}">
|
||||
{{meeting_type.label}}
|
||||
<span class="duration">({{meeting_type.duration}} {% trans "minutes" %})</span>
|
||||
<span class="identifier">[{% trans "identifier:" %} {{meeting_type.slug}}]</span>
|
||||
</a>
|
||||
<a rel="popup" class="delete" href="{% url 'chrono-manager-meeting-type-delete' pk=meeting_type.id %}">{% trans "remove" %}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% else %}
|
||||
<div class="big-msg-info">
|
||||
{% blocktrans trimmed %}
|
||||
This agenda doesn't have any meeting type yet. Click on the "New Meeting Type" button to add a first one.
|
||||
{% endblocktrans %}
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="panel--buttons">
|
||||
<a rel="popup" class="button" href="{% url 'chrono-manager-agenda-add-meeting-type' pk=object.id %}">{% trans 'New Meeting Type' %}</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="panel--buttons">
|
||||
<a rel="popup" class="button" href="{% url 'chrono-manager-agenda-add-meeting-type' pk=object.id %}">{% trans 'New Meeting Type' %}</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if object.desk_simple_management %}
|
||||
<div aria-labelledby="tab-desks" hidden="" id="panel-desks" role="tabpanel" tabindex="0">
|
||||
<div aria-labelledby="tab-desks" "" id="panel-desks" role="tabpanel" tabindex="0">
|
||||
<ul class="objects-list single-links">
|
||||
{% for desk in object.prefetched_desks %}
|
||||
<li>
|
||||
|
@ -150,8 +165,8 @@
|
|||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% if has_resources %}
|
||||
<div aria-labelledby="tab-resources" hidden="" id="panel-resources" role="tabpanel" tabindex="0">
|
||||
{% if has_resources and user_can_manage %}
|
||||
<div aria-labelledby="tab-resources" "" id="panel-resources" role="tabpanel" tabindex="0">
|
||||
{% with object.resources.all as agenda_resources %}
|
||||
{% if agenda_resources %}
|
||||
<ul class="objects-list single-links">
|
||||
|
@ -179,16 +194,18 @@
|
|||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div aria-labelledby="tab-display-options" hidden="" id="panel-display-options" role="tabpanel" tabindex="0">
|
||||
<ul>
|
||||
<li>
|
||||
{% trans "Booking display template:" %}
|
||||
{% if user_can_manage %}
|
||||
<div aria-labelledby="tab-display-options" "" id="panel-display-options" role="tabpanel" tabindex="0">
|
||||
<ul>
|
||||
<li>
|
||||
{% trans "Booking display template:" %}
|
||||
<pre>{{ agenda.get_booking_user_block_template }}</pre>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="panel--buttons">
|
||||
<a rel="popup" class="button" href="{% url 'chrono-manager-agenda-display-settings' pk=object.pk %}">{% trans 'Configure' %}</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="panel--buttons">
|
||||
<a rel="popup" class="button" href="{% url 'chrono-manager-agenda-display-settings' pk=object.pk %}">{% trans 'Configure' %}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
data-end-datetime="{{ end_datetime.isoformat }}"
|
||||
>
|
||||
{% if view.date.date == today %}
|
||||
<div class="partial-booking--hour-indicator-wrapper" aria-hidden="true">
|
||||
<div class="partial-booking--hour-indicator-wrapper" aria-"true">
|
||||
<div class="partial-booking--hour-indicator" hidden></div>
|
||||
<script>
|
||||
const hour_indicator = (function() {
|
||||
|
|
|
@ -76,7 +76,7 @@
|
|||
</div>
|
||||
|
||||
{% if has_holidays %}
|
||||
<div aria-labelledby="tab-holidays" hidden="" id="panel-holidays" role="tabpanel" tabindex="0">
|
||||
<div aria-labelledby="tab-holidays" "" id="panel-holidays" role="tabpanel" tabindex="0">
|
||||
{% if agenda.holiday_rules.all %}
|
||||
<ul class="objects-list single-links">
|
||||
{% for rule in agenda.holiday_rules.all %}
|
||||
|
@ -99,7 +99,7 @@
|
|||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div aria-labelledby="tab-time-periods" hidden="" id="panel-time-periods" role="tabpanel" tabindex="0">
|
||||
<div aria-labelledby="tab-time-periods" "" id="panel-time-periods" role="tabpanel" tabindex="0">
|
||||
{% if exceptional_periods %}
|
||||
<ul class="objects-list single-links">
|
||||
{% for period in exceptional_periods %}
|
||||
|
|
|
@ -35,8 +35,8 @@
|
|||
{{ field.errors }}
|
||||
<p>{{ field.label_tag }} {{ field }}{% if field.name == 'start_datetime' %} <button type="button" id="allday">{% trans "All day" %}</button>{% endif%}</p>
|
||||
{% endfor %}
|
||||
{% for hidden in form.hidden_fields %}
|
||||
{{ hidden }}
|
||||
{% for in form.hidden_fields %}
|
||||
{{ hop }}
|
||||
{% endfor %}
|
||||
<div class="buttons">
|
||||
<button class="submit-button">{% trans "Save" %}</button>
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div aria-labelledby="tab-permissions" hidden id="panel-permissions" role="tabpanel" tabindex="0">
|
||||
<div aria-labelledby="tab-permissions" id="panel-permissions" role="tabpanel" tabindex="0">
|
||||
<div class="section">
|
||||
<ul>
|
||||
{% for label, value in object.get_permissions_inspect_fields %}
|
||||
|
@ -33,7 +33,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div aria-labelledby="tab-exceptions" hidden id="panel-exceptions" role="tabpanel" tabindex="0">
|
||||
<div aria-labelledby="tab-exceptions" id="panel-exceptions" role="tabpanel" tabindex="0">
|
||||
<div class="section">
|
||||
{% for exception in object.timeperiodexception_set.all %}
|
||||
<h4>{{ exception }}</h4>
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
</div>
|
||||
|
||||
{% if virtual_members %}
|
||||
<div aria-labelledby="tab-meeting-types" hidden="" id="panel-meeting-types" role="tabpanel" tabindex="0">
|
||||
<div aria-labelledby="tab-meeting-types" "" id="panel-meeting-types" role="tabpanel" tabindex="0">
|
||||
{% if meeting_types %}
|
||||
<ul class="objects-list single-links">
|
||||
{% for meeting_type in meeting_types %}
|
||||
|
@ -64,7 +64,7 @@
|
|||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div aria-labelledby="tab-time-periods" hidden="" id="panel-time-periods" role="tabpanel" tabindex="0">
|
||||
<div aria-labelledby="tab-time-periods" "" id="panel-time-periods" role="tabpanel" tabindex="0">
|
||||
{% if agenda.excluded_timeperiods.count %}
|
||||
<ul class="objects-list single-links">
|
||||
{% for time_period in agenda.excluded_timeperiods.all %}
|
||||
|
|
|
@ -202,7 +202,9 @@ class HomepageView(WithApplicationsMixin, ListView):
|
|||
queryset = self.with_applications_queryset()
|
||||
if not self.request.user.is_staff:
|
||||
group_ids = [x.id for x in self.request.user.groups.all()]
|
||||
queryset = queryset.filter(Q(view_role_id__in=group_ids) | Q(edit_role_id__in=group_ids))
|
||||
queryset = queryset.filter(
|
||||
Q(view_role_id__in=group_ids) | Q(admin_role_id__in=group_ids) | Q(edit_role_id__in=group_ids)
|
||||
)
|
||||
return queryset.select_related('category').order_by('category__label', 'label')
|
||||
|
||||
def has_access_to_unavailability_calendars(self):
|
||||
|
@ -1364,11 +1366,11 @@ class ViewableAgendaMixin:
|
|||
return context
|
||||
|
||||
|
||||
class ManagedAgendaMixin(ViewableAgendaMixin):
|
||||
class EditableAgendaMixin(ViewableAgendaMixin):
|
||||
tab_anchor = None
|
||||
|
||||
def check_permissions(self, user):
|
||||
return self.agenda.can_be_managed(user)
|
||||
return self.agenda.can_be_edited(user)
|
||||
|
||||
def get_form_kwargs(self):
|
||||
kwargs = super().get_form_kwargs()
|
||||
|
@ -1384,6 +1386,11 @@ class ManagedAgendaMixin(ViewableAgendaMixin):
|
|||
return url
|
||||
|
||||
|
||||
class ManagedAgendaMixin(EditableAgendaMixin):
|
||||
def check_permissions(self, user):
|
||||
return self.agenda.can_be_managed(user)
|
||||
|
||||
|
||||
class AgendaEditView(ManagedAgendaMixin, UpdateView):
|
||||
template_name = 'chrono/manager_agenda_form.html'
|
||||
title = _('Edit Agenda')
|
||||
|
@ -1412,6 +1419,9 @@ class AgendaBookingDelaysView(AgendaEditView):
|
|||
tab_anchor = 'delays'
|
||||
comment = _('changed booking delays')
|
||||
|
||||
def check_permissions(self, user):
|
||||
return self.agenda.can_be_edited(user)
|
||||
|
||||
|
||||
agenda_booking_delays = AgendaBookingDelaysView.as_view()
|
||||
|
||||
|
@ -1632,7 +1642,7 @@ class AgendaDateView(DateMixin, ViewableAgendaMixin):
|
|||
context['booking_colors'] = BookingColor.objects.filter(
|
||||
bookings__event__in=self.object_list, bookings__cancellation_datetime__isnull=True
|
||||
).distinct()
|
||||
context['user_can_manage'] = self.agenda.can_be_managed(self.request.user)
|
||||
context['user_can_edit'] = self.agenda.can_be_edited(self.request.user)
|
||||
return context
|
||||
|
||||
def get_queryset(self):
|
||||
|
@ -2432,13 +2442,16 @@ class AgendaOpenEventsView(ViewableAgendaMixin, DetailView):
|
|||
agenda_open_events_view = AgendaOpenEventsView.as_view()
|
||||
|
||||
|
||||
class ManagedAgendaSubobjectMixin:
|
||||
class EditableAgendaSubobjectMixin:
|
||||
agenda = None
|
||||
tab_anchor = None
|
||||
|
||||
def check_permissions(self, user):
|
||||
return self.agenda.can_be_edited(user)
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
self.agenda = self.get_object().agenda
|
||||
if not self.agenda.can_be_managed(request.user):
|
||||
if not self.check_permissions(request.user):
|
||||
raise PermissionDenied()
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
|
@ -2454,6 +2467,11 @@ class ManagedAgendaSubobjectMixin:
|
|||
return url
|
||||
|
||||
|
||||
class ManagedAgendaSubobjectMixin(EditableAgendaSubobjectMixin):
|
||||
def check_permissions(self, user):
|
||||
return self.agenda.can_be_managed(user)
|
||||
|
||||
|
||||
class ManagedDeskMixin:
|
||||
desk = None
|
||||
tab_anchor = None
|
||||
|
@ -2463,7 +2481,7 @@ class ManagedDeskMixin:
|
|||
self.desk = Desk.objects.get(id=kwargs.get('pk'))
|
||||
except Desk.DoesNotExist:
|
||||
raise Http404()
|
||||
if not self.desk.agenda.can_be_managed(request.user):
|
||||
if not self.desk.agenda.can_be_edited(request.user):
|
||||
raise PermissionDenied()
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
|
@ -2497,7 +2515,7 @@ class ManagedTimePeriodMixin:
|
|||
if self.time_period.desk:
|
||||
self.agenda = self.time_period.desk.agenda
|
||||
|
||||
if not self.agenda.can_be_managed(request.user):
|
||||
if not self.agenda.can_be_edited(request.user):
|
||||
raise PermissionDenied()
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
|
@ -2522,7 +2540,7 @@ class ManagedTimePeriodExceptionMixin:
|
|||
object_ = self.get_object()
|
||||
if object_.desk:
|
||||
self.desk = self.get_object().desk
|
||||
if not self.desk.agenda.can_be_managed(request.user):
|
||||
if not self.desk.agenda.can_be_edited(request.user):
|
||||
raise PermissionDenied()
|
||||
elif object_.unavailability_calendar:
|
||||
self.unavailability_calendar = object_.unavailability_calendar
|
||||
|
@ -2563,12 +2581,12 @@ class AgendaSettingsRedirectView(RedirectView):
|
|||
agenda_settings_redirect_view = AgendaSettingsRedirectView.as_view()
|
||||
|
||||
|
||||
class AgendaSettings(ManagedAgendaMixin, DetailView):
|
||||
class AgendaSettings(EditableAgendaMixin, DetailView):
|
||||
model = Agenda
|
||||
|
||||
def set_agenda(self, **kwargs):
|
||||
self.agenda = get_object_or_404(
|
||||
Agenda.objects.select_related('edit_role', 'view_role'),
|
||||
Agenda.objects.select_related('admin_role', 'edit_role', 'view_role'),
|
||||
pk=kwargs.get('pk'),
|
||||
)
|
||||
|
||||
|
@ -2580,6 +2598,7 @@ class AgendaSettings(ManagedAgendaMixin, DetailView):
|
|||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context['show_history'] = settings.SNAPSHOTS_ENABLED
|
||||
context['user_can_manage'] = self.object.can_be_managed(self.request.user)
|
||||
if self.agenda.accept_meetings():
|
||||
context['meeting_types'] = self.object.iter_meetingtypes()
|
||||
if self.agenda.kind == 'virtual':
|
||||
|
@ -2665,7 +2684,7 @@ class AgendaDuplicate(FormView):
|
|||
agenda_duplicate = AgendaDuplicate.as_view()
|
||||
|
||||
|
||||
class AgendaAddEventView(ManagedAgendaMixin, CreateView):
|
||||
class AgendaAddEventView(EditableAgendaMixin, CreateView):
|
||||
template_name = 'chrono/manager_event_form.html'
|
||||
model = Event
|
||||
form_class = NewEventForm
|
||||
|
@ -2679,7 +2698,7 @@ class AgendaAddEventView(ManagedAgendaMixin, CreateView):
|
|||
agenda_add_event = AgendaAddEventView.as_view()
|
||||
|
||||
|
||||
class AgendaEventDuplicateView(ManagedAgendaMixin, UpdateView):
|
||||
class AgendaEventDuplicateView(EditableAgendaMixin, UpdateView):
|
||||
model = Event
|
||||
queryset = Event.objects.filter(primary_event__isnull=True)
|
||||
pk_url_kwarg = 'event_pk'
|
||||
|
@ -2834,7 +2853,7 @@ class AgendaDeskManagementToggleView(ManagedAgendaMixin, View):
|
|||
agenda_desk_management_toggle_view = AgendaDeskManagementToggleView.as_view()
|
||||
|
||||
|
||||
class AgendaNotificationsSettingsView(ManagedAgendaMixin, UpdateView):
|
||||
class AgendaNotificationsSettingsView(EditableAgendaMixin, UpdateView):
|
||||
template_name = 'chrono/manager_agenda_notifications_form.html'
|
||||
model = AgendaNotificationsSettings
|
||||
form_class = AgendaNotificationsForm
|
||||
|
@ -2875,11 +2894,14 @@ class AgendaReminderSettingsView(AgendaEditView):
|
|||
except AgendaReminderSettings.DoesNotExist:
|
||||
return AgendaReminderSettings.objects.create(agenda=self.agenda)
|
||||
|
||||
def check_permissions(self, user):
|
||||
return self.agenda.can_be_edited(user)
|
||||
|
||||
|
||||
agenda_reminder_settings = AgendaReminderSettingsView.as_view()
|
||||
|
||||
|
||||
class AgendaReminderTestView(ManagedAgendaMixin, FormView):
|
||||
class AgendaReminderTestView(EditableAgendaMixin, FormView):
|
||||
template_name = 'chrono/manager_send_reminder_form.html'
|
||||
form_class = AgendaReminderTestForm
|
||||
|
||||
|
@ -2907,7 +2929,7 @@ class AgendaReminderTestView(ManagedAgendaMixin, FormView):
|
|||
agenda_reminder_test = AgendaReminderTestView.as_view()
|
||||
|
||||
|
||||
class AgendaReminderPreviewView(ManagedAgendaMixin, TemplateView):
|
||||
class AgendaReminderPreviewView(EditableAgendaMixin, TemplateView):
|
||||
template_name = 'chrono/manager_agenda_reminder_preview.html'
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
|
@ -3163,7 +3185,7 @@ class EventDetailRedirectView(RedirectView):
|
|||
event_redirect_view = EventDetailRedirectView.as_view()
|
||||
|
||||
|
||||
class EventEditView(ManagedAgendaMixin, UpdateView):
|
||||
class EventEditView(EditableAgendaMixin, UpdateView):
|
||||
template_name = 'chrono/manager_event_form.html'
|
||||
model = Event
|
||||
form_class = EventForm
|
||||
|
@ -3188,7 +3210,7 @@ class EventEditView(ManagedAgendaMixin, UpdateView):
|
|||
event_edit = EventEditView.as_view()
|
||||
|
||||
|
||||
class EventDeleteView(ManagedAgendaMixin, DeleteView):
|
||||
class EventDeleteView(EditableAgendaMixin, DeleteView):
|
||||
template_name = 'chrono/manager_confirm_event_delete.html'
|
||||
model = Event
|
||||
pk_url_kwarg = 'event_pk'
|
||||
|
@ -3805,7 +3827,7 @@ class AgendaDeskMixin:
|
|||
return super().get_success_url()
|
||||
|
||||
|
||||
class AgendaAddDesk(AgendaDeskMixin, ManagedAgendaMixin, CreateView):
|
||||
class AgendaAddDesk(AgendaDeskMixin, EditableAgendaMixin, CreateView):
|
||||
template_name = 'chrono/manager_desk_form.html'
|
||||
model = Desk
|
||||
form_class = NewDeskForm
|
||||
|
@ -3824,7 +3846,7 @@ class AgendaAddDesk(AgendaDeskMixin, ManagedAgendaMixin, CreateView):
|
|||
agenda_add_desk = AgendaAddDesk.as_view()
|
||||
|
||||
|
||||
class DeskEditView(AgendaDeskMixin, ManagedAgendaSubobjectMixin, UpdateView):
|
||||
class DeskEditView(AgendaDeskMixin, EditableAgendaSubobjectMixin, UpdateView):
|
||||
template_name = 'chrono/manager_desk_form.html'
|
||||
model = Desk
|
||||
form_class = DeskForm
|
||||
|
@ -3842,7 +3864,7 @@ class DeskEditView(AgendaDeskMixin, ManagedAgendaSubobjectMixin, UpdateView):
|
|||
desk_edit = DeskEditView.as_view()
|
||||
|
||||
|
||||
class DeskDeleteView(AgendaDeskMixin, ManagedAgendaSubobjectMixin, DeleteView):
|
||||
class DeskDeleteView(AgendaDeskMixin, EditableAgendaSubobjectMixin, DeleteView):
|
||||
template_name = 'chrono/manager_confirm_delete.html'
|
||||
model = Desk
|
||||
tab_anchor = 'desks'
|
||||
|
@ -4058,7 +4080,7 @@ class TimePeriodExceptionDeleteView(ManagedTimePeriodExceptionMixin, DeleteView)
|
|||
time_period_exception_delete = TimePeriodExceptionDeleteView.as_view()
|
||||
|
||||
|
||||
class DeskImportTimePeriodExceptionsView(ManagedAgendaSubobjectMixin, UpdateView):
|
||||
class DeskImportTimePeriodExceptionsView(EditableAgendaSubobjectMixin, UpdateView):
|
||||
model = Desk
|
||||
form_class = DeskExceptionsImportForm
|
||||
template_name = 'chrono/manager_import_exceptions.html'
|
||||
|
@ -4238,7 +4260,7 @@ class AgendaInspectView(ManagedAgendaMixin, DetailView):
|
|||
def set_agenda(self, **kwargs):
|
||||
self.agenda = get_object_or_404(
|
||||
Agenda.objects.select_related(
|
||||
'category', 'events_type', 'edit_role', 'view_role'
|
||||
'category', 'events_type', 'admin_role', 'edit_role', 'view_role'
|
||||
).prefetch_related(
|
||||
'resources',
|
||||
Prefetch(
|
||||
|
|
|
@ -22,6 +22,7 @@ pytestmark = pytest.mark.django_db
|
|||
|
||||
|
||||
def test_agendas_api(settings, app):
|
||||
admin_group = Group.objects.create(name='Admin')
|
||||
edit_group = Group.objects.create(name='Edit')
|
||||
view_group = Group.objects.create(name='View')
|
||||
category_a = Category.objects.create(label='Category A')
|
||||
|
@ -32,7 +33,7 @@ def test_agendas_api(settings, app):
|
|||
label='Foo bar',
|
||||
category=category_a,
|
||||
events_type=events_type,
|
||||
edit_role=edit_group,
|
||||
admin_role=admin_group,
|
||||
)
|
||||
Desk.objects.create(agenda=event_agenda, slug='_exceptions_holder')
|
||||
event_agenda2 = Agenda.objects.create(label='Foo bar 2', category=category_a, events_type=events_type2)
|
||||
|
@ -52,6 +53,7 @@ def test_agendas_api(settings, app):
|
|||
kind='virtual',
|
||||
minimal_booking_delay=1,
|
||||
maximal_booking_delay=56,
|
||||
admin_role=admin_group,
|
||||
edit_role=edit_group,
|
||||
view_role=view_group,
|
||||
)
|
||||
|
@ -68,7 +70,8 @@ def test_agendas_api(settings, app):
|
|||
'minimal_booking_delay_in_working_days': False,
|
||||
'maximal_booking_delay': 56,
|
||||
'minimal_booking_time': '00:00:00',
|
||||
'edit_role': 'Edit',
|
||||
'admin_role': 'Admin',
|
||||
'edit_role': None,
|
||||
'view_role': None,
|
||||
'category': 'category-a',
|
||||
'category_label': 'Category A',
|
||||
|
@ -88,6 +91,7 @@ def test_agendas_api(settings, app):
|
|||
'minimal_booking_delay_in_working_days': False,
|
||||
'maximal_booking_delay': 56,
|
||||
'minimal_booking_time': '00:00:00',
|
||||
'admin_role': None,
|
||||
'edit_role': None,
|
||||
'view_role': None,
|
||||
'category': 'category-a',
|
||||
|
@ -108,6 +112,7 @@ def test_agendas_api(settings, app):
|
|||
'minimal_booking_delay_in_working_days': False,
|
||||
'maximal_booking_delay': 56,
|
||||
'minimal_booking_time': '00:00:00',
|
||||
'admin_role': None,
|
||||
'edit_role': None,
|
||||
'view_role': None,
|
||||
'category': None,
|
||||
|
@ -126,6 +131,7 @@ def test_agendas_api(settings, app):
|
|||
'minimal_booking_delay': 1,
|
||||
'maximal_booking_delay': 56,
|
||||
'minimal_booking_time': '00:00:00',
|
||||
'admin_role': None,
|
||||
'edit_role': None,
|
||||
'view_role': 'View',
|
||||
'category': 'category-b',
|
||||
|
@ -149,6 +155,7 @@ def test_agendas_api(settings, app):
|
|||
'minimal_booking_delay': 1,
|
||||
'maximal_booking_delay': 56,
|
||||
'minimal_booking_time': '00:00:00',
|
||||
'admin_role': None,
|
||||
'edit_role': None,
|
||||
'view_role': None,
|
||||
'category': None,
|
||||
|
@ -169,6 +176,7 @@ def test_agendas_api(settings, app):
|
|||
'minimal_booking_delay': 1,
|
||||
'maximal_booking_delay': 56,
|
||||
'minimal_booking_time': '00:00:00',
|
||||
'admin_role': 'Admin',
|
||||
'edit_role': 'Edit',
|
||||
'view_role': 'View',
|
||||
'category': None,
|
||||
|
@ -425,6 +433,7 @@ def test_virtual_agenda_detail(app, virtual_meetings_agenda):
|
|||
'minimal_booking_delay': None,
|
||||
'maximal_booking_delay': None,
|
||||
'minimal_booking_time': '00:00:00',
|
||||
'admin_role': None,
|
||||
'edit_role': None,
|
||||
'view_role': None,
|
||||
'category': None,
|
||||
|
@ -502,7 +511,8 @@ def test_add_agenda(app, user, settings):
|
|||
'minimal_booking_delay': 'oups',
|
||||
'minimal_booking_delay_in_working_days': 'oups',
|
||||
'anonymize_delay': 'oups',
|
||||
'edit_role': 'oups',
|
||||
'admin_role': 'oups',
|
||||
'edit_role': 'bla',
|
||||
'view_role': 'plop',
|
||||
'category': 'oups',
|
||||
'events_type': 'oups',
|
||||
|
@ -514,7 +524,8 @@ def test_add_agenda(app, user, settings):
|
|||
'minimal_booking_delay': ['A valid integer is required.'],
|
||||
'minimal_booking_delay_in_working_days': ['Must be a valid boolean.'],
|
||||
'anonymize_delay': ['A valid integer is required.'],
|
||||
'edit_role': ['unknown role: oups'],
|
||||
'admin_role': ['unknown role: oups'],
|
||||
'edit_role': ['unknown role: bla'],
|
||||
'view_role': ['unknown role: plop'],
|
||||
'category': ['unknown category: oups'],
|
||||
'events_type': ['unknown events type: oups'],
|
||||
|
@ -567,6 +578,7 @@ def test_add_agenda(app, user, settings):
|
|||
assert AgendaSnapshot.objects.count() == 1
|
||||
|
||||
settings.WORKING_DAY_CALENDAR = 'workalendar.europe.France'
|
||||
admin_group = Group.objects.create(name='Admin')
|
||||
edit_group = Group.objects.create(name='Edit')
|
||||
view_group = Group.objects.create(name='View')
|
||||
|
||||
|
@ -578,6 +590,7 @@ def test_add_agenda(app, user, settings):
|
|||
'minimal_booking_delay': 1,
|
||||
'maximal_booking_delay': 3,
|
||||
'anonymize_delay': 30,
|
||||
'admin_role': 'Admin',
|
||||
'edit_role': 'Edit',
|
||||
'view_role': 'View',
|
||||
'category': 'category-a',
|
||||
|
@ -592,6 +605,7 @@ def test_add_agenda(app, user, settings):
|
|||
day=10, hour=0, minute=0, second=0, microsecond=0
|
||||
)
|
||||
assert agenda.minimal_booking_time == datetime.time(0)
|
||||
assert agenda.admin_role == admin_group
|
||||
assert agenda.edit_role == edit_group
|
||||
assert agenda.view_role == view_group
|
||||
assert agenda.category == category_a
|
||||
|
@ -609,6 +623,7 @@ def test_add_agenda(app, user, settings):
|
|||
'maximal_booking_delay': 3,
|
||||
'minimal_booking_time': None,
|
||||
'anonymize_delay': 30,
|
||||
'admin_role': 'Admin',
|
||||
'edit_role': 'Edit',
|
||||
'view_role': 'View',
|
||||
'category': 'category-a',
|
||||
|
@ -622,6 +637,7 @@ def test_add_agenda(app, user, settings):
|
|||
assert not resp.json['err']
|
||||
assert len(resp.json['data']) == 1
|
||||
agenda = Agenda.objects.get(slug='foo-events')
|
||||
assert agenda.admin_role == admin_group
|
||||
assert agenda.edit_role == edit_group
|
||||
assert agenda.view_role == view_group
|
||||
assert agenda.min_booking_datetime == localtime(now()).replace(
|
||||
|
|
|
@ -174,10 +174,13 @@ def test_export_agenda(app, admin_user):
|
|||
app.authorization = ('Basic', ('admin', 'admin'))
|
||||
group1 = Group.objects.create(name='group1')
|
||||
group2 = Group.objects.create(name='group2')
|
||||
Agenda.objects.create(label='Rdv', slug='rdv', kind='meetings', edit_role=group1, view_role=group2)
|
||||
group3 = Group.objects.create(name='group3')
|
||||
Agenda.objects.create(
|
||||
label='Rdv', slug='rdv', kind='meetings', admin_role=group1, view_role=group2, edit_role=group3
|
||||
)
|
||||
resp = app.get('/api/export-import/agendas/rdv/')
|
||||
assert resp.json['data']['label'] == 'Rdv'
|
||||
assert resp.json['data']['permissions'] == {'view': 'group2', 'edit': 'group1'}
|
||||
assert resp.json['data']['permissions'] == {'view': 'group2', 'admin': 'group1', 'edit': 'group3'}
|
||||
|
||||
|
||||
def test_export_minor_components(app, admin_user):
|
||||
|
@ -294,7 +297,10 @@ def test_agenda_dependencies_groups(app, admin_user):
|
|||
app.authorization = ('Basic', ('admin', 'admin'))
|
||||
group1 = Group.objects.create(name='group1')
|
||||
group2 = Group.objects.create(name='group2')
|
||||
Agenda.objects.create(label='Rdv', slug='rdv', kind='meetings', edit_role=group1, view_role=group2)
|
||||
group3 = Group.objects.create(name='group3')
|
||||
Agenda.objects.create(
|
||||
label='Rdv', slug='rdv', kind='meetings', admin_role=group1, view_role=group2, edit_role=group3
|
||||
)
|
||||
resp = app.get('/api/export-import/agendas/rdv/dependencies/')
|
||||
# note: with hobo.agent.common installed, 'groups' will contain group slugs,
|
||||
# not group id
|
||||
|
@ -302,6 +308,7 @@ def test_agenda_dependencies_groups(app, admin_user):
|
|||
'data': [
|
||||
{'id': group2.id, 'text': group2.name, 'type': 'roles', 'urls': {}, 'uuid': None},
|
||||
{'id': group1.id, 'text': group1.name, 'type': 'roles', 'urls': {}, 'uuid': None},
|
||||
{'id': group3.id, 'text': group3.name, 'type': 'roles', 'urls': {}, 'uuid': None},
|
||||
],
|
||||
'err': 0,
|
||||
}
|
||||
|
@ -448,7 +455,7 @@ def create_bundle(app, admin_user, visible=True, version_number='42.0'):
|
|||
category, _ = Category.objects.get_or_create(slug='foo', label='Foo')
|
||||
|
||||
meetings_agenda, _ = Agenda.objects.get_or_create(
|
||||
slug='rdv', label='Rdv', kind='meetings', edit_role=group, category=category
|
||||
slug='rdv', label='Rdv', kind='meetings', admin_role=group, category=category
|
||||
)
|
||||
resource, _ = Resource.objects.get_or_create(slug='foo', label='Foo')
|
||||
meetings_agenda.resources.add(resource)
|
||||
|
|
|
@ -58,15 +58,21 @@ def test_manager_user_access(app, manager_user):
|
|||
assert app.get('/manage/', status=403)
|
||||
|
||||
agenda.view_role = manager_user.groups.all()[0]
|
||||
agenda.edit_role = None
|
||||
agenda.admin_role = None
|
||||
agenda.save()
|
||||
assert app.get('/manage/', status=200)
|
||||
|
||||
agenda.edit_role = None
|
||||
agenda.admin_role = None
|
||||
agenda.view_role = manager_user.groups.all()[0]
|
||||
agenda.save()
|
||||
assert app.get('/manage/', status=200)
|
||||
|
||||
agenda.admin_role = None
|
||||
agenda.view_role = None
|
||||
agenda.edit_role = manager_user.groups.all()[0]
|
||||
agenda.save()
|
||||
assert app.get('/manage/', status=200)
|
||||
|
||||
|
||||
def test_home_redirect(app):
|
||||
assert app.get('/', status=302).location.endswith('/manage/')
|
||||
|
@ -477,12 +483,12 @@ def test_add_agenda_and_set_role(app, admin_user, manager_user):
|
|||
|
||||
resp = app.get('/manage/agendas/%s/settings' % agenda.id)
|
||||
resp = resp.click('Configure', href='roles')
|
||||
resp.form['edit_role'] = manager_user.groups.all()[0].pk
|
||||
resp.form['admin_role'] = manager_user.groups.all()[0].pk
|
||||
resp = resp.form.submit().follow()
|
||||
assert 'Edit Role: Managers' in resp.text
|
||||
assert 'Admin Role: Managers' in resp.text
|
||||
assert AgendaSnapshot.objects.count() == 2
|
||||
snapshot = AgendaSnapshot.objects.latest('pk')
|
||||
assert snapshot.serialization['permissions'] == {'edit': 'Managers', 'view': None}
|
||||
assert snapshot.serialization['permissions'] == {'admin': 'Managers', 'view': None, 'edit': None}
|
||||
|
||||
# still only one desk
|
||||
assert agenda.desk_set.count() == 1
|
||||
|
@ -497,9 +503,9 @@ def test_agenda_set_role_with_partial_booking(settings, app, admin_user):
|
|||
|
||||
resp = app.get('/manage/agendas/%s/settings' % agenda.id)
|
||||
resp = resp.click('Configure', href='roles')
|
||||
resp.form['edit_role'] = group.pk
|
||||
resp.form['admin_role'] = group.pk
|
||||
resp = resp.form.submit().follow()
|
||||
assert 'Edit Role: testgroup' in resp.text
|
||||
assert 'Admin Role: testgroup' in resp.text
|
||||
|
||||
|
||||
def test_options_agenda_redirect(app, admin_user):
|
||||
|
@ -789,7 +795,7 @@ def test_options_agenda_as_manager(app, manager_user):
|
|||
agenda.kind = 'events'
|
||||
agenda.save()
|
||||
|
||||
agenda.edit_role = manager_user.groups.all()[0]
|
||||
agenda.admin_role = manager_user.groups.all()[0]
|
||||
agenda.save()
|
||||
|
||||
resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
|
||||
|
@ -870,7 +876,7 @@ def test_inspect_agenda_as_manager(app, manager_user):
|
|||
agenda.save()
|
||||
app.get('/manage/agendas/%s/inspect/' % agenda.pk, status=403)
|
||||
|
||||
agenda.edit_role = manager_user.groups.all()[0]
|
||||
agenda.admin_role = manager_user.groups.all()[0]
|
||||
agenda.save()
|
||||
app.get('/manage/agendas/%s/inspect/' % agenda.pk, status=200)
|
||||
|
||||
|
@ -981,7 +987,7 @@ def test_delete_busy_agenda(app, admin_user):
|
|||
|
||||
def test_delete_agenda_as_manager(app, manager_user):
|
||||
agenda = Agenda(label='Foo bar')
|
||||
agenda.edit_role = manager_user.groups.all()[0]
|
||||
agenda.admin_role = manager_user.groups.all()[0]
|
||||
agenda.save()
|
||||
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
|
||||
app = login(app, username='manager', password='manager')
|
||||
|
@ -2596,7 +2602,7 @@ def test_agenda_view_edit_event(app, manager_user):
|
|||
assert 'Options' not in resp.text
|
||||
assert 'Delete' not in resp.text
|
||||
|
||||
agenda.edit_role = manager_user.groups.all()[0]
|
||||
agenda.admin_role = manager_user.groups.all()[0]
|
||||
agenda.save()
|
||||
event_url = resp.request.url
|
||||
resp = app.get(event_url)
|
||||
|
@ -3368,7 +3374,7 @@ def test_duplicate_agenda(app, admin_user):
|
|||
|
||||
def test_duplicate_agenda_as_manager(app, manager_user):
|
||||
agenda = Agenda(label='Foo bar')
|
||||
agenda.edit_role = manager_user.groups.all()[0]
|
||||
agenda.admin_role = manager_user.groups.all()[0]
|
||||
agenda.save()
|
||||
app = login(app, username='manager', password='manager')
|
||||
resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
|
||||
|
@ -3550,29 +3556,29 @@ def test_agenda_notifications(app, admin_user, managers_group):
|
|||
|
||||
resp = resp.click('Configure', href='notifications')
|
||||
resp.form['cancelled_event_emails'] = 'hop@entrouvert.com, top@entrouvert.com'
|
||||
resp.form['almost_full_event'] = 'edit-role'
|
||||
resp.form['almost_full_event'] = 'admin-role'
|
||||
option = resp.form['almost_full_event'].selectedIndex
|
||||
assert resp.form['almost_full_event'].options[option][2] == 'Edit Role (undefined)'
|
||||
assert resp.form['almost_full_event'].options[option][2] == 'Admin Role (undefined)'
|
||||
resp.form['full_event'] = 'view-role'
|
||||
option = resp.form['full_event'].selectedIndex
|
||||
assert resp.form['full_event'].options[option][2] == 'View Role (Managers)'
|
||||
resp = resp.form.submit().follow()
|
||||
|
||||
settings = agenda.notifications_settings
|
||||
assert settings.almost_full_event == 'edit-role'
|
||||
assert settings.almost_full_event == 'admin-role'
|
||||
assert settings.full_event == 'view-role'
|
||||
assert settings.cancelled_event == 'use-email-field'
|
||||
assert settings.cancelled_event_emails == ['hop@entrouvert.com', 'top@entrouvert.com']
|
||||
|
||||
assert 'Cancelled event: hop@entrouvert.com, top@entrouvert.com will be notified' in resp.text
|
||||
assert 'Almost full event (90%): Edit Role (undefined) will be notified' in resp.text
|
||||
assert 'Almost full event (90%): Admin Role (undefined) will be notified' in resp.text
|
||||
assert 'Full event: View Role (Managers) will be notified' in resp.text
|
||||
|
||||
agenda.edit_role = Group.objects.create(name='hop')
|
||||
agenda.admin_role = Group.objects.create(name='hop')
|
||||
agenda.save()
|
||||
|
||||
resp = app.get('/manage/agendas/%s/settings' % agenda.id)
|
||||
assert 'Almost full event (90%): Edit Role (hop) will be notified' in resp.text
|
||||
assert 'Almost full event (90%): Admin Role (hop) will be notified' in resp.text
|
||||
|
||||
|
||||
def test_agenda_notifications_no_old_events(app, admin_user, mailoutbox):
|
||||
|
@ -3839,9 +3845,11 @@ def test_manager_agenda_roles(app, admin_user, manager_user):
|
|||
resp = app.get('/manage/agendas/%s/settings' % agenda.id)
|
||||
resp = resp.click('Configure', href='roles')
|
||||
|
||||
resp.form['admin_role'] = manager_user.groups.all()[0].pk
|
||||
resp.form['edit_role'] = manager_user.groups.all()[0].pk
|
||||
resp = resp.form.submit().follow()
|
||||
|
||||
assert 'Admin Role: Managers' in resp.text
|
||||
assert 'Edit Role: Managers' in resp.text
|
||||
|
||||
|
||||
|
@ -4193,3 +4201,59 @@ def test_meeting_agenda_lease_display(app, admin_user, manager_user, api_user):
|
|||
assert len(resp.pyquery('.booking')) == 1
|
||||
assert len(resp.pyquery('.booking.lease')) == 1
|
||||
assert 'Currently being booked...' in resp.pyquery('.booking.lease').text()
|
||||
|
||||
|
||||
@freezegun.freeze_time('2024-05-01')
|
||||
def test_meeting_agenda_edit_role(app, manager_user, managers_group):
|
||||
agenda = Agenda.objects.create(
|
||||
label='New Example', kind='meetings', edit_role=managers_group, desk_simple_management=True
|
||||
)
|
||||
meeting_type = MeetingType.objects.create(agenda=agenda, label='Meeting Type', duration=30)
|
||||
|
||||
app = login(app, username='manager', password='manager')
|
||||
resp = app.get('/').follow()
|
||||
resp = resp.click('New Example').follow().follow()
|
||||
resp = resp.click('Settings')
|
||||
|
||||
assert len(resp.pyquery('#sidebar')) == 0
|
||||
assert len(resp.pyquery('.extra-actions-menu-opener')) == 0
|
||||
assert [x.text for x in resp.pyquery('.pk-tabs button')] == [
|
||||
'Desks',
|
||||
'Opening hours',
|
||||
'Booking reminders',
|
||||
'Booking Delays',
|
||||
]
|
||||
|
||||
resp = resp.click('New Desk')
|
||||
resp.form['label'] = 'Desk 1'
|
||||
resp = resp.form.submit().follow()
|
||||
|
||||
assert 'Desk 1' in resp.text
|
||||
|
||||
resp = resp.click('Add a unique period', index=0)
|
||||
resp.form['date'] = '2024-05-02'
|
||||
resp.form['start_time'] = '10:00'
|
||||
resp.form['end_time'] = '17:00'
|
||||
resp = resp.form.submit().follow()
|
||||
|
||||
assert 'Thursday 02 May 2024 / 10 a.m. → 5 p.m.' in resp.text
|
||||
|
||||
resp = resp.click('Add repeating periods')
|
||||
resp.form.get('weekdays', index=4).checked = True
|
||||
resp.form['start_time'] = '10:00'
|
||||
resp.form['end_time'] = '17:00'
|
||||
resp = resp.form.submit().follow()
|
||||
|
||||
assert 'Friday / 10 a.m. → 5 p.m.' in resp.text
|
||||
|
||||
resp = resp.click('Add a time period exception')
|
||||
resp.form['label'] = 'Exception 1'
|
||||
resp.form['start_datetime_0'] = '2024-05-02'
|
||||
resp.form['start_datetime_1'] = '08:00'
|
||||
resp.form['start_datetime_0'] = '2024-05-02'
|
||||
resp.form['end_datetime_1'] = '16:00'
|
||||
resp = resp.form.submit().follow()
|
||||
|
||||
assert 'Exception 1' in resp.text
|
||||
|
||||
breakpoint()
|
||||
|
|
|
@ -127,7 +127,7 @@ def test_add_event_as_manager(app, manager_user):
|
|||
resp = app.get('/manage/agendas/%s/' % agenda.id, status=302)
|
||||
app.get('/manage/agendas/%s/add-event' % agenda.id, status=403)
|
||||
|
||||
agenda.edit_role = manager_user.groups.all()[0]
|
||||
agenda.admin_role = manager_user.groups.all()[0]
|
||||
agenda.save()
|
||||
|
||||
resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
|
||||
|
@ -270,7 +270,7 @@ def test_edit_event_as_manager(app, manager_user):
|
|||
app = login(app, username='manager', password='manager')
|
||||
resp = app.get('/manage/agendas/%s/events/%s/edit' % (agenda.id, event.id), status=403)
|
||||
|
||||
agenda.edit_role = manager_user.groups.all()[0]
|
||||
agenda.admin_role = manager_user.groups.all()[0]
|
||||
agenda.save()
|
||||
resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=200)
|
||||
resp = resp.click('Feb. 15, 2016, 5 p.m.')
|
||||
|
@ -722,7 +722,7 @@ def test_delete_recurring_event(app, admin_user, freezer):
|
|||
|
||||
def test_delete_event_as_manager(app, manager_user):
|
||||
agenda = Agenda(label='Foo bar')
|
||||
agenda.edit_role = manager_user.groups.all()[0]
|
||||
agenda.admin_role = manager_user.groups.all()[0]
|
||||
agenda.save()
|
||||
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
|
||||
event = Event(start_datetime=make_aware(datetime.datetime(2016, 2, 15, 17, 0)), places=10, agenda=agenda)
|
||||
|
|
|
@ -38,7 +38,7 @@ def test_options_meetings_agenda_delays(app, admin_user):
|
|||
|
||||
def test_options_meetings_agenda_num_queries(app, admin_user, managers_group):
|
||||
agenda = Agenda.objects.create(
|
||||
label='Agenda', kind='meetings', edit_role=managers_group, view_role=managers_group
|
||||
label='Agenda', kind='meetings', admin_role=managers_group, view_role=managers_group
|
||||
)
|
||||
resource = Resource.objects.create(label='Resource')
|
||||
agenda.resources.add(resource)
|
||||
|
|
|
@ -1010,7 +1010,7 @@ def test_resource_access_permission(app, manager_user):
|
|||
assert app.get('/manage/resource/%s/' % resource.pk, status=403)
|
||||
assert app.get('/manage/resource/%s/' % resource2.pk, status=403)
|
||||
|
||||
agenda.edit_role = manager_user.groups.all()[0]
|
||||
agenda.admin_role = manager_user.groups.all()[0]
|
||||
agenda.save()
|
||||
|
||||
resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
|
||||
|
|
|
@ -117,7 +117,7 @@ def test_agenda_history_as_manager(app, manager_user):
|
|||
status=403,
|
||||
)
|
||||
|
||||
agenda.edit_role = manager_user.groups.all()[0]
|
||||
agenda.admin_role = manager_user.groups.all()[0]
|
||||
agenda.save()
|
||||
app.get('/manage/agendas/%s/history/' % agenda.pk, status=200)
|
||||
app.get(
|
||||
|
|
|
@ -106,7 +106,7 @@ def test_meetings_agenda_add_time_period_as_manager(app, manager_user):
|
|||
app.get('/manage/timeperiods/%d/edit' % time_period.id, status=403)
|
||||
app.get('/manage/timeperiods/%d/delete' % time_period.id, status=403)
|
||||
# grant edit right to manager
|
||||
agenda.edit_role = manager_user.groups.all()[0]
|
||||
agenda.admin_role = manager_user.groups.all()[0]
|
||||
agenda.save()
|
||||
|
||||
resp = app.get('/manage/agendas/%s/settings' % agenda.pk)
|
||||
|
|
|
@ -1244,13 +1244,14 @@ def test_timeperiodexception_creation_from_ics_with_recurrences_atreal():
|
|||
def test_management_role_deletion():
|
||||
group = Group(name='Group')
|
||||
group.save()
|
||||
agenda = Agenda(label='Test agenda', edit_role=group, view_role=group)
|
||||
agenda = Agenda(label='Test agenda', admin_role=group, edit_role=group, view_role=group)
|
||||
agenda.save()
|
||||
|
||||
Group.objects.all().delete()
|
||||
|
||||
assert Agenda.objects.get(id=agenda.id).view_role is None
|
||||
assert Agenda.objects.get(id=agenda.id).edit_role is None
|
||||
assert Agenda.objects.get(id=agenda.id).admin_role is None
|
||||
|
||||
|
||||
def test_virtual_agenda_init():
|
||||
|
@ -1948,11 +1949,11 @@ def test_agenda_notifications_role_email(mocked_role, emails_to_members, emails,
|
|||
expected_recipients.append(user.email)
|
||||
expected_email_count = 1 if emails else 0
|
||||
|
||||
agenda = Agenda.objects.create(label='Foo bar', kind='event', edit_role=group)
|
||||
agenda = Agenda.objects.create(label='Foo bar', kind='event', admin_role=group)
|
||||
|
||||
event = Event.objects.create(agenda=agenda, places=10, start_datetime=now(), label='Hop')
|
||||
settings = AgendaNotificationsSettings.objects.create(agenda=agenda)
|
||||
settings.almost_full_event = AgendaNotificationsSettings.EDIT_ROLE
|
||||
settings.almost_full_event = AgendaNotificationsSettings.ADMIN_ROLE
|
||||
settings.save()
|
||||
|
||||
# book 9/10 places to reach almost full state
|
||||
|
|
|
@ -450,8 +450,10 @@ def test_import_export_permissions(app):
|
|||
meetings_agenda = Agenda.objects.create(label='Foo Bar', kind='meetings')
|
||||
group1 = Group.objects.create(name='gé1')
|
||||
group2 = Group.objects.create(name='gé2')
|
||||
group3 = Group.objects.create(name='gé3')
|
||||
meetings_agenda.view_role = group1
|
||||
meetings_agenda.edit_role = group2
|
||||
meetings_agenda.admin_role = group2
|
||||
meetings_agenda.edit_role = group3
|
||||
meetings_agenda.save()
|
||||
output = get_output_of_command('export_site')
|
||||
assert len(json.loads(output)['agendas']) == 1
|
||||
|
@ -467,59 +469,25 @@ def test_import_export_permissions(app):
|
|||
group1.save()
|
||||
with pytest.raises(AgendaImportError) as excinfo:
|
||||
import_site(json.loads(output), overwrite=True)
|
||||
assert '%s' % excinfo.value == 'Missing roles: "gé2"'
|
||||
assert 'gé2' in str(excinfo.value) and 'gé3' in str(excinfo.value)
|
||||
|
||||
with tempfile.NamedTemporaryFile() as f:
|
||||
f.write(force_bytes(output))
|
||||
f.flush()
|
||||
with pytest.raises(CommandError) as excinfo:
|
||||
call_command('import_site', f.name)
|
||||
assert '%s' % excinfo.value == 'Missing roles: "gé2"'
|
||||
assert 'gé2' in str(excinfo.value) and 'gé3' in str(excinfo.value)
|
||||
|
||||
group2 = Group(name='gé2')
|
||||
group2.save()
|
||||
group3 = Group(name='gé3')
|
||||
group3.save()
|
||||
import_site(json.loads(output), overwrite=True)
|
||||
|
||||
agenda = Agenda.objects.get(slug=meetings_agenda.slug)
|
||||
assert agenda.view_role == group1
|
||||
assert agenda.edit_role == group2
|
||||
|
||||
|
||||
def test_import_export_permissions_admin_role(app):
|
||||
meetings_agenda = Agenda.objects.create(label='Foo Bar', kind='meetings')
|
||||
group1 = Group.objects.create(name='gé1')
|
||||
group2 = Group.objects.create(name='gé2')
|
||||
group3 = Group.objects.create(name='gé3')
|
||||
meetings_agenda.view_role = group1
|
||||
meetings_agenda.edit_role = group2
|
||||
meetings_agenda.save()
|
||||
|
||||
output = json.loads(get_output_of_command('export_site'))
|
||||
|
||||
# simulate newest export format
|
||||
output['agendas'][0]['permissions'] = {
|
||||
'admin': 'gé1', # new admin role permissions corresponds to current edit role permissions
|
||||
'edit': 'gé2', # new edit role has no equivalent and should be ignored
|
||||
'view': 'gé3', # view role corresponds to current view role
|
||||
}
|
||||
|
||||
import_site(data={}, clean=True)
|
||||
assert Agenda.objects.count() == 0
|
||||
Group.objects.all().delete()
|
||||
|
||||
group1 = Group.objects.create(name='gé1')
|
||||
group2 = Group.objects.create(name='gé2')
|
||||
group3 = Group.objects.create(name='gé3')
|
||||
import_site(output, overwrite=True)
|
||||
|
||||
agenda = Agenda.objects.get(slug=meetings_agenda.slug)
|
||||
assert agenda.edit_role == group1
|
||||
assert agenda.view_role == group3
|
||||
|
||||
group1.delete()
|
||||
with pytest.raises(AgendaImportError) as excinfo:
|
||||
import_site(output, overwrite=True)
|
||||
assert '%s' % excinfo.value == 'Missing roles: "gé1"'
|
||||
assert agenda.admin_role == group2
|
||||
assert agenda.edit_role == group3
|
||||
|
||||
|
||||
def test_import_export_agenda_with_resources(app):
|
||||
|
@ -820,7 +788,7 @@ def test_import_export_notification_settings():
|
|||
Desk.objects.create(agenda=agenda, slug='_exceptions_holder')
|
||||
AgendaNotificationsSettings.objects.create(
|
||||
agenda=agenda,
|
||||
almost_full_event=AgendaNotificationsSettings.EDIT_ROLE,
|
||||
almost_full_event=AgendaNotificationsSettings.ADMIN_ROLE,
|
||||
full_event=AgendaNotificationsSettings.VIEW_ROLE,
|
||||
cancelled_event=AgendaNotificationsSettings.EMAIL_FIELD,
|
||||
cancelled_event_emails=['hop@entrouvert.com', 'top@entrouvert.com'],
|
||||
|
@ -835,7 +803,7 @@ def test_import_export_notification_settings():
|
|||
agenda = Agenda.objects.first()
|
||||
AgendaNotificationsSettings.objects.get(
|
||||
agenda=agenda,
|
||||
almost_full_event=AgendaNotificationsSettings.EDIT_ROLE,
|
||||
almost_full_event=AgendaNotificationsSettings.ADMIN_ROLE,
|
||||
full_event=AgendaNotificationsSettings.VIEW_ROLE,
|
||||
cancelled_event=AgendaNotificationsSettings.EMAIL_FIELD,
|
||||
cancelled_event_emails=['hop@entrouvert.com', 'top@entrouvert.com'],
|
||||
|
|
|
@ -441,3 +441,55 @@ def test_migration_booking_check_data():
|
|||
assert with_check_type.user_check.end_time == datetime.time(14, 0)
|
||||
assert with_check_type.computed_start_time == datetime.time(12, 30)
|
||||
assert with_check_type.computed_end_time == datetime.time(14, 30)
|
||||
|
||||
|
||||
def test_migration_notification_settings_role():
|
||||
app = 'agendas'
|
||||
|
||||
migrate_from = [(app, '0172_rename_edit_role_agenda_admin_role')]
|
||||
migrate_to = [(app, '0173_migrate_notification_settings_role')]
|
||||
executor = MigrationExecutor(connection)
|
||||
old_apps = executor.loader.project_state(migrate_from).apps
|
||||
executor.migrate(migrate_from)
|
||||
|
||||
Agenda = old_apps.get_model(app, 'Agenda')
|
||||
AgendaNotificationsSettings = old_apps.get_model('agendas', 'AgendaNotificationsSettings')
|
||||
|
||||
agenda = Agenda.objects.create(slug='foo1')
|
||||
empty_settings = AgendaNotificationsSettings.objects.create(agenda=agenda)
|
||||
agenda = Agenda.objects.create(slug='foo2')
|
||||
view_settings = AgendaNotificationsSettings.objects.create(
|
||||
agenda=agenda,
|
||||
almost_full_event='view-role',
|
||||
full_event='view-role',
|
||||
cancelled_event='view-role',
|
||||
)
|
||||
agenda = Agenda.objects.create(slug='foo3')
|
||||
edit_settings = AgendaNotificationsSettings.objects.create(
|
||||
agenda=agenda,
|
||||
almost_full_event='edit-role',
|
||||
full_event='edit-role',
|
||||
cancelled_event='edit-role',
|
||||
)
|
||||
|
||||
executor = MigrationExecutor(connection)
|
||||
executor.migrate(migrate_to)
|
||||
executor.loader.build_graph()
|
||||
|
||||
apps = executor.loader.project_state(migrate_to).apps
|
||||
AgendaNotificationsSettings = apps.get_model('agendas', 'AgendaNotificationsSettings')
|
||||
|
||||
empty_settings = AgendaNotificationsSettings.objects.get(pk=empty_settings.pk)
|
||||
assert empty_settings.almost_full_event == ''
|
||||
assert empty_settings.full_event == ''
|
||||
assert empty_settings.cancelled_event == ''
|
||||
|
||||
view_settings = AgendaNotificationsSettings.objects.get(pk=view_settings.pk)
|
||||
assert view_settings.almost_full_event == 'view-role'
|
||||
assert view_settings.full_event == 'view-role'
|
||||
assert view_settings.cancelled_event == 'view-role'
|
||||
|
||||
edit_settings = AgendaNotificationsSettings.objects.get(pk=edit_settings.pk)
|
||||
assert edit_settings.almost_full_event == 'admin-role'
|
||||
assert edit_settings.full_event == 'admin-role'
|
||||
assert edit_settings.cancelled_event == 'admin-role'
|
||||
|
|
Loading…
Reference in New Issue