Projet

Général

Profil

0001-wip.patch

Valentin Deniaud, 02 juillet 2020 17:27

Télécharger (13,6 ko)

Voir les différences:

Subject: [PATCH] wip

 .../0051_agendanotificationssettings.py       | 108 ++++++++++++++++++
 chrono/agendas/models.py                      |  70 ++++++++++++
 chrono/manager/forms.py                       |  26 +++++
 .../manager_agenda_notifications_form.html    |  48 ++++++++
 .../manager_events_agenda_settings.html       |  18 +++
 chrono/manager/urls.py                        |   5 +
 chrono/manager/views.py                       |  18 +++
 7 files changed, 293 insertions(+)
 create mode 100644 chrono/agendas/migrations/0051_agendanotificationssettings.py
 create mode 100644 chrono/manager/templates/chrono/manager_agenda_notifications_form.html
chrono/agendas/migrations/0051_agendanotificationssettings.py
1
# -*- coding: utf-8 -*-
2
# Generated by Django 1.11.18 on 2020-07-02 14:42
3
from __future__ import unicode_literals
4

  
5
import django.contrib.postgres.fields
6
from django.db import migrations, models
7
import django.db.models.deletion
8

  
9

  
10
class Migration(migrations.Migration):
11

  
12
    dependencies = [
13
        ('auth', '0008_alter_user_username_max_length'),
14
        ('agendas', '0050_event_slug'),
15
    ]
16

  
17
    operations = [
18
        migrations.CreateModel(
19
            name='AgendaNotificationsSettings',
20
            fields=[
21
                (
22
                    'id',
23
                    models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
24
                ),
25
                (
26
                    'use_email_fields',
27
                    models.BooleanField(default=False, verbose_name='Use email addresses instead of roles'),
28
                ),
29
                (
30
                    'almost_full_emails',
31
                    django.contrib.postgres.fields.ArrayField(
32
                        base_field=models.EmailField(max_length=254),
33
                        blank=True,
34
                        help_text='Enter a comma separated list of email addresses.',
35
                        null=True,
36
                        size=None,
37
                        verbose_name='Almost full event (90%)',
38
                    ),
39
                ),
40
                (
41
                    'full_emails',
42
                    django.contrib.postgres.fields.ArrayField(
43
                        base_field=models.EmailField(max_length=254),
44
                        blank=True,
45
                        help_text='Enter a comma separated list of email addresses.',
46
                        null=True,
47
                        size=None,
48
                        verbose_name='Full event',
49
                    ),
50
                ),
51
                (
52
                    'cancelled_emails',
53
                    django.contrib.postgres.fields.ArrayField(
54
                        base_field=models.EmailField(max_length=254),
55
                        blank=True,
56
                        help_text='Enter a comma separated list of email addresses.',
57
                        null=True,
58
                        size=None,
59
                        verbose_name='Cancelled event',
60
                    ),
61
                ),
62
                (
63
                    'agenda',
64
                    models.OneToOneField(
65
                        on_delete=django.db.models.deletion.CASCADE,
66
                        related_name='notifications_settings',
67
                        to='agendas.Agenda',
68
                    ),
69
                ),
70
                (
71
                    'almost_full_role',
72
                    models.ForeignKey(
73
                        blank=True,
74
                        default=None,
75
                        null=True,
76
                        on_delete=django.db.models.deletion.SET_NULL,
77
                        related_name='+',
78
                        to='auth.Group',
79
                        verbose_name='Almost full event (90%)',
80
                    ),
81
                ),
82
                (
83
                    'cancelled_role',
84
                    models.ForeignKey(
85
                        blank=True,
86
                        default=None,
87
                        null=True,
88
                        on_delete=django.db.models.deletion.SET_NULL,
89
                        related_name='+',
90
                        to='auth.Group',
91
                        verbose_name='Cancelled event',
92
                    ),
93
                ),
94
                (
95
                    'full_role',
96
                    models.ForeignKey(
97
                        blank=True,
98
                        default=None,
99
                        null=True,
100
                        on_delete=django.db.models.deletion.SET_NULL,
101
                        related_name='+',
102
                        to='auth.Group',
103
                        verbose_name='Full event',
104
                    ),
105
                ),
106
            ],
107
        ),
108
    ]
