From fc925fa54393110ab270e9af2d35526e08c92625 Mon Sep 17 00:00:00 2001 From: Yoan Le Clanche Date: Tue, 2 May 2023 12:09:48 +0200 Subject: [PATCH] Django 3 migration --- app/settings.py | 42 ++++++--- app/urls.py | 1 + etc/apache2-dev.conf | 3 - requirements-dev.txt | 2 +- requirements.txt | 21 ++++- teleforma/admin.py | 43 +++++---- .../0001_initial.py | 0 ...02_auto__chg_field_script_reject_reason.py | 0 ..._script_file__chg_field_scriptpage_file.py | 0 .../0004_auto__add_field_quota_script_type.py | 0 ...chg_field_quota_course__chg_field_quota.py | 0 ...me_type__chg_field_scriptpage_mime_type.py | 0 .../__init__.py | 0 teleforma/forms.py | 31 ++++--- .../teleforma-convert-boolean-fields.py | 18 ++++ teleforma/migrations/0001_initial.py | 91 ++++--------------- teleforma/models/__init__.py | 1 - teleforma/models/ae.py | 65 ------------- teleforma/models/core.py | 19 ++-- teleforma/models/crfpa.py | 34 +++---- teleforma/models/pro.py | 2 +- teleforma/templates/postman/base_write.html | 2 +- .../registration/registration_complete.html | 2 +- teleforma/templates/teleforma/annals.html | 8 +- .../templates/teleforma/appointments.html | 2 +- .../teleforma/course_conference.html | 8 +- .../teleforma/course_conference_audio.html | 4 +- .../templates/teleforma/course_detail.html | 2 +- .../templates/teleforma/course_document.html | 2 +- .../templates/teleforma/course_media.html | 9 +- .../teleforma/course_media_transcoded.html | 1 - .../teleforma/course_media_video_embed.html | 2 +- teleforma/templates/teleforma/courses.html | 10 +- .../templates/teleforma/courses_pending.html | 2 +- .../teleforma/inc/conference_list.html | 4 +- .../teleforma/inc/document_list.html | 4 +- .../templates/teleforma/inc/media_list.html | 2 +- .../templates/teleforma/inc/newsitem.html | 4 +- .../teleforma/inc/newsitems_portlet.html | 4 +- .../templates/teleforma/inc/user_list.html | 4 +- .../templates/teleforma/newsitem_list.html | 4 +- .../templates/teleforma/profile_detail.html | 2 +- .../templates/teleforma/search_criteria.html | 4 +- teleforma/templates/teleforma/users.html | 8 +- teleforma/templates/telemeta/base.html | 4 +- teleforma/templatetags/teleforma_tags.py | 4 +- teleforma/urls.py | 7 -- teleforma/views/core.py | 66 ++++++-------- teleforma/webclass/migrations/0001_initial.py | 2 +- 49 files changed, 229 insertions(+), 321 deletions(-) rename teleforma/exam/{migrations => south_migrations}/0001_initial.py (100%) rename teleforma/exam/{migrations => south_migrations}/0002_auto__chg_field_script_reject_reason.py (100%) rename teleforma/exam/{migrations => south_migrations}/0003_auto__chg_field_script_file__chg_field_scriptpage_file.py (100%) rename teleforma/exam/{migrations => south_migrations}/0004_auto__add_field_quota_script_type.py (100%) rename teleforma/exam/{migrations => south_migrations}/0005_auto__add_field_quota_session__chg_field_quota_course__chg_field_quota.py (100%) rename teleforma/exam/{migrations => south_migrations}/0006_auto__chg_field_script_mime_type__chg_field_scriptpage_mime_type.py (100%) rename teleforma/exam/{migrations => south_migrations}/__init__.py (100%) create mode 100644 teleforma/management/commands/teleforma-convert-boolean-fields.py delete mode 100644 teleforma/models/ae.py diff --git a/app/settings.py b/app/settings.py index 76100369..72c1387e 100644 --- a/app/settings.py +++ b/app/settings.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # Django settings for sandbox project. -from django.utils.encoding import force_text +from django.utils.encoding import force_str import warnings import os import sys @@ -30,12 +30,18 @@ MANAGERS = ADMINS DATABASES = { 'default': { - 'ENGINE': 'django.db.backends.mysql', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'. - 'NAME': 'teleforma', # Or path to database file if using sqlite3. - 'USER': 'teleforma', # Not used with sqlite3. - 'PASSWORD': 'HMYsrZLEtYeBrvER', # Not used with sqlite3. - 'HOST': '', # Set to empty string for localhost. Not used with sqlite3. - 'PORT': '', # Set to empty string for default. Not used with sqlite3. + # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'. + 'ENGINE': 'django.db.backends.postgresql_psycopg2', + # Or path to database file if using sqlite3. + 'NAME': os.environ.get('POSTGRES_DATABASE'), + # Not used with sqlite3. + 'USER': os.environ.get('POSTGRES_USER'), + # Not used with sqlite3. + 'PASSWORD': os.environ.get('POSTGRES_PASSWORD'), + # Set to empty string for localhost. Not used with sqlite3. + 'HOST': os.environ.get('DB_HOST'), + # Set to empty string for default. Not used with sqlite3. + 'PORT': os.environ.get('DB_PORT'), } } @@ -140,6 +146,8 @@ INSTALLED_APPS = ( 'django.contrib.admin', # 'south', 'teleforma', + 'teleforma.exam', + 'teleforma.webclass', 'sorl.thumbnail', # 'django_extensions', 'dj_pagination', @@ -241,17 +249,25 @@ TELECASTER_LIVE_ICECAST_STREAMING_PORT = 8000 TELECASTER_LIVE_STREAM_M_STREAMING_PORT = 8888 # CRFPA or AE or PRO -TELEFORMA_E_LEARNING_TYPE = 'CRFPA' +TELEFORMA_E_LEARNING_TYPE = 'AE' +TELEFORMA_ORGANIZATION = 'Pré-Barreau - Avocats étrangers' +TELEFORMA_SUBJECTS = ('Barreau', 'Avocats', 'étrangers', 'e-learning') +TELEFORMA_DESCRIPTION = "E-learning Pré-Barreau - Avocats étrangers" TELEFORMA_GLOBAL_TWEETER = False TELEFORMA_PERIOD_TWEETER = True TELEFORMA_EXAM_TOPIC_DEFAULT_DOC_TYPE_ID = 4 TELEFORMA_EXAM_SCRIPT_UPLOAD = True TELEFORMA_REGISTER_DEFAULT_DOC_ID = 5506 -TELEFORMA_PERIOD_DEFAULT_ID = 22 -TELEFORMA_EXAM_MAX_SESSIONS = 15 +TELEFORMA_PERIOD_DEFAULT_ID = 11 +TELEFORMA_EXAM_MAX_SESSIONS = 10 TELEFORMA_EXAM_SCRIPT_MAX_SIZE = 20480000 TELEFORMA_EXAM_SCRIPT_SERVICE_URL = '/webviewer/teleforma.html' +# courses choice in register form +TELEFORMA_REGISTER_COURSE_CHOICE = (28, 29, 30, 31) +# courses added to all registered users +TELEFORMA_REGISTER_COURSE_AUTOREGISTER = (27, 34, 35, 36, 37) + TELECASTER_LIVE_STREAMING_SERVER = 'stream4.parisson.com' TELECASTER_LIVE_STREAMING_PORT = 443 TELECASTER_LIVE_ICECAST_STREAMING_PORT = 8000 @@ -269,6 +285,10 @@ FILE_UPLOAD_TEMP_DIR = '/tmp' SESSION_ENGINE = "unique_session.backends.session_backend" UNIQUE_SESSION_WHITELIST = (1, 2042) +RECAPTCHA_PUBLIC_KEY = '6Ldq5DgbAAAAADkKg19JXlhx6F1XUQDsrXfXqSP6' +RECAPTCHA_PRIVATE_KEY = '6Ldq5DgbAAAAAOVDOeF2kH8i2e2VSNHpqlinbpAJ' +RECAPTCHA_REQUIRED_SCORE = 0.85 + # SOUTH_MIGRATION_MODULES = { # 'captcha': 'captcha.south_migrations', # } @@ -345,7 +365,7 @@ def show_user_as(user): if user.quotas.count() and not professor and not user.is_superuser: return "#"+str(user.id) else: - return force_text(user) + return force_str(user) POSTMAN_SHOW_USER_AS = show_user_as diff --git a/app/urls.py b/app/urls.py index 355c941c..84b68022 100644 --- a/app/urls.py +++ b/app/urls.py @@ -1,4 +1,5 @@ # -*- coding: utf-8 -*- +from django.conf import settings from django.http import HttpResponse from django.conf.urls import include, url from django.views.i18n import JavaScriptCatalog diff --git a/etc/apache2-dev.conf b/etc/apache2-dev.conf index 87917d8d..d47c932d 100644 --- a/etc/apache2-dev.conf +++ b/etc/apache2-dev.conf @@ -551,8 +551,5 @@ SSLRandomSeed connect builtin RewriteEngine on ProxyPreserveHost on - RewriteCond %{HTTP:Connection} Upgrade [NC] - RewriteCond %{HTTP:Upgrade} websocket [NC] - RewriteRule ^/(.*)$ ws://channels:8000/$1 [P,L] RewriteRule ^(.*)$ http://app:8000$1 [P,L] diff --git a/requirements-dev.txt b/requirements-dev.txt index d1cc50e1..3a22361c 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,2 +1,2 @@ ipdb==0.13.8 -django-debug-toolbar \ No newline at end of file +django-debug-toolbar==3.8.1 \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index da76a6c2..e802cc87 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,9 @@ bigbluebutton-api-python==0.0.11 +channels==3.0.4 +channels_redis==3.4.0 docutils==0.17.1 -Django==3.2.3 +Django==3.2.13 +djangorestframework==3.13.1 # django-extensions==1.2.1 # django-timezones==0.2 # django-registration==3.1.2 @@ -10,17 +13,27 @@ django-json-rpc==0.7.1 # django-google-tools==1.1.0 django-nvd3==0.8.2 django-postman==4.2 -django-simple-captcha==0.5.14 # a maj django-tinymce==3.3.0 -e git+https://git.parisson.com/git/django-unique-session.git@master#egg=django-unique-session django-user-agents==0.4.0 +django-recaptcha==2.0.6 jxmlease==1.0.3 mysqlclient==2.0.3 numpy==1.20.3 # django-user-agents==0.3.0 # html5lib==1.1 +requests sorl-thumbnail==12.7.0 unidecode==1.2.0 -xhtml2pdf==0.2.5 +weasyprint==52.5 xlrd==2.0.1 -xlwt==1.3.0 \ No newline at end of file +xlwt==1.3.0 +psycopg2==2.8.6 +redis==3.5.3 +uwsgi==2.0.19 +daphne==3.0.2 +pymemcache==3.4.4 +django-debug-toolbar==3.2.1 +uvicorn[standard]==0.18.1 +httpx==0.23.3 +ipython diff --git a/teleforma/admin.py b/teleforma/admin.py index b133ad86..ec05e40f 100644 --- a/teleforma/admin.py +++ b/teleforma/admin.py @@ -2,6 +2,7 @@ import csv import datetime +from django.conf import settings from django.contrib import admin from django.contrib.admin import SimpleListFilter from django.contrib.auth.admin import UserAdmin @@ -9,6 +10,9 @@ from django.contrib.auth.models import User from django.core import serializers from django.http import HttpResponse from django.utils.translation import ugettext_lazy as _ +from django import forms +from django.contrib.admin.helpers import ActionForm + from .exam.admin import QuotaInline from .models.appointment import (Appointment, AppointmentJury, @@ -81,9 +85,8 @@ class StudentInline(admin.StackedInline): model = Student extra = 1 -# TODO fix max_length -# class StudentGroupForm(ActionForm): -# group_name = forms.CharField(_('Group'), required=False) +class StudentGroupForm(ActionForm): + group_name = forms.CharField(label=_('Group'), max_length=255, required=False) class StudentGroupAdmin(admin.ModelAdmin): @@ -189,8 +192,8 @@ else: actions = ['export_xls', 'write_message', 'add_to_group'] action_form = StudentGroupForm - def get_trainings(self, instance): - return ' - '.join([str(training) for training in instance.trainings.all()]) + def get_trainings(self, instance): + return ' - '.join([str(training) for training in instance.trainings.all()]) def student_name(self, instance): return instance.user.last_name + ' ' + instance.user.first_name @@ -205,23 +208,23 @@ else: serializers.serialize("json", queryset, stream=response) return response - def export_xls(self, request, queryset): - book = UserXLSBook(students=queryset) - book.write() - response = HttpResponse(content_type="application/vnd.ms-excel") - response['Content-Disposition'] = 'attachment; filename=users.xls' - book.book.save(response) - return response + def export_xls(self, request, queryset): + book = UserXLSBook(students=queryset) + book.write() + response = HttpResponse(content_type="application/vnd.ms-excel") + response['Content-Disposition'] = 'attachment; filename=users.xls' + book.book.save(response) + return response - export_xls.short_description = "Export vers XLS" + 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): diff --git a/teleforma/exam/migrations/0001_initial.py b/teleforma/exam/south_migrations/0001_initial.py similarity index 100% rename from teleforma/exam/migrations/0001_initial.py rename to teleforma/exam/south_migrations/0001_initial.py diff --git a/teleforma/exam/migrations/0002_auto__chg_field_script_reject_reason.py b/teleforma/exam/south_migrations/0002_auto__chg_field_script_reject_reason.py similarity index 100% rename from teleforma/exam/migrations/0002_auto__chg_field_script_reject_reason.py rename to teleforma/exam/south_migrations/0002_auto__chg_field_script_reject_reason.py diff --git a/teleforma/exam/migrations/0003_auto__chg_field_script_file__chg_field_scriptpage_file.py b/teleforma/exam/south_migrations/0003_auto__chg_field_script_file__chg_field_scriptpage_file.py similarity index 100% rename from teleforma/exam/migrations/0003_auto__chg_field_script_file__chg_field_scriptpage_file.py rename to teleforma/exam/south_migrations/0003_auto__chg_field_script_file__chg_field_scriptpage_file.py diff --git a/teleforma/exam/migrations/0004_auto__add_field_quota_script_type.py b/teleforma/exam/south_migrations/0004_auto__add_field_quota_script_type.py similarity index 100% rename from teleforma/exam/migrations/0004_auto__add_field_quota_script_type.py rename to teleforma/exam/south_migrations/0004_auto__add_field_quota_script_type.py diff --git a/teleforma/exam/migrations/0005_auto__add_field_quota_session__chg_field_quota_course__chg_field_quota.py b/teleforma/exam/south_migrations/0005_auto__add_field_quota_session__chg_field_quota_course__chg_field_quota.py similarity index 100% rename from teleforma/exam/migrations/0005_auto__add_field_quota_session__chg_field_quota_course__chg_field_quota.py rename to teleforma/exam/south_migrations/0005_auto__add_field_quota_session__chg_field_quota_course__chg_field_quota.py diff --git a/teleforma/exam/migrations/0006_auto__chg_field_script_mime_type__chg_field_scriptpage_mime_type.py b/teleforma/exam/south_migrations/0006_auto__chg_field_script_mime_type__chg_field_scriptpage_mime_type.py similarity index 100% rename from teleforma/exam/migrations/0006_auto__chg_field_script_mime_type__chg_field_scriptpage_mime_type.py rename to teleforma/exam/south_migrations/0006_auto__chg_field_script_mime_type__chg_field_scriptpage_mime_type.py diff --git a/teleforma/exam/migrations/__init__.py b/teleforma/exam/south_migrations/__init__.py similarity index 100% rename from teleforma/exam/migrations/__init__.py rename to teleforma/exam/south_migrations/__init__.py diff --git a/teleforma/forms.py b/teleforma/forms.py index 358ca36b..7cb8535f 100644 --- a/teleforma/forms.py +++ b/teleforma/forms.py @@ -2,7 +2,7 @@ import datetime from io import BytesIO -from captcha.fields import CaptchaField +from captcha.fields import ReCaptchaField from django import forms from django.conf import settings from django.contrib.auth.models import User @@ -55,6 +55,7 @@ def get_unique_username(first_name, last_name): class BBBConferenceForm(ModelForm): class Meta: model = Conference + fields = '__all__' class UserProfileForm(ModelForm): class Meta: @@ -110,7 +111,7 @@ if settings.TELEFORMA_E_LEARNING_TYPE != 'AE': widget=forms.Select()) # no model - captcha = CaptchaField() + captcha = ReCaptchaField() accept = BooleanField() class Meta: @@ -132,23 +133,23 @@ if settings.TELEFORMA_E_LEARNING_TYPE != 'AE': return image #width, height = get_image_dimensions(image) #ratio = float(height) / float(width) - #if ratio > 2.5 or ratio < 1: + # if ratio > 2.5 or ratio < 1: # raise ValidationError({'portrait': "L'image n'est pas au format portrait."}) NEW_HEIGHT = 230 NEW_WIDTH = 180 - #if width < NEW_WIDTH or height < NEW_HEIGHT: + # if width < NEW_WIDTH or height < NEW_HEIGHT: # raise ValidationError({'portrait': "L'image est trop petite. Elle doit faire au moins %spx de large et %spx de hauteur." % (NEW_WIDTH, NEW_HEIGHT)}) - # resize image - img = Image.open(image.file) - new_image = img.resize((NEW_WIDTH, NEW_HEIGHT), Image.ANTIALIAS) - if new_image.mode == "RGBA": - new_image = new_image.convert("RGB") + # resize image + img = Image.open(image.file) + new_image = img.resize((NEW_WIDTH, NEW_HEIGHT), Image.ANTIALIAS) + if new_image.mode == "RGBA": + new_image = new_image.convert("RGB") - temp = BytesIO() - new_image.save(temp, 'jpeg') - temp.seek(0) - return SimpleUploadedFile('temp', temp.read()) + temp = BytesIO() + new_image.save(temp, 'jpeg') + temp.seek(0) + return SimpleUploadedFile('temp', temp.read()) def save(self, commit=True): @@ -234,7 +235,7 @@ else: required=True) # no model - captcha = CaptchaField() + captcha = ReCaptchaField() accept = BooleanField() class Meta: @@ -323,7 +324,7 @@ class CorrectorForm(ModelForm): queryset=Course.objects.all().exclude(title="Aucune").order_by('title'), widget=forms.CheckboxSelectMultiple()) # no model - captcha = CaptchaField() + captcha = ReCaptchaField() # accept = BooleanField() class Meta: diff --git a/teleforma/management/commands/teleforma-convert-boolean-fields.py b/teleforma/management/commands/teleforma-convert-boolean-fields.py new file mode 100644 index 00000000..fcbd33de --- /dev/null +++ b/teleforma/management/commands/teleforma-convert-boolean-fields.py @@ -0,0 +1,18 @@ +from django.conf import settings +from django.apps import apps +from django.core.management.base import BaseCommand, CommandError +import django.db.models as models + +class Command(BaseCommand): + help = "Issue SQL commands to fix boolean fields after MySQL migration" + admin_email = 'webmaster@parisson.com' + + def handle(self, *args, **options): + for app, _ in apps.all_models.items(): + app_models = apps.get_app_config(app).get_models() + for model in app_models: + table = model._meta.db_table + for field in model._meta.fields: + if isinstance(field, models.BooleanField): + field_name = field.column + print(f"alter table {table} alter {field_name} type boolean using case when {field_name}=0 then false else true end;") diff --git a/teleforma/migrations/0001_initial.py b/teleforma/migrations/0001_initial.py index d5866158..32bb774b 100644 --- a/teleforma/migrations/0001_initial.py +++ b/teleforma/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 3.2.3 on 2021-06-01 15:28 +# Generated by Django 3.2.13 on 2023-04-26 11:59 from django.conf import settings from django.db import migrations, models @@ -42,7 +42,7 @@ class Migration(migrations.Migration): fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('public_id', models.CharField(blank=True, max_length=255, verbose_name='public_id')), - ('session', models.CharField(choices=[('1', '1'), ('2', '2'), ('3', '3'), ('4', '4'), ('5', '5'), ('6', '6'), ('7', '7'), ('8', '8'), ('9', '9'), ('10', '10'), ('11', '11'), ('12', '12'), ('13', '13'), ('14', '14'), ('15', '15')], default='1', max_length=16, verbose_name='session')), + ('session', 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')), ('comment', teleforma.fields.ShortTextField(blank=True, max_length=255, verbose_name='comment')), ('date_begin', models.DateTimeField(blank=True, null=True, verbose_name='begin date')), ('date_end', models.DateTimeField(blank=True, null=True, verbose_name='end date')), @@ -65,14 +65,6 @@ class Migration(migrations.Migration): ('title_tweeter', models.CharField(max_length=255, verbose_name='tweeter title')), ('date_modified', models.DateTimeField(auto_now=True, null=True, verbose_name='date modified')), ('number', models.IntegerField(blank=True, null=True, verbose_name='number')), - ('synthesis_note', models.BooleanField(verbose_name='synthesis note')), - ('obligation', models.BooleanField(verbose_name='obligations')), - ('magistral', models.BooleanField(verbose_name='magistral')), - ('procedure', models.BooleanField(verbose_name='procedure')), - ('written_speciality', models.BooleanField(verbose_name='written_speciality')), - ('oral_speciality', models.BooleanField(verbose_name='oral_speciality')), - ('oral_1', models.BooleanField(verbose_name='oral_1')), - ('oral_2', models.BooleanField(verbose_name='oral_2')), ('has_exam_scripts', models.BooleanField(default=True, verbose_name="copies d'examen")), ], options={ @@ -232,7 +224,7 @@ class Migration(migrations.Migration): ('restricted', models.BooleanField(default=False, help_text="Cocher cette case lorsque vous voulez que l'étudiant puisse se connecter, mais ne pas avoir accès aux cours.", verbose_name='Accès restreint')), ('portrait', models.ImageField(blank=True, max_length=500, null=True, upload_to='portraits/')), ('platform_only', models.BooleanField(verbose_name='e-learning platform only')), - ('application_fees', models.BooleanField(blank=True, default=True, verbose_name='application fees')), + ('application_fees', models.BooleanField(blank=True, default=False, verbose_name='application fees')), ('subscription_fees', models.FloatField(blank=True, help_text='€', null=True, verbose_name='subscription fees')), ('promo_code', models.CharField(blank=True, max_length=100, verbose_name='promo code')), ('date_registered', models.DateTimeField(auto_now_add=True, null=True, verbose_name='registration date')), @@ -247,32 +239,15 @@ class Migration(migrations.Migration): ('payment_schedule', models.CharField(blank=True, choices=[('split', 'en plusieurs fois'), ('once', 'en une seule fois')], default='split', max_length=64, null=True, verbose_name='échéancier de paiement')), ('comment', models.TextField(blank=True, null=True, verbose_name='commentaire')), ('receipt_id', models.IntegerField(blank=True, null=True, unique=True, verbose_name='numéro de facture')), + ('courses', models.ManyToManyField(blank=True, related_name='student', to='teleforma.Course', verbose_name='courses')), ('iej', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='student', to='teleforma.iej', verbose_name='iej')), - ('options', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='options_students', to='teleforma.course', verbose_name='options')), - ('oral_1', models.ForeignKey(blank=True, help_text='Matière d’oral de langue (en option)', limit_choices_to={'oral_1': True}, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='oral_1_students', to='teleforma.course', verbose_name='oral de langue (option)')), - ('oral_2', models.ForeignKey(blank=True, help_text='Matière d’oral technique 2 (en option)', limit_choices_to={'oral_2': True}, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='oral_2_students', to='teleforma.course', verbose_name='oral 2 (option)')), - ('oral_speciality', models.ForeignKey(blank=True, help_text='Matière d’oral de spécialité (matière incluse dans la formation approfondie, en option pour toutes les autres formations)', limit_choices_to={'oral_speciality': True}, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='oral_speciality_students', to='teleforma.course', verbose_name='oral speciality')), - ('period', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='student', to='teleforma.period', verbose_name='period')), - ('procedure', models.ForeignKey(blank=True, help_text='Matière de procédure', limit_choices_to={'procedure': True}, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='procedure_students', to='teleforma.course', verbose_name='procedure')), + ('period', models.ManyToManyField(blank=True, related_name='student', to='teleforma.Period', verbose_name='period')), ], options={ - 'verbose_name': 'Student', - 'verbose_name_plural': 'Students', - 'db_table': 'teleforma_student', - 'ordering': ['user__last_name', '-date_subscribed'], - }, - ), - migrations.CreateModel( - name='WebClassGroup', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=255, verbose_name='name')), - ('iejs', models.ManyToManyField(blank=True, related_name='web_class_group', to='teleforma.IEJ', verbose_name='IEJ')), - ], - options={ - 'verbose_name': 'web class group', - 'verbose_name_plural': 'web class group', - 'ordering': ['name'], + 'verbose_name': 'AE student', + 'verbose_name_plural': 'AE students', + 'db_table': 'teleforma_ae_student', + 'ordering': ['user__last_name'], }, ), migrations.CreateModel( @@ -288,17 +263,8 @@ class Migration(migrations.Migration): ('available', models.BooleanField(verbose_name='available')), ('platform_only', models.BooleanField(verbose_name='e-learning platform only')), ('duration', models.IntegerField(default=0, verbose_name='Durée en heures')), - ('magistral', models.ManyToManyField(blank=True, related_name='training_magistral', to='teleforma.CourseType', verbose_name='magistral')), - ('obligation', models.ManyToManyField(blank=True, related_name='training_obligation', to='teleforma.CourseType', verbose_name='obligations')), - ('options', models.ManyToManyField(blank=True, related_name='training_options', to='teleforma.CourseType', verbose_name='options')), - ('oral_1', models.ManyToManyField(blank=True, related_name='training_oral_1', to='teleforma.CourseType', verbose_name='oral 1')), - ('oral_2', models.ManyToManyField(blank=True, related_name='training_oral_2', to='teleforma.CourseType', verbose_name='oral 2')), - ('oral_speciality', models.ManyToManyField(blank=True, related_name='training_oral_speciality', to='teleforma.CourseType', verbose_name='oral speciality')), ('parent', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='children', to='teleforma.training', verbose_name='parent')), ('period', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='training', to='teleforma.period', verbose_name='period')), - ('procedure', models.ManyToManyField(blank=True, related_name='training_procedure', to='teleforma.CourseType', verbose_name='procedure')), - ('synthesis_note', models.ManyToManyField(blank=True, related_name='training_synthesis_note', to='teleforma.CourseType', verbose_name='synthesis note')), - ('written_speciality', models.ManyToManyField(blank=True, related_name='training_written_speciality', to='teleforma.CourseType', verbose_name='written speciality')), ], options={ 'verbose_name': 'training', @@ -317,11 +283,6 @@ class Migration(migrations.Migration): 'db_table': 'teleforma_student_groups', }, ), - migrations.AddField( - model_name='student', - name='training', - field=models.ForeignKey(blank=True, limit_choices_to={'available': True}, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='student_training', to='teleforma.training', verbose_name='training'), - ), migrations.AddField( model_name='student', name='trainings', @@ -332,11 +293,6 @@ class Migration(migrations.Migration): name='user', field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='student', to=settings.AUTH_USER_MODEL, unique=True, verbose_name='user'), ), - migrations.AddField( - model_name='student', - name='written_speciality', - field=models.ForeignKey(blank=True, help_text='Matière juridique de spécialité', limit_choices_to={'written_speciality': True}, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='written_speciality_2students', to='teleforma.course', verbose_name='written speciality'), - ), migrations.CreateModel( name='Room', fields=[ @@ -362,7 +318,7 @@ class Migration(migrations.Migration): ('language', models.CharField(blank=True, max_length=255, verbose_name='Language')), ('telephone', models.CharField(blank=True, max_length=255, verbose_name='Telephone')), ('expiration_date', models.DateField(blank=True, null=True, verbose_name='Expiration_date')), - ('init_password', models.BooleanField(verbose_name='Password initialized')), + ('init_password', models.BooleanField(default=False, verbose_name='Password initialized')), ('wifi_login', models.CharField(blank=True, max_length=255, verbose_name='WiFi login')), ('wifi_pass', models.CharField(blank=True, max_length=255, verbose_name='WiFi pass')), ('birthday', models.DateField(blank=True, help_text='jj/mm/aaaa', null=True, verbose_name='birthday')), @@ -564,7 +520,7 @@ class Migration(migrations.Migration): ('is_published', models.BooleanField(verbose_name='published')), ('mime_type', models.CharField(blank=True, max_length=255, verbose_name='mime type')), ('weight', models.IntegerField(blank=True, choices=[(1, 1), (2, 2), (3, 3), (4, 4)], default=1, verbose_name='weight')), - ('session', models.CharField(choices=[('1', '1'), ('2', '2'), ('3', '3'), ('4', '4'), ('5', '5'), ('6', '6'), ('7', '7'), ('8', '8'), ('9', '9'), ('10', '10'), ('11', '11'), ('12', '12'), ('13', '13'), ('14', '14'), ('15', '15')], default='1', max_length=16, verbose_name='session')), + ('session', 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')), ('is_annal', models.BooleanField(verbose_name='annal')), ('annal_year', models.IntegerField(blank=True, null=True, verbose_name='year')), ('file', models.FileField(blank=True, db_column='filename', max_length=1024, upload_to='items/%Y/%m/%d', verbose_name='file')), @@ -632,6 +588,11 @@ class Migration(migrations.Migration): name='periods', field=models.ManyToManyField(blank=True, related_name='courses', to='teleforma.Period', verbose_name='Périodes associées'), ), + migrations.AddField( + model_name='course', + name='types', + field=models.ManyToManyField(blank=True, related_name='course', to='teleforma.CourseType', verbose_name='types'), + ), migrations.CreateModel( name='Corrector', fields=[ @@ -684,11 +645,6 @@ class Migration(migrations.Migration): name='room', field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='conference', to='teleforma.room', verbose_name='room'), ), - migrations.AddField( - model_name='conference', - name='web_class_group', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='conferences', to='teleforma.webclassgroup', verbose_name='web class group'), - ), migrations.CreateModel( name='AppointmentSlot', fields=[ @@ -731,21 +687,6 @@ class Migration(migrations.Migration): 'ordering': ('id',), }, ), - migrations.CreateModel( - name='AEStudent', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('platform_only', models.BooleanField(verbose_name='platform only')), - ('courses', models.ManyToManyField(blank=True, related_name='ae_student', to='teleforma.Course', verbose_name='courses')), - ('period', models.ManyToManyField(blank=True, related_name='ae_student', to='teleforma.Period', verbose_name='period')), - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='ae_student', to=settings.AUTH_USER_MODEL, unique=True, verbose_name='user')), - ], - options={ - 'verbose_name': 'AE student', - 'db_table': 'teleforma_ae_student', - 'ordering': ['user__last_name'], - }, - ), migrations.CreateModel( name='Appointment', fields=[ diff --git a/teleforma/models/__init__.py b/teleforma/models/__init__.py index cf70770c..5603dfc9 100644 --- a/teleforma/models/__init__.py +++ b/teleforma/models/__init__.py @@ -1,6 +1,5 @@ from .core import * from .crfpa import * # from pro import * -from .ae import * from .messages import * from .appointment import * diff --git a/teleforma/models/ae.py b/teleforma/models/ae.py deleted file mode 100644 index 3dc4baa3..00000000 --- a/teleforma/models/ae.py +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -""" - teleforma - - Copyright (c) 2012 Guillaume Pellerin - -# This software is governed by the CeCILL license under French law and -# abiding by the rules of distribution of free software. You can use, -# modify and/ or redistribute the software under the terms of the CeCILL -# license as circulated by CEA, CNRS and INRIA at the following URL -# "http://www.cecill.info". - -# As a counterpart to the access to the source code and rights to copy, -# modify and redistribute granted by the license, users are provided only -# with a limited warranty and the software's author, the holder of the -# economic rights, and the successive licensors have only limited -# liability. - -# In this respect, the user's attention is drawn to the risks associated -# with loading, using, modifying and/or developing or reproducing the -# software by the user in light of its specific status of free software, -# that may mean that it is complicated to manipulate, and that also -# therefore means that it is reserved for developers and experienced -# professionals having in-depth computer knowledge. Users are therefore -# encouraged to load and test the software's suitability as regards their -# requirements in conditions enabling the security of their systems and/or -# data to be ensured and, more generally, to use and operate it in the -# same conditions as regards security. - -# The fact that you are presently reading this means that you have had -# knowledge of the CeCILL license and that you accept its terms. - -# Author: Guillaume Pellerin -""" - -import django.db.models as models -from django.contrib.auth.models import User -from django.utils.translation import ugettext_lazy as _ - -from ..models import app_label -from ..models.core import MetaCore - - -class AEStudent(models.Model): - - user = models.ForeignKey( - User, related_name='ae_student', verbose_name=_('user'), unique=True, on_delete=models.CASCADE) - period = models.ManyToManyField('Period', related_name='ae_student', verbose_name=_('period'), - blank=True) - platform_only = models.BooleanField(_('platform only')) - courses = models.ManyToManyField('Course', related_name="ae_student", - verbose_name=_('courses'), - blank=True) - - def __str__(self): - try: - return self.user.last_name + ' ' + self.user.first_name - except: - return '' - - class Meta(MetaCore): - db_table = app_label + '_' + 'ae_student' - verbose_name = _('AE student') - ordering = ['user__last_name'] diff --git a/teleforma/models/core.py b/teleforma/models/core.py index af555b3d..6a1dfbc1 100755 --- a/teleforma/models/core.py +++ b/teleforma/models/core.py @@ -252,10 +252,10 @@ class Course(models.Model): periods = models.ManyToManyField('Period', related_name="courses", verbose_name=u'Périodes associées', - blank=True, null=True) + blank=True) types = models.ManyToManyField('CourseType', related_name="course", verbose_name=_('types'), - blank=True, null=True) + blank=True) def __str__(self): return self.title @@ -392,8 +392,8 @@ class Conference(models.Model): status = models.IntegerField( _('status'), choices=STATUS_CHOICES, default=2) streaming = models.BooleanField(_('streaming'), default=True) - web_class_group = models.ForeignKey('WebClassGroup', related_name='conferences', verbose_name=_('web class group'), - blank=True, null=True, on_delete=models.SET_NULL) + # web_class_group = models.ForeignKey('WebClassGroup', related_name='conferences', verbose_name=_('web class group'), + # blank=True, null=True, on_delete=models.SET_NULL) @property def description(self): @@ -599,7 +599,7 @@ class LiveStream(models.Model): @property def url(self): if self.server.type == 'stream-m': - return 'https://' + self.server.host + '/stream/video/consume/' + self.slug + return 'https://' + self.server.host + '/stream/video/consume/' + self.slug else: return 'https://' + self.server.host + '/stream/audio/' + self.slug @@ -798,9 +798,6 @@ class Media(MediaBase): blank=True, null=True, on_delete=models.SET_NULL) period = models.ForeignKey('Period', related_name='media', verbose_name=_('period'), null=True, blank=True, on_delete=models.SET_NULL) - if HAS_TELEMETA: - item = models.ForeignKey(MediaItem, related_name='media', - verbose_name='item', blank=True, null=True, on_delete=models.SET_NULL) type = models.CharField( _('type'), choices=streaming_choices, max_length=32) readers = models.ManyToManyField(User, related_name="media", verbose_name=_('readers'), @@ -959,10 +956,10 @@ class NamePage(object): else: return '%c-%c' % (self.start_letter, self.end_letter) -class StudentMixin(Model): - user = models.ForeignKey(User, related_name='student', verbose_name=_('user'), unique=True) +class StudentMixin(models.Model): + user = models.ForeignKey(User, related_name='student', verbose_name=_('user'), unique=True, on_delete=models.CASCADE) trainings = models.ManyToManyField('Training', related_name='student_trainings', verbose_name=_('trainings'), - blank=True, null=True) + blank=True) iej = models.ForeignKey('IEJ', related_name='student', verbose_name=_('iej'), blank=True, null=True, on_delete=models.SET_NULL) restricted = models.BooleanField("Accès restreint", help_text="Cocher cette case lorsque vous voulez que l'étudiant puisse se connecter, mais ne pas avoir accès aux cours.", default=False) diff --git a/teleforma/models/crfpa.py b/teleforma/models/crfpa.py index 01c11253..12d2b681 100755 --- a/teleforma/models/crfpa.py +++ b/teleforma/models/crfpa.py @@ -44,7 +44,7 @@ from django.urls.base import reverse_lazy from django.utils.translation import ugettext_lazy as _ from tinymce.models import HTMLField -from ..models.core import (Course, Media, MetaCore, payment_choices, +from ..models.core import (Course, Media, MetaCore, StudentMixin, payment_choices, payment_schedule_choices) app_label = 'teleforma' @@ -75,36 +75,36 @@ class Training(models.Model): code = models.CharField(_('code'), max_length=255) name = models.CharField(_('name'), max_length=255, blank=True) description = models.CharField(_('description'), max_length=512, blank=True) - period = models.ForeignKey('Period', related_name='training', verbose_name=_('period'), blank=True, null=True) - parent = models.ForeignKey('Training', related_name='children', verbose_name=_('parent'), blank=True, null=True) + period = models.ForeignKey('Period', related_name='training', verbose_name=_('period'), blank=True, null=True, on_delete=models.SET_NULL) + parent = models.ForeignKey('Training', related_name='children', verbose_name=_('parent'), blank=True, null=True, on_delete=models.SET_NULL) if settings.TELEFORMA_E_LEARNING_TYPE != 'AE': synthesis_note = models.ManyToManyField('CourseType', related_name="training_synthesis_note", verbose_name=_('synthesis note'), - blank=True, null=True) + blank=True) obligation = models.ManyToManyField('CourseType', related_name="training_obligation", verbose_name=_('obligations'), - blank=True, null=True) + blank=True) procedure = models.ManyToManyField('CourseType', related_name="training_procedure", verbose_name=_('procedure'), - blank=True, null=True) + blank=True) written_speciality = models.ManyToManyField('CourseType', related_name="training_written_speciality", verbose_name=_('written speciality'), - blank=True, null=True) + blank=True) oral_speciality = models.ManyToManyField('CourseType', related_name="training_oral_speciality", verbose_name=_('oral speciality'), - blank=True, null=True) + blank=True) oral_1 = models.ManyToManyField('CourseType', related_name="training_oral_1", verbose_name=_('oral 1'), - blank=True, null=True) + blank=True) oral_2 = models.ManyToManyField('CourseType', related_name="training_oral_2", verbose_name=_('oral 2'), - blank=True, null=True) + blank=True) options = models.ManyToManyField('CourseType', related_name="training_options", verbose_name=_('options'), - blank=True, null=True) + blank=True) magistral = models.ManyToManyField('CourseType', related_name="training_magistral", verbose_name=_('magistral'), - blank=True, null=True) + blank=True) cost = models.FloatField(_('cost'), blank=True, null=True) cost_elearning_fascicle = models.FloatField( @@ -167,11 +167,11 @@ if settings.TELEFORMA_E_LEARNING_TYPE != 'AE': else: class Student(StudentMixin): - period = ManyToManyField('Period', related_name='student', verbose_name=_('period'), - blank=True, null=True) - courses = ManyToManyField('Course', related_name="student", + period = models.ManyToManyField('Period', related_name='student', verbose_name=_('period'), + blank=True) + courses = models.ManyToManyField('Course', related_name="student", verbose_name=_('courses'), - blank=True, null=True) + blank=True) # to stay in sync with crfpa training = None @@ -350,7 +350,7 @@ class Home(models.Model): _('Title'), max_length=255, null=True, blank=True) text = models.TextField('Texte', blank=True) video = models.ForeignKey(Media, verbose_name="Video", null=True, blank=True, on_delete=models.SET_NULL) - modified_at = models.DateTimeField(u'Date de modification', auto_now=True, default=datetime.datetime.now) + modified_at = models.DateTimeField(u'Date de modification', auto_now=True) periods = models.ManyToManyField('Period', related_name="home_texts", verbose_name=u'Périodes associées', blank=True) diff --git a/teleforma/models/pro.py b/teleforma/models/pro.py index 2f89dee6..8aab47cf 100644 --- a/teleforma/models/pro.py +++ b/teleforma/models/pro.py @@ -69,7 +69,7 @@ class Seminar(models.Model): verbose_name=_('corrected document'), blank=True, null=True) suscribers = models.ManyToManyField(User, related_name="seminar", verbose_name=_('suscribers'), - blank=True, null=True) + blank=True) date_added = models.DateTimeField(_('date added'), auto_now_add=True) date_modified = models.DateTimeField(_('date modified'), auto_now=True) diff --git a/teleforma/templates/postman/base_write.html b/teleforma/templates/postman/base_write.html index 186813e3..b99f7ad0 100644 --- a/teleforma/templates/postman/base_write.html +++ b/teleforma/templates/postman/base_write.html @@ -15,7 +15,7 @@ {% trans "Pour les questions concernant l'organisation des cours, le planning, les documents de cours ou les copies, adressez-vous à Admin-CRFPA." %}
{% trans "Pour les questions concernant uniquement l'accès à la plateforme et aux médias vidéo ou audio, lire d'abord" %} - la page + la page d'aide {% trans "puis adressez-vous à Support technique." %}

