Changeset - 420d8ec870bd
[Not reviewed]
0 6 1
Scott Bragg - 8 years ago 2016-09-03 02:48:31
jsbragg@scriptforge.org
Remove description from Presentation, add fields to proposal for notification template.
7 files changed with 31 insertions and 8 deletions:
0 comments (0 inline, 0 general)
requirements/base.txt
Show inline comments
 
Django>=1.9.2
 
Django==1.9.2
 
django-appconf==1.0.1
 
django-model-utils==2.4.0
 
django-reversion==1.10.1
 
django-sitetree==1.5.1
 
django-taggit==0.18.0
 
django-timezone-field==1.3
 
django-user-accounts==1.3.1
 
easy-thumbnails==2.3
 
html5lib==0.9999999
 
markdown==2.6.5
 
pytz==2015.7
symposion/proposals/models.py
Show inline comments
...
 
@@ -175,50 +175,51 @@ class ProposalBase(models.Model):
 
    def speaker_email(self):
 
        return self.speaker.email
 

	
 
    @property
 
    def number(self):
 
        return str(self.pk).zfill(3)
 

	
 
    @property
 
    def status(self):
 
        try:
 
            return self.result.status
 
        except ObjectDoesNotExist:
 
            return _('Undecided')
 

	
 
    def speakers(self):
 
        yield self.speaker
 
        speakers = self.additional_speakers.exclude(
 
            additionalspeaker__status=AdditionalSpeaker.SPEAKING_STATUS_DECLINED)
 
        for speaker in speakers:
 
            yield speaker
 

	
 
    def notification_email_context(self):
 
        return {
 
            "title": self.title,
 
            "speaker": self.speaker.name,
 
            "speaker": self.speaker,
 
            "speakers": ', '.join([x.name for x in self.speakers()]),
 
            "additional_speakers": self.additional_speakers,
 
            "kind": self.kind.name,
 
        }
 

	
 
    def __str__(self):
 
        return self.title
 

	
 
reversion.register(ProposalBase)
 

	
 

	
 
@python_2_unicode_compatible
 
class AdditionalSpeaker(models.Model):
 

	
 
    SPEAKING_STATUS_PENDING = 1
 
    SPEAKING_STATUS_ACCEPTED = 2
 
    SPEAKING_STATUS_DECLINED = 3
 

	
 
    SPEAKING_STATUS = [
 
        (SPEAKING_STATUS_PENDING, _("Pending")),
 
        (SPEAKING_STATUS_ACCEPTED, _("Accepted")),
 
        (SPEAKING_STATUS_DECLINED, _("Declined")),
 
    ]
 

	
 
    speaker = models.ForeignKey(Speaker, verbose_name=_("Speaker"))
 
    proposalbase = models.ForeignKey(ProposalBase, verbose_name=_("Proposalbase"))
symposion/reviews/models.py
Show inline comments
...
 
@@ -340,49 +340,48 @@ class ResultNotification(models.Model):
 
    template = models.ForeignKey(NotificationTemplate, null=True, blank=True,
 
                                 on_delete=models.SET_NULL, verbose_name=_("Template"))
 
    timestamp = models.DateTimeField(default=datetime.now, verbose_name=_("Timestamp"))
 
    to_address = models.EmailField(verbose_name=_("To address"))
 
    from_address = models.EmailField(verbose_name=_("From address"))
 
    subject = models.CharField(max_length=100, verbose_name=_("Subject"))
 
    body = models.TextField(verbose_name=_("Body"))
 

	
 
    def recipients(self):
 
        for speaker in self.proposal.speakers():
 
            yield speaker.email
 

	
 
    @property
 
    def email_args(self):
 
        return (self.subject, self.body, self.from_address, self.recipients())
 

	
 

	
 
