From 5bab52981cfe4ee517e0d701c54ab96cb2f55b8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89lie=20Bouttier?= Date: Sat, 4 Nov 2017 20:11:50 +0100 Subject: [PATCH] suggest to add already known co-speaker --- cfp/models.py | 4 + cfp/templates/cfp/proposal_speaker_form.html | 22 ++- cfp/templates/cfp/proposal_talk_details.html | 8 +- cfp/urls.py | 17 +-- cfp/views.py | 30 +++-- locale/fr/LC_MESSAGES/django.mo | Bin 20632 -> 21053 bytes locale/fr/LC_MESSAGES/django.po | 134 +++++++++++-------- 7 files changed, 131 insertions(+), 84 deletions(-) diff --git a/cfp/models.py b/cfp/models.py index 0a4fada..f35d182 100644 --- a/cfp/models.py +++ b/cfp/models.py @@ -129,6 +129,10 @@ class Participant(PonyConfModel): def __str__(self): return str(self.name) + @property + def co_speaker_set(self): + return Participant.objects.filter(site=self.site, talk__in=self.talk_set.values_list('pk')).exclude(pk=self.pk).order_by('name').distinct() + @property def accepted_talk_set(self): return self.talk_set.filter(accepted=True) diff --git a/cfp/templates/cfp/proposal_speaker_form.html b/cfp/templates/cfp/proposal_speaker_form.html index 13e2a82..baa8090 100644 --- a/cfp/templates/cfp/proposal_speaker_form.html +++ b/cfp/templates/cfp/proposal_speaker_form.html @@ -30,13 +30,23 @@
-
- {% csrf_token %} - {{ form|crispy }} -
- + {% if co_speaker_candidates %} +
+ {% trans "You may want to add one of the following speakers:" %} + {% for spkr in co_speaker_candidates %} + {% if forloop.first %}{% endif %} + {% endfor %}
- + {% endif %} +
+ {% csrf_token %} + {{ form|crispy }} +
+ +
+
{% endblock %} diff --git a/cfp/templates/cfp/proposal_talk_details.html b/cfp/templates/cfp/proposal_talk_details.html index 9c2878a..5707479 100644 --- a/cfp/templates/cfp/proposal_talk_details.html +++ b/cfp/templates/cfp/proposal_talk_details.html @@ -55,7 +55,13 @@ {% if forloop.first %}{% endif %} {% endfor %} diff --git a/cfp/urls.py b/cfp/urls.py index e15e192..41067d8 100644 --- a/cfp/urls.py +++ b/cfp/urls.py @@ -10,14 +10,15 @@ urlpatterns = [ url(r'^cfp/(?P[\w\-]+)/$', views.proposal_dashboard, name='proposal-dashboard'), url(r'^cfp/(?P[\w\-]+)/profile/$', views.proposal_speaker_edit, name='proposal-profile-edit'), url(r'^cfp/(?P[\w\-]+)/talk/add/$', views.proposal_talk_edit, name='proposal-talk-add'), - url(r'^cfp/(?P[\w\-]+)/talk/(?P[\w\-]+)/$', views.proposal_talk_details, name='proposal-talk-details'), - url(r'^cfp/(?P[\w\-]+)/talk/(?P[\w\-]+)/edit/$', views.proposal_talk_edit, name='proposal-talk-edit'), - url(r'^cfp/(?P[\w\-]+)/talk/(?P[\w\-]+)/speaker/add/$', views.proposal_speaker_edit, name='proposal-speaker-add'), - url(r'^cfp/(?P[\w\-]+)/talk/(?P[\w\-]+)/confirm/$', views.proposal_talk_acknowledgment, {'confirm': True}, name='proposal-talk-confirm'), - url(r'^cfp/(?P[\w\-]+)/talk/(?P[\w\-]+)/desist/$', views.proposal_talk_acknowledgment, {'confirm': False}, name='proposal-talk-desist'), - #url(r'^cfp/(?P[\w\-]+)/talk/(?P[\w\-]+)/speaker/(?P[\w\-]+)/$', views.proposal_speaker_details, name='proposal-speaker-details'), - url(r'^cfp/(?P[\w\-]+)/talk/(?P[\w\-]+)/speaker/(?P[\w\-]+)/edit/$', views.proposal_speaker_edit, name='proposal-speaker-edit'), - url(r'^cfp/(?P[\w\-]+)/talk/(?P[\w\-]+)/speaker/(?P[\w\-]+)/remove/$', views.proposal_speaker_remove, name='proposal-speaker-remove'), + url(r'^cfp/(?P[\w\-]+)/talk/(?P[0-9]+)/$', views.proposal_talk_details, name='proposal-talk-details'), + url(r'^cfp/(?P[\w\-]+)/talk/(?P[0-9]+)/edit/$', views.proposal_talk_edit, name='proposal-talk-edit'), + url(r'^cfp/(?P[\w\-]+)/talk/(?P[0-9]+)/speaker/add/$', views.proposal_speaker_edit, name='proposal-speaker-add'), + url(r'^cfp/(?P[\w\-]+)/talk/(?P[0-9]+)/speaker/add/(?P[0-9]+)/$', views.proposal_speaker_add, name='proposal-speaker-add-existing'), + #url(r'^cfp/(?P[\w\-]+)/talk/(?P[0-9]+)/speaker/(?P[0-9]+)/$', views.proposal_speaker_details, name='proposal-speaker-details'), + url(r'^cfp/(?P[\w\-]+)/talk/(?P[0-9]+)/speaker/(?P[0-9]+)/edit/$', views.proposal_speaker_edit, name='proposal-speaker-edit'), + url(r'^cfp/(?P[\w\-]+)/talk/(?P[0-9]+)/speaker/(?P[0-9]+)/remove/$', views.proposal_speaker_remove, name='proposal-speaker-remove'), + url(r'^cfp/(?P[\w\-]+)/talk/(?P[0-9]+)/confirm/$', views.proposal_talk_acknowledgment, {'confirm': True}, name='proposal-talk-confirm'), + url(r'^cfp/(?P[\w\-]+)/talk/(?P[0-9]+)/desist/$', views.proposal_talk_acknowledgment, {'confirm': False}, name='proposal-talk-desist'), # Backward compatibility url(r'^cfp/(?P[\w\-]+)/speaker/add/$', views.talk_proposal_speaker_edit, name='talk-proposal-speaker-add'), url(r'^cfp/(?P[\w\-]+)/speaker/(?P[\w\-]+)/$', views.talk_proposal_speaker_edit, name='talk-proposal-speaker-edit'), diff --git a/cfp/views.py b/cfp/views.py index daa3188..0e7d2cf 100644 --- a/cfp/views.py +++ b/cfp/views.py @@ -319,21 +319,15 @@ def proposal_talk_acknowledgment(request, speaker, talk_id, confirm): @speaker_required def proposal_speaker_edit(request, speaker, talk_id=None, co_speaker_id=None): + talk, co_speaker, co_speaker_candidates = None, None, None if talk_id: talk = get_object_or_404(Talk, site=request.conference.site, speakers__pk=speaker.pk, pk=talk_id) if co_speaker_id: co_speaker = get_object_or_404(Participant, site=request.conference.site, talk__pk=talk.pk, pk=co_speaker_id) else: - co_speaker = None - else: - talk = None - co_speaker = None + co_speaker_candidates = speaker.co_speaker_set.exclude(pk__in=talk.speakers.values_list('pk')) form = ParticipantForm(request.POST or None, conference=request.conference, instance=co_speaker if talk else speaker) if request.method == 'POST' and form.is_valid(): - # TODO: Allow to add a co-speaker which already exists. - # This should be automatically allowed if the speaker already have a talk in common with the co-speaker. - # Otherwise, we should send an speaker request to the other user OR allow the other user to join the talk with his token. - # This last requirements in planned for v3. edited_speaker = form.save() if talk: talk.speakers.add(edited_speaker) @@ -345,15 +339,31 @@ def proposal_speaker_edit(request, speaker, talk_id=None, co_speaker_id=None): 'speaker': speaker, 'talk': talk, 'co_speaker': co_speaker, + 'co_speaker_candidates': co_speaker_candidates, 'form': form, }) +@speaker_required +def proposal_speaker_add(request, speaker, talk_id, speaker_id): + talk = get_object_or_404(Talk, site=request.conference.site, speakers__pk=speaker.pk, pk=talk_id) + co_speaker = get_object_or_404(Participant, pk__in=speaker.co_speaker_set.values_list('pk')) + talk.speakers.add(co_speaker) + messages.success(request, _('Co-speaker successfully added to the talk.')) + return redirect(reverse('proposal-talk-details', kwargs=dict(speaker_token=speaker.token, talk_id=talk_id))) + + +# TODO: ask for confirmation (with POST request needed) @speaker_required def proposal_speaker_remove(request, speaker, talk_id, co_speaker_id): talk = get_object_or_404(Talk, site=request.conference.site, speakers__pk=speaker.pk, pk=talk_id) - co_speaker = get_object_or_404(Participant, site=request.conference.site, talk_set__pk=talk.pk, pk=co_speaker_id) - return redirect(reverse('proposal-speaker-details', kwargs=dict())) + co_speaker = get_object_or_404(Participant, site=request.conference.site, talk__pk=talk.pk, pk=co_speaker_id) + # prevent speaker from removing his/her self + if co_speaker.pk == speaker.pk: + raise PermissionDenied + talk.speakers.remove(co_speaker) + messages.success(request, _('Co-speaker successfully removed from the talk.')) + return redirect(reverse('proposal-talk-details', kwargs=dict(speaker_token=speaker.token, talk_id=talk_id))) # BACKWARD COMPATIBILITY diff --git a/locale/fr/LC_MESSAGES/django.mo b/locale/fr/LC_MESSAGES/django.mo index 6a3a1c50613ce61f3c9a438e8fb55d61ecfeffe5..731ab28f779e900cd0b78be40671dc52cf19180a 100644 GIT binary patch delta 6179 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 V+=QCU;g>@i+nc(*3(`kS`Zo}c+~xoP delta 5766 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 E0Ri(+DF6Tf diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po index 74b942e..e40e7a9 100644 --- a/locale/fr/LC_MESSAGES/django.po +++ b/locale/fr/LC_MESSAGES/django.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2017-11-04 14:58+0000\n" -"PO-Revision-Date: 2017-11-04 15:58+0100\n" +"POT-Creation-Date: 2017-11-04 19:09+0000\n" +"PO-Revision-Date: 2017-11-04 20:11+0100\n" "Last-Translator: \n" "Language-Team: \n" "Language: fr\n" @@ -34,15 +34,15 @@ msgstr "Décliné" msgid "Waiting" msgstr "En attente" -#: cfp/forms.py:29 cfp/forms.py:130 cfp/forms.py:237 cfp/models.py:353 +#: cfp/forms.py:29 cfp/forms.py:130 cfp/forms.py:237 cfp/models.py:357 msgid "Confirmed" msgstr "Confirmé" -#: cfp/forms.py:30 cfp/models.py:355 +#: cfp/forms.py:30 cfp/models.py:359 msgid "Cancelled" msgstr "Annulé" -#: cfp/forms.py:62 cfp/models.py:448 +#: cfp/forms.py:62 cfp/models.py:452 msgid "Activity" msgstr "Activité" @@ -65,13 +65,13 @@ msgstr "Catégorie" msgid "Title" msgstr "Titre" -#: cfp/forms.py:108 cfp/models.py:147 cfp/models.py:443 -#: cfp/templates/cfp/proposal_talk_details.html:67 +#: cfp/forms.py:108 cfp/models.py:151 cfp/models.py:447 +#: cfp/templates/cfp/proposal_talk_details.html:73 #: cfp/templates/cfp/staff/talk_details.html:64 msgid "Description" msgstr "Description" -#: cfp/forms.py:109 cfp/models.py:111 cfp/models.py:424 +#: cfp/forms.py:109 cfp/models.py:111 cfp/models.py:428 #: cfp/templates/cfp/staff/participant_details.html:19 #: cfp/templates/cfp/staff/talk_details.html:78 #: cfp/templates/cfp/staff/volunteer_details.html:20 @@ -82,7 +82,7 @@ msgstr "Notes" msgid "Visible by speakers" msgstr "Visible par les orateurs" -#: cfp/forms.py:136 cfp/forms.py:243 cfp/models.py:310 +#: cfp/forms.py:136 cfp/forms.py:243 cfp/models.py:314 #: cfp/templates/cfp/staff/talk_details.html:21 #: cfp/templates/cfp/staff/talk_list.html:46 #: cfp/templates/cfp/staff/track_form.html:14 @@ -120,7 +120,7 @@ msgstr "Programmé" msgid "Filter talks already / not yet scheduled" msgstr "Filtrer les exposés déjà / pas encore planifiées" -#: cfp/forms.py:160 cfp/models.py:327 +#: cfp/forms.py:160 cfp/models.py:331 #: cfp/templates/cfp/staff/talk_details.html:54 msgid "Materials" msgstr "Supports" @@ -157,7 +157,7 @@ msgstr "Ajouter une étiquette" msgid "Put in a room" msgstr "Assigner à une salle" -#: cfp/forms.py:259 cfp/models.py:419 +#: cfp/forms.py:259 cfp/models.py:423 #: cfp/templates/cfp/staff/volunteer_details.html:11 #: cfp/templates/cfp/staff/volunteer_list.html:30 msgid "Email" @@ -242,7 +242,7 @@ msgstr "" "L’adresse de réponse doit être une chaine de texte formatable avec un " "argument « token » (e.g. ponyconf+{token}@exemple.com)." -#: cfp/models.py:99 cfp/models.py:145 cfp/models.py:197 cfp/models.py:441 +#: cfp/models.py:99 cfp/models.py:149 cfp/models.py:201 cfp/models.py:445 #: cfp/templates/cfp/staff/participant_list.html:35 #: cfp/templates/cfp/staff/volunteer_list.html:29 msgid "Name" @@ -277,12 +277,12 @@ msgstr "Facebook" msgid "Mastodon" msgstr "Mastodon" -#: cfp/models.py:109 cfp/models.py:421 +#: cfp/models.py:109 cfp/models.py:425 #: cfp/templates/cfp/staff/volunteer_details.html:14 msgid "Phone number" msgstr "Numéro de téléphone" -#: cfp/models.py:112 cfp/models.py:309 +#: cfp/models.py:112 cfp/models.py:313 msgid "This field is only visible by organizers." msgstr "Ce champs est uniquement visible par les organisateurs." @@ -290,23 +290,23 @@ msgstr "Ce champs est uniquement visible par les organisateurs." msgid "Invited speaker" msgstr "Orateur invité" -#: cfp/models.py:199 +#: cfp/models.py:203 msgid "Color" msgstr "Couleur" -#: cfp/models.py:231 +#: cfp/models.py:235 msgid "Default duration (min)" msgstr "Durée par défaut (min)" -#: cfp/models.py:232 +#: cfp/models.py:236 msgid "Color on program" msgstr "Couleur sur le programme" -#: cfp/models.py:233 +#: cfp/models.py:237 msgid "Label on program" msgstr "Label dans le xml du programme" -#: cfp/models.py:304 cfp/templates/cfp/proposal_talk_details.html:51 +#: cfp/models.py:308 cfp/templates/cfp/proposal_talk_details.html:51 #: cfp/templates/cfp/staff/base.html:11 #: cfp/templates/cfp/staff/participant_list.html:8 #: cfp/templates/cfp/staff/talk_details.html:68 @@ -314,19 +314,19 @@ msgstr "Label dans le xml du programme" msgid "Speakers" msgstr "Orateurs" -#: cfp/models.py:305 +#: cfp/models.py:309 msgid "Talk Title" msgstr "Titre de la proposition" -#: cfp/models.py:308 +#: cfp/models.py:312 msgid "Description of your talk" msgstr "Description de votre proposition" -#: cfp/models.py:312 cfp/templates/cfp/proposal_talk_details.html:77 +#: cfp/models.py:316 cfp/templates/cfp/proposal_talk_details.html:83 msgid "Message to organizers" msgstr "Message aux organisateurs" -#: cfp/models.py:313 +#: cfp/models.py:317 msgid "" "If you have any constraint or if you have anything that may help you to " "select your talk, like a video or slides of your talk, please write it down " @@ -336,67 +336,67 @@ msgstr "" "votre proposition, comme une vidéo, des slides, n'hésitez pas à les ajouter " "ici." -#: cfp/models.py:316 +#: cfp/models.py:320 msgid "Talk Category" msgstr "Catégorie de proposition" -#: cfp/models.py:317 +#: cfp/models.py:321 msgid "I'm ok to be recorded on video" msgstr "J’accepte d’être enregistré en vidéo" -#: cfp/models.py:319 +#: cfp/models.py:323 msgid "Video licence" msgstr "Licence vidéo" -#: cfp/models.py:320 +#: cfp/models.py:324 msgid "I need sound" msgstr "J’ai besoin de son" -#: cfp/models.py:323 +#: cfp/models.py:327 msgid "Beginning date and time" msgstr "Date et heure de début" -#: cfp/models.py:324 +#: cfp/models.py:328 msgid "Duration (min)" msgstr "Durée (min)" -#: cfp/models.py:328 +#: cfp/models.py:332 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." -#: cfp/models.py:357 +#: cfp/models.py:361 msgid "Waiting confirmation" msgstr "En attente de confirmation" -#: cfp/models.py:359 +#: cfp/models.py:363 msgid "Refused" msgstr "Refusé" -#: cfp/models.py:361 +#: cfp/models.py:365 #, python-format msgid "Pending decision, score: %(score).1f" msgstr "En cours, score : %(score).1f" -#: cfp/models.py:418 +#: cfp/models.py:422 msgid "Your Name" msgstr "Votre Nom" -#: cfp/models.py:422 +#: cfp/models.py:426 msgid "SMS prefered" msgstr "SMS préférés" -#: cfp/models.py:425 +#: cfp/models.py:429 msgid "If you have some constraints, you can indicate them here." msgstr "Si vous avez des contraintes, vous pouvez les indiquer ici." -#: cfp/models.py:444 cfp/templates/cfp/staff/volunteer_details.html:8 +#: cfp/models.py:448 cfp/templates/cfp/staff/volunteer_details.html:8 msgid "Volunteer" msgstr "Bénévole" -#: cfp/models.py:449 cfp/templates/cfp/staff/volunteer_details.html:25 +#: cfp/models.py:453 cfp/templates/cfp/staff/volunteer_details.html:25 #: cfp/templates/cfp/staff/volunteer_list.html:32 msgid "Activities" msgstr "Activités" @@ -433,7 +433,7 @@ msgstr "Ajouter un nouvel utilisateur" #: cfp/templates/cfp/admin/conference.html:14 #: cfp/templates/cfp/proposal_home.html:28 #: cfp/templates/cfp/proposal_mail_token.html:25 -#: cfp/templates/cfp/proposal_speaker_form.html:38 +#: cfp/templates/cfp/proposal_speaker_form.html:48 #: cfp/templates/cfp/proposal_talk_form.html:28 #: cfp/templates/cfp/staff/create_user.html:13 msgid "Save" @@ -565,14 +565,18 @@ msgid "Edit a speaker" msgstr "Éditer un orateur" #: cfp/templates/cfp/proposal_speaker_form.html:15 -#: cfp/templates/cfp/proposal_talk_details.html:63 +#: cfp/templates/cfp/proposal_talk_details.html:69 msgid "Add a co-speaker" -msgstr "Ajouter un co-orateur" +msgstr "Ajouter un co-intervenant" #: cfp/templates/cfp/proposal_speaker_form.html:17 msgid "Go back to the talk" msgstr "Retourner à l’exposé" +#: cfp/templates/cfp/proposal_speaker_form.html:36 +msgid "You may want to add one of the following speakers:" +msgstr "Vous souhaitez peut-être ajouter un des intervenants suivants :" + #: cfp/templates/cfp/proposal_talk_details.html:14 msgid "My profile" msgstr "Mon profil" @@ -619,12 +623,16 @@ msgstr "Bonne nouvelle, je peux finalement être présent !" msgid "Sorry, refused :-(" msgstr "Désolé, refusé :-(" -#: cfp/templates/cfp/proposal_talk_details.html:58 +#: cfp/templates/cfp/proposal_talk_details.html:59 msgid "you!" msgstr "vous !" -#: cfp/templates/cfp/proposal_talk_details.html:73 -#: cfp/templates/cfp/proposal_talk_details.html:83 +#: cfp/templates/cfp/proposal_talk_details.html:62 +msgid "remove" +msgstr "supprimer" + +#: cfp/templates/cfp/proposal_talk_details.html:79 +#: cfp/templates/cfp/proposal_talk_details.html:89 #: cfp/templates/cfp/staff/talk_details.html:66 msgid "No description provided." msgstr "Aucune description fournie." @@ -1154,51 +1162,59 @@ msgstr "Nous avons enregistré votre indisponibilité." msgid "Speaker %(speaker)s CANCELLED his/her participation." msgstr "L’intervenant %(speaker)s a ANNULÉ sa participation." -#: cfp/views.py:397 +#: cfp/views.py:352 +msgid "Co-speaker successfully added to the talk." +msgstr "Co-intervenant ajouté à l’exposé avec succès." + +#: cfp/views.py:365 +msgid "Co-speaker successfully removed from the talk." +msgstr "Co-intervenant supprimé de l’exposé avec succès." + +#: cfp/views.py:407 msgid "The speaker confirmation have been noted." msgstr "La confirmation de l’orateur a été notée." -#: cfp/views.py:398 +#: cfp/views.py:408 msgid "The talk have been confirmed." msgstr "L’exposé a été confirmé." -#: cfp/views.py:400 +#: cfp/views.py:410 msgid "The speaker unavailability have been noted." msgstr "L’indisponibilité de l’intervenant a été notée." -#: cfp/views.py:401 +#: cfp/views.py:411 msgid "The talk have been cancelled." msgstr "L’exposé a été annulé." -#: cfp/views.py:476 cfp/views.py:578 +#: cfp/views.py:486 cfp/views.py:588 msgid "The talk has been accepted." msgstr "L’exposé a été accepté." -#: cfp/views.py:478 cfp/views.py:580 +#: cfp/views.py:488 cfp/views.py:590 msgid "The talk has been declined." msgstr "L’exposé a été décliné." -#: cfp/views.py:547 cfp/views.py:640 +#: cfp/views.py:557 cfp/views.py:650 msgid "Message sent!" msgstr "Message envoyé !" -#: cfp/views.py:561 +#: cfp/views.py:571 msgid "Vote successfully created" msgstr "A voté !" -#: cfp/views.py:561 +#: cfp/views.py:571 msgid "Vote successfully updated" msgstr "Vote mis à jour" -#: cfp/views.py:582 +#: cfp/views.py:592 msgid "Decision taken in account" msgstr "Décision enregistrée" -#: cfp/views.py:668 +#: cfp/views.py:678 msgid "[{}] You have been added to the staff team" msgstr "[{}] Vous avez été ajouté aux membres du staff" -#: cfp/views.py:669 +#: cfp/views.py:679 msgid "" "Hi {},\n" "\n" @@ -1222,15 +1238,15 @@ msgstr "" "{}\n" "\n" -#: cfp/views.py:690 +#: cfp/views.py:700 msgid "Modifications successfully saved." msgstr "Modification enregistrée avec succès." -#: cfp/views.py:767 +#: cfp/views.py:777 msgid "User created successfully." msgstr "Utilisateur créé avec succès." -#: cfp/views.py:788 +#: cfp/views.py:798 #, python-format msgid "Format '%s' not available" msgstr "Format '%s' non disponible"