From: Yoan Le Clanche Date: Tue, 30 Jun 2020 15:24:32 +0000 (+0200) Subject: WIP notelemeta X-Git-Tag: 2.8.1-ae~78 X-Git-Url: https://git.parisson.com/?a=commitdiff_plain;h=110b6f7c2e4b9abe63006b2d67003f3ed5296723;p=teleforma.git WIP notelemeta --- diff --git a/requirements.txt b/requirements.txt index 9a76a5b1..cc96fd4c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,21 +1,21 @@ setuptools django==1.4.19 telemeta==1.4.6 -south -django-pagination==1.0.7 +south # a supprimer +django-pagination==1.0.7 # a supprimer django-postman==3.2.0 django-extensions==0.9 -django-notes +django-notes # a supprimer django-timezones==0.2 django-jqchat -crocodoc +crocodoc # a supprimer django-registration==0.8 -django-extra-views==0.6.5 -django-simple-captcha -django-suit +django-extra-views==0.6.5 # a supprimer +django-simple-captcha # a maj +django-suit # a maj django-nvd3 django-user-agents xhtml2pdf html5lib==0.95 django-tinymce==1.5.4 -django-quiz +django-quiz # a supprimer diff --git a/teleforma/4.0.5.zip b/teleforma/4.0.5.zip new file mode 100644 index 00000000..db83dbe4 Binary files /dev/null and b/teleforma/4.0.5.zip differ diff --git a/teleforma/forms.py b/teleforma/forms.py index c92b8580..945a5eaf 100644 --- a/teleforma/forms.py +++ b/teleforma/forms.py @@ -17,7 +17,7 @@ from extra_views import CreateWithInlinesView, UpdateWithInlinesView from captcha.fields import CaptchaField from teleforma.models.core import Course, Professor -from teleforma.models.profile import UserProfile +from teleforma.models.crfpa import Profile as UserProfile from tinymce.widgets import TinyMCE from itertools import cycle from django.core.files.images import get_image_dimensions diff --git a/teleforma/locale/fr/LC_MESSAGES/django.po b/teleforma/locale/fr/LC_MESSAGES/django.po index ede7a522..f4107710 100644 --- a/teleforma/locale/fr/LC_MESSAGES/django.po +++ b/teleforma/locale/fr/LC_MESSAGES/django.po @@ -2217,7 +2217,7 @@ msgstr "" #: templates/telemeta/base.html:171 templates/telemeta/base.html.py:176 msgid "Sign out" -msgstr "" +msgstr "Se déconnecter" #: templates/telemeta/base.html:226 msgid "Powered by" @@ -2266,11 +2266,11 @@ msgstr "" #: templates/telemeta/login.html:29 msgid "Password forgotten" -msgstr "" +msgstr "Mot de passe oublié ?" #: templates/telemeta/login.html:30 msgid "Sign in" -msgstr "" +msgstr "Connexion" #: templates/telemeta/profile_detail.html:7 msgid "User Profile" @@ -2331,7 +2331,7 @@ msgstr "" #: templates/telemeta/profile_detail.html:85 msgid "WiFi password" -msgstr "" +msgstr "Mot de passe WiFi" #: templates/telemeta/profile_detail.html:89 msgid "Expiration date" @@ -2339,11 +2339,11 @@ msgstr "Date d'expiration" #: templates/telemeta/profile_detail.html:90 msgid "Last login" -msgstr "" +msgstr "Dernière connexion" #: templates/telemeta/profile_detail.html:101 msgid "Apply" -msgstr "" +msgstr "Appliquer" #: templates/telemeta/search_criteria.html:5 #: templates/telemeta/search_criteria.html:76 @@ -2352,7 +2352,7 @@ msgstr "" #: templates/telemeta/search_criteria.html:69 msgid "Search" -msgstr "" +msgstr "Recherche" #: templates/telemeta/search_criteria.html:113 msgid "Year of recording" diff --git a/teleforma/models/core.py b/teleforma/models/core.py index 706c09cb..b22d5e4d 100755 --- a/teleforma/models/core.py +++ b/teleforma/models/core.py @@ -780,9 +780,8 @@ class Media(MediaBase): def poster_url(self, geometry='640'): url = '' - for related in self.item.related.all(): - if 'preview' in related.title: - url = sorl_default.backend.get_thumbnail(related.file, geometry).url + if self.poster_file: + url = sorl_default.backend.get_thumbnail(self.poster_file, geometry).url return url class Meta(MetaCore): diff --git a/teleforma/models/profile.py b/teleforma/models/profile.py deleted file mode 100644 index 501e4d09..00000000 --- a/teleforma/models/profile.py +++ /dev/null @@ -1,20 +0,0 @@ -from django.db import models -from django.contrib.auth.models import User -from teleforma.models.core import MetaCore -from django.utils.translation import ugettext_lazy as _ - -class UserProfile(models.Model): - "User profile extension" - - user = models.ForeignKey(User, unique=True, related_name="profile") - institution = models.CharField(_('Institution')) - department = models.CharField(_('Department')) - attachment = models.CharField(_('Attachment')) - function = models.CharField(_('Function')) - address = models.TextField(_('Address')) - telephone = models.CharField(_('Telephone')) - expiration_date = models.DateField(_('Expiration_date')) - - class Meta(MetaCore): - db_table = 'profiles' - permissions = (("can_not_view_users_and_profiles", "Cannot view other users and any profile"),) diff --git a/teleforma/models/profile.py.bak b/teleforma/models/profile.py.bak new file mode 100644 index 00000000..501e4d09 --- /dev/null +++ b/teleforma/models/profile.py.bak @@ -0,0 +1,20 @@ +from django.db import models +from django.contrib.auth.models import User +from teleforma.models.core import MetaCore +from django.utils.translation import ugettext_lazy as _ + +class UserProfile(models.Model): + "User profile extension" + + user = models.ForeignKey(User, unique=True, related_name="profile") + institution = models.CharField(_('Institution')) + department = models.CharField(_('Department')) + attachment = models.CharField(_('Attachment')) + function = models.CharField(_('Function')) + address = models.TextField(_('Address')) + telephone = models.CharField(_('Telephone')) + expiration_date = models.DateField(_('Expiration_date')) + + class Meta(MetaCore): + db_table = 'profiles' + permissions = (("can_not_view_users_and_profiles", "Cannot view other users and any profile"),) diff --git a/teleforma/static/django_tinymce/init_tinymce.js b/teleforma/static/django_tinymce/init_tinymce.js new file mode 100644 index 00000000..99c141ae --- /dev/null +++ b/teleforma/static/django_tinymce/init_tinymce.js @@ -0,0 +1,38 @@ +(function ($) { + function initTinyMCE($e) { + if ($e.parents('.empty-form').length == 0) { // Don't do empty inlines + var mce_conf = $.parseJSON($e.attr('data-mce-conf')); + var id = $e.attr('id'); + if ('elements' in mce_conf && mce_conf['mode'] == 'exact') { + mce_conf['elements'] = id; + } + if ($e.attr('data-mce-gz-conf')) { + tinyMCE_GZ.init($.parseJSON($e.attr('data-mce-gz-conf'))); + } + if (!tinyMCE.editors[id]) { + tinyMCE.init(mce_conf); + } + } + } + + $(function () { + // initialize the TinyMCE editors on load + $('.tinymce').each(function () { + initTinyMCE($(this)); + }); + + // initialize the TinyMCE editor after adding an inline + // XXX: We don't use jQuery's click event as it won't work in Django 1.4 + document.body.addEventListener("click", function(ev) { + if(!ev.target.parentNode || ev.target.parentNode.className.indexOf("add-row") === -1) { + return; + } + var $addRow = $(ev.target.parentNode); + setTimeout(function() { // We have to wait until the inline is added + $('textarea.tinymce', $addRow.parent()).each(function () { + initTinyMCE($(this)); + }); + }, 0); + }, true); + }); +}(jQuery)); diff --git a/teleforma/static/teleforma/css/teleforma.css b/teleforma/static/teleforma/css/teleforma.css index 2f64c2eb..234d97cb 100644 --- a/teleforma/static/teleforma/css/teleforma.css +++ b/teleforma/static/teleforma/css/teleforma.css @@ -623,8 +623,6 @@ color:#FFF; } #footer :link, #footer :visited { color: #FFF; } #footer hr { display: none } -#footer #telemeta_powered { border: 0; float: left } -#footer #telemeta_powered:hover { background: transparent } #footer p { margin: 0; } #footer p.left { float: left; diff --git a/teleforma/static/teleforma/images/text-speak.png b/teleforma/static/teleforma/images/text-speak.png new file mode 100644 index 00000000..b31ebac2 Binary files /dev/null and b/teleforma/static/teleforma/images/text-speak.png differ diff --git a/teleforma/static/teleforma/js/application.js b/teleforma/static/teleforma/js/application.js index 0d6365a1..5f351714 100644 --- a/teleforma/static/teleforma/js/application.js +++ b/teleforma/static/teleforma/js/application.js @@ -92,7 +92,7 @@ $(document).ready(function(){ */ /** - * Class for telemeta global functions. + * Class for teleforma global functions. * Note that the dollar sign is a reserved keyword in some browsers * (see http://davidwalsh.name/dollar-functions) * which might be in conflict with jQuery dollar sign. @@ -127,7 +127,7 @@ function foldInfoBlocks() { } /** - * Global telemeta function which sets the current selected menu according to the current url + * Global teleforma function which sets the current selected menu according to the current url */ function setSelectedMenu(){ var $J = jQuery; diff --git a/teleforma/static/teleforma/js/locale.js b/teleforma/static/teleforma/js/locale.js new file mode 100644 index 00000000..3f737535 --- /dev/null +++ b/teleforma/static/teleforma/js/locale.js @@ -0,0 +1,50 @@ +var localeStrings = { + 'title': gettext('title'), + 'description': gettext('description'), + 'delete the marker permanently?': gettext('delete the marker permanently?'), + 'marker added to the selected playlist': gettext('marker added to the selected playlist'), + 'item added to the selected playlist': gettext('item added to the selected playlist'), + 'collection added to the selected playlist': gettext('collection added to the selected playlist'), + 'resource added to the selected playlist': gettext('resource added to the selected playlist'), + 'there are unsaved or modified markers': gettext('there are unsaved or modified markers'), + 'If you exit the page you will loose your changes' : gettext('If you exit the page you will loose your changes'), + 'author' : gettext('author'), + 'Paste HTML to embed player in website': gettext('Paste HTML to embed player in website'), + 'delete the item permanently?' : gettext('delete the item permanently?'), + 'delete the collection permanently?' : gettext('delete the collection permanently?'), + 'delete the playlist permanently?' : gettext('delete the playlist permanently?'), + 'delete the resource from the playlist permanently?' : gettext('delete the resource from the playlist permanently?'), +}; + +function gettrans(str){ + var loc = localeStrings; //instantiate once for faster lookup + return str in loc ? loc[str] : str; +} + +/* + * Copyright (C) 2007-2011 Parisson + * Copyright (c) 2011 Riccardo Zaccarelli + * + * This file is part of TimeSide. + * + * TimeSide is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * TimeSide is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with TimeSide. If not, see . + * + * Author: Riccardo Zaccarelli + */ + +/** + * Class for managing translations in telemeta. + */ + + diff --git a/teleforma/static/teleforma/js/teleforma-moodle-media.js b/teleforma/static/teleforma/js/teleforma-moodle-media.js index 49ff7a8a..17cb4322 100644 --- a/teleforma/static/teleforma/js/teleforma-moodle-media.js +++ b/teleforma/static/teleforma/js/teleforma-moodle-media.js @@ -23,7 +23,7 @@ */ /** - * Class for telemeta global functions. + * Class for teleforma global functions. * Note that the dollar sign is a reserved keyword in some browsers * (see http://davidwalsh.name/dollar-functions) * which might be in conflict with jQuery dollar sign. diff --git a/teleforma/templates/registration/activate.html b/teleforma/templates/registration/activate.html index 6cf22cbc..a85fd163 100644 --- a/teleforma/templates/registration/activate.html +++ b/teleforma/templates/registration/activate.html @@ -2,7 +2,7 @@ {% load i18n %} {% block title %}{% if account %}{% trans "Activation complete" %}{% else %}{% trans "Activation problem" %}{% endif %}{% endblock %} {% block content %} -{% url auth_login as auth_login_url %} +{% url teleforma-login as auth_login_url %} {% if account %} {% blocktrans %} Thanks {{ account }}, activation complete! diff --git a/teleforma/templates/registration/activation_complete.html b/teleforma/templates/registration/activation_complete.html index 63f343bf..a83b1b0b 100644 --- a/teleforma/templates/registration/activation_complete.html +++ b/teleforma/templates/registration/activation_complete.html @@ -2,7 +2,7 @@ {% load i18n %} {% block title %}{% trans "Activation complete" %}{% endblock %} {% block content %} -{% url auth_login as auth_login_url %} +{% url teleforma-login as auth_login_url %} {% blocktrans %} Thanks, activation complete! You may now login using the username and password you set at registration. {% endblocktrans %} diff --git a/teleforma/templates/registration/login.html b/teleforma/templates/registration/login.html index f8ceae74..c8be9a82 100644 --- a/teleforma/templates/registration/login.html +++ b/teleforma/templates/registration/login.html @@ -9,7 +9,7 @@

