From 0efbbe953d760c0a0be9cb61996733380c65a3a2 Mon Sep 17 00:00:00 2001 From: Yoan Le Clanche Date: Tue, 3 Jan 2023 14:08:15 +0100 Subject: [PATCH] conference link with trainings --- teleforma/admin.py | 8 +- .../migrations/0022_auto_20221222_1427.py | 25 ++++ teleforma/models/core.py | 28 ++++- .../teleforma/inc/conference_list.html | 2 +- .../templates/teleforma/inc/media_list.html | 42 +++---- teleforma/templatetags/teleforma_tags.py | 25 ++-- teleforma/views/core.py | 107 +++++++++++++----- 7 files changed, 176 insertions(+), 61 deletions(-) create mode 100644 teleforma/migrations/0022_auto_20221222_1427.py diff --git a/teleforma/admin.py b/teleforma/admin.py index ac2439a4..8961cc17 100644 --- a/teleforma/admin.py +++ b/teleforma/admin.py @@ -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 index 00000000..04994580 --- /dev/null +++ b/teleforma/migrations/0022_auto_20221222_1427.py @@ -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')), + ], + ), + ] diff --git a/teleforma/models/core.py b/teleforma/models/core.py index acd643c0..3688e9da 100755 --- a/teleforma/models/core.py +++ b/teleforma/models/core.py @@ -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') diff --git a/teleforma/templates/teleforma/inc/conference_list.html b/teleforma/templates/teleforma/inc/conference_list.html index 0d3ed819..75b39d4f 100644 --- a/teleforma/templates/teleforma/inc/conference_list.html +++ b/teleforma/templates/teleforma/inc/conference_list.html @@ -1,7 +1,7 @@ {% load teleforma_tags %} {% load i18n %} -{% course_conferences as conference %} +{% course_ingoing_conferences as conference %} {% if conferences %}
diff --git a/teleforma/templates/teleforma/inc/media_list.html b/teleforma/templates/teleforma/inc/media_list.html index 852c241f..3664b922 100644 --- a/teleforma/templates/teleforma/inc/media_list.html +++ b/teleforma/templates/teleforma/inc/media_list.html @@ -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 %}

{% trans "Conférences en différé" %}

- {% for media in all_media %} - {% if media.type == 'webm' or media.type == 'mp4' %} + {% for conference in all_conferences %} + {% if conference.video %}
- - {% if media.poster_file %} - {% thumbnail media.poster_file "168x96" as im %} + + {% if conference.video.poster_file %} + {% thumbnail conference.video.poster_file "168x96" as im %}
{% trans 'Click here' %}
@@ -31,21 +31,21 @@
-
{% trans "Title" %}
{{ media.conference.course.title }}
-
{% trans "Session" %}
{{ media.conference.session }}
- {% if media.conference.professor %} -
{% trans "Professor" %}
{{ media.conference.professor }}
+
{% trans "Title" %}
{{ conference.course.title }}
+
{% trans "Session" %}
{{ conference.session }}
+ {% if conference.professor %} +
{% trans "Professor" %}
{{ conference.professor }}
{% endif %} - {% if media.conference.date_publish %} -
{% trans "Publishing date" %}
{{ media.conference.date_publish }}
+ {% if conference.date_publish %} +
{% trans "Publishing date" %}
{{ conference.date_publish }}
{% else %} -
{% trans "Begin date" %}
{{ media.conference.date_begin }}
+
{% trans "Begin date" %}
{{ conference.date_begin }}
{% endif %} - {% if media.conference.duration %} -
{% trans "Duration" %}
{{ media.conference.duration }}
+ {% if conference.duration %} +
{% trans "Duration" %}
{{ conference.duration }}
{% endif %} - {% if media.conference.comment %} -
{% trans "Comment" %}
{{ media.conference.comment }}
+ {% if conference.comment %} +
{% trans "Comment" %}
{{ conference.comment }}
{% endif %}
@@ -56,9 +56,9 @@ {% elif not media.is_published and user.is_staff %} {% 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' %} - + {% 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' %} + {% endif %} diff --git a/teleforma/templatetags/teleforma_tags.py b/teleforma/templatetags/teleforma_tags.py index 19ee2d96..bdbcf415 100644 --- a/teleforma/templatetags/teleforma_tags.py +++ b/teleforma/templatetags/teleforma_tags.py @@ -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) diff --git a/teleforma/views/core.py b/teleforma/views/core.py index c3df2f7a..38e07faf 100644 --- a/teleforma/views/core.py +++ b/teleforma/views/core.py @@ -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 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) + + -- 2.39.5