Merge branch 'master' into relaunch_ry

Conflicts:
	core/signals.py
	frontend/views.py
pull/1/head
Raymond Yee 2012-09-10 14:18:30 -07:00
commit 0e1839d531
18 changed files with 621 additions and 501 deletions

View File

@ -0,0 +1,232 @@
# 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):
# Deleting field 'Ebook.unglued'
db.delete_column('core_ebook', 'unglued')
# Adding field 'Edition.unglued'
db.add_column('core_edition', 'unglued', self.gf('django.db.models.fields.BooleanField')(default=False), keep_default=False)
def backwards(self, orm):
# Adding field 'Ebook.unglued'
db.add_column('core_ebook', 'unglued', self.gf('django.db.models.fields.BooleanField')(default=False), keep_default=False)
# Deleting field 'Edition.unglued'
db.delete_column('core_edition', 'unglued')
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': ('ckeditor.fields.RichTextField', [], {'null': 'True'}),
'details': ('ckeditor.fields.RichTextField', [], {'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, 9, 10, 14, 9, 45, 330452)', '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'},
'cover_image': ('django.db.models.fields.URLField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': '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', 'blank': 'True'}),
'publisher': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '1000'}),
'unglued': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'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.key': {
'Meta': {'object_name': 'Key'},
'encrypted_value': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'})
},
'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'}),
'description': ('django.db.models.fields.TextField', [], {'default': "''", 'null': '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

@ -16,7 +16,7 @@ from django.utils.translation import ugettext_lazy as _
import regluit
import regluit.core.isbn
from regluit.core.signals import successful_campaign, unsuccessful_campaign
from regluit.core.signals import successful_campaign, unsuccessful_campaign, wishlist_added
import binascii
from regluit.payment.parameters import TRANSACTION_STATUS_ACTIVE, TRANSACTION_STATUS_COMPLETE, TRANSACTION_STATUS_CANCELED, TRANSACTION_STATUS_ERROR, TRANSACTION_STATUS_FAILED, TRANSACTION_STATUS_INCOMPLETE
@ -695,6 +695,7 @@ class Edition(models.Model):
public_domain = models.NullBooleanField(null=True, blank=True)
work = models.ForeignKey("Work", related_name="editions", null=True)
cover_image = models.URLField(null=True, blank=True)
unglued = models.BooleanField(blank=True)
def __unicode__(self):
if self.isbn_13:
@ -784,7 +785,6 @@ class Ebook(models.Model):
created = models.DateTimeField(auto_now_add=True)
format = models.CharField(max_length=25, choices = FORMAT_CHOICES)
provider = models.CharField(max_length=255)
unglued = models.BooleanField()
# use 'PD-US', 'CC BY', 'CC BY-NC-SA', 'CC BY-NC-ND', 'CC BY-NC', 'CC BY-ND', 'CC BY-SA', 'CC0'
rights = models.CharField(max_length=255, null=True, choices = RIGHTS_CHOICES)
@ -836,7 +836,8 @@ class Wishlist(models.Model):
w = Wishes.objects.get(wishlist=self,work=work)
except:
Wishes.objects.create(source=source,wishlist=self,work=work)
work.update_num_wishes()
work.update_num_wishes()
wishlist_added.send(sender=self, work=work, supporter=self.user)
def remove_work(self, work):
w = Wishes.objects.filter(wishlist=self, work=work)

View File

@ -97,6 +97,10 @@ def create_notice_types(app, created_models, verbosity, **kwargs):
notification.create_notice_type("rights_holder_claim_approved", _("Claim Accepted"), _("A claim you've entered has been accepted."))
notification.create_notice_type("wishlist_unsuccessful_amazon", _("Campaign shut down"), _("An ungluing campaign that you supported had to be shut down due to an Amazon Payments policy change."))
notification.create_notice_type("pledge_donation_credit", _("Donation Credit Balance"), _("You have a donation credit balance"))
<<<<<<< HEAD
=======
notification.create_notice_type("new_wisher", _("New wisher"), _("Someone new has wished for a book that you're the rightsholder for"))
>>>>>>> master
signals.post_syncdb.connect(create_notice_types, sender=notification)
@ -214,60 +218,18 @@ def handle_wishlist_unsuccessful_amazon(campaign, **kwargs):
amazon_suspension.connect(handle_wishlist_unsuccessful_amazon)
# The notification templates need some context; I'm making a note of that here
# This can be removed as the relevant functions are written
# RIGHTS_HOLDER_CLAIM_APPROVED:
# 'site': (site)
# 'claim': (claim)
# RIGHTS_HOLDER_CREATED: (no context needed)
# note -- it might be that wishlist_near_target and wishlist_near_deadline would
# both be triggered at about the same time -- do we want to prevent supporters
# from getting both within a small time frame? if so which supersedes?
# WISHLIST_NEAR_DEADLINE:
# 'site': (site)
# 'campaign': (the campaign)
# 'pledged': (true if the supporter has pledged, false otherwise)
# 'amount': (amount the supporter has pledged; only needed if pledged is true)
# WISHLIST_NEAR_TARGET:
# 'site': (site)
# 'campaign': (the campaign)
# 'pledged': (true if the supporter has pledged, false otherwise)
# 'amount': (amount the supporter has pledged; only needed if pledged is true)
# WISHLIST_PREMIUM_LIMITED_SUPPLY:
# (note we should not send this to people who have already claimed this premium)
# should we only send this to people who haven't pledged at all, or whose pledge
# is smaller than the amount of this premium? (don't want to encourage people to
# lower their pledge)
# the text assumes there is only 1 left -- if we're going to send at some other
# threshhold this will need to be revised
# 'campaign': (campaign)
# 'premium': (the premium in question)
# 'site': (site)
# WISHLIST_PRICE_DROP:
# 'campaign'
# 'pledged': (true if recipient has pledged to campaign, otherwise false)
# 'amount': (amount recipient has pledged, only needed if pledged=True)
# 'site'
# WISHLIST_SUCCESSFUL:
# 'pledged'
# 'campaign'
# 'site'
# WISHLIST_UNSUCCESSFUL:
# 'campaign'
# 'site'
# WISHLIST_UPDATED:
# I'd like to provide the actual text of the update in the message but I don't think
# we can reasonably do that, since campaign.description may contain HTML and we are
# sending notifications in plaintext. If we can send the update information in the
# email, though, let's do that.
# 'campaign'
# 'site'
# WISHLIST_WORK_CLAIMED
# does this trigger when someone claims a work, or when the claim is approved?
# I've written the text assuming it is the latter (sending notifications on the
# former seems too sausage-making, and might make people angry if they get
# notifications about claims they believe are false). If it's the former, the
# text should be revisited.
# 'claim'
# 'site'
# 'rightsholder' (the name of the rightsholder)
wishlist_added = Signal(providing_args=["supporter", "work"])
def handle_wishlist_added(supporter, work, **kwargs):
"""send notification to confirmed rights holder when someone wishes for their work"""
claim = work.claim.filter(status="active")
if claim:
notification.queue([claim.user], "new_wisher", {
'supporter': supporter,
'work': work
}, True)
from regluit.core.tasks import emit_notifications
emit_notifications.delay()
wishlist_added.connect(handle_wishlist_added)

View File

@ -45,12 +45,13 @@ class EditionForm(forms.ModelForm):
'title': forms.TextInput(attrs={'size': 40}),
'add_author': forms.TextInput(attrs={'size': 30}),
'add_subject': forms.TextInput(attrs={'size': 30}),
'unglued': forms.CheckboxInput(),
}
class EbookForm(forms.ModelForm):
class Meta:
model = Ebook
exclude =( 'created', 'unglued',)
exclude =( 'created',)
widgets = {
'edition': forms.HiddenInput,
'user': forms.HiddenInput,

View File

@ -12,100 +12,109 @@
{% block content %}
<div class="download_container">
<div id="lightbox_content">
<h2>Downloads for {{ work.title }}</h2>
{% if unglued_ebook %}
<div class="unglued">
<h3>Read the unglued edition!</h3>
<div class="ebook_download">
{% with unglued_ebook.url as url %}
<a href="{{ url }}"><img src="{{ unglued_ebook.rights_badge }}"></a>
<a href="{{ url }}">{{ unglued_ebook.format }}</a>
{% endwith %}
</div>
<div class="border">
<h2>Downloads for {{ work.title }}</h2>
{% if unglued_ebooks %}
<div class="unglued">
<h3>Read the unglued edition!</h3>
<div class="ebook_download">
{% for ebook in unglued_ebooks %}
{% with ebook.url as url %}
<a href="{{ url }}"><img src="{{ ebook.rights_badge }}"></a>
<a href="{{ url }}">{{ ebook.format }}</a>
{% if not forloop.last %}<br /><br />{% endif %}
{% endwith %}
{% endfor %}
</div>
</div>
{% endif %}
{% if other_ebooks %}
<div class="not_unglued">
{% if unglued_ebook %}
<h4>Other freely available editions</h4>
{% else %}
<h4>Freely available editions</h4>
{% endif %}
{% for edition in other_ebooks %}
<div class="ebook_download">
{% with edition.url as url %}
<a href="{{ url }}"><img src="{{ edition.rights_badge }}"></a>
<a href="{{ url }}">{{ edition.format }}</a>
{% if not forloop.last %}<br /><br />{% endif %}
{% endwith %}
</div>
{% endfor %}
</div>
{% endif %}
</div>
{% endif %}
{% if other_ebooks %}
{% if unglued_ebook %}<h4>Freely available editions</h4>{% endif %}
{% comment %}
the header is only necessary if we have an unglued edition we're distinguishing
non-unglued editions from
{% endcomment %}
{% for edition in other_ebooks %}
<div class="ebook_download clearfix">
{% with edition.url as url %}
<a href="{{ url }}"><img src="{{ edition.rights_badge }}"></a>
<a href="{{ url }}">{{ edition.format }}</a>
{% endwith %}
</div>
{% endfor %}
{% endif %}
{% if unglued_ebook or other_ebooks %}
<h3>How to download</h3>
<p>Ebooks you find at Unglue.it may be read on any device, and you're welcome to convert them to whatever electronic format is most useful to you. While we can't cover every possible combination of readers, software, and formats you might use, here's some help for the most common cases.</p>
<h4>Any device</h4>
<p>You may already have an app which reads our ebook formats. If so, when you download the file, you will be given an option to open the file using that app. You're done!</p>
<p>If this doesn't work, use the instructions below for your device.</p>
<h4>Android devices</h4>
<p class="ebook_download logo"><img src="/static/images/aldiko_logo.png">Aldiko</p>
<ul>
<li><a href="http://www.aldiko.com/download.html">Download the free Aldiko app.</a></li>
<li>Download your book from this page using your device's web browser.</li>
<li>You can read HTML files right in the browser. For other formats, you will be given the option of opening the file in Aldiko.</li>
</ul>
{% comment %}
this doesn't seem to work. i get only browser and IndieBound reader as options on my phone. perhaps I should recommend IBReader instead?
{% endcomment %}
<h4>iOS devices</h4>
<p class="ebook_download logo"><img src="/static/images/ibooks_logo.jpeg">iBooks</p>
{% comment %}test{% endcomment %}
<ul>
<li><a href="http://itunes.apple.com/us/app/ibooks/id364709193?mt=8">Download the free iBooks app</a> from the App Store.</li>
<li>Download your book from this page using your device's web browser.</li>
<li>You can read HTML files right in the browser. For other formats, you will be given the option of opening the file in iBooks.</li>
</ul>
<h4>PC, Mac, or Linux</h4>
<p class="ebook_download logo"><img src="/static/images/calibre_logo.png">Calibre</p>
<ul>
<li><a href="http://calibre-ebook.com/download">Download the free Calibre app.</a></li>
<li>Download your book from this page using your device's web browser.</li>
<li>Open the ebook file in Calibre.</li>
</ul>
<h4>Ereaders</h4>
<p>If you'd like to read epub files on a Kindle or Kindle Fire, you'll need to follow the "Converting epubs for Kindle" instructions below, and then the instructions here. To read mobi files on a Kindle, or any ebooks on other ereaders, use these instructions.</p>
<ul>
<li>Download the ebook to a laptop or desktop computer.</li>
<li>Plug the ereader into your computer with a USB cable.</li>
<li>Using the Finder (Mac) or Windows Explorer (Windows), drag and drop the ebook file into the Documents folder on your device. (It may also be called My Documents or My Stuff, depending on your ereader.) If you have downloaded Calibre, you can also use its "Send to Device" button.</li>
<li>Eject your device from the Finder or Explorer and disconnect the USB.</li>
<li>You may need to reboot your device to see the new book.</li>
</ul>
<h4>Converting epubs for Kindle</h4>
<p>Kindles can read plain text, MOBI, PDF, and HTML files. They cannot read epub books (the format unglued ebooks are released in). However, you can convert epubs to mobi files using free software.</p>
<ul>
<li><a href="http://calibre-ebook.com/download">Download the free Calibre app</a> to a desktop or laptop computer.</li>
<li>Download your book from this page onto the desktop or laptop.</li>
<li>Open the ebook file in Calibre.</li>
<li>Convert the epub to a mobi file: select the file; click on "convert books"; and set the output format to mobi.</li>
<li>When the conversion is done, put the file on your device using the instructions for ereaders above. If you've set up your Kindle email address at Amazon.com, you can also email it to yourself using the "Connect/share" button, without needing to plug your Kindle in. Calibre will walk you through the process of setting up your Kindle email in Calibre.</li>
</ul>
<h4>Need more help?</h4>
<p>Need help with something not listed here? Email us at <a href="mailto:support@gluejar.com?Subject=Ebook%20downloading%20help">support@gluejar.com</a>.</p>
<div class="border">
<h3>How to download</h3>
<p>Ebooks you find at Unglue.it may be read on any device, and you're welcome to convert them to whatever electronic format is most useful to you. While we can't cover every possible combination of readers, software, and formats you might use, here's some help for the most common cases.</p>
<h4>Any device</h4>
<p>You may already have an app which reads our ebook formats. If so, when you download the file, you will be given an option to open the file using that app. You're done!</p>
<p>If this doesn't work, use the instructions below for your device.</p>
<h4>Android devices</h4>
<p class="ebook_download logo"><img src="/static/images/aldiko_logo.png">Aldiko</p>
<ul>
<li><a href="http://www.aldiko.com/download.html">Download the free Aldiko app.</a></li>
<li>Download your book from this page using your device's web browser.</li>
<li>You can read HTML files right in the browser. For other formats, you will be given the option of opening the file in Aldiko.</li>
</ul>
{% comment %}
this doesn't seem to work. i get only browser and IndieBound reader as options on my phone. perhaps I should recommend IBReader instead?
{% endcomment %}
<h4>iOS devices</h4>
<p class="ebook_download logo"><img src="/static/images/ibooks_logo.jpeg">iBooks</p>
{% comment %}test{% endcomment %}
<ul>
<li><a href="http://itunes.apple.com/us/app/ibooks/id364709193?mt=8">Download the free iBooks app</a> from the App Store.</li>
<li>Download your book from this page using your device's web browser.</li>
<li>You can read HTML files right in the browser. For other formats, you will be given the option of opening the file in iBooks.</li>
</ul>
<h4>PC, Mac, or Linux</h4>
<p class="ebook_download logo"><img src="/static/images/calibre_logo.png">Calibre</p>
<ul>
<li><a href="http://calibre-ebook.com/download">Download the free Calibre app.</a></li>
<li>Download your book from this page using your device's web browser.</li>
<li>Open the ebook file in Calibre.</li>
</ul>
<h4>Ereaders</h4>
<p>If you'd like to read epub files on a Kindle or Kindle Fire, you'll need to follow the "Converting epubs for Kindle" instructions below, and then the instructions here. To read mobi files on a Kindle, or any ebooks on other ereaders, use these instructions.</p>
<ul>
<li>Download the ebook to a laptop or desktop computer.</li>
<li>Plug the ereader into your computer with a USB cable.</li>
<li>Using the Finder (Mac) or Windows Explorer (Windows), drag and drop the ebook file into the Documents folder on your device. (It may also be called My Documents or My Stuff, depending on your ereader.) If you have downloaded Calibre, you can also use its "Send to Device" button.</li>
<li>Eject your device from the Finder or Explorer and disconnect the USB.</li>
<li>You may need to reboot your device to see the new book.</li>
</ul>
<h4>Converting epubs for Kindle</h4>
<p>Kindles can read plain text, MOBI, PDF, and HTML files. They cannot read epub books (the format unglued ebooks are released in). However, you can convert epubs to mobi files using free software.</p>
<ul>
<li><a href="http://calibre-ebook.com/download">Download the free Calibre app</a> to a desktop or laptop computer.</li>
<li>Download your book from this page onto the desktop or laptop.</li>
<li>Open the ebook file in Calibre.</li>
<li>Convert the epub to a mobi file: select the file; click on "convert books"; and set the output format to mobi.</li>
<li>When the conversion is done, put the file on your device using the instructions for ereaders above. If you've set up your Kindle email address at Amazon.com, you can also email it to yourself using the "Connect/share" button, without needing to plug your Kindle in. Calibre will walk you through the process of setting up your Kindle email in Calibre.</li>
</ul>
<h4>Need more help?</h4>
<p>Need help with something not listed here? Email us at <a href="mailto:support@gluejar.com?Subject=Ebook%20downloading%20help">support@gluejar.com</a>.</p>
</div>
{% else %}
<p id="content-block">There are no freely available downloads of <I>{{ work.title }}</I> right now. {% if not work in request.user.wishlist.works.all %}Would you like there to be? <a class="add-wishlist"><span class="work_id" id="w{{ work.id }}">Add this book to your wishlist.</span></a>{% else %}Ask your friends to add it to their wishlists!{% endif %}</p>
<p>If you know of a Creative-Commons-licensed or US public domain edition of this book, you can add it through the <a href="{% url work work.id %}?tab=4">Rights tab of the book page</a>.</p>
<p id="content-block">There are no freely available downloads of <I>{{ work.title }}</I> right now. {% if not work in request.user.wishlist.works.all %}Would you like there to be? <a class="add-wishlist"><span class="work_id" id="w{{ work.id }}">Add this book to your wishlist.</span></a>{% else %}Ask your friends to add it to their wishlists!{% endif %}</p>
<p>If you know of a Creative-Commons-licensed or US public domain edition of this book, you can add it through the <a href="{% url work work.id %}?tab=4">Rights tab of the book page</a>.</p>
{% endif %}
</div>
</div>

View File

@ -111,18 +111,30 @@ Please fix the following before launching your campaign:
{% csrf_token %}
{{ form.media }}
<h3>Select the edition</h3>
<p> Please choose the edition that most closely matches the edition to be unglued:</p>
<p> Please choose the edition that most closely matches the edition to be unglued. This is the edition whose cover image will display on your book's page. Your unglued edition should be identical to this edition if possible; you should note any differences under Rights Details below.</p>
{{ form.edition.errors }}{{ form.edition }}
{% if campaign.edition %}
<p>You can edit the campaign's <a href="{% url rh_edition work.id campaign.edition.id %}">preferred edition</a>.</p>
<p>If the details of the edition you've chosen aren't accurate, you can <a href="{% url rh_edition work.id campaign.edition.id %}">edit the edition</a>.</p>
{% else %}
<p>If none of the existing editions matches what you want to release, you can <a href="{% url rh_edition work.id '' %}">create a new edition</a>.</p>
<p>If the edition details are inaccurate (e.g. wrong cover image), go ahead and set up the campaign with that edition anyway. You'll be able to edit the edition details from this page later on.</p>
{% endif %}
<p>If you don't see an edition that matches what you want to release, you can <a href="{% url rh_edition work.id '' %}">create a new edition</a>.</p>
<h3>Make Your Pitch</h3>
<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.</p>
<p>This isn't a dry synopsis in a catalog. It's your chance to be creative, to share your passion for this work, and to inspire readers. A strong pitch:</p>
<ul class="terms">
<li>A synopsis of the work.</li>
<li>Introduces the work. What's this book like?</li>
<li>Shows why it matters. How will someone or something -- the world, readers, some cause that matters -- be better off if this book is freely available? What kind of impact has the book had already? What will ungluers get out of supporting this campaign?</li>
<li>Has visual appeal (photos and/or videos).</li>
<li>Defines important but potentially unfamiliar things. What's an ungluing campaign, and why are you running one? Is there anything unusual about the book, its genre, et cetera? For those who aren't already familiar with you (or the author), who are you? Are you offering any particularly great premiums you want to call people's attention to?</li>
<li>Gives examples of the author's work. This could be links to your site or places people can find more information about you or the book. You can also add quotes, embed a free sample chapter or story, display images, et cetera. These work samples might be from the campaign book itself, or from your (or the author's) other creative works.</li>
<li>Has personality. The writing should be thoroughly proofread but it should have a point of view. This is the place to be conversational, opinionated, funny, quirky -- whatever reflects your style. Be you.</li>
<li>Optionally, provides extra incentives (like new or improved premiums) that will kick in if the campaign is unusually successful. Will you do something special when you reach 10% or 50% or 75% of your goal? Or if you reach that milestone before a particular deadline (e.g. in the first week of your campaign)?</li>
{% comment %}
<li>Hyperlinks for the author(s), publisher making the offer, or for the work itself. <span class="rh_help" id="helpHyperlink">(How do I hyperlink?)</span>
<div class="rh_answer" id="helpHyperlink2">
<p>Format a hyperlink like this:</p>
@ -144,23 +156,41 @@ Please fix the following before launching your campaign:
<p>If you'd like to change the size of the video, feel free; just don't make it more than 445px wide. Leaving it the default size is fine, too.</p>
<p>If you'd like to embed a video from another source, please talk to us. You certainly can; we just want to make sure we've given you the right instructions.</p>
</div></li>
{% endcomment %}
</ul>
<p>Make it concise and emotionally appealing. The point here is not to tell ungluers everything about your book; it's to remind them why they love it.</p>
<p>Above all, be engaging. The point here is not to tell ungluers everything about your book; it's to remind them why they love it.</p>
<p>Looking for inspiration? Check out the all-time most-funded projects on crowdfunding sites <a href="http://www.kickstarter.com/discover/most-funded">Kickstarter</a> or <a href="http://www.indiegogo.com/projects?filter_quick=most_funded">IndieGogo</a>, or have a look at <a href="http://www.kickstarter.com/discover/categories/publishing">Kickstarter's Publishing category</a> or <a href="http://www.indiegogo.com/projects?filter_category=Writing">IndieGogo's Writing category</a>.</p>
{{ form.description.errors }}{{ form.description }}
<h3>Offer details</h3>
<p>This will be displayed on the Rights tab for your work. It's the fine print for your offer. For example, if your unglued edition will exclude certain illustrations due to rights issues, or otherwise differ from existing editions, this is the place to disclose that. If your offer doesn't have any fine print, you can leave this blank.</p>
<h3>Edition and Rights Details</h3>
<p>This will be displayed on the Rights tab for your work. It's the fine print for your campaign. Make sure to disclose any ways the unglued edition will differ from the existing edition; for example:
<ul>
<li>Any material that may have to be excluded due to permissions issues: illustrations, forewords, etc.</li>
<li>Any additional materials that will be included, if not already covered in your pitch -- but we encourage you to cover them there to show supporters the value of ungluing!</li>
<li>If the cover image will differ.</li>
</ul>
<p>In short, is there a fact about this campaign that you think would matter to your agent or another publishing wonk, but that no one else is likely to care about? Put it here. If your campaign doesn't have any fine print, you can leave this blank.</p>
{{ form.details.errors }}{{ form.details }}
{% ifnotequal campaign_status 'ACTIVE' %}
<h3>Target Price</h3>
<p> This is the target price for your campaign. Once you launch the campaign, you won't be able to increase it. The <i>mimimum</i> target is ${{form.minimum_target|intcomma}} .</p>
<p>This is the target price for your campaign. The <i>mimimum</i> target is ${{form.minimum_target|intcomma}}.</p>
<p>Your target should be high enough to compensate you for potential lost future revenue from sales of this edition and reflect well on your brand, but low enough to seem realistic to supporters; people are more likely to back campaigns that they think will succeed.</p>
<p>Once you launch the campaign, you'll be able to decrease your target, but not increase it.</p>
<p>Please email us if you want to talk about pricing strategy.</p>
{{ form.target.errors }}${{ form.target }}
<h3>License being offered</h3>
<p> This is the license you are offering to use once the campaign succeeds. For more info on the licenses you can use, see <a href="http://creativecommons.org/licenses">Creative Commons: About the Licenses</a>.</p>
<p> This is the license you are offering to use once the campaign succeeds. For more information on the licenses you can use, see <a href="http://creativecommons.org/licenses">Creative Commons: About the Licenses</a>. Once your campaign is active, you'll be able to switch to a less restrictive license, but not a more restrictive one.</p>
{{ form.license.errors }}{{ form.license }}
<h3>Ending date</h3>
<p> This is the ending date of your campaign. Once you launch the campaign, you won't be able to change it.
The ending date can't be more than six months away- that's a practical limit for credit card authorizations. The <i>latest</i> ending you can choose <i>right now</i> is {{ form.latest_ending }}</p>
<p> This is the ending date of your campaign. Once you launch the campaign, you won't be able to change it.</p>
<p>The ending date can't be more than six months away- that's a practical limit for credit card authorizations. The <i>latest</i> ending you can choose <i>right now</i> is {{ form.latest_ending }}</p>
{{ form.deadline.errors }}{{ form.deadline }}
@ -171,7 +201,7 @@ Please fix the following before launching your campaign:
<h3>License being offered</h3>
<p>If your campaign succeeds, you will be offering your ebook under a <b><a href="{{campaign.license_url }}">{{ campaign.license }}</a></b> license.</p>
<p>During a campaign, you may only change the license to remove restrictions. For more info on the licenses you can use, see <a href="http://creativecommons.org/licenses">Creative Commons: About the Licenses</a>.</p></p>
<p>Since your campaign is active, you may only change the license to remove restrictions. For more information on the licenses you can use, see <a href="http://creativecommons.org/licenses">Creative Commons: About the Licenses</a>.</p></p>
{{ form.license.errors }}<span>{{ form.license }}</span>
<h3>Ending date</h3>
<p>The ending date of your campaign is <b>{{ campaign.deadline }}</b>. Your campaign will conclude on this date or when you meet your target price, whichever is earlier. You may not change the ending date of an active campaign.</p>
@ -179,7 +209,9 @@ Please fix the following before launching your campaign:
{% endifnotequal %}
<h3>Paypal collection address</h3>
<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>Enter the email address associated with your PayPal account.</p>
<p>We don't support PayPal yet; if your campaign succeeds we'll be paying you by check. However, we've applied PayPal for a merchant account, and should that application be approved PayPal expects us to have this information.</p>
<p>{{ form.paypal_receiver.errors }}{{ form.paypal_receiver }}</p>
{% ifequal campaign_status 'ACTIVE' %}

View File

@ -10,48 +10,76 @@
{% block doccontent %}
{% if edition.pk %}
<h2>Edit Edition {{edition.pk}}</h2>
<h2>Edit Edition</h2>
{% else %}
<h2>Create New Edition</h2>
{% endif %}
<p>Title and ISBN 13 are required; the rest is optional, though a cover image link is strongly recommended.</p>
<form method="POST" action="#">
{% csrf_token %}
{{ form.work }}
<div>
Title: {{ form.title.errors }}{{ form.title }}<br />
Authors:<ul>
{% if edition.pk and edition.authors %}
{% for author in edition.authors.all %}
<li>{{ author.name }}</li>
{% endfor %}
{% endif %}
{% for author in edition.new_author_names %}
<li>{{ author }}<input type="hidden" name="new_author" value="{{ author }}" /></li>
{% endfor %}
</ul>
Add an Author: {{ form.add_author.errors }}{{ form.add_author }}
<input type="submit" name="add_author_submit" value="Add Author" id="submit_author"><br />
Language: {{ form.language.errors }}{{ form.language }}<br />
ISBN: {{ form.isbn_13.errors }}{{ form.isbn_13 }}<br />
Description: <br />{{ form.description.errors }}{{ form.description }}<br />
Publisher: {{ form.publisher.errors }}{{ form.publisher }}<br />
Publish Date: {{ form.publication_date.errors }}{{ form.publication_date }}<br />
Public Domain?: {{ form.public_domain.errors }}{{ form.public_domain }}<br />
Subjects:<ul>
{% if edition.work.subjects %}
{% for subject in edition.work.subjects.all %}
<li>{{ subject.name }}</li>
{% endfor %}
{% endif %}
{% for new_subject in edition.new_subjects %}
<li>{{ new_subject }}<input type="hidden" name="new_subject" value="{{ new_subject }}" /></li>
{% endfor %}
</ul>
Add a Subject: {{ form.add_subject.errors }}{{ form.add_subject }}
<input type="submit" name="add_subject_submit" value="Add Subject" id="submit_subject"><br />
Cover Image (Small): {{ form.cover_image.errors }}{{ form.cover_image }}{{ form.cover_image.help_text }}<br />
</div>
<input type="submit" name="create_new_edition" value="{% if edition.pk %}Save Edits{% else %}Create Edition{% endif %}" id="submit">
{% csrf_token %}
{{ form.work }}
<div>
<p><b>Title</b>: {{ form.title.errors }}{{ form.title }}</p>
<p>
<b>Authors</b>:
{% if edition.authors or edition.new_author_names %}
<ul>
{% if edition.pk and edition.authors %}
{% for author in edition.authors.all %}
<li>{{ author.name }}</li>
{% endfor %}
{% endif %}
{% for author in edition.new_author_names %}
<li>{{ author }}<input type="hidden" name="new_author" value="{{ author }}" /></li>
{% endfor %}
</ul>
{% else %}
(None listed)
{% endif %}
</p>
<p><b>Add an Author</b> (<I>Firstname Lastname</I>): {{ form.add_author.errors }}{{ form.add_author }}
<input type="submit" name="add_author_submit" value="Add Author" id="submit_author"></p>
<p><b>Language</b>: {{ form.language.errors }}{{ form.language }}</p>
<p><b>ISBN-13</b>: {{ form.isbn_13.errors }}{{ form.isbn_13 }}</p>
<p><b>Description</b>: <br />
{{ form.description.errors }}{{ form.description }}<br />
(<I>This will appear in the Description tab on the book page. If you create a campaign for this work, the campaign pitch will override this description</i>)</p>
<p><b>Publisher</b>: {{ form.publisher.errors }}{{ form.publisher }}</p>
<p><b>Publish Date</b> (<I>four-digit year</I>): {{ form.publication_date.errors }}{{ form.publication_date }}</p>
<p><b>Public Domain?</b>: {{ form.public_domain.errors }}{{ form.public_domain }}</p>
{% comment %}
this has been removed since there's no point in exposing subject functionality when we're not doing anything with it -- will just confuse people.
<p><b>Subjects</b>:
<ul>
{% if edition.work.subjects %}
{% for subject in edition.work.subjects.all %}
<li>{{ subject.name }}</li>
{% endfor %}
{% endif %}
{% for new_subject in edition.new_subjects %}
<li>{{ new_subject }}<input type="hidden" name="new_subject" value="{{ new_subject }}" /></li>
{% endfor %}
</ul>
<b>Add a Subject</b>: {{ form.add_subject.errors }}{{ form.add_subject }}
<input type="submit" name="add_subject_submit" value="Add Subject" id="submit_subject"></p>
{% endcomment %}
<p><b>Cover Image</b>: {{ form.cover_image.errors }}{{ form.cover_image }}{{ form.cover_image.help_text }}<br />
(<i>Enter a link to an image, ideally 120px wide. You can't upload an image through this form at this time. If you have a cover image file and you're not sure how to put it online, email us and we can upload it for you.</I>)</p>
{% if request.user.is_staff %}
<p><b>Is this the unglued edition?</b> {{ form.unglued }}</p>
{% endif %}
</div>
<input type="submit" name="create_new_edition" value="{% if edition.pk %}Save Edits{% else %}Create Edition{% endif %}" id="submit">
</form>

View File

@ -0,0 +1,4 @@
{{ supporter }} has wished for a work you hold rights to, {{ work.title }}. Hooray! There are now {{ work.num_wishes }} people wishing for this work.
The Unglue.it team

View File

@ -0,0 +1,9 @@
{% extends "notification/notice_template.html" %}
{% block comments_book %}
<a href="{% url work work.id %}?tab=2"><img src="{{ work.cover_image_small }}" alt="cover image for {{ work.title }}" /></a>
{% endblock %}
{% block comments_graphical %}
<a href="{% url supporter supporter %}">{{ supporter }}</a> has wished for a work you hold rights to, <a href="{% url work work.id %}?tab=2">{{ work.title }}</a>. Hooray!
{% endblock %}

View File

@ -0,0 +1,3 @@
{{ supporter }} has wished for a work you hold rights to, {{ work.title }}. Hooray! There are now {{ work.num_wishes }} people wishing for this work.

View File

@ -0,0 +1 @@
Someone new has wished for your work at Unglue.it

View File

@ -317,45 +317,53 @@ $j(document).ready(function(){
{% endif %}
{% if alert %}<div class="alert"><b>Ebook Contribution:</b><br />{{ alert }}</div>{% endif %}
{% for edition in editions %}
<div class="editions">{% if edition.googlebooks_id %}<div class="image"><img src="{{ edition.cover_image_small }}" title="edition cover" alt="edition cover" /></div>{% endif %}
<div class="metadata" id="edition_{{edition.id}}">{% if edition.publisher %}Publisher: {{edition.publisher}}<br />{% endif %}
{% if edition.publication_date %}Published: {{edition.publication_date}}<br />{% endif %}
{% if edition.isbn_13 %}
ISBN: {{ edition.isbn_13 }}<br />
{% endif %}
{% if edition.oclc %}
OCLC: <a href="http://www.worldcat.org/oclc/{{ edition.oclc }}">{{ edition.oclc }}</a><br />
{% endif %}
{% if user.is_staff %}
<a href="{% url new_edition work_id edition.id %}">Edit this edition</a><br />
{% for edition in editions %}
<div class="clearfix">
<div class="editions">
{% if edition.googlebooks_id %}
<div class="image">
<img src="{{ edition.cover_image_small }}" title="edition cover" alt="edition cover" />
</div>
{% endif %}
{% if edition.googlebooks_id %}
See <a href="https://encrypted.google.com/books?id={{ edition.googlebooks_id }}">this edition on Google Books</a>
{% endif %}
</div>
</div>
{% if edition.ebook_form %}{% ifnotequal status 'ACTIVE' %}
{% if edition.hide_details %}<div class="show_more_edition" >more...</div>{% endif %}
<div {% if edition.hide_details %} class="more_edition" {% endif %}>
{% if edition.ebooks.count %}
<h5>eBooks for this Edition</h5>
{% for ebook in edition.ebooks.all %}
<a href="{{ebook.url}}">{{ ebook.format }}</a> {{ebook.rights}} at {{ebook.provider}}<br />
{% endfor %}
{% endif %}
<h5>Add an eBook for this Edition:</h5>
<span>If you know that this edition is available as a public domain or Creative Commons ebook, you can enter the link here and "unglue" it. Right now, we're only accepting URLs that point to Internet Archive, Wikisources, Hathitrust, Project Gutenberg, or Google Books.</span>
<form method="POST" action="#edition_{{edition.id}}">
{% csrf_token %}{{ edition.ebook_form.edition.errors }}{{ edition.ebook_form.edition }}{{ edition.ebook_form.user.errors }}{{ edition.ebook_form.user }}{{ edition.ebook_form.provider.errors }}{{ edition.ebook_form.provider }}
{{ edition.ebook_form.url.errors }}<span>URL: {{ edition.ebook_form.url }}</span><br />
{{ edition.ebook_form.format.errors }}<span>File Format: {{ edition.ebook_form.format }}</span>&nbsp;&nbsp;&nbsp;
{{ edition.ebook_form.rights.errors }}<span>License: {{ edition.ebook_form.rights }}</span><br />
<input type="submit" name="add_ebook" value="add ebook" />
</form>
<div class="metadata" id="edition_{{edition.id}}">{% if edition.publisher %}Publisher: {{edition.publisher}}<br />{% endif %}
{% if edition.publication_date %}Published: {{edition.publication_date}}<br />{% endif %}
{% if edition.isbn_13 %}
ISBN: {{ edition.isbn_13 }}<br />
{% endif %}
{% if edition.oclc %}
OCLC: <a href="http://www.worldcat.org/oclc/{{ edition.oclc }}">{{ edition.oclc }}</a><br />
{% endif %}
{% if user.is_staff %}
<a href="{% url new_edition work_id edition.id %}">Edit this edition</a><br />
{% endif %}
{% if edition.googlebooks_id %}
See <a href="https://encrypted.google.com/books?id={{ edition.googlebooks_id }}">this edition on Google Books</a>
{% endif %}
</div>
</div>
{% endifnotequal %}{% endif %}
{% if edition.ebook_form %}{% ifnotequal status 'ACTIVE' %}
{% if edition.hide_details %}
<div class="show_more_edition" >more...</div>
{% endif %}
<div {% if edition.hide_details %} class="more_edition" {% endif %}>
{% if edition.ebooks.count %}
<h5>eBooks for this Edition</h5>
{% for ebook in edition.ebooks.all %}
<a href="{{ebook.url}}">{{ ebook.format }}</a> {{ebook.rights}} at {{ebook.provider}}<br />
{% endfor %}
{% endif %}
<h5>Add an eBook for this Edition:</h5>
<span>If you know that this edition is available as a public domain or Creative Commons ebook, you can enter the link here and "unglue" it. Right now, we're only accepting URLs that point to Internet Archive, Wikisources, Hathitrust, Project Gutenberg, or Google Books.</span>
<form method="POST" action="#edition_{{edition.id}}">
{% csrf_token %}{{ edition.ebook_form.edition.errors }}{{ edition.ebook_form.edition }}{{ edition.ebook_form.user.errors }}{{ edition.ebook_form.user }}{{ edition.ebook_form.provider.errors }}{{ edition.ebook_form.provider }}
{{ edition.ebook_form.url.errors }}<span>URL: {{ edition.ebook_form.url }}</span><br />
{{ edition.ebook_form.format.errors }}<span>File Format: {{ edition.ebook_form.format }}</span>&nbsp;&nbsp;&nbsp;
{{ edition.ebook_form.rights.errors }}<span>License: {{ edition.ebook_form.rights }}</span><br />
<input type="submit" name="add_ebook" value="add ebook" />
</form>
</div>
{% endifnotequal %}{% endif %}
</div>
{% endfor %}
</div>
</div>

View File

@ -1944,22 +1944,11 @@ def download(request, work_id):
work = safe_get_work(work_id)
context.update({'work': work})
unglued_ebook = work.ebooks().filter(unglued=True)
other_ebooks = work.ebooks().filter(unglued=False)
try:
ungluedcount = unglued_ebook.count()
assert (ungluedcount == 1 or ungluedcount == 0)
except:
logger.warning("There is more than one unglued edition for %s" % work.title)
try:
unglued_ebook = unglued_ebook[0]
except:
pass
unglued_ebooks = work.ebooks().filter(edition__unglued=True)
other_ebooks = work.ebooks().filter(edition__unglued=False)
context.update({
'unglued_ebook': unglued_ebook,
'unglued_ebooks': unglued_ebooks,
'other_ebooks': other_ebooks
})

View File

@ -18,9 +18,6 @@
-moz-border-radius: 7px;
-webkit-border-radius: 7px;
border-radius: 7px;
-moz-border-radius: 7px;
-webkit-border-radius: 7px;
border-radius: 7px;
padding: 1px;
color: #fff;
margin: 0 8px 0 0;
@ -32,9 +29,6 @@
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
text-align: center;
display: inline-block;
}
@ -52,8 +46,6 @@
padding: 14px 0;
}
.google_signup_div div {
height: 24px;
line-height: 24px;
height: 24px;
line-height: 24px;
float: left;
@ -68,15 +60,10 @@
width: auto;
height: 36px;
line-height: 36px;
height: 36px;
line-height: 36px;
background: #8dc63f;
-moz-border-radius: 32px;
-webkit-border-radius: 32px;
border-radius: 32px;
-moz-border-radius: 32px;
-webkit-border-radius: 32px;
border-radius: 32px;
color: white;
cursor: pointer;
font-size: 13px;
@ -86,9 +73,6 @@
margin: 5px 0;
}
.errors {
-moz-border-radius: 16px 16px 0 0;
-webkit-border-radius: 16px 16px 0 0;
border-radius: 16px 16px 0 0;
-moz-border-radius: 16px 16px 0 0;
-webkit-border-radius: 16px 16px 0 0;
border-radius: 16px 16px 0 0;
@ -162,9 +146,6 @@ ul.tabs li a {
-moz-border-radius: 7px 7px 0 0;
-webkit-border-radius: 7px 7px 0 0;
border-radius: 7px 7px 0 0;
-moz-border-radius: 7px 7px 0 0;
-webkit-border-radius: 7px 7px 0 0;
border-radius: 7px 7px 0 0;
background: #d6dde0;
color: #3d4e53;
}
@ -194,8 +175,6 @@ ul.tabs li.active a {
#book-detail-img img {
padding: 5px;
border: solid 5px #EDF3F4;
padding: 5px;
border: solid 5px #EDF3F4;
}
.book-detail-info {
float: left;
@ -269,9 +248,6 @@ ul.tabs li.active a {
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
}
.book-detail-info .pledged-info {
padding: 0;
@ -288,177 +264,6 @@ ul.tabs li.active a {
height: 25px;
margin-top: -12px;
}
/* variables and mixins used in multiple less files go here */
.header-text {
height: 36px;
line-height: 36px;
display: block;
text-decoration: none;
font-weight: bold;
font-size: 13px;
letter-spacing: -0.05em;
}
.panelborders {
border-width: 1px 0px;
border-style: solid none;
border-color: #FFFFFF;
}
.roundedspan {
border: 1px solid #d4d4d4;
-moz-border-radius: 7px;
-webkit-border-radius: 7px;
border-radius: 7px;
-moz-border-radius: 7px;
-webkit-border-radius: 7px;
border-radius: 7px;
padding: 1px;
color: #fff;
margin: 0 8px 0 0;
display: inline-block;
}
.roundedspan > span {
padding: 7px 7px;
min-width: 15px;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
text-align: center;
display: inline-block;
}
.roundedspan > span .hovertext {
display: none;
}
.roundedspan > span:hover .hovertext {
display: inline;
}
.mediaborder {
padding: 5px;
border: solid 5px #EDF3F4;
}
.google_signup_div {
padding: 14px 0;
}
.google_signup_div div {
height: 24px;
line-height: 24px;
height: 24px;
line-height: 24px;
float: left;
padding-left: 5px;
}
.google_signup_div img {
float: left;
height: 24px;
width: 24px;
}
.actionbuttons {
width: auto;
height: 36px;
line-height: 36px;
height: 36px;
line-height: 36px;
background: #8dc63f;
-moz-border-radius: 32px;
-webkit-border-radius: 32px;
border-radius: 32px;
-moz-border-radius: 32px;
-webkit-border-radius: 32px;
border-radius: 32px;
color: white;
cursor: pointer;
font-size: 13px;
font-weight: bold;
padding: 0 15px;
border: none;
margin: 5px 0;
}
.errors {
-moz-border-radius: 16px 16px 0 0;
-webkit-border-radius: 16px 16px 0 0;
border-radius: 16px 16px 0 0;
-moz-border-radius: 16px 16px 0 0;
-webkit-border-radius: 16px 16px 0 0;
border-radius: 16px 16px 0 0;
border: solid #e35351 3px;
clear: both;
width: 90%;
height: auto;
line-height: 16px;
padding: 7px 0;
font-weight: bold;
font-size: 13px;
text-align: center;
}
.errors li {
list-style: none;
border: none;
}
.download_container {
width: 50%;
margin: auto;
}
#lightbox_content a {
color: #6994a3;
}
#lightbox_content .signuptoday a {
color: white;
}
#lightbox_content h2,
#lightbox_content h3,
#lightbox_content h4 {
margin-top: 15px;
}
#lightbox_content .ebook_download {
margin-bottom: 15px;
}
#lightbox_content .ebook_download a {
margin: auto 5px auto 0;
font-size: 15px;
}
#lightbox_content .ebook_download img {
vertical-align: middle;
}
#lightbox_content .logo {
font-size: 15px;
}
#lightbox_content .logo img {
-moz-border-radius: 7px;
-webkit-border-radius: 7px;
border-radius: 7px;
-moz-border-radius: 7px;
-webkit-border-radius: 7px;
border-radius: 7px;
height: 50px;
width: 50px;
margin-right: 5px;
}
#lightbox_content .unglued {
border: solid 2px #8dc63f;
margin-left: -2px;
padding: 5px;
}
#lightbox_content .unglued h3 {
margin-top: 5px;
}
#lightbox_content a.add-wishlist .on-wishlist,
#lightbox_content a.success,
a.success:hover {
text-decoration: none;
color: #3d4e53;
}
#lightbox_content a.success,
a.success:hover {
cursor: default;
}
#lightbox_content ul {
padding-left: 50px;
}
#lightbox_content ul li {
margin-bottom: 4px;
}
/* Common elements of share links -- just swap in the background image */
/* Page layout */
#js-page-wrap {
@ -473,9 +278,6 @@ a.success:hover {
}
#js-leftcol .jsmodule.rounded .jsmod-content,
.pledge.jsmodule.rounded .jsmod-content {
-moz-border-radius: 20px;
-webkit-border-radius: 20px;
border-radius: 20px;
-moz-border-radius: 20px;
-webkit-border-radius: 20px;
border-radius: 20px;
@ -613,8 +415,6 @@ div#content-block-content a {
div#content-block-content #tabs-1 img {
padding: 5px;
border: solid 5px #EDF3F4;
padding: 5px;
border: solid 5px #EDF3F4;
}
div#content-block-content #tabs-3 {
margin-left: -5px;
@ -625,12 +425,14 @@ div#content-block-content #tabs-3 {
.tabs-content iframe {
padding: 5px;
border: solid 5px #EDF3F4;
padding: 5px;
border: solid 5px #EDF3F4;
}
.tabs-content form {
margin-left: -5px;
}
.tabs-content .clearfix {
margin-bottom: 10px;
border-bottom: 2px solid #d6dde0;
}
.work_supporter {
height: auto;
min-height: 50px;
@ -645,13 +447,8 @@ div#content-block-content #tabs-3 {
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
}
.work_supporter_name {
height: 50px;
line-height: 50px;
height: 50px;
line-height: 50px;
float: left;
@ -668,12 +465,10 @@ div#content-block-content #tabs-3 {
padding: 3px;
margin-left: -5px;
}
.editions {
clear: both;
}
.editions div {
float: left;
padding-bottom: 5px;
margin-bottom: 5px;
}
.editions .image {
width: 60px;
@ -722,9 +517,6 @@ div#content-block-content #tabs-3 {
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
border-radius: 10px;
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
border-radius: 10px;
padding: 10px;
height: auto;
font-style: normal;
@ -739,8 +531,6 @@ div#content-block-content #tabs-3 {
font-style: normal;
height: 22px;
line-height: 22px;
height: 22px;
line-height: 22px;
}
#js-rightcol .jsmodule,
#pledge-rightcol .jsmodule {
@ -758,9 +548,6 @@ div#content-block-content #tabs-3 {
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
border-radius: 10px;
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
border-radius: 10px;
padding: 10px;
}
/* Right column - sharing */
@ -775,9 +562,6 @@ ul.social li {
-moz-border-radius: 0px;
-webkit-border-radius: 0px;
border-radius: 0px;
-moz-border-radius: 0px;
-webkit-border-radius: 0px;
border-radius: 0px;
}
ul.social li.facebook {
background: url("/static/images/icons/facebook.png") 10px center no-repeat;
@ -837,9 +621,6 @@ ul.social li.embed:hover span {
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
border-radius: 10px;
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
border-radius: 10px;
padding: 10px;
}
/* Right column - support tiers */

View File

@ -105,9 +105,6 @@
#lightbox_content h4 {
margin-top: 15px;
}
#lightbox_content .ebook_download {
margin-bottom: 15px;
}
#lightbox_content .ebook_download a {
margin: auto 5px auto 0;
font-size: 15px;
@ -126,14 +123,26 @@
width: 50px;
margin-right: 5px;
}
#lightbox_content .unglued {
border: solid 2px #8dc63f;
#lightbox_content .unglued,
#lightbox_content .not_unglued {
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
margin-left: -2px;
padding: 5px;
padding-bottom: 15px;
margin-bottom: 5px;
}
#lightbox_content .unglued h3 {
#lightbox_content .unglued h3,
#lightbox_content .not_unglued h3 {
margin-top: 5px;
}
#lightbox_content .unglued {
border: solid 2px #8dc63f;
}
#lightbox_content .not_unglued {
border: solid 2px #d6dde0;
}
#lightbox_content a.add-wishlist .on-wishlist,
#lightbox_content a.success,
a.success:hover {
@ -150,3 +159,12 @@ a.success:hover {
#lightbox_content ul li {
margin-bottom: 4px;
}
.border {
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
border: solid 2px #d6dde0;
margin: 5px auto;
padding-right: 5px;
padding-left: 5px;
}

View File

@ -230,9 +230,6 @@
#lightbox_content h4 {
margin-top: 15px;
}
#lightbox_content .ebook_download {
margin-bottom: 15px;
}
#lightbox_content .ebook_download a {
margin: auto 5px auto 0;
font-size: 15px;
@ -254,14 +251,29 @@
width: 50px;
margin-right: 5px;
}
#lightbox_content .unglued {
border: solid 2px #8dc63f;
#lightbox_content .unglued,
#lightbox_content .not_unglued {
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
margin-left: -2px;
padding: 5px;
padding-bottom: 15px;
margin-bottom: 5px;
}
#lightbox_content .unglued h3 {
#lightbox_content .unglued h3,
#lightbox_content .not_unglued h3 {
margin-top: 5px;
}
#lightbox_content .unglued {
border: solid 2px #8dc63f;
}
#lightbox_content .not_unglued {
border: solid 2px #d6dde0;
}
#lightbox_content a.add-wishlist .on-wishlist,
#lightbox_content a.success,
a.success:hover {
@ -278,6 +290,18 @@ a.success:hover {
#lightbox_content ul li {
margin-bottom: 4px;
}
.border {
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
border: solid 2px #d6dde0;
margin: 5px auto;
padding-right: 5px;
padding-left: 5px;
}
/* remove before beta */
.preview {
border: solid 3px #e35351;

View File

@ -1,7 +1,6 @@
@import "variables.less";
@import "campaign_tabs.less";
@import "book_detail.less";
@import "download.less";
/* Common elements of share links -- just swap in the background image */
.shareclass(@sharewhere) {
@ -185,6 +184,11 @@ div#content-block-content {
form {
margin-left: -5px;
}
.clearfix {
margin-bottom: 10px;
border-bottom: 2px solid @blue-grey;
}
}
.work_supporter {
@ -222,12 +226,11 @@ div#content-block-content {
margin-left: -5px;
}
.editions {
clear: both;
.editions {
div {
float:left;
padding-bottom: 5px;
margin-bottom: 5px;
}
.image {

View File

@ -27,9 +27,6 @@
img {
vertical-align: middle;
}
margin-bottom: 15px;
}
#lightbox_content .logo {
@ -43,16 +40,26 @@
font-size: @font-size-larger;
}
#lightbox_content .unglued {
border: solid 2px @call-to-action;
#lightbox_content .unglued, #lightbox_content .not_unglued {
.one-border-radius(5px);
margin-left: -2px;
padding: 5px;
padding-bottom: 15px;
margin-bottom: 5px;
h3 {
margin-top: 5px;
}
}
#lightbox_content .unglued {
border: solid 2px @call-to-action;
}
#lightbox_content .not_unglued {
border: solid 2px @blue-grey;
}
#lightbox_content a.add-wishlist .on-wishlist, #lightbox_content a.success, a.success:hover {
text-decoration: none;
color: @text-blue;
@ -68,4 +75,12 @@
li {
margin-bottom: 4px;
}
}
.border {
.one-border-radius(5px);
border: solid 2px @blue-grey;
margin: 5px auto;
padding-right: 5px;
padding-left: 5px;
}