{% blocktrans %}Your username and password didn't match. Please try again.{% endblocktrans %}

{% endif %} -
{% csrf_token %} +{% csrf_token %} diff --git a/teleforma/templates/teleforma/base.html b/teleforma/templates/teleforma/base.html index f92d860b..188a6a9e 100644 --- a/teleforma/templates/teleforma/base.html +++ b/teleforma/templates/teleforma/base.html @@ -47,7 +47,7 @@ - + {% if user.is_authenticated %} @@ -237,7 +237,7 @@ diff --git a/teleforma/templates/teleforma/course.html b/teleforma/templates/teleforma/course.html index 34522332..1a5e9c89 100644 --- a/teleforma/templates/teleforma/course.html +++ b/teleforma/templates/teleforma/course.html @@ -38,8 +38,8 @@ {% for media in course.media.all %} - - + + {% endfor %} diff --git a/teleforma/templates/teleforma/course_media.html b/teleforma/templates/teleforma/course_media.html index 8ad87586..b44f9ac2 100644 --- a/teleforma/templates/teleforma/course_media.html +++ b/teleforma/templates/teleforma/course_media.html @@ -58,8 +58,8 @@ $(document).ready(function(){ {% endblock extra_javascript %} {% block module-action %} -{% if media.item.file and media.is_published or user.is_superuser or user.is_staff %} - {% if not "video" in media.mime_type or perms.telemeta.can_play_all_items or request.user_agent.os.family == 'iOS' %} +{% 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' %} @@ -73,7 +73,7 @@ $(document).ready(function(){
{% if "video" in media.mime_type %} -  {% trans "Audio" %} +  {% trans "Audio" %} {% endif %} {% if "audio" in media.mime_type %}  {% trans "Video" %} @@ -96,23 +96,19 @@ $(document).ready(function(){ {% if "video" in media.mime_type %}
-
{% elif "audio" in media.mime_type %}
-{% if media.item.related.all %} +{% if media.poster_file %} - {% for related in media.item.related.all %} - {% if related.title == "preview" %} - {% thumbnail related.file "300" as im %} + {% thumbnail media.poster_file "300" as im %} preview {% endthumbnail %} - {% endif %} - {% endfor %} {% else %} snapshot @@ -121,7 +117,7 @@ $(document).ready(function(){
{% endif %} diff --git a/teleforma/templates/teleforma/course_media_transcoded.html b/teleforma/templates/teleforma/course_media_transcoded.html new file mode 100644 index 00000000..5374132a --- /dev/null +++ b/teleforma/templates/teleforma/course_media_transcoded.html @@ -0,0 +1,120 @@ +{% extends "teleforma/course_detail.html" %} +{% load teleforma_tags %} +{% load i18n %} +{% load thumbnail %} + +{% block extra_javascript %} + +{% if "video" in media.mime_type %} + + +{% endif %} + + + +{% endblock extra_javascript %} + +{% block module-action %} +{% if media_transcoded.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 %} +{% endblock module-action %} + +{% block course %} +
+ +
+
+ {% if "video" in media_transcoded.mime_type %} +  {% trans "Audio" %} + {% endif %} + {% if "audio" in media_transcoded.mime_type %} +  {% trans "Video" %} + {% endif %} +
+ + {{ course.title }} - {{ type }}{% if media.conference.session %} - {% trans "Session" %} {{ media.conference.session }}{% endif %} + +
+ +{% if access_error %} +

{{ access_error }}

+

{{ message }}

+ +{% else %} +
+ + +{% if "video" in media_transcoded.mime_type %} +
+ +
+ +{% elif "audio" in media_transcoded.mime_type %} + + +
+{% if media.poster_file %} + + {% thumbnail media.poster_file "300" as im %} + preview + {% endthumbnail %} + +{% else %} + snapshot +{% endif %} + +
+
+ +
+{% endif %} + +
+{% endif %} + +{% block general_info %} +
+
+ +{% if media.conference %} +
{% trans "Course" %}
{{ media.course.title }} - {{ media.course_type }}
+
{% trans "Session" %}
{{ media.conference.session }}
+{% if media.conference.professor %} +
{% trans "Professor" %}
+
{{ media.conference.professor }}
+{% endif %} +{% if media.conference.comment %}
{% trans "Comment" %}
{{ media.conference.comment }}
{% endif %} +
{% trans "Begin date" %}
{{ media.conference.date_begin }}
+
{% trans "End date" %}
{{ media.conference.date_end }}
+{% if media.conference.room %}
{% trans "Room" %}
{{ media.conference.room }}
{% endif %} +{% if user.is_staff or user.is_superuser %} +
{% trans "Mime type" %}
{{ media.mime_type }}
+
{% trans "Date added" %}
{{ media.date_added }}
+
{% 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 %} + +
+
+ +{% endblock general_info %} + +
+{% endblock course %} diff --git a/teleforma/templates/teleforma/course_media_video_embed.html b/teleforma/templates/teleforma/course_media_video_embed.html index 1cad0de5..1ecf5280 100644 --- a/teleforma/templates/teleforma/course_media_video_embed.html +++ b/teleforma/templates/teleforma/course_media_video_embed.html @@ -16,10 +16,10 @@ {% block layout %} -{% if media.item.file and media.is_published or user.is_superuser or user.is_staff %} +{% if media.file and media.is_published or user.is_superuser or user.is_staff %}
-
{% endif %} diff --git a/teleforma/templates/teleforma/courses.html b/teleforma/templates/teleforma/courses.html index aa55b043..3c590eba 100644 --- a/teleforma/templates/teleforma/courses.html +++ b/teleforma/templates/teleforma/courses.html @@ -98,16 +98,12 @@
diff --git a/teleforma/templates/teleforma/inc/media_list_pending.html b/teleforma/templates/teleforma/inc/media_list_pending.html index 2728c4ed..b47e8f7c 100644 --- a/teleforma/templates/teleforma/inc/media_list_pending.html +++ b/teleforma/templates/teleforma/inc/media_list_pending.html @@ -15,16 +15,12 @@
{% trans form.username.label_tag %}

Copyright © {% current_year %} {% organization %} | - TODO : missing link + {% trans "Legal notices" %}

{{ media.item.title }}{{ media.item.description }}{{ media.title }}{{ media.description }} {{ media.date_added }}
- {% if media.item.related.all %} - {% for related in media.item.related.all %} - {% if related.title == "preview" %} - {% thumbnail related.file "168x96" as im %} + {% if media.poster_file %} + {% thumbnail media.poster_file "168x96" as im %}
{% trans 'Click here' %}
{% endthumbnail %} - {% endif %} - {% endfor %} {% else %} {% trans 'Click here' %} {% endif %} @@ -51,10 +47,12 @@ {% elif not media.is_published and user.is_staff %} {% endif %} - {% if media.item.file and user.is_staff %} -
- - + {% 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 %}
- {% if media.item.related.all %} - {% for related in media.item.related.all %} - {% if related.title == "preview" %} - {% thumbnail related.file "168x96" as im %} + {% if media.poster_file %} + {% thumbnail media.poster_file "168x96" as im %}
{% trans 'Click here' %}
{% endthumbnail %} - {% endif %} - {% endfor %} {% else %} {% trans 'Click here' %} {% endif %} @@ -52,8 +48,8 @@ {% elif not media.is_published and user.is_staff %} {% endif %} - {% if media.item.file %} -
+ {% if media.file %} + {% endif %} diff --git a/teleforma/templatetags/teleforma_tags.py b/teleforma/templatetags/teleforma_tags.py index 73bf3110..5eac0a7b 100644 --- a/teleforma/templatetags/teleforma_tags.py +++ b/teleforma/templatetags/teleforma_tags.py @@ -38,6 +38,9 @@ import json from timezones.utils import localtime_for_timezone from django.utils.translation import ugettext_lazy as _ from urlparse import urlparse +from docutils.core import publish_parts +from django.utils.encoding import smart_str, force_unicode +from django.utils.safestring import mark_safe from teleforma.models.core import Document from teleforma.models.crfpa import Course, NewsItem @@ -242,11 +245,9 @@ def show_chat(user): @register.filter def get_audio_id(media): - if media.conference: - medias = media.conference.media.all() - for m in medias: - if 'audio' in m.mime_type: - return m.id + for m in media.transcoded.all(): + if 'audio' in m.mime_type: + return m.id return @register.filter @@ -347,4 +348,33 @@ def organization(): @register.simple_tag def current_year(): - return datetime.datetime.now().strftime("%Y") \ No newline at end of file + return datetime.datetime.now().strftime("%Y") + +@register.filter +def render_flatpage(content): + parsed = "" + path = getattr(content, 'path', '') + if isinstance(content, basestring): + content = content.split("\n") + + for line in content: + match = re.match('^(\.\. *(?:_[^:]*:|(?:\|\w+\|)? *image::) *)([^ ]+) *$', line) + if match: + directive, urlname = match.groups() + line = directive + try: + i = urlname.index('telemeta-') + except ValueError: + i = -1 + if i == 0: + line += reverse(urlname) + elif urlname[:1] != '/': + line += reverse('telemeta-flatpage', args=[path + '/../' + urlname]) + else: + line += urlname + + parsed += line + "\n" + + parts = publish_parts(source=smart_str(parsed), writer_name="html4css1", settings_overrides={}) + return mark_safe('
\n' + force_unicode(parts["html_body"]) + '
') +render_flatpage.is_safe = True \ No newline at end of file diff --git a/teleforma/urls.py b/teleforma/urls.py index 5433ecee..24d9ed41 100644 --- a/teleforma/urls.py +++ b/teleforma/urls.py @@ -47,14 +47,16 @@ htdocs_forma = os.path.dirname(__file__) + '/static/teleforma/' profile_view = CRFPAProfileView() document = DocumentView() media = MediaView() +home_view = HomeView() +media_transcoded = MediaTranscodedView urlpatterns = patterns('', # login / logout + url(r'^login/$', 'django.contrib.auth.views.login', {'template_name': 'teleforma/login.html'}, + name="telemeta-login"), url(r'^accounts/login/$', 'django.contrib.auth.views.login', {'template_name': 'registration/login.html'}, name="teleforma-login"), - url(r'^accounts/login/$', 'django.contrib.auth.views.login', {'template_name': 'teleforma/login.html'}, - name="auth_login"), url(r'^logout/$', 'django.contrib.auth.views.logout', name="teleforma-logout"), # (r'^accounts/register0/$', RegistrationView.as_view(), {'form_class':CustomRegistrationForm}), @@ -94,6 +96,8 @@ urlpatterns = patterns('', # Unauthorized url(r'^unauthorized/$', TemplateView.as_view(template_name="teleforma/unauthorized.html"), name="teleforma-unauthorized"), + # Flat pages + url(r'^pages/(?P.*)$', home_view.render_flatpage, name="teleforma-flatpage"), # Desk url(r'^desk/$', HomeRedirectView.as_view(), name="teleforma-desk"), @@ -102,6 +106,10 @@ urlpatterns = patterns('', url(r'^desk/periods/(?P.*)/courses/(?P.*)/detail/$', CourseView.as_view(), name="teleforma-desk-period-course"), + + url(r'^desk/periods/(?P.*)/medias/transcode/(?P.*)/detail/$', MediaTranscodedView.as_view(), name="teleforma-media-transcoded"), + url(r'^desk/periods/(?P.*)/medias/transcode/(?P.*)/download/$', media_transcoded.download, name="teleforma-media-transcoded-download"), + url(r'^desk/periods/(?P.*)/medias/transcode/(?P.*)/stream/$', media_transcoded.stream, name="teleforma-media-transcoded-stream"), url(r'^desk/periods/(?P.*)/medias/(?P.*)/detail/$', MediaView.as_view(), name="teleforma-media-detail"), url(r'^desk/periods/(?P.*)/medias/(?P.*)/embed/$', MediaViewEmbed.as_view(), name="teleforma-media-embed"), url(r'^desk/periods/(?P.*)/medias/(?P.*)/download/$', media.download, name="teleforma-media-download"), diff --git a/teleforma/views/__init__.py b/teleforma/views/__init__.py index 73dd9d12..f194bee7 100644 --- a/teleforma/views/__init__.py +++ b/teleforma/views/__init__.py @@ -4,3 +4,4 @@ from crfpa import * from appointment import * from payment import * from profile import * +from home import * diff --git a/teleforma/views/core.py b/teleforma/views/core.py index ade46245..1150cd34 100644 --- a/teleforma/views/core.py +++ b/teleforma/views/core.py @@ -73,6 +73,7 @@ from teleforma.forms import * from teleforma.models.appointment import AppointmentPeriod from teleforma.webclass.models import Webclass, WebclassSlot, WebclassRecord from teleforma.decorators import access_required +import pages import jqchat.models from xlwt import Workbook @@ -507,10 +508,10 @@ class CourseView(CourseAccessMixin, DetailView): course = Course.objects.get(code=id) media_list = [] for media in course.media.all(): - if media.is_published and media.item.file and media.conference and 'video' in media.mime_type: - urls = [ {'url': settings.MEDIA_URL + unicode(media.item.file), 'mime_type': media.mime_type} ] - for transcoded in media.item.transcoded.all(): - urls.append({'url':settings.MEDIA_URL + unicode(transcoded.file), 'mime_type': media.mime_type}) + if media.is_published and media.file and media.conference and 'video' in media.mime_type: + urls = [ {'url': settings.MEDIA_URL + unicode(media.file), 'mime_type': media.mime_type} ] + for transcoded in media.transcoded.all(): + urls.append({'url':settings.MEDIA_URL + unicode(transcoded.file), 'mime_type': transcoded.mime_type}) media_list.append({'session': media.conference.session, 'urls': urls, 'poster': media.poster_url()}) return media_list @@ -537,7 +538,6 @@ class MediaView(CourseAccessMixin, DetailView): media.set_mime_type() context['mime_type'] = media.mime_type context['course'] = media.course - context['item'] = media.item context['type'] = media.course_type # context['notes'] = media.notes.all().filter(author=self.request.user) content_type = ContentType.objects.get(app_label="teleforma", model="course") @@ -577,7 +577,57 @@ class MediaView(CourseAccessMixin, DetailView): courses = get_courses(request.user) media = Media.objects.get(id=pk) if get_access(media, courses): - media_path = media.item.file.path + media_path = media.file.path + return serve_media(media_path, content_type=media.mime_type, streaming=streaming) + else: + raise Http404("You don't have access to this media.") + + def download(self, request, period_id, pk): + return self.stream(request, period_id, pk, streaming=False) + +class MediaTranscodedView(CourseAccessMixin, DetailView): + + model = MediaTranscoded + template_name='teleforma/course_media_transcoded.html' + + def get_context_data(self, **kwargs): + context = super(MediaTranscodedView, self).get_context_data(**kwargs) + media_transcoded = self.get_object() + media = media_transcoded.item + if not media_transcoded.mime_type: + media_transcoded.set_mime_type() + context['media'] = media + context['media_transcoded'] = media_transcoded + context['mime_type'] = media_transcoded.mime_type + context['course'] = media.course + context['type'] = media.course_type + # context['notes'] = media.notes.all().filter(author=self.request.user) + content_type = ContentType.objects.get(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, + id=media.course.id) + + access = get_access(media, context['all_courses']) + if not access: + context['access_error'] = access_error + context['message'] = contact_message + + return context + + @method_decorator(login_required) + def dispatch(self, *args, **kwargs): + return super(MediaTranscodedView, self).dispatch(*args, **kwargs) + + def stream(self, request, period_id, pk, streaming=True): + courses = get_courses(request.user) + media = MediaTranscoded.objects.get(id=pk) + if get_access(media, courses): + media_path = media.file.path return serve_media(media_path, content_type=media.mime_type, streaming=streaming) else: raise Http404("You don't have access to this media.") diff --git a/teleforma/views/home.py b/teleforma/views/home.py new file mode 100644 index 00000000..b549b43c --- /dev/null +++ b/teleforma/views/home.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +# Copyright (C) 2007-2010 Samalyse SARL +# Copyright (C) 2010-2012 Parisson SARL + +# This software is a computer program whose purpose is to backup, analyse, +# transcode and stream any audio content with its metadata over a web frontend. + +# 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. + +# Authors: Olivier Guilyardi +# Guillaume Pellerin + +import pages +from django.shortcuts import render, redirect +from django.contrib import auth +from django.http import HttpResponse + +class HomeView(object): + """Provide general web UI methods""" + + def render_flatpage(self, request, path): + try: + content = pages.get_page_content(request, path) + except pages.MalformedPagePath: + return redirect(request.path + '/') + + if isinstance(content, pages.PageAttachment): + return HttpResponse(content, content.mimetype()) + else: + return render(request, 'teleforma/flatpage.html', {'page_content': content }) + + def logout(self, request): + auth.logout(request) + return redirect('teleforma-home') + diff --git a/teleforma/views/pages.py b/teleforma/views/pages.py new file mode 100644 index 00000000..f805f5bd --- /dev/null +++ b/teleforma/views/pages.py @@ -0,0 +1,118 @@ +from django.conf import settings +import re +import os +import mimetypes +import teleforma + +PAGES_ROOT = os.path.join(os.path.dirname(teleforma.__file__), 'pages') + +class PageTextContent(object): + def __init__(self, filename, path): + self.filename = filename + self.path = path + + def __iter__(self): + file = open(self.filename, 'r') + for line in file: + yield line.rstrip('\r\n') + file.close() + + def __unicode__(self): + file = open(self.filename, 'r') + data = file.read() + file.close() + return data + +class PageAttachment(object): + def __init__(self, filename, path): + self.filename = filename + self.path = path + + def mimetype(self): + type, encoding = mimetypes.guess_type(self.filename) + return type + + def __iter__(self): + file = open(self.filename, 'rb') + buffer_size = 0x10000 + while True: + chunk = file.read(buffer_size) + yield chunk + if len(chunk) < buffer_size: + break + + file.close() + +def language_code(request=None): + code = (request and getattr(request, 'LANGUAGE_CODE', None)) or settings.LANGUAGE_CODE + cut = re.split('[_-]', code) + code = cut[0] + return code.lower() + +def project_dir(): + import settings as settings_mod + if '__init__.py' in settings_mod.__file__: + p = os.path.dirname(settings_mod.__file__) + else: + p = settings_mod.__file__ + project_directory, settings_filename = os.path.split(p) + if project_directory == os.curdir or not project_directory: + project_directory = os.getcwd() + + return project_directory + +def resolve_page_file(root, relative_path, ignore_slash_issue=False): + root = os.path.realpath(root) + filename = None + current = root + is_attachment = False + for node in relative_path.split('/'): + if not node: + continue + current = os.path.join(current, node) + rst = current + '.rst' + if os.path.isfile(rst): + filename = rst + break + elif os.path.isfile(current): + filename = current + is_attachment = True + elif not os.path.isdir(current): + break + + if not filename and os.path.isdir(current): + rst = os.path.join(current, 'index.rst') + if os.path.isfile(rst): + if not ignore_slash_issue and relative_path[-1:] != '/': + raise MalformedPagePath("The relative page os.path must end with a slash when " + "resolving an implicit directory index") + filename = rst + + if filename: + filename = os.path.realpath(filename) + if filename.index(root) != 0: + filename = None + + if filename: + if is_attachment: + return PageAttachment(filename, relative_path) + else: + return PageTextContent(filename, relative_path) + + return None + +def get_page_content(request, relative_path, ignore_slash_issue=False): + lang = language_code(request) + userroot = os.path.join(project_dir(), 'telemeta-pages') + rootlist = [os.path.join(userroot, lang), os.path.join(userroot, 'default'), + os.path.join(PAGES_ROOT, lang), os.path.join(PAGES_ROOT, 'default')] + for root in rootlist: + content = resolve_page_file(root, relative_path, ignore_slash_issue=ignore_slash_issue) + if content: + return content + + return None + +class MalformedPagePath(Exception): + pass + diff --git a/teleforma/views/profile.py b/teleforma/views/profile.py index 5e5015d7..0a077ff1 100644 --- a/teleforma/views/profile.py +++ b/teleforma/views/profile.py @@ -1,44 +1,44 @@ -# -*- coding: utf-8 -*- -# Copyright (C) 2007-2010 Samalyse SARL -# Copyright (C) 2010-2012 Parisson SARL +# # -*- coding: utf-8 -*- +# # Copyright (C) 2007-2010 Samalyse SARL +# # Copyright (C) 2010-2012 Parisson SARL -# This software is a computer program whose purpose is to backup, analyse, -# transcode and stream any audio content with its metadata over a web frontend. +# # This software is a computer program whose purpose is to backup, analyse, +# # transcode and stream any audio content with its metadata over a web frontend. -# 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". +# # 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. +# # 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. +# # 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. +# # The fact that you are presently reading this means that you have had +# # knowledge of the CeCILL license and that you accept its terms. -# Authors: Olivier Guilyardi -# Guillaume Pellerin +# # Authors: Olivier Guilyardi +# # Guillaume Pellerin from django.contrib.auth.models import User from django.contrib.auth.forms import UserChangeForm from django.utils.decorators import method_decorator from django.contrib.auth.decorators import login_required -from teleforma.models.profile import UserProfile +from teleforma.models.crfpa import Profile as UserProfile from teleforma.forms import UserProfileForm class ProfileView(object): diff --git a/wsgi.py b/wsgi.py new file mode 100644 index 00000000..e69de29b