Changeset - 5c07d3e9454b
[Not reviewed]
0 11 0
Martin Brochhaus - 11 years ago 2014-01-11 06:50:04
mbrochh@gmail.com
Django 1.6 compatibility
11 files changed with 25 insertions and 22 deletions:
0 comments (0 inline, 0 general)
symposion/boxes/urls.py
Show inline comments
 
from django.conf.urls.defaults import url, patterns
 
from django.conf.urls import url, patterns
 

	
 

	
 
urlpatterns = patterns("symposion.boxes.views",
 
    url(r"^([-\w]+)/edit/$", "box_edit", name="box_edit"),
 
)
...
 
\ No newline at end of file
 
)
symposion/cms/urls.py
Show inline comments
 
from django.conf.urls.defaults import url, patterns
 
from django.conf.urls import url, patterns
 

	
 
PAGE_RE = r"(([\w-]{1,})(/[\w-]{1,})*)/"
 

	
 
urlpatterns = patterns("symposion.cms.views",
 
    url(r"^files/$", "file_index", name="file_index"),
 
    url(r"^files/create/$", "file_create", name="file_create"),
 
    url(r"^files/(\d+)/([^/]+)$", "file_download", name="file_download"),
 
    url(r"^files/(\d+)/delete/$", "file_delete", name="file_delete"),
 
    url(r"^(?P<path>%s)_edit/$" % PAGE_RE, "page_edit", name="cms_page_edit"),
 
    url(r"^(?P<path>%s)$" % PAGE_RE, "page", name="cms_page"),
 
)
symposion/conference/urls.py
Show inline comments
 
from django.conf.urls.defaults import *
 
from django.conf.urls import patterns, url
 

	
 

	
 
urlpatterns = patterns("symposion.conference.views",
 
    url(r"^users/$", "user_list", name="user_list"),
 
)
symposion/proposals/models.py
Show inline comments
 
import datetime
 
import os
 
import uuid
 

	
 
from django.core.urlresolvers import reverse
 
from django.db import models
 
from django.db.models import Q
 
from django.utils.translation import ugettext_lazy as _
 
from django.utils.timezone import now
 

	
 
from django.contrib.auth.models import User
 

	
 
import reversion
 

	
 
from markitup.fields import MarkupField
 

	
 
from model_utils.managers import InheritanceManager
 

	
 
from symposion.conference.models import Section
 

	
 

	
 
class ProposalSection(models.Model):
 
    """
 
    configuration of proposal submissions for a specific Section.
 
    
 
    a section is available for proposals iff:
 
      * it is after start (if there is one) and
 
      * it is before end (if there is one) and
 
      * closed is NULL or False
 
    """
 
    
 
    section = models.OneToOneField(Section)
 
    
 
    start = models.DateTimeField(null=True, blank=True)
 
    end = models.DateTimeField(null=True, blank=True)
 
    closed = models.NullBooleanField()
 
    published = models.NullBooleanField()
 
    
 
    @classmethod
 
    def available(cls):
 
        now = datetime.datetime.now()
 
        return cls._default_manager.filter(
 
            Q(start__lt=now) | Q(start=None),
 
            Q(end__gt=now) | Q(end=None),
 
            Q(start__lt=now()) | Q(start=None),
 
            Q(end__gt=now()) | Q(end=None),
 
            Q(closed=False) | Q(closed=None),
 
        )
 
    
 
    def is_available(self):
 
        if self.closed:
 
            return False
 
        now = datetime.datetime.now()
 
        if self.start and self.start > now:
 
        if self.start and self.start > now():
 
            return False
 
        if self.end and self.end < now:
 
        if self.end and self.end < now():
 
            return False
 
        return True
 
    
 
    def __unicode__(self):
 
        return self.section.name
 

	
 

	
 
