]> git.parisson.com Git - teleforma.git/commitdiff
Professor can now add webclass from the UI :
authorYoan Le Clanche <yoanl@pilotsystems.net>
Mon, 28 Apr 2025 12:10:22 +0000 (14:10 +0200)
committerYoan Le Clanche <yoanl@pilotsystems.net>
Mon, 28 Apr 2025 12:10:22 +0000 (14:10 +0200)
teleforma/management/commands/teleforma-webclass-create-conferencerecords.py [new file with mode: 0644]
teleforma/static/teleforma/css/teleforma.css
teleforma/templates/teleforma/course_detail.html
teleforma/webclass/migrations/0010_auto_20250424_1640.py [new file with mode: 0644]
teleforma/webclass/migrations/0011_webclassrecord_professor.py [new file with mode: 0644]
teleforma/webclass/models.py
teleforma/webclass/templates/webclass/webclass_record.html
teleforma/webclass/urls.py
teleforma/webclass/views.py

diff --git a/teleforma/management/commands/teleforma-webclass-create-conferencerecords.py b/teleforma/management/commands/teleforma-webclass-create-conferencerecords.py
new file mode 100644 (file)
index 0000000..81b0aa9
--- /dev/null
@@ -0,0 +1,31 @@
+# -*- coding: utf-8 -*-
+
+from optparse import make_option
+from django.conf import settings
+from django.core.management.base import BaseCommand, CommandError
+from django.contrib.auth.models import User
+from ...models.core import Conference
+from teleforma.webclass.models import *
+
+
+
+class Command(BaseCommand):
+    help = "Store record id for conferences"
+
+    def handle(self, *args, **options):
+        bbb = BBBServer.objects.get(pk=2).get_instance()
+
+        missing_records = WebclassRecord.objects.filter(record_id__isnull=True, room_id__isnull=False)
+
+        for record in missing_records:
+            recordings = bbb.get_recordings(record.room_id).get_field('recordings')
+            if hasattr(recordings, 'get'):
+                recordings = recordings['recording']
+            if type(recordings) is XMLDictNode:
+                recordings = [recordings]
+            if recordings:
+                # get last session id from the same course
+                record.record_id = recordings[0]['recordID']
+
+                print("Add record id %s for webclass record %s" % (record.record_id, record.id))
+                record.save()
\ No newline at end of file
index 0efb41c8879b014cefe11f03aa937a76d332b0b7..09be859678f85172af79eea895f53204b77e04ed 100644 (file)
@@ -1728,8 +1728,18 @@ form.add_actus #id_text_parent{
     padding: 0em;
     font-weight: bold;
     font-size: 1.2em;