def promote_proposal(proposal):
 
    if hasattr(proposal, "presentation") and proposal.presentation:
 
        # already promoted
 
        presentation = proposal.presentation
 
    else:
 
        presentation = Presentation(
 
            title=proposal.title,
 
            description=proposal.description,
 
            abstract=proposal.abstract,
 
            speaker=proposal.speaker,
 
            section=proposal.section,
 
            proposal_base=proposal,
 
        )
 
        presentation.save()
 
        for speaker in proposal.additional_speakers.all():
 
            presentation.additional_speakers.add(speaker)
 
            presentation.save()
 

	
 
    return presentation
 

	
 

	
 
def unpromote_proposal(proposal):
 
    if hasattr(proposal, "presentation") and proposal.presentation:
 
        proposal.presentation.delete()
 

	
 

	
 
def accepted_proposal(sender, instance=None, **kwargs):
 
    if instance is None:
 
        return
 
    if instance.status == "accepted":
 
        promote_proposal(instance.proposal)
 
    else:
symposion/reviews/views.py
Show inline comments
...
 
@@ -624,36 +624,40 @@ def result_notification_send(request, section_slug, status):
 
        return HttpResponseBadRequest()
 

	
 
    proposals = ProposalBase.objects.filter(
 
        kind__section__slug=section_slug,
 
        result__status=status,
 
    )
 
    proposals = proposals.filter(pk__in=proposal_pks)
 
    proposals = proposals.select_related("speaker__user", "result")
 
    proposals = proposals.select_subclasses()
 

	
 
    notification_template_pk = request.POST.get("notification_template", "")
 
    if notification_template_pk:
 
        notification_template = NotificationTemplate.objects.get(pk=notification_template_pk)
 
    else:
 
        notification_template = None
 

	
 
    emails = []
 

	
 
    for proposal in proposals:
 
        rn = ResultNotification()
 
        rn.proposal = proposal
 
        rn.template = notification_template
 
        rn.to_address = proposal.speaker_email
 
        rn.from_address = request.POST["from_address"]
 
        rn.subject = request.POST["subject"]
 
        rn.subject = Template(request.POST["subject"]).render(
 
            Context({
 
                "proposal": proposal.notification_email_context()
 
            })
 
        )
 
        rn.body = Template(request.POST["body"]).render(
 
            Context({
 
                "proposal": proposal.notification_email_context()
 
            })
 
        )
 
        rn.save()
 
        emails.append(rn.email_args)
 

	
 
    send_mass_mail(emails)
 

	
 
    return redirect("result_notification", section_slug=section_slug, status=status)
symposion/schedule/migrations/0002_auto_20160903_0146.py
Show inline comments
 
new file 100644
 
# -*- coding: utf-8 -*-
 
# Generated by Django 1.9.2 on 2016-09-03 01:46
 
from __future__ import unicode_literals
 

	
 
from django.db import migrations, models
 

	
 

	
 
class Migration(migrations.Migration):
 

	
 
    dependencies = [
 
        ('symposion_schedule', '0001_initial'),
 
    ]
 

	
 
    operations = [
 
        migrations.RemoveField(
 
            model_name='presentation',
 
            name='description',
 
        ),
 
        migrations.RemoveField(
 
            model_name='presentation',
 
            name='description_html',
 
        ),
 
    ]
symposion/schedule/models.py
Show inline comments
...
 
@@ -164,61 +164,58 @@ class Slot(models.Model):
 
@python_2_unicode_compatible
 
class SlotRoom(models.Model):
 
    """
 
    Links a slot with a room.
 
    """
 

	
 
    slot = models.ForeignKey(Slot, verbose_name=_("Slot"))
 
    room = models.ForeignKey(Room, verbose_name=_("Room"))
 

	
 
    def __str__(self):
 
        return "%s %s" % (self.room, self.slot)
 

	
 
    class Meta:
 
        unique_together = [("slot", "room")]
 
        ordering = ["slot", "room__order"]
 
        verbose_name = _("Slot room")
 
        verbose_name_plural = _("Slot rooms")
 

	
 

	
 