class ProposalKind(models.Model):
 
    """
 
    e.g. talk vs panel vs tutorial vs poster
 
    
 
    Note that if you have different deadlines, reviewers, etc. you'll want
 
    to distinguish the section as well as the kind.
 
    """
 
    
 
    section = models.ForeignKey(Section, related_name="proposal_kinds")
 
    
 
    name = models.CharField(_("Name"), max_length=100)
 
    slug = models.SlugField()
 
    
 
    def __unicode__(self):
 
        return self.name
 

	
 

	
 
class ProposalBase(models.Model):
 
    
 
    objects = InheritanceManager()
 
    
 
    kind = models.ForeignKey(ProposalKind)
 
    
 
    title = models.CharField(max_length=100)
 
    description = models.TextField(
 
        _("Brief Description"),
 
        max_length=400,  # @@@ need to enforce 400 in UI
 
        help_text="If your proposal is accepted this will be made public and printed in the program. Should be one paragraph, maximum 400 characters."
 
    )
 
    abstract = MarkupField(
 
        _("Detailed Abstract"),
 
        help_text=_("Detailed outline. Will be made public if your proposal is accepted. Edit using <a href='http://daringfireball.net/projects/markdown/basics' target='_blank'>Markdown</a>.")
 
    )
 
    additional_notes = MarkupField(
 
        blank=True,
 
        help_text=_("Anything else you'd like the program committee to know when making their selection: your past experience, etc. This is not made public. Edit using <a href='http://daringfireball.net/projects/markdown/basics' target='_blank'>Markdown</a>.")
 
    )
 
    submitted = models.DateTimeField(
 
        default=datetime.datetime.now,
 
        default=now,
 
        editable=False,
 
    )
 
    speaker = models.ForeignKey("speakers.Speaker", related_name="proposals")
 
    additional_speakers = models.ManyToManyField("speakers.Speaker", through="AdditionalSpeaker", blank=True)
 
    cancelled = models.BooleanField(default=False)
 
    
 
    def can_edit(self):
 
        return True
 
    
 
    @property
 
    def section(self):
 
        return self.kind.section
 
    
 
    @property
 
    def speaker_email(self):
 
        return self.speaker.email
 
    
 
    @property
 
    def number(self):
 
        return str(self.pk).zfill(3)
 
    
 
    def speakers(self):
 
        yield self.speaker
 
        for speaker in self.additional_speakers.exclude(additionalspeaker__status=AdditionalSpeaker.SPEAKING_STATUS_DECLINED):
 
            yield speaker
 
    
 
    def notification_email_context(self):
 
        return {
 
            "title": self.title,
 
            "speaker": self.speaker.name,
 
            "kind": self.kind.name,
 
        }
 

	
 

	
 
reversion.register(ProposalBase)
 

	
 

	
 
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("speakers.Speaker")
 
    proposalbase = models.ForeignKey(ProposalBase)
 
    status = models.IntegerField(choices=SPEAKING_STATUS, default=SPEAKING_STATUS_PENDING)
 
    
 
    class Meta:
 
        db_table = "proposals_proposalbase_additional_speakers"
 
        unique_together = ("speaker", "proposalbase")
 

	
 

	
 
def uuid_filename(instance, filename):
 
    ext = filename.split(".")[-1]
 
    filename = "%s.%s" % (uuid.uuid4(), ext)
 
    return os.path.join("document", filename)
 

	
 

	
 
class SupportingDocument(models.Model):
 
    
 
    proposal = models.ForeignKey(ProposalBase, related_name="supporting_documents")
 
    
 
    uploaded_by = models.ForeignKey(User)
 
    created_at = models.DateTimeField(default=datetime.datetime.now)
 
    created_at = models.DateTimeField(default=now)
 
    
 
    file = models.FileField(upload_to=uuid_filename)
 
    description = models.CharField(max_length=140)
 

	
 
    def download_url(self):
 
        return reverse("proposal_document_download", args=[self.pk, os.path.basename(self.file.name).lower()])