-    }
-
+    display: flex;
+    flex-direction: row;
+    justify-content: space-between;
+}
+.create-bbb-conference {
+    font-size: 0.8em;
+}
+.bbb-placeholder {
+    width: 100%;
+    height: 116px;
+    background-color: #dfdfdf;
+}
 .course_content {
     background-color: #FFF;
     -moz-border-radius: 8px 0px 8px 8px;
index 44793c31663670623a87746d36ccc62cbd36973f..adf3548bf614fcf3f18a22730eef32207cefce01 100644 (file)
@@ -82,6 +82,8 @@
   <div class="course">
     <div class="course_title">{{ course.title }} - Corrections de copies{% if course.description %} -
       {{ course.description }}{% endif %}
+      {% if user.is_staff or user.professor.count %}<a href="{% url 'teleforma-create-cc-bbb-conference' period.id course.id %}" class="create-bbb-conference">Créer une correction de copie</a>{% endif %}
+
     </div>
     {% block webclass_corrections %}
     {% include "webclass/inc/webclass_corrections_list.html" %}
diff --git a/teleforma/webclass/migrations/0010_auto_20250424_1640.py b/teleforma/webclass/migrations/0010_auto_20250424_1640.py
new file mode 100644 (file)
index 0000000..966161e
--- /dev/null
@@ -0,0 +1,23 @@
+# Generated by Django 3.2.25 on 2025-04-24 16:40
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('webclass', '0009_auto_20250214_1201'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='webclassrecord',
+            name='room_id',
+            field=models.CharField(blank=True, max_length=255, null=True, unique=True, verbose_name='id de la conférence BBB (généré automatiquement)'),
+        ),
+        migrations.AlterField(
+            model_name='webclassrecord',
+            name='record_id',
+            field=models.CharField(blank=True, max_length=255, null=True, verbose_name='Enregistrement BBB'),
+        ),
+    ]
diff --git a/teleforma/webclass/migrations/0011_webclassrecord_professor.py b/teleforma/webclass/migrations/0011_webclassrecord_professor.py
new file mode 100644 (file)
index 0000000..10abc9d
--- /dev/null
@@ -0,0 +1,20 @@
+# Generated by Django 3.2.25 on 2025-04-24 16:46
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('teleforma', '0029_merge_0028_auto_20240318_1139_0028_auto_20240415_0414'),
+        ('webclass', '0010_auto_20250424_1640'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='webclassrecord',
+            name='professor',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='webclass_records', to='teleforma.professor', verbose_name='professor'),
+        ),
+    ]
index 0ff52a606138983ee7ddf5bab33ededa48af9129..2b8341127b6dc43b859c2dd7825244ee0671236c 100644 (file)
@@ -429,13 +429,19 @@ class WebclassRecord(models.Model):
     period = models.ForeignKey('teleforma.Period', verbose_name=_('period'), on_delete=models.CASCADE)
     course = models.ForeignKey(
         'teleforma.Course', related_name='webclass_records', verbose_name=_('course'), on_delete=models.CASCADE)
-    record_id = models.CharField("Enregistrement BBB", max_length=255)
+    record_id = models.CharField("Enregistrement BBB", max_length=255, blank=True, null=True)
     # not used for now, but may be handy if we need to optimize performance
     bbb_server = models.ForeignKey(
         '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)
     session = models.CharField(
         _('session'), choices=session_choices, max_length=16, blank=True, null=True)
+    
+    # Used when conference are created from webclass by teachers to retrive the record id
+    room_id = models.CharField(
+        'id de la conférence BBB (généré automatiquement)', blank=True, null=True, max_length=255, unique=True)
+    professor = models.ForeignKey('teleforma.Professor', related_name='webclass_records', verbose_name=_('professor'), on_delete=models.SET_NULL, blank=True, null=True)
+    
 
     WEBCLASS = 'WC'
     CORRECTION = 'CC'
index 3e6f839be12c853b1640707c0d3e35682d9c6beb..5f40c5562a09259b5b8167e9ed3b54d30be8ac14 100644 (file)
@@ -3,8 +3,11 @@
 <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>
+            {% if record.preview %}
+                <img src="{{ record.preview }}" style="width:176px" alt="{% trans 'Click here' %}" />
+            {% else %}
+                <img src="/static/teleforma/images/play_168.png" class="bbb-placeholder" alt="{% trans 'Click here' %}" />
+            {% endif %}
         </a>
     </td>
     <td {% if forloop.first %}class="border-top" {% endif %} style="padding-left: 1em;">
index 7cc6b9cfd07b12da8c186c2b49bc203d1fade981..f9c8eaf96831382628479414517684d4d88de116 100644 (file)
@@ -36,7 +36,7 @@ from django.conf.urls import url
 
 from ..webclass.views import (WebclassAppointment,
                               WebclassProfessorAppointments,
-                              WebclassRecordsFormView, WebclassRecordView,
+                              WebclassRecordsFormView, WebclassRecordView, create_cc_bbb_conference,
                               join_webclass, unregister)
 
 urlpatterns = [
@@ -53,6 +53,8 @@ urlpatterns = [
         name="teleforma-webclass-unregister"),
     url(r'^desk/webclass/(?P<pk>.*)/join/$',
         join_webclass,
-        name="teleforma-webclass-join")
-    
+        name="teleforma-webclass-join"),
+    url(r'^desk/webclass/(?P<period_id>.*)/(?P<course_id>.*)/create_cc_bbb_conference/$',
+        create_cc_bbb_conference,
+        name="teleforma-create-cc-bbb-conference")
 ]
