add admin commands to approve speaker and event proposals

This commit is contained in:
Thomas Steen Rasmussen 2017-03-16 00:30:59 +01:00
parent c2528129a5
commit a715cba597
5 changed files with 87 additions and 6 deletions

View file

@ -5,12 +5,22 @@ from .models import Event, Speaker, EventType, EventInstance, EventLocation, Spe
@admin.register(SpeakerProposal) @admin.register(SpeakerProposal)
class SpeakerProposalAdmin(admin.ModelAdmin): class SpeakerProposalAdmin(admin.ModelAdmin):
pass def mark_speakerproposal_as_approved(self, request, queryset):
for sp in queryset:
sp.mark_as_approved()
mark_speakerproposal_as_approved.description = 'Approve and create Speaker object(s)'
actions = ['mark_speakerproposal_as_approved']
@admin.register(EventProposal) @admin.register(EventProposal)
class EventProposalAdmin(admin.ModelAdmin): class EventProposalAdmin(admin.ModelAdmin):
pass def mark_eventproposal_as_approved(self, request, queryset):
for ep in queryset:
ep.mark_as_approved()
mark_eventproposal_as_approved.description = 'Approve and create Event object(s)'
actions = ['mark_eventproposal_as_approved']
@admin.register(EventLocation) @admin.register(EventLocation)

View file

@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.5 on 2017-03-15 23:04
from __future__ import unicode_literals
from django.db import migrations, models
import program.models
class Migration(migrations.Migration):
dependencies = [
('program', '0035_auto_20170314_2325'),
]
operations = [
migrations.AlterField(
model_name='speakerproposal',
name='picture_large',
field=models.ImageField(blank=True, help_text='A picture of the speaker', max_length=255, null=True, storage=program.models.CustomUrlStorage(), upload_to=program.models.get_speakerproposal_picture_upload_path),
),
migrations.AlterField(
model_name='speakerproposal',
name='picture_small',
field=models.ImageField(blank=True, help_text='A thumbnail of the speaker picture', max_length=255, null=True, storage=program.models.CustomUrlStorage(), upload_to=program.models.get_speakerproposal_picture_upload_path),
),
]

View file

@ -18,7 +18,7 @@ class EnsureUnapprovedProposalMixin(SingleObjectMixin):
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
# do not permit editing if the proposal is already approved # do not permit editing if the proposal is already approved
if self.get_object().proposal_status == models.UserSubmittedModel.PROPOSAL_APPROVED: if self.get_object().proposal_status == models.UserSubmittedModel.PROPOSAL_APPROVED:
messages.error(request, "This proposal has already been approved. Please contact the organisers if you need to modify something." % self.camp.title) messages.error(request, "This proposal has already been approved. Please contact the organisers if you need to modify something.")
return redirect(reverse('proposal_list', kwargs={'camp_slug': self.camp.slug})) return redirect(reverse('proposal_list', kwargs={'camp_slug': self.camp.slug}))
# alright, continue with the request # alright, continue with the request

View file

