Merge branch 'master' of github.com:Gluejar/regluit

pull/1/head
Raymond Yee 2012-05-01 22:49:44 -07:00
commit b4e6d7dcff
23 changed files with 486 additions and 185 deletions

View File

@ -0,0 +1,218 @@
# encoding: utf-8
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding field 'Campaign.edition'
db.add_column('core_campaign', 'edition', self.gf('django.db.models.fields.related.ForeignKey')(related_name='campaigns', null=True, to=orm['core.Edition']), keep_default=False)
def backwards(self, orm):
# Deleting field 'Campaign.edition'
db.delete_column('core_campaign', 'edition_id')
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'core.author': {
'Meta': {'object_name': 'Author'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'editions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'authors'", 'symmetrical': 'False', 'to': "orm['core.Edition']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '500'})
},
'core.campaign': {
'Meta': {'object_name': 'Campaign'},
'activated': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
'amazon_receiver': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'deadline': ('django.db.models.fields.DateTimeField', [], {}),
'description': ('django.db.models.fields.TextField', [], {'null': 'True'}),
'details': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'edition': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'campaigns'", 'null': 'True', 'to': "orm['core.Edition']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'left': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '14', 'decimal_places': '2'}),
'license': ('django.db.models.fields.CharField', [], {'default': "'CC BY-NC-ND'", 'max_length': '255'}),
'managers': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'campaigns'", 'symmetrical': 'False', 'to': "orm['auth.User']"}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '500', 'null': 'True'}),
'paypal_receiver': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
'status': ('django.db.models.fields.CharField', [], {'default': "'INITIALIZED'", 'max_length': '15', 'null': 'True'}),
'target': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '14', 'decimal_places': '2'}),
'work': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'campaigns'", 'to': "orm['core.Work']"})
},
'core.campaignaction': {
'Meta': {'object_name': 'CampaignAction'},
'campaign': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'actions'", 'to': "orm['core.Campaign']"}),
'comment': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'timestamp': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'type': ('django.db.models.fields.CharField', [], {'max_length': '15'})
},
'core.celerytask': {
'Meta': {'object_name': 'CeleryTask'},
'active': ('django.db.models.fields.NullBooleanField', [], {'default': 'True', 'null': 'True', 'blank': 'True'}),
'created': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime(2012, 4, 30, 16, 55, 2, 205843)', 'auto_now_add': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.CharField', [], {'max_length': '2048', 'null': 'True'}),
'function_args': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
'function_name': ('django.db.models.fields.CharField', [], {'max_length': '1024'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'task_id': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'tasks'", 'null': 'True', 'to': "orm['auth.User']"})
},
'core.claim': {
'Meta': {'object_name': 'Claim'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'rights_holder': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'claim'", 'to': "orm['core.RightsHolder']"}),
'status': ('django.db.models.fields.CharField', [], {'default': "'pending'", 'max_length': '7'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'claim'", 'to': "orm['auth.User']"}),
'work': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'claim'", 'to': "orm['core.Work']"})
},
'core.ebook': {
'Meta': {'object_name': 'Ebook'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'edition': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'ebooks'", 'to': "orm['core.Edition']"}),
'format': ('django.db.models.fields.CharField', [], {'max_length': '25'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'provider': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'rights': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
'url': ('django.db.models.fields.URLField', [], {'max_length': '1024'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True'})
},
'core.edition': {
'Meta': {'object_name': 'Edition'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'default': "''", 'null': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'public_domain': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}),
'publication_date': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True'}),
'publisher': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '1000'}),
'work': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'editions'", 'null': 'True', 'to': "orm['core.Work']"})
},
'core.identifier': {
'Meta': {'unique_together': "(('type', 'value'),)", 'object_name': 'Identifier'},
'edition': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'identifiers'", 'null': 'True', 'to': "orm['core.Edition']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'type': ('django.db.models.fields.CharField', [], {'max_length': '4'}),
'value': ('django.db.models.fields.CharField', [], {'max_length': '31'}),
'work': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'identifiers'", 'to': "orm['core.Work']"})
},
'core.premium': {
'Meta': {'object_name': 'Premium'},
'amount': ('django.db.models.fields.DecimalField', [], {'max_digits': '10', 'decimal_places': '0'}),
'campaign': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'premiums'", 'null': 'True', 'to': "orm['core.Campaign']"}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'null': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'limit': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'type': ('django.db.models.fields.CharField', [], {'max_length': '2'})
},
'core.rightsholder': {
'Meta': {'object_name': 'RightsHolder'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'email': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'owner': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'rights_holder'", 'to': "orm['auth.User']"}),
'rights_holder_name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'core.subject': {
'Meta': {'ordering': "['name']", 'object_name': 'Subject'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '200'}),
'works': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subjects'", 'symmetrical': 'False', 'to': "orm['core.Work']"})
},
'core.userprofile': {
'Meta': {'object_name': 'UserProfile'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'facebook_id': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True'}),
'goodreads_auth_secret': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'goodreads_auth_token': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'goodreads_user_id': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}),
'goodreads_user_link': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
'goodreads_user_name': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
'home_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'librarything_id': ('django.db.models.fields.CharField', [], {'max_length': '31', 'blank': 'True'}),
'pic_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
'tagline': ('django.db.models.fields.CharField', [], {'max_length': '140', 'blank': 'True'}),
'twitter_id': ('django.db.models.fields.CharField', [], {'max_length': '15', 'blank': 'True'}),
'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'profile'", 'unique': 'True', 'to': "orm['auth.User']"})
},
'core.waswork': {
'Meta': {'object_name': 'WasWork'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'moved': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True'}),
'was': ('django.db.models.fields.IntegerField', [], {'unique': 'True'}),
'work': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['core.Work']"})
},
'core.wishes': {
'Meta': {'object_name': 'Wishes', 'db_table': "'core_wishlist_works'"},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'source': ('django.db.models.fields.CharField', [], {'max_length': '15', 'blank': 'True'}),
'wishlist': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['core.Wishlist']"}),
'work': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'wishes'", 'to': "orm['core.Work']"})
},
'core.wishlist': {
'Meta': {'object_name': 'Wishlist'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'wishlist'", 'unique': 'True', 'to': "orm['auth.User']"}),
'works': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'wishlists'", 'symmetrical': 'False', 'through': "orm['core.Wishes']", 'to': "orm['core.Work']"})
},
'core.work': {
'Meta': {'ordering': "['title']", 'object_name': 'Work'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'language': ('django.db.models.fields.CharField', [], {'default': "'en'", 'max_length': '2'}),
'num_wishes': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'openlibrary_lookup': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '1000'})
}
}
complete_apps = ['core']

View File

@ -115,6 +115,7 @@ class Campaign(models.Model):
managers = models.ManyToManyField(User, related_name="campaigns", null=False) managers = models.ManyToManyField(User, related_name="campaigns", null=False)
# status: INITIALIZED, ACTIVE, SUSPENDED, WITHDRAWN, SUCCESSFUL, UNSUCCESSFUL # status: INITIALIZED, ACTIVE, SUSPENDED, WITHDRAWN, SUCCESSFUL, UNSUCCESSFUL
status = models.CharField(max_length=15, null=True, blank=False, default="INITIALIZED") status = models.CharField(max_length=15, null=True, blank=False, default="INITIALIZED")
edition = models.ForeignKey("Edition", related_name="campaigns", null=True)
problems = [] problems = []
def __unicode__(self): def __unicode__(self):
@ -323,13 +324,13 @@ class Work(models.Model):
def cover_image_small(self): def cover_image_small(self):
try: try:
return self.editions.all()[0].cover_image_small() return self.preferred_edition.cover_image_small()
except IndexError: except IndexError:
return "/static/images/generic_cover_larger.png" return "/static/images/generic_cover_larger.png"
def cover_image_thumbnail(self): def cover_image_thumbnail(self):
try: try:
return self.editions.all()[0].cover_image_thumbnail() return self.preferred_edition.cover_image_thumbnail()
except IndexError: except IndexError:
return "/static/images/generic_cover_larger.png" return "/static/images/generic_cover_larger.png"
@ -352,6 +353,13 @@ class Work(models.Model):
self._last_campaign_ = None self._last_campaign_ = None
return self._last_campaign_ return self._last_campaign_
@property
def preferred_edition(self):
if self.last_campaign():
if self.last_campaign().edition:
return self.last_campaign().edition
return self.editions.all()[0]
def last_campaign_status(self): def last_campaign_status(self):
campaign = self.last_campaign() campaign = self.last_campaign()
if campaign: if campaign:
@ -494,7 +502,14 @@ class Edition(models.Model):
work = models.ForeignKey("Work", related_name="editions", null=True) work = models.ForeignKey("Work", related_name="editions", null=True)
def __unicode__(self): def __unicode__(self):
return "%s (%s)" % (self.title, self.isbn_13) if self.isbn_13:
return "%s (ISBN %s) %s" % (self.title, self.isbn_13, self.publisher)
if self.oclc:
return "%s (OCLC %s) %s" % (self.title, self.oclc, self.publisher)
if self.googlebooks_id:
return "%s (GOOG %s) %s" % (self.title, self.googlebooks_id, self.publisher)
else:
return "%s (GLUE %s) %s" % (self.title, self.id, self.publisher)
def cover_image_small(self): def cover_image_small(self):
if self.googlebooks_id: if self.googlebooks_id:

View File

@ -5,13 +5,14 @@ from django.contrib.auth.models import User
from django.conf import settings from django.conf import settings
from django.core.validators import validate_email from django.core.validators import validate_email
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.forms.widgets import RadioSelect
from django.forms.extras.widgets import SelectDateWidget from django.forms.extras.widgets import SelectDateWidget
from decimal import Decimal as D from decimal import Decimal as D
from selectable.forms import AutoCompleteSelectMultipleWidget,AutoCompleteSelectMultipleField from selectable.forms import AutoCompleteSelectMultipleWidget,AutoCompleteSelectMultipleField
from selectable.forms import AutoCompleteSelectWidget,AutoCompleteSelectField from selectable.forms import AutoCompleteSelectWidget,AutoCompleteSelectField
from regluit.core.models import UserProfile, RightsHolder, Claim, Campaign, Premium, Ebook from regluit.core.models import UserProfile, RightsHolder, Claim, Campaign, Premium, Ebook, Edition
from regluit.core.lookups import OwnerLookup from regluit.core.lookups import OwnerLookup
from regluit.utils.localdatetime import now from regluit.utils.localdatetime import now
@ -165,50 +166,56 @@ class CustomPremiumForm(forms.ModelForm):
'type': forms.HiddenInput(attrs={'value':'XX'}), 'type': forms.HiddenInput(attrs={'value':'XX'}),
'limit': forms.TextInput(attrs={'value':'0'}), 'limit': forms.TextInput(attrs={'value':'0'}),
} }
def getManageCampaignForm ( instance, data=None, *args, **kwargs ):
def get_queryset():
work=instance.work
return Edition.objects.filter(work = work)
class ManageCampaignForm(forms.ModelForm): class ManageCampaignForm(forms.ModelForm):
paypal_receiver = forms.EmailField( paypal_receiver = forms.EmailField(
label=_("email address to collect Paypal funds"), label=_("email address to collect Paypal funds"),
max_length=100, max_length=100,
error_messages={'required': 'You must enter the email associated with your Paypal account.'}, error_messages={'required': 'You must enter the email associated with your Paypal account.'},
) )
target = forms.DecimalField( min_value= D('0.00'), error_messages={'required': 'Please specify a target price.'} ) target = forms.DecimalField( min_value= D('0.00'), error_messages={'required': 'Please specify a target price.'} )
class Meta: edition = forms.ModelChoiceField(get_queryset(), widget=RadioSelect(),empty_label='no edition selected')
model = Campaign
fields = 'description', 'details', 'license', 'target', 'deadline', 'paypal_receiver'
widgets = {
'description': forms.Textarea(attrs={'cols': 80, 'rows': 20}),
'details': forms.Textarea(attrs={'cols': 80, 'rows': 20}),
'deadline': SelectDateWidget
}
def clean_target(self): class Meta:
new_target = self.cleaned_data['target'] model = Campaign
if self.instance: fields = 'description', 'details', 'license', 'target', 'deadline', 'paypal_receiver', 'edition'
if self.instance.status == 'ACTIVE' and self.instance.target < new_target: widgets = {
raise forms.ValidationError(_('The fundraising target for an ACTIVE campaign cannot be increased.')) 'description': forms.Textarea(attrs={'cols': 80, 'rows': 20}),
if new_target < D(settings.UNGLUEIT_MINIMUM_TARGET): 'details': forms.Textarea(attrs={'cols': 80, 'rows': 20}),
raise forms.ValidationError(_('A campaign may not be launched with a target less than $%s' % settings.UNGLUEIT_MINIMUM_TARGET)) 'deadline': SelectDateWidget,
return new_target }
def clean_deadline(self): def clean_target(self):
new_deadline = self.cleaned_data['deadline'] new_target = self.cleaned_data['target']
if self.instance: if self.instance:
if self.instance.status == 'ACTIVE' and self.instance.deadline != new_deadline: if self.instance.status == 'ACTIVE' and self.instance.target < new_target:
raise forms.ValidationError(_('The closing date for an ACTIVE campaign cannot be changed.')) raise forms.ValidationError(_('The fundraising target for an ACTIVE campaign cannot be increased.'))
if new_deadline - now() > timedelta(days=int(settings.UNGLUEIT_LONGEST_DEADLINE)): if new_target < D(settings.UNGLUEIT_MINIMUM_TARGET):
raise forms.ValidationError(_('The chosen closing date is more than %s days from now' % settings.UNGLUEIT_LONGEST_DEADLINE)) raise forms.ValidationError(_('A campaign may not be launched with a target less than $%s' % settings.UNGLUEIT_MINIMUM_TARGET))
elif new_deadline - now() < timedelta(days=int(settings.UNGLUEIT_SHORTEST_DEADLINE)): return new_target
raise forms.ValidationError(_('The chosen closing date is less than %s days from now' % settings.UNGLUEIT_SHORTEST_DEADLINE))
return new_deadline
def clean_license(self): def clean_deadline(self):
new_license = self.cleaned_data['license'] new_deadline = self.cleaned_data['deadline']
if self.instance: if self.instance:
if self.instance.status == 'ACTIVE' and self.instance.license != new_license: if self.instance.status == 'ACTIVE' and self.instance.deadline != new_deadline:
raise forms.ValidationError(_('The license for an ACTIVE campaign cannot be changed.')) raise forms.ValidationError(_('The closing date for an ACTIVE campaign cannot be changed.'))
return new_license if new_deadline - now() > timedelta(days=int(settings.UNGLUEIT_LONGEST_DEADLINE)):
raise forms.ValidationError(_('The chosen closing date is more than %s days from now' % settings.UNGLUEIT_LONGEST_DEADLINE))
elif new_deadline - now() < timedelta(days=int(settings.UNGLUEIT_SHORTEST_DEADLINE)):
raise forms.ValidationError(_('The chosen closing date is less than %s days from now' % settings.UNGLUEIT_SHORTEST_DEADLINE))
return new_deadline
def clean_license(self):
new_license = self.cleaned_data['license']
if self.instance:
if self.instance.status == 'ACTIVE' and self.instance.license != new_license:
raise forms.ValidationError(_('The license for an ACTIVE campaign cannot be changed.'))
return new_license
return ManageCampaignForm(instance = instance, data=data)
class CampaignPledgeForm(forms.Form): class CampaignPledgeForm(forms.Form):
preapproval_amount = forms.DecimalField( preapproval_amount = forms.DecimalField(

View File

@ -30,7 +30,7 @@ $j("#js-leftcol").ready(function() {
{% else %}{% if faqmenu == "cancel" %} {% else %}{% if faqmenu == "cancel" %}
{% include "faq_pledge_cancel.html" %} {% include "faq_pledge_cancel.html" %}
{% else %}{% if faqmenu == "complete" %} {% else %}{% if faqmenu == "complete" %}
{% include "sidebar_pledge_complete.html" %} {% include "explore.html" %}
{% endif %}{% endif %}{% endif %} {% endif %}{% endif %}{% endif %}
</div> </div>
<div id="js-maincol-fr" class="have-right doc"> <div id="js-maincol-fr" class="have-right doc">
@ -50,14 +50,6 @@ $j("#js-leftcol").ready(function() {
</div> </div>
</div> </div>
{% if faqmenu == "complete" %}
<br />
<div id="js-slide">
<div class="jsmodule pledge">
{% include "slideshow.html" %}
</div>
</div>
{% endif %}
{% endblock %} {% endblock %}

View File

@ -53,6 +53,17 @@
{% endif %}{% endif %}{% endif %}{% endif %}{% endif %}{% endif %}{% endif %} {% endif %}{% endif %}{% endif %}{% endif %}{% endif %}{% endif %}{% endif %}
</div> </div>
{% comment %}link to work page{% endcomment %}
<div class="moreinfo">
<a href="{% if work.id %}{% url work work.id %}{% else %}{% url googlebooks googlebooks_id %}{% endif %}" target="_top">More Info</a>
</div>
{% comment %}bibliographic data{% endcomment %}
<div class="white_text">
<p><a href="{% if work.id %}{% url work work.id %}{% else %}{% url googlebooks googlebooks_id %}{% endif %}">{{ work.title }}</a></p>
<p>{{ author }}</p>
</div>
{% comment %}status of book vis-a-vis user's wishlist{% endcomment %} {% comment %}status of book vis-a-vis user's wishlist{% endcomment %}
{% if works and activetab %} {% if works and activetab %}
<div class="moreinfo add-wishlist"> <div class="moreinfo add-wishlist">
@ -82,17 +93,6 @@
</div> </div>
{% endif %}{% endif %}{% endifequal %}{% endif %}{% endif %} {% endif %}{% endif %}{% endifequal %}{% endif %}{% endif %}
{% comment %}bibliographic data{% endcomment %}
<div class="white_text">
<p><a href="{% if work.id %}{% url work work.id %}{% else %}{% url googlebooks googlebooks_id %}{% endif %}">{{ work.title }}</a></p>
<p>{{ author }}</p>
</div>
{% comment %}link to work page{% endcomment %}
<div class="moreinfo">
<a href="{% if work.id %}{% url work work.id %}{% else %}{% url googlebooks googlebooks_id %}{% endif %}" target="_top">More Info</a>
</div>
</div> </div>
</div> </div>
<div class="listview panelfront side1 book-thumb"> <div class="listview panelfront side1 book-thumb">

View File

@ -27,7 +27,7 @@
<p>Target: {{campaign.target}}</p> <p>Target: {{campaign.target}}</p>
<p>Deadline: {{campaign.deadline}}</p> <p>Deadline: {{campaign.deadline}}</p>
<p>Status: {{campaign.status}}</p> <p>Status: {{campaign.status}}</p>
<p>ISBN: {{campaign.work.editions.all.0.isbn_10}} | {{campaign.work.first_isbn_13}} </p> <p>ISBN: {{campaign.work.first_isbn_13}} </p>
<p><a href="{% url widget isbn=campaign.work.first_isbn_13 %}">Widget Link</a></p> <p><a href="{% url widget isbn=campaign.work.first_isbn_13 %}">Widget Link</a></p>
<p>Embed a widget:</p> <p>Embed a widget:</p>
<textarea rows="2" cols="80">&lt;iframe src="{{base_url}}/api/widget/{{campaign.work.first_isbn_13}}/" width="152" height="325" frameborder="0"&gt;</iframe></textarea> <textarea rows="2" cols="80">&lt;iframe src="{{base_url}}/api/widget/{{campaign.work.first_isbn_13}}/" width="152" height="325" frameborder="0"&gt;</iframe></textarea>

View File

@ -367,7 +367,7 @@ Unglue.it signs agreements assuring the copyright status of every work we unglue
<dl> <dl>
<dt>What do I need to do to become an authorized Rights Holder on Unglue.it?</dt> <dt>What do I need to do to become an authorized Rights Holder on Unglue.it?</dt>
<dd>Contact Amanda Mecke, <a href="mailto:amecke@gluejar.com">amecke@gluejar.com</a>, to discuss signing our Platform Services Agreement. This is the first step in being able to make an offer to license, set a monetary goal, and run a campaign on Unglue.it.</dd> <dd>Contact our Rights Holder Relations team, <a href="mailto:rights@gluejar.com">rights@gluejar.com</a>, to discuss signing our Platform Services Agreement. This is the first step in being able to make an offer to license, set a monetary goal, and run a campaign on Unglue.it.</dd>
<dt>Do I need to know the exact titles I might want to unglue before I sign the Platform Services Agreement?</dt> <dt>Do I need to know the exact titles I might want to unglue before I sign the Platform Services Agreement?</dt>
@ -429,7 +429,7 @@ We strongly encourage you to include video. You can upload it to YouTube and em
<dl> <dl>
<dt>I need help using social media channels to publicize my campaign.</dt> <dt>I need help using social media channels to publicize my campaign.</dt>
<dd>We're developing a social media toolkit for rights holders. Please tell us what you think should be in it so we can serve you better: <a href="mailto:andromeda@gluejar.com">andromeda@gluejar.com</a>. In the meantime we're happy to help you one-on-one, at the same address.</dd> <dd>We're developing a social media toolkit for rights holders. Please tell us what you think should be in it so we can serve you better: <a href="mailto:support@gluejar.com">support@gluejar.com</a>. In the meantime we're happy to help you one-on-one, at the same address.</dd>
<dt>Can I contact my supporters directly?</dt> <dt>Can I contact my supporters directly?</dt>
<dd>We will not provide you contact information, except as needed to fulfill premiums after successful campaigns. Supporters may voluntarily disclose certain contact information (such as Twitter handles) on their profile pages. We encourage you to be thoughtful in your use of this information. Supporters have likely provided it as a way to connect with other like-minded people, not as a marketing tool, so please engage with it in that spirit.</dd> <dd>We will not provide you contact information, except as needed to fulfill premiums after successful campaigns. Supporters may voluntarily disclose certain contact information (such as Twitter handles) on their profile pages. We encourage you to be thoughtful in your use of this information. Supporters have likely provided it as a way to connect with other like-minded people, not as a marketing tool, so please engage with it in that spirit.</dd>

View File

@ -47,7 +47,7 @@ Or, <a href="{% url rightsholders %}">go back</a> to rights holder tools page.<b
<h2 class="book-name">Title: <a href="{% url work campaign.work.id %}">{{ campaign.work.title }}</a></h2> <h2 class="book-name">Title: <a href="{% url work campaign.work.id %}">{{ campaign.work.title }}</a></h2>
<h3 class="book-author">Authors: {{ campaign.work.author }}</h3> <h3 class="book-author">Authors: {{ campaign.work.author }}</h3>
<h3 class="book-year">Published: {{ campaign.work.publication_date }}</h3> <h3 class="book-year">Published: {{ campaign.work.publication_date }}</h3>
<h3 class="book-author">Language: {{ campaign.work.editions.all.0.language }}</h3> <h3 class="book-author">Language: {{ campaign.work.language }}</h3>
<p>Target Price: ${{ campaign.target }}</p> <p>Target Price: ${{ campaign.target }}</p>
<p>End Date: {{ campaign.deadline|date:"M d, Y" }}</p> <p>End Date: {{ campaign.deadline|date:"M d, Y" }}</p>
<p>Campaign status: {{ campaign.status }}</p> <p>Campaign status: {{ campaign.status }}</p>
@ -58,6 +58,8 @@ Or, <a href="{% url rightsholders %}">go back</a> to rights holder tools page.<b
<h3>Description of the work offered for ungluing</h3> <h3>Description of the work offered for ungluing</h3>
<form action="#" method="POST"> <form action="#" method="POST">
{% csrf_token %} {% csrf_token %}
<p> Please choose the edition that most closely matches the edition to be unglued:
{{ form.edition.errors }}{{ form.edition }}
<p>This will be displayed in the Campaign tab for your work. It's your main pitch to supporters. It should include:</p> <p>This will be displayed in the Campaign tab for your work. It's your main pitch to supporters. It should include:</p>
<ul class="terms"> <ul class="terms">
<li>A synopsis of the work.</li> <li>A synopsis of the work.</li>
@ -104,7 +106,7 @@ The ending date can't be more than six months away- that's a practical limit for
<p> If your campaign succeeds, the funds raised (less commission and fees) will be deposited in a paypal account bearing this email address.</p> <p> If your campaign succeeds, the funds raised (less commission and fees) will be deposited in a paypal account bearing this email address.</p>
<p>{{ form.paypal_receiver.errors }}{{ form.paypal_receiver }}</p> <p>{{ form.paypal_receiver.errors }}{{ form.paypal_receiver }}</p>
<p>We recommend that you save and then preview your campaign before launch. If it doesn't look exactly the way you like, we're happy to help; please email Amanda (<a href="mailto:amecke@gluejar.com">amecke@gluejar.com</a>) or Andromeda (<a href="mailto:andromeda@gluejar.com">andromeda@gluejar.com</a>).</p> <p>We recommend that you save and then preview your campaign before launch. If it doesn't look exactly the way you like, we're happy to help; please email unglue.it support (<a href="mailto:support@gluejar.com">support@gluejar.com</a>).</p>
{% ifequal campaign.status 'ACTIVE' %} {% ifequal campaign.status 'ACTIVE' %}
<input type="submit" name="save" value="Modify Campaign" /> <input type="submit" name="save" value="Modify Campaign" />

View File

@ -20,7 +20,7 @@ URL: {{ ebook.url }}
{% if work.ebooks.0.rights == 'PD-US' %} {% if work.ebooks.0.rights == 'PD-US' %}
A public domain ebook belongs to all of us. You can do anything you like with it. A public domain ebook belongs to all of us. You can do anything you like with it.
{% else %} {% else %}
The Creative Commons licensing terms for allow you to redistribute the files under the specified license terms. There's no DRM. The Creative Commons licensing terms for {{ work.title }} allow you to redistribute the files under the specified license terms. There's no DRM. For full details, see http://creativecommons.org/licenses/.
{% endif %} {% endif %}
{% if work.last_campaign_status == 'SUCCESSFUL' %} {% if work.last_campaign_status == 'SUCCESSFUL' %}

View File

@ -10,16 +10,29 @@
{% endblock %} {% endblock %}
{% block doccontent %} {% block doccontent %}
<div style="height:10px";></div> <div style="height:15px";></div>
<div class="book-detail"> <div class="book-detail">
<div class="book-detail-img"> <div id="book-detail-img">
<a href="#"><img src="{{ work.cover_image_thumbnail }}" alt="{{ work.title }}" title="{{ work.title }}" width="131" height="192" /></a> <a href="#"><img src="{{ work.cover_image_thumbnail }}" alt="{{ work.title }}" title="{{ work.title }}" width="131" height="192" /></a>
</div> </div>
<div class="book-detail-info"> <div class="book-detail-info">
<h2 class="book-name">{{ work.title }}</h2> <div class="layout">
<h3 class="book-author">{{ work.author }}</h3> <h2 class="book-name">{{ work.title }}</h2>
<h3 class="book-year">{{ work.publication_date }}</h3> <div>
<div class="pubinfo">
<h3 class="book-author">{{ work.author }}</h3>
<h3 class="book-year">{{ pubdate }}</h3>
</div>
</div>
</div>
<div class="jsmodule rounded pledge">
<div class="jsmod-content">
${{ work.last_campaign.target }} needed by<br />
{{ work.last_campaign.deadline }}
</div>
</div>
<div class="pledged-info"> <div class="pledged-info">
<div class="pledged-group"> <div class="pledged-group">
@ -32,13 +45,6 @@
</div> </div>
</div> </div>
<div class="jsmodule rounded pledge">
<div class="jsmod-content">
${{ work.last_campaign.target }} needed by<br />
{{ work.last_campaign.deadline }}
</div>
</div>
<div class="jsmodule rounded"> <div class="jsmodule rounded">
<div class="jsmod-content"> <div class="jsmod-content">

View File

@ -9,6 +9,7 @@
<script src="/static/js/slides.min.jquery.js"></script> <script src="/static/js/slides.min.jquery.js"></script>
<script src="/static/js/slideshow.js"></script> <script src="/static/js/slideshow.js"></script>
<script src="/static/js/greenpanel.js"></script>
<!-- toggle to panelview state instead of listview default --> <!-- toggle to panelview state instead of listview default -->
<script type="text/javascript"> <script type="text/javascript">
@ -32,7 +33,7 @@ we need the share options and also something like the home page slide show to gi
<h2 class="thank-you">Thank you!</h2> <h2 class="thank-you">Thank you!</h2>
<p class="pledge_complete">You're now ungluing <a href="{% url work work.id %}">{{work.title}}</a>.</p> <p class="pledge_complete">You've just pledged ${{ transaction.amount }} to <a href="{% url work work.id %}">{{ work.title }}</a>. If it reaches its goal of ${{ campaign.target }} by {{ campaign.deadline|date:"M d Y"}}, it will be unglued for all to enjoy.</p>
<p class="pledge_complete">You can help even more by sharing this campaign with your friends:</p> <p class="pledge_complete">You can help even more by sharing this campaign with your friends:</p>
<div id="widgetcode">Copy/paste this into your site:<br /><textarea rows="7" cols="22">&lt;iframe src="https://{{request.META.HTTP_HOST}}/api/widget/{{work.first_isbn_13}}/" width="152" height="325" frameborder="0"&gt;&lt;/iframe&gt;</textarea></div> <div id="widgetcode">Copy/paste this into your site:<br /><textarea rows="7" cols="22">&lt;iframe src="https://{{request.META.HTTP_HOST}}/api/widget/{{work.first_isbn_13}}/" width="152" height="325" frameborder="0"&gt;&lt;/iframe&gt;</textarea></div>
@ -43,6 +44,24 @@ we need the share options and also something like the home page slide show to gi
<a href="#" id="embed"><li class="embed"><span>Embed</span></li></a> <a href="#" id="embed"><li class="embed"><span>Embed</span></li></a>
</ul> </ul>
</div> </div>
<br />
<div id="js-slide">
<div class="js-main">
<div class="jsmodule">
{% include "slideshow.html" %}
</div>
</div>
</div>
<div id="js-maincontainer-bot-block">
<div id="js-search">
<label>What book would you give to the world? </label>
<form action="{% url search %}" method="get">
<input type="text" id="watermark" onfocus="imgfocus()" onblur="imgblur(0)" size="25" class="inputbox" name="q" value="{{ q }}">
<input type="submit" class="greenbutton" value="Search">
</form>
</div>
</div>
{% endblock %} {% endblock %}

View File

@ -1,4 +1,4 @@
<h3><span{% if is_preview %}>Most wishlisted{% else %}{% if faqmenu %} class="pledge_indent">What next?{% else %}>Top ungluing campaigns{% endif %}{% endif %}</span></h3> <h3><span>{% if is_preview %}Most wishlisted{% else %}{% if faqmenu %}You might also like...{% else %}Top ungluing campaigns{% endif %}{% endif %}</span></h3>
<div class="jsmod-content"> <div class="jsmod-content">
<div id="js-slideshow"> <div id="js-slideshow">
<div class="slides_container"> <div class="slides_container">

View File

@ -255,6 +255,13 @@ there's no tab for seeing ALL my books, only the filters! huh.
<div id="js-maincol-fr"> <div id="js-maincol-fr">
<div class="js-maincol-inner"> <div class="js-maincol-inner">
<div id="content-block"> <div id="content-block">
{% if not works %}
{% comment %}
if we're in empty-wishlist, slideshow mode, suppress tab area
{% endcomment %}
<div class="content-block-heading wantto" id="tabs"> <div class="content-block-heading wantto" id="tabs">
<ul class="tabs"> <ul class="tabs">
<li class="tabs1"><a href="#">Unglued</a></li> <li class="tabs1"><a href="#">Unglued</a></li>
@ -262,12 +269,6 @@ there's no tab for seeing ALL my books, only the filters! huh.
<li class="tabs3"><a href="#">Wishlisted</a></li> <li class="tabs3"><a href="#">Wishlisted</a></li>
</ul> </ul>
{% if not works %}
{% comment %}
don't let people toggle views if we're doing the slideshow -- it'll look weird
{% endcomment %}
<ul class="book-list-view"> <ul class="book-list-view">
<li>View As:</li> <li>View As:</li>
<li class="view-list"> <li class="view-list">
@ -281,14 +282,15 @@ there's no tab for seeing ALL my books, only the filters! huh.
</a> </a>
</li> </li>
</ul> </ul>
{% endif %}
</div> </div>
{% endif %}
<div id="content-block-content"> <div id="content-block-content">
{% ifequal wishlist.works.all.count 0 %} {% ifequal wishlist.works.all.count 0 %}
{% ifequal request.user supporter %} {% ifequal request.user supporter %}
<div class="empty-wishlist"> <div class="empty-wishlist">
<div>You haven't wishlisted anything yet. Can we help?<br /><br /></div> <div><h2 style="padding-left:35px;">Add a book to your wishlist to get started.</h2><br /><br /></div>
<div id="js-slide"> <div id="js-slide">
<div class="js-main"> <div class="js-main">

View File

@ -55,13 +55,15 @@ $j(document).ready(function(){
<div class="js-main"> <div class="js-main">
<div id="js-leftcol"> <div id="js-leftcol">
<div class="jsmodule rounded"> <div class="jsmodule rounded">
<div class="jsmod-content{% if status == 'ACTIVE' %} active{{ work.percent_unglued}}{% endif %}"> <div class="jsmod-content {{ status }}">
<span> <span>
{% if work.first_ebook %} {% if work.first_ebook %}
AVAILABLE! AVAILABLE!
{% else %}{% if work.last_campaign %} {% else %}{% if work.last_campaign %}
{% if status == 'ACTIVE' %} {% if status == 'ACTIVE' %}
Campaign in Progress: <br />${{ work.last_campaign.current_total }}/${{ work.last_campaign.target }} Unglue it! <br />
${{ work.last_campaign.current_total }}/${{ work.last_campaign.target }} <br />
Ending {{ countdown }}
{% else %} {% else %}
{% if status == 'SUCCESSFUL' %} {% if status == 'SUCCESSFUL' %}
Unglued on {{ work.last_campaign.deadline|date:"M j, Y"}}! <br />${{ work.last_campaign.current_total }} raised of ${{ work.last_campaign.target }} goal Unglued on {{ work.last_campaign.deadline|date:"M j, Y"}}! <br />${{ work.last_campaign.current_total }} raised of ${{ work.last_campaign.target }} goal
@ -72,19 +74,24 @@ $j(document).ready(function(){
{% else %}{% if status == 'WITHDRAWN' %} {% else %}{% if status == 'WITHDRAWN' %}
Campaign withdrawn. <br />See <a href="/faq">FAQ</a>. Campaign withdrawn. <br />See <a href="/faq">FAQ</a>.
{% else %}{% if wishers == 1 %} {% else %}{% if wishers == 1 %}
<span class="findtheungluers">{{ wishers }} Ungluer is WISHING</span> <span class="findtheungluers">{{ wishers }} Ungluer is wishing</span>
{% else %} {% else %}
<span class="findtheungluers">{{ wishers }} Ungluers are WISHING</span> <span class="findtheungluers">{{ wishers }} Ungluers are wishing</span>
{% endif %}{% endif %}{% endif %}{% endif %}{% endif %} {% endif %}
<br />
You can too!
{% endif %}{% endif %}{% endif %}{% endif %}
{% endif %} {% endif %}
{% else %} {% else %}
<span class="findtheungluers"> <span class="findtheungluers">
{% if wishers == 1 %} {% if wishers == 1 %}
{{ wishers }} Ungluer is WISHING {{ wishers }} Ungluer is wishing
{% else %} {% else %}
{{ wishers }} Ungluers are WISHING {{ wishers }} Ungluers are wishing
{% endif %} {% endif %}
</span> </span>
<br />
You can too!
{% endif %}{% endif %} {% endif %}{% endif %}
</span> </span>
<span class="spacer">&nbsp;<br />&nbsp;</span> <span class="spacer">&nbsp;<br />&nbsp;</span>
@ -114,7 +121,7 @@ $j(document).ready(function(){
<div class="btn_support"><form action="{% url pledge work_id=work.id %}" method="get"><input type="submit" value="Support" /></form></div> <div class="btn_support"><form action="{% url pledge work_id=work.id %}" method="get"><input type="submit" value="Support" /></form></div>
{% endif %} {% endif %}
{% endif %} {% endif %}
</div> </div>
</div> </div>
{% if work.first_ebook %} {% if work.first_ebook %}
<div class="get-book"> <div class="get-book">
@ -139,7 +146,7 @@ $j(document).ready(function(){
{% endfor %} {% endfor %}
</span> </span>
</div> </div>
{% endif %} {% endif %}
<div class="find-book"> <div class="find-book">
<label>Find it:</label> <label>Find it:</label>
<div class="find-link"> <div class="find-link">

View File

@ -44,7 +44,7 @@ from regluit.core.search import gluejar_search
from regluit.core.goodreads import GoodreadsClient from regluit.core.goodreads import GoodreadsClient
from regluit.frontend.forms import UserData, UserEmail, ProfileForm, CampaignPledgeForm, GoodreadsShelfLoadingForm from regluit.frontend.forms import UserData, UserEmail, ProfileForm, CampaignPledgeForm, GoodreadsShelfLoadingForm
from regluit.frontend.forms import RightsHolderForm, UserClaimForm, LibraryThingForm, OpenCampaignForm from regluit.frontend.forms import RightsHolderForm, UserClaimForm, LibraryThingForm, OpenCampaignForm
from regluit.frontend.forms import ManageCampaignForm, DonateForm, CampaignAdminForm, EmailShareForm, FeedbackForm from regluit.frontend.forms import getManageCampaignForm, DonateForm, CampaignAdminForm, EmailShareForm, FeedbackForm
from regluit.frontend.forms import EbookForm, CustomPremiumForm, EditManagersForm from regluit.frontend.forms import EbookForm, CustomPremiumForm, EditManagersForm
from regluit.payment.manager import PaymentManager from regluit.payment.manager import PaymentManager
from regluit.payment.models import Transaction from regluit.payment.models import Transaction
@ -129,8 +129,11 @@ def work(request, work_id, action='display'):
activetab = '1'; activetab = '1';
except: except:
activetab = '1'; activetab = '1';
editions = work.editions.all().order_by('-publication_date')
campaign = work.last_campaign() campaign = work.last_campaign()
if campaign and campaign.edition:
editions = [campaign.edition]
else:
editions = work.editions.all().order_by('-publication_date')
if action == 'preview': if action == 'preview':
work.last_campaign_status = 'ACTIVE' work.last_campaign_status = 'ACTIVE'
try: try:
@ -138,6 +141,18 @@ def work(request, work_id, action='display'):
except: except:
pledged = None pledged = None
countdown = ""
if work.last_campaign_status() == 'ACTIVE':
time_remaining = campaign.deadline - now()
if time_remaining.days:
countdown = "in %s days" % time_remaining.days
elif time_remaining.seconds > 3600:
countdown = "in %s hours" % time_remaining.seconds/3600
elif time_remaining.seconds > 60:
countdown = "in %s minutes" % time_remaining.seconds/60
else:
countdown = "right now"
try: try:
pubdate = work.publication_date[:4] pubdate = work.publication_date[:4]
except IndexError: except IndexError:
@ -199,6 +214,7 @@ def work(request, work_id, action='display'):
'alert': alert, 'alert': alert,
'claimstatus': claimstatus, 'claimstatus': claimstatus,
'rights_holder_name': rights_holder_name, 'rights_holder_name': rights_holder_name,
'countdown': countdown,
}) })
def manage_campaign(request, id): def manage_campaign(request, id):
@ -220,9 +236,9 @@ def manage_campaign(request, id):
new_premium_form = CustomPremiumForm(data={'campaign': campaign}) new_premium_form = CustomPremiumForm(data={'campaign': campaign})
else: else:
alerts.append(_('New premium has not been added')) alerts.append(_('New premium has not been added'))
form = ManageCampaignForm(instance=campaign) form = getManageCampaignForm(instance=campaign)
elif request.POST.has_key('save') or request.POST.has_key('launch') : elif request.POST.has_key('save') or request.POST.has_key('launch') :
form= ManageCampaignForm(instance=campaign, data=request.POST) form= getManageCampaignForm(instance=campaign, data=request.POST)
if form.is_valid(): if form.is_valid():
form.save() form.save()
alerts.append(_('Campaign data has been saved')) alerts.append(_('Campaign data has been saved'))
@ -244,10 +260,10 @@ def manage_campaign(request, id):
selected_premium.type = 'XX' selected_premium.type = 'XX'
selected_premium.save() selected_premium.save()
alerts.append(_('Premium %s has been inactivated'% premium_to_stop)) alerts.append(_('Premium %s has been inactivated'% premium_to_stop))
form = ManageCampaignForm(instance=campaign) form = getManageCampaignForm(instance=campaign)
new_premium_form = CustomPremiumForm(data={'campaign': campaign}) new_premium_form = CustomPremiumForm(data={'campaign': campaign})
else: else:
form = ManageCampaignForm(instance=campaign) form = getManageCampaignForm(instance=campaign)
new_premium_form = CustomPremiumForm(data={'campaign': campaign}) new_premium_form = CustomPremiumForm(data={'campaign': campaign})
return render(request, 'manage_campaign.html', { return render(request, 'manage_campaign.html', {
@ -423,7 +439,13 @@ class PledgeView(FormView):
else: else:
form = form_class() form = form_class()
context.update({'work':work,'campaign':campaign, 'premiums':premiums, 'form':form, 'premium_id':premium_id, 'faqmenu': 'pledge'}) try:
pubdate = work.publication_date[:4]
except IndexError:
pubdate = 'unknown'
context.update({'work':work,'campaign':campaign, 'premiums':premiums, 'form':form, 'premium_id':premium_id, 'faqmenu': 'pledge', 'pubdate':pubdate})
return context return context
def form_valid(self, form): def form_valid(self, form):
@ -664,9 +686,9 @@ class PledgeCompleteView(TemplateView):
# ok to overwrite Wishes.source? # ok to overwrite Wishes.source?
user.wishlist.add_work(work, 'pledging') user.wishlist.add_work(work, 'pledging')
worklist = slideshow(12) worklist = slideshow(8)
works = worklist[:6] works = worklist[:4]
works2 = worklist[6:12] works2 = worklist[4:8]
context["transaction"] = transaction context["transaction"] = transaction
context["correct_user"] = correct_user context["correct_user"] = correct_user

View File

@ -109,26 +109,15 @@
border: none; border: none;
margin: 0; margin: 0;
} }
#js-leftcol .jsmodule.rounded .jsmod-content.active0, #js-leftcol .jsmodule.rounded .jsmod-content.ACTIVE, .pledge.jsmodule.rounded .jsmod-content.ACTIVE {
.pledge.jsmodule.rounded .jsmod-content.active0,
#js-leftcol .jsmodule.rounded .jsmod-content.active1,
.pledge.jsmodule.rounded .jsmod-content.active1 {
background: #e35351;
}
#js-leftcol .jsmodule.rounded .jsmod-content.active2, .pledge.jsmodule.rounded .jsmod-content.active2 {
background: #e18551;
}
#js-leftcol .jsmodule.rounded .jsmod-content.active3, .pledge.jsmodule.rounded .jsmod-content.active3 {
background: #e5a956;
}
#js-leftcol .jsmodule.rounded .jsmod-content.active4, .pledge.jsmodule.rounded .jsmod-content.active4 {
background: #efd45e;
}
#js-leftcol .jsmodule.rounded .jsmod-content.active5, .pledge.jsmodule.rounded .jsmod-content.active5 {
background: #bbcf67;
}
#js-leftcol .jsmodule.rounded .jsmod-content.active6, .pledge.jsmodule.rounded .jsmod-content.active6 {
background: #8dc63f; background: #8dc63f;
color: white;
font-size: 18px;
font-weight: normal;
}
#js-leftcol .jsmodule.rounded .jsmod-content.No.campaign.yet, .pledge.jsmodule.rounded .jsmod-content.No.campaign.yet {
background: #e18551;
color: white;
} }
#js-leftcol .jsmodule.rounded .jsmod-content span, .pledge.jsmodule.rounded .jsmod-content span { #js-leftcol .jsmodule.rounded .jsmod-content span, .pledge.jsmodule.rounded .jsmod-content span {
display: inline-block; display: inline-block;
@ -196,6 +185,7 @@
.book-detail-info > div.layout div.pubinfo { .book-detail-info > div.layout div.pubinfo {
float: left; float: left;
width: auto; width: auto;
padding-bottom: 7px;
} }
.book-detail-info > div.layout div.btn_support { .book-detail-info > div.layout div.btn_support {
float: right; float: right;
@ -262,8 +252,7 @@
#tabs-1, #tabs-1,
#tabs-2, #tabs-2,
#tabs-3, #tabs-3,
#tabs-4, #tabs-4 {
.more_ebooks {
display: none; display: none;
} }
#tabs-1.active, #tabs-1.active,
@ -368,6 +357,9 @@ ul.tabs li a:hover, ul.tabs li.active a {
div#content-block-content { div#content-block-content {
padding-left: 5px; padding-left: 5px;
} }
div#content-block-content a {
color: #6994a3;
}
.tabs-content { .tabs-content {
padding-right: 5px; padding-right: 5px;
} }
@ -538,7 +530,7 @@ ul.support li:hover a {
.editions a:hover { .editions a:hover {
text-decoration: underline; text-decoration: underline;
} }
.show_more_edition,.show_more_ebooks{ .show_more_edition, .show_more_ebooks {
cursor: pointer; cursor: pointer;
} }
.thank-you { .thank-you {
@ -567,13 +559,18 @@ ul.support li:hover a {
padding-bottom: 10px; padding-bottom: 10px;
padding-left: 60px; padding-left: 60px;
} }
.show_more_edition:hover, .show_more_edition:hover {
.show_more_ebooks:hover {
text-decoration: underline; text-decoration: underline;
} }
.show_more_edition { .show_more_edition {
text-align: right; text-align: right;
} }
.more_ebooks {
display: none;
}
.show_more_ebooks:hover {
text-decoration: underline;
}
.alert > .errorlist { .alert > .errorlist {
list-style-type: none; list-style-type: none;
font-size: 14px; font-size: 14px;
@ -598,3 +595,10 @@ ul.support li:hover a {
#js-slide .jsmodule { #js-slide .jsmodule {
width: 660px !important; width: 660px !important;
} }
a {
color: #3d4e53;
font-size: 12px;
}
#js-search {
margin: 0 15px 0 15px !important;
}

View File

@ -578,11 +578,8 @@ h2.thank-you {
#js-slide .jsmodule.pledge { #js-slide .jsmodule.pledge {
width: 960px !important; width: 960px !important;
} }
h3 .pledge_indent {
margin-left: 240px;
}
ul.social.pledge { ul.social.pledge {
margin-bottom: 150px; margin-bottom: 100px;
} }
ul.social.pledge li { ul.social.pledge li {
float: left; float: left;

View File

@ -100,13 +100,12 @@
cursor: pointer; cursor: pointer;
} }
.pledge_amount { .pledge_amount {
margin: auto auto 10px 10px; padding: 10px;
font-size: 17px; font-size: 17px;
background: #edf3f4;
} }
form.pledgeform { form.pledgeform {
margin-top: 10px; width: 470px;
padding-top: 10px;
border-top: solid 2px #d6dde0;
} }
#id_preapproval_amount { #id_preapproval_amount {
width: 50%; width: 50%;
@ -119,3 +118,9 @@ ul.support li, ul.support li:hover {
p { p {
margin: 7px auto; margin: 7px auto;
} }
.jsmodule.pledge {
margin: auto;
}
.jsmodule.pledge .jsmod-content {
float: right !important;
}

View File

@ -175,9 +175,9 @@ body {
bottom: 0; bottom: 0;
width: 160px; width: 160px;
height: 32px; height: 32px;
-moz-border-radius: 32px; -moz-border-radius: 10px 10px 0 0;
-webkit-border-radius: 32px; -webkit-border-radius: 10px 10px 0 0;
border-radius: 32px; border-radius: 10px 10px 0 0;
background: #8dc63f; background: #8dc63f;
margin-bottom: 0; margin-bottom: 0;
text-align: center; text-align: center;

View File

@ -37,28 +37,16 @@
border:none; border:none;
margin:0; margin:0;
&.active0, &.active1 { &.ACTIVE {
background: #e35351;
}
&.active2 {
background: #e18551;
}
&.active3 {
background: #e5a956;
}
&.active4 {
background: #efd45e;
}
&.active5 {
background: #bbcf67;
}
&.active6 {
background: @green; background: @green;
color: white;
font-size: 18px;
font-weight: normal;
}
&.No.campaign.yet {
background: #e18551;
color: white;
} }
span { span {
@ -139,6 +127,7 @@
div.pubinfo { div.pubinfo {
float: left; float: left;
width: auto; width: auto;
padding-bottom: 7px;
} }
div.btn_support { div.btn_support {
@ -328,6 +317,10 @@ ul.tabs {
div#content-block-content { div#content-block-content {
padding-left: 5px; padding-left: 5px;
a {
color: @medium-blue;
}
} }
.tabs-content { .tabs-content {
@ -544,3 +537,12 @@ ul.support li {
#js-slide .jsmodule { #js-slide .jsmodule {
width: 660px !important; width: 660px !important;
} }
a {
color:#3d4e53;
font-size:12px;
}
#js-search {
margin: 0 15px 0 15px !important;
}

View File

@ -304,17 +304,13 @@ h2.thank-you {
width: 960px !important; width: 960px !important;
} }
h3 .pledge_indent {
margin-left: 240px;
}
ul.social.pledge { ul.social.pledge {
li { li {
float: left; float: left;
padding-right: 30px !important; padding-right: 30px !important;
} }
margin-bottom: 150px; margin-bottom: 100px;
} }
#widgetcode { #widgetcode {

View File

@ -13,14 +13,13 @@
} }
.pledge_amount { .pledge_amount {
margin: auto auto 10px 10px; padding: 10px;
font-size: 17px; font-size: 17px;
background: @pale-blue;
} }
form.pledgeform { form.pledgeform {
margin-top: 10px; width: 470px;
padding-top: 10px;
border-top: solid 2px @blue-grey;
} }
#id_preapproval_amount { #id_preapproval_amount {
@ -36,3 +35,11 @@ ul.support li, ul.support li:hover {
p { p {
margin: 7px auto; margin: 7px auto;
} }
.jsmodule.pledge {
margin: auto;
.jsmod-content {
float: right !important;
}
}

View File

@ -85,7 +85,7 @@ body{
bottom:0; bottom:0;
width:160px; width:160px;
height:32px; height:32px;
.one-border-radius(32px); .border-radius(10px, 10px, 0, 0);
background: @call-to-action; background: @call-to-action;
margin-bottom: 0; margin-bottom: 0;
text-align: center; text-align: center;