symposion/proposals/urls.py
Show inline comments
 
from django.conf.urls.defaults import *
 
from django.conf.urls import patterns, url
 

	
 

	
 
urlpatterns = patterns("symposion.proposals.views",
 
    url(r"^submit/$", "proposal_submit", name="proposal_submit"),
 
    url(r"^submit/([\w\-]+)/$", "proposal_submit_kind", name="proposal_submit_kind"),
 
    url(r"^(\d+)/$", "proposal_detail", name="proposal_detail"),
 
    url(r"^(\d+)/edit/$", "proposal_edit", name="proposal_edit"),
 
    url(r"^(\d+)/speakers/$", "proposal_speaker_manage", name="proposal_speaker_manage"),
 
    url(r"^(\d+)/cancel/$", "proposal_cancel", name="proposal_cancel"),
 
    url(r"^(\d+)/leave/$", "proposal_leave", name="proposal_leave"),
 
    url(r"^(\d+)/join/$", "proposal_pending_join", name="proposal_pending_join"),
 
    url(r"^(\d+)/decline/$", "proposal_pending_decline", name="proposal_pending_decline"),
 
    
 
    url(r"^(\d+)/document/create/$", "document_create", name="proposal_document_create"),
 
    url(r"^document/(\d+)/delete/$", "document_delete", name="proposal_document_delete"),
 
    url(r"^document/(\d+)/([^/]+)$", "document_download", name="proposal_document_download"),
 
)
symposion/proposals/views.py
Show inline comments
 
import random
 
import sys
 

	
 
from django.conf import settings
 
from django.core.exceptions import ObjectDoesNotExist
 
from django.db.models import Q
 
from django.http import Http404, HttpResponse, HttpResponseForbidden
 
from django.shortcuts import render, redirect, get_object_or_404
 
from django.utils.hashcompat import sha_constructor
 

	
 
try:
 
    from hashlib import sha1 as sha_constructor
 
except ImportError:
 
    from django.utils.hashcompat import sha_constructor
 

	
 
from django.views import static
 

	
 
from django.contrib import messages
 
from django.contrib.auth.models import User
 
from django.contrib.auth.decorators import login_required
 

	
 
from account.models import EmailAddress
 
from symposion.proposals.models import ProposalBase, ProposalSection, ProposalKind
 
from symposion.proposals.models import SupportingDocument, AdditionalSpeaker
 
from symposion.speakers.models import Speaker
 
from symposion.utils.mail import send_email
 

	
 
from symposion.proposals.forms import AddSpeakerForm, SupportingDocumentCreateForm
 

	
 

	
 
def get_form(name):
 
    dot = name.rindex(".")
 
    mod_name, form_name = name[:dot], name[dot + 1:]
 
    __import__(mod_name)
 
    return getattr(sys.modules[mod_name], form_name)
 

	
 

	
 
def proposal_submit(request):
 
    if not request.user.is_authenticated():
 
        return redirect("home")  # @@@ unauth'd speaker info page?
 
    else:
 
        try:
 
            request.user.speaker_profile
 
        except ObjectDoesNotExist:
 
            return redirect("dashboard")
 
    
 
    kinds = []
 
    for proposal_section in ProposalSection.available():
 
        for kind in proposal_section.section.proposal_kinds.all():
 
            kinds.append(kind)
 
    
 
    return render(request, "proposals/proposal_submit.html", {
 
        "kinds": kinds,
 
    })
 

	
 

	
 