diff --git a/teleforma/templates/registration/registration_complete.html b/teleforma/templates/registration/registration_complete.html index acb6a200..de6eb9c0 100644 --- a/teleforma/templates/registration/registration_complete.html +++ b/teleforma/templates/registration/registration_complete.html @@ -15,7 +15,7 @@ Afin de compléter votre inscription, il est nécessaire d’imprimer le formula


- {% trans "Download" %} + {% trans "Download" %}


Une fois votre dossier reçu et confirmé par nos services, vous recevrez un mail vous invitant à procéder au règlement des arrhes par carte bancaire. Votre inscription ne sera validée qu’au terme de cette ultime étape. diff --git a/teleforma/templates/teleforma/annals.html b/teleforma/templates/teleforma/annals.html index 38e52df2..5ae0288c 100644 --- a/teleforma/templates/teleforma/annals.html +++ b/teleforma/templates/teleforma/annals.html @@ -17,7 +17,7 @@ {% block courses %} {% for c in all_courses %} {% with c.course as course %} -
  • {{ course.title }}
  • +
  • {{ course.title }}
  • {% endwith %} {% endfor %} {% endblock courses %} @@ -32,7 +32,7 @@ @@ -65,11 +65,11 @@ {% for doc in docs %} - {% if doc.file %}{% endif %} {{ doc.title }}{% if doc.file %}{% endif %} + {% if doc.file %}{% endif %} {{ doc.title }}{% if doc.file %}{% endif %} {{ year }} - {% if doc.file %}{% endif %} + {% if doc.file %}{% endif %} {% endfor %} diff --git a/teleforma/templates/teleforma/appointments.html b/teleforma/templates/teleforma/appointments.html index 9809e68b..9c10ea5c 100644 --- a/teleforma/templates/teleforma/appointments.html +++ b/teleforma/templates/teleforma/appointments.html @@ -219,7 +219,7 @@

    {% if ap_period.appointment.can_cancel %} -
    + {% csrf_token %} diff --git a/teleforma/templates/teleforma/course_conference.html b/teleforma/templates/teleforma/course_conference.html index cd08ffe3..99aca695 100644 --- a/teleforma/templates/teleforma/course_conference.html +++ b/teleforma/templates/teleforma/course_conference.html @@ -9,7 +9,7 @@ var conferenceUtils = { stop : function(id){ json([id],'teleforma.stop_conference',function(){ - location.href = '{% url teleforma-conference-record %}'; + location.href = "{% url 'teleforma-conference-record' %}""; } ); }} @@ -33,9 +33,9 @@
    - {{ course.title }} - {{ type }} - {% trans "Session" %} {{ conference.session }} + {{ course.title }} - {{ type }} - {% trans "Session" %} {{ conference.session }}
    @@ -62,7 +62,7 @@
    {% if conference.professor %} -
    {% trans "Course" %}
    {{ conference.course.title }} - {{ conference.course_type }}
    +
    {% trans "Course" %}
    {{ conference.course.title }} - {{ conference.course_type }}
    {% trans "Session" %}
    {{ conference.session }}
    {% trans "Professor" %}
    {{ conference.professor }}
    {% endif %} diff --git a/teleforma/templates/teleforma/course_conference_audio.html b/teleforma/templates/teleforma/course_conference_audio.html index 1eb79839..1e8f4ccb 100644 --- a/teleforma/templates/teleforma/course_conference_audio.html +++ b/teleforma/templates/teleforma/course_conference_audio.html @@ -7,7 +7,7 @@ var conferenceUtils = { stop : function(id){ json([id],'teleforma.conference_stop',function(){ - location.href = '{% url teleforma-conference-record %}';}); + location.href = "{% url 'teleforma-conference-record' %}"";}); }} jQuery(window).ready(function(){ @@ -32,7 +32,7 @@
    {{ course.title }}{% if course.description %} - {{ course.description }}{% endif %} - {{ conference.session }} - {{ conference.professor }} diff --git a/teleforma/templates/teleforma/course_detail.html b/teleforma/templates/teleforma/course_detail.html index 17e03efc..2bdf4334 100644 --- a/teleforma/templates/teleforma/course_detail.html +++ b/teleforma/templates/teleforma/course_detail.html @@ -5,7 +5,7 @@ {% block courses %} {% for c in all_courses %} {% with c.course as course %} -
  • {{ course.title }}
  • +
  • {{ course.title }}
  • {% endwith %} {% endfor %} {% endblock courses %} diff --git a/teleforma/templates/teleforma/course_document.html b/teleforma/templates/teleforma/course_document.html index d4087072..74db19eb 100644 --- a/teleforma/templates/teleforma/course_document.html +++ b/teleforma/templates/teleforma/course_document.html @@ -16,7 +16,7 @@ // // Fetch the PDF document from the URL using promices // -PDFJS.getDocument('{% url teleforma-document-download document.id %}').then(function(pdf) { +PDFJS.getDocument("{% url 'teleforma-document-download' document.id %}").then(function(pdf) { // Using promise to fetch the page pdf.getPage(1).then(function(page) { var scale = 1.5; diff --git a/teleforma/templates/teleforma/course_media.html b/teleforma/templates/teleforma/course_media.html index 774261ac..4033ce9e 100644 --- a/teleforma/templates/teleforma/course_media.html +++ b/teleforma/templates/teleforma/course_media.html @@ -60,7 +60,7 @@ $(document).ready(function(){ {% 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' %} {% endif %} {% endif %} @@ -75,14 +75,14 @@ $(document).ready(function(){  {% trans "Audio" %} {% endif %} {% if "audio" in media.mime_type %} -  {% trans "Video" %} +  {% trans "Video" %} {% endif %} {% if user.is_staff %} {% if media.is_published %}{% trans " published" %}{% else %}{% trans " rejected" %}{% endif %} {% endif %}
    - {{ course.title }} - {{ type }}{% if media.conference.session %} - {% trans "Session" %} {{ media.conference.session }}{% endif %} + {{ course.title }} - {{ type }}{% if media.conference.session %} - {% trans "Session" %} {{ media.conference.session }}{% endif %}
    @@ -129,7 +129,7 @@ $(document).ready(function(){
    {% if media.conference %} -
    {% trans "Course" %}
    {{ media.course.title }} - {{ media.course_type }}
    +
    {% trans "Course" %}
    {{ media.course.title }} - {{ media.course_type }}
    {% trans "Session" %}
    {{ media.conference.session }}
    {% if media.conference.professor %}
    {% trans "Professor" %}
    {{ media.conference.professor }}
    @@ -144,7 +144,6 @@ $(document).ready(function(){
    {% trans "Date modified" %}
    {{ media.date_modified }}
    {% trans "Media ID" %}
    {{ media.id }}
    {% trans "Conference ID" %}
    {{ media.conference.public_id }}
    -
    {% trans "Web class group" %}
    {{ media.conference.web_class_group }}
    {% endif %} {% endif %} diff --git a/teleforma/templates/teleforma/course_media_transcoded.html b/teleforma/templates/teleforma/course_media_transcoded.html index 2fa6fc10..99473353 100644 --- a/teleforma/templates/teleforma/course_media_transcoded.html +++ b/teleforma/templates/teleforma/course_media_transcoded.html @@ -106,7 +106,6 @@ $(document).ready(function(){
    {% trans "Date modified" %}
    {{ media.date_modified }}
    {% trans "Media ID" %}
    {{ media.id }}
    {% trans "Conference ID" %}
    {{ media.conference.public_id }}
    -
    {% trans "Web class group" %}
    {{ media.conference.web_class_group }}
    {% endif %} {% endif %} diff --git a/teleforma/templates/teleforma/course_media_video_embed.html b/teleforma/templates/teleforma/course_media_video_embed.html index 1ecf5280..eb218228 100644 --- a/teleforma/templates/teleforma/course_media_video_embed.html +++ b/teleforma/templates/teleforma/course_media_video_embed.html @@ -29,7 +29,7 @@
    {% if media.conference %} -
    {% trans "Course" %}
    {{ media.course.title }} - {{ media.course_type }}
    +
    {% trans "Course" %}
    {{ media.course.title }} - {{ media.course_type }}
    {% trans "Session" %}
    {{ media.conference.session }}
    {% if media.conference.professor %}
    {% trans "Professor" %}
    {{ media.conference.professor }}
    diff --git a/teleforma/templates/teleforma/courses.html b/teleforma/templates/teleforma/courses.html index 2518564c..9574aa80 100644 --- a/teleforma/templates/teleforma/courses.html +++ b/teleforma/templates/teleforma/courses.html @@ -18,7 +18,7 @@ {% block courses %} {% for c in all_courses %} {% with c.course as course %} -
  • {{ course.title }}
  • +
  • {{ course.title }}
  • {% endwith %} {% endfor %} {% endblock courses %} @@ -31,14 +31,14 @@ {% get_telecaster as telecaster %} {% if telecaster %} {% endif %} {% if user.is_staff %} {% endif %} @@ -121,7 +121,7 @@ {% elif slot.status == 'almost' %} La webclasse "{{slot.webclass.course.title}}" va démarrer bientôt. {% endif %} - Cliquez ici pour rejoindre la webclasse

    @@ -134,7 +134,7 @@

    Vous n'êtes pas inscrit à la webclasse "{{webclass.course.title}}". Cliquez-ici pour choisir un créneau + href="{% url 'teleforma-webclass-appointments' webclass.id %}">Cliquez-ici pour choisir un créneau horaire

    diff --git a/teleforma/templates/teleforma/courses_pending.html b/teleforma/templates/teleforma/courses_pending.html index 7460181e..537b5d7f 100644 --- a/teleforma/templates/teleforma/courses_pending.html +++ b/teleforma/templates/teleforma/courses_pending.html @@ -13,7 +13,7 @@ {% for type in c.types %}
    {% block media %} diff --git a/teleforma/templates/teleforma/inc/conference_list.html b/teleforma/templates/teleforma/inc/conference_list.html index db43f0b4..96cc8166 100644 --- a/teleforma/templates/teleforma/inc/conference_list.html +++ b/teleforma/templates/teleforma/inc/conference_list.html @@ -15,7 +15,7 @@ {% if stream.streaming %} - + {% trans 'Click here' %} @@ -25,7 +25,7 @@
    {% trans "Title" %}
    {{ stream.conference.course.title }}
    {% trans "Session" %}
    {{ stream.conference.session }}
    {% if stream.conference.professor.user.username %} -
    {% trans "Professor" %}
    {{ stream.conference.professor }}
    +
    {% trans "Professor" %}
    {{ stream.conference.professor }}
    {% endif %}
    {% trans "Begin" %}
    {{ stream.conference.date_begin }}
    diff --git a/teleforma/templates/teleforma/inc/document_list.html b/teleforma/templates/teleforma/inc/document_list.html index 99a88b10..b1f21155 100644 --- a/teleforma/templates/teleforma/inc/document_list.html +++ b/teleforma/templates/teleforma/inc/document_list.html @@ -15,9 +15,9 @@ {% for doc in docs|from_course_type:type|from_doc_type:doc_type|from_periods:period|published %} - {% if doc.file %}{% endif %} {{ doc.title }}{% if doc.file %}{% endif %} + {% if doc.file %}{% endif %} {{ doc.title }}{% if doc.file %}{% endif %} {{ doc.date_added }} - {% if doc.file %}{% endif %} + {% if doc.file %}{% endif %} {% endfor %} diff --git a/teleforma/templates/teleforma/inc/media_list.html b/teleforma/templates/teleforma/inc/media_list.html index 4826e3e4..b83a7556 100644 --- a/teleforma/templates/teleforma/inc/media_list.html +++ b/teleforma/templates/teleforma/inc/media_list.html @@ -32,7 +32,7 @@
    {% trans "Title" %}
    {{ media.conference.course.title }}
    {% trans "Session" %}
    {{ media.conference.session }}
    {% if media.conference.professor %} -
    {% trans "Professor" %}
    {{ media.conference.professor }}
    +
    {% trans "Professor" %}
    {{ media.conference.professor }}
    {% endif %}
    {% trans "Begin" %}
    {{ media.conference.date_begin }}
    {% if media.conference.comment %} diff --git a/teleforma/templates/teleforma/inc/newsitem.html b/teleforma/templates/teleforma/inc/newsitem.html index 1c8a43ef..7f4692d4 100644 --- a/teleforma/templates/teleforma/inc/newsitem.html +++ b/teleforma/templates/teleforma/inc/newsitem.html @@ -7,13 +7,13 @@
      {% if newsitem.can_edit %}
    • - éditer + éditer
    • {% endif %} {% if newsitem.can_delete %}
    • - supprimer + supprimer
    • {% endif %}
    diff --git a/teleforma/templates/teleforma/inc/newsitems_portlet.html b/teleforma/templates/teleforma/inc/newsitems_portlet.html index f5beb44a..f4204806 100644 --- a/teleforma/templates/teleforma/inc/newsitems_portlet.html +++ b/teleforma/templates/teleforma/inc/newsitems_portlet.html @@ -6,10 +6,10 @@

    actualitésActualités

    diff --git a/teleforma/templates/teleforma/inc/user_list.html b/teleforma/templates/teleforma/inc/user_list.html index 6f50d651..0f0b03ad 100644 --- a/teleforma/templates/teleforma/inc/user_list.html +++ b/teleforma/templates/teleforma/inc/user_list.html @@ -25,8 +25,8 @@ {% for user in page.object_list %} - {{ user.last_name }} - {{ user.first_name }} + {{ user.last_name }} + {{ user.first_name }} {% if user.student.get %} {% with user.student.get as student %} diff --git a/teleforma/templates/teleforma/newsitem_list.html b/teleforma/templates/teleforma/newsitem_list.html index d5e0c68b..99c98972 100644 --- a/teleforma/templates/teleforma/newsitem_list.html +++ b/teleforma/templates/teleforma/newsitem_list.html @@ -11,13 +11,13 @@ diff --git a/teleforma/templates/teleforma/profile_detail.html b/teleforma/templates/teleforma/profile_detail.html index da83fa78..640ae763 100644 --- a/teleforma/templates/teleforma/profile_detail.html +++ b/teleforma/templates/teleforma/profile_detail.html @@ -48,7 +48,7 @@ {% if user.is_authenticated and user.username == usr.username %} {% elif user.is_staff %} - + {% endif %}
    diff --git a/teleforma/templates/teleforma/search_criteria.html b/teleforma/templates/teleforma/search_criteria.html index 6e8ef116..a81e32a8 100644 --- a/teleforma/templates/teleforma/search_criteria.html +++ b/teleforma/templates/teleforma/search_criteria.html @@ -31,7 +31,7 @@ function update_period(source, from_field, to_field) { } $(document).ready(function () { - $('#location').autocomplete('{% url telemeta-complete-location %}', { + $('#location').autocomplete('{% url 'telemeta-complete-location' %}', { max: 20, formatResult: function(data) { return data[0].replace(/ *\([0-9]+.*\) *$/, ''); @@ -74,7 +74,7 @@ $(document).ready(function () {

    {% trans "Advanced Search" %}

    -{% csrf_token %} +{% csrf_token %}

    diff --git a/teleforma/templates/teleforma/users.html b/teleforma/templates/teleforma/users.html index 6f744f68..a9953fc5 100644 --- a/teleforma/templates/teleforma/users.html +++ b/teleforma/templates/teleforma/users.html @@ -16,7 +16,7 @@

    @@ -29,7 +29,7 @@ @@ -42,7 +42,7 @@
      {% block courses %} {% for c in courses %} -
    • {{ c }}
    • +
    • {{ c }}
    • {% endfor %} {% endblock courses %}
    @@ -61,7 +61,7 @@ {% if user.is_staff %} {% endif %} diff --git a/teleforma/templates/telemeta/base.html b/teleforma/templates/telemeta/base.html index 378acf7f..386fc5af 100644 --- a/teleforma/templates/telemeta/base.html +++ b/teleforma/templates/telemeta/base.html @@ -167,8 +167,8 @@ alt="logo" /> {% else %} -
  • {% trans "Profile" %}
  • -
  • {% trans "Sign out" %}
  • +
  • {% trans "Profile" %}
  • +
  • {% trans "Sign out" %}
  • {% endif %} {% endif %} diff --git a/teleforma/templatetags/teleforma_tags.py b/teleforma/templatetags/teleforma_tags.py index 25cb62a9..aaa18ac9 100644 --- a/teleforma/templatetags/teleforma_tags.py +++ b/teleforma/templatetags/teleforma_tags.py @@ -43,7 +43,7 @@ from django.contrib.auth.models import User from django.db.models.query_utils import Q from django.shortcuts import get_object_or_404 from django.urls.base import reverse -from django.utils.encoding import force_text, smart_str +from django.utils.encoding import force_str, smart_str from django.utils.safestring import mark_safe from django.utils.translation import ugettext_lazy as _ from docutils.core import publish_parts @@ -419,7 +419,7 @@ def render_flatpage(content): parts = publish_parts(source=smart_str( parsed), writer_name="html4css1", settings_overrides={}) - return mark_safe('
    \n' + force_text(parts["html_body"]) + '
    ') + return mark_safe('
    \n' + force_str(parts["html_body"]) + '
    ') render_flatpage.is_safe = True diff --git a/teleforma/urls.py b/teleforma/urls.py index a644ea54..b471edd3 100644 --- a/teleforma/urls.py +++ b/teleforma/urls.py @@ -125,9 +125,6 @@ urlpatterns = [ url(r'^accounts/password_reset_complete/$', PasswordResetCompleteView.as_view( template_name='registration/password_reset_complete.html'), name="teleforma-password-reset-complete"), - - url(r'^captcha/', include('captcha.urls')), - # Help url(r'^help/$', HelpView.as_view(), name="teleforma-help"), @@ -188,10 +185,6 @@ urlpatterns = [ url(r'^desk/periods/(?P.*)/conferences/(?P.*)/audio/$', ConferenceView.as_view(template_name="teleforma/course_conference_audio.html"), name="teleforma-conference-audio"), - url(r'^desk/conference_record/$', ConferenceRecordView.as_view(), - name="teleforma-conference-record"), - url(r'^desk/bbbconference_record/$', BBBConferenceRecordView.as_view(), - name="teleforma-bbbconference-record"), url(r'^desk/periods/(?P.*)/conferences/list/$', ConferenceListView.as_view(), name="teleforma-conferences"), diff --git a/teleforma/views/core.py b/teleforma/views/core.py index 31d41686..548d8bc4 100644 --- a/teleforma/views/core.py +++ b/teleforma/views/core.py @@ -42,12 +42,13 @@ from teleforma.utils import guess_mimetypes from jsonrpc import jsonrpc_method +import weasyprint from django.utils.decorators import method_decorator from django.contrib.auth import authenticate, login, get_backends from django.template import RequestContext, loader, Context from django import template -from django.http import HttpResponse, HttpResponseRedirect, Http404 -from django.shortcuts import render_to_response, redirect, get_object_or_404 +from django.http import FileResponse, HttpResponse, HttpResponseRedirect, Http404 +from django.shortcuts import render, redirect, get_object_or_404 from django.views.generic import * from django.views.generic.base import * from django.conf import settings @@ -78,15 +79,13 @@ from teleforma.models.crfpa import Home import pages from xlwt import Workbook -from cgi import escape -from cStringIO import StringIO -from xhtml2pdf import pisa +from html import escape from ..decorators import access_required from ..models.appointment import Appointment, AppointmentPeriod from ..models.core import (Conference, Course, CourseType, Department, Document, DocumentType, Media, MediaTranscoded, - Organization, Period, Professor, WebClassGroup, + Organization, Period, Professor, get_user_role) from ..webclass.models import Webclass, WebclassRecord from .pages import get_page_content @@ -205,15 +204,15 @@ def get_default_period(periods): else: return Period.objects.get(id=getattr(settings, 'TELEFORMA_PERIOD_DEFAULT_ID', 1)) - def content_to_pdf(content, dest, encoding='utf-8', **kwargs): """ Write into *dest* file object the given html *content*. Return True if the operation completed successfully. """ - src = BytesIO(content.encode(encoding)) - pdf = pisa.pisaDocument(src, dest, encoding=encoding, **kwargs) - return not pdf.err + src = weasyprint.HTML(string=content, encoding=encoding) + src.write_pdf(dest) + return True + def content_to_response(content, filename=None): @@ -316,8 +315,7 @@ def serve_media(media_path, content_type="", buffering=True, streaming=False): buffering=buffering, streaming=streaming) else: try: - pass - #response = FileResponse(open(media_path, 'rb')) + response = FileResponse(open(media_path, 'rb')) except: response = StreamingHttpResponse(stream_from_file(media_path), content_type=content_type) filename = os.path.basename(media_path) @@ -608,8 +606,6 @@ class MediaView(CourseAccessMixin, DetailView): app_label="teleforma", model="course") room_name = media.course.code - if media.conference.web_class_group: - room_name += '_' + media.conference.public_id context['room'] = get_room(name=room_name, period=context['period'].name, content_type=content_type, @@ -672,8 +668,6 @@ class MediaTranscodedView(CourseAccessMixin, DetailView): app_label="teleforma", model="course") room_name = media.course.code - if media.conference.web_class_group: - room_name += '_' + media.conference.public_id context['room'] = get_room(name=room_name, period=context['period'].name, content_type=content_type, @@ -780,8 +774,6 @@ class ConferenceView(CourseAccessMixin, DetailView): app_label="teleforma", model="course") room_name = conference.course.code - if conference.web_class_group: - room_name += '_' + conference.public_id context['room'] = get_room(name=room_name, period=context['period'].name, content_type=content_type, @@ -870,10 +862,10 @@ class ConferenceMixin(FormView): model = Conference hidden_fields = ['started', 'date_begin', 'date_end', 'public_id', 'readers'] -class ConferenceRecordView(ConferenceMixin): - "Conference record form : TeleCaster module required" - form_class = ConferenceForm - template_name='teleforma/course_conference_record.html' +# class ConferenceRecordView(ConferenceMixin): +# "Conference record form : TeleCaster module required" +# form_class = ConferenceForm +# template_name='teleforma/course_conference_record.html' # def get_context_data(self, **kwargs): # context = super(ConferenceRecordView, self).get_context_data(**kwargs) @@ -1065,24 +1057,24 @@ class ProfessorListView(View): professor.save() -class WebClassGroupView(View): +# class WebClassGroupView(View): - @jsonrpc_method('teleforma.get_class_group_list') - def get_class_group_list(request): - class_groups = WebClassGroup.objects.all() - return [w.to_json_dict() for w in class_groups] +# @jsonrpc_method('teleforma.get_class_group_list') +# def get_class_group_list(request): +# class_groups = WebClassGroup.objects.all() +# return [w.to_json_dict() for w in class_groups] - def pull(request, host=None): - if host: - url = 'http://' + host + '/json/' - else: - url = 'http://' + settings.TELECASTER_MASTER_SERVER + '/json/' - s = ServiceProxy(url) +# def pull(request, host=None): +# if host: +# url = 'http://' + host + '/json/' +# else: +# url = 'http://' + settings.TELECASTER_MASTER_SERVER + '/json/' +# s = ServiceProxy(url) - remote_list = s.teleforma.get_class_group_list() - for class_group_dict in remote_list['result']: - class_group, c = WebClassGroup.objects.get_or_create( - name=class_group_dict['name']) +# remote_list = s.teleforma.get_class_group_list() +# for class_group_dict in remote_list['result']: +# class_group, c = WebClassGroup.objects.get_or_create( +# name=class_group_dict['name']) class HelpView(TemplateView): diff --git a/teleforma/webclass/migrations/0001_initial.py b/teleforma/webclass/migrations/0001_initial.py index 65a107ff..87a2441f 100644 --- a/teleforma/webclass/migrations/0001_initial.py +++ b/teleforma/webclass/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 3.2.3 on 2021-06-01 15:28 +# Generated by Django 3.2.13 on 2023-04-26 11:59 from django.conf import settings from django.db import migrations, models -- 2.39.5