chrono/agendas/models.py
29 29
import django
30 30
from django.conf import settings
31 31
from django.contrib.auth.models import Group
32
from django.contrib.postgres.fields import ArrayField
32 33
from django.core.exceptions import FieldDoesNotExist
33 34
from django.core.exceptions import ValidationError
34 35
from django.core.validators import MaxValueValidator
......
1363 1364
    def as_interval(self):
1364 1365
        '''Simplify insertion into IntervalSet'''
1365 1366
        return Interval(self.start_datetime, self.end_datetime)
1367

  
1368

  
1369
class AgendaNotificationsSettings(models.Model):
1370
    agenda = models.OneToOneField(Agenda, on_delete=models.CASCADE, related_name='notifications_settings')
1371
    use_email_fields = models.BooleanField(
1372
        verbose_name=_('Use email addresses instead of roles'), default=False
1373
    )
1374

  
1375
    almost_full_role = models.ForeignKey(
1376
        Group,
1377
        blank=True,
1378
        null=True,
1379
        default=None,
1380
        related_name='+',
1381
        verbose_name=_('Almost full event (90%)'),
1382
        on_delete=models.SET_NULL,
1383
    )
1384
    almost_full_emails = ArrayField(
1385
        models.EmailField(),
1386
        blank=True,
1387
        null=True,
1388
        verbose_name=_('Almost full event (90%)'),
1389
        help_text=_('Enter a comma separated list of email addresses.'),
1390
    )
1391

  
1392
    full_role = models.ForeignKey(
1393
        Group,
1394
        blank=True,
1395
        null=True,
1396
        default=None,
1397
        related_name='+',
1398
        verbose_name=_('Full event'),
1399
        on_delete=models.SET_NULL,
1400
    )
1401
    full_emails = ArrayField(
1402
        models.EmailField(),
1403
        blank=True,
1404
        null=True,
1405
        verbose_name=_('Full event'),
1406
        help_text=_('Enter a comma separated list of email addresses.'),
1407
    )
1408

  
1409
    cancelled_role = models.ForeignKey(
1410
        Group,
1411
        blank=True,
1412
        null=True,
1413
        default=None,
1414
        related_name='+',
1415
        verbose_name=_('Cancelled event'),
1416
        on_delete=models.SET_NULL,
1417
    )
1418
    cancelled_emails = ArrayField(
1419
        models.EmailField(),
1420
        blank=True,
1421
        null=True,
1422
        verbose_name=_('Cancelled event'),
1423
        help_text=_('Enter a comma separated list of email addresses.'),
1424
    )
1425

  
1426
    def __iter__(self):
1427
        '''Yield enabled settings verbose names and values'''
1428
        if self.use_email_fields:
1429
            fields = ['almost_full_emails', 'full_emails', 'cancelled_emails']
1430
        else:
1431
            fields = ['almost_full_role', 'full_role', 'cancelled_role']
1432
        for field in fields:
1433
            value = getattr(self, field)
1434
            if value:
1435
                yield (self._meta.get_field(field).verbose_name, getattr(self, field))
chrono/manager/forms.py
37 37
    TimePeriodExceptionSource,
38 38
    VirtualMember,
39 39
    Resource,
40
    AgendaNotificationsSettings,
40 41
    WEEKDAYS_LIST,
41 42
)
42 43

  
......
428 429

  
429 430
class AgendaDuplicateForm(forms.Form):
430 431
    label = forms.CharField(label=_('New label'), max_length=150, required=False)
432

  
433

  
434
class AgendaNotificationsForm(forms.ModelForm):
435
    role_fields = ['almost_full_role', 'full_role', 'cancelled_role']
436
    email_fields = ['almost_full_emails', 'full_emails', 'cancelled_emails']
437

  
438
    class Meta:
439
        model = AgendaNotificationsSettings
440
        fields = '__all__'
441
        widgets = {
442
            'agenda': forms.HiddenInput(),
443
        }
444

  
445
    def __init__(self, *args, **kwargs):
446
        super().__init__(*args, **kwargs)
447

  
448
        for field in self.email_fields:
449
            self.fields[field].widget.attrs['class'] = 'notification-email-field'
450
            self.fields[field].widget.attrs['size'] = 80
451

  
452
        for field in self.role_fields:
453
            self.fields[field].widget.attrs['class'] = 'notification-role-field'
454

  
455
    # TODO restrict roles to view and edit, and only if email is present
456
    # or use sort on initial qs so view and edit are top
