Merge branch 'i18n-all' of https://github.com/miurahr/symposion into miurahr-i18n-all
Conflicts: symposion/boxes/models.py symposion/conference/models.py symposion/schedule/models.py symposion/speakers/models.py symposion/sponsorship/admin.py symposion/sponsorship/models.py symposion/teams/models.py
This commit is contained in:
		
						commit
						67433cacb4
					
				
					 25 changed files with 340 additions and 241 deletions
				
			
		| 
						 | 
					@ -2,6 +2,7 @@ from __future__ import unicode_literals
 | 
				
			||||||
from django.db import models
 | 
					from django.db import models
 | 
				
			||||||
from django.contrib.auth.models import User
 | 
					from django.contrib.auth.models import User
 | 
				
			||||||
from django.utils.encoding import python_2_unicode_compatible
 | 
					from django.utils.encoding import python_2_unicode_compatible
 | 
				
			||||||
 | 
					from django.utils.translation import ugettext_lazy as _
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import reversion
 | 
					import reversion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,17 +12,17 @@ from markitup.fields import MarkupField
 | 
				
			||||||
@python_2_unicode_compatible
 | 
					@python_2_unicode_compatible
 | 
				
			||||||
class Box(models.Model):
 | 
					class Box(models.Model):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    label = models.CharField(max_length=100, db_index=True)
 | 
					    label = models.CharField(max_length=100, db_index=True, verbose_name=_("Label"))
 | 
				
			||||||
    content = MarkupField(blank=True)
 | 
					    content = MarkupField(blank=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    created_by = models.ForeignKey(User, related_name="boxes")
 | 
					    created_by = models.ForeignKey(User, related_name="boxes", verbose_name=_("Created by"))
 | 
				
			||||||
    last_updated_by = models.ForeignKey(User, related_name="updated_boxes")
 | 
					    last_updated_by = models.ForeignKey(User, related_name="updated_boxes", verbose_name=_("Last updated by"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __str__(self):
 | 
					    def __str__(self):
 | 
				
			||||||
        return self.label
 | 
					        return self.label
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class Meta:
 | 
					    class Meta:
 | 
				
			||||||
        verbose_name_plural = "boxes"
 | 
					        verbose_name = _("Box")
 | 
				
			||||||
 | 
					        verbose_name_plural = _("Boxes")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
reversion.register(Box)
 | 
					reversion.register(Box)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -40,6 +40,10 @@ class Page(models.Model):
 | 
				
			||||||
    def __str__(self):
 | 
					    def __str__(self):
 | 
				
			||||||
        return self.title
 | 
					        return self.title
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class Meta:
 | 
				
			||||||
 | 
					        verbose_name = _("page")
 | 
				
			||||||
 | 
					        verbose_name_plural = _("pages")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @models.permalink
 | 
					    @models.permalink
 | 
				
			||||||
    def get_absolute_url(self):
 | 
					    def get_absolute_url(self):
 | 
				
			||||||
        return ("cms_page", [self.path])
 | 
					        return ("cms_page", [self.path])
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,8 +1,9 @@
 | 
				
			||||||
from __future__ import unicode_literals
 | 
					from __future__ import unicode_literals
 | 
				
			||||||
from django.apps import AppConfig
 | 
					from django.apps import AppConfig
 | 
				
			||||||
 | 
					from django.utils.translation import ugettext_lazy as _
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ConferenceConfig(AppConfig):
 | 
					class ConferenceConfig(AppConfig):
 | 
				
			||||||
    name = "symposion.conference"
 | 
					    name = "symposion.conference"
 | 
				
			||||||
    label = "symposion_conference"
 | 
					    label = "symposion_conference"
 | 
				
			||||||
    verbose_name = "Symposion Conference"
 | 
					    verbose_name = _("Symposion Conference")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,11 +15,11 @@ class Conference(models.Model):
 | 
				
			||||||
    the full conference for a specific year, e.g. US PyCon 2012.
 | 
					    the full conference for a specific year, e.g. US PyCon 2012.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    title = models.CharField(_("title"), max_length=100)
 | 
					    title = models.CharField(_("Title"), max_length=100)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # when the conference runs
 | 
					    # when the conference runs
 | 
				
			||||||
    start_date = models.DateField(_("start date"), null=True, blank=True)
 | 
					    start_date = models.DateField(_("Start date"), null=True, blank=True)
 | 
				
			||||||
    end_date = models.DateField(_("end date"), null=True, blank=True)
 | 
					    end_date = models.DateField(_("End date"), null=True, blank=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # timezone the conference is in
 | 
					    # timezone the conference is in
 | 
				
			||||||
    timezone = TimeZoneField(blank=True, verbose_name=_("timezone"))
 | 
					    timezone = TimeZoneField(blank=True, verbose_name=_("timezone"))
 | 
				
			||||||
| 
						 | 
					@ -53,14 +53,14 @@ class Section(models.Model):
 | 
				
			||||||
    scheduling process.
 | 
					    scheduling process.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    conference = models.ForeignKey(Conference, verbose_name=_("conference"))
 | 
					    conference = models.ForeignKey(Conference, verbose_name=_("Conference"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    name = models.CharField(_("name"), max_length=100)
 | 
					    name = models.CharField(_("Name"), max_length=100)
 | 
				
			||||||
    slug = models.SlugField()
 | 
					    slug = models.SlugField(verbose_name=_("Slug"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # when the section runs
 | 
					    # when the section runs
 | 
				
			||||||
    start_date = models.DateField(_("start date"), null=True, blank=True)
 | 
					    start_date = models.DateField(_("Start date"), null=True, blank=True)
 | 
				
			||||||
    end_date = models.DateField(_("end date"), null=True, blank=True)
 | 
					    end_date = models.DateField(_("End date"), null=True, blank=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __str__(self):
 | 
					    def __str__(self):
 | 
				
			||||||
        return "%s %s" % (self.conference, self.name)
 | 
					        return "%s %s" % (self.conference, self.name)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,13 +6,14 @@ except ImportError:
 | 
				
			||||||
from django import forms
 | 
					from django import forms
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import account.forms
 | 
					import account.forms
 | 
				
			||||||
 | 
					from django.utils.translation import ugettext_lazy as _
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class SignupForm(account.forms.SignupForm):
 | 
					class SignupForm(account.forms.SignupForm):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    first_name = forms.CharField()
 | 
					    first_name = forms.CharField(label=_("First name"))
 | 
				
			||||||
    last_name = forms.CharField()
 | 
					    last_name = forms.CharField(label=_("Last name"))
 | 
				
			||||||
    email_confirm = forms.EmailField(label="Confirm Email")
 | 
					    email_confirm = forms.EmailField(label=_("Confirm Email"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, *args, **kwargs):
 | 
					    def __init__(self, *args, **kwargs):
 | 
				
			||||||
        super(SignupForm, self).__init__(*args, **kwargs)
 | 
					        super(SignupForm, self).__init__(*args, **kwargs)
 | 
				
			||||||
| 
						 | 
					@ -32,7 +33,7 @@ class SignupForm(account.forms.SignupForm):
 | 
				
			||||||
        if email:
 | 
					        if email:
 | 
				
			||||||
            if email != email_confirm:
 | 
					            if email != email_confirm:
 | 
				
			||||||
                raise forms.ValidationError(
 | 
					                raise forms.ValidationError(
 | 
				
			||||||
                    "Email address must match previously typed email address")
 | 
					                    _("Email address must match previously typed email address"))
 | 
				
			||||||
        return email_confirm
 | 
					        return email_confirm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,10 +2,11 @@ from __future__ import unicode_literals
 | 
				
			||||||
import csv
 | 
					import csv
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from django.http import HttpResponse
 | 
					from django.http import HttpResponse
 | 
				
			||||||
 | 
					from django.utils.translation import ugettext_lazy as _
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def export_as_csv_action(description="Export selected objects as CSV file",
 | 
					def export_as_csv_action(description=None, fields=None, exclude=None,
 | 
				
			||||||
                         fields=None, exclude=None, header=True):
 | 
					                         header=True):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    This function returns an export csv action
 | 
					    This function returns an export csv action
 | 
				
			||||||
    'fields' and 'exclude' work like in Django ModelForm
 | 
					    'fields' and 'exclude' work like in Django ModelForm
 | 
				
			||||||
| 
						 | 
					@ -32,5 +33,7 @@ def export_as_csv_action(description="Export selected objects as CSV file",
 | 
				
			||||||
            writer.writerow(
 | 
					            writer.writerow(
 | 
				
			||||||
                [unicode(getattr(obj, field)).encode("utf-8", "replace") for field in field_names])
 | 
					                [unicode(getattr(obj, field)).encode("utf-8", "replace") for field in field_names])
 | 
				
			||||||
        return response
 | 
					        return response
 | 
				
			||||||
 | 
					    if description is None:
 | 
				
			||||||
 | 
					        description = _("Export selected objects as CSV file")
 | 
				
			||||||
    export_as_csv.short_description = description
 | 
					    export_as_csv.short_description = description
 | 
				
			||||||
    return export_as_csv
 | 
					    return export_as_csv
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,8 +1,9 @@
 | 
				
			||||||
from __future__ import unicode_literals
 | 
					from __future__ import unicode_literals
 | 
				
			||||||
from django.apps import AppConfig
 | 
					from django.apps import AppConfig
 | 
				
			||||||
 | 
					from django.utils.translation import ugettext_lazy as _
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ProposalsConfig(AppConfig):
 | 
					class ProposalsConfig(AppConfig):
 | 
				
			||||||
    name = "symposion.proposals"
 | 
					    name = "symposion.proposals"
 | 
				
			||||||
    label = "symposion_proposals"
 | 
					    label = "symposion_proposals"
 | 
				
			||||||
    verbose_name = "Symposion Proposals"
 | 
					    verbose_name = _("Symposion Proposals")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,7 @@
 | 
				
			||||||
from __future__ import unicode_literals
 | 
					from __future__ import unicode_literals
 | 
				
			||||||
from django import forms
 | 
					from django import forms
 | 
				
			||||||
from django.db.models import Q
 | 
					from django.db.models import Q
 | 
				
			||||||
 | 
					from django.utils.translation import ugettext_lazy as _
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from symposion.proposals.models import SupportingDocument
 | 
					from symposion.proposals.models import SupportingDocument
 | 
				
			||||||
# from markitup.widgets import MarkItUpWidget
 | 
					# from markitup.widgets import MarkItUpWidget
 | 
				
			||||||
| 
						 | 
					@ -12,7 +13,7 @@ from symposion.proposals.models import SupportingDocument
 | 
				
			||||||
class AddSpeakerForm(forms.Form):
 | 
					class AddSpeakerForm(forms.Form):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    email = forms.EmailField(
 | 
					    email = forms.EmailField(
 | 
				
			||||||
        label="Email address of new speaker (use their email address, not yours)"
 | 
					        label=_("Email address of new speaker (use their email address, not yours)")
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, *args, **kwargs):
 | 
					    def __init__(self, *args, **kwargs):
 | 
				
			||||||
| 
						 | 
					@ -27,7 +28,7 @@ class AddSpeakerForm(forms.Form):
 | 
				
			||||||
        ).exists()
 | 
					        ).exists()
 | 
				
			||||||
        if exists:
 | 
					        if exists:
 | 
				
			||||||
            raise forms.ValidationError(
 | 
					            raise forms.ValidationError(
 | 
				
			||||||
                "This email address has already been invited to your talk proposal"
 | 
					                _("This email address has already been invited to your talk proposal")
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
        return value
 | 
					        return value
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -34,12 +34,12 @@ class ProposalSection(models.Model):
 | 
				
			||||||
      * closed is NULL or False
 | 
					      * closed is NULL or False
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    section = models.OneToOneField(Section)
 | 
					    section = models.OneToOneField(Section, verbose_name=_("Section"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    start = models.DateTimeField(null=True, blank=True)
 | 
					    start = models.DateTimeField(null=True, blank=True, verbose_name=_("Start"))
 | 
				
			||||||
    end = models.DateTimeField(null=True, blank=True)
 | 
					    end = models.DateTimeField(null=True, blank=True, verbose_name=_("End"))
 | 
				
			||||||
    closed = models.NullBooleanField()
 | 
					    closed = models.NullBooleanField(verbose_name=_("Closed"))
 | 
				
			||||||
    published = models.NullBooleanField()
 | 
					    published = models.NullBooleanField(verbose_name=_("Published"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @classmethod
 | 
					    @classmethod
 | 
				
			||||||
    def available(cls):
 | 
					    def available(cls):
 | 
				
			||||||
| 
						 | 
					@ -71,10 +71,10 @@ class ProposalKind(models.Model):
 | 
				
			||||||
    to distinguish the section as well as the kind.
 | 
					    to distinguish the section as well as the kind.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    section = models.ForeignKey(Section, related_name="proposal_kinds")
 | 
					    section = models.ForeignKey(Section, related_name="proposal_kinds", verbose_name=_("Section"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    name = models.CharField(_("Name"), max_length=100)
 | 
					    name = models.CharField(_("Name"), max_length=100)
 | 
				
			||||||
    slug = models.SlugField()
 | 
					    slug = models.SlugField(verbose_name=_("Slug"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __str__(self):
 | 
					    def __str__(self):
 | 
				
			||||||
        return self.name
 | 
					        return self.name
 | 
				
			||||||
| 
						 | 
					@ -85,9 +85,9 @@ class ProposalBase(models.Model):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    objects = InheritanceManager()
 | 
					    objects = InheritanceManager()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    kind = models.ForeignKey(ProposalKind)
 | 
					    kind = models.ForeignKey(ProposalKind, verbose_name=_("Kind"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    title = models.CharField(max_length=100)
 | 
					    title = models.CharField(max_length=100, verbose_name=_("Title"))
 | 
				
			||||||
    description = models.TextField(
 | 
					    description = models.TextField(
 | 
				
			||||||
        _("Brief Description"),
 | 
					        _("Brief Description"),
 | 
				
			||||||
        max_length=400,  # @@@ need to enforce 400 in UI
 | 
					        max_length=400,  # @@@ need to enforce 400 in UI
 | 
				
			||||||
| 
						 | 
					@ -101,6 +101,7 @@ class ProposalBase(models.Model):
 | 
				
			||||||
                    "target='_blank'>Markdown</a>.")
 | 
					                    "target='_blank'>Markdown</a>.")
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    additional_notes = MarkupField(
 | 
					    additional_notes = MarkupField(
 | 
				
			||||||
 | 
					        _("Addtional Notes"),
 | 
				
			||||||
        blank=True,
 | 
					        blank=True,
 | 
				
			||||||
        help_text=_("Anything else you'd like the program committee to know when making their "
 | 
					        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 "
 | 
					                    "selection: your past experience, etc. This is not made public. Edit using "
 | 
				
			||||||
| 
						 | 
					@ -110,8 +111,9 @@ class ProposalBase(models.Model):
 | 
				
			||||||
    submitted = models.DateTimeField(
 | 
					    submitted = models.DateTimeField(
 | 
				
			||||||
        default=now,
 | 
					        default=now,
 | 
				
			||||||
        editable=False,
 | 
					        editable=False,
 | 
				
			||||||
 | 
					        verbose_name=_("Submitted")
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    speaker = models.ForeignKey(Speaker, related_name="proposals")
 | 
					    speaker = models.ForeignKey(Speaker, related_name="proposals", verbose_name=_("Speaker"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def additional_speaker_validator(self, a_speaker):
 | 
					    def additional_speaker_validator(self, a_speaker):
 | 
				
			||||||
        if a_speaker.speaker.email == self.speaker.email:
 | 
					        if a_speaker.speaker.email == self.speaker.email:
 | 
				
			||||||
| 
						 | 
					@ -120,8 +122,9 @@ class ProposalBase(models.Model):
 | 
				
			||||||
            raise ValidationError(_("%s has already been in speakers.") % a_speaker.speaker.email)
 | 
					            raise ValidationError(_("%s has already been in speakers.") % a_speaker.speaker.email)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    additional_speakers = models.ManyToManyField(Speaker, through="AdditionalSpeaker",
 | 
					    additional_speakers = models.ManyToManyField(Speaker, through="AdditionalSpeaker",
 | 
				
			||||||
                                                 blank=True, validators=[additional_speaker_validator])
 | 
					                                                 blank=True, verbose_name=_("Addtional speakers"),
 | 
				
			||||||
    cancelled = models.BooleanField(default=False)
 | 
					                                                 validators=[additional_speaker_validator])
 | 
				
			||||||
 | 
					    cancelled = models.BooleanField(default=False, verbose_name=_("Cancelled"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def can_edit(self):
 | 
					    def can_edit(self):
 | 
				
			||||||
        return True
 | 
					        return True
 | 
				
			||||||
| 
						 | 
					@ -179,12 +182,14 @@ class AdditionalSpeaker(models.Model):
 | 
				
			||||||
        (SPEAKING_STATUS_DECLINED, _("Declined")),
 | 
					        (SPEAKING_STATUS_DECLINED, _("Declined")),
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    speaker = models.ForeignKey(Speaker)
 | 
					    speaker = models.ForeignKey(Speaker, verbose_name=_("Speaker"))
 | 
				
			||||||
    proposalbase = models.ForeignKey(ProposalBase)
 | 
					    proposalbase = models.ForeignKey(ProposalBase, verbose_name=_("Proposalbase"))
 | 
				
			||||||
    status = models.IntegerField(choices=SPEAKING_STATUS, default=SPEAKING_STATUS_PENDING)
 | 
					    status = models.IntegerField(choices=SPEAKING_STATUS, default=SPEAKING_STATUS_PENDING, verbose_name=_("Status"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class Meta:
 | 
					    class Meta:
 | 
				
			||||||
        unique_together = ("speaker", "proposalbase")
 | 
					        unique_together = ("speaker", "proposalbase")
 | 
				
			||||||
 | 
					        verbose_name = _("Addtional speaker")
 | 
				
			||||||
 | 
					        verbose_name_plural = _("Additional speakers")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __str__(self):
 | 
					    def __str__(self):
 | 
				
			||||||
        if self.status is self.SPEAKING_STATUS_PENDING:
 | 
					        if self.status is self.SPEAKING_STATUS_PENDING:
 | 
				
			||||||
| 
						 | 
					@ -203,14 +208,14 @@ def uuid_filename(instance, filename):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class SupportingDocument(models.Model):
 | 
					class SupportingDocument(models.Model):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    proposal = models.ForeignKey(ProposalBase, related_name="supporting_documents")
 | 
					    proposal = models.ForeignKey(ProposalBase, related_name="supporting_documents", verbose_name=_("Proposal"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uploaded_by = models.ForeignKey(User)
 | 
					    uploaded_by = models.ForeignKey(User, verbose_name=_("Uploaded by"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    created_at = models.DateTimeField(default=now)
 | 
					    created_at = models.DateTimeField(default=now, verbose_name=_("Created at"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    file = models.FileField(upload_to=uuid_filename)
 | 
					    file = models.FileField(upload_to=uuid_filename, verbose_name=_("File"))
 | 
				
			||||||
    description = models.CharField(max_length=140)
 | 
					    description = models.CharField(max_length=140, verbose_name=_("Description"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def download_url(self):
 | 
					    def download_url(self):
 | 
				
			||||||
        return reverse("proposal_document_download",
 | 
					        return reverse("proposal_document_download",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -88,7 +88,7 @@ def proposal_submit_kind(request, kind_slug):
 | 
				
			||||||
            proposal.speaker = speaker_profile
 | 
					            proposal.speaker = speaker_profile
 | 
				
			||||||
            proposal.save()
 | 
					            proposal.save()
 | 
				
			||||||
            form.save_m2m()
 | 
					            form.save_m2m()
 | 
				
			||||||
            messages.success(request, "Proposal submitted.")
 | 
					            messages.success(request, _("Proposal submitted."))
 | 
				
			||||||
            if "add-speakers" in request.POST:
 | 
					            if "add-speakers" in request.POST:
 | 
				
			||||||
                return redirect("proposal_speaker_manage", proposal.pk)
 | 
					                return redirect("proposal_speaker_manage", proposal.pk)
 | 
				
			||||||
            return redirect("dashboard")
 | 
					            return redirect("dashboard")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,8 +1,9 @@
 | 
				
			||||||
from __future__ import unicode_literals
 | 
					from __future__ import unicode_literals
 | 
				
			||||||
from django.apps import AppConfig
 | 
					from django.apps import AppConfig
 | 
				
			||||||
 | 
					from django.utils.translation import ugettext_lazy as _
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ReviewsConfig(AppConfig):
 | 
					class ReviewsConfig(AppConfig):
 | 
				
			||||||
    name = "symposion.reviews"
 | 
					    name = "symposion.reviews"
 | 
				
			||||||
    label = "symposion_reviews"
 | 
					    label = "symposion_reviews"
 | 
				
			||||||
    verbose_name = "Symposion Reviews"
 | 
					    verbose_name = _("Symposion Reviews")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,6 @@
 | 
				
			||||||
from __future__ import unicode_literals
 | 
					from __future__ import unicode_literals
 | 
				
			||||||
from django import forms
 | 
					from django import forms
 | 
				
			||||||
 | 
					from django.utils.translation import ugettext_lazy as _
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from markitup.widgets import MarkItUpWidget
 | 
					from markitup.widgets import MarkItUpWidget
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -36,6 +37,7 @@ class SpeakerCommentForm(forms.ModelForm):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class BulkPresentationForm(forms.Form):
 | 
					class BulkPresentationForm(forms.Form):
 | 
				
			||||||
    talk_ids = forms.CharField(
 | 
					    talk_ids = forms.CharField(
 | 
				
			||||||
 | 
					        label=_("Talk ids"),
 | 
				
			||||||
        max_length=500,
 | 
					        max_length=500,
 | 
				
			||||||
        help_text="Provide a comma seperated list of talk ids to accept."
 | 
					        help_text=_("Provide a comma seperated list of talk ids to accept.")
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,6 +8,7 @@ from django.db.models import Q
 | 
				
			||||||
from django.db.models.signals import post_save
 | 
					from django.db.models.signals import post_save
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from django.contrib.auth.models import User
 | 
					from django.contrib.auth.models import User
 | 
				
			||||||
 | 
					from django.utils.translation import ugettext_lazy as _
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from markitup.fields import MarkupField
 | 
					from markitup.fields import MarkupField
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -32,10 +33,10 @@ class Votes(object):
 | 
				
			||||||
    MINUS_ONE = "−1"
 | 
					    MINUS_ONE = "−1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    CHOICES = [
 | 
					    CHOICES = [
 | 
				
			||||||
        (PLUS_ONE, u"+1 — Good proposal and I will argue for it to be accepted."),
 | 
					        (PLUS_ONE, _("+1 — Good proposal and I will argue for it to be accepted.")),
 | 
				
			||||||
        (PLUS_ZERO, u"+0 — OK proposal, but I will not argue for it to be accepted."),
 | 
					        (PLUS_ZERO, _("+0 — OK proposal, but I will not argue for it to be accepted.")),
 | 
				
			||||||
        (MINUS_ZERO, u"−0 — Weak proposal, but I will not argue strongly against acceptance."),
 | 
					        (MINUS_ZERO, _("−0 — Weak proposal, but I will not argue strongly against acceptance.")),
 | 
				
			||||||
        (MINUS_ONE, u"−1 — Serious issues and I will argue to reject this proposal."),
 | 
					        (MINUS_ONE, _("−1 — Serious issues and I will argue to reject this proposal.")),
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
VOTES = Votes()
 | 
					VOTES = Votes()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -48,18 +49,18 @@ class ReviewAssignment(models.Model):
 | 
				
			||||||
    NUM_REVIEWERS = 3
 | 
					    NUM_REVIEWERS = 3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ORIGIN_CHOICES = [
 | 
					    ORIGIN_CHOICES = [
 | 
				
			||||||
        (AUTO_ASSIGNED_INITIAL, "auto-assigned, initial"),
 | 
					        (AUTO_ASSIGNED_INITIAL, _("auto-assigned, initial")),
 | 
				
			||||||
        (OPT_IN, "opted-in"),
 | 
					        (OPT_IN, _("opted-in")),
 | 
				
			||||||
        (AUTO_ASSIGNED_LATER, "auto-assigned, later"),
 | 
					        (AUTO_ASSIGNED_LATER, _("auto-assigned, later")),
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    proposal = models.ForeignKey(ProposalBase)
 | 
					    proposal = models.ForeignKey(ProposalBase, verbose_name=_("Proposal"))
 | 
				
			||||||
    user = models.ForeignKey(User)
 | 
					    user = models.ForeignKey(User, verbose_name=_("User"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    origin = models.IntegerField(choices=ORIGIN_CHOICES)
 | 
					    origin = models.IntegerField(choices=ORIGIN_CHOICES, verbose_name=_("Origin"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    assigned_at = models.DateTimeField(default=datetime.now)
 | 
					    assigned_at = models.DateTimeField(default=datetime.now, verbose_name=_("Assigned at"))
 | 
				
			||||||
    opted_out = models.BooleanField(default=False)
 | 
					    opted_out = models.BooleanField(default=False, verbose_name=_("Opted out"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @classmethod
 | 
					    @classmethod
 | 
				
			||||||
    def create_assignments(cls, proposal, origin=AUTO_ASSIGNED_INITIAL):
 | 
					    def create_assignments(cls, proposal, origin=AUTO_ASSIGNED_INITIAL):
 | 
				
			||||||
| 
						 | 
					@ -93,27 +94,29 @@ class ReviewAssignment(models.Model):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ProposalMessage(models.Model):
 | 
					class ProposalMessage(models.Model):
 | 
				
			||||||
    proposal = models.ForeignKey(ProposalBase, related_name="messages")
 | 
					    proposal = models.ForeignKey(ProposalBase, related_name="messages", verbose_name=_("Proposal"))
 | 
				
			||||||
    user = models.ForeignKey(User)
 | 
					    user = models.ForeignKey(User, verbose_name=_("User"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    message = MarkupField()
 | 
					    message = MarkupField(verbose_name=_("Message"))
 | 
				
			||||||
    submitted_at = models.DateTimeField(default=datetime.now, editable=False)
 | 
					    submitted_at = models.DateTimeField(default=datetime.now, editable=False, verbose_name=_("Submitted at"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class Meta:
 | 
					    class Meta:
 | 
				
			||||||
        ordering = ["submitted_at"]
 | 
					        ordering = ["submitted_at"]
 | 
				
			||||||
 | 
					        verbose_name = _("proposal message")
 | 
				
			||||||
 | 
					        verbose_name_plural = _("proposal messages")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Review(models.Model):
 | 
					class Review(models.Model):
 | 
				
			||||||
    VOTES = VOTES
 | 
					    VOTES = VOTES
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    proposal = models.ForeignKey(ProposalBase, related_name="reviews")
 | 
					    proposal = models.ForeignKey(ProposalBase, related_name="reviews", verbose_name=_("Proposal"))
 | 
				
			||||||
    user = models.ForeignKey(User)
 | 
					    user = models.ForeignKey(User, verbose_name=_("User"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # No way to encode "-0" vs. "+0" into an IntegerField, and I don't feel
 | 
					    # No way to encode "-0" vs. "+0" into an IntegerField, and I don't feel
 | 
				
			||||||
    # like some complicated encoding system.
 | 
					    # like some complicated encoding system.
 | 
				
			||||||
    vote = models.CharField(max_length=2, blank=True, choices=VOTES.CHOICES)
 | 
					    vote = models.CharField(max_length=2, blank=True, choices=VOTES.CHOICES, verbose_name=_("Vote"))
 | 
				
			||||||
    comment = MarkupField()
 | 
					    comment = MarkupField(verbose_name=_("Comment"))
 | 
				
			||||||
    submitted_at = models.DateTimeField(default=datetime.now, editable=False)
 | 
					    submitted_at = models.DateTimeField(default=datetime.now, editable=False, verbose_name=_("Submitted at"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def save(self, **kwargs):
 | 
					    def save(self, **kwargs):
 | 
				
			||||||
        if self.vote:
 | 
					        if self.vote:
 | 
				
			||||||
| 
						 | 
					@ -181,20 +184,26 @@ class Review(models.Model):
 | 
				
			||||||
    def section(self):
 | 
					    def section(self):
 | 
				
			||||||
        return self.proposal.kind.section.slug
 | 
					        return self.proposal.kind.section.slug
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class Meta:
 | 
				
			||||||
 | 
					        verbose_name = _("review")
 | 
				
			||||||
 | 
					        verbose_name_plural = _("reviews")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class LatestVote(models.Model):
 | 
					class LatestVote(models.Model):
 | 
				
			||||||
    VOTES = VOTES
 | 
					    VOTES = VOTES
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    proposal = models.ForeignKey(ProposalBase, related_name="votes")
 | 
					    proposal = models.ForeignKey(ProposalBase, related_name="votes", verbose_name=_("Proposal"))
 | 
				
			||||||
    user = models.ForeignKey(User)
 | 
					    user = models.ForeignKey(User, verbose_name=_("User"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # No way to encode "-0" vs. "+0" into an IntegerField, and I don't feel
 | 
					    # No way to encode "-0" vs. "+0" into an IntegerField, and I don't feel
 | 
				
			||||||
    # like some complicated encoding system.
 | 
					    # like some complicated encoding system.
 | 
				
			||||||
    vote = models.CharField(max_length=2, choices=VOTES.CHOICES)
 | 
					    vote = models.CharField(max_length=2, choices=VOTES.CHOICES, verbose_name=_("Vote"))
 | 
				
			||||||
    submitted_at = models.DateTimeField(default=datetime.now, editable=False)
 | 
					    submitted_at = models.DateTimeField(default=datetime.now, editable=False, verbose_name=_("Submitted at"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class Meta:
 | 
					    class Meta:
 | 
				
			||||||
        unique_together = [("proposal", "user")]
 | 
					        unique_together = [("proposal", "user")]
 | 
				
			||||||
 | 
					        verbose_name = _("latest vote")
 | 
				
			||||||
 | 
					        verbose_name_plural = _("latest votes")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def css_class(self):
 | 
					    def css_class(self):
 | 
				
			||||||
        return {
 | 
					        return {
 | 
				
			||||||
| 
						 | 
					@ -206,25 +215,25 @@ class LatestVote(models.Model):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ProposalResult(models.Model):
 | 
					class ProposalResult(models.Model):
 | 
				
			||||||
    proposal = models.OneToOneField(ProposalBase, related_name="result")
 | 
					    proposal = models.OneToOneField(ProposalBase, related_name="result", verbose_name=_("Proposal"))
 | 
				
			||||||
    score = models.DecimalField(max_digits=5, decimal_places=2, default=Decimal("0.00"))
 | 
					    score = models.DecimalField(max_digits=5, decimal_places=2, default=Decimal("0.00"), verbose_name=_("Score"))
 | 
				
			||||||
    comment_count = models.PositiveIntegerField(default=0)
 | 
					    comment_count = models.PositiveIntegerField(default=0, verbose_name=_("Comment count"))
 | 
				
			||||||
    vote_count = models.PositiveIntegerField(default=0)
 | 
					    vote_count = models.PositiveIntegerField(default=0, verbose_name=_("Vote count"))
 | 
				
			||||||
    plus_one = models.PositiveIntegerField(default=0)
 | 
					    plus_one = models.PositiveIntegerField(default=0, verbose_name=_("Plus one"))
 | 
				
			||||||
    plus_zero = models.PositiveIntegerField(default=0)
 | 
					    plus_zero = models.PositiveIntegerField(default=0, verbose_name=_("Plus zero"))
 | 
				
			||||||
    minus_zero = models.PositiveIntegerField(default=0)
 | 
					    minus_zero = models.PositiveIntegerField(default=0, verbose_name=_("Minus zero"))
 | 
				
			||||||
    minus_one = models.PositiveIntegerField(default=0)
 | 
					    minus_one = models.PositiveIntegerField(default=0, verbose_name=_("Minus one"))
 | 
				
			||||||
    accepted = models.NullBooleanField(choices=[
 | 
					    accepted = models.NullBooleanField(choices=[
 | 
				
			||||||
        (True, "accepted"),
 | 
					        (True, "accepted"),
 | 
				
			||||||
        (False, "rejected"),
 | 
					        (False, "rejected"),
 | 
				
			||||||
        (None, "undecided"),
 | 
					        (None, "undecided"),
 | 
				
			||||||
    ], default=None)
 | 
					    ], default=None, verbose_name=_("Accepted"))
 | 
				
			||||||
    status = models.CharField(max_length=20, choices=[
 | 
					    status = models.CharField(max_length=20, choices=[
 | 
				
			||||||
        ("accepted", "accepted"),
 | 
					        ("accepted", _("accepted")),
 | 
				
			||||||
        ("rejected", "rejected"),
 | 
					        ("rejected", _("rejected")),
 | 
				
			||||||
        ("undecided", "undecided"),
 | 
					        ("undecided", _("undecided")),
 | 
				
			||||||
        ("standby", "standby"),
 | 
					        ("standby", _("standby")),
 | 
				
			||||||
    ], default="undecided")
 | 
					    ], default="undecided", verbose_name=_("Status"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @classmethod
 | 
					    @classmethod
 | 
				
			||||||
    def full_calculate(cls):
 | 
					    def full_calculate(cls):
 | 
				
			||||||
| 
						 | 
					@ -280,35 +289,47 @@ class ProposalResult(models.Model):
 | 
				
			||||||
        model = self.__class__
 | 
					        model = self.__class__
 | 
				
			||||||
        model._default_manager.filter(pk=self.pk).update(score=ProposalScoreExpression())
 | 
					        model._default_manager.filter(pk=self.pk).update(score=ProposalScoreExpression())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class Meta:
 | 
				
			||||||
 | 
					        verbose_name = _("proposal_result")
 | 
				
			||||||
 | 
					        verbose_name_plural = _("proposal_results")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Comment(models.Model):
 | 
					class Comment(models.Model):
 | 
				
			||||||
    proposal = models.ForeignKey(ProposalBase, related_name="comments")
 | 
					    proposal = models.ForeignKey(ProposalBase, related_name="comments", verbose_name=_("Proposal"))
 | 
				
			||||||
    commenter = models.ForeignKey(User)
 | 
					    commenter = models.ForeignKey(User, verbose_name=_("Commenter"))
 | 
				
			||||||
    text = MarkupField()
 | 
					    text = MarkupField(verbose_name=_("Text"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Or perhaps more accurately, can the user see this comment.
 | 
					    # Or perhaps more accurately, can the user see this comment.
 | 
				
			||||||
    public = models.BooleanField(choices=[(True, "public"), (False, "private")], default=False)
 | 
					    public = models.BooleanField(choices=[(True, _("public")), (False, _("private"))], default=False, verbose_name=_("Public"))
 | 
				
			||||||
    commented_at = models.DateTimeField(default=datetime.now)
 | 
					    commented_at = models.DateTimeField(default=datetime.now, verbose_name=_("Commented at"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class Meta:
 | 
				
			||||||
 | 
					        verbose_name = _("comment")
 | 
				
			||||||
 | 
					        verbose_name_plural = _("comments")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class NotificationTemplate(models.Model):
 | 
					class NotificationTemplate(models.Model):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    label = models.CharField(max_length=100)
 | 
					    label = models.CharField(max_length=100, verbose_name=_("Label"))
 | 
				
			||||||
    from_address = models.EmailField()
 | 
					    from_address = models.EmailField(verbose_name=_("From address"))
 | 
				
			||||||
    subject = models.CharField(max_length=100)
 | 
					    subject = models.CharField(max_length=100, verbose_name=_("Subject"))
 | 
				
			||||||
    body = models.TextField()
 | 
					    body = models.TextField(verbose_name=_("Body"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class Meta:
 | 
				
			||||||
 | 
					        verbose_name = _("notification template")
 | 
				
			||||||
 | 
					        verbose_name_plural = _("notification templates")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ResultNotification(models.Model):
 | 
					class ResultNotification(models.Model):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    proposal = models.ForeignKey(ProposalBase, related_name="notifications")
 | 
					    proposal = models.ForeignKey(ProposalBase, related_name="notifications", verbose_name=_("Proposal"))
 | 
				
			||||||
    template = models.ForeignKey(NotificationTemplate, null=True, blank=True,
 | 
					    template = models.ForeignKey(NotificationTemplate, null=True, blank=True,
 | 
				
			||||||
                                 on_delete=models.SET_NULL)
 | 
					                                 on_delete=models.SET_NULL, verbose_name=_("Template"))
 | 
				
			||||||
    timestamp = models.DateTimeField(default=datetime.now)
 | 
					    timestamp = models.DateTimeField(default=datetime.now, verbose_name=_("Timestamp"))
 | 
				
			||||||
    to_address = models.EmailField()
 | 
					    to_address = models.EmailField(verbose_name=_("To address"))
 | 
				
			||||||
    from_address = models.EmailField()
 | 
					    from_address = models.EmailField(verbose_name=_("From address"))
 | 
				
			||||||
    subject = models.CharField(max_length=100)
 | 
					    subject = models.CharField(max_length=100, verbose_name=_("Subject"))
 | 
				
			||||||
    body = models.TextField()
 | 
					    body = models.TextField(verbose_name=_("Body"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def recipients(self):
 | 
					    def recipients(self):
 | 
				
			||||||
        for speaker in self.proposal.speakers():
 | 
					        for speaker in self.proposal.speakers():
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,10 +1,12 @@
 | 
				
			||||||
from __future__ import unicode_literals
 | 
					from __future__ import unicode_literals
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import datetime
 | 
					import datetime
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from django.core.exceptions import ObjectDoesNotExist
 | 
					from django.core.exceptions import ObjectDoesNotExist
 | 
				
			||||||
from django.contrib.auth.models import User
 | 
					from django.contrib.auth.models import User
 | 
				
			||||||
from django.db import models
 | 
					from django.db import models
 | 
				
			||||||
from django.utils.encoding import python_2_unicode_compatible
 | 
					from django.utils.encoding import python_2_unicode_compatible
 | 
				
			||||||
 | 
					from django.utils.translation import ugettext_lazy as _
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from markitup.fields import MarkupField
 | 
					from markitup.fields import MarkupField
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,22 +18,24 @@ from symposion.speakers.models import Speaker
 | 
				
			||||||
@python_2_unicode_compatible
 | 
					@python_2_unicode_compatible
 | 
				
			||||||
class Schedule(models.Model):
 | 
					class Schedule(models.Model):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    section = models.OneToOneField(Section)
 | 
					    section = models.OneToOneField(Section, verbose_name=_("Section"))
 | 
				
			||||||
    published = models.BooleanField(default=True)
 | 
					    published = models.BooleanField(default=True, verbose_name=_("Published"))
 | 
				
			||||||
    hidden = models.BooleanField("Hide schedule from overall conference view", default=False)
 | 
					    hidden = models.BooleanField(_("Hide schedule from overall conference view"), default=False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __str__(self):
 | 
					    def __str__(self):
 | 
				
			||||||
        return "%s Schedule" % self.section
 | 
					        return "%s Schedule" % self.section
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class Meta:
 | 
					    class Meta:
 | 
				
			||||||
        ordering = ["section"]
 | 
					        ordering = ["section"]
 | 
				
			||||||
 | 
					        verbose_name = _('Schedule')
 | 
				
			||||||
 | 
					        verbose_name_plural = _('Schedules')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@python_2_unicode_compatible
 | 
					@python_2_unicode_compatible
 | 
				
			||||||
class Day(models.Model):
 | 
					class Day(models.Model):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    schedule = models.ForeignKey(Schedule)
 | 
					    schedule = models.ForeignKey(Schedule, verbose_name=_("Schedule"))
 | 
				
			||||||
    date = models.DateField()
 | 
					    date = models.DateField(verbose_name=_("Date"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __str__(self):
 | 
					    def __str__(self):
 | 
				
			||||||
        return "%s" % self.date
 | 
					        return "%s" % self.date
 | 
				
			||||||
| 
						 | 
					@ -39,18 +43,24 @@ class Day(models.Model):
 | 
				
			||||||
    class Meta:
 | 
					    class Meta:
 | 
				
			||||||
        unique_together = [("schedule", "date")]
 | 
					        unique_together = [("schedule", "date")]
 | 
				
			||||||
        ordering = ["date"]
 | 
					        ordering = ["date"]
 | 
				
			||||||
 | 
					        verbose_name = _("date")
 | 
				
			||||||
 | 
					        verbose_name_plural = _("dates")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@python_2_unicode_compatible
 | 
					@python_2_unicode_compatible
 | 
				
			||||||
class Room(models.Model):
 | 
					class Room(models.Model):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    schedule = models.ForeignKey(Schedule)
 | 
					    schedule = models.ForeignKey(Schedule, verbose_name=_("Schedule"))
 | 
				
			||||||
    name = models.CharField(max_length=65)
 | 
					    name = models.CharField(max_length=65, verbose_name=_("Name"))
 | 
				
			||||||
    order = models.PositiveIntegerField()
 | 
					    order = models.PositiveIntegerField(verbose_name=_("Order"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __str__(self):
 | 
					    def __str__(self):
 | 
				
			||||||
        return self.name
 | 
					        return self.name
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class Meta:
 | 
				
			||||||
 | 
					        verbose_name = _("Room")
 | 
				
			||||||
 | 
					        verbose_name_plural = _("Rooms")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@python_2_unicode_compatible
 | 
					@python_2_unicode_compatible
 | 
				
			||||||
class SlotKind(models.Model):
 | 
					class SlotKind(models.Model):
 | 
				
			||||||
| 
						 | 
					@ -59,21 +69,25 @@ class SlotKind(models.Model):
 | 
				
			||||||
    break, lunch, or X-minute talk.
 | 
					    break, lunch, or X-minute talk.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    schedule = models.ForeignKey(Schedule)
 | 
					    schedule = models.ForeignKey(Schedule, verbose_name=_("schedule"))
 | 
				
			||||||
    label = models.CharField(max_length=50)
 | 
					    label = models.CharField(max_length=50, verbose_name=_("Label"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __str__(self):
 | 
					    def __str__(self):
 | 
				
			||||||
        return self.label
 | 
					        return self.label
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class Meta:
 | 
				
			||||||
 | 
					        verbose_name = _("Slot kind")
 | 
				
			||||||
 | 
					        verbose_name_plural = _("Slot kinds")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@python_2_unicode_compatible
 | 
					@python_2_unicode_compatible
 | 
				
			||||||
class Slot(models.Model):
 | 
					class Slot(models.Model):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    day = models.ForeignKey(Day)
 | 
					    day = models.ForeignKey(Day, verbose_name=_("Day"))
 | 
				
			||||||
    kind = models.ForeignKey(SlotKind)
 | 
					    kind = models.ForeignKey(SlotKind, verbose_name=_("Kind"))
 | 
				
			||||||
    start = models.TimeField()
 | 
					    start = models.TimeField(verbose_name=_("Start"))
 | 
				
			||||||
    end = models.TimeField()
 | 
					    end = models.TimeField(verbose_name=_("End"))
 | 
				
			||||||
    content_override = MarkupField(blank=True)
 | 
					    content_override = MarkupField(blank=True, verbose_name=_("Content override"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def assign(self, content):
 | 
					    def assign(self, content):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
| 
						 | 
					@ -137,6 +151,8 @@ class Slot(models.Model):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class Meta:
 | 
					    class Meta:
 | 
				
			||||||
        ordering = ["day", "start", "end"]
 | 
					        ordering = ["day", "start", "end"]
 | 
				
			||||||
 | 
					        verbose_name = _("slot")
 | 
				
			||||||
 | 
					        verbose_name_plural = _("slots")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@python_2_unicode_compatible
 | 
					@python_2_unicode_compatible
 | 
				
			||||||
| 
						 | 
					@ -145,8 +161,8 @@ class SlotRoom(models.Model):
 | 
				
			||||||
    Links a slot with a room.
 | 
					    Links a slot with a room.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    slot = models.ForeignKey(Slot)
 | 
					    slot = models.ForeignKey(Slot, verbose_name=_("Slot"))
 | 
				
			||||||
    room = models.ForeignKey(Room)
 | 
					    room = models.ForeignKey(Room, verbose_name=_("Room"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __str__(self):
 | 
					    def __str__(self):
 | 
				
			||||||
        return "%s %s" % (self.room, self.slot)
 | 
					        return "%s %s" % (self.room, self.slot)
 | 
				
			||||||
| 
						 | 
					@ -154,21 +170,23 @@ class SlotRoom(models.Model):
 | 
				
			||||||
    class Meta:
 | 
					    class Meta:
 | 
				
			||||||
        unique_together = [("slot", "room")]
 | 
					        unique_together = [("slot", "room")]
 | 
				
			||||||
        ordering = ["slot", "room__order"]
 | 
					        ordering = ["slot", "room__order"]
 | 
				
			||||||
 | 
					        verbose_name = _("Slot room")
 | 
				
			||||||
 | 
					        verbose_name_plural = _("Slot rooms")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@python_2_unicode_compatible
 | 
					@python_2_unicode_compatible
 | 
				
			||||||
class Presentation(models.Model):
 | 
					class Presentation(models.Model):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    slot = models.OneToOneField(Slot, null=True, blank=True, related_name="content_ptr")
 | 
					    slot = models.OneToOneField(Slot, null=True, blank=True, related_name="content_ptr", verbose_name=_("Slot"))
 | 
				
			||||||
    title = models.CharField(max_length=100)
 | 
					    title = models.CharField(max_length=100, verbose_name=_("Title"))
 | 
				
			||||||
    description = MarkupField()
 | 
					    description = MarkupField(verbose_name=_("Description"))
 | 
				
			||||||
    abstract = MarkupField()
 | 
					    abstract = MarkupField(verbose_name=_("Abstract"))
 | 
				
			||||||
    speaker = models.ForeignKey(Speaker, related_name="presentations")
 | 
					    speaker = models.ForeignKey(Speaker, related_name="presentations", verbose_name=_("Speaker"))
 | 
				
			||||||
    additional_speakers = models.ManyToManyField(Speaker, related_name="copresentations",
 | 
					    additional_speakers = models.ManyToManyField(Speaker, related_name="copresentations",
 | 
				
			||||||
                                                 blank=True)
 | 
					                                                 blank=True, verbose_name=_("Additional speakers"))
 | 
				
			||||||
    cancelled = models.BooleanField(default=False)
 | 
					    cancelled = models.BooleanField(default=False, verbose_name=_("Cancelled"))
 | 
				
			||||||
    proposal_base = models.OneToOneField(ProposalBase, related_name="presentation")
 | 
					    proposal_base = models.OneToOneField(ProposalBase, related_name="presentation", verbose_name=_("Proposal base"))
 | 
				
			||||||
    section = models.ForeignKey(Section, related_name="presentations")
 | 
					    section = models.ForeignKey(Section, related_name="presentations", verbose_name=_("Section"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
    def number(self):
 | 
					    def number(self):
 | 
				
			||||||
| 
						 | 
					@ -191,13 +209,15 @@ class Presentation(models.Model):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class Meta:
 | 
					    class Meta:
 | 
				
			||||||
        ordering = ["slot"]
 | 
					        ordering = ["slot"]
 | 
				
			||||||
 | 
					        verbose_name = _("presentation")
 | 
				
			||||||
 | 
					        verbose_name_plural = _("presentations")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@python_2_unicode_compatible
 | 
					@python_2_unicode_compatible
 | 
				
			||||||
class Session(models.Model):
 | 
					class Session(models.Model):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    day = models.ForeignKey(Day, related_name="sessions")
 | 
					    day = models.ForeignKey(Day, related_name="sessions", verbose_name=_("Day"))
 | 
				
			||||||
    slots = models.ManyToManyField(Slot, related_name="sessions")
 | 
					    slots = models.ManyToManyField(Slot, related_name="sessions", verbose_name=_("Slots"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def sorted_slots(self):
 | 
					    def sorted_slots(self):
 | 
				
			||||||
        return self.slots.order_by("start")
 | 
					        return self.slots.order_by("start")
 | 
				
			||||||
| 
						 | 
					@ -227,6 +247,10 @@ class Session(models.Model):
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
        return ""
 | 
					        return ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class Meta:
 | 
				
			||||||
 | 
					        verbose_name = _("Session")
 | 
				
			||||||
 | 
					        verbose_name_plural = _("Sessions")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@python_2_unicode_compatible
 | 
					@python_2_unicode_compatible
 | 
				
			||||||
class SessionRole(models.Model):
 | 
					class SessionRole(models.Model):
 | 
				
			||||||
| 
						 | 
					@ -235,19 +259,21 @@ class SessionRole(models.Model):
 | 
				
			||||||
    SESSION_ROLE_RUNNER = 2
 | 
					    SESSION_ROLE_RUNNER = 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    SESSION_ROLE_TYPES = [
 | 
					    SESSION_ROLE_TYPES = [
 | 
				
			||||||
        (SESSION_ROLE_CHAIR, "Session Chair"),
 | 
					        (SESSION_ROLE_CHAIR, _("Session Chair")),
 | 
				
			||||||
        (SESSION_ROLE_RUNNER, "Session Runner"),
 | 
					        (SESSION_ROLE_RUNNER, _("Session Runner")),
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    session = models.ForeignKey(Session)
 | 
					    session = models.ForeignKey(Session, verbose_name=_("Session"))
 | 
				
			||||||
    user = models.ForeignKey(User)
 | 
					    user = models.ForeignKey(User, verbose_name=_("User"))
 | 
				
			||||||
    role = models.IntegerField(choices=SESSION_ROLE_TYPES)
 | 
					    role = models.IntegerField(choices=SESSION_ROLE_TYPES, verbose_name=_("Role"))
 | 
				
			||||||
    status = models.NullBooleanField()
 | 
					    status = models.NullBooleanField(verbose_name=_("Status"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    submitted = models.DateTimeField(default=datetime.datetime.now)
 | 
					    submitted = models.DateTimeField(default=datetime.datetime.now)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class Meta:
 | 
					    class Meta:
 | 
				
			||||||
        unique_together = [("session", "user", "role")]
 | 
					        unique_together = [("session", "user", "role")]
 | 
				
			||||||
 | 
					        verbose_name = _("Session role")
 | 
				
			||||||
 | 
					        verbose_name_plural = _("Session roles")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __str__(self):
 | 
					    def __str__(self):
 | 
				
			||||||
        return "%s %s: %s" % (self.user, self.session,
 | 
					        return "%s %s: %s" % (self.user, self.session,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,8 +1,9 @@
 | 
				
			||||||
from __future__ import unicode_literals
 | 
					from __future__ import unicode_literals
 | 
				
			||||||
from django.apps import AppConfig
 | 
					from django.apps import AppConfig
 | 
				
			||||||
 | 
					from django.utils.translation import ugettext_lazy as _
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class SpeakersConfig(AppConfig):
 | 
					class SpeakersConfig(AppConfig):
 | 
				
			||||||
    name = "symposion.speakers"
 | 
					    name = "symposion.speakers"
 | 
				
			||||||
    label = "symposion_speakers"
 | 
					    label = "symposion_speakers"
 | 
				
			||||||
    verbose_name = "Symposion Speakers"
 | 
					    verbose_name = _("Symposion Speakers")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,9 +1,11 @@
 | 
				
			||||||
from __future__ import unicode_literals
 | 
					from __future__ import unicode_literals
 | 
				
			||||||
import datetime
 | 
					 | 
				
			||||||
from django.utils.encoding import python_2_unicode_compatible
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
from django.db import models
 | 
					import datetime
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from django.core.urlresolvers import reverse
 | 
					from django.core.urlresolvers import reverse
 | 
				
			||||||
 | 
					from django.db import models
 | 
				
			||||||
 | 
					from django.utils.encoding import python_2_unicode_compatible
 | 
				
			||||||
 | 
					from django.utils.translation import ugettext_lazy as _
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from django.contrib.auth.models import User
 | 
					from django.contrib.auth.models import User
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,24 +20,28 @@ class Speaker(models.Model):
 | 
				
			||||||
        (2, "Two")
 | 
					        (2, "Two")
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    user = models.OneToOneField(User, null=True, related_name="speaker_profile")
 | 
					    user = models.OneToOneField(User, null=True, related_name="speaker_profile", verbose_name=_("User"))
 | 
				
			||||||
    name = models.CharField(max_length=100, help_text=("As you would like it to appear in the "
 | 
					    name = models.CharField(verbose_name=_("Name"), max_length=100,
 | 
				
			||||||
                                                       "conference program."))
 | 
					                            help_text=_("As you would like it to appear in the"
 | 
				
			||||||
    biography = MarkupField(blank=True, help_text=("A little bit about you.  Edit using "
 | 
					                                        " conference program."))
 | 
				
			||||||
 | 
					    biography = MarkupField(blank=True, help_text=_("A little bit about you.  Edit using "
 | 
				
			||||||
                                                    "<a href='http://warpedvisions.org/projects/"
 | 
					                                                    "<a href='http://warpedvisions.org/projects/"
 | 
				
			||||||
                                                    "markdown-cheat-sheet/target='_blank'>"
 | 
					                                                    "markdown-cheat-sheet/target='_blank'>"
 | 
				
			||||||
                                                   "Markdown</a>."))
 | 
					                                                    "Markdown</a>."), verbose_name=_("Biography"))
 | 
				
			||||||
    photo = models.ImageField(upload_to="speaker_photos", blank=True)
 | 
					    photo = models.ImageField(upload_to="speaker_photos", blank=True, verbose_name=_("Photo"))
 | 
				
			||||||
    annotation = models.TextField()  # staff only
 | 
					    annotation = models.TextField(verbose_name=_("Annotation"))  # staff only
 | 
				
			||||||
    invite_email = models.CharField(max_length=200, unique=True, null=True, db_index=True)
 | 
					    invite_email = models.CharField(max_length=200, unique=True, null=True, db_index=True, verbose_name=_("Invite_email"))
 | 
				
			||||||
    invite_token = models.CharField(max_length=40, db_index=True)
 | 
					    invite_token = models.CharField(max_length=40, db_index=True, verbose_name=_("Invite token"))
 | 
				
			||||||
    created = models.DateTimeField(
 | 
					    created = models.DateTimeField(
 | 
				
			||||||
        default=datetime.datetime.now,
 | 
					        default=datetime.datetime.now,
 | 
				
			||||||
        editable=False
 | 
					        editable=False,
 | 
				
			||||||
 | 
					        verbose_name=_("Created")
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class Meta:
 | 
					    class Meta:
 | 
				
			||||||
        ordering = ['name']
 | 
					        ordering = ['name']
 | 
				
			||||||
 | 
					        verbose_name = _("Speaker")
 | 
				
			||||||
 | 
					        verbose_name_plural = _("Speakers")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __str__(self):
 | 
					    def __str__(self):
 | 
				
			||||||
        if self.user:
 | 
					        if self.user:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,6 +6,7 @@ from django.shortcuts import render, redirect, get_object_or_404
 | 
				
			||||||
from django.contrib import messages
 | 
					from django.contrib import messages
 | 
				
			||||||
from django.contrib.auth.decorators import login_required
 | 
					from django.contrib.auth.decorators import login_required
 | 
				
			||||||
from django.contrib.auth.models import User
 | 
					from django.contrib.auth.models import User
 | 
				
			||||||
 | 
					from django.utils.translation import ugettext_lazy as _
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from symposion.proposals.models import ProposalBase
 | 
					from symposion.proposals.models import ProposalBase
 | 
				
			||||||
from symposion.speakers.forms import SpeakerForm
 | 
					from symposion.speakers.forms import SpeakerForm
 | 
				
			||||||
| 
						 | 
					@ -34,7 +35,7 @@ def speaker_create(request):
 | 
				
			||||||
            if not found:
 | 
					            if not found:
 | 
				
			||||||
                speaker.invite_email = None
 | 
					                speaker.invite_email = None
 | 
				
			||||||
            speaker.save()
 | 
					            speaker.save()
 | 
				
			||||||
            messages.success(request, "Speaker profile created.")
 | 
					            messages.success(request, _("Speaker profile created."))
 | 
				
			||||||
            return redirect("dashboard")
 | 
					            return redirect("dashboard")
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        form = SpeakerForm(initial={"name": request.user.get_full_name()})
 | 
					        form = SpeakerForm(initial={"name": request.user.get_full_name()})
 | 
				
			||||||
| 
						 | 
					@ -62,7 +63,7 @@ def speaker_create_staff(request, pk):
 | 
				
			||||||
            speaker = form.save(commit=False)
 | 
					            speaker = form.save(commit=False)
 | 
				
			||||||
            speaker.user = user
 | 
					            speaker.user = user
 | 
				
			||||||
            speaker.save()
 | 
					            speaker.save()
 | 
				
			||||||
            messages.success(request, "Speaker profile created.")
 | 
					            messages.success(request, _("Speaker profile created."))
 | 
				
			||||||
            return redirect("user_list")
 | 
					            return redirect("user_list")
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        form = SpeakerForm(initial={"name": user.get_full_name()})
 | 
					        form = SpeakerForm(initial={"name": user.get_full_name()})
 | 
				
			||||||
| 
						 | 
					@ -89,7 +90,7 @@ def speaker_create_token(request, token):
 | 
				
			||||||
            ).update(
 | 
					            ).update(
 | 
				
			||||||
                speaker=existing_speaker
 | 
					                speaker=existing_speaker
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
            messages.info(request, ("You have been associated with all pending "
 | 
					            messages.info(request, _("You have been associated with all pending "
 | 
				
			||||||
                                     "talk proposals"))
 | 
					                                     "talk proposals"))
 | 
				
			||||||
            return redirect("dashboard")
 | 
					            return redirect("dashboard")
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -69,9 +69,9 @@ class SponsorAdmin(admin.ModelAdmin):
 | 
				
			||||||
        # @@@ kinda ugly but using choices= on NullBooleanField is broken
 | 
					        # @@@ kinda ugly but using choices= on NullBooleanField is broken
 | 
				
			||||||
        form = super(SponsorAdmin, self).get_form(*args, **kwargs)
 | 
					        form = super(SponsorAdmin, self).get_form(*args, **kwargs)
 | 
				
			||||||
        form.base_fields["active"].widget.choices = [
 | 
					        form.base_fields["active"].widget.choices = [
 | 
				
			||||||
            (u"1", _("unreviewed")),
 | 
					            ("1", _("unreviewed")),
 | 
				
			||||||
            (u"2", _("approved")),
 | 
					            ("2", _("approved")),
 | 
				
			||||||
            (u"3", _("rejected"))
 | 
					            ("3", _("rejected"))
 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
        return form
 | 
					        return form
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,9 @@
 | 
				
			||||||
 | 
					from __future__ import unicode_literals
 | 
				
			||||||
from django.apps import AppConfig
 | 
					from django.apps import AppConfig
 | 
				
			||||||
 | 
					from django.utils.translation import ugettext_lazy as _
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class SponsorshipConfig(AppConfig):
 | 
					class SponsorshipConfig(AppConfig):
 | 
				
			||||||
    name = "symposion.sponsorship"
 | 
					    name = "symposion.sponsorship"
 | 
				
			||||||
    label = "symposion_sponsorship"
 | 
					    label = "symposion_sponsorship"
 | 
				
			||||||
    verbose_name = "Symposion Sponsorship"
 | 
					    verbose_name = _("Symposion Sponsorship")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,6 +3,7 @@ from django import forms
 | 
				
			||||||
from django.forms.models import inlineformset_factory, BaseInlineFormSet
 | 
					from django.forms.models import inlineformset_factory, BaseInlineFormSet
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from django.contrib.admin.widgets import AdminFileWidget
 | 
					from django.contrib.admin.widgets import AdminFileWidget
 | 
				
			||||||
 | 
					from django.utils.translation import ugettext_lazy as _
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from symposion.sponsorship.models import Sponsor, SponsorBenefit
 | 
					from symposion.sponsorship.models import Sponsor, SponsorBenefit
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -65,7 +66,7 @@ class SponsorBenefitsInlineFormSet(BaseInlineFormSet):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # provide word limit as help_text
 | 
					            # provide word limit as help_text
 | 
				
			||||||
            if form.instance.benefit.type == "text" and form.instance.max_words:
 | 
					            if form.instance.benefit.type == "text" and form.instance.max_words:
 | 
				
			||||||
                form.fields[field].help_text = u"maximum %s words" % form.instance.max_words
 | 
					                form.fields[field].help_text = _("maximum %s words") % form.instance.max_words
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # use admin file widget that shows currently uploaded file
 | 
					            # use admin file widget that shows currently uploaded file
 | 
				
			||||||
            if field == "upload":
 | 
					            if field == "upload":
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -48,16 +48,16 @@ BENEFITS = [
 | 
				
			||||||
@python_2_unicode_compatible
 | 
					@python_2_unicode_compatible
 | 
				
			||||||
class SponsorLevel(models.Model):
 | 
					class SponsorLevel(models.Model):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    conference = models.ForeignKey(Conference, verbose_name=_("conference"))
 | 
					    conference = models.ForeignKey(Conference, verbose_name=_("Conference"))
 | 
				
			||||||
    name = models.CharField(_("name"), max_length=100)
 | 
					    name = models.CharField(_("Name"), max_length=100)
 | 
				
			||||||
    order = models.IntegerField(_("order"), default=0)
 | 
					    order = models.IntegerField(_("Order"), default=0)
 | 
				
			||||||
    cost = models.PositiveIntegerField(_("cost"))
 | 
					    cost = models.PositiveIntegerField(_("Cost"))
 | 
				
			||||||
    description = models.TextField(_("description"), blank=True, help_text=_("This is private."))
 | 
					    description = models.TextField(_("Description"), blank=True, help_text=_("This is private."))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class Meta:
 | 
					    class Meta:
 | 
				
			||||||
        ordering = ["conference", "order"]
 | 
					        ordering = ["conference", "order"]
 | 
				
			||||||
        verbose_name = _("sponsor level")
 | 
					        verbose_name = _("Sponsor level")
 | 
				
			||||||
        verbose_name_plural = _("sponsor levels")
 | 
					        verbose_name_plural = _("Sponsor levels")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __str__(self):
 | 
					    def __str__(self):
 | 
				
			||||||
        return "%s %s" % (self.conference, self.name)
 | 
					        return "%s %s" % (self.conference, self.name)
 | 
				
			||||||
| 
						 | 
					@ -69,22 +69,22 @@ class SponsorLevel(models.Model):
 | 
				
			||||||
@python_2_unicode_compatible
 | 
					@python_2_unicode_compatible
 | 
				
			||||||
class Sponsor(models.Model):
 | 
					class Sponsor(models.Model):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    applicant = models.ForeignKey(User, related_name="sponsorships", verbose_name=_("applicant"),
 | 
					    applicant = models.ForeignKey(User, related_name="sponsorships", verbose_name=_("Applicant"),
 | 
				
			||||||
                                  null=True)
 | 
					                                  null=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    name = models.CharField(_("Sponsor Name"), max_length=100)
 | 
					    name = models.CharField(_("Sponsor Name"), max_length=100)
 | 
				
			||||||
    display_url = models.URLField(_("display URL"), blank=True)
 | 
					    display_url = models.URLField(_("display URL"), blank=True)
 | 
				
			||||||
    external_url = models.URLField(_("external URL"))
 | 
					    external_url = models.URLField(_("External URL"))
 | 
				
			||||||
    annotation = models.TextField(_("annotation"), blank=True)
 | 
					    annotation = models.TextField(_("Annotation"), blank=True)
 | 
				
			||||||
    contact_name = models.CharField(_("Contact Name"), max_length=100)
 | 
					    contact_name = models.CharField(_("Contact Name"), max_length=100)
 | 
				
			||||||
    contact_email = models.EmailField(_(u"Contact Email"))
 | 
					    contact_email = models.EmailField(_("Contact Email"))
 | 
				
			||||||
    level = models.ForeignKey(SponsorLevel, verbose_name=_("level"))
 | 
					    level = models.ForeignKey(SponsorLevel, verbose_name=_("level"))
 | 
				
			||||||
    added = models.DateTimeField(_("added"), default=datetime.datetime.now)
 | 
					    added = models.DateTimeField(_("added"), default=datetime.datetime.now)
 | 
				
			||||||
    active = models.BooleanField(_("active"), default=False)
 | 
					    active = models.BooleanField(_("active"), default=False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Denormalization (this assumes only one logo)
 | 
					    # Denormalization (this assumes only one logo)
 | 
				
			||||||
    sponsor_logo = models.ForeignKey("SponsorBenefit", related_name="+", null=True, blank=True,
 | 
					    sponsor_logo = models.ForeignKey("SponsorBenefit", related_name="+", null=True, blank=True,
 | 
				
			||||||
                                     editable=False)
 | 
					                                     editable=False, verbose_name=_("Sponsor logo"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Whether things are complete
 | 
					    # Whether things are complete
 | 
				
			||||||
    # True = complete, False = incomplate, Null = n/a for this sponsor level
 | 
					    # True = complete, False = incomplate, Null = n/a for this sponsor level
 | 
				
			||||||
| 
						 | 
					@ -99,8 +99,8 @@ class Sponsor(models.Model):
 | 
				
			||||||
        return self.name
 | 
					        return self.name
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class Meta:
 | 
					    class Meta:
 | 
				
			||||||
        verbose_name = _("sponsor")
 | 
					        verbose_name = _("Sponsor")
 | 
				
			||||||
        verbose_name_plural = _("sponsors")
 | 
					        verbose_name_plural = _("Sponsors")
 | 
				
			||||||
        ordering = ['name']
 | 
					        ordering = ['name']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def save(self, *args, **kwargs):
 | 
					    def save(self, *args, **kwargs):
 | 
				
			||||||
| 
						 | 
					@ -213,12 +213,12 @@ post_save.connect(_check_level_change, sender=Sponsor)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
BENEFIT_TYPE_CHOICES = [
 | 
					BENEFIT_TYPE_CHOICES = [
 | 
				
			||||||
    ("text", "Text"),
 | 
					    ("text", _("Text")),
 | 
				
			||||||
    ("richtext", "Rich Text"),
 | 
					    ("file", _("File")),
 | 
				
			||||||
    ("file", "File"),
 | 
					    ("richtext", _("Rich Text")),
 | 
				
			||||||
    ("weblogo", "Web Logo"),
 | 
					    ("weblogo", _("Web Logo")),
 | 
				
			||||||
    ("simple", "Simple"),
 | 
					    ("simple", _("Simple")),
 | 
				
			||||||
    ("option", "Option")
 | 
					    ("option", _("Option"))
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CONTENT_TYPE_CHOICES = [
 | 
					CONTENT_TYPE_CHOICES = [
 | 
				
			||||||
| 
						 | 
					@ -231,10 +231,10 @@ CONTENT_TYPE_CHOICES = [
 | 
				
			||||||
@python_2_unicode_compatible
 | 
					@python_2_unicode_compatible
 | 
				
			||||||
class Benefit(models.Model):
 | 
					class Benefit(models.Model):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    name = models.CharField(_("name"), max_length=100)
 | 
					    name = models.CharField(_("Name"), max_length=100)
 | 
				
			||||||
    description = models.TextField(_("description"), blank=True)
 | 
					    description = models.TextField(_("Description"), blank=True)
 | 
				
			||||||
    type = models.CharField(_("type"), choices=BENEFIT_TYPE_CHOICES,
 | 
					    type = models.CharField(_("Type"), choices=BENEFIT_TYPE_CHOICES, max_length=10,
 | 
				
			||||||
                            max_length=10, default="simple")
 | 
					                            default="simple")
 | 
				
			||||||
    content_type = models.CharField(_("content type"), choices=CONTENT_TYPE_CHOICES,
 | 
					    content_type = models.CharField(_("content type"), choices=CONTENT_TYPE_CHOICES,
 | 
				
			||||||
                                    max_length=20, default="simple")
 | 
					                                    max_length=20, default="simple")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -245,15 +245,17 @@ class Benefit(models.Model):
 | 
				
			||||||
@python_2_unicode_compatible
 | 
					@python_2_unicode_compatible
 | 
				
			||||||
class BenefitLevel(models.Model):
 | 
					class BenefitLevel(models.Model):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    benefit = models.ForeignKey(Benefit, related_name="benefit_levels", verbose_name=_("benefit"))
 | 
					    benefit = models.ForeignKey(Benefit, related_name="benefit_levels", verbose_name=_("Benefit"))
 | 
				
			||||||
    level = models.ForeignKey(SponsorLevel, related_name="benefit_levels", verbose_name=_("level"))
 | 
					    level = models.ForeignKey(SponsorLevel, related_name="benefit_levels", verbose_name=_("Level"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # default limits for this benefit at given level
 | 
					    # default limits for this benefit at given level
 | 
				
			||||||
    max_words = models.PositiveIntegerField(_("max words"), blank=True, null=True)
 | 
					    max_words = models.PositiveIntegerField(_("Max words"), blank=True, null=True)
 | 
				
			||||||
    other_limits = models.CharField(_("other limits"), max_length=200, blank=True)
 | 
					    other_limits = models.CharField(_("Other limits"), max_length=200, blank=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class Meta:
 | 
					    class Meta:
 | 
				
			||||||
        ordering = ["level"]
 | 
					        ordering = ["level"]
 | 
				
			||||||
 | 
					        verbose_name = _("Benefit level")
 | 
				
			||||||
 | 
					        verbose_name_plural = _("Benefit levels")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __str__(self):
 | 
					    def __str__(self):
 | 
				
			||||||
        return "%s - %s" % (self.level, self.benefit)
 | 
					        return "%s - %s" % (self.level, self.benefit)
 | 
				
			||||||
| 
						 | 
					@ -262,18 +264,18 @@ class BenefitLevel(models.Model):
 | 
				
			||||||
@python_2_unicode_compatible
 | 
					@python_2_unicode_compatible
 | 
				
			||||||
class SponsorBenefit(models.Model):
 | 
					class SponsorBenefit(models.Model):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sponsor = models.ForeignKey(Sponsor, related_name="sponsor_benefits", verbose_name=_("sponsor"))
 | 
					    sponsor = models.ForeignKey(Sponsor, related_name="sponsor_benefits", verbose_name=_("Sponsor"))
 | 
				
			||||||
    benefit = models.ForeignKey(Benefit, related_name="sponsor_benefits", verbose_name=_("benefit"))
 | 
					    benefit = models.ForeignKey(Benefit, related_name="sponsor_benefits", verbose_name=_("Benefit"))
 | 
				
			||||||
    active = models.BooleanField(default=True)
 | 
					    active = models.BooleanField(default=True, verbose_name=_("Active"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Limits: will initially be set to defaults from corresponding BenefitLevel
 | 
					    # Limits: will initially be set to defaults from corresponding BenefitLevel
 | 
				
			||||||
    max_words = models.PositiveIntegerField(_("max words"), blank=True, null=True)
 | 
					    max_words = models.PositiveIntegerField(_("Max words"), blank=True, null=True)
 | 
				
			||||||
    other_limits = models.CharField(_("other limits"), max_length=200, blank=True)
 | 
					    other_limits = models.CharField(_("Other limits"), max_length=200, blank=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Data: zero or one of these fields will be used, depending on the
 | 
					    # Data: zero or one of these fields will be used, depending on the
 | 
				
			||||||
    # type of the Benefit (text, file, or simple)
 | 
					    # type of the Benefit (text, file, or simple)
 | 
				
			||||||
    text = models.TextField(_("text"), blank=True)
 | 
					    text = models.TextField(_("Text"), blank=True)
 | 
				
			||||||
    upload = models.FileField(_("file"), blank=True, upload_to="sponsor_files")
 | 
					    upload = models.FileField(_("File"), blank=True, upload_to="sponsor_files")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Whether any assets required from the sponsor have been provided
 | 
					    # Whether any assets required from the sponsor have been provided
 | 
				
			||||||
    # (e.g. a logo file for a Web logo benefit).
 | 
					    # (e.g. a logo file for a Web logo benefit).
 | 
				
			||||||
| 
						 | 
					@ -281,6 +283,8 @@ class SponsorBenefit(models.Model):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class Meta:
 | 
					    class Meta:
 | 
				
			||||||
        ordering = ["-active"]
 | 
					        ordering = ["-active"]
 | 
				
			||||||
 | 
					        verbose_name = _("Sponsor benefit")
 | 
				
			||||||
 | 
					        verbose_name_plural = _("Sponsor benefits")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __str__(self):
 | 
					    def __str__(self):
 | 
				
			||||||
        return "%s - %s (%s)" % (self.sponsor, self.benefit, self.benefit_type)
 | 
					        return "%s - %s (%s)" % (self.sponsor, self.benefit, self.benefit_type)
 | 
				
			||||||
| 
						 | 
					@ -296,8 +300,8 @@ class SponsorBenefit(models.Model):
 | 
				
			||||||
        num_words = len(self.text.split())
 | 
					        num_words = len(self.text.split())
 | 
				
			||||||
        if self.max_words and num_words > self.max_words:
 | 
					        if self.max_words and num_words > self.max_words:
 | 
				
			||||||
            raise ValidationError(
 | 
					            raise ValidationError(
 | 
				
			||||||
                "Sponsorship level only allows for %s words, you provided %d." % (
 | 
					                _("Sponsorship level only allows for %(word)s words, you provided %(num)d.") % {
 | 
				
			||||||
                    self.max_words, num_words))
 | 
					                    "word": self.max_words, "num": num_words})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def data_fields(self):
 | 
					    def data_fields(self):
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,16 +7,14 @@ import time
 | 
				
			||||||
from zipfile import ZipFile, ZipInfo
 | 
					from zipfile import ZipFile, ZipInfo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from django.conf import settings
 | 
					from django.conf import settings
 | 
				
			||||||
 | 
					from django.contrib import messages
 | 
				
			||||||
 | 
					from django.contrib.admin.views.decorators import staff_member_required
 | 
				
			||||||
 | 
					from django.contrib.auth.decorators import login_required
 | 
				
			||||||
from django.http import Http404, HttpResponse
 | 
					from django.http import Http404, HttpResponse
 | 
				
			||||||
from django.shortcuts import render_to_response, redirect, get_object_or_404
 | 
					from django.shortcuts import render_to_response, redirect, get_object_or_404
 | 
				
			||||||
from django.template import RequestContext
 | 
					from django.template import RequestContext
 | 
				
			||||||
from django.utils.translation import ugettext_lazy as _
 | 
					from django.utils.translation import ugettext_lazy as _
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from django.contrib import messages
 | 
					 | 
				
			||||||
from django.contrib.admin.views.decorators import staff_member_required
 | 
					 | 
				
			||||||
from django.contrib.auth.decorators import login_required
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
from symposion.sponsorship.forms import SponsorApplicationForm, \
 | 
					from symposion.sponsorship.forms import SponsorApplicationForm, \
 | 
				
			||||||
    SponsorDetailsForm, SponsorBenefitsFormSet
 | 
					    SponsorDetailsForm, SponsorBenefitsFormSet
 | 
				
			||||||
from symposion.sponsorship.models import Benefit, Sponsor, SponsorBenefit, \
 | 
					from symposion.sponsorship.models import Benefit, Sponsor, SponsorBenefit, \
 | 
				
			||||||
| 
						 | 
					@ -91,7 +89,7 @@ def sponsor_detail(request, pk):
 | 
				
			||||||
            form.save()
 | 
					            form.save()
 | 
				
			||||||
            formset.save()
 | 
					            formset.save()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            messages.success(request, "Sponsorship details have been updated")
 | 
					            messages.success(request, _("Sponsorship details have been updated"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return redirect("dashboard")
 | 
					            return redirect("dashboard")
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,6 +3,7 @@ from django import forms
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from django.utils.html import escape
 | 
					from django.utils.html import escape
 | 
				
			||||||
from django.utils.safestring import mark_safe
 | 
					from django.utils.safestring import mark_safe
 | 
				
			||||||
 | 
					from django.utils.translation import ugettext_lazy as _
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from django.contrib.auth.models import User
 | 
					from django.contrib.auth.models import User
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,7 +12,8 @@ from symposion.teams.models import Membership
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TeamInvitationForm(forms.Form):
 | 
					class TeamInvitationForm(forms.Form):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    email = forms.EmailField(help_text=("email address must be that of an account on this "
 | 
					    email = forms.EmailField(label=_("Email"),
 | 
				
			||||||
 | 
					                             help_text=_("email address must be that of an account on this "
 | 
				
			||||||
                                         "conference site"))
 | 
					                                         "conference site"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, *args, **kwargs):
 | 
					    def __init__(self, *args, **kwargs):
 | 
				
			||||||
| 
						 | 
					@ -23,7 +25,7 @@ class TeamInvitationForm(forms.Form):
 | 
				
			||||||
        email = cleaned_data.get("email")
 | 
					        email = cleaned_data.get("email")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if email is None:
 | 
					        if email is None:
 | 
				
			||||||
            raise forms.ValidationError("valid email address required")
 | 
					            raise forms.ValidationError(_("valid email address required"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            user = User.objects.get(email=email)
 | 
					            user = User.objects.get(email=email)
 | 
				
			||||||
| 
						 | 
					@ -31,16 +33,16 @@ class TeamInvitationForm(forms.Form):
 | 
				
			||||||
            # eventually we can invite them but for now assume they are
 | 
					            # eventually we can invite them but for now assume they are
 | 
				
			||||||
            # already on the site
 | 
					            # already on the site
 | 
				
			||||||
            raise forms.ValidationError(
 | 
					            raise forms.ValidationError(
 | 
				
			||||||
                mark_safe("no account with email address <b>%s</b> found on this conference "
 | 
					                mark_safe(_("no account with email address <b>%s</b> found on this conference "
 | 
				
			||||||
                          "site" % escape(email)))
 | 
					                          "site") % escape(email)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        state = self.team.get_state_for_user(user)
 | 
					        state = self.team.get_state_for_user(user)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if state in ["member", "manager"]:
 | 
					        if state in ["member", "manager"]:
 | 
				
			||||||
            raise forms.ValidationError("user already in team")
 | 
					            raise forms.ValidationError(_("user already in team"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if state in ["invited"]:
 | 
					        if state in ["invited"]:
 | 
				
			||||||
            raise forms.ValidationError("user already invited to team")
 | 
					            raise forms.ValidationError(_("user already invited to team"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.user = user
 | 
					        self.user = user
 | 
				
			||||||
        self.state = state
 | 
					        self.state = state
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,37 +1,44 @@
 | 
				
			||||||
from __future__ import unicode_literals
 | 
					from __future__ import unicode_literals
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import datetime
 | 
					import datetime
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from django.db import models
 | 
					from django.db import models
 | 
				
			||||||
 | 
					from django.utils.encoding import python_2_unicode_compatible
 | 
				
			||||||
 | 
					from django.utils.translation import ugettext_lazy as _
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from django.contrib.auth.models import Permission, User
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import reversion
 | 
					import reversion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from django.contrib.auth.models import Permission, User
 | 
					 | 
				
			||||||
from django.utils.encoding import python_2_unicode_compatible
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
TEAM_ACCESS_CHOICES = [
 | 
					TEAM_ACCESS_CHOICES = [
 | 
				
			||||||
    ("open", "open"),
 | 
					    ("open", _("open")),
 | 
				
			||||||
    ("application", "by application"),
 | 
					    ("application", _("by application")),
 | 
				
			||||||
    ("invitation", "by invitation")
 | 
					    ("invitation", _("by invitation"))
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@python_2_unicode_compatible
 | 
					@python_2_unicode_compatible
 | 
				
			||||||
class Team(models.Model):
 | 
					class Team(models.Model):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    slug = models.SlugField(unique=True)
 | 
					    slug = models.SlugField(unique=True, verbose_name=_("Slug"))
 | 
				
			||||||
    name = models.CharField(max_length=100)
 | 
					    name = models.CharField(max_length=100, verbose_name=_("Name"))
 | 
				
			||||||
    description = models.TextField(blank=True)
 | 
					    description = models.TextField(blank=True, verbose_name=_("Description"))
 | 
				
			||||||
    access = models.CharField(max_length=20, choices=TEAM_ACCESS_CHOICES)
 | 
					    access = models.CharField(max_length=20, choices=TEAM_ACCESS_CHOICES,
 | 
				
			||||||
 | 
					                              verbose_name=_("Access"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # member permissions
 | 
					    # member permissions
 | 
				
			||||||
    permissions = models.ManyToManyField(Permission, blank=True, related_name="member_teams")
 | 
					    permissions = models.ManyToManyField(Permission, blank=True,
 | 
				
			||||||
 | 
					                                         related_name="member_teams",
 | 
				
			||||||
 | 
					                                         verbose_name=_("Permissions"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # manager permissions
 | 
					    # manager permissions
 | 
				
			||||||
    manager_permissions = models.ManyToManyField(Permission, blank=True,
 | 
					    manager_permissions = models.ManyToManyField(Permission, blank=True,
 | 
				
			||||||
                                                 related_name="manager_teams")
 | 
					                                                 related_name="manager_teams",
 | 
				
			||||||
 | 
					                                                 verbose_name=_("Manager permissions"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    created = models.DateTimeField(default=datetime.datetime.now, editable=False)
 | 
					    created = models.DateTimeField(default=datetime.datetime.now,
 | 
				
			||||||
 | 
					                                   editable=False, verbose_name=_("Created"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @models.permalink
 | 
					    @models.permalink
 | 
				
			||||||
    def get_absolute_url(self):
 | 
					    def get_absolute_url(self):
 | 
				
			||||||
| 
						 | 
					@ -58,23 +65,32 @@ class Team(models.Model):
 | 
				
			||||||
    def managers(self):
 | 
					    def managers(self):
 | 
				
			||||||
        return self.memberships.filter(state="manager")
 | 
					        return self.memberships.filter(state="manager")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class Meta:
 | 
				
			||||||
 | 
					        verbose_name = _('Team')
 | 
				
			||||||
 | 
					        verbose_name_plural = _('Teams')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MEMBERSHIP_STATE_CHOICES = [
 | 
					MEMBERSHIP_STATE_CHOICES = [
 | 
				
			||||||
    ("applied", "applied"),
 | 
					    ("applied", _("applied")),
 | 
				
			||||||
    ("invited", "invited"),
 | 
					    ("invited", _("invited")),
 | 
				
			||||||
    ("declined", "declined"),
 | 
					    ("declined", _("declined")),
 | 
				
			||||||
    ("rejected", "rejected"),
 | 
					    ("rejected", _("rejected")),
 | 
				
			||||||
    ("member", "member"),
 | 
					    ("member", _("member")),
 | 
				
			||||||
    ("manager", "manager"),
 | 
					    ("manager", _("manager")),
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Membership(models.Model):
 | 
					class Membership(models.Model):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    user = models.ForeignKey(User, related_name="memberships")
 | 
					    user = models.ForeignKey(User, related_name="memberships",
 | 
				
			||||||
    team = models.ForeignKey(Team, related_name="memberships")
 | 
					                             verbose_name=_("User"))
 | 
				
			||||||
    state = models.CharField(max_length=20, choices=MEMBERSHIP_STATE_CHOICES)
 | 
					    team = models.ForeignKey(Team, related_name="memberships",
 | 
				
			||||||
    message = models.TextField(blank=True)
 | 
					                             verbose_name=_("Team"))
 | 
				
			||||||
 | 
					    state = models.CharField(max_length=20, choices=MEMBERSHIP_STATE_CHOICES,
 | 
				
			||||||
 | 
					                             verbose_name=_("State"))
 | 
				
			||||||
 | 
					    message = models.TextField(blank=True, verbose_name=_("Message"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class Meta:
 | 
				
			||||||
 | 
					        verbose_name = _("Membership")
 | 
				
			||||||
 | 
					        verbose_name_plural = _("Memberships")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
reversion.register(Membership)
 | 
					reversion.register(Membership)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,6 +6,7 @@ from django.contrib.auth.decorators import login_required
 | 
				
			||||||
from django.contrib import messages
 | 
					from django.contrib import messages
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from symposion.utils.mail import send_email
 | 
					from symposion.utils.mail import send_email
 | 
				
			||||||
 | 
					from django.utils.translation import ugettext_lazy as _
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from symposion.teams.forms import TeamInvitationForm
 | 
					from symposion.teams.forms import TeamInvitationForm
 | 
				
			||||||
from symposion.teams.models import Team, Membership
 | 
					from symposion.teams.models import Team, Membership
 | 
				
			||||||
| 
						 | 
					@ -67,7 +68,7 @@ def team_detail(request, slug):
 | 
				
			||||||
            if form.is_valid():
 | 
					            if form.is_valid():
 | 
				
			||||||
                form.invite()
 | 
					                form.invite()
 | 
				
			||||||
                send_email([form.user.email], "teams_user_invited", context={"team": team})
 | 
					                send_email([form.user.email], "teams_user_invited", context={"team": team})
 | 
				
			||||||
                messages.success(request, "Invitation created.")
 | 
					                messages.success(request, _("Invitation created."))
 | 
				
			||||||
                return redirect("team_detail", slug=slug)
 | 
					                return redirect("team_detail", slug=slug)
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            form = TeamInvitationForm(team=team)
 | 
					            form = TeamInvitationForm(team=team)
 | 
				
			||||||
| 
						 | 
					@ -95,7 +96,7 @@ def team_join(request, slug):
 | 
				
			||||||
        membership, created = Membership.objects.get_or_create(team=team, user=request.user)
 | 
					        membership, created = Membership.objects.get_or_create(team=team, user=request.user)
 | 
				
			||||||
        membership.state = "member"
 | 
					        membership.state = "member"
 | 
				
			||||||
        membership.save()
 | 
					        membership.save()
 | 
				
			||||||
        messages.success(request, "Joined team.")
 | 
					        messages.success(request, _("Joined team."))
 | 
				
			||||||
        return redirect("team_detail", slug=slug)
 | 
					        return redirect("team_detail", slug=slug)
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        return redirect("team_detail", slug=slug)
 | 
					        return redirect("team_detail", slug=slug)
 | 
				
			||||||
| 
						 | 
					@ -111,7 +112,7 @@ def team_leave(request, slug):
 | 
				
			||||||
    if can_leave(team, request.user) and request.method == "POST":
 | 
					    if can_leave(team, request.user) and request.method == "POST":
 | 
				
			||||||
        membership = Membership.objects.get(team=team, user=request.user)
 | 
					        membership = Membership.objects.get(team=team, user=request.user)
 | 
				
			||||||
        membership.delete()
 | 
					        membership.delete()
 | 
				
			||||||
        messages.success(request, "Left team.")
 | 
					        messages.success(request, _("Left team."))
 | 
				
			||||||
        return redirect("dashboard")
 | 
					        return redirect("dashboard")
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        return redirect("team_detail", slug=slug)
 | 
					        return redirect("team_detail", slug=slug)
 | 
				
			||||||
| 
						 | 
					@ -133,7 +134,7 @@ def team_apply(request, slug):
 | 
				
			||||||
            "team": team,
 | 
					            "team": team,
 | 
				
			||||||
            "user": request.user
 | 
					            "user": request.user
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
        messages.success(request, "Applied to join team.")
 | 
					        messages.success(request, _("Applied to join team."))
 | 
				
			||||||
        return redirect("team_detail", slug=slug)
 | 
					        return redirect("team_detail", slug=slug)
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        return redirect("team_detail", slug=slug)
 | 
					        return redirect("team_detail", slug=slug)
 | 
				
			||||||
| 
						 | 
					@ -149,7 +150,7 @@ def team_promote(request, pk):
 | 
				
			||||||
        if membership.state == "member":
 | 
					        if membership.state == "member":
 | 
				
			||||||
            membership.state = "manager"
 | 
					            membership.state = "manager"
 | 
				
			||||||
            membership.save()
 | 
					            membership.save()
 | 
				
			||||||
            messages.success(request, "Promoted to manager.")
 | 
					            messages.success(request, _("Promoted to manager."))
 | 
				
			||||||
    return redirect("team_detail", slug=membership.team.slug)
 | 
					    return redirect("team_detail", slug=membership.team.slug)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -163,7 +164,7 @@ def team_demote(request, pk):
 | 
				
			||||||
        if membership.state == "manager":
 | 
					        if membership.state == "manager":
 | 
				
			||||||
            membership.state = "member"
 | 
					            membership.state = "member"
 | 
				
			||||||
            membership.save()
 | 
					            membership.save()
 | 
				
			||||||
            messages.success(request, "Demoted from manager.")
 | 
					            messages.success(request, _("Demoted from manager."))
 | 
				
			||||||
    return redirect("team_detail", slug=membership.team.slug)
 | 
					    return redirect("team_detail", slug=membership.team.slug)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -177,7 +178,7 @@ def team_accept(request, pk):
 | 
				
			||||||
        if membership.state == "applied":
 | 
					        if membership.state == "applied":
 | 
				
			||||||
            membership.state = "member"
 | 
					            membership.state = "member"
 | 
				
			||||||
            membership.save()
 | 
					            membership.save()
 | 
				
			||||||
            messages.success(request, "Accepted application.")
 | 
					            messages.success(request, _("Accepted application."))
 | 
				
			||||||
    return redirect("team_detail", slug=membership.team.slug)
 | 
					    return redirect("team_detail", slug=membership.team.slug)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -191,5 +192,5 @@ def team_reject(request, pk):
 | 
				
			||||||
        if membership.state == "applied":
 | 
					        if membership.state == "applied":
 | 
				
			||||||
            membership.state = "rejected"
 | 
					            membership.state = "rejected"
 | 
				
			||||||
            membership.save()
 | 
					            membership.save()
 | 
				
			||||||
            messages.success(request, "Rejected application.")
 | 
					            messages.success(request, _("Rejected application."))
 | 
				
			||||||
    return redirect("team_detail", slug=membership.team.slug)
 | 
					    return redirect("team_detail", slug=membership.team.slug)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue