diff --git a/badger_multiplayer/forms.py b/badger_multiplayer/forms.py
index 5162131..5ed5458 100644
--- a/badger_multiplayer/forms.py
+++ b/badger_multiplayer/forms.py
@@ -12,33 +12,10 @@ except ImportError, e:
from django.utils.translation import ugettext_lazy as _
from badger.models import (Award)
+from badger.forms import (MyModelForm, MyForm)
from badger_multiplayer.models import (Badge, Nomination)
-class MyModelForm(forms.ModelForm):
- def as_ul(self):
- "Returns this form rendered as HTML
s -- excluding the ."
- return self._html_output(
- normal_row=(u'%(label)s %(field)s' +
- '%(help_text)s%(errors)s'),
- error_row=u'%s',
- row_ender='',
- help_text_html=u' %s
',
- errors_on_separate_row=False)
-
-
-class MyForm(forms.Form):
- def as_ul(self):
- "Returns this form rendered as HTML s -- excluding the ."
- return self._html_output(
- normal_row=(u'%(label)s %(field)s' +
- '%(help_text)s%(errors)s'),
- error_row=u'%s',
- row_ender='',
- help_text_html=u' %s
',
- errors_on_separate_row=False)
-
-
class BadgeEditForm(MyModelForm):
class Meta:
@@ -63,3 +40,10 @@ class BadgeNewForm(BadgeEditForm):
super(BadgeNewForm, self).__init__(*args, **kwargs)
#if not settings.RECAPTCHA_PRIVATE_KEY:
# del self.fields['captcha']
+
+class BadgeSubmitNominationForm(MyModelForm):
+
+ class Meta:
+ model = Nomination
+ fields = ('nominee', )
+
diff --git a/badger_multiplayer/models.py b/badger_multiplayer/models.py
index d527ef8..8f71d41 100644
--- a/badger_multiplayer/models.py
+++ b/badger_multiplayer/models.py
@@ -18,14 +18,33 @@ from badger.models import (Award, BadgerException,
from .signals import (nomination_will_be_approved, nomination_was_approved,
nomination_will_be_accepted, nomination_was_accepted,
- user_will_be_nominated, user_was_nominated,)
+ user_will_be_nominated, user_was_nominated, )
class Badge(badger.models.Badge):
"""Enhanced Badge model with multiplayer features"""
+
class Meta:
proxy = True
+ get_permissions_for = get_permissions_for
+
+ def allows_nominate_for(self, user):
+ """Is nominate_for() allowed for this user?"""
+ if None == user:
+ return True
+ if user.is_anonymous():
+ return False
+ if user.is_staff or user.is_superuser:
+ return True
+ if user == self.creator:
+ return True
+
+ # TODO: Flag to enable / disable nominations from anyone
+ # TODO: List of delegates from whom nominations are accepted
+
+ return True
+
def nominate_for(self, nominee, nominator=None):
"""Nominate a nominee for this badge on the nominator's behalf"""
return Nomination.objects.create(badge=self, creator=nominator,
@@ -35,6 +54,20 @@ class Badge(badger.models.Badge):
return Nomination.objects.filter(nominee=user, badge=self).count() > 0
+class Award(badger.models.Award):
+ """Enhanced Award model with multiplayer features"""
+
+ class Meta:
+ proxy = True
+
+ @property
+ def badge(self):
+ """Property that wraps the related badge in a multiplayer upgrade"""
+ new_inst = Badge()
+ new_inst.__dict__ = super(Award, self).badge.__dict__
+ return new_inst
+
+
class NominationException(BadgerException):
"""Nomination model exception"""
@@ -88,7 +121,14 @@ class Nomination(models.Model):
nomination=self)
if self.is_approved() and self.is_accepted():
- self.award = self.badge.award_to(self.nominee, self.approver)
+ # HACK: Convert the original-flavor Award into a multiplayer Award
+ # before assigning to self.
+ real_award = self.badge.award_to(self.nominee, self.approver)
+ award = Award()
+ award.__dict__ = real_award.__dict__
+ self.award = award
+ # This was the original code, which caused errors:
+ # self.award = self.badge.award_to(self.nominee, self.approver)
super(Nomination, self).save(*args, **kwargs)
@@ -96,11 +136,26 @@ class Nomination(models.Model):
user_was_nominated.send(sender=self.__class__,
nomination=self)
+ def allows_detail_by(self, user):
+ if (user.is_staff or
+ user.is_superuser or
+ user == self.badge.creator or
+ user == self.nominee or
+ user == self.creator ):
+ return True
+
+ # TODO: List of delegates empowered by badge creator to approve nominations
+
+ return False
+
def allows_approve_by(self, user):
if user.is_staff or user.is_superuser:
return True
if user == self.badge.creator:
return True
+
+ # TODO: List of delegates empowered by badge creator to approve nominations
+
return False
def approve_by(self, approver):
diff --git a/badger_multiplayer/templates/badger/includes/badge_full.html b/badger_multiplayer/templates/badger/includes/badge_full.html
deleted file mode 100644
index b9f0191..0000000
--- a/badger_multiplayer/templates/badger/includes/badge_full.html
+++ /dev/null
@@ -1,21 +0,0 @@
-
- {% if award and award.image %}
- - Image:
-
- {% elif badge.image %}
- - Image:
-
- {% endif %}
- - Title:
- - {{ badge.title }}
- {% if badge.description %}
- - Description:
-
-
- {{ badge.description }}
- {% endif %}
- {% if badge.allows_edit_by(request.user) %}
- - Actions:
-
- {% endif %}
-
diff --git a/badger_multiplayer/templates/badger_multiplayer/badge_nominate_for.html b/badger_multiplayer/templates/badger_multiplayer/badge_nominate_for.html
new file mode 100644
index 0000000..998bb43
--- /dev/null
+++ b/badger_multiplayer/templates/badger_multiplayer/badge_nominate_for.html
@@ -0,0 +1,22 @@
+{% extends "badger/base.html" %}
+
+{% block pageid %}badge_nominate{% endblock %}
+
+{% block content %}
+
+Submit a badge nomination
+
+
+
+
+ Badge
+ {% include "badger/includes/badge_full.html" %}
+
+
+{% endblock %}
diff --git a/badger_multiplayer/templates/badger_multiplayer/includes/badge_full_actions.html b/badger_multiplayer/templates/badger_multiplayer/includes/badge_full_actions.html
new file mode 100644
index 0000000..8a485ef
--- /dev/null
+++ b/badger_multiplayer/templates/badger_multiplayer/includes/badge_full_actions.html
@@ -0,0 +1,6 @@
+{% if badge.allows_nominate_for(request.user) %}
+ {{ _('Submit nomination') }}
+{% endif %}
+{% if badge.allows_edit_by(request.user) %}
+ {{ _('Edit badge') }}
+{% endif %}
diff --git a/badger_multiplayer/templates/badger_multiplayer/nomination_detail.html b/badger_multiplayer/templates/badger_multiplayer/nomination_detail.html
new file mode 100644
index 0000000..68270d8
--- /dev/null
+++ b/badger_multiplayer/templates/badger_multiplayer/nomination_detail.html
@@ -0,0 +1,58 @@
+{% extends "badger/base.html" %}
+
+{% block pageid %}nomination_detail{% endblock %}
+
+{% block content %}
+
+
+ Nomination
+
+ {% set show_approve = not nomination.is_approved() and nomination.allows_approve_by(request.user) %}
+ {% set show_accept = not nomination.is_accepted() and nomination.allows_accept(request.user) %}
+ {% if show_approve or show_accept %}
+ - Actions:
+ {% if show_approve %}
+
+ {% endif %}
+ {% if show_accept %}
+
+ {% endif %}
+
+ {% endif %}
+ {% if nomination.award %}
+ - Award:
+ - {{ nomination.award }}
+ {% endif %}
+ - Accepted?:
+ - {{ nomination.accepted and "Yes" or "No" }}
+ - Approved?:
+ - {{ nomination.approver and "Yes" or "No" }}
+ - Nominee:
+ - {{ nomination.nominee }}
+ - Nominator:
+ - {{ nomination.creator }}
+ {% if nomination.approver %}
+ - Approver:
+ - {{ nomination.approver }}
+ {% endif %}
+ - Created:
+ - {{ nomination.created }}
+ - Modified:
+ - {{ nomination.modified }}
+
+
+
+
+ Badge
+ {% include "badger/includes/badge_full.html" %}
+
+
+{% endblock %}
diff --git a/badger_multiplayer/urls.py b/badger_multiplayer/urls.py
index a13f2f4..c139a39 100644
--- a/badger_multiplayer/urls.py
+++ b/badger_multiplayer/urls.py
@@ -8,10 +8,14 @@ from .feeds import BadgesRecentFeed
urlpatterns = patterns('badger_multiplayer.views',
- url(r'^create$', 'create',
+ url(r'^;create$', 'create',
name='badger_multiplayer.create_badge'),
- url(r'^badges/(?P[^/]+)/edit$', 'edit',
+ url(r'^detail/(?P[^/]+);nominate$', 'nominate_for',
+ name='badger_multiplayer.nominate_for'),
+ url(r'^detail/(?P[^/]+);edit$', 'edit',
name='badger_multiplayer.badge_edit'),
+ url(r'^detail/(?P[^/]+)/nominations/(?P[^/]+)/?$', 'nomination_detail',
+ name='badger.nomination_detail'),
url(r'^feeds/(?P[^/]+)/badges/?$', BadgesRecentFeed(),
name="badger_multiplayer.feeds.badges_recent"),
diff --git a/badger_multiplayer/views.py b/badger_multiplayer/views.py
index 70039da..b58316c 100644
--- a/badger_multiplayer/views.py
+++ b/badger_multiplayer/views.py
@@ -36,7 +36,8 @@ from badger_multiplayer.models import (Badge, Nomination,
NominationApproveNotAllowedException,
NominationAcceptNotAllowedException)
-from badger_multiplayer.forms import (BadgeNewForm, BadgeEditForm)
+from badger_multiplayer.forms import (BadgeNewForm, BadgeEditForm,
+ BadgeSubmitNominationForm)
@require_http_methods(['GET', 'POST'])
@@ -83,3 +84,51 @@ def edit(request, slug):
return render_to_response('badger_multiplayer/badge_edit.html', dict(
badge=badge, form=form,
), context_instance=RequestContext(request))
+
+
+@require_http_methods(['GET', 'POST'])
+@login_required
+def nomination_detail(request, slug, id, format="html"):
+ """Show details on a nomination, provide for approval and acceptance"""
+ badge = get_object_or_404(Badge, slug=slug)
+ nomination = get_object_or_404(Nomination, badge=badge, pk=id)
+ if not nomination.allows_detail_by(request.user):
+ return HttpResponseForbidden()
+
+ if request.method == "POST":
+ action = request.POST.get('action', '')
+ if action == 'approve_by':
+ nomination.approve_by(request.user)
+ elif action == 'accept':
+ nomination.accept(request.user)
+ return HttpResponseRedirect(reverse(
+ 'badger_multiplayer.views.nomination_detail',
+ args=(slug, id)))
+
+ return render_to_response('badger_multiplayer/nomination_detail.html', dict(
+ badge=badge, nomination=nomination,
+ ), context_instance=RequestContext(request))
+
+
+@require_http_methods(['GET', 'POST'])
+@login_required
+def nominate_for(request, slug):
+ """Submit nomination for a badge"""
+ badge = get_object_or_404(Badge, slug=slug)
+ if not badge.allows_nominate_for(request.user):
+ return HttpResponseForbidden()
+
+ if request.method != "POST":
+ form = BadgeSubmitNominationForm()
+ else:
+ form = BadgeSubmitNominationForm(request.POST, request.FILES)
+ if form.is_valid():
+ award = badge.nominate_for(form.cleaned_data['nominee'],
+ request.user)
+ return HttpResponseRedirect(reverse(
+ 'badger_multiplayer.views.nomination_detail',
+ args=(badge.slug, award.id, )))
+
+ return render_to_response('badger_multiplayer/badge_nominate_for.html', dict(
+ form=form, badge=badge,
+ ), context_instance=RequestContext(request))