]> git.parisson.com Git - teleforma.git/commitdiff
Add grouped messages
authorYoan Le Clanche <yoanl@pilotsystems.net>
Mon, 22 May 2023 12:33:37 +0000 (14:33 +0200)
committerYoan Le Clanche <yoanl@pilotsystems.net>
Mon, 22 May 2023 12:33:37 +0000 (14:33 +0200)
15 files changed:
teleforma/admin.py
teleforma/migrations/0005_auto_20230522_0936.py [new file with mode: 0644]
teleforma/migrations/0006_groupedmessage_studentgroup.py [new file with mode: 0644]
teleforma/models/crfpa.py
teleforma/webclass/admin.py
teleforma/webclass/forms.py
teleforma/webclass/migrations/0002_auto_20230522_1200.py [new file with mode: 0644]
teleforma/webclass/models.py
teleforma/webclass/templates/webclass/appointments.html
teleforma/webclass/templates/webclass/appointments_professor.html
teleforma/webclass/templates/webclass/inc/webclass_corrections_list.html [new file with mode: 0644]
teleforma/webclass/templates/webclass/inc/webclass_list.html
teleforma/webclass/templates/webclass/webclass_record.html [new file with mode: 0644]
teleforma/webclass/urls.py
teleforma/webclass/views.py

index d3f9325e4c37ede3d61e6e98dac8ab4202c17dfb..7ef112bfe4f38f92d5d6133b91ce66bb4ab72f7b 100644 (file)
@@ -221,13 +221,13 @@ else:
 
             export_xls.short_description = "Export vers XLS"
 
-            def add_to_group(self, request, queryset):
-                group_name = request.POST['group_name']
-                group, c = StudentGroup.objects.get_or_create(name=group_name)
-                for student in queryset:
-                    group.students.add(student)
-                # self.message_user(request, ("Successfully added to group : %s") % (group_name,), messages.SUCCESS)
-            add_to_group.short_description = "Ajouter au groupe"
+        def add_to_group(self, request, queryset):
+            group_name = request.POST['group_name']
+            group, c = StudentGroup.objects.get_or_create(name=group_name)
+            for student in queryset:
+                group.students.add(student)
+            # self.message_user(request, ("Successfully added to group : %s") % (group_name,), messages.SUCCESS)
+        add_to_group.short_description = "Ajouter au groupe"
 
 
 class CorrectorAdmin(admin.ModelAdmin):
@@ -478,7 +478,7 @@ admin.site.register(LiveStream)
 admin.site.register(Student, StudentAdmin)
 # admin.site.register(Corrector, CorrectorAdmin)
 admin.site.register(Professor, ProfessorAdmin)
-admin.site.register(StudentGroup, StudentGroupAdmin)
+admin.site.register(StudentGroup, StudentGroupAdmin)
 admin.site.register(GroupedMessage)
 admin.site.register(Home, HomeAdmin)
 admin.site.register(Parameters, ParametersAdmin)
diff --git a/teleforma/migrations/0005_auto_20230522_0936.py b/teleforma/migrations/0005_auto_20230522_0936.py
new file mode 100644 (file)
index 0000000..f2a9dc3
--- /dev/null
@@ -0,0 +1,23 @@
+# Generated by Django 3.2.13 on 2023-05-22 09:36
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('teleforma', '0004_payment'),
+    ]
+
+    operations = [
+        migrations.RemoveField(
+            model_name='studentgroup',
+            name='students',
+        ),
+        migrations.DeleteModel(
+            name='GroupedMessage',
+        ),
+        migrations.DeleteModel(
+            name='StudentGroup',
+        ),
+    ]
diff --git a/teleforma/migrations/0006_groupedmessage_studentgroup.py b/teleforma/migrations/0006_groupedmessage_studentgroup.py
new file mode 100644 (file)
index 0000000..98f4ba8
--- /dev/null
@@ -0,0 +1,45 @@
+# Generated by Django 3.2.13 on 2023-05-22 09:36
+
+from django.conf import settings
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+        ('teleforma', '0005_auto_20230522_0936'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='StudentGroup',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('name', models.CharField(max_length=255, verbose_name='name')),
+                ('students', models.ManyToManyField(blank=True, related_name='groups', to='teleforma.Student', verbose_name='students')),
+            ],
+            options={
+                'verbose_name': 'Student group',
+                'db_table': 'teleforma_student_groups',
+            },
+        ),
+        migrations.CreateModel(
+            name='GroupedMessage',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('subject', models.CharField(max_length=119, verbose_name='subject')),
+                ('message', models.TextField(verbose_name='message')),
+                ('to_send', models.BooleanField(default=False, verbose_name='to send')),
+                ('sent', models.BooleanField(default=False, verbose_name='sent')),
+                ('date_sent', models.DateTimeField(blank=True, null=True, verbose_name='date sent')),
+                ('group', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='grouped_messages', to='teleforma.studentgroup', verbose_name='group')),
+                ('sender', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='grouped_messages', to=settings.AUTH_USER_MODEL, verbose_name='sender')),
+            ],
+            options={
+                'verbose_name': 'Grouped message',
+                'db_table': 'teleforma_grouped_messages',
+            },
+        ),
+    ]
index 12d2b6815c624c6163546710557cf59d2b6266ab..57d8691499e39e90b27fd96fa27cff295779d122 100755 (executable)
@@ -181,6 +181,9 @@ else:
             verbose_name_plural = _('AE students')
             ordering = ['user__last_name']
 
+        def __str__(self):
+            return self.user.get_full_name()
+
 def update_balance_signal(sender, instance, *args, **kwargs):
     try:
         if sender is Student or sender:
index f9b5dbdf95a3324c97f3a747a6906597d3e41bec..8dc7c4afeb7c88682e79b7ad2c749a54e02bf3b2 100644 (file)
@@ -16,14 +16,14 @@ class WebclassSlotInline(admin.StackedInline):
 
 class WebclassAdmin(admin.ModelAdmin):
     inlines = [WebclassSlotInline]
-    list_filter = ('course', 'period', 'iej', 'bbb_server', 'status')
-    list_display = ('course', 'period', 'bbb_server', 'status')
+    list_filter = ('course', 'period', 'iej', 'session', 'bbb_server', 'status')
+    list_display = ('course', 'period', 'session', 'bbb_server', 'status')
     filter_horizontal = ('iej',)
     search_fields = ['id', 'course__code', 'course__title']
 
 class WebclassRecordAdmin(admin.ModelAdmin):
-    list_filter = ('course', 'period')
-    list_display = ('course', 'period', 'created')
+    list_filter = ('course', 'period', 'category')
+    list_display = ('course', 'period', 'category', 'created')
     search_fields = ['id', 'course__code', 'course__title']
 
     # def get_form(self, request, obj=None, **kwargs):
