just merging my local codebase post-internet librarian...
commit
e41e1e7b6d
|
@ -10,7 +10,11 @@ from regluit.core import models
|
|||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def add_by_isbn(isbn):
|
||||
def add_by_isbn(isbn, work=None):
|
||||
"""add a book to the UnglueIt database based on ISBN. The work parameter
|
||||
is optional, and if not supplied the edition will be associated with
|
||||
a stub work.
|
||||
"""
|
||||
url = "https://www.googleapis.com/books/v1/volumes"
|
||||
results = _get_json(url, {"q": "isbn:%s" % isbn})
|
||||
|
||||
|
@ -18,21 +22,27 @@ def add_by_isbn(isbn):
|
|||
logger.warn("no google hits for %s" % isbn)
|
||||
return None
|
||||
|
||||
return add_by_googlebooks_id(results['items'][0]['id'])
|
||||
return add_by_googlebooks_id(results['items'][0]['id'], work)
|
||||
|
||||
|
||||
def add_by_googlebooks_id(googlebooks_id):
|
||||
url = "https://www.googleapis.com/books/v1/volumes/%s" % googlebooks_id
|
||||
d = _get_json(url)['volumeInfo']
|
||||
|
||||
def add_by_googlebooks_id(googlebooks_id, work=None):
|
||||
"""add a book to the UnglueIt database based on the GoogleBooks ID. The
|
||||
work parameter is optional, and if not supplied the edition will be
|
||||
associated with a stub work.
|
||||
"""
|
||||
# don't ping google again if we already know about the edition
|
||||
e, created = models.Edition.objects.get_or_create(googlebooks_id=googlebooks_id)
|
||||
if not created:
|
||||
return e
|
||||
|
||||
url = "https://www.googleapis.com/books/v1/volumes/%s" % googlebooks_id
|
||||
d = _get_json(url)['volumeInfo']
|
||||
|
||||
e.title = d.get('title')
|
||||
e.description = d.get('description')
|
||||
e.publisher = d.get('publisher')
|
||||
e.publication_date = d.get('publishedDate')
|
||||
e.language = d.get('language')
|
||||
|
||||
for i in d.get('industryIdentifiers', []):
|
||||
if i['type'] == 'ISBN_10':
|
||||
|
@ -48,20 +58,44 @@ def add_by_googlebooks_id(googlebooks_id):
|
|||
s, created = models.Subject.objects.get_or_create(name=s)
|
||||
s.editions.add(e)
|
||||
|
||||
# add a stub Work for the edition
|
||||
if e.work == None:
|
||||
# if we know what work to add the edition to do it
|
||||
if work:
|
||||
work.editions.add(e)
|
||||
|
||||
# otherwise we need to create a stub work
|
||||
else:
|
||||
w = models.Work.objects.create(title=e.title)
|
||||
w.editions.add(e)
|
||||
|
||||
return e
|
||||
|
||||
|
||||
def add_related(isbn):
|
||||
"""add all books related to a particular ISBN to the UnglueIt database.
|
||||
The initial seed ISBN will be added if it's not already there.
|
||||
"""
|
||||
# make sure the seed edition is there
|
||||
edition = add_by_isbn(isbn)
|
||||
|
||||
# this is the work everything will hang off
|
||||
work = edition.work
|
||||
|
||||
for other_isbn in thingisbn(isbn):
|
||||
# TODO: if the other book is there already we have some surgery
|
||||
# to do on the works, and the wishlists
|
||||
add_by_isbn(other_isbn, work)
|
||||
|
||||
|
||||
def thingisbn(isbn):
|
||||
"""given an ISBN return a list of related edition ISBNs, according to
|
||||
Library Thing.
|
||||
"""
|
||||
url = "http://www.librarything.com/api/thingISBN/%s" % isbn
|
||||
xml = requests.get(url, headers={"User-Agent": settings.USER_AGENT}).content
|
||||
doc = ElementTree.fromstring(xml)
|
||||
return [e.text for e in doc.findall('isbn')]
|
||||
|
||||
|
||||
def _get_json(url, params={}):
|
||||
# TODO: should X-Forwarded-For change based on the request from client?
|
||||
headers = {'User-Agent': settings.USER_AGENT,
|
||||
|
|
|
@ -0,0 +1,125 @@
|
|||
# encoding: utf-8
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import SchemaMigration
|
||||
from django.db import models
|
||||
|
||||
class Migration(SchemaMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
|
||||
# Adding field 'Edition.language'
|
||||
db.add_column('core_edition', 'language', self.gf('django.db.models.fields.CharField')(max_length=2, null=True), keep_default=False)
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
|
||||
# Deleting field 'Edition.language'
|
||||
db.delete_column('core_edition', 'language')
|
||||
|
||||
|
||||
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', 'null': 'True'}),
|
||||
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'deadline': ('django.db.models.fields.DateTimeField', [], {}),
|
||||
'description': ('django.db.models.fields.TextField', [], {}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
|
||||
'paypal_receiver': ('django.db.models.fields.CharField', [], {'max_length': '100', 'null': 'True'}),
|
||||
'supended_reason': ('django.db.models.fields.TextField', [], {'null': 'True'}),
|
||||
'suspended': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
|
||||
'target': ('django.db.models.fields.DecimalField', [], {'max_digits': '14', 'decimal_places': '2'}),
|
||||
'withdrawn': ('django.db.models.fields.DateTimeField', [], {'null': 'True'}),
|
||||
'withdrawn_reason': ('django.db.models.fields.TextField', [], {'null': 'True'}),
|
||||
'work': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'campaigns'", 'to': "orm['core.Work']"})
|
||||
},
|
||||
'core.edition': {
|
||||
'Meta': {'object_name': 'Edition'},
|
||||
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'description': ('django.db.models.fields.TextField', [], {'default': "''", 'null': 'True'}),
|
||||
'googlebooks_id': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'isbn_10': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True'}),
|
||||
'isbn_13': ('django.db.models.fields.CharField', [], {'max_length': '13', 'null': 'True'}),
|
||||
'language': ('django.db.models.fields.CharField', [], {'max_length': '2', 'null': 'True'}),
|
||||
'publication_date': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
|
||||
'publisher': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
'title': ('django.db.models.fields.CharField', [], {'max_length': '1000'}),
|
||||
'work': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'editions'", 'null': 'True', 'to': "orm['core.Work']"})
|
||||
},
|
||||
'core.subject': {
|
||||
'Meta': {'object_name': 'Subject'},
|
||||
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'editions': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'subjects'", '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.userprofile': {
|
||||
'Meta': {'object_name': 'UserProfile'},
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'tagline': ('django.db.models.fields.CharField', [], {'max_length': '140', 'blank': 'True'}),
|
||||
'user': ('django.db.models.fields.related.OneToOneField', [], {'related_name': "'profile'", 'unique': 'True', 'to': "orm['auth.User']"})
|
||||
},
|
||||
'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', 'to': "orm['core.Work']"})
|
||||
},
|
||||
'core.work': {
|
||||
'Meta': {'object_name': 'Work'},
|
||||
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'openlibrary_id': ('django.db.models.fields.CharField', [], {'max_length': '50', 'null': 'True'}),
|
||||
'title': ('django.db.models.fields.CharField', [], {'max_length': '1000'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['core']
|
|
@ -152,6 +152,7 @@ class Edition(models.Model):
|
|||
isbn_10 = models.CharField(max_length=10, null=True)
|
||||
isbn_13 = models.CharField(max_length=13, null=True)
|
||||
work = models.ForeignKey("Work", related_name="editions", null=True)
|
||||
language = models.CharField(max_length=2, null=True)
|
||||
|
||||
def __unicode__(self):
|
||||
return "%s (%s)" % (self.title, self.isbn_13)
|
||||
|
|
|
@ -21,6 +21,7 @@ class TestBookLoader(TestCase):
|
|||
self.assertEqual(edition.isbn_10, '0441012035')
|
||||
self.assertEqual(edition.isbn_13, '9780441012039')
|
||||
self.assertEqual(edition.googlebooks_id, "2NyiPwAACAAJ")
|
||||
self.assertEqual(edition.language, "en")
|
||||
|
||||
# subjects
|
||||
subject_names = [subject.name for subject in edition.subjects.all()]
|
||||
|
@ -52,6 +53,18 @@ class TestBookLoader(TestCase):
|
|||
self.assertTrue('0441012035' in isbns)
|
||||
self.assertTrue('3453313895' in isbns)
|
||||
|
||||
def test_add_related(self):
|
||||
# add one edition
|
||||
edition = bookloader.add_by_isbn('0441012035')
|
||||
self.assertEqual(models.Edition.objects.count(), 1)
|
||||
self.assertEqual(models.Work.objects.count(), 1)
|
||||
|
||||
# ask for related editions to be added using the work we just created
|
||||
bookloader.add_related('0441012035')
|
||||
self.assertTrue(models.Edition.objects.count() > 20)
|
||||
self.assertEqual(models.Work.objects.count(), 1)
|
||||
self.assertTrue(edition.work.editions.count() > 20)
|
||||
|
||||
class SearchTests(TestCase):
|
||||
|
||||
def test_basic_search(self):
|
||||
|
@ -86,10 +99,10 @@ class CampaignTests(TestCase):
|
|||
c = Campaign(target=D('1000.00'), deadline=datetime(2012, 1, 1))
|
||||
self.assertRaises(IntegrityError, c.save)
|
||||
|
||||
#w = Work()
|
||||
#w.save()
|
||||
#c = Campaign(target=D('1000.00'), deadline=datetime(2012, 1, 1), work=w)
|
||||
#c.save()
|
||||
w = Work()
|
||||
w.save()
|
||||
c = Campaign(target=D('1000.00'), deadline=datetime(2012, 1, 1), work=w)
|
||||
c.save()
|
||||
|
||||
|
||||
def test_campaign_status(self):
|
||||
|
|
|
@ -17,13 +17,23 @@
|
|||
<body>
|
||||
|
||||
<div id="js-page-wrap">
|
||||
<div id="js-header">
|
||||
<div class="js-main">
|
||||
<div class="js-logo">
|
||||
<a href="/"><img src="/static/images/logo.png" alt="unglue.it" title="unglue.it" /></a>
|
||||
<div id="js-header">
|
||||
<div class="js-main">
|
||||
<div class="js-logo">
|
||||
<a href="/"><img src="/static/images/logo.png" alt="unglue.it" title="unglue.it" /></a>
|
||||
</div>
|
||||
{% if not suppress_search_box %}
|
||||
<div class="js-search" style="float: left; margin-left: 50px;">
|
||||
<div class="js-search-inner">
|
||||
<form action="{% url search %}" method="get">
|
||||
<input type="text" placeholder="Search for a book..." size="30" class="inputbox" name="q" value="{{ q }}">
|
||||
<input type="button" onclick="this.form.searchword.focus();" class="button" value="Search">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="js-topmenu">
|
||||
<ul class="menu">
|
||||
<ul class="menu">
|
||||
{% if user.is_authenticated %}
|
||||
<li class="first"><a href="/supporter/{{user.username}}"><span id="welcome">Welcome, {{ user.username }}</span></a></li>
|
||||
<li><a href="{% url auth_logout %}"><span>Sign Out</span></a></li>
|
||||
|
@ -47,12 +57,12 @@
|
|||
</div>
|
||||
|
||||
<div id="footer">
|
||||
<p>
|
||||
<a href="{{privacyurl}}"><span>Privacy</span></a>
|
||||
<a href="{{rhtoolsurl}}"><span>Rightsholder tools</span></a>
|
||||
{% if user.is_authenticated %}
|
||||
<a href="{{editurl}}"><span>Settings</span></a>
|
||||
{% endif %}
|
||||
<p>
|
||||
<a href="{{privacyurl}}"><span>Privacy</span></a>
|
||||
<a href="{{rhtoolsurl}}"><span>Rightsholder tools</span></a>
|
||||
{% if user.is_authenticated %}
|
||||
<a href="{{editurl}}"><span>Settings</span></a>
|
||||
{% endif %}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -1,24 +1,7 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block extra_head %}
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$(".add-wishlist").each(function (index, element) {
|
||||
$(element).click(function() {
|
||||
var span = $(element).find("span");
|
||||
var gb_id = span.attr('id')
|
||||
if (!gb_id) return;
|
||||
$.post('/wishlist/', {'googlebooks_id': gb_id}, function(data) {
|
||||
span.fadeOut();
|
||||
var newSpan = $("<span>On Your Wishlist!</span>").hide();
|
||||
span.replaceWith(newSpan);
|
||||
newSpan.fadeIn();
|
||||
newSpan.removeAttr("id");
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<script type="text/javascript" src="/static/js/wishlist.js"></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block title %}Search Results{% endblock %}
|
||||
|
|
|
@ -3,77 +3,45 @@
|
|||
{% block title %} — {{ supporter.username }}{% endblock %}
|
||||
|
||||
{% block extra_head %}
|
||||
<script type="text/javascript">
|
||||
$$(document).ready(function() {
|
||||
$(".add-wishlist").each(function (index, element) {
|
||||
$(element).click(function() {
|
||||
var span = $(element).find("span");
|
||||
var gb_id = span.attr('id')
|
||||
if (!gb_id) return;
|
||||
$.post('/wishlist/', {'googlebooks_id': gb_id}, function(data) {
|
||||
span.fadeOut();
|
||||
var newSpan = $("<span>On Your Wishlist!</span>").hide();
|
||||
span.replaceWith(newSpan);
|
||||
newSpan.fadeIn();
|
||||
newSpan.removeAttr("id");
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$(".remove-wishlist").each(function (index, element) {
|
||||
$(element).click(function() {
|
||||
var span = $(element).find("span");
|
||||
var work_id = span.attr('id')
|
||||
$.post('/wishlist/', {'remove_work_id': work_id}, function(data) {
|
||||
var book = $(element).parent();
|
||||
book.fadeOut();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<script type="text/javascript" src="/static/js/wishlist.js"></script>
|
||||
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script>
|
||||
<script type="text/javascript" src="/static/js/jquery-ui-1.8.16.custom.min.js"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
var $j = jQuery.noConflict();
|
||||
$j(document).ready(function(){
|
||||
$j('.user-block-hide').hide();
|
||||
$j('.user-block1 a').click(
|
||||
function() {
|
||||
$j(this).toggleClass("active");
|
||||
$j(".user-block-hide").slideToggle(300);
|
||||
}
|
||||
);
|
||||
$j('.tabs1').click(function(){
|
||||
$j('#tabs').find('.active').removeClass('active');
|
||||
$j(this).addClass('active');
|
||||
$j('.content-block-content').find('.active').removeClass('active');
|
||||
$j('#tabs-1').addClass('active').show(300);
|
||||
$j('#tabs-2').hide(200);
|
||||
$j('#tabs-3').hide(200);
|
||||
});
|
||||
$j('.tabs2').click(function(){
|
||||
$j('#tabs').find('.active').removeClass('active');
|
||||
$j(this).addClass('active');
|
||||
$j('.content-block-content').find('.active').removeClass('active');
|
||||
$j('#tabs-2').addClass('active').show(300);
|
||||
$j('#tabs-1').hide(200);
|
||||
$j('#tabs-3').hide(200);
|
||||
});
|
||||
$j('.tabs3').click(function(){
|
||||
$j('#tabs').find('.active').removeClass('active');
|
||||
$j(this).addClass('active');
|
||||
$j('.content-block-content').find('.active').removeClass('active');
|
||||
$j('#tabs-3').addClass('active').show(300);
|
||||
$j('#tabs-2').hide(200);
|
||||
$j('#tabs-1').hide(200);
|
||||
});
|
||||
});
|
||||
var $j = jQuery.noConflict();
|
||||
$j(document).ready(function(){
|
||||
$j('.user-block-hide').hide();
|
||||
$j('.user-block1 a').click(
|
||||
function() {
|
||||
$j(this).toggleClass("active");
|
||||
$j(".user-block-hide").slideToggle(300);
|
||||
}
|
||||
);
|
||||
$j('.tabs1').click(function(){
|
||||
$j('#tabs').find('.active').removeClass('active');
|
||||
$j(this).addClass('active');
|
||||
$j('.content-block-content').find('.active').removeClass('active');
|
||||
$j('#tabs-1').addClass('active').show(300);
|
||||
$j('#tabs-2').hide(200);
|
||||
$j('#tabs-3').hide(200);
|
||||
});
|
||||
$j('.tabs2').click(function(){
|
||||
$j('#tabs').find('.active').removeClass('active');
|
||||
$j(this).addClass('active');
|
||||
$j('.content-block-content').find('.active').removeClass('active');
|
||||
$j('#tabs-2').addClass('active').show(300);
|
||||
$j('#tabs-1').hide(200);
|
||||
$j('#tabs-3').hide(200);
|
||||
});
|
||||
$j('.tabs3').click(function(){
|
||||
$j('#tabs').find('.active').removeClass('active');
|
||||
$j(this).addClass('active');
|
||||
$j('.content-block-content').find('.active').removeClass('active');
|
||||
$j('#tabs-3').addClass('active').show(300);
|
||||
$j('#tabs-2').hide(200);
|
||||
$j('#tabs-1').hide(200);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
</script>
|
||||
|
@ -83,24 +51,22 @@ $(document).ready(function() {
|
|||
/*
|
||||
To do:
|
||||
create topsection file for inclusion in multiple contexts, if needed
|
||||
do we really want to display date joined in profile? if so, with any text? "supporter since (date) is too long"
|
||||
add support for userpics/avatars/something
|
||||
crop/resize? other infrastructure we need? can we pull from twitter/fb?
|
||||
add support for twitter/fb/other links
|
||||
part of user profile? can I just add to db model?
|
||||
loosely coupled vs actually integrated with signin
|
||||
canonicalize -- user enters cut/paste link vs username
|
||||
figure out how to configure date display
|
||||
decide if we're even including date joined in profile
|
||||
add support for userpics
|
||||
crop/resize? other infrastructure we need? can we pull from twitter/fb?
|
||||
add support for twitter/fb/other links?
|
||||
part of user profile? can I just add to db model?
|
||||
loosely coupled vs actually integrated with signin
|
||||
canonicalize -- user enters cut/paste link vs username
|
||||
Goodreads & Librarything support
|
||||
If people lack homepage, etc., do we have greyed-out icons or no icons?
|
||||
if greyed-out, can they add in place by clicking on them?
|
||||
make sure profile settings do something
|
||||
if greyed-out, can they add in place by clicking on them?
|
||||
make sure we have the profile settings we need
|
||||
resurrect add/remove functionality
|
||||
be sure words display correctly
|
||||
be sure words display correctly
|
||||
do I need both add-wishlist and remove-wishlist classes? do they differ?
|
||||
better alignment on I am ungluing & badges
|
||||
progress indicators
|
||||
change status text to something more user-friendly
|
||||
js is not DRY right now -- need to put into scripts folder and reference
|
||||
|
||||
make sure backed/backing/wishlist is the order we want the badges to be in
|
||||
test code with other campaign statuses -- random_campaigns needs to set a variety of statuses!
|
||||
|
@ -108,101 +74,91 @@ why is there a status in regluit.payment.models.Transaction? does it duplicate
|
|||
|
||||
|
||||
there's no tab for seeing ALL my books, only the filters! huh.
|
||||
|
||||
|
||||
Values I need:
|
||||
how do I integrate the your wishlist thing with the tabs thing?
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
*/
|
||||
|
||||
{% block topsection %}
|
||||
|
||||
<div id="js-topsection">
|
||||
<div class="js-main">
|
||||
<div class="js-topnews">
|
||||
<div class="js-topnews1">
|
||||
<div class="js-topnews2">
|
||||
<div class="js-topnews3">
|
||||
<div class="user-block">
|
||||
{% ifequal supporter request.user %}
|
||||
<div class="js-main">
|
||||
<div class="js-topnews">
|
||||
<div class="js-topnews1">
|
||||
<div class="js-topnews2">
|
||||
<div class="js-topnews3">
|
||||
<div class="user-block">
|
||||
{% ifequal supporter request.user %}
|
||||
<div class="user-block1">
|
||||
<div class="block-inner">
|
||||
<a class="my-setting" href="#">My Settings</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endifequal %}
|
||||
{% endifequal %}
|
||||
<div class="user-block2">
|
||||
<img class="user-avatar" src="/static/images/header/avatar.png" height="50" width="50" alt="User avatar" title="User avatar" />
|
||||
<img class="user-avatar" src="/static/images/header/avatar.png" height="50" width="50" alt="User avatar" title="User avatar" />
|
||||
<span class="user-name"><a href="#">{{ supporter.username }}</a></span>
|
||||
<span class="user-date">{{ date }}</span>
|
||||
<span class="user-short-info">{{ supporter.profile.tagline }}</span>
|
||||
</div>
|
||||
<div class="user-block4">
|
||||
<div class="social">
|
||||
<a href="#"><img src="/static/images/header/icon-home.png" alt="Home" title="Home" /></a>
|
||||
<div class="social">
|
||||
<a href="#"><img src="/static/images/header/icon-home.png" alt="Home" title="Home" /></a>
|
||||
<a href="#"><img src="/static/images/header/icon-facebook.png" alt="Facebook" title="Facebook" /></a>
|
||||
<a href="#"><img src="/static/images/header/icon-tweeter.png" alt="tweeter" title="tweeter" /></a>
|
||||
<a href="#"><img src="/static/images/header/icon-twitter.png" alt="twitter" title="twitter" /></a>
|
||||
<a href="#"><img src="/static/images/header/icon-google.png" alt="google" title="google" /></a>
|
||||
<a href="#"><img src="/static/images/header/icon-group.png" alt="group" title="group" /></a></div>
|
||||
</div>
|
||||
<div class="user-block3">
|
||||
<div class="user-block">
|
||||
<div class="user-block">
|
||||
<span class="rounded"><span class="blue">{{ backed }}</span></span>
|
||||
<span class="rounded"><span class="orange">{{ backing }}</span></span>
|
||||
<span class="rounded"><span class="grey">{{ wished }}</span></span>
|
||||
</div>
|
||||
<span class="user-status-title">I am ungluing</span>
|
||||
</div>
|
||||
<span class="user-status-title">I am ungluing</span>
|
||||
</div>
|
||||
</div>
|
||||
{% ifequal supporter request.user %}
|
||||
<div class="user-block-hide">
|
||||
<div class="block block1">
|
||||
<div class="block block1">
|
||||
<div class="block-inner">
|
||||
<h3><a class="profile-edit" href="#">Profile / edit</a></h3>
|
||||
Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
|
||||
<div class="profile-save">
|
||||
<a href="#" class="profile-save">Save setting</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="block block2">
|
||||
<h3 class="title">Pledges</h3>
|
||||
<div class="check-list">
|
||||
<input type="checkbox" />
|
||||
<label>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</label>
|
||||
</div>
|
||||
<div class="check-list">
|
||||
<input type="checkbox" />
|
||||
<label>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="block block3">
|
||||
<h3 class="title">Links</h3>
|
||||
<div class="check-list">
|
||||
<input type="checkbox" />
|
||||
<label>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</label>
|
||||
</div>
|
||||
<div class="check-list">
|
||||
<input type="checkbox" />
|
||||
<label>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="block block4">
|
||||
<h3 class="title">Privacy</h3>
|
||||
<div class="check-list">
|
||||
<input type="checkbox" />
|
||||
<label>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</label>
|
||||
</div>
|
||||
<div class="check-list">
|
||||
<input type="checkbox" />
|
||||
<label>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<h3><a class="profile-edit" href="#">Profile / edit</a></h3>
|
||||
<form method="POST" action="">
|
||||
{% csrf_token %}
|
||||
{{ profile_form.as_p }}
|
||||
|
||||
<input class="profile-save" type="submit" name="submit" value="Update" id="submit">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="block block2">
|
||||
<h3 class="title">Links</h3>
|
||||
<div class="check-list">
|
||||
<input type="checkbox" />
|
||||
<label>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</label>
|
||||
</div>
|
||||
<div class="check-list">
|
||||
<input type="checkbox" />
|
||||
<label>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="block block3">
|
||||
<h3 class="title">Privacy</h3>
|
||||
<div class="check-list">
|
||||
<input type="checkbox" />
|
||||
<label>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</label>
|
||||
</div>
|
||||
<div class="check-list">
|
||||
<input type="checkbox" />
|
||||
<label>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{% endifequal %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -223,7 +179,7 @@ how do I integrate the your wishlist thing with the tabs thing?
|
|||
<div class="js-maincol-inner">
|
||||
<div class="content-block">
|
||||
<div class="content-block-heading" id="tabs">
|
||||
<ul class="tabs">
|
||||
<ul class="tabs">
|
||||
<li class="tabs1"><a href="#">Unglued</a></li>
|
||||
<li class="tabs2"><a href="#">Being Unglued</a></li>
|
||||
<li class="tabs3"><a href="#">Want to Unglue</a></li>
|
||||
|
@ -249,26 +205,49 @@ how do I integrate the your wishlist thing with the tabs thing?
|
|||
</ul>
|
||||
</div>
|
||||
<div class="content-block-content">
|
||||
{% ifequal wishlist.works.all.count 0 %}
|
||||
{% ifequal request.user supporter %}
|
||||
<div class="empty-wishlist">
|
||||
Your wishlist is currently empty.<br><br>
|
||||
Go ahead and <span class="bounce-search">find</span> some books to give to the world, and add them to your Wishlist!<br><br>
|
||||
We double dog dare you...
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="empty-wishlist">
|
||||
It looks like {{ supporter.username }} is just
|
||||
getting started, and hasn't added anything to their
|
||||
wishlist just yet.<br><br>
|
||||
Nudge, nudge, say no more.
|
||||
{% endifequal %}
|
||||
{% else %}
|
||||
{% for work in wishlist.works.all %}
|
||||
<div id="tabs-1" class="tabs">
|
||||
<div class="book-list {% cycle 'row1' 'row2' %}">
|
||||
<div id="tabs-1" class="tabs">
|
||||
<div class="book-list {% cycle 'row1' 'row2' %}">
|
||||
<div class="book-thumb">
|
||||
<a href="#"><img src="{{ work.cover_image_small }}" alt="Book name" title="book name" /></a>
|
||||
</div>
|
||||
<div class="book-name">
|
||||
<span>
|
||||
{{ work.title }}
|
||||
<a href="{% url work work.id %}">{{ work.title }}</a>
|
||||
</span>
|
||||
</div>
|
||||
{% if work in request.user.wishlist.works.all %}
|
||||
{% ifequal supporter request.user %}
|
||||
<div class="remove-wishlist">
|
||||
<a href="#"><span id="{{ work.id }}">Remove from Wishlist</span></a>
|
||||
<span id="{{ work.id }}">Remove from Wishlist</span>
|
||||
</div>
|
||||
{% else %}
|
||||
{% else %}{% if work in shared_works %}
|
||||
<div>
|
||||
<span>On Your Wishlist!</span>
|
||||
</div>
|
||||
{% else %}{% if request.user.is_anonymous %}
|
||||
<div class="create-account">
|
||||
<span>Add to Wishlist</span>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="add-wishlist">
|
||||
<a href="#"><span id="{{ work.id }}">Add to Wishlist</span></a>
|
||||
<span id="{{ work.editions.all.0.googlebooks_id }}">Add to Wishlist</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}{% endif %}{% endifequal %}
|
||||
<div class="booklist-status">
|
||||
<span class="booklist-status-text">{{ work.last_campaign_status }}</span>
|
||||
<span class="booklist-status-img">
|
||||
|
@ -284,6 +263,7 @@ how do I integrate the your wishlist thing with the tabs thing?
|
|||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endifequal %}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -19,7 +19,7 @@ def home(request):
|
|||
if request.user.is_authenticated():
|
||||
return HttpResponseRedirect(reverse('supporter',
|
||||
args=[request.user.username]))
|
||||
return render(request, 'home.html')
|
||||
return render(request, 'home.html', {'suppress_search_box': True})
|
||||
|
||||
def supporter(request, supporter_username):
|
||||
supporter = get_object_or_404(User, username=supporter_username)
|
||||
|
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
@ -0,0 +1,30 @@
|
|||
$(document).ready(function() {
|
||||
|
||||
$(".add-wishlist").each(function (index, element) {
|
||||
$(element).click(function() {
|
||||
var span = $(element).find("span");
|
||||
var gb_id = span.attr('id')
|
||||
if (!gb_id) return;
|
||||
$.post('/wishlist/', {'googlebooks_id': gb_id}, function(data) {
|
||||
span.fadeOut();
|
||||
var newSpan = $("<span>On Your Wishlist!</span>").hide();
|
||||
span.replaceWith(newSpan);
|
||||
newSpan.fadeIn();
|
||||
newSpan.removeAttr("id");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
$(".remove-wishlist").each(function (index, element) {
|
||||
$(element).click(function() {
|
||||
var span = $(element).find("span");
|
||||
var work_id = span.attr('id')
|
||||
$.post('/wishlist/', {'remove_work_id': work_id}, function(data) {
|
||||
var book = $(element).parent();
|
||||
book.fadeOut();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
Loading…
Reference in New Issue