if one or more speakerproposals exist show a list so the user can pick an existing or choose to add a new; use the multimodelform stuff only when the user wants to add a new speakerproposal

This commit is contained in:
Thomas Steen Rasmussen 2018-05-20 21:11:53 +02:00
parent 733fdbf4ba
commit 5dc3e17d66
4 changed files with 97 additions and 25 deletions

View file

@ -0,0 +1,33 @@
{% extends 'program_base.html' %}
{% block title %}
Use Existing {{ eventtype.host_title }} or Add New? | {{ block.super }}
{% endblock %}
{% block program_content %}
<h3>Use Existing {{ eventtype.host_title }}?</h3>
<p class="lead">Pick a {{ eventtype.host_title }} from the list below, or press the button at the bottom to add a new {{ eventtype.host_title }} for this {{ eventtype.name }}.</p>
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Use an Existing {{ eventtype.host_title }}</h3>
</div>
<div class="panel-body">
<div class="list-group">
{% for speakerproposal in speakerproposal_list %}
<a href="{% url 'program:eventproposal_create' camp_slug=camp.slug event_type_slug=eventtype.slug speaker_uuid=speakerproposal.uuid %}" class="list-group-item">
<h4 class="list-group-item-heading">
Use {{ speakerproposal.name }} as {{ eventtype.host_title }}
</h4>
</a>
{% endfor %}
</div>
</div>
</div>
<a href="{% url 'program:proposal_combined_submit' camp_slug=camp.slug event_type_slug=eventtype.slug %}" class="btn btn-primary btn-success"><i class="fas fa-plus"></i> Add New {{ eventtype.host_title }}</a>
<a href="{% url 'program:proposal_list' camp_slug=camp.slug %}" class="btn btn-primary"><i class="fas fa-undo"></i> Cancel</a>
{% endblock %}

View file

@ -14,7 +14,7 @@
{% if speaker %} {% if speaker %}
<a href="{%url 'program:eventproposal_create' camp_slug=camp.slug event_type_slug=eventtype.slug speaker_uuid=speaker.uuid %}" class="list-group-item"> <a href="{%url 'program:eventproposal_create' camp_slug=camp.slug event_type_slug=eventtype.slug speaker_uuid=speaker.uuid %}" class="list-group-item">
{% else %} {% else %}
<a href="{% url 'program:proposal_combined_submit' camp_slug=camp.slug event_type_slug=eventtype.slug %}" class="list-group-item"> <a href="{% url 'program:proposal_combined_person_select' camp_slug=camp.slug event_type_slug=eventtype.slug %}" class="list-group-item">
{% endif %} {% endif %}
<h4 class="list-group-item-heading"> <h4 class="list-group-item-heading">
<i class="fas fa-{{ eventtype.icon }} fa-2x fa-pull-left fa-fw" style="color: {{ eventtype.color }};"></i> <i class="fas fa-{{ eventtype.icon }} fa-2x fa-pull-left fa-fw" style="color: {{ eventtype.color }};"></i>

View file