def proposal_submit_kind(request, kind_slug):
 
    
 
    kind = get_object_or_404(ProposalKind, slug=kind_slug)
 
    
 
    if not request.user.is_authenticated():
 
        return redirect("home")  # @@@ unauth'd speaker info page?
 
    else:
 
        try:
 
            speaker_profile = request.user.speaker_profile
 
        except ObjectDoesNotExist:
 
            return redirect("dashboard")
 
    
 
    if not kind.section.proposalsection.is_available():
 
        return redirect("proposal_submit")
 
    
 
    form_class = get_form(settings.PROPOSAL_FORMS[kind_slug])
 
    
 
    if request.method == "POST":
 
        form = form_class(request.POST)
 
        if form.is_valid():
 
            proposal = form.save(commit=False)
 
            proposal.kind = kind
 
            proposal.speaker = speaker_profile
 
            proposal.save()
 
            form.save_m2m()
 
            messages.success(request, "Proposal submitted.")
 
            if "add-speakers" in request.POST:
 
                return redirect("proposal_speaker_manage", proposal.pk)
 
            return redirect("dashboard")
 
    else:
 
        form = form_class()
 
    
 
    return render(request, "proposals/proposal_submit_kind.html", {
 
        "kind": kind,
 
        "form": form,
 
    })
 

	
 

	
 
@login_required
 
def proposal_speaker_manage(request, pk):
 
    queryset = ProposalBase.objects.select_related("speaker")
 
    proposal = get_object_or_404(queryset, pk=pk)
 
    proposal = ProposalBase.objects.get_subclass(pk=proposal.pk)
 
    
 
    if proposal.speaker != request.user.speaker_profile:
 
        raise Http404()
 
    
 
    if request.method == "POST":
 
        add_speaker_form = AddSpeakerForm(request.POST, proposal=proposal)
 
        if add_speaker_form.is_valid():
 
            message_ctx = {
 
                "proposal": proposal,
 
            }
 
            
 
            def create_speaker_token(email_address):
 
                # create token and look for an existing speaker to prevent
 
                # duplicate tokens and confusing the pending speaker
 
                try:
 
                    pending = Speaker.objects.get(
 
                        Q(user=None, invite_email=email_address)
 
                    )
 
                except Speaker.DoesNotExist:
 
                    salt = sha_constructor(str(random.random())).hexdigest()[:5]
 
                    token = sha_constructor(salt + email_address).hexdigest()
 
                    pending = Speaker.objects.create(
 
                        invite_email=email_address,
 
                        invite_token=token,
 
                    )
 
                else:
 
                    token = pending.invite_token
 
                return pending, token
 
            email_address = add_speaker_form.cleaned_data["email"]
 
            # check if email is on the site now
 
            users = EmailAddress.objects.get_users_for(email_address)
 
            if users:
 
                # should only be one since we enforce unique email
 
                user = users[0]
 
                message_ctx["user"] = user
 
                # look for speaker profile
 
                try:
 
                    speaker = user.speaker_profile
 
                except ObjectDoesNotExist:
 
                    speaker, token = create_speaker_token(email_address)
 
                    message_ctx["token"] = token
 
                    # fire off email to user to create profile
 
                    send_email(
 
                        [email_address], "speaker_no_profile",
 
                        context = message_ctx
 
                    )
 
                else:
 
                    # fire off email to user letting them they are loved.
 
                    send_email(
 
                        [email_address], "speaker_addition",
 
                        context = message_ctx
 
                    )
 
            else:
 
                speaker, token = create_speaker_token(email_address)
 
                message_ctx["token"] = token
 
                # fire off email letting user know about site and to create
 
                # account and speaker profile
 
                send_email(
 
                    [email_address], "speaker_invite",
 
                    context = message_ctx
 
                )
 
            invitation, created = AdditionalSpeaker.objects.get_or_create(proposalbase=proposal.proposalbase_ptr, speaker=speaker)
 
            messages.success(request, "Speaker invited to proposal.")
 
            return redirect("proposal_speaker_manage", proposal.pk)
 
    else:
 
        add_speaker_form = AddSpeakerForm(proposal=proposal)
 
    ctx = {
 
        "proposal": proposal,
 
        "speakers": proposal.speakers(),
 
        "add_speaker_form": add_speaker_form,
 
    }
 
    return render(request, "proposals/proposal_speaker_manage.html", ctx)
 

	
 

	
 