@ -7,10 +7,11 @@ from utils.models import CreatedUpdatedModel, CampRelatedModel
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from datetime import timedelta from datetime import timedelta
from django.core.urlresolvers import reverse_lazy from django.core.urlresolvers import reverse_lazy
import uuid import uuid, os
from django.core.files.storage import FileSystemStorage from django.core.files.storage import FileSystemStorage
from django.urls import reverse from django.urls import reverse
from django.apps import apps from django.apps import apps
from django.core.files.base import ContentFile
class CustomUrlStorage(FileSystemStorage): class CustomUrlStorage(FileSystemStorage):
@ -138,6 +139,7 @@ class SpeakerProposal(UserSubmittedModel):
upload_to=get_speakerproposal_picture_upload_path, upload_to=get_speakerproposal_picture_upload_path,
help_text='A picture of the speaker', help_text='A picture of the speaker',
storage=storage, storage=storage,
max_length=255
) )
picture_small = models.ImageField( picture_small = models.ImageField(
@ -146,6 +148,7 @@ class SpeakerProposal(UserSubmittedModel):
upload_to=get_speakerproposal_picture_upload_path, upload_to=get_speakerproposal_picture_upload_path,
help_text='A thumbnail of the speaker picture', help_text='A thumbnail of the speaker picture',
storage=storage, storage=storage,
max_length=255
) )
@property @property
@ -155,6 +158,26 @@ class SpeakerProposal(UserSubmittedModel):
def get_absolute_url(self): def get_absolute_url(self):
return reverse_lazy('speakerproposal_detail', kwargs={'camp_slug': self.camp.slug, 'pk': self.uuid}) return reverse_lazy('speakerproposal_detail', kwargs={'camp_slug': self.camp.slug, 'pk': self.uuid})
def mark_as_approved(self):
speakermodel = apps.get_model('program', 'speaker')
speakerproposalmodel = apps.get_model('program', 'speakerproposal')
speaker = speakermodel()
speaker.camp = self.camp
speaker.name = self.name
speaker.biography = self.biography
if self.picture_small and self.picture_large:
temp = ContentFile(self.picture_small.read())
temp.name = os.path.basename(self.picture_small.name)
speaker.picture_small = temp
temp = ContentFile(self.picture_large.read())
temp.name = os.path.basename(self.picture_large.name)
speaker.picture_large = temp
speaker.proposal = self
speaker.save()
self.proposal_status = speakerproposalmodel.PROPOSAL_APPROVED
self.save()
class EventProposal(UserSubmittedModel): class EventProposal(UserSubmittedModel):
""" An event proposal """ """ An event proposal """
@ -191,6 +214,24 @@ class EventProposal(UserSubmittedModel):
def get_absolute_url(self): def get_absolute_url(self):
return reverse_lazy('eventproposal_detail', kwargs={'camp_slug': self.camp.slug, 'pk': self.uuid}) return reverse_lazy('eventproposal_detail', kwargs={'camp_slug': self.camp.slug, 'pk': self.uuid})
def mark_as_approved(self):
eventmodel = apps.get_model('program', 'event')
eventproposalmodel = apps.get_model('program', 'eventproposal')
event = eventmodel()
event.camp = self.camp
event.title = self.title
event.abstract = self.abstract
event.event_type = self.event_type
event.proposal = self
event.save()
# loop through the speakerproposals linked to this eventproposal and associate any related speaker objects with this event
for sp in self.speakers.all():
if sp.speaker:
event.speaker_set.add(sp.speaker)
self.proposal_status = eventproposalmodel.PROPOSAL_APPROVED
self.save()
############################################################################################# #############################################################################################

View file

@ -24,8 +24,12 @@ Proposals | {{ block.super }}
<td> <td>
<a href="{% url 'speakerproposal_detail' camp_slug=camp.slug pk=speakerproposal.uuid %}" class="btn btn-primary btn-xs">Details</a> <a href="{% url 'speakerproposal_detail' camp_slug=camp.slug pk=speakerproposal.uuid %}" class="btn btn-primary btn-xs">Details</a>
{% if not camp.read_only %} {% if not camp.read_only %}
{% if speakerproposal.proposal_status == "approved" %}
<a href="{% url 'speakerproposal_update' camp_slug=camp.slug pk=speakerproposal.uuid %}" class="btn btn-primary btn-xs btn-disabled" disabled>Modify</a>
{% else %}
<a href="{% url 'speakerproposal_update' camp_slug=camp.slug pk=speakerproposal.uuid %}" class="btn btn-primary btn-xs">Modify</a> <a href="{% url 'speakerproposal_update' camp_slug=camp.slug pk=speakerproposal.uuid %}" class="btn btn-primary btn-xs">Modify</a>
{% if speakerproposal.proposal_status == "pending" %} {% endif %}
{% if speakerproposal.proposal_status == "pending" or speakerproposal.proposal_status == "approved" %}
<a href="{% url 'speakerproposal_submit' camp_slug=camp.slug pk=speakerproposal.uuid %}" class="btn btn-primary btn-xs btn-disabled" disabled>Submit</a> <a href="{% url 'speakerproposal_submit' camp_slug=camp.slug pk=speakerproposal.uuid %}" class="btn btn-primary btn-xs btn-disabled" disabled>Submit</a>
{% else %} {% else %}
<a href="{% url 'speakerproposal_submit' camp_slug=camp.slug pk=speakerproposal.uuid %}" class="btn btn-primary btn-xs">Submit</a> <a href="{% url 'speakerproposal_submit' camp_slug=camp.slug pk=speakerproposal.uuid %}" class="btn btn-primary btn-xs">Submit</a>