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