@login_required
 
def proposal_edit(request, pk):
 
    queryset = ProposalBase.objects.select_related("speaker")
 
    proposal = get_object_or_404(queryset, pk=pk)
 
    proposal = ProposalBase.objects.get_subclass(pk=proposal.pk)
 

	
 
    if request.user != proposal.speaker.user:
 
        raise Http404()
 
    
 
    if not proposal.can_edit():
 
        ctx = {
 
            "title": "Proposal editing closed",
 
            "body": "Proposal editing is closed for this session type."
 
        }
 
        return render(request, "proposals/proposal_error.html", ctx)
 
    
 
    form_class = get_form(settings.PROPOSAL_FORMS[proposal.kind.slug])
 

	
 
    if request.method == "POST":
 
        form = form_class(request.POST, instance=proposal)
 
        if form.is_valid():
 
            form.save()
 
            if hasattr(proposal, "reviews"):
 
                users = User.objects.filter(
 
                    Q(review__proposal=proposal) |
 
                    Q(proposalmessage__proposal=proposal)
 
                )
 
                users = users.exclude(id=request.user.id).distinct()
 
                for user in users:
 
                    ctx = {
 
                        "user": request.user,
 
                        "proposal": proposal,
 
                    }
 
                    send_email(
symposion/reviews/urls.py
Show inline comments
 
from django.conf.urls.defaults import patterns, url
 
from django.conf.urls import patterns, url
 

	
 

	
 
urlpatterns = patterns("symposion.reviews.views",
 
    url(r"^section/(?P<section_slug>[\w\-]+)/all/$", "review_section", {"reviewed": "all"}, name="review_section"),
 
    url(r"^section/(?P<section_slug>[\w\-]+)/reviewed/$", "review_section", {"reviewed": "reviewed"}, name="user_reviewed"),
 
    url(r"^section/(?P<section_slug>[\w\-]+)/not_reviewed/$", "review_section", {"reviewed": "not_reviewed"}, name="user_not_reviewed"),
 
    url(r"^section/(?P<section_slug>[\w\-]+)/assignments/$", "review_section", {"assigned": True}, name="review_section_assignments"),
 
    url(r"^section/(?P<section_slug>[\w\-]+)/status/$", "review_status", name="review_status"),
 
    url(r"^section/(?P<section_slug>[\w\-]+)/status/(?P<key>\w+)/$", "review_status", name="review_status"),
 
    url(r"^section/(?P<section_slug>[\w\-]+)/list/(?P<user_pk>\d+)/$", "review_list", name="review_list_user"),
 
    url(r"^section/(?P<section_slug>[\w\-]+)/admin/$", "review_admin", name="review_admin"),
 
    url(r"^section/(?P<section_slug>[\w\-]+)/admin/accept/$", "review_bulk_accept", name="review_bulk_accept"),
 
    url(r"^section/(?P<section_slug>[\w\-]+)/notification/(?P<status>\w+)/$", "result_notification", name="result_notification"),
 
    url(r"^section/(?P<section_slug>[\w\-]+)/notification/(?P<status>\w+)/prepare/$", "result_notification_prepare", name="result_notification_prepare"),
 
    url(r"^section/(?P<section_slug>[\w\-]+)/notification/(?P<status>\w+)/send/$", "result_notification_send", name="result_notification_send"),
 
    
 
    url(r"^review/(?P<pk>\d+)/$", "review_detail", name="review_detail"),
 
    
 
    url(r"^(?P<pk>\d+)/delete/$", "review_delete", name="review_delete"),
 
    url(r"^assignments/$", "review_assignments", name="review_assignments"),
 
    url(r"^assignment/(?P<pk>\d+)/opt-out/$", "review_assignment_opt_out", name="review_assignment_opt_out"),
 
)
symposion/schedule/urls.py
Show inline comments
 
from django.conf.urls.defaults import url, patterns
 
from django.conf.urls import url, patterns
 

	
 

	
 
urlpatterns = patterns("symposion.schedule.views",
 
    url(r"^$", "schedule_conference", name="schedule_conference"),
 
    url(r"^edit/$", "schedule_edit", name="schedule_edit"),
 
    url(r"^list/$", "schedule_list", name="schedule_list"),
 
    url(r"^presentations.csv$", "schedule_list_csv", name="schedule_list_csv"),
 
    url(r"^presentation/(\d+)/$", "schedule_presentation_detail", name="schedule_presentation_detail"),
 
    url(r"^([\w\-]+)/$", "schedule_detail", name="schedule_detail"),
 
    url(r"^([\w\-]+)/edit/$", "schedule_edit", name="schedule_edit"),
 
    url(r"^([\w\-]+)/list/$", "schedule_list", name="schedule_list"),
 
    url(r"^([\w\-]+)/presentations.csv$", "schedule_list_csv", name="schedule_list_csv"),
 
    url(r"^([\w\-]+)/edit/slot/(\d+)/", "schedule_slot_edit", name="schedule_slot_edit"),
 
)
symposion/speakers/urls.py
Show inline comments
 
from django.conf.urls.defaults import *
 
from django.conf.urls import patterns, url
 

	
 

	
 
urlpatterns = patterns("symposion.speakers.views",
 
    url(r"^create/$", "speaker_create", name="speaker_create"),
 
    url(r"^create/(\w+)/$", "speaker_create_token", name="speaker_create_token"),
 
    url(r"^edit/(?:(?P<pk>\d+)/)?$", "speaker_edit", name="speaker_edit"),
 
    url(r"^profile/(?P<pk>\d+)/$", "speaker_profile", name="speaker_profile"),
 
    url(r"^staff/create/(\d+)/$", "speaker_create_staff", name="speaker_create_staff"),
 
)
symposion/sponsorship/urls.py
Show inline comments
 
from django.conf.urls.defaults import patterns, url
 
from django.views.generic.simple import direct_to_template
 
from django.conf.urls import patterns, url
 
from django.views.generic import TemplateView
 

	
 

	
 
urlpatterns = patterns("symposion.sponsorship.views",
 
    url(r"^$", direct_to_template, {"template": "sponsorship/list.html"}, name="sponsor_list"),
 
    url(r"^$", TemplateView.as_view(template_name="sponsorship/list.html"), name="sponsor_list"),
 
    url(r"^apply/$", "sponsor_apply", name="sponsor_apply"),
 
    url(r"^add/$", "sponsor_add", name="sponsor_add"),
 
    url(r"^(?P<pk>\d+)/$", "sponsor_detail", name="sponsor_detail"),
 
)
symposion/teams/urls.py
Show inline comments
 
from django.conf.urls.defaults import *
 
from django.conf.urls import patterns, url
 

	
 

	
 
urlpatterns = patterns("symposion.teams.views",
 
    # team specific
 
    url(r"^(?P<slug>[\w\-]+)/$", "team_detail", name="team_detail"),
 
    url(r"^(?P<slug>[\w\-]+)/join/$", "team_join", name="team_join"),
 
    url(r"^(?P<slug>[\w\-]+)/leave/$", "team_leave", name="team_leave"),
 
    url(r"^(?P<slug>[\w\-]+)/apply/$", "team_apply", name="team_apply"),
 
    
 
    # membership specific
 
    url(r"^promote/(?P<pk>\d+)/$", "team_promote", name="team_promote"),
 
    url(r"^demote/(?P<pk>\d+)/$", "team_demote", name="team_demote"),
 
    url(r"^accept/(?P<pk>\d+)/$", "team_accept", name="team_accept"),
 
    url(r"^reject/(?P<pk>\d+)/$", "team_reject", name="team_reject"),
 
)
0 comments (0 inline, 0 general)