index 3cf8c1cc1bab13d6631f28a3a4482818a907cc76..6d2738b1f3ed2bbe75b705587225761816cbd4ff 100644 (file)
@@ -7,12 +7,19 @@ 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 bigbluebutton_api_python.exception import BBBException
+
 from datetime import datetime
+import string
+import random
+
+from ..models.core import Conference, Course, Professor
 
 from ..decorators import access_required
 from ..views.core import get_courses, get_periods
 from ..webclass.forms import WebclassRecordsForm
-from ..webclass.models import Webclass, WebclassSlot
+from ..webclass.models import BBBServer, Webclass, WebclassRecord, WebclassSlot
+from django.contrib.auth.models import User
 
 
 class WebclassProfessorAppointments(TemplateView):
@@ -231,3 +238,81 @@ def unregister(request, pk):
                                  "Votre réservation a été annulé.")
     # redirect to register form
     return redirect(reverse("teleforma-webclass-appointments", kwargs={'pk':webclass_slot.webclass.id}))
+
+
+
+@access_required
+def create_cc_bbb_conference(request, period_id, course_id):
+    """
+    Join a bbb webclass for "correction de copie" (cc) with a random room id. 
+    A cron script will later create a WebclassRecord object.
+    """
+
+    username = request.user.get_full_name()
+    is_professor = len(request.user.professor.all()) >= 1
+    is_staff = request.user.is_staff or request.user.is_superuser
+
+    if not is_professor and not is_staff:
+        raise ValueError("User is not a professor or staff")
+    course = Course.objects.get(pk=course_id)
+
+    year = datetime.now().year
+    bbb = BBBServer.objects.get(pk=2).get_instance()
+    # generate password
+    password = User.objects.make_random_password()
+    # generate random room id
+    room_id = "".join(random.choices(string.ascii_letters + string.digits, k=20))
+
+    params = {
+        'name': "Conférence %s" % course.title,
+        'moderatorPW': password,
+        'attendeePW': "PWATTENDEE",
+        # 'maxParticipants':self.webclass_max_participants + 1,
+        'welcome': "Pré-Barreau : Bienvenue sur la conférence \"%s\"." % (course.title),
+        'record': True,
+        'autoStartRecording':True,
+        'muteOnStart': True,
+        'allowModsToUnmuteUsers': True,
+        'logo':'https://e-learning.crfpa.pre-barreau.com/static/teleforma/images/logo_pb.png',
+        'copyright': "© %d Pré-Barreau" % year,
+        # 'guestPolicy':'ALWAYS_ACCEPT'
+        'bannerText': "Pré-Barreau - CRFPA",
+        'bannerColor': "#003768",
+        # 'customStyleUrl': site_url+"/static/teleforma/css/bbb.css"
+        'logoutURL': "https://e-learning.ae.pre-barreau.com",
+        'endWhenNoModerator': True,
+        'meetingLayout': "VIDEO_FOCUS",
+        "notifyRecordingIsOn": True,
+    }
+
+    meta = {
+        'origin': 'crfpa',
+        'periodid': period_id,
+        'courseid': course_id,
+        'professorid': request.user.id,
+        'type': 'cc',
+    }
+
+    try:
+        result = bbb.create_meeting(
+            room_id, params=params, meta=meta)
+    except BBBException as e:
+        print(e)
+        raise
+
+    try:
+        professor = request.user.professor.get()
+    except Professor.DoesNotExist:
+        professor = None
+
+    WebclassRecord.objects.create(
+        room_id=room_id,
+        bbb_server=BBBServer.objects.get(pk=2),
+        period_id=period_id,
+        course_id=course_id,
+        category=WebclassRecord.CORRECTION,
+        professor=professor,
+    )
+
+    params = {'userID': request.user.username}
+    return redirect(bbb.get_join_meeting_url(username, room_id, password, params))