@ -39,6 +39,11 @@ urlpatterns = [
CombinedProposalSubmitView.as_view(), CombinedProposalSubmitView.as_view(),
name='proposal_combined_submit', name='proposal_combined_submit',
), ),
url(
r'^(?P<event_type_slug>[-_\w+]+)/select_person/$',
CombinedProposalPersonSelectView.as_view(),
name='proposal_combined_person_select',
),
]), ]),
), ),
url( url(

View file

@ -269,9 +269,8 @@ class EventProposalAddPersonView(LoginRequiredMixin, CampViewMixin, EnsureWritab
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
""" Get the speakerproposal object """ """ Get the speakerproposal object """
response = super().dispatch(request, *args, **kwargs)
self.speakerproposal = get_object_or_404(models.SpeakerProposal, pk=kwargs['speaker_uuid'], user=request.user) self.speakerproposal = get_object_or_404(models.SpeakerProposal, pk=kwargs['speaker_uuid'], user=request.user)
return response return super().dispatch(request, *args, **kwargs)
def get_context_data(self, *args, **kwargs): def get_context_data(self, *args, **kwargs):
""" Make speakerproposal object available in template """ """ Make speakerproposal object available in template """
@ -396,10 +395,38 @@ class CombinedProposalTypeSelectView(LoginRequiredMixin, CampViewMixin, ListView
return super().get_queryset().filter(public=True) return super().get_queryset().filter(public=True)
class CombinedProposalPersonSelectView(LoginRequiredMixin, CampViewMixin, ListView):
"""
A view which allows the user to 1) choose between existing SpeakerProposals or
2) pressing a button to create a new SpeakerProposal.
Redirect straight to 2) if no existing SpeakerProposals exist.
"""
model = models.SpeakerProposal
template_name = 'combined_proposal_select_person.html'
def dispatch(self, request, *args, **kwargs):
"""
Check that we have a valid EventType
"""
# get EventType from url kwargs
self.eventtype = get_object_or_404(models.EventType, slug=self.kwargs['event_type_slug'])
return super().dispatch(request, *args, **kwargs)
def get_context_data(self, **kwargs):
"""
Add EventType to template context
"""
context = super().get_context_data(**kwargs)
context['eventtype'] = self.eventtype
return context
class CombinedProposalSubmitView(LoginRequiredMixin, CampViewMixin, CreateView): class CombinedProposalSubmitView(LoginRequiredMixin, CampViewMixin, CreateView):
""" """
This view is used by users to submit CFP proposals. This view is used by users to submit CFP proposals.
It allows the user to submit an EventProposal and a SpeakerProposal together. It allows the user to submit an EventProposal and a SpeakerProposal together.
It can also be used with a preselected SpeakerProposal uuid in url kwargs
""" """
template_name = 'combined_proposal_submit.html' template_name = 'combined_proposal_submit.html'
@ -407,16 +434,10 @@ class CombinedProposalSubmitView(LoginRequiredMixin, CampViewMixin, CreateView):
""" """
Check that we have a valid EventType Check that we have a valid EventType
""" """
try: # get EventType from url kwargs
self.eventtype = models.EventType.objects.get( self.eventtype = get_object_or_404(models.EventType, slug=self.kwargs['event_type_slug'])
slug=self.kwargs['event_type_slug']
)
except models.EventType.DoesNotExist:
raise Http404
return super().dispatch( return super().dispatch(request, *args, **kwargs)
request, *args, **kwargs
)
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
""" """
@ -428,30 +449,43 @@ class CombinedProposalSubmitView(LoginRequiredMixin, CampViewMixin, CreateView):
def form_valid(self, form): def form_valid(self, form):
""" """
We save each object here before redirecting Save the object(s) here before redirecting
""" """
# first save the SpeakerProposal if hasattr(self, 'speakerproposal'):
speakerproposal = form['speakerproposal'].save(commit=False) eventproposal = form.save(commit=False)
speakerproposal.camp = self.camp eventproposal.user = self.request.user
speakerproposal.user = self.request.user eventproposal.event_type = self.eventtype
speakerproposal.save() eventproposal.save()
eventproposal.speakers.add(self.speakerproposal)
else:
# first save the SpeakerProposal
speakerproposal = form['speakerproposal'].save(commit=False)
speakerproposal.camp = self.camp
speakerproposal.user = self.request.user
speakerproposal.save()
# then save the eventproposal # then save the eventproposal
eventproposal = form['eventproposal'].save(commit=False) eventproposal = form['eventproposal'].save(commit=False)
eventproposal.user = self.request.user eventproposal.user = self.request.user
eventproposal.event_type = self.eventtype eventproposal.event_type = self.eventtype
eventproposal.save() eventproposal.save()
# add the speakerproposal to the eventproposal # add the speakerproposal to the eventproposal
eventproposal.speakers.add(speakerproposal) eventproposal.speakers.add(speakerproposal)
# all good # all good
return redirect(reverse_lazy('program:proposal_list', kwargs={'camp_slug': self.camp.slug})) return redirect(reverse_lazy('program:proposal_list', kwargs={'camp_slug': self.camp.slug}))
def get_form_class(self): def get_form_class(self):
""" """
Unless we have an existing SpeakerProposal we must show two forms on the page.
We use betterforms.MultiModelForm to combine two forms on the page We use betterforms.MultiModelForm to combine two forms on the page
""" """
if hasattr(self, 'speakerproposal'):
# we already have a speakerproposal, just show an eventproposal form
return get_eventproposal_form_class(eventtype=self.eventtype)
# get the two forms we need to build the MultiModelForm
SpeakerProposalForm = get_speakerproposal_form_class(eventtype=self.eventtype) SpeakerProposalForm = get_speakerproposal_form_class(eventtype=self.eventtype)
EventProposalForm = get_eventproposal_form_class(eventtype=self.eventtype) EventProposalForm = get_eventproposal_form_class(eventtype=self.eventtype)