]> git.parisson.com Git - teleforma.git/commitdiff
conference link with trainings
authorYoan Le Clanche <yoanl@pilotsystems.net>
Tue, 3 Jan 2023 13:08:15 +0000 (14:08 +0100)
committerYoan Le Clanche <yoanl@pilotsystems.net>
Tue, 3 Jan 2023 13:09:11 +0000 (14:09 +0100)
teleforma/admin.py
teleforma/migrations/0022_auto_20221222_1427.py [new file with mode: 0644]
teleforma/models/core.py
teleforma/templates/teleforma/inc/conference_list.html
teleforma/templates/teleforma/inc/media_list.html
teleforma/templatetags/teleforma_tags.py
teleforma/views/core.py

index ac2439a4033defd0e2bf2160f0915154592a215b..8961cc1768d44a2ba5faf6ef08475f854b26e2d9 100644 (file)
@@ -22,7 +22,7 @@ from collections import OrderedDict
 from .exam.admin import QuotaInline
 from .models.appointment import (Appointment, AppointmentJury,
                                  AppointmentPeriod, AppointmentSlot)
-from .models.core import (Conference, Course, CourseType, Department, Document,
+from .models.core import (Conference, ConferencePublication, Course, CourseType, Department, Document,
                           DocumentSimple, DocumentType, LiveStream, Media,
                           MediaTranscoded, Organization, Period, Professor,
                           Room, StreamingServer)
@@ -368,6 +368,8 @@ class MediaInline(admin.StackedInline):
     model = Media
     exclude = ['readers', ]
 
+class ConferenceInline(admin.StackedInline):
+    model = ConferencePublication
 
 @admin.action(description='Publish selected conferences')
 def publish_conferences(modeladmin, request, queryset):
@@ -393,8 +395,10 @@ def duplicate_conferences(modeladmin, request, queryset):
             media.save()
 
 
+
+
 class ConferenceAdmin(admin.ModelAdmin):
-    inlines = [MediaInline, ]
+    inlines = [MediaInline, ConferenceInline]
     exclude = ['readers']
     list_per_page = 30
     list_filter = ('course', 'period', 'date_begin', 'session', 'course_type')
diff --git a/teleforma/migrations/0022_auto_20221222_1427.py b/teleforma/migrations/0022_auto_20221222_1427.py
new file mode 100644 (file)
index 0000000..0499458
--- /dev/null
@@ -0,0 +1,25 @@
+# Generated by Django 3.2.13 on 2022-12-22 14:27
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('teleforma', '0021_auto_20221208_1214'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='ConferencePublication',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('date_publish', models.DateTimeField(blank=True, null=True, verbose_name='publishing date')),
+                ('status', models.IntegerField(choices=[(0, 'Hidden'), (1, 'Private'), (2, 'Draft'), (3, 'Public')], default=2, verbose_name='status')),
+                ('notified', models.BooleanField(default=False, verbose_name='notified')),
+                ('conference', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='publications', to='teleforma.conference', verbose_name='conference')),
+                ('trainings', models.ManyToManyField(related_name='conference_publications', to='teleforma.Training', verbose_name='trainings')),
+            ],
+        ),
+    ]
index acd643c0a2434024e91247c5c4a75c31d54fd5b4..3688e9da70af9ddfeb668b2a79721665e0f92df6 100755 (executable)
@@ -368,6 +368,15 @@ class Room(models.Model):
         verbose_name = _('room')
 
 
+class ConferencePublication(models.Model):
+    conference = models.ForeignKey('Conference', related_name='publications', verbose_name=_('conference'),
+                                    on_delete=models.CASCADE)
+    trainings = models.ManyToManyField('Training', related_name='conference_publications', verbose_name=_('trainings'))
+    date_publish = models.DateTimeField(_('publishing date'), null=True, blank=True)
+    status = models.IntegerField(
+        _('status'), choices=STATUS_CHOICES, default=2)
+    notified = models.BooleanField(_('notified'), default=False)
+
 class Conference(models.Model):
 
     public_id = models.CharField(_('public_id'), max_length=255, blank=True, unique=True)
@@ -418,10 +427,7 @@ class Conference(models.Model):
         return slug
 
     def __str__(self):