chrono/manager/templates/chrono/manager_agenda_notifications_form.html
1
{% extends "chrono/manager_agenda_view.html" %}
2
{% load i18n %}
3

  
4
{% block breadcrumb %}
5
{{ block.super }}
6
<a href="">{% trans "Notification settings" %}</a>
7
{% endblock %}
8

  
9
{% block appbar %}
10
<h2>{% trans "Notification settings" %}</h2>
11
{% endblock %}
12

  
13
{% block content %}
14
<form method="post" enctype="multipart/form-data">
15
  {% csrf_token %}
16
  {{ form.as_p }}
17
  <div class="buttons">
18
    <button class="submit-button">{% trans "Save" %}</button>
19
    <a class="cancel" href="{% url 'chrono-manager-agenda-settings' pk=agenda.id %}">{% trans 'Cancel' %}</a>
20
  </div>
21
</form>
22

  
23
<script>
24
function display_email_fields(show){
25
  field_to_show = 'input.notification-email-field';
26
  field_to_hide = 'select.notification-role-field';
27

  
28
  if(!show)
29
    [field_to_show, field_to_hide] = [field_to_hide, field_to_show];
30

  
31
  $(field_to_show).each(function(index, element){
32
    console.log($(this).parent('p'));
33
    $(this).parent('p').show();
34
  });
35
  $(field_to_hide).each(function(index, element){
36
    $(this).parent('p').hide();
37
  });
38
}
39

  
40
$('input#id_use_email_fields').change(function(){
41
  if ($(this).is(':checked'))
42
    display_email_fields(true);
43
  else
44
    display_email_fields(false);
45
});
46
$('input#id_use_email_fields').trigger('change');
47
</script>
48
{% endblock %}
chrono/manager/templates/chrono/manager_events_agenda_settings.html
62 62
</div>
63 63
</div>
64 64

  
65
<div class="section">
66
<h3>{% trans "Notifications" %}</h3>
67
<div>
68
<ul>
69
{% for setting, value in object.notifications_settings %}
70
  <li>
71
  {% blocktrans %}
72
  {{ setting }}: <i>{{ value }}</i> will receive a notification.
73
  {% endblocktrans %}
74
  </li>
75
{% empty %}
76
{% trans "Notifications are disabled for this agenda." %}
77
{% endfor %}
78
</ul>
79
<a rel="popup" href="{% url 'chrono-manager-agenda-notifications-settings' pk=object.id %}">{% trans 'Configure' %}</a>
80
</div>
81
</div>
82

  
65 83
{% endblock %}
chrono/manager/urls.py
59 59
        views.agenda_import_events,
60 60
        name='chrono-manager-agenda-import-events',
61 61
    ),
62
    url(
63
        r'^agendas/(?P<pk>\d+)/notifications$',
64
        views.agenda_notifications_settings,
65
        name='chrono-manager-agenda-notifications-settings',
66
    ),
62 67
    url(
63 68
        r'^agendas/(?P<pk>\d+)/events/(?P<event_pk>\d+)/$',
64 69
        views.event_view,
chrono/manager/views.py
59 59
    TimePeriodExceptionSource,
60 60
    VirtualMember,
61 61
    Resource,
62
    AgendaNotificationsSettings,
62 63
)
63 64

  
64 65
from .forms import (
......
82 83
    ResourceEditForm,
83 84
    AgendaResourceForm,
84 85
    AgendaDuplicateForm,
86
    AgendaDuplicateForm,
87
    AgendaNotificationsForm,
85 88
)
86 89
from .utils import import_site
87 90

  
......
1210 1213
agenda_import_events = AgendaImportEventsView.as_view()
1211 1214

  
1212 1215

  
1216
class AgendaNotificationsSettingsView(ManagedAgendaMixin, UpdateView):
1217
    template_name = 'chrono/manager_agenda_notifications_form.html'
1218
    model = AgendaNotificationsSettings
1219
    form_class = AgendaNotificationsForm
1220

  
1221
    def get_object(self):
1222
        try:
1223
            return self.agenda.notifications_settings
1224
        except AgendaNotificationsSettings.DoesNotExist:
1225
            return AgendaNotificationsSettings.objects.create(agenda=self.agenda)
1226

  
1227

  
1228
agenda_notifications_settings = AgendaNotificationsSettingsView.as_view()
1229

  
1230

  
1213 1231
class EventDetailView(ViewableAgendaMixin, DetailView):
1214 1232
    model = Event
1215 1233
    pk_url_kwarg = 'event_pk'
1216
-