@python_2_unicode_compatible
 
class Presentation(models.Model):
 

	
 
    slot = models.OneToOneField(Slot, null=True, blank=True, related_name="content_ptr", verbose_name=_("Slot"))
 
    title = models.CharField(max_length=100, verbose_name=_("Title"))
 
    description = models.TextField(verbose_name=_("Description"))
 
    description_html = models.TextField(blank=True)
 
    abstract = models.TextField(verbose_name=_("Abstract"))
 
    abstract_html = models.TextField(blank=True)
 
    speaker = models.ForeignKey(Speaker, related_name="presentations", verbose_name=_("Speaker"))
 
    additional_speakers = models.ManyToManyField(Speaker, related_name="copresentations",
 
                                                 blank=True, verbose_name=_("Additional speakers"))
 
    cancelled = models.BooleanField(default=False, verbose_name=_("Cancelled"))
 
    proposal_base = models.OneToOneField(ProposalBase, related_name="presentation", verbose_name=_("Proposal base"))
 
    section = models.ForeignKey(Section, related_name="presentations", verbose_name=_("Section"))
 

	
 
    def save(self, *args, **kwargs):
 
        self.description_html = parse(self.description)
 
        self.abstract_html = parse(self.abstract)
 
        return super(Presentation, self).save(*args, **kwargs)
 

	
 
    @property
 
    def number(self):
 
        return self.proposal.number
 

	
 
    @property
 
    def proposal(self):
 
        if self.proposal_base_id is None:
 
            return None
 
        return ProposalBase.objects.get_subclass(pk=self.proposal_base_id)
 

	
 
    def speakers(self):
 
        yield self.speaker
 
        for speaker in self.additional_speakers.all():
 
            if speaker.user:
 
                yield speaker
 

	
 
    def __str__(self):
 
        return "#%s %s (%s)" % (self.number, self.title, self.speaker)
 

	
 
    class Meta:
 
        ordering = ["slot"]
symposion/schedule/views.py
Show inline comments
...
 
@@ -204,49 +204,48 @@ def schedule_json(request):
 
            "end": slot.end_datetime.isoformat(),
 
            "duration": slot.length_in_minutes,
 
            "kind": slot.kind.label,
 
            "section": slot.day.schedule.section.slug,
 
            "conf_key": slot.pk,
 
            # TODO: models should be changed.
 
            # these are model features from other conferences that have forked symposion
 
            # these have been used almost everywhere and are good candidates for
 
            # base proposals
 
            "license": "CC BY",
 
            "tags": "",
 
            "released": True,
 
            "contact": [],
 

	
 

	
 
        }
 
        if hasattr(slot.content, "proposal"):
 
            slot_data.update({
 
                "name": slot.content.title,
 
                "authors": [s.name for s in slot.content.speakers()],
 
                "contact": [
 
                    s.email for s in slot.content.speakers()
 
                ] if request.user.is_staff else ["redacted"],
 
                "abstract": slot.content.abstract.raw,
 
                "description": slot.content.description.raw,
 
                "conf_url": "%s://%s%s" % (
 
                    protocol,
 
                    Site.objects.get_current().domain,
 
                    reverse("schedule_presentation_detail", args=[slot.content.pk])
 
                ),
 
                "cancelled": slot.content.cancelled,
 
            })
 
        else:
 
            slot_data.update({
 
                "name": slot.content_override.raw if slot.content_override else "Slot",
 
            })
 
        data.append(slot_data)
 

	
 
    return HttpResponse(
 
        json.dumps({"schedule": data}),
 
        content_type="application/json"
 
    )
 

	
 

	
 
def session_list(request):
 
    sessions = Session.objects.all().order_by('pk')
 

	
 
    return render(request, "symposion/schedule/session_list.html", {
 
        "sessions": sessions,
0 comments (0 inline, 0 general)