-        if self.date_publish:
-            date = self.date_publish
-        else:
-            date = self.date_begin
+        date = self.date_begin
 
         if self.professor:
             list = [self.course.title,
@@ -540,6 +546,20 @@ class Conference(models.Model):
                 self.web_class_group = WebClassGroup.objet.get(
                     name=data['web_class_group'])
 
+    def video(self):
+        """
+        get media video
+        """
+        try:
+            return self.media.get(type='mp4')
+        except Media.DoesNotExist:
+            try:
+                return self.media.get(type='webm')
+            except Media.DoesNotExist:
+                pass
+        return None
+        
+
     class Meta(MetaCore):
         db_table = app_label + '_' + 'conference'
         verbose_name = _('conference')
index 0d3ed8195aa02b2e4b524a0be4ed3f94e567ea81..75b39d4faf5fa114b64aeabd648ede6596e963e1 100644 (file)
@@ -1,7 +1,7 @@
 {% load teleforma_tags %}
 {% load i18n %}
 
-{% course_conferences as conference %}
+{% course_ingoing_conferences as conference %}
 
 {% if conferences %}
 <div class="course_content content_video">
index 852c241fbf9664442362e377d50633bf24134de5..3664b9221ffa9c68654789fad6cb37828c3072f5 100644 (file)
@@ -2,22 +2,22 @@
 {% load thumbnail %}
 {% load i18n %}
 
-{% course_media as all_media %}
+{% course_past_conferences as all_conferences %}
 
-{% if all_media %}
+{% if all_conferences %}
 <div class="course_content content_video">
 <div class="course_subtitle">
     <h3><img src="/static/teleforma/images/item_title.png" width="10px" alt="" /> {% trans "Conférences en différé" %}</h3>
 </div>
     <table class="listing" width="100%">
     <tbody>
-        {% for media in all_media %}
-          {% if media.type == 'webm' or media.type == 'mp4' %}
+        {% for conference in all_conferences %}
+          {% if conference.video %}
             <tr>
             <td {% if forloop.first %}class="border-top"{% endif %} width="230px" style="vertical-align:middle">
-            <a href="{% url 'teleforma-media-detail' period.id media.id %}" title="{% trans "Play" %}">
-            {% if media.poster_file %}
-               {% thumbnail media.poster_file "168x96" as im %}
+            <a href="{% url 'teleforma-media-detail' period.id conference.video.id %}" title="{% trans "Play" %}">
+            {% if conference.video.poster_file %}
+               {% thumbnail conference.video.poster_file "168x96" as im %}
                 <div style="background: no-repeat url('{{ im.url }}') 0 1px; background-size: 100%; background-color: #dfdfdf;">
                  <img src="/static/teleforma/images/play_168.png" width="100%" alt="{% trans 'Click here' %}" />
                 </div>
             <td {% if forloop.first %}class="border-top"{% endif %} width="60%" style="padding-left: 1em;">
                 <div>
                     <dl class="listing" style="font-size: 1.2em;">
-                    <dt>{% trans "Title" %}</dt><dd>{{ media.conference.course.title }}</dd>
-                    <dt>{% trans "Session" %}</dt><dd>{{ media.conference.session }}</dd>
-                    {% if media.conference.professor %}
-                    <dt>{% trans "Professor" %}</dt><dd>{{ media.conference.professor }}</dd>
+                    <dt>{% trans "Title" %}</dt><dd>{{ conference.course.title }}</dd>
+                    <dt>{% trans "Session" %}</dt><dd>{{ conference.session }}</dd>
+                    {% if conference.professor %}
+                    <dt>{% trans "Professor" %}</dt><dd>{{ conference.professor }}</dd>
                     {% endif %}
-                    {% if media.conference.date_publish %}
-                        <dt>{% trans "Publishing date" %}</dt><dd>{{ media.conference.date_publish }}</dd>
+                    {% if conference.date_publish %}
+                        <dt>{% trans "Publishing date" %}</dt><dd>{{ conference.date_publish }}</dd>
                     {% else %}
-                        <dt>{% trans "Begin date" %}</dt><dd>{{ media.conference.date_begin }}</dd>
+                        <dt>{% trans "Begin date" %}</dt><dd>{{ conference.date_begin }}</dd>
                     {% endif %}
-                    {% if media.conference.duration %}
-                        <dt>{% trans "Duration" %}</dt><dd>{{ media.conference.duration }}</dd>
+                    {% if conference.duration %}
+                        <dt>{% trans "Duration" %}</dt><dd>{{ conference.duration }}</dd>
                     {% endif %}
-                    {% if media.conference.comment %}
-                    <dt>{% trans "Comment" %}</dt><dd>{{ media.conference.comment }}</dd>
+                    {% if conference.comment %}
+                    <dt>{% trans "Comment" %}</dt><dd>{{ conference.comment }}</dd>
                     {% endif %}
                     </dl>
                  </div>
@@ -56,9 +56,9 @@
             {% elif not media.is_published and user.is_staff %}
              <img src="/static/teleforma/images/delete.png" style="vertical-align:middle" alt="" title="{% trans ' rejected' %}" />
             {% endif %}
-            {% if media.file and media.is_published or user.is_superuser or user.is_staff %}
-                {% if not "video" in media.mime_type or request.user_agent.os.family == 'iOS' %}
-                    <a href="{% url 'teleforma-media-download' period.id media.id %}">
+            {% if conference.video.file and conference.video.is_published or user.is_superuser or user.is_staff %}
+                {% if not "video" in conference.video.mime_type or request.user_agent.os.family == 'iOS' %}
+                    <a href="{% url 'teleforma-media-download' period.id conference.video.id %}">
                         <img src="/static/teleforma/images/download_media.png" style="vertical-align:middle" alt="" title="{% trans "Download" %}" />
                     </a>
                 {% endif %}
index 19ee2d96c6379911fdf76a06be40ab6f6c2fb197..bdbcf415c551ad42e89393e99f6c5e7ed4240cb5 100644 (file)
@@ -49,6 +49,8 @@ from django.utils.safestring import mark_safe
 from django.utils.translation import ugettext_lazy as _
 from docutils.core import publish_parts
 
+from teleforma.views.core import get_course_conferences
+
 from ..exam.models import Quota, Script
 from ..models.core import Document, Professor
 from ..models.crfpa import IEJ, Course, NewsItem, Training
@@ -463,7 +465,7 @@ def course_docs_by_type(context):
     return res
 
 @register.simple_tag(takes_context=True)
-def course_conferences(context):
+def course_ingoing_conferences(context):
     course = context['course']
     confs = course.conference.filter(streaming=True,
                                      period=context['period'],
@@ -471,10 +473,19 @@ def course_conferences(context):
     return list(confs)
 
 @register.simple_tag(takes_context=True)
-def course_media(context):
+def course_past_conferences(context):
+    user = context['user']
     course = context['course']
-    media = course.media.filter(period=context['period'],
-                                course_type=context['type'])
-    if not context['user'].is_staff or context.get('list_view', None):
-        media = media.filter(is_published = True)
-    return list(media)
+    period = context['period']
+    course_type = context['type']
+
+    return get_course_conferences(user, period, course, course_type)
+
+# @register.simple_tag(takes_context=True)
+# def course_media(context):
+#     course = context['course']
+#     media = course.media.filter(period=context['period'],
+#                                 course_type=context['type'])
+#     if not context['user'].is_staff or context.get('list_view', None):
+#         media = media.filter(is_published = True)
+#     return list(media)
index c3df2f7ab283b0eb6cdfbfcd49ab43a08ed7d211..38e07faf6976aa403fa4b0fa3387091e5cb21b58 100644 (file)
@@ -57,6 +57,9 @@ from django.views.generic.base import TemplateResponseMixin, TemplateView, View
 from django.views.generic.detail import DetailView
 from django.views.generic.list import ListView
 from django.core.cache import cache
+from django.db.models import Q
+from django.contrib.sites import Site
+
 
 from jsonrpc import jsonrpc_method
 from jsonrpc.proxy import ServiceProxy
@@ -67,14 +70,14 @@ from rest_framework.response import Response
 #
 # Authors: Guillaume Pellerin <yomguy@parisson.com>
 from rest_framework.views import APIView
-from teleforma.models.crfpa import Home
+from teleforma.models.crfpa import Home, Training
 from teleforma.models.notification import Notification
 from teleforma.utils import guess_mimetypes
 
 from ..decorators import access_required
 from ..models.appointment import Appointment, AppointmentPeriod
 from ..models.chat import ChatMessage
-from ..models.core import (Conference, Course, CourseType, Department,
+from ..models.core import (Conference, ConferencePublication, Course, CourseType, Department,
                            Document, DocumentType, Media, MediaTranscoded,
                            Organization, Period, Professor, WebClassGroup,
                            StreamingServer, LiveStream,
@@ -120,6 +123,42 @@ def get_courses(user, date_order=False, num_order=False, num_courses=False, peri
         return get_ae_courses(user, date_order, num_order, period)
 
 
+def get_trainings(user):
+    trainings = []
+
+    if not user.is_authenticated:
+        return trainings
+
+    professor = user.professor.all()
+    student = user.student.all()
+    quotas = user.quotas.all()
+
+    if professor or quotas or user.is_staff:
+        trainings = Training.objects.filter(available=True)
+
+    elif student:
+        student = user.student.get()
+        trainings = student.trainings.all()
+    return trainings
+
+
+def get_course_conferences(user, period, course, course_type):
+    trainings = get_trainings(user)
+    conferences = []
+    # get conference publications
+    publications = ConferencePublication.objects.filter(
+        trainings__in=trainings, status=3, conference__course=course, conference__course_type=course_type).distinct()
+    for publication in publications:
+        conferences.append(publication.conference)
+
+    for conference in Conference.objects.filter(period=period, status=3, course=course, course_type=course_type):
+        # do not include conferences with publication rules
+        if conference.publications.filter(trainings__in=trainings).count():
+            continue
+        conferences.append(conference)
+    return conferences
+
+
 def stream_from_file(__file):
     chunk_size = 0x10000
     f = open(__file, 'r')
@@ -175,7 +214,8 @@ def get_periods(request):
     elif students:
         period_ids = request.session.get('period_ids')
         if period_ids:
-            periods = [Period.objects.get(id=period_id) for period_id in period_ids]
+            periods = [Period.objects.get(id=period_id)
+                       for period_id in period_ids]
         else:
             student = user.student.get()
             periods = [training.period for training in student.trainings.all()]
@@ -272,8 +312,8 @@ def nginx_media_accel(media_path, content_type="", buffering=True, streaming=Fal
 def live_message(site, conference):
     token = settings.ADMIN_TOKEN
     requests.post('https://' + site.domain + '/chat/messages',
-        headers={'Authorization' : 'Token ' + token},
-        data={'conference_id': conference.id})
+                  headers={'Authorization': 'Token ' + token},
+                  data={'conference_id': conference.id})
 
 
 class HomeRedirectView(View):
@@ -356,14 +396,17 @@ class CourseListView(CourseAccessMixin, ListView):
 
         # get last published media / document
         last_published = []
-        last_media = Media.objects.filter(period=self.period, is_published=True, course__in=courses).order_by("-date_added").first()
+        last_media = Media.objects.filter(
+            period=self.period, is_published=True, course__in=courses).order_by("-date_added").first()
         if last_media:
             last_published.append(last_media)
-        last_document = Document.objects.filter(periods=self.period, is_published=True, course__in=courses).order_by("-date_added").first()
+        last_document = Document.objects.filter(
+            periods=self.period, is_published=True, course__in=courses).order_by("-date_added").first()
         if last_document:
             last_published.append(last_document)
         if last_published:
-            last_published = sorted(last_published, key=lambda k: k.date_added, reverse=True)[0]
+            last_published = sorted(
+                last_published, key=lambda k: k.date_added, reverse=True)[0]
             # get course with the latest published media / document
             for course in context['all_courses']:
                 if course['course'].id == last_published.course.id:
@@ -372,7 +415,7 @@ class CourseListView(CourseAccessMixin, ListView):
         else:
             # get course with the latest "date"
             context['courses'] = sorted(
-                 context['all_courses'], key=lambda k: k['date'], reverse=True)[:1]
+                context['all_courses'], key=lambda k: k['date'], reverse=True)[:1]
 
         user = self.request.user
         is_student = user.student.all().count()
@@ -412,9 +455,10 @@ class CourseListView(CourseAccessMixin, ListView):
             student = user.student.all()[0]
             slots = []
             to_subscribe = []
+            student_trainings = get_trainings(user)
             student_courses = [course['course']
                                for course in get_courses(user)]
-            for webclass in Webclass.published.filter(period=self.period, iej=student.iej, course__in=student_courses):
+            for webclass in Webclass.published.filter(trainings__in=student_trainings, iej=student.iej, course__in=student_courses):
                 # if webclass.course not in student_courses:
                 #     continue
                 if student.platform_only and not webclass.allow_elearning:
@@ -513,10 +557,11 @@ class CourseView(CourseAccessMixin, DetailView):
         if student:
             student = student[0]
 
+        trainings = get_trainings(self.request.user)
         if student:
             try:
                 webclass = Webclass.published.filter(
-                    period=self.period, course=course, iej=student.iej)[0]
+                    trainings__in=trainings, course=course, iej=student.iej)[0]
             except IndexError:
                 pass
             if webclass:
@@ -532,12 +577,13 @@ class CourseView(CourseAccessMixin, DetailView):
 
         records = {}
         try:
-            records = WebclassRecord.get_records(context['period'], course)
+            records = WebclassRecord.get_records(trainings, course)
         except Exception as e:
             print(e)
             context['webclass_error'] = True
         context['webclass_records'] = records.get(WebclassRecord.WEBCLASS)
-        context['webclass_corrections_records'] = records.get(WebclassRecord.CORRECTION)
+        context['webclass_corrections_records'] = records.get(
+            WebclassRecord.CORRECTION)
         return context
 
     @method_decorator(access_required)
@@ -794,7 +840,6 @@ class ConferenceView(CourseAccessMixin, DetailView):
             except:
                 pass
 
-
     @jsonrpc_method('teleforma.create_conference')
     def create(request, conf_dict):
         if isinstance(conf_dict, dict):
@@ -805,23 +850,29 @@ class ConferenceView(CourseAccessMixin, DetailView):
                 conference.save()
                 if conference.streaming:
                     for stream in conf_dict['streams']:
-                        host = getattr(settings, "TELECASTER_LIVE_STREAMING_SERVER", stream['host'])
-                        protocol = getattr(settings, "TELECASTER_LIVE_STREAMING_PROTOCOL", 'http')
+                        host = getattr(
+                            settings, "TELECASTER_LIVE_STREAMING_SERVER", stream['host'])
+                        protocol = getattr(
+                            settings, "TELECASTER_LIVE_STREAMING_PROTOCOL", 'http')
                         server_type = stream['server_type']
                         stream_type = stream['stream_type']
                         if server_type == 'icecast':
-                            port = getattr(settings, "TELECASTER_LIVE_ICECAST_STREAMING_PORT", '8000')
-                            path = getattr(settings, "TELECASTER_LIVE_ICECAST_STREAMING_PATH", '/')
+                            port = getattr(
+                                settings, "TELECASTER_LIVE_ICECAST_STREAMING_PORT", '8000')
+                            path = getattr(
+                                settings, "TELECASTER_LIVE_ICECAST_STREAMING_PATH", '/')
                         elif server_type == 'stream-m':
-                            port = getattr(settings, "TELECASTER_LIVE_STREAM_M_STREAMING_PORT", '8080')
-                            path = getattr(settings, "TELECASTER_LIVE_STREAM_M_STREAMING_PATH", '/')
+                            port = getattr(
+                                settings, "TELECASTER_LIVE_STREAM_M_STREAMING_PORT", '8080')
+                            path = getattr(
+                                settings, "TELECASTER_LIVE_STREAM_M_STREAMING_PATH", '/')
                         #site = Site.objects.all()[0]
                         server, c = StreamingServer.objects.get_or_create(
-                                        protocol=protocol,
-                                        host=host,
-                                        port=port,
-                                        path=path,
-                                        type=server_type)
+                            protocol=protocol,
+                            host=host,
+                            port=port,
+                            path=path,
+                            type=server_type)
                         stream = LiveStream(conference=conference, server=server,
                                             stream_type=stream_type, streaming=True)
                         stream.save()
@@ -898,12 +949,14 @@ class ChatMessageView(APIView):
         room_name = request.POST.get('room_name')
         message = request.POST.get('message')
         if not room_name:
-            conference = Conference.objects.get(id=request.POST.get('conference_id'))
+            conference = Conference.objects.get(
+                id=request.POST.get('conference_id'))
             ChatMessage.live_conference_message(conference=conference)
         else:
             ChatMessage.add_message(room_name, message, system=True)
         return Response({'status': 'ok'})
 
+
 class NotificationView(APIView):
     permission_classes = [IsAuthenticated]
 
@@ -1201,3 +1254,5 @@ class PDFTemplateResponseMixin(TemplateResponseMixin):
         context[self.pdf_url_varname] = self.get_pdf_url()
         return super(PDFTemplateResponseMixin, self).render_to_response(
             context, **response_kwargs)
+
+