index 424ecf8e6965b3bbaad1904bc414b4902fb7ae7d..8a8be59929ac2204352d01effb9dce8d758cdb71 100644 (file)
@@ -8,14 +8,9 @@ from ..webclass.models import (BBBServer, WebclassRecord, WebclassSlot,
 
 
 class WebclassRecordsForm(Form):
-    # period = ModelChoiceField(label='Période',
-    #                         queryset=Period.objects.filter(is_open=True))
-
-    class Meta:
-        pass
-
 
     def __init__(self, *args, **kwargs):
+        # for each course, we create a field whcih includes a list of bbb course from the same course id and same period id
         self.period_id = kwargs.pop('period_id')
         self.period = Period.objects.get(pk=self.period_id)
         super(WebclassRecordsForm, self).__init__(*args, **kwargs)
@@ -24,8 +19,10 @@ class WebclassRecordsForm(Form):
         all_records = self.get_records_by_course()
 
         for course in courses:
+            # get list of webclass
             webclasses = course.webclass.filter(period=self.period).all()
             if webclasses:
+                # build a rooms id list
                 rooms = []
                 for webclass in webclasses:
                     for slot in webclass.slots.all():
@@ -38,6 +35,8 @@ class WebclassRecordsForm(Form):
                 # for each bbb record for the current course, add an option to the field
 
                 for record in records:
+                    if not record['slot']:
+                        continue
                     webclass_slot = WebclassSlot.objects.get(
                         pk=record['slot'].id)
                     label = u"%s à %s - %s" % (record['start_date'].strftime(
@@ -48,10 +47,14 @@ class WebclassRecordsForm(Form):
                     label=course.title,  choices=vocabulary, required=False)
 
     def get_records_by_course(self):
+        """ 
+        Get all records, in a dict with course_id as key 
+        """
         records = get_records(period_id=self.period_id)
         by_course = {}
         for record in records:
-            by_course.setdefault(record['course_id'], []).append(record)
+            if record.get('course_id'):
+                by_course.setdefault(record['course_id'], []).append(record)
         return by_course
 
     def save_records(self):
diff --git a/teleforma/webclass/migrations/0002_auto_20230522_1200.py b/teleforma/webclass/migrations/0002_auto_20230522_1200.py
new file mode 100644 (file)
index 0000000..f8e14c4
--- /dev/null
@@ -0,0 +1,43 @@
+# Generated by Django 3.2.13 on 2023-05-22 12:00
+
+from django.db import migrations, models
+import teleforma.fields
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('webclass', '0001_initial'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='webclass',
+            name='allow_elearning',
+            field=models.BooleanField(default=True, verbose_name='Autoriser e-learning'),
+        ),
+        migrations.AddField(
+            model_name='webclass',
+            name='allow_presentiel',
+            field=models.BooleanField(default=True, verbose_name='Autoriser présentiel'),
+        ),
+        migrations.AddField(
+            model_name='webclass',
+            name='comment',
+            field=teleforma.fields.ShortTextField(blank=True, max_length=255, verbose_name='comment'),
+        ),
+        migrations.AddField(
+            model_name='webclass',
+            name='session',
+            field=models.CharField(choices=[('1', '1'), ('2', '2'), ('3', '3'), ('4', '4'), ('5', '5'), ('6', '6'), ('7', '7'), ('8', '8'), ('9', '9'), ('10', '10')], default='1', max_length=16, verbose_name='session'),
+        ),
+        migrations.AddField(
+            model_name='webclassrecord',
+            name='category',
+            field=models.CharField(choices=[('WC', 'Webclass'), ('CC', 'Correction de copie')], default='WC', max_length=2, verbose_name='Catégorie'),
+        ),
+        migrations.AddIndex(
+            model_name='webclass',
+            index=models.Index(fields=['status', 'period', 'course'], name='teleforma_w_status_03cc4b_idx'),
+        ),
+    ]
index ea4946a05abf605bb698218096d2f0378fe11b34..430ae8d7e15144c7b4b9dfb61c5d8dd6c79aacbb 100644 (file)
@@ -3,6 +3,7 @@
 import calendar
 import datetime
 from datetime import date, timedelta
+from unidecode import unidecode
 
 import django.db.models as models
 from bigbluebutton_api_python import BigBlueButton
@@ -15,8 +16,9 @@ from django.template.defaultfilters import slugify
 from django.utils import translation
 from django.utils.translation import ugettext_lazy as _
 from jxmlease import XMLDictNode, XMLListNode
-from teleforma.fields import DurationField
-from unidecode import unidecode
+from teleforma.fields import DurationField, ShortTextField
+from teleforma.models import session_choices
+
 
 translation.activate('fr')
 app_label = 'teleforma'
@@ -61,7 +63,7 @@ def get_records_from_bbb(**kwargs):
                 'end': end,
                 'end_date': datetime.datetime.fromtimestamp(end),
                 'url': url,
-                'preview': str(recording.get('playback', {}).get('format', {}).get('preview', {}).get('images', {}).get('image', [])[0]),
+                'preview': str(recording.get('playback', {}).get('format', {}).get('preview', {}).get('images', {}).get('image', [])),
                 'state': str(recording['state']),
             }
             if recording['metadata'].get('periodid'):
@@ -72,7 +74,7 @@ def get_records_from_bbb(**kwargs):
                         pk=int(recording['metadata'].get('slotid', -1)))
                 except WebclassSlot.DoesNotExist:
                     # this happen if the slot is deleted in django admin
