merge master into work_page_CTAs

pull/1/head
eric 2013-03-11 22:39:48 -04:00
commit 57ebbc087e
41 changed files with 868 additions and 378 deletions

View File

@ -88,6 +88,12 @@ Instructions for setting please are slightly different.
1. `sudo chown celery:celery /var/log/celerybeat`
1. `sudo /etc/init.d/celerybeat start`
## setup to enable ckeditor to work properly
1. `mkdir /var/www/static/media/`
1. `sudo chown ubuntu:www-data /var/www/static/media/`
Updating Production
--------------------

View File

@ -69,6 +69,7 @@ class WorkResource(ModelResource):
queryset = models.Work.objects.all()
resource_name = 'work'
filtering = {'editions': ALL_WITH_RELATIONS, 'id': ALL, 'identifiers': ALL_WITH_RELATIONS}
ordering = ['num_wishes']
class CampaignResource(ModelResource):
work = fields.ToOneField(WorkResource, 'work')

View File

@ -17,13 +17,21 @@
<a href="/api/v1/?format=json">Available Resources (JSON)</a>
<p>
Resources on this list can be accessed via {{ base_url }}/api/v1/{resource_on_list}/?format=json&amp;api_key={your_api_key}&amp;username={your_username} .
</p>
<p>
Works can be ordered by how often they've been wishlisted; append &amp;order_by=num_wishes (ascending) or &amp;order_by=-num_wishes (descending).
</p>
{% if user.is_authenticated %}
<h3>Campaign info</h3>
<p>JSON to get data on all campaigns</p>
<a href="/api/v1/campaign/?format=json&amp;api_key={{api_key}}&amp;username={{user.username}}">{{base_url}}/api/v1/campaign/?format=json&amp;api_key={api_key}&amp;username={username}</a>
<a href="/api/v1/campaign/?format=json&amp;api_key={{api_key}}&amp;username={{user.username}}">{{base_url}}/api/v1/campaign/?format=json&amp;api_key={your_api_key}&amp;username={your_username}</a>
<h3>Identifier Resolution</h3>
<p>JSON to get work/edition data for an isbn</p>
<a href="/api/v1/identifier/?format=json&amp;api_key={{api_key}}&amp;username={{user.username}}&amp;type=isbn&amp;value=9780441012039">{{base_url}}/api/v1/identifier/?format=json&amp;api_key={api_key}&amp;username={username}&amp;type=isbn&amp;value=9780441012039</a>
<a href="/api/v1/identifier/?format=json&amp;api_key={{api_key}}&amp;username={{user.username}}&amp;type=isbn&amp;value=9780441012039">{{base_url}}/api/v1/identifier/?format=json&amp;api_key={your_api_key}&amp;username={your_username}&amp;type=isbn&amp;value=9780441012039</a>
<p> In addition to isbn, you can use 'goog' if you have a google books id, and 'oclc' for oclc numbers.</p>
{% endif %}

View File

@ -22,7 +22,7 @@ class ApiTests(TestCase):
deadline=now(),
target=Decimal('1000.00'),
)
self.user = User.objects.create_user('test', 'test@example.com', 'testpass')
self.user = User.objects.create_user('test', 'test@example.org', 'testpass')
self.client = Client()
def test_user(self):

View File

@ -477,6 +477,9 @@ def merge_works(w1, w2, user=None):
w2source = wishlist.work_source(w2)
wishlist.remove_work(w2)
wishlist.add_work(w1, w2source)
for subject in w2.subjects.all():
if subject not in w1.subjects.all():
w1.subjects.add(subject)
models.WasWork(was=w2.pk, work=w1, user=user).save()
for ww in models.WasWork.objects.filter(work = w2):
@ -485,6 +488,17 @@ def merge_works(w1, w2, user=None):
w2.delete()
def despam_description(description):
""" a lot of descriptions from openlibrary have free-book promotion text; this removes some of it."""
if description.find("GeneralBooksClub.com")>-1 or description.find("AkashaPublishing.Com")>-1:
return ""
pieces=description.split("1stWorldLibrary.ORG -")
if len(pieces)>1:
return pieces[1]
pieces=description.split("a million books for free.")
if len(pieces)>1:
return pieces[1]
return description
def add_openlibrary(work, hard_refresh = False):
if (not hard_refresh) and work.openlibrary_lookup is not None:
@ -538,6 +552,7 @@ def add_openlibrary(work, hard_refresh = False):
if isinstance(description,dict):
if description.has_key('value'):
description=description['value']
description=despam_description(description)
if not work.description or work.description.startswith('{') or len(description) > len(work.description):
work.description = description
work.save()
@ -707,3 +722,4 @@ def add_missing_isbn_to_editions(max_num=None, confirm=False):
class LookupFailure(Exception):
pass

View File

@ -0,0 +1,17 @@
from django.core.management.base import BaseCommand
from regluit.core import models, bookloader
class Command(BaseCommand):
help = "check description db for free ebook spam"
def handle(self, **options):
spam_strings=["1stWorldLibrary.ORG", "GeneralBooksClub.com", "million-books.com", "AkashaPublishing.Com"]
for spam_string in spam_strings:
qs=models.Work.objects.filter(description__icontains=spam_string)
print "Number of Works with %s in description: %s" % (spam_string, qs.count())
for work in qs:
work.description = bookloader.despam_description(work.description)
print "updating work %s" % work
bookloader.add_openlibrary(work, hard_refresh = True)

View File

@ -0,0 +1,250 @@
# -*- coding: 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 index on 'Campaign', fields ['deadline']
db.create_index('core_campaign', ['deadline'])
# Adding index on 'Work', fields ['num_wishes']
db.create_index('core_work', ['num_wishes'])
# Adding index on 'Edition', fields ['publisher']
db.create_index('core_edition', ['publisher'])
# Adding index on 'Ebook', fields ['rights']
db.create_index('core_ebook', ['rights'])
def backwards(self, orm):
# Removing index on 'Ebook', fields ['rights']
db.delete_index('core_ebook', ['rights'])
# Removing index on 'Edition', fields ['publisher']
db.delete_index('core_edition', ['publisher'])
# Removing index on 'Work', fields ['num_wishes']
db.delete_index('core_work', ['num_wishes'])
# Removing index on 'Campaign', fields ['deadline']
db.delete_index('core_campaign', ['deadline'])
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.badge': {
'Meta': {'object_name': 'Badge'},
'description': ('django.db.models.fields.TextField', [], {'default': "''", 'null': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '72', 'blank': 'True'})
},
'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', [], {'db_index': 'True'}),
'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(2013, 3, 6, 0, 0)', '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', 'db_index': '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', [], {'db_index': 'True', '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'},
'badges': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'holders'", 'symmetrical': 'False', 'to': "orm['core.Badge']"}),
'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', 'db_index': 'True'}),
'openlibrary_lookup': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
'title': ('django.db.models.fields.CharField', [], {'max_length': '1000'})
}
}
complete_apps = ['core']

View File

@ -1,11 +1,13 @@
import re
import random
import logging
from regluit.utils.localdatetime import now, date_today
from regluit.utils import crypto
from datetime import timedelta
from decimal import Decimal
from notification import models as notification
from ckeditor.fields import RichTextField
from postmonkey import PostMonkey, MailChimpException
from django.db import models
from django.db.models import Q, get_model
@ -23,6 +25,9 @@ from regluit.payment.parameters import TRANSACTION_STATUS_ACTIVE, TRANSACTION_ST
from django.db.models import Q
pm = PostMonkey(settings.MAILCHIMP_API_KEY)
logger = logging.getLogger(__name__)
class UnglueitError(RuntimeError):
pass
@ -830,7 +835,7 @@ class Subject(models.Model):
class Edition(models.Model):
created = models.DateTimeField(auto_now_add=True)
title = models.CharField(max_length=1000)
publisher = models.CharField(max_length=255, null=True, blank=True)
publisher = models.CharField(max_length=255, null=True, blank=True, db_index=True)
publication_date = models.CharField(max_length=50, null=True, blank=True)
public_domain = models.NullBooleanField(null=True, blank=True)
work = models.ForeignKey("Work", related_name="editions", null=True)
@ -1101,7 +1106,36 @@ class UserProfile(models.Model):
return last.anonymous
else:
return None
@property
def on_ml(self):
try:
return settings.MAILCHIMP_NEWS_ID in pm.listsForEmail(email_address=self.user.email)
except MailChimpException, e:
if e.code!=215: # don't log case where user is not on a list
logger.error("error getting mailchimp status %s" % (e))
except Exception, e:
logger.error("error getting mailchimp status %s" % (e))
return False
def ml_subscribe(self, **kwargs):
if "@example.org" in self.user.email:
# use @example.org email addresses for testing!
return True
try:
if not self.on_ml:
return pm.listSubscribe(id=settings.MAILCHIMP_NEWS_ID, email_address=self.user.email, **kwargs)
except Exception, e:
logger.error("error subscribing to mailchimp list %s" % (e))
return False
def ml_unsubscribe(self):
try:
return pm.listUnsubscribe(id=settings.MAILCHIMP_NEWS_ID, email_address=self.user.email)
except Exception, e:
logger.error("error unsubscribing from mailchimp list %s" % (e))
return False
#class CampaignSurveyResponse(models.Model):
# # generic
# campaign = models.ForeignKey("Campaign", related_name="surveyresponse", null=False)

View File

@ -44,7 +44,8 @@ def create_user_objects(sender, created, instance, **kwargs):
UserProfile = get_model('core', 'UserProfile')
if created:
Wishlist.objects.create(user=instance)
UserProfile.objects.create(user=instance)
profile = UserProfile.objects.create(user=instance)
profile.ml_subscribe()
except DatabaseError:
# this can happen when creating superuser during syncdb since the
# core_wishlist table doesn't exist yet

View File

@ -15,7 +15,7 @@ from django.contrib.sites.models import Site
from django.http import Http404
from regluit.payment.models import Transaction
from regluit.core.models import Campaign, Work, UnglueitError, Edition, RightsHolder, Claim, Key, Ebook, Premium
from regluit.core.models import Campaign, Work, UnglueitError, Edition, RightsHolder, Claim, Key, Ebook, Premium, Subject
from regluit.core import bookloader, models, search, goodreads, librarything
from regluit.core import isbn
from regluit.payment.parameters import PAYMENT_TYPE_AUTHORIZATION
@ -112,11 +112,17 @@ class BookLoaderTests(TestCase):
def test_merge_works_mechanics(self):
"""Make sure then merge_works is still okay when we try to merge works with themselves and with deleted works"""
sub1= Subject(name='test1')
sub1.save()
sub2= Subject(name='test2')
sub2.save()
w1 = Work(title="Work 1")
w1.save()
w1.subjects.add(sub1)
w2 = Work(title="Work 2")
w2.save()
w2.subjects.add(sub1,sub2)
e1 = Edition(work=w1)
e1.save()
@ -145,7 +151,8 @@ class BookLoaderTests(TestCase):
bookloader.merge_works(e1.work, e2.work)
self.assertEqual(models.Work.objects.count(),1)
self.assertEqual(models.WasWork.objects.count(),1)
self.assertEqual(w1.subjects.count(),2)
# getting proper view?
anon_client = Client()
r = anon_client.get("/work/%s/" % w1_id)
@ -172,10 +179,10 @@ class BookLoaderTests(TestCase):
self.assertEqual(models.Work.objects.count(), 2)
# add the stub works to a wishlist
user = User.objects.create_user('test', 'test@example.com', 'testpass')
user = User.objects.create_user('test', 'test@example.org', 'testpass')
user.wishlist.add_work(e1.work, 'test')
user.wishlist.add_work(e2.work, 'test')
manager = User.objects.create_user('manager', 'manager@example.com', 'managerpass')
manager = User.objects.create_user('manager', 'manager@example.org', 'managerpass')
# create campaigns for the stub works
c1 = models.Campaign.objects.create(
name=e1.work.title,
@ -279,7 +286,9 @@ class BookLoaderTests(TestCase):
def test_add_no_ebook(self):
# this edition lacks an ebook, but we should still be able to load it
e = bookloader.add_by_isbn('0465019358')
# http://books.google.com/books?id=D-WjL_HRbNQC&printsec=frontcover#v=onepage&q&f=false
# Social Life of Information
e = bookloader.add_by_isbn('1578517087')
self.assertTrue(e)
@unittest.expectedFailure
@ -381,7 +390,7 @@ class CampaignTests(TestCase):
def test_campaign_status(self):
# need a user to associate with a transaction
user = User.objects.create_user('test', 'test@example.com', 'testpass')
user = User.objects.create_user('test', 'test@example.org', 'testpass')
w = Work()
w.save()
@ -395,7 +404,7 @@ class CampaignTests(TestCase):
c2 = Campaign(target=D('1000.00'),deadline=datetime(2013,1,1),work=w)
c2.save()
self.assertEqual(c2.status, 'INITIALIZED')
u = User.objects.create_user('claimer', 'claimer@example.com', 'claimer')
u = User.objects.create_user('claimer', 'claimer@example.org', 'claimer')
u.save()
rh = RightsHolder(owner = u, rights_holder_name = 'rights holder name')
rh.save()
@ -477,7 +486,7 @@ class WishlistTest(TestCase):
def test_add_remove(self):
# add a work to a user's wishlist
user = User.objects.create_user('test', 'test@example.com', 'testpass')
user = User.objects.create_user('test', 'test@example.org', 'testpass')
edition = bookloader.add_by_isbn('0441007465')
work = edition.work
num_wishes=work.num_wishes
@ -634,7 +643,7 @@ class DownloadPageTest(TestCase):
e2.save()
eb1 = models.Ebook()
eb1.url = "http://example.com"
eb1.url = "http://example.org"
eb1.edition = e1
eb1.format = 'epub'
@ -648,7 +657,7 @@ class DownloadPageTest(TestCase):
anon_client = Client()
response = anon_client.get("/work/%s/download/" % w.id)
self.assertContains(response, "http://example.com", count=4)
self.assertContains(response, "http://example.org", count=4)
self.assertContains(response, "http://example2.com", count=3)
@ -691,5 +700,14 @@ class LocaldatetimeTest(TestCase):
else:
reload(localdatetime)
class MailingListTests(TestCase):
#mostly to check that MailChimp account is setp correctly
def test_mailchimp(self):
from postmonkey import PostMonkey
pm = PostMonkey(settings.MAILCHIMP_API_KEY)
self.assertEqual(pm.ping(),"Everything's Chimpy!" )
self.user = User.objects.create_user('chimp_test', 'eric@gluejar.com', 'chimp_test')
self.assertTrue(self.user.profile.on_ml)

View File

@ -13,7 +13,7 @@ def other_users(user, how_many):
user_list = candidates[0: count]
else :
slice = random.random() * (count - how_many)
user_list = candidates[slice: slice+how_many]
user_list = candidates.filter(is_staff=False)[slice: slice+how_many]
return user_list
def supporting_users(work, how_many):
@ -23,18 +23,18 @@ def supporting_users(work, how_many):
user_list = work.wished_by()[0: count]
else :
slice = random.random() * (count - how_many)
user_list = work.wished_by()[slice: slice+how_many]
user_list = work.wished_by().filter(is_staff=False)[slice: slice+how_many]
return user_list
def work_list_users(work_list, how_many):
"""return up to how_many users with one of the works on work_list in their wishlist"""
#users = User.objects.filter(wishlist__works__in=work_list).distinct().reverse()
# for MySQL, avoiding a nested query is more efficient: https://docs.djangoproject.com/en/dev/ref/models/querysets/#in
users = User.objects.filter(wishlist__works__in=list(work_list[:100])).distinct().reverse()
users = User.objects.filter(wishlist__works__in=list(work_list[:100]), is_staff=False).distinct().reverse()
return users.all()[0:how_many]
def campaign_list_users(campaign_list, how_many):
users = User.objects.filter(wishlist__works__campaigns__in=list(campaign_list[:100])).distinct().reverse()
users = User.objects.filter(wishlist__works__campaigns__in=list(campaign_list[:100]), is_staff=False).distinct().reverse()
count = users.count()
if count <= how_many :
user_list = users[0: count]

View File

@ -9,7 +9,7 @@
cd /opt/regluit
sudo -u ubuntu /usr/bin/git pull
source ENV/bin/activate
#pip install -r requirements_versioned.pip
pip install -r requirements_versioned.pip
django-admin.py syncdb --migrate --settings regluit.settings.just
django-admin.py collectstatic --noinput --settings regluit.settings.just
sudo /etc/init.d/apache2 restart

View File

@ -1,5 +1,5 @@
{% extends "basedocumentation.html" %}
{% block title %} Everything You Always Wanted to Know {% endblock %}
{% block doccontent %}
<h2>About</h2>
<p><a href="http://unglue.it">Unglue.it</a> is a service provided by <a href="http://gluejar.com">Gluejar, Inc.</a> It's a place for individuals and institutions to join together to liberate specific ebooks and other types of digital content by paying rights holders to relicense their works under <a href="http://creativecommons.org">Creative Commons</a> licenses.</p>

View File

@ -1,5 +1,5 @@
{% extends "basedocumentation.html" %}
{% block title %} for Smashwords Authors{% endblock %}
{% block doccontent %}
<h1>Smashwords + Unglue.it</h1>

View File

@ -11,6 +11,7 @@
{% url landing as landingurl %}
{% url new_edition '' '' as editionurl %}
{% url libraries as librariesurl %}
{% url about_specific 'main' as aboutmainurl %}
{% load truncatechars %}
<html>
@ -153,7 +154,7 @@
<div class="column">
<span>About Unglue.it</span>
<ul>
<li><a href="{% url about_specific 'main' %}" class="hijax">Concept</a></li>
<li><a href="{{ aboutmainurl }}" class="hijax">Concept</a></li>
<li><a href="{{ abouturl }}">Team</a></li>
<li><a href="http://blog.unglue.it">Blog</a></li>
<li><a href="{{ pressurl }}">Press</a></li>

View File

@ -0,0 +1,8 @@
{% extends "work_list.html" %}
{% load endless %}
{% load lang_utils %}
{% block title %} Works published by {{ pubname }} {% endblock %}
{% block userblock2 %}
<span class="special-user-name">Books from {{ pubname }} {% if pub_lang %}( {{pub_lang|ez_lang_name}} ) {% endif %}</span>
{% endblock %}

View File

@ -1,9 +1,4 @@
{% extends "base.html" %}
{% comment %}
realtime updating?
comments rss?
{% endcomment %}
{% block title %} Comments {% endblock %}
{% block extra_css %}
<link type="text/css" rel="stylesheet" href="/static/css/supporter_layout.css" />

View File

@ -20,6 +20,15 @@
<li><a href="{% url work_list 'new' %}"><span>Newly Wished</span></a></li>
<li><a href="{% url work_list 'recommended' %}"><span>Noteworthy</span></a></li>
<li class="last"><a href="{% url unglued_list '' %}"><span>Ready to Read</span></a></li>
{% if pubname %}
<li>{{ pubname }}...
<ul class="menu level3">
<li class="first"><a href="{% url bypub_list 'popular' pubname %}"><span>Most popular</span></a></li>
<li><a href="{% url bypub_list pubname %}"><span>By Title</span></a></li>
<li><a href="{% url bypub_list 'pubdate' pubname %}"><span>By Date Published</span></a></li>
</ul>
</li>
{% endif %}
</ul>
</li>
{% if show_langs %}
@ -33,6 +42,7 @@
</ul>
</li>
{% endif %}
{% if ungluers %}
<li class="parent">
<span>Ungluers</span>
<ul class="menu level2">
@ -48,6 +58,7 @@
{% endfor %}
</ul>
</li>
{% endif %}
</ul>
</div>
</div>

View File

@ -1,6 +1,6 @@
{% extends "base.html" %}
{% load truncatechars %}
{% block title %}&#151; Support Free eBooks{% endblock %}
{% block extra_js %}
<script type="text/javascript" src="{{ jquery_ui_home }}"></script>
{% endblock %}
@ -30,7 +30,7 @@
<script src="/static/js/slides.min.jquery.js"></script>
<script src="/static/js/slideshow.js"></script>
<script type="text/javascript" src="/static/js/expand.js"></script>
<meta name="google-site-verification" content="wFZncBw5tNpwRVyR08NZFNr7WXqv5X1BkEga2fpUNOo" />
{% endblock %}
{% block topsection %}

View File

@ -1,5 +1,5 @@
{% extends "basedocumentation.html" %}
{% block title %} &#x2665; Libraries{% endblock %}
{% block extra_css %}
<link type="text/css" rel="stylesheet" href="/static/css/campaign.css" />
<link type="text/css" rel="stylesheet" href="/static/css/libraries.css" />

View File

@ -108,6 +108,7 @@ $j(document).ready(function(){
<ul>
<li>Want to <a href="{% url auth_password_change %}">change your password</a>?</li>
<li>Want to <a href="/accounts/edit/">change your username or email address</a>?</li>
<li>Want to <a href="{% url notification_notice_settings %}">manage your contact preferences</a>?</li>
</ul>
{% endblock %}

View File

@ -174,6 +174,31 @@ Please fix the following before launching your campaign:
<li>Click Source again to get back to the normal editing mode.</li>
</ul>
<p>You'll see an IFRAME code in the editor where your video will go. The video will display normally on your campaign page.</p>
<p>
Prefer screencasts? Here you go: <a href="/static/images/How_to_embed_a_video.mp4">how to embed a video</a> in your campaign page.
</p>
<h4>How to add a PDF</h4>
This assumes that you have a (free) Google account.
<ul class="bullets">
<li>Upload your PDF to <a href="http://drive.google.com">Google Drive</a>.</li>
<li>Click on the Share button.</li>
<li>Change the visibility to public on the web and click Save, then Done.</li>
<li>In the File menu, click the Embed this PDF option.</li>
<li>Copy the HTML code that pops up.</li>
<li>In the editor toolbar below, click Source.</li>
<li>Paste the HTML code from Google Drive in the box below.</li>
<li>Find the part of the code that says something like <pre>width="640"</pre> and change that to <pre>width="445"</pre>.</li>
<li>Click Source again to get back to the normal editing mode.</li>
</ul>
<p>You'll see an IFRAME code in the editor where your PDF will go. The PDF will display normally on your campaign page.</p>
<p>
Prefer screencasts? Here: <a href="/static/images/How_to_embed_a_PDF.mp4">how to embed a PDF</a> in your campaign page (screencast)
</p>
{{ form.description.errors }}{{ form.description }}
<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:

View File

@ -0,0 +1,13 @@
{% if request.user.profile.on_ml %}
You are subscribed to the Unglue.it Newsletter. It comes roughly twice a month. <br />
<form id="ml_unsubscribe" action="{% url ml_unsubscribe %}" method="POST">
{% csrf_token %}
<input type="submit" name="ml_unsubscribe" value="Unsubscribe" />
</form>
{% else %}
You are NOT subscribed to the Unglue.it Newsletter. It comes roughly twice a month. If you have just become an ungluer, your list invitation should be on its way. Put "gluenews@gluejar.com" in your contact list to make sure you get it.<br />
<form id="ml_subscribe" action="{% url ml_subscribe %}" method="POST">
{% csrf_token %}
<input type="submit" name="ml_subscribe" value="Subscribe" />
</form>
{% endif %}

View File

@ -8,6 +8,18 @@
<link type="text/css" rel="stylesheet" href="/static/css/notices.css" />
{% endblock %}
{% block extra_js %}
<script type="text/javascript" src="/static/js/definitions.js"></script>
<script>
$j(document).ready(function() {
jQuery.post("/ml/status/", function(data){
$j("#mailing_list").html(data);
});
});
</script>
{% endblock %}
{% block doccontent %}
<h2>{% trans "Notification Settings" %}</h2>
@ -126,8 +138,9 @@
</tr>
</table>
</form>
<h3>Your mailing list subscription</h3>
<div id="mailing_list"></div>
<h3>Your email</h3>
{% if user.email %}
<p>

View File

@ -1,5 +1,5 @@
{% extends "basedocumentation.html" %}
{% block title %} Press Information{% endblock %}
{% block doccontent %}
<h1>Press</h1>
<div class="presstoc">

View File

@ -0,0 +1,22 @@
{% extends "work_list.html" %}
{% load endless %}
{% load lang_utils %}
{% block title %} Works published by {{ pubname }} {% endblock %}
{% block noworks %}
Check back soon to see what we're recommending.
{% endblock %}
{% block userblock %}
<div id="user-block1">
<div id="block-intro-text"><span class="special-user-name">Staff Picks</span></div>
</div>
<div class="user-block2"><span class="user-short-info">Here are the {% if pub_lang %}{{pub_lang|ez_lang_name}} language {% endif %}books <a href="{% url supporter 'AmandaM' %}">Amanda</a>, <a href="{% url supporter 'andromeda' %}">Andromeda</a>, <a href="{% url supporter 'eric' %}">Eric</a>, and <a href="{% url supporter 'rdhyee' %}">Raymond</a> are loving lately.</span>
</div>
<div class="user-block3 recommended">
<a href="{% url supporter 'AmandaM' %}"><img class="user-avatar" src="https://si0.twimg.com/profile_images/1801686082/image_normal.jpg" height="50" width="50" alt="Picture of Amanda" title="Amanda" /></a>
<a href="{% url supporter 'andromeda' %}"><img class="user-avatar" src="https://si0.twimg.com/profile_images/611713549/andromeda_by_molly_color_normal.jpg" height="50" width="50" alt="Picture of Andromeda" title="Andromeda" /></a>
<a href="{% url supporter 'eric' %}"><img class="user-avatar" src="https://graph.facebook.com/1009077800/picture" height="50" width="50" alt="Picture of Eric" title="Eric" /></a>
<a href="{% url supporter 'RaymondYee' %}"><img class="user-avatar" src="https://graph.facebook.com/1229336/picture" height="50" width="50" alt="Picture of Raymond" title="Raymond" /></a>
</div>
{% endblock %}

View File

@ -3,7 +3,7 @@
{% block doccontent %}
{% if not user.is_authenticated %}
An activation email has been sent. Please check your email and click on the link to activate your account.
An account activation email has been sent. Please check your email and click on the link to activate your account. We're also sending you an invitation to our email newsletter. It comes out about twice a month. Put "gluenews@gluejar.com" in your contact list to make sure you get it.
{% else %}
<div>
You are logged in as <a href="{% url supporter supporter_username=request.user.username %}">{{ request.user.username }}</a>.

View File

@ -12,7 +12,7 @@
</div>
<br />
<div class="welcomealternatives">
Or you can <a href="{{editurl}}">change your username</a> &#151; <a href="{% url work_list 'popular' %}">see the most wishlisted books</a> &#151; <a href="/feedback/">send us feedback</a>
Or you can <a href="{{editurl}}">change your username</a> &#151; <a href="{% url work_list 'popular' %}">see the most wishlisted books</a> &#151; <a href="/feedback/">send us feedback</a> &#151; <a href="{% url notification_notice_settings %}">manage your contact preferences</a>
</div>
{% endblock %}

View File

@ -1,7 +1,13 @@
{% extends "base.html" %}
{% load comments %}
{% load humanize %}
{% block title %}&#151; {% if work.last_campaign_status == 'ACTIVE' %}Campaign to unglue {% endif %}{{ work.title }}{% endblock %}
{% block title %}&#151;
{% if work.first_ebook %}
{{ work.title }} is a Free eBook
{% else %}
Help us make {{ work.title }} a Free eBook!
{% endif %}
{% endblock %}
{% block extra_css %}
<link type="text/css" rel="stylesheet" href="/static/css/campaign.css" />
@ -71,59 +77,42 @@ $j(document).ready(function(){
</div>
<div id="js-maincol">
<div class="js-maincol-inner">
<div id="content-block">
<div class="book-detail">
{% if work.googlebooks_id %}
<div id="book-detail-img">
<a href="{{ work.googlebooks_url }}">
<img src="{{ work.cover_image_thumbnail }}" alt="Find {{ work.title }} at Google Books" title="Find {{ work.title }} at Google Books" width="131" height="192" /></a>
</div>
{% else %}
<div id="book-detail-img">
<img src="{% if work.cover_image_thumbnail %}{{ work.cover_image_thumbnail }}{% else %}/static/images/generic_cover_larger.png{% endif %}" alt="{{ work.title }}" title="{{ work.title }}" width="131" height="192" />
</div>
{% endif %}
<div class="book-detail-info">
<div class="layout">
<h2 class="book-name">{{ work.title }}</h2>
<div>
<div class="pubinfo">
<h3 class="book-author">{{ work.author }}</h3>
<h3 class="book-year">{{ work.publication_date_year }}</h3>
</div>
</div>
</div>
{% ifequal status 'ACTIVE' %}
<div class="thermometer" title="{{ work.percent_of_goal }}% of goal">
<div class="cover" style="width: {{ cover_width }}%;">
</div>
<span>{{ work.percent_of_goal }}% of goal</span>
</div>
<div class="pledged-info noborder">
<div class="campaign-status-info">
<span>${{ work.last_campaign.current_total|floatformat:0|intcomma }}</span> pledged
</div>
<div class="campaign-status-info">
<span>${{ work.last_campaign.target|floatformat:0|intcomma }}</span> goal
</div>
<div class="campaign-status-info">
{% if work.last_campaign.supporters_count == 1 %}
<span>1</span> ungluer
{% else %}
<span> {{ work.last_campaign.supporters_count }}</span> ungluers
{% endif %}
</div>
<div class="campaign-status-info">
<span>{{ countdown }}</span> to go
</div>
<div id="content-block">
<div class="book-detail">
{% if work.googlebooks_id %}
<div id="book-detail-img">
<a href="{{ work.googlebooks_url }}">
<img src="{{ work.cover_image_thumbnail }}" alt="Find {{ work.title }} at Google Books" title="Find {{ work.title }} at Google Books" width="131" height="192" /></a>
</div>
{% else %}
{% ifequal status 'SUCCESSFUL' %}
<div class="thermometer successful">
This campaign succeeded on {{ work.last_campaign.success_date|date:"M j, Y" }}.
<div id="book-detail-img">
<img src="{% if work.cover_image_thumbnail %}{{ work.cover_image_thumbnail }}{% else %}/static/images/generic_cover_larger.png{% endif %}" alt="{{ work.title }}" title="{{ work.title }}" width="131" height="192" />
</div>
{% endif %}
<div class="book-detail-info">
<div class="layout">
<h2 class="book-name">{{ work.title }}</h2>
<div>
<div class="pubinfo">
<h3 class="book-author">{{ work.author }}</h3>
<h3 class="book-year">{{ work.publication_date_year }}</h3>
</div>
</div>
</div>
{% ifequal status 'ACTIVE' %}
<div class="thermometer" title="{{ work.percent_of_goal }}% of goal">
<div class="cover" style="width: {{ cover_width }}%;">
</div>
<span>{{ work.percent_of_goal }}% of goal</span>
</div>
<div class="pledged-info noborder">
<div class="campaign-status-info">
<span>${{ work.last_campaign.current_total|floatformat:0|intcomma }}</span> pledged
</div>
<div class="campaign-status-info">
<span>${{ work.last_campaign.target|floatformat:0|intcomma }}</span> goal
</div>
<div class="campaign-status-info">
{% if work.last_campaign.supporters_count == 1 %}
<span>1</span> ungluer
@ -132,263 +121,281 @@ $j(document).ready(function(){
{% endif %}
</div>
<div class="campaign-status-info">
<span>${{ work.last_campaign.current_total|floatformat:0|intcomma }}</span> pledged
<span>{{ countdown }}</span> to go
</div>
<div class="campaign-status-info">
<span>${{ work.last_campaign.target|floatformat:0|intcomma }}</span> goal
</div>
{% else %}
{% ifequal status 'SUCCESSFUL' %}
<div class="thermometer successful">
This campaign succeeded on {{ work.last_campaign.success_date|date:"M j, Y" }}.
</div>
<div class="campaign-status-info">
<span>Unglued!</span>
<div class="pledged-info noborder">
<div class="campaign-status-info">
{% if work.last_campaign.supporters_count == 1 %}
<span>1</span> ungluer
{% else %}
<span> {{ work.last_campaign.supporters_count }}</span> ungluers
{% endif %}
</div>
<div class="campaign-status-info">
<span>${{ work.last_campaign.current_total|floatformat:0|intcomma }}</span> pledged
</div>
<div class="campaign-status-info">
<span>${{ work.last_campaign.target|floatformat:0|intcomma }}</span> goal
</div>
<div class="campaign-status-info">
<span>Unglued!</span>
</div>
</div>
{% endifequal %}
<div class="pledged-info">
{% if wishers == 1 %}
1 Ungluer has
{% else %}
{{ wishers }} Ungluers have
{% endif %} wished for this Work
</div>
{% endifequal %}
<div class="pledged-info">
{% if wishers == 1 %}
1 Ungluer has
{% else %}
{{ wishers }} Ungluers have
{% endif %} wished for this Work
</div>
{% endifequal %}
<div class="find-book">
<label>Learn more at...</label>
<div class="find-link">
{% if work.googlebooks_id %}
<a id="find-google" href="{{ work.googlebooks_url }}"><img src="/static/images/supporter_icons/googlebooks_square.png" title="Find on Google Books" alt="Find on Google Books" /></a>
{% endif %}
{% if work.first_oclc %}
<a rel="nofollow" id="find-oclc" href="http://www.worldcat.org/oclc/{{ work.first_oclc }}"><img src="/static/images/supporter_icons/worldcat_square.png" title="Find on Worldcat" alt="Find on Worldcat" /></a>
{% endif %}
<a rel="nofollow" class="find-openlibrary" href="{% url work_openlibrary work_id %}"><img src="/static/images/supporter_icons/openlibrary_square.png" title="Find on OpenLibrary" alt="Find on OpenLibrary" /></a>
{% if not request.user.is_anonymous %}
{% if request.user.profile.goodreads_user_link %}
<a rel="nofollow" class="find-goodreads" href="{% url work_goodreads work_id %}"><img src="/static/images/supporter_icons/goodreads_square.png" title="Find on GoodReads" alt="Find on GoodReads" /></a>
<div class="find-book">
<label>Learn more at...</label>
<div class="find-link">
{% if work.googlebooks_id %}
<a id="find-google" href="{{ work.googlebooks_url }}"><img src="/static/images/supporter_icons/googlebooks_square.png" title="Find on Google Books" alt="Find on Google Books" /></a>
{% endif %}
{% if request.user.profile.librarything_id %}
<a rel="nofollow" class="find-librarything" href="{% url work_librarything work_id %}"><img src="/static/images/supporter_icons/librarything_square.png" title="Find on LibraryThing" alt="Find on LibraryThing" /></a>
{% if work.first_oclc %}
<a rel="nofollow" id="find-oclc" href="http://www.worldcat.org/oclc/{{ work.first_oclc }}"><img src="/static/images/supporter_icons/worldcat_square.png" title="Find on Worldcat" alt="Find on Worldcat" /></a>
{% endif %}
<a rel="nofollow" class="find-openlibrary" href="{% url work_openlibrary work_id %}"><img src="/static/images/supporter_icons/openlibrary_square.png" title="Find on OpenLibrary" alt="Find on OpenLibrary" /></a>
{% if not request.user.is_anonymous %}
{% if request.user.profile.goodreads_user_link %}
<a rel="nofollow" class="find-goodreads" href="{% url work_goodreads work_id %}"><img src="/static/images/supporter_icons/goodreads_square.png" title="Find on GoodReads" alt="Find on GoodReads" /></a>
{% endif %}
{% if request.user.profile.librarything_id %}
<a rel="nofollow" class="find-librarything" href="{% url work_librarything work_id %}"><img src="/static/images/supporter_icons/librarything_square.png" title="Find on LibraryThing" alt="Find on LibraryThing" /></a>
{% endif %}
{% endif %}
{% endif %}
</div>
</div>
<div class="btn_wishlist" id="wishlist_actions">
{% if request.user.id in work.last_campaign.supporters %}
<div class="add-wishlist">
<span class="on-wishlist">On your wishlist!</span>
</div>
{% else %}
{% if work in request.user.wishlist.works.all %}
<div class="remove-wishlist-workpage">
<span id="w{{ work_id }}">Remove from Wishlist</span>
</div>
{% endif %}
{% endif %}
</div>
</div>
</div>
{% get_comment_count for work as comment_count %}
<div class="content-block-heading" id="tabs">
<ul class="tabs">
<li class="tabs1 {% if activetab == '1' %}active{% endif %}"><a href="#">{% if status == 'ACTIVE' %}Campaign{% else %}Description{% endif %}</a></li>
<li class="tabs2 {% if activetab == '2' %}active{% endif %}"><a href="#">Comments {% if comment_count > 0 %}({{ comment_count }}){% endif %}</a></li>
<li class="tabs3 {% if activetab == '3' %}active{% endif %}" id="supporters"><a href="#">Ungluers {% if wishers > 0 %}<br />({{ wishers }}){% endif %}</a></li>
<li class="tabs4 {% if activetab == '4' %}active{% endif %}"><a href="#">Rights</a></li>
</ul>
</div>
<div id="content-block-content">
<div id="tabs-1" class="tabs {% if activetab == '1' %}active{% endif %}">
<div class="tabs-content">
{% if status == 'ACTIVE' or status == 'SUCCESSFUL' %}
{{ work.last_campaign.description|safe }}
{% else %}
{% if status == 'SUSPENDED' %}
<div class="launch_top alert">
This campaign has been suspended. See the <a href="{% url faq_location 'campaigns' %}">FAQ</a> for details.
</div>
<div class="btn_wishlist" id="wishlist_actions">
{% if request.user.id in work.last_campaign.supporters %}
<div class="add-wishlist">
<span class="on-wishlist">On your wishlist!</span>
</div>
{% else %}
{% if status == 'WITHDRAWN' %}
<div class="launch_top alert">
This campaign has been withdrawn. See the <a href="{% url faq_location 'campaigns' %}">FAQ</a> for details.
{% if work in request.user.wishlist.works.all %}
<div class="remove-wishlist-workpage">
<span id="w{{ work_id }}">Remove from Wishlist</span>
</div>
{% endif %}
{% endif %}
<h3 class="tabcontent-title">{{work.title}}</h3>
<p>{{ work.description|safe }}</p>
{% endif %}
</div>
</div>
</div>
<div id="tabs-2" class="tabs {% if activetab == '2' %}active{% endif %}">
<h3>Why unglue this? Have your say.</h3>
<div class="tabs-content">
{% render_comment_list for work %}
{% if user.is_authenticated %}
{% render_comment_form for work %}
{% else %}
<p>You must be <a href="{% url auth_login %}?next={{ request.path }}">logged in</a> to comment.</p>
{% endif %}
</div>
{% get_comment_count for work as comment_count %}
<div class="content-block-heading" id="tabs">
<ul class="tabs">
<li class="tabs1 {% if activetab == '1' %}active{% endif %}"><a href="#">{% if status == 'ACTIVE' %}Campaign{% else %}Description{% endif %}</a></li>
<li class="tabs2 {% if activetab == '2' %}active{% endif %}"><a href="#">Comments {% if comment_count > 0 %}({{ comment_count }}){% endif %}</a></li>
<li class="tabs3 {% if activetab == '3' %}active{% endif %}" id="supporters"><a href="#">Ungluers {% if wishers > 0 %}<br />({{ wishers }}){% endif %}</a></li>
<li class="tabs4 {% if activetab == '4' %}active{% endif %}"><a href="#">Rights</a></li>
</ul>
</div>
<div id="tabs-3" class="tabs {% if activetab == '3' %}active{% endif %}">
<div class="tabs-content">
{% for wish in work.wishes.all reversed %}
{% with wish.wishlist.user as supporter %}
<div class="work_supporter_nocomment">
<a href="{% url supporter supporter_username=supporter.username %}">
<div class="work_supporter_avatar">
{% if supporter.profile.pic_url %}
<img class="user-avatar" src="{{ supporter.profile.pic_url }}" height="50" width="50" alt="Picture of {{ supporter }}" title="{{ supporter }}" />
{% else %}
<img class="user-avatar" src="/static/images/header/avatar.png" height="50" width="50" alt="Generic Ungluer Avatar" title="Ungluer" />
{% endif %}
<div id="content-block-content">
<div id="tabs-1" class="tabs {% if activetab == '1' %}active{% endif %}">
<div class="tabs-content">
{% if status == 'ACTIVE' or status == 'SUCCESSFUL' %}
{{ work.last_campaign.description|safe }}
{% else %}
{% if status == 'SUSPENDED' %}
<div class="launch_top alert">
This campaign has been suspended. See the <a href="{% url faq_location 'campaigns' %}">FAQ</a> for details.
</div>
{% else %}
{% if status == 'WITHDRAWN' %}
<div class="launch_top alert">
This campaign has been withdrawn. See the <a href="{% url faq_location 'campaigns' %}">FAQ</a> for details.
</div>
<div class="work_supporter_name">{{ supporter }}</div>
</a>
</div>
{% endwith %}
{% endfor %}
{% endif %}
{% endif %}
<h3 class="tabcontent-title">{{work.title}}</h3>
<p>{{ work.description|safe }}</p>
{% endif %}
</div>
</div>
</div>
<div id="tabs-4" class="tabs {% if activetab == '4' %}active{% endif %}">
<div class="tabs-content">
{% if status == 'ACTIVE' %}
<h3 class="tabcontent-title">A campaign is running to unglue <i>{{work.title}}</i>!</h3>
<p>The rights holder, {% for claim in work.claim.all %}
{% if claim.status == 'active' %}
{{ claim.rights_holder.rights_holder_name }}
{% endif %}
<div id="tabs-2" class="tabs {% if activetab == '2' %}active{% endif %}">
<h3>Why unglue this? Have your say.</h3>
<div class="tabs-content">
{% render_comment_list for work %}
{% if user.is_authenticated %}
{% render_comment_form for work %}
{% else %}
<p>You must be <a href="{% url auth_login %}?next={{ request.path }}">logged in</a> to comment.</p>
{% endif %}
</div>
</div>
<div id="tabs-3" class="tabs {% if activetab == '3' %}active{% endif %}">
<div class="tabs-content">
{% for wish in work.wishes.all reversed %}
{% with wish.wishlist.user as supporter %}
<div class="work_supporter_nocomment">
<a href="{% url supporter supporter_username=supporter.username %}">
<div class="work_supporter_avatar">
{% if supporter.profile.pic_url %}
<img class="user-avatar" src="{{ supporter.profile.pic_url }}" height="50" width="50" alt="Picture of {{ supporter }}" title="{{ supporter }}" />
{% else %}
<img class="user-avatar" src="/static/images/header/avatar.png" height="50" width="50" alt="Generic Ungluer Avatar" title="Ungluer" />
{% endif %}
</div>
<div class="work_supporter_name">{{ supporter }}</div>
</a>
</div>
{% endwith %}
{% endfor %}
, has agreed to release <i>{{work.title}}</i> to the world as a Creative Commons licensed ebook (<a href="{{ work.last_campaign.license_url }}">{{ work.last_campaign.license }}</a>) if ungluers can join together to raise ${{ work.last_campaign.target|floatformat:0|intcomma }} by {{ work.last_campaign.deadline }}.
You can help!</p>
<h4>Campaign details: the fine print</h4>
{{ work.last_campaign.details|safe }}
{% else %}
{% if status == 'SUCCESSFUL' %}
<h3 class="tabcontent-title">A campaign has succeeded to unglue <i>{{work.title}}</i>!</h3>
<p>The rights holder, {% for claim in work.claim.all %}
{% if claim.status == 'active' %}
{{ claim.rights_holder.rights_holder_name }}
{% endif %}
</div>
</div>
<div id="tabs-4" class="tabs {% if activetab == '4' %}active{% endif %}">
<div class="tabs-content">
{% if status == 'ACTIVE' %}
<h3 class="tabcontent-title">A campaign is running to unglue <i>{{work.title}}</i>!</h3>
<p>The rights holder,
{% for claim in work.claim.all %}
{% if claim.status == 'active' %}
{{ claim.rights_holder.rights_holder_name }}
{% endif %}
{% endfor %}
, has agreed to release <i>{{work.title}}</i> to the world as a Creative Commons licensed ebook (<a href="{{ work.last_campaign.license_url }}">{{ work.last_campaign.license }}</a>) thanks to the efforts of ungluers like you.</p>
, has agreed to release <i>{{work.title}}</i> to the world as a Creative Commons licensed ebook (<a href="{{ work.last_campaign.license_url }}">{{ work.last_campaign.license }}</a>) if ungluers can join together to raise ${{ work.last_campaign.target|floatformat:0|intcomma }} by {{ work.last_campaign.deadline }}.
You can help!</p>
<h4>Campaign details: the fine print</h4>
{{ work.last_campaign.details|safe }}
{% else %}
<h4> Rights Information </h4>
{% if claimstatus == 'one_active' %}
<p>This work has been claimed by {{ rights_holder_name }}.</p>
{% if status == 'SUCCESSFUL' %}
<h3 class="tabcontent-title">A campaign has succeeded to unglue <i>{{work.title}}</i>!</h3>
<p>The rights holder, {% for claim in work.claim.all %}
{% if claim.status == 'active' %}
{{ claim.rights_holder.rights_holder_name }}
{% endif %}
{% endfor %}
, has agreed to release <i>{{work.title}}</i> to the world as a Creative Commons licensed ebook (<a href="{{ work.last_campaign.license_url }}">{{ work.last_campaign.license }}</a>) thanks to the efforts of ungluers like you.</p>
<h4>Campaign details: the fine print</h4>
{{ work.last_campaign.details|safe }}
{% else %}
{% if claimstatus == 'disputed' %}
<p>Rights claims are pending.</p>
<h4> Rights Information </h4>
{% if claimstatus == 'one_active' %}
<p>This work has been claimed by {{ rights_holder_name }}.</p>
{% else %}
{% if claimstatus == 'one_pending' %}
<p>A claim for this work by {{ rights_holder_name }} is pending.</p>
{% if claimstatus == 'disputed' %}
<p>Rights claims are pending.</p>
{% else %}
{% if request.user.rights_holder.all.count %}
Is this work yours? Claim it: <br /><br />
{% if claimstatus == 'one_pending' %}
<p>A claim for this work by {{ rights_holder_name }} is pending.</p>
{% else %}
{% if request.user.rights_holder.all.count %}
Is this work yours? Claim it: <br /><br />
<form method="GET" action="{% url claim %}">
{% csrf_token %}
{{ claimform.user }}
{{ claimform.work }}
{{ claimform.rights_holder }}
<input type="submit" name="submit" value="Claim">
</form><br />
<form method="GET" action="{% url claim %}">
{% csrf_token %}
{{ claimform.user }}
{{ claimform.work }}
{{ claimform.rights_holder }}
<input type="submit" name="submit" value="Claim">
</form><br />
{% endif %}
{% endif %}
{% endif %}
{% endif %}
{% endif %}
{% endif %}
{% endif %}
<p>If you'd like to contact us regarding rights for this work, please email <a href="mailto:rights@gluejar.com">rights@gluejar.com</a>.</p>
<p>If you'd like to contact us regarding rights for this work, please email <a href="mailto:rights@gluejar.com">rights@gluejar.com</a>.</p>
{% if user.is_staff %}
<h4>Related Works</h4>
<a href="{% url merge work_id %}">Merge other works into this one</a><br />
{% endif %}
{% if user.is_staff %}
<h4>Related Works</h4>
<a href="{% url merge work_id %}">Merge other works into this one</a><br />
{% endif %}
{% if work.subjects.all.count > 0 %}
<h4>Subjects</h4>
<ul>
{% for subject in work.subjects.all %}
<li>{{ subject.name }}</li>
{% endfor %}
</ul>
{% endif %}
{% if work.subjects.all.count > 0 %}
<h4>Subjects</h4>
<ul>
{% for subject in work.subjects.all %}
<li>{{ subject.name }}</li>
{% endfor %}
</ul>
{% endif %}
<h4>Editions</h4>
{% if user.is_staff %}
<div><a href="{% url new_edition work_id edition.id %}">Create a new edition for this work</a><br /><br /></div>
{% endif %}
<h4>Editions</h4>
{% if user.is_staff %}
<div><a href="{% url new_edition work_id edition.id %}">Create a new edition for this work</a><br /><br /></div>
{% endif %}
{% if alert %}
<div class="alert"><b>Ebook Contribution:</b><br />{{ alert }}</div>
{% endif %}
{% 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 %}
<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>
{% 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 %}
{% if alert %}
<div class="alert"><b>Ebook Contribution:</b><br />{{ alert }}</div>
{% endif %}
{% 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 %}
<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>
{% endifnotequal %}
{% endif %}
</div>
{% endfor %}
</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>
{% endifnotequal %}
{% endif %}
</div>
{% endfor %}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div id="js-rightcol">

View File

@ -27,26 +27,18 @@
<div class="js-topnews2">
<div class="js-topnews3">
<div class="user-block">
<div id="user-block1">
{% if facet == 'recommended' %}
<div id="block-intro-text"><span class="special-user-name">Staff Picks</span></div>
</div>
<div class="user-block2"><span class="user-short-info">Here are the {% if pub_lang %}{{pub_lang|ez_lang_name}} language {% endif %}books <a href="{% url supporter 'AmandaM' %}">Amanda</a>, <a href="{% url supporter 'andromeda' %}">Andromeda</a>, <a href="{% url supporter 'eric' %}">Eric</a>, and <a href="{% url supporter 'rdhyee' %}">Raymond</a> are loving lately.</span>
</div>
<div class="user-block3 recommended">
<a href="{% url supporter 'AmandaM' %}"><img class="user-avatar" src="https://si0.twimg.com/profile_images/1801686082/image_normal.jpg" height="50" width="50" alt="Picture of Amanda" title="Amanda" /></a>
<a href="{% url supporter 'andromeda' %}"><img class="user-avatar" src="https://si0.twimg.com/profile_images/611713549/andromeda_by_molly_color_normal.jpg" height="50" width="50" alt="Picture of Andromeda" title="Andromeda" /></a>
<a href="{% url supporter 'eric' %}"><img class="user-avatar" src="https://graph.facebook.com/1009077800/picture" height="50" width="50" alt="Picture of Eric" title="Eric" /></a>
<a href="{% url supporter 'RaymondYee' %}"><img class="user-avatar" src="https://graph.facebook.com/1229336/picture" height="50" width="50" alt="Picture of Raymond" title="Raymond" /></a>
</div>
{% else %}
{% block userblock %}
<div id="user-block1">
<div id="block-intro-text"><span class="special-user-name">{{ facet|capfirst }}</span></div>
</div>
<div class="user-block2"><span class="user-short-info">With your help we're raising money to buy the rights to give these {% if pub_lang %}{{pub_lang|ez_lang_name}} language {% endif %}books to the world.</span>
<div class="user-block2">
{% block userblock2 %}
<span class="user-short-info">With your help we're raising money to buy the rights to give these {% if pub_lang %}{{pub_lang|ez_lang_name}} language {% endif %}books to the world.</span>
{% endblock %}
</div>
<div class="user-block3">
</div>
{% endif %}
{% endblock %}
</div>
</div>
</div>
@ -90,16 +82,11 @@
</div>
<div id="content-block-content">
{% ifequal work_list.count 0 %}
{% if facet == 'recommended' %}
Check back soon to see what we're recommending.
{% else %}
{% block noworks %}
There aren't any {{ pub_lang|ez_lang_name }} works in this list yet. Why not add your favorite books to your wishlist, so we can feature them here?
{% endif %}
{% endblock %}
{% else %}
{% comment %}
pagination commented out for now because it was causing huge db hits/pageload times. These sets have been limited in views.py to 20 on the theory that people only want to see the MOST popular works, and the other facets are unlikely to produce sets exceeding this anyway.
{% lazy_paginate 20 works_unglued using "works_unglued" %}
{% endcomment %}
{% for work in works_unglued %}
<div class="{% cycle 'row1' 'row2' %}">
{% with work.last_campaign_status as status %}
@ -109,18 +96,13 @@
{% endwith %}{% endwith %}{% endwith %}
</div>
{% endfor %}
{% comment %}
<div class="pagination content-block-heading tabs-1">
{% get_pages %}
{% for page in pages %}
<a href="{{ page.path }}#1" class="endless_page_link">{{ page.number }}</a>
{% endfor %}
</div>
{% endcomment %}
{% comment %}
{% lazy_paginate 20 works_active using "works_active" %}
{% endcomment %}
{% for work in works_active %}
<div class="{% cycle 'row1' 'row2' %}">
{% with work.last_campaign_status as status %}
@ -130,18 +112,14 @@
{% endwith %}{% endwith %}{% endwith %}
</div>
{% endfor %}
{% comment %}
<div class="pagination content-block-heading tabs-2">
{% get_pages %}
{% for page in pages %}
<a href="{{ page.path }}#2" class="endless_page_link">{{ page.number }}</a>
{% endfor %}
</div>
{% endcomment %}
{% comment %}
{% lazy_paginate 20 works_wished using "works_wished" %}
{% endcomment %}
{% for work in works_wished %}
<div class="{% cycle 'row1' 'row2' %}">
{% with work.last_campaign_status as status %}
@ -151,14 +129,12 @@
{% endwith %}{% endwith %}{% endwith %}
</div>
{% endfor %}
{% comment %}
<div class="pagination content-block-heading tabs-3">
{% get_pages %}
{% for page in pages %}
<a href="{{ page.path }}#3" class="endless_page_link">{{ page.number }}</a>
{% endfor %}
</div>
{% endcomment %}
{% endifequal %}
</div>
</div>

View File

@ -11,7 +11,7 @@ from regluit.core.feeds import SupporterWishlistFeed
from regluit.core.models import Campaign
from regluit.frontend.views import GoodreadsDisplayView, LibraryThingView, PledgeView, PledgeCompleteView, PledgeCancelView, PledgeRechargeView, FAQView
from regluit.frontend.views import CampaignListView, WorkListView, UngluedListView, InfoPageView, InfoLangView, DonationView, FundPledgeView
from regluit.frontend.views import NonprofitCampaign, DonationCredit, PledgeModifiedView, ManageAccount, MergeView
from regluit.frontend.views import NonprofitCampaign, DonationCredit, PledgeModifiedView, ManageAccount, MergeView, ByPubListView
urlpatterns = patterns(
"regluit.frontend.views",
@ -37,6 +37,8 @@ urlpatterns = patterns(
url(r"^wishlist/$", "wishlist", name="wishlist"),
url(r"^campaigns/(?P<facet>\w*)$", CampaignListView.as_view(), name='campaign_list'),
url(r"^lists/(?P<facet>\w*)$", WorkListView.as_view(), name='work_list'),
url(r"^bypub/all/(?P<pubname>.*)$", ByPubListView.as_view(), name='bypub_list'),
url(r"^bypub/(?P<facet>\w*)/(?P<pubname>.*)$", ByPubListView.as_view(), name='bypub_list'),
url(r"^unglued/(?P<facet>\w*)$", UngluedListView.as_view(), name='unglued_list'),
url(r"^goodreads/auth/$", "goodreads_auth", name="goodreads_auth"),
url(r"^goodreads/auth_cb/$", "goodreads_cb", name="goodreads_cb"),
@ -92,6 +94,9 @@ urlpatterns = patterns(
get_context_data=lambda: {'site': Site.objects.get_current()}
),
name="libraries"),
url(r"^ml/status/$","ml_status", name="ml_status"),
url(r"^ml/subscribe/$","ml_subscribe", name="ml_subscribe"),
url(r"^ml/unsubscribe/$","ml_unsubscribe", name="ml_unsubscribe"),
)
if settings.DEBUG:

View File

@ -493,15 +493,17 @@ recommended_user = User.objects.filter( username=settings.UNGLUEIT_RECOMMENDED_U
class WorkListView(FilterableListView):
template_name = "work_list.html"
context_object_name = "work_list"
max_works=100000
def get_queryset_all(self):
facet = self.kwargs['facet']
if (facet == 'popular'):
return models.Work.objects.order_by('-num_wishes', 'id')
return models.Work.objects.exclude(num_wishes=0).order_by('-num_wishes', 'id')
elif (facet == 'recommended'):
self.template_name = "recommended.html"
return models.Work.objects.filter(wishlists__user=recommended_user).order_by('-num_wishes')
elif (facet == 'new'):
return models.Work.objects.filter(num_wishes__gt=0).order_by('-created', '-num_wishes' ,'id')
return models.Work.objects.exclude(num_wishes=0).order_by('-created', '-num_wishes' ,'id')
else:
return models.Work.objects.all().order_by('-created', 'id')
@ -509,11 +511,11 @@ class WorkListView(FilterableListView):
context = super(WorkListView, self).get_context_data(**kwargs)
qs=self.get_queryset()
context['ungluers'] = userlists.work_list_users(qs,5)
context['facet'] = self.kwargs['facet']
works_unglued = qs.filter(editions__ebooks__isnull=False).distinct() | qs.filter(campaigns__status='SUCCESSFUL').distinct()
context['works_unglued'] = works_unglued.order_by('-campaigns__status', 'campaigns__deadline', '-num_wishes')[:20]
context['works_active'] = qs.filter(campaigns__status='ACTIVE').distinct()[:20]
context['works_wished'] = qs.exclude(editions__ebooks__isnull=False).exclude(campaigns__status='ACTIVE').exclude(campaigns__status='SUCCESSFUL').distinct()[:20]
context['facet'] = self.kwargs.get('facet','')
works_unglued = qs.exclude(editions__ebooks__isnull=True).distinct() | qs.filter(campaigns__status='SUCCESSFUL').distinct()
context['works_unglued'] = works_unglued.order_by('-campaigns__status', 'campaigns__deadline', '-num_wishes')[:self.max_works]
context['works_active'] = qs.filter(campaigns__status='ACTIVE').distinct()[:self.max_works]
context['works_wished'] = qs.exclude(editions__ebooks__isnull=False).exclude(campaigns__status='ACTIVE').exclude(campaigns__status='SUCCESSFUL').distinct()[:self.max_works]
context['activetab'] = "#3"
@ -525,6 +527,29 @@ class WorkListView(FilterableListView):
return context
class ByPubListView(WorkListView):
template_name = "bypub_list.html"
context_object_name = "work_list"
max_works=100000
def get_queryset_all(self):
facet = self.kwargs.get('facet','')
pubname = self.kwargs['pubname']
objects = models.Work.objects.filter(editions__publisher__iexact=pubname).distinct()
if (facet == 'popular'):
return objects.order_by('-num_wishes', 'id')
elif (facet == 'pubdate'):
return objects.order_by('-editions__publication_date') # turns out this messes up distinct, and MySQL doesn't support DISTINCT ON
elif (facet == 'new'):
return objects.filter(num_wishes__gt=0).order_by('-created', '-num_wishes' ,'id')
else:
return objects.order_by('title', 'id')
def get_context_data(self, **kwargs):
context = super(ByPubListView, self).get_context_data(**kwargs)
context['pubname'] = self.kwargs['pubname']
return context
class UngluedListView(FilterableListView):
template_name = "unglued_list.html"
context_object_name = "work_list"
@ -533,8 +558,6 @@ class UngluedListView(FilterableListView):
facet = self.kwargs['facet']
if (facet == 'popular'):
return models.Work.objects.filter(editions__ebooks__isnull=False).distinct().order_by('-num_wishes')
elif (facet == '' or facet == 'unglued'):
return models.Work.objects.filter(campaigns__status="SUCCESSFUL").distinct().order_by('-campaigns__deadline')
elif (facet == 'cc' or facet == 'creativecommons'):
# assumes all ebooks have a PD or CC license. compare rights_badge property
return models.Work.objects.filter(
@ -546,6 +569,9 @@ class UngluedListView(FilterableListView):
editions__ebooks__isnull=False,
editions__ebooks__rights__in=['PD-US', 'CC0', '']
).distinct().order_by('-num_wishes')
else :
#(facet == '' or facet == 'unglued' or facet is other)
return models.Work.objects.filter(campaigns__status="SUCCESSFUL").distinct().order_by('-campaigns__deadline')
def get_context_data(self, **kwargs):
context = super(UngluedListView, self).get_context_data(**kwargs)
@ -2174,3 +2200,19 @@ def about(request, facet):
template = "about_" + facet + ".html"
return render(request, template)
@login_required
@csrf_exempt
def ml_status(request):
return render(request, "ml_status.html")
@require_POST
@login_required
def ml_subscribe(request):
request.user.profile.ml_subscribe(double_optin=False,send_welcome=True, merge_vars = {"OPTIN_IP":request.META['REMOTE_ADDR'],"OPTIN_TIME":now().isoformat()})
return HttpResponseRedirect(reverse("notification_notice_settings"))
@require_POST
@login_required
def ml_unsubscribe(request):
request.user.profile.ml_unsubscribe()
return HttpResponseRedirect(reverse("notification_notice_settings"))

View File

@ -306,8 +306,8 @@ class CreditTest(TestCase):
def setUp(self):
"""
"""
self.user1 = User.objects.create_user('credit_test1', 'support@gluejar.com', 'credit_test1')
self.user2 = User.objects.create_user('credit_test2', 'support+1@gluejar.com', 'credit_test2')
self.user1 = User.objects.create_user('credit_test1', 'support@example.org', 'credit_test1')
self.user2 = User.objects.create_user('credit_test2', 'support+1@example.org', 'credit_test2')
def testSimple(self):
"""
@ -333,7 +333,7 @@ class TransactionTest(TestCase):
create a single transaction with PAYMENT_TYPE_AUTHORIZATION / ACTIVE with a $12.34 pledge and see whether the payment
manager can query and get the right amount.
"""
user = User.objects.create_user('payment_test', 'support@gluejar.com', 'payment_test')
user = User.objects.create_user('payment_test', 'support@example.org', 'payment_test')
w = Work()
w.save()
@ -389,9 +389,9 @@ class AccountTest(TestCase):
def setUp(self):
# create a user
self.user1 = User.objects.create_user('account_test1', 'account_test1@gluejar.com', 'account_test1_pw')
self.user1 = User.objects.create_user('account_test1', 'account_test1@example.org', 'account_test1_pw')
self.user1.save()
self.user2 = User.objects.create_user('account_test2', 'account_test2@gluejar.com', 'account_test2_pw')
self.user2 = User.objects.create_user('account_test2', 'account_test2@example.org', 'account_test2_pw')
self.user2.save()
self.account1 = Account(host='host1', account_id='1', user=self.user1)
self.account1.save()

View File

@ -9,13 +9,14 @@ WebTest==1.4.0
amqplib==1.0.2
anyjson==0.3.3
billiard==2.7.3.12
#boto==2.3.0
git+ssh://git@github.com/Gluejar/boto.git@2.3.0
boto==2.8.0
#git+ssh://git@github.com/Gluejar/boto.git@2.3.0
celery==3.0.9
distribute==0.6.28
django-celery==3.0.9
django-ckeditor==3.6.2.1
django-endless-pagination==1.1
#django-ckeditor==3.6.2.1
git+ssh://git@github.com/Gluejar/django-ckeditor.git@24350a6fba78e38682008e468741661a75483591
django-endless-pagination==2.0
django-extensions==0.9
django-kombu==0.9.4
django-maintenancemode==0.10
@ -26,6 +27,7 @@ django-registration==0.8
django-selectable==0.5.2
django-smtp-ssl==1.0
django-social-auth==0.7.5
django-storages==1.1.6
django-tastypie==0.9.11
feedparser==5.1.2
freebase==1.0.8
@ -37,6 +39,7 @@ mimeparse==0.1.3
nose==1.1.2
oauth2==1.5.211
paramiko==1.7.7.2
postmonkey==1.0a4
pyasn1==0.1.4
pycrypto==2.6
python-dateutil==2.1

View File

@ -140,9 +140,10 @@ INSTALLED_APPS = (
'regluit.payment.templatetags',
'notification',
'ckeditor',
'storages',
# this must appear *after* django.frontend or else it overrides the
# registration templates in frontend/templates/registration
'django.contrib.admin',
'django.contrib.admin',
)
@ -305,3 +306,13 @@ class NONPROFIT:
# we should suppress Google Analytics outside of production
SHOW_GOOGLE_ANALYTICS = False
# to enable uploading to S3 and integration of django-storages + django-ckeditor
# some variables to be overriddden in more specific settings files -- e.g., prod.py,
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto.S3BotoStorage'
AWS_ACCESS_KEY_ID = ''
AWS_SECRET_ACCESS_KEY = ''
AWS_STORAGE_BUCKET_NAME = ''
MAILCHIMP_API_KEY = '5f8e846a2bbc847807ed89086de4b4bf-us2'
MAILCHIMP_NEWS_ID = u'c5cce92fe1'

View File

@ -129,8 +129,8 @@ LOGGING = {
}
STATIC_ROOT = '/var/www/static'
CKEDITOR_UPLOAD_PATH = '/var/www/static/media/'
CKEDITOR_UPLOAD_PREFIX = 'https://just.unglue.it/static/media/'
#CKEDITOR_UPLOAD_PATH = '/var/www/static/media/'
#CKEDITOR_UPLOAD_PREFIX = 'https://just.unglue.it/static/media/'
IS_PREVIEW = False
@ -148,6 +148,12 @@ AMAZON_FPS_HOST = "fps.sandbox.amazonaws.com"
# local settings for maintenance mode
MAINTENANCE_MODE = False
# Amazon keys to permit S3 access
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto.S3BotoStorage'
AWS_ACCESS_KEY_ID = 'AKIAIYP6XRVAUWKQFT5Q'
AWS_SECRET_ACCESS_KEY = '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'
AWS_STORAGE_BUCKET_NAME = 'just_unglueit'
# if settings/local.py exists, import those settings -- allows for dynamic generation of parameters such as DATABASES
try:

View File

@ -130,7 +130,8 @@ LOGGING = {
}
STATIC_ROOT = '/var/www/static'
CKEDITOR_UPLOAD_PATH = '/var/www/static/media/'
#CKEDITOR_UPLOAD_PATH = '/var/www/static/media/'
#CKEDITOR_UPLOAD_PREFIX = 'https://unglue.it/static/media/'
# decide which of the period tasks to add to the schedule
#CELERYBEAT_SCHEDULE['send_test_email'] = SEND_TEST_EMAIL_JOB
@ -147,6 +148,12 @@ AMAZON_FPS_HOST = "fps.amazonaws.com"
# local settings for maintenance mode
MAINTENANCE_MODE = False
# Amazon keys to permit S3 access
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto.S3BotoStorage'
AWS_ACCESS_KEY_ID = 'AKIAIRLBDIET3DFCNU4A'
AWS_SECRET_ACCESS_KEY = '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'
AWS_STORAGE_BUCKET_NAME = 'unglueit_files'
# if settings/local.py exists, import those settings -- allows for dynamic generation of parameters such as DATABASES
try:
from regluit.settings.local import *

View File

@ -1 +1 @@
.header-text{height:36px;line-height:36px;display:block;text-decoration:none;font-weight:bold;letter-spacing:-0.05em}.panelborders{border-width:1px 0;border-style:solid none;border-color:#fff}.roundedspan{border:1px solid #d4d4d4;-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;text-align:center;display:inline-block}.roundedspan>span .hovertext{display:none}.roundedspan>span:hover .hovertext{display:inline}.mediaborder{padding:5px;border:solid 5px #edf3f4}.actionbuttons{width:auto;height:36px;line-height:36px;background:#8dc63f;-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:0;margin:5px 0}.errors{-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:0}.notices_menu{float:right;-moz-border-radius:20px;-webkit-border-radius:20px;border-radius:20px;background:#edf3f4;padding:10px 20px;margin:-15px auto 7px 7px}.notices_menu a{font-size:13px;font-weight:bold}#js-main-container{float:none!important;padding-right:15px}th{text-align:left}tr{line-height:24px}tr.row1{background:#edf3f4}td{padding-left:7px;padding-right:7px}td#last{padding:0}input[type="submit"]{float:right;margin-right:0}.comments{border:solid 3px #d6dde0;margin:3px auto}.comments hr{margin:10px auto 5px;color:#d6dde0;background-color:#d6dde0;height:2px;border:0}.comments .comments_book{padding:5px;border:solid 5px #edf3f4;margin-right:10px;margin-bottom:10px;max-width:80px}.comments .comments_book img{max-width:80px}.comments .comments_textual{padding:10px 5px 5px}.comments .comments_textual div{margin-bottom:5px}.comments .comments_info{border-bottom:solid 1px #d6dde0;padding:5px}.comments .comments_info div{float:left}.comments .comments_info .comments_graphical{padding:5px auto}.comments .comments_info span{text-indent:0}
.header-text{height:36px;line-height:36px;display:block;text-decoration:none;font-weight:bold;letter-spacing:-0.05em}.panelborders{border-width:1px 0;border-style:solid none;border-color:#fff}.roundedspan{border:1px solid #d4d4d4;-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;text-align:center;display:inline-block}.roundedspan>span .hovertext{display:none}.roundedspan>span:hover .hovertext{display:inline}.mediaborder{padding:5px;border:solid 5px #edf3f4}.actionbuttons{width:auto;height:36px;line-height:36px;background:#8dc63f;-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:0;margin:5px 0}.errors{-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:0}.notices_menu{float:right;-moz-border-radius:20px;-webkit-border-radius:20px;border-radius:20px;background:#edf3f4;padding:10px 20px;margin:-15px auto 7px 7px}.notices_menu a{font-size:13px;font-weight:bold}#js-main-container{float:none!important;padding-right:15px}th{text-align:left}tr{line-height:24px}tr.row1{background:#edf3f4}td{padding-left:7px;padding-right:7px}td#last{padding:0}table input[type="submit"]{float:right;margin-right:0}.comments{border:solid 3px #d6dde0;margin:3px auto}.comments hr{margin:10px auto 5px;color:#d6dde0;background-color:#d6dde0;height:2px;border:0}.comments .comments_book{padding:5px;border:solid 5px #edf3f4;margin-right:10px;margin-bottom:10px;max-width:80px}.comments .comments_book img{max-width:80px}.comments .comments_textual{padding:10px 5px 5px}.comments .comments_textual div{margin-bottom:5px}.comments .comments_info{border-bottom:solid 1px #d6dde0;padding:5px}.comments .comments_info div{float:left}.comments .comments_info .comments_graphical{padding:5px auto}.comments .comments_info span{text-indent:0}

View File

@ -4,7 +4,7 @@
var $j = jQuery.noConflict();
$j(document).ready(function() {
$j("#js-page-wrap").on("click", "a.hijax", function(event) {
$j("#js-page-wrap, #footer").on("click", "a.hijax", function(event) {
event.preventDefault();
$j("#lightbox").load($j(this).attr("href") + " #lightbox_content", function() {
// centering divs of dynamic width: shockingly hard. make sure lightbox is centered on load.
@ -24,9 +24,7 @@ $j(document).ready(function() {
}
// fade-out rest of page elements on expand
$j('#feedback').css({"opacity": "0.07"});
$j('#js-page-wrap').css({"opacity": "0.07"});
$j('#footer').css({"opacity": "0.07"});
$j('#feedback, #js-page-wrap, #footer').css({"opacity": "0.07"});
$j('#about_expandable').css({'position': 'absolute'});
$j('#about_expandable').fadeTo("slow", 1);
@ -48,15 +46,8 @@ $j(document).ready(function() {
// fade-in normal page elements on collapse
$j('#about_collapser').on("click", function(){
$j('#js-topsection').fadeTo("slow", 1);
$j('.launch_top').fadeTo("slow", 1);
$j('.preview').fadeTo("slow", 1);
$j('#main-container').fadeTo("slow", 1);
$j('#js-rightcol').fadeTo("slow", 1);
$j('#js-header').fadeTo("slow", 1);
$j('#js-topsection, .launch_top, .preview, #main-container, #js-rightcol, #js-header, #js-page-wrap, #footer, #feedback').fadeTo("slow", 1);
$j('#js-header a').css({"cursor": "pointer"});
$j('#js-page-wrap').fadeTo("slow", 1);
$j('#footer').fadeTo("slow", 1);
$j('#about_expandable').css({"display": "none"});
});

View File

@ -1,11 +1,13 @@
// hijack a link with class "hijax" to show its content in a lightbox instead
// allows for ajaxy presentation of things like download links in a way that
// degrades gracefully for non-js users
// hijack a link with class "hijax" to load only the list element
var $j = jQuery.noConflict();
$j(document).ready(function() {
$j("a.hijax_unglued").click(function(event) {
event.preventDefault();
$j("#content-block-content").html('<img src="/static/images/loading.gif">').load($j(this).attr("href") + " #books-go-here");
$j("#content-block-content").html('<img src="/static/images/loading.gif">').load($j(this).attr("href") + " #books-go-here", function(){
$j('#toggle-list').click(toggleList);
$j('#toggle-panel').click(togglePanel);
if($j.cookie('view')=='panel') {togglePanel();}
});
});
});

View File

@ -40,7 +40,7 @@ td {
}
}
input[type="submit"] {
table input[type="submit"] {
float: right;
margin-right: 0;
}