From 530b99b1fe65444255a202cd431c6f6069edff04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89lie=20Bouttier?= Date: Thu, 24 Nov 2016 00:39:19 +0100 Subject: [PATCH] talk materials (file upload) --- locale/fr/LC_MESSAGES/django.mo | Bin 15336 -> 15561 bytes locale/fr/LC_MESSAGES/django.po | 127 ++++++++++-------- ponyconf/templates/_form.html | 2 +- proposals/forms.py | 3 +- proposals/migrations/0029_talk_materials.py | 20 +++ proposals/models.py | 11 ++ .../templates/proposals/talk_detail.html | 4 + proposals/templates/proposals/talk_edit.html | 2 +- proposals/views.py | 3 +- 9 files changed, 109 insertions(+), 63 deletions(-) create mode 100644 proposals/migrations/0029_talk_materials.py diff --git a/locale/fr/LC_MESSAGES/django.mo b/locale/fr/LC_MESSAGES/django.mo index 82c3f9c37681a22ae710dc2344c0278d9c122482..fa6ba254c7211806c3092e467c58de30c3dd3a41 100644 GIT binary patch delta 5162 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\n" "Language-Team: LANGUAGE \n" @@ -93,7 +93,7 @@ msgstr "Licence vidéo" #: accounts/models.py:81 #: accounts/templates/accounts/participant_details.html:71 -#: proposals/models.py:156 proposals/templates/proposals/talk_detail.html:94 +#: proposals/models.py:161 proposals/templates/proposals/talk_detail.html:98 msgid "Notes" msgstr "Notes" @@ -470,7 +470,7 @@ msgstr "S’inscrire" msgid "Powered by" msgstr "Propulsé par" -#: ponyconf/templates/staff.html:9 proposals/models.py:154 +#: ponyconf/templates/staff.html:9 proposals/models.py:159 #: proposals/templates/proposals/talk_detail.html:26 #: proposals/templates/proposals/talk_list.html:48 #: proposals/templates/proposals/topic_list.html:9 @@ -482,9 +482,9 @@ msgstr "Thèmes" msgid "Tracks" msgstr "Sessions" -#: ponyconf/templates/staff.html:12 proposals/models.py:149 +#: ponyconf/templates/staff.html:12 proposals/models.py:154 #: proposals/templates/proposals/speaker_list.html:9 -#: proposals/templates/proposals/talk_detail.html:68 +#: proposals/templates/proposals/talk_detail.html:72 #: proposals/templates/proposals/talk_list.html:47 msgid "Speakers" msgstr "Orateurs" @@ -498,135 +498,144 @@ msgstr "Bénévoles" msgid "Conference" msgstr "Conférence" -#: proposals/forms.py:45 +#: proposals/forms.py:46 msgid "Should be less than 255 characters" msgstr "Texte court, moins de 255 caractères" -#: proposals/forms.py:46 +#: proposals/forms.py:47 msgid "If you want to add some precisions for the organizers." msgstr "Si vous souhaitez apporter des précisions à l'équipe d'organisation." -#: proposals/forms.py:71 +#: proposals/forms.py:72 msgid "Filter talks you already / not yet voted for" msgstr "" "Filtrer les propositions pour lesquelles vous avez déjà voté / pas encore " "voté" -#: proposals/forms.py:72 +#: proposals/forms.py:73 msgid "Filter talks already / not yet affected to a room" msgstr "Filtrer les exposés déjà / pas encore affectées à une salle" -#: proposals/forms.py:73 +#: proposals/forms.py:74 msgid "Filter talks already / not yet scheduled" msgstr "Filtrer les exposés déjà / pas encore planifiées" -#: proposals/forms.py:88 +#: proposals/forms.py:89 msgid "Accept talk?" msgstr "Accepter la proposition ?" -#: proposals/forms.py:89 +#: proposals/forms.py:90 msgid "Assign to a track" msgstr "Assigner à une session" -#: proposals/forms.py:90 +#: proposals/forms.py:91 msgid "Put in a room" msgstr "Assigner à une salle" -#: proposals/forms.py:192 +#: proposals/forms.py:193 msgid "Name or nickname" msgstr "Nom ou pseudo" -#: proposals/forms.py:193 +#: proposals/forms.py:194 msgid "How much is 3+4?" msgstr "Combien font 3+4 ?" -#: proposals/forms.py:193 +#: proposals/forms.py:194 msgid "Anti-bot" msgstr "Anti-robot" -#: proposals/forms.py:198 +#: proposals/forms.py:199 msgid "Please re-do the maths." msgstr "Refaites les calculs." -#: proposals/models.py:51 proposals/models.py:74 proposals/models.py:131 +#: proposals/models.py:52 proposals/models.py:75 proposals/models.py:132 #: volunteers/models.py:12 msgid "Name" msgstr "Nom" -#: proposals/models.py:53 proposals/models.py:76 proposals/models.py:153 -#: proposals/templates/proposals/talk_detail.html:64 volunteers/models.py:14 +#: proposals/models.py:54 proposals/models.py:77 proposals/models.py:158 +#: proposals/templates/proposals/talk_detail.html:68 volunteers/models.py:14 msgid "Description" msgstr "Description" -#: proposals/models.py:55 +#: proposals/models.py:56 msgid "Managers" msgstr "Responsables" -#: proposals/models.py:77 +#: proposals/models.py:78 msgid "Destination track" msgstr "Session de destination" -#: proposals/models.py:79 +#: proposals/models.py:80 msgid "Reviewers" msgstr "Responsables" -#: proposals/models.py:95 +#: proposals/models.py:96 msgid "Default duration (min)" msgstr "Durée par défaut (min)" -#: proposals/models.py:96 +#: proposals/models.py:97 msgid "Color on program" msgstr "Couleur sur le programme" -#: proposals/models.py:97 +#: proposals/models.py:98 msgid "Label on program" msgstr "Label dans le xml du programme" -#: proposals/models.py:138 +#: proposals/models.py:139 msgid "Email" msgstr "E-mail" -#: proposals/models.py:150 proposals/templates/proposals/talk_list.html:45 +#: proposals/models.py:155 proposals/templates/proposals/talk_list.html:45 msgid "Title" msgstr "Titre" -#: proposals/models.py:150 +#: proposals/models.py:155 msgid "After submission, title can only be changed by the staff." msgstr "" "Après soumission, le titre ne peut être modifié que par l’équipe " "d’organisation." -#: proposals/models.py:152 +#: proposals/models.py:157 msgid "Abstract" msgstr "Résumé" -#: proposals/models.py:154 +#: proposals/models.py:159 msgid "The topics can not be changed after submission." msgstr "Les thèmes ne peuvent pas être modifiés après soumission." -#: proposals/models.py:155 proposals/templates/proposals/talk_detail.html:33 -#: proposals/templates/proposals/talk_detail.html:81 +#: proposals/models.py:160 proposals/templates/proposals/talk_detail.html:33 +#: proposals/templates/proposals/talk_detail.html:85 #: proposals/templates/proposals/talk_list.html:49 #: proposals/templates/proposals/track_form.html:14 msgid "Track" msgstr "Session" -#: proposals/models.py:157 proposals/templates/proposals/talk_list.html:46 +#: proposals/models.py:162 proposals/templates/proposals/talk_list.html:46 msgid "Intervention kind" msgstr "Type d’intervention" -#: proposals/models.py:160 +#: proposals/models.py:165 msgid "Duration (min)" msgstr "Durée (min)" -#: proposals/models.py:164 proposals/templates/proposals/talk_detail.html:123 +#: proposals/models.py:169 proposals/templates/proposals/talk_detail.html:127 msgid "Attendees" msgstr "Inscrits" -#: proposals/models.py:165 +#: proposals/models.py:170 msgid "Max. number of attendees" msgstr "Nombre maximum d’inscrits" +#: proposals/models.py:171 proposals/templates/proposals/talk_detail.html:60 +msgid "Materials" +msgstr "Supports" + +#: proposals/models.py:172 +msgid "" +"You can use this field to share some materials related to your intervention." +msgstr "Vous pouvez utiliser ce champs pour partager les supports de votre intervention." + #: proposals/signals.py:28 msgid "conference (short)" msgstr "conférence (courte)" @@ -814,7 +823,7 @@ msgid "No topics." msgstr "Aucun thème." #: proposals/templates/proposals/talk_detail.html:37 -#: proposals/templates/proposals/talk_detail.html:82 +#: proposals/templates/proposals/talk_detail.html:86 msgid "No assigned yet." msgstr "Pas encore assigné." @@ -831,52 +840,52 @@ msgstr "Inscriptions" msgid "required but unlimited" msgstr "requis mais non limité" -#: proposals/templates/proposals/talk_detail.html:66 +#: proposals/templates/proposals/talk_detail.html:70 msgid "No description provided." msgstr "Aucune description fournie." -#: proposals/templates/proposals/talk_detail.html:75 +#: proposals/templates/proposals/talk_detail.html:79 msgid "No speakers." msgstr "Aucun orateur." -#: proposals/templates/proposals/talk_detail.html:86 +#: proposals/templates/proposals/talk_detail.html:90 msgid "Assign to" msgstr "Assigner à" -#: proposals/templates/proposals/talk_detail.html:96 +#: proposals/templates/proposals/talk_detail.html:100 msgid "No notes." msgstr "Aucune note." -#: proposals/templates/proposals/talk_detail.html:100 +#: proposals/templates/proposals/talk_detail.html:104 msgid "Moderation" msgstr "Modération" -#: proposals/templates/proposals/talk_detail.html:102 +#: proposals/templates/proposals/talk_detail.html:106 #: proposals/templates/proposals/talk_list.html:50 msgid "Status" msgstr "Statut" -#: proposals/templates/proposals/talk_detail.html:107 +#: proposals/templates/proposals/talk_detail.html:111 msgid "Vote" msgstr "Vote" -#: proposals/templates/proposals/talk_detail.html:116 +#: proposals/templates/proposals/talk_detail.html:120 msgid "vote" msgstr "vote" -#: proposals/templates/proposals/talk_detail.html:116 +#: proposals/templates/proposals/talk_detail.html:120 msgid "average:" msgstr "moyenne :" -#: proposals/templates/proposals/talk_detail.html:130 +#: proposals/templates/proposals/talk_detail.html:134 msgid "No attendees yet." msgstr "Il n’y a pas encore d’inscrit." -#: proposals/templates/proposals/talk_detail.html:135 +#: proposals/templates/proposals/talk_detail.html:139 msgid "Messages" msgstr "Messages" -#: proposals/templates/proposals/talk_detail.html:136 +#: proposals/templates/proposals/talk_detail.html:140 msgid "These messages are for organization team only." msgstr "Ces messages sont à destination de la team d’organisation seulement." @@ -966,39 +975,39 @@ msgid_plural "Note: the room %(room)s has %(capacity)s seats." msgstr[0] "Note : la salle %(room)s a %(capacity)s place." msgstr[1] "Note : la salle %(room)s a %(capacity)s places." -#: proposals/views.py:211 +#: proposals/views.py:212 msgid "Talk modified successfully!" msgstr "Exposé modifié avec succès !" -#: proposals/views.py:217 +#: proposals/views.py:218 msgid "Talk proposed successfully!" msgstr "Exposé proposé avec succès !" -#: proposals/views.py:234 +#: proposals/views.py:235 msgid "Talk assigned to track successfully!" msgstr "Exposé assigné à la session avec succès !" -#: proposals/views.py:307 +#: proposals/views.py:308 msgid "Vote successfully created" msgstr "A voté !" -#: proposals/views.py:307 +#: proposals/views.py:308 msgid "Vote successfully updated" msgstr "Vote mis à jour" -#: proposals/views.py:333 +#: proposals/views.py:334 msgid "Decision taken in account" msgstr "Décision enregistrée" -#: proposals/views.py:431 +#: proposals/views.py:432 msgid "Unregistered :-(" msgstr "Vous avez été désinscrit :-(" -#: proposals/views.py:433 +#: proposals/views.py:434 msgid "Already registered!" msgstr "Vous êtes déjà inscrit !" -#: proposals/views.py:438 +#: proposals/views.py:439 msgid "Registered!" msgstr "Vous avez été inscrit !" diff --git a/ponyconf/templates/_form.html b/ponyconf/templates/_form.html index 49f09e9..c9ddd26 100644 --- a/ponyconf/templates/_form.html +++ b/ponyconf/templates/_form.html @@ -1,5 +1,5 @@ {% load bootstrap3 i18n %} -
+ {% csrf_token %} {% block beforeform %}{% endblock %} {% if form %} diff --git a/proposals/forms.py b/proposals/forms.py index 6d4d81a..2f1f520 100644 --- a/proposals/forms.py +++ b/proposals/forms.py @@ -28,6 +28,7 @@ class TalkForm(forms.ModelForm): super(TalkForm, self).__init__(*args, **kwargs) self.fields['topics'].queryset = Topic.objects.filter(site=site) self.fields['track'].queryset = Track.objects.filter(site=site) + self.fields['materials'].required = False if staff: self.fields['event'].queryset = Event.objects.filter(site=site) else: @@ -39,7 +40,7 @@ class TalkForm(forms.ModelForm): class Meta: model = Talk - fields = ['title', 'abstract', 'description', 'topics', 'track', 'notes', 'event', 'speakers', 'duration', 'start_date', 'room', 'registration_required', 'attendees_limit'] + fields = ['title', 'abstract', 'description', 'topics', 'track', 'notes', 'event', 'speakers', 'materials', 'duration', 'start_date', 'room', 'registration_required', 'attendees_limit'] widgets = {'topics': forms.CheckboxSelectMultiple(), 'speakers': Select2TagWidget()} help_texts = { 'abstract': _('Should be less than 255 characters'), diff --git a/proposals/migrations/0029_talk_materials.py b/proposals/migrations/0029_talk_materials.py new file mode 100644 index 0000000..525e37a --- /dev/null +++ b/proposals/migrations/0029_talk_materials.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10 on 2016-11-23 22:36 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('proposals', '0028_auto_20161113_2204'), + ] + + operations = [ + migrations.AddField( + model_name='talk', + name='materials', + field=models.FileField(help_text='You can use this field to share some materials related to your intervention.', null=True, upload_to='', verbose_name='Materials'), + ), + ] diff --git a/proposals/models.py b/proposals/models.py index 9455059..c06a0b4 100644 --- a/proposals/models.py +++ b/proposals/models.py @@ -1,5 +1,6 @@ from enum import IntEnum from datetime import timedelta +from os.path import join, basename from django.contrib.auth.models import User from django.contrib.sites.models import Site @@ -141,6 +142,10 @@ class Attendee(PonyConfModel): return self.get_name() +def talk_materials_destination(talk, filename): + return join(talk.site.name, talk.slug, filename) + + class Talk(PonyConfModel): site = models.ForeignKey(Site, on_delete=models.CASCADE) @@ -163,6 +168,8 @@ class Talk(PonyConfModel): registration_required = models.BooleanField(default=False) attendees = models.ManyToManyField(Attendee, verbose_name=_('Attendees')) attendees_limit = models.PositiveIntegerField(default=0, verbose_name=_('Max. number of attendees')) + materials = models.FileField(null=True, upload_to=talk_materials_destination, verbose_name=_('Materials'), + help_text=_('You can use this field to share some materials related to your intervention.')) class Meta: ordering = ('title',) @@ -232,6 +239,10 @@ class Talk(PonyConfModel): def dtend(self): return self.end_date.strftime('%Y%m%dT%H%M%SZ') + @property + def materials_name(self): + return basename(self.materials.name) + class Meta: ordering = ('event__id',) diff --git a/proposals/templates/proposals/talk_detail.html b/proposals/templates/proposals/talk_detail.html index 2c6f58d..62e23c1 100644 --- a/proposals/templates/proposals/talk_detail.html +++ b/proposals/templates/proposals/talk_detail.html @@ -56,6 +56,10 @@
{% trans "Registrations" %}
{% if talk.attendees_limit %}{{ talk.attendees.count }} / {{ talk.attendees_limit }}{% else %}{% trans "required but unlimited" %}{% endif %}
{% endif %} + {% if talk.materials %} +
{% trans "Materials" %}
+
{{ talk.materials_name }}
+ {% endif %} diff --git a/proposals/templates/proposals/talk_edit.html b/proposals/templates/proposals/talk_edit.html index dbc2110..4091a7b 100644 --- a/proposals/templates/proposals/talk_edit.html +++ b/proposals/templates/proposals/talk_edit.html @@ -9,7 +9,7 @@

{% if talk %}{% trans "Edit a talk" %}{% else %}{% trans "Propose a talk" %}{% endif %}

-{% include "_form.html" %} +{% include "_form.html" with multipart=True %} {% endblock %} diff --git a/proposals/views.py b/proposals/views.py index d0f6767..3b8ce7c 100644 --- a/proposals/views.py +++ b/proposals/views.py @@ -191,7 +191,7 @@ def talk_edit(request, talk=None): if not is_orga(request, request.user) and not conf.cfp_is_open(): raise PermissionDenied staff = talk.is_moderable_by(request.user) if talk else is_orga(request, request.user) - form = TalkForm(request.POST or None, instance=talk, site=site, staff=staff) + form = TalkForm(request.POST or None, request.FILES or None, instance=talk, site=site, staff=staff) if talk: form.fields['topics'].disabled = True if 'duration' in form.fields and talk.event.duration: @@ -202,6 +202,7 @@ def talk_edit(request, talk=None): "Note: the room %(room)s has %(capacity)s seats.", talk.room.capacity) % {'room': talk.room.name, 'capacity': talk.room.capacity} else: + form.fields.pop('materials') form.fields['speakers'].initial = [request.user] if request.method == 'POST' and form.is_valid(): if hasattr(talk, 'id'):