-                    continue
+                    pass
                 data.update({
                     'period_id': int(recording['metadata'].get('periodid', -1)),
                     'course_id': int(recording['metadata'].get('courseid', -1)),
@@ -124,10 +126,9 @@ class BBBServer(models.Model):
         return "Serveur %d" % self.id
 
 
-class PublishedManager(models.Manager):
-    def get_query_set(self):
-        return super(PublishedManager, self).get_query_set().filter(status=3).exclude(end_date__lt=date.today())
-
+class WebclassPublishedManager(models.Manager):
+    def get_queryset(self):
+        return super(WebclassPublishedManager, self).get_queryset().filter(status=3).exclude(end_date__lt=date.today())
 
 class Webclass(models.Model):
 
@@ -139,22 +140,30 @@ class Webclass(models.Model):
         'teleforma.Course', related_name='webclass', verbose_name=_('course'), on_delete=models.CASCADE)
     iej = models.ManyToManyField(
         'teleforma.IEJ', related_name='webclass', verbose_name=_('iej'), blank=True)
+    allow_elearning = models.BooleanField('Autoriser e-learning', default=True)
+    allow_presentiel = models.BooleanField('Autoriser présentiel', default=True)
     bbb_server = models.ForeignKey(
         'BBBServer', related_name='webclass', verbose_name='Serveur BBB', on_delete=models.CASCADE)
     duration = DurationField('Durée de la conférence', default="00:30:00")
     max_participants = models.IntegerField(
         'Nombre maxium de participants par créneau', blank=True, null=True, default=80)
     end_date = models.DateField('date de fin', blank=True, null=True)
+    session = models.CharField(_('session'), choices=session_choices,
+                               max_length=16, default="1")
     status = models.IntegerField(
         _('status'), choices=STATUS_CHOICES, default=2)
+    comment = ShortTextField(_('comment'), max_length=255, blank=True)
 
     objects = models.Manager()
-    published = PublishedManager()
+    published = WebclassPublishedManager()
 
     class Meta(MetaCore):
         db_table = app_label + '_' + 'webclass'
         verbose_name = _('webclass')
         verbose_name_plural = _('webclass')
+        indexes = [
+            models.Index(fields=['status', 'period', 'course', ]),
+         ]
 
     def __str__(self):
         return "Webclass %d : %s" % (self.id, self.course.title)
@@ -166,10 +175,18 @@ class Webclass(models.Model):
         except WebclassSlot.DoesNotExist:
             return None
 
+    def is_not_over(self):
+        """
+        Check if the webclass is not over yet
+        """
+        if self.end_date and self.end_date < datetime.date.today():
+            return False
+        return True
+        
 
 class SlotPublishedManager(models.Manager):
-    def get_query_set(self):
-        return super(SlotPublishedManager, self).get_query_set().filter(webclass__status=3).exclude(webclass__end_date__lt=date.today())
+    def get_queryset(self):
+        return super(SlotPublishedManager, self).get_queryset().filter(webclass__status=3).exclude(webclass__end_date__lt=date.today())
 
 
 class WebclassSlot(models.Model):
@@ -197,6 +214,21 @@ class WebclassSlot(models.Model):
     def __str__(self):
         return "Webclass slot : " + str(self.id)
 
+    @property
+    def date(self):
+        """
+        Compute the last date (from weekday) before the end of webclass.
+        This is the webclass date. Before, webclass were every "monday" for example.
+        Now there is only one date per webclass.
+        This is not ideal. We should have a "date" field on the webclass slot instead of "day". 
+        But we're waiting to see how PB use webclasses in the future.
+        """
+        end_day = self.webclass.end_date
+        next_day = end_day + datetime.timedelta(days=7 - end_day.weekday() + self.day, weeks=-1)
+        if next_day > end_day:
+            next_day = next_day - datetime.timedelta(weeks=1)
+        return next_day
+
     @property
     def remaining_participant_slot(self):
         """
@@ -272,7 +304,6 @@ class WebclassSlot(models.Model):
                     'slotid': self.id,
                     'professor': self.professor.user.username,
                 }
-                print(params)
                 try:
                     result = self.bbb.create_meeting(
                         self.room_id, params=params, meta=meta)
@@ -378,6 +409,19 @@ class WebclassRecord(models.Model):
         'BBBServer', related_name='webclass_records', verbose_name='Serveur BBB', on_delete=models.CASCADE)
     created = models.DateTimeField("Date de la conférence", auto_now_add=True)
 
+    WEBCLASS = 'WC'
+    CORRECTION = 'CC'
+    CATEGORY_CHOICES = [
+        (WEBCLASS, 'Webclass'),
+        (CORRECTION, 'Correction de copie'),
+    ]
+    category = models.CharField(
+        "Catégorie",
+        max_length=2,
+        choices=CATEGORY_CHOICES,
+        default=WEBCLASS,
+    )
+
     class Meta(MetaCore):
         db_table = app_label + '_' + 'webclass_record'
         verbose_name = 'enregistrement'
@@ -389,9 +433,21 @@ class WebclassRecord(models.Model):
     @staticmethod
     def get_records(period, course):
         record_ids = set()
+        # id : category mapping
+        category_mapping = {}
         for record in WebclassRecord.objects.filter(period=period, course=course):
             record_ids.add(record.record_id)
+            category_mapping[record.record_id] = record.category
         if not record_ids:
-            return []
+            return {}
         records = get_records_from_bbb(recording_id=','.join(record_ids))
-        return records
+
+        # group records by category
+        categories = {}
+        for record in records:
+            category = category_mapping[record['id']]
+            if category not in categories:
+                categories[category] = []
+            categories[category].append(record)
+
+        return categories
index 637b1c4b321d3bed8ccd3f07625a991698fb5628..7a5652c7002a30c995819572b162de14ef7c2815 100644 (file)
@@ -60,7 +60,7 @@
             <tr>
                 <th>Horaire</th>
                 <th>Professeur</th>
-                <th>Places restantes</th>
+                {% comment %} <th>Places restantes</th> {% endcomment %}
                 <th>Inscription</th>
             </tr>
         </thead>
         {% for slot in slots %}
             <tr>
                 <td>
-                <span class="booking_date"><strong>{{slot.get_day_display}}</strong> de <strong>{{slot.start_hour|date:"H\hi"}}</strong> à <strong>{{slot.end_hour|date:"H\hi"}}</strong></span>
+                <span class="booking_date">{{slot.get_day_display}} <strong>{{slot.date}}</strong> de <strong>{{slot.start_hour|date:"H\hi"}}</strong> à <strong>{{slot.end_hour|date:"H\hi"}}</strong></span>
                 </td>
                 <td>
                 {{slot.professor}}
                 </td>
-                <td>
+                {% comment %} <td>
                 {{slot.remaining_participant_slot}}
-                </td>
+                </td> {% endcomment %}
 
                 <td>
                     <form class="booking_form" method="POST">
-                        <span class="booking_date" style="display:none"><strong>{{slot.get_day_display}}</strong> de <strong>{{slot.start_hour|date:"H\hi"}}</strong> à <strong>{{slot.end_hour|date:"H\hi"}}</strong></span>
+                        <span class="booking_date" style="display:none">{{slot.get_day_display}} <strong>{{slot.date}}</strong> de <strong>{{slot.start_hour|date:"H\hi"}}</strong> à <strong>{{slot.end_hour|date:"H\hi"}}</strong></span>
                         {% csrf_token %}
                         <input type="hidden" name="slot_id" value="{{slot.id}}" />
                         {% if slot.participant_slot_available %}
index 58250e187174a41d90e3bc08607aa6feec863d8b..f48b3c78eab59c4aa40839b4c6e2efcda1cd6717 100644 (file)
@@ -15,44 +15,52 @@ Calendrier des Webclass
 {% block content %}
 <table class="webclass-appointment listing" width="100%">
     <thead>
-    <tr>
-        <th>Horaire</th>
-        <th>Période</th>
-        <th>Cours</th>
-        {% comment %} <th>IEJ</th> {% endcomment %}
-        <th>Participants</th>
-        <th>Salon</th>
-    </tr>
+        <tr>
+            <th>Horaire</th>
+            <th>Période</th>
+            <th>Cours</th>
+            {% comment %} <th>IEJ</th> {% endcomment %}
+            <th>Participants</th>
+            <th>Salon</th>
+            {% if is_superuser %}
+            <th>Professeur</th>
+            {% endif %}
+        </tr>
     </thead>
     <tbody>
-    {% for slot in slots %}
-    <tr>
-        <td>
-            <span><strong>{{slot.get_day_display}}</strong> de <strong>{{slot.start_hour|date:"H\hi"}}</strong> à <strong>{{slot.end_hour|date:"H\hi"}}</strong></span>
-        </td>
-        <td>
-        {{slot.webclass.period.name}}
-        </td>
-        <td>
-        {{slot.webclass.course.title}}
-        </td>
-        {% comment %} <td>
-        {% for iej in slot.webclass.iej.all %}
-        {{iej.name}}
+        {% for slot in slots %}
+        <tr>
+            <td>
+                <span>{{slot.get_day_display}} <strong>{{slot.date}}</strong> de <strong>{{slot.start_hour|date:"H\hi"}}</strong> à
+                    <strong>{{slot.end_hour|date:"H\hi"}}</strong></span>
+            </td>
+            <td>
+                {{slot.webclass.period.name}}
+            </td>
+            <td>
+                {{slot.webclass.course.title}}
+            </td>
+            {% comment %} <td>
+                {% for iej in slot.webclass.iej.all %}
+                {{iej.name}}
+                {% endfor %}
+            </td> {% endcomment %}
+            <td>
+                {{slot.participants.count}}
+            </td>
+            <td>
+                <a href="{% url 'teleforma-webclass-join' slot.id %}" target="_blank"
+                    class="conference-big-button component_icon button icon_next">Rejoindre la conférence</a>
+            </td>
+            {% if is_superuser %}
+            <td>{{slot.professor}}</td>
+            {% endif %}
+        </tr>
+        {% empty %}
+        <tr>
+            <td colspan="5">Aucune webclasse programmée.</td>
+        </tr>
         {% endfor %}
-        </td> {% endcomment %}
-        <td>
-         {{slot.participants.count}}
-        </td>
-        <td>
-            <a href="{% url 'teleforma-webclass-join' slot.id %}" target="_blank" class="conference-big-button component_icon button icon_next">Rejoindre la conférence</a>
-        </td>
-    </tr>
-    {% empty %}
-    <tr>
-    <td colspan="5">Aucune webclasse programmée.</td>
-    </tr>
-    {% endfor %}
     </tbody>
 </table>
-{% endblock content %}
+{% endblock content %}
\ No newline at end of file
diff --git a/teleforma/webclass/templates/webclass/inc/webclass_corrections_list.html b/teleforma/webclass/templates/webclass/inc/webclass_corrections_list.html
new file mode 100644 (file)
index 0000000..2007a7d
--- /dev/null
@@ -0,0 +1,19 @@
+{% load teleforma_tags webclass %}
+{% load i18n %}
+
+{% if webclass_corrections_records %}
+<div class="course_content content_video">
+    <table class="listing" width="100%">
+        <tbody>
+           
+            {% for record in webclass_corrections_records %}
+            {% webclass_record record %}
+            {% endfor %}
+        </tbody>
+    </table>
+</div>
+{% else %}
+<div class="course_content">
+    <p>Aucun document</p>
+</div>
+{% endif %}
\ No newline at end of file
index 962b878639943b44d9def2492d90ac93f702e936..b48d4c0f11ecb96241692f9d95dba8cd5c73a327 100644 (file)
@@ -1,4 +1,4 @@
-{% load teleforma_tags %}
+{% load teleforma_tags webclass %}
 {% load i18n %}
 
 {% if webclass_slot or webclass_records %}
             {% if webclass_slot %}
             <tr>
                 <td colspan="2">
-                    <p>Vous êtes inscrit pour les webclasses du
-                        <strong>{{webclass_slot.get_day_display}} de
+                    <p>Vous êtes inscrit pour la webclass du
+                        <strong>{{webclass_slot.get_day_display}} {{webclass_slot.date}} de
                             {{webclass_slot.start_hour|date:"H\hi"}} à
                             {{webclass_slot.end_hour|date:"H\hi"}}</strong>
-                        avec le professeur <strong>{{webclass_slot.professor.user.last_name}}</strong>.</p>
+                        avec le professeur <strong>{{webclass_slot.professor.user.last_name}}</strong>.
+                    </p>
+                    <p><a href="{% url 'teleforma-webclass-unregister' pk=webclass_slot.id %}" class="component_icon button icon_next">Se désinscrire</a> Vous pourrez ensuite vous inscrire sur un autre créneau.</p>
 
                     {% if webclass_slot.status == 'past' %}
                     <p>
             </tr>
             {% endif %}
             {% for record in webclass_records %}
-            <tr>
-                <td {% if forloop.first %}class="border-top" {% endif %} style="width:200px">
-                    <a href="{% url 'teleforma-webclass-record' %}?url={{record.url}}" title="{% trans "View" %}">
-                        <img src="{{ record.preview }}" style="width:176px" alt="{% trans 'Click here' %}" />
-                        <div>Cliquez-ici</div>
-                    </a>
-                </td>
-                <td {% if forloop.first %}class="border-top" {% endif %} style="padding-left: 1em;">
-                    <div>
-                        <dl class="listing" style="font-size: 1.2em;">
-                            {% if record.slot %}
-                                <dt>{% trans "Professor" %}</dt>
-                                <dd>{{ record.slot.professor }}</dd>
-                            {% endif %}
-                            <dt>{% trans "Begin" %}</dt>
-                            <dd>{{ record.start_date }}</dd>
-                        </dl>
-                    </div>
-                </td>
-                <div style="padding-left: 1em;">
-
-                </div>
-            </tr>
+            {% webclass_record record %}
             {% endfor %}
         </tbody>
     </table>
 </div>
+{% else %}
+<div class="course_content">
+    <p>Aucun document</p>
+</div>
 {% endif %}
\ No newline at end of file
diff --git a/teleforma/webclass/templates/webclass/webclass_record.html b/teleforma/webclass/templates/webclass/webclass_record.html
new file mode 100644 (file)
index 0000000..ae78052
--- /dev/null
@@ -0,0 +1,25 @@
+{% load i18n %}
+
+<tr>
+    <td {% if forloop.first %}class="border-top" {% endif %} style="width:200px">
+        <a href="{% url 'teleforma-webclass-record' %}?url={{record.url}}" title="{% trans "View" %}">
+            <img src="{{ record.preview }}" style="width:176px" alt="{% trans 'Click here' %}" />
+            <div>Cliquez-ici</div>
+        </a>
+    </td>
+    <td {% if forloop.first %}class="border-top" {% endif %} style="padding-left: 1em;">
+        <div>
+            <dl class="listing" style="font-size: 1.2em;">
+                {% if record.slot %}
+                <dt>{% trans "Professor" %}</dt>
+                <dd>{{ record.slot.professor }}</dd>
+                {% endif %}
+                <dt>{% trans "Begin" %}</dt>
+                <dd>{{ record.start_date }}</dd>
+            </dl>
+        </div>
+    </td>
+    <div style="padding-left: 1em;">
+
+    </div>
+</tr>
\ No newline at end of file
index fdc9c35e38cf720f87f09fbddec2ad88e301f6f8..7cc6b9cfd07b12da8c186c2b49bc203d1fade981 100644 (file)
@@ -37,7 +37,7 @@ from django.conf.urls import url
 from ..webclass.views import (WebclassAppointment,
                               WebclassProfessorAppointments,
                               WebclassRecordsFormView, WebclassRecordView,
-                              join_webclass)
+                              join_webclass, unregister)
 
 urlpatterns = [
     url(r'^desk/webclass_appointments/(?P<pk>.*)$', WebclassAppointment.as_view(),
@@ -48,7 +48,11 @@ urlpatterns = [
         name="teleforma-webclass-record"),
     url(r'^webclass/periods/(?P<period_id>.*)/webclass_records_form/$',
         WebclassRecordsFormView.as_view(), name="teleforma-webclass-records-form"),
+    url(r'^desk/webclass/(?P<pk>.*)/unregister/$',
+        unregister,
+        name="teleforma-webclass-unregister"),
     url(r'^desk/webclass/(?P<pk>.*)/join/$',
         join_webclass,
         name="teleforma-webclass-join")
+    
 ]
index 869461a49c1fe95aab90d65eb626f8f7d4fd504b..3cf8c1cc1bab13d6631f28a3a4482818a907cc76 100644 (file)
@@ -7,8 +7,7 @@ from django.shortcuts import get_object_or_404, redirect, render
 from django.urls import reverse
 from django.utils.decorators import method_decorator
 from django.views.generic import FormView, TemplateView, View
-
-from teleforma.models.core import Professor
+from datetime import datetime
 
 from ..decorators import access_required
 from ..views.core import get_courses, get_periods
@@ -19,24 +18,23 @@ from ..webclass.models import Webclass, WebclassSlot
 class WebclassProfessorAppointments(TemplateView):
     template_name = 'webclass/appointments_professor.html'
 
-    def dispatch(self, request, *args, **kwargs):
-        user = self.request.user
-        try:
-            user.professor.get()
-        except Professor.DoesNotExist:
-            return HttpResponse('Unauthorized', status=401)
-
-        return super().dispatch(request, *args, **kwargs)
-
-
     def get_context_data(self, **kwargs):
         """ """
         context = super(WebclassProfessorAppointments,
                         self).get_context_data(**kwargs)
-        
-        context['slots'] = WebclassSlot.published.filter(
-            professor=user.professor.get(), webclass__status=3).order_by('day', 'start_hour')
-        print(context['slots'])
+
+        user = self.request.user
+        if not user.professor.all() and not user.is_superuser:
+            return HttpResponse('Unauthorized', status=401)
+        today = datetime.today()
+        query = {
+            'webclass__status': 3,
+            'webclass__end_date__gte': today
+        }
+        if user.professor.all():
+            query['professor'] = user.professor.get()
+        context['slots'] = WebclassSlot.published.filter(**query).order_by('day', 'start_hour')
+        context['is_superuser'] = user.is_superuser
         return context
 
 
@@ -52,7 +50,7 @@ class WebclassAppointment(View):
         student = student[0]
         # check period
         period_id = webclass.period.id
-        periods = [p for p in get_periods(user) if int(p.id) == period_id]
+        periods = [p for p in get_periods(self.request) if int(p.id) == period_id]
         if not periods:
             return HttpResponse('Unauthorized', status=401)
         # check courses
@@ -64,14 +62,30 @@ class WebclassAppointment(View):
         # Student is in the right IEJ ?
         if not student.iej in webclass.iej.all():
             return HttpResponse('Unauthorized', status=401)
+        if student.platform_only and not webclass.allow_elearning:
+            return HttpResponse('Unauthorized', status=401)
+        if not student.platform_only and not webclass.allow_presentiel:
+            return HttpResponse('Unauthorized', status=401)
+            
         return
 
     def render(self, request, webclass):
         # Ensure user is logged in, a student, and has access to current period
         user = request.user
         student = user.student.all()[0]
-        
-        return render(request, self.template_name, {'slots': webclass.slots.order_by('day', 'start_hour'), 'webclass': webclass})
+        slots = webclass.slots.order_by('day', 'start_hour')
+        # only display unavaible slots or first slot of the day
+        filtered_slots = []
+        day = None
+        for slot in slots:
+            if slot.participant_slot_available:
+                if slot.day != day:
+                    filtered_slots.append(slot)
+                    day = slot.day
+            else:
+                filtered_slots.append(slot)
+
+        return render(request, self.template_name, {'slots': filtered_slots, 'webclass': webclass})
 
     def check_slot_validity(self, user, slot):
         """
@@ -143,6 +157,7 @@ class WebclassAppointment(View):
     #     return data
 
 
+
 class WebclassRecordView(TemplateView):
     template_name = 'webclass/record.html'
 
@@ -199,3 +214,20 @@ def join_webclass(request, pk):
         return redirect(webclass_slot.get_join_webclass_url(request, user))
     else:
         return HttpResponse('Unauthorized', status=401)
+
+
+@access_required
+def unregister(request, pk):
+    """
+    Unregister to a webclass
+    """
+    webclass_slot = WebclassSlot.objects.get(pk=int(pk))
+    user = request.user
+
+    if user in webclass_slot.participants.all():
+        webclass_slot.participants.remove(user)
+
+    messages.add_message(request, messages.INFO,
+                                 "Votre réservation a été annulé.")
+    # redirect to register form
+    return redirect(reverse("teleforma-webclass-appointments", kwargs={'pk':webclass_slot.webclass.id}))