Merge branch 'master' into newpayment

Conflicts:
	frontend/views.py
pull/1/head
Raymond Yee 2012-08-27 07:59:12 -07:00
commit 981790883e
9 changed files with 296 additions and 56 deletions

View File

@ -0,0 +1,53 @@
{% extends "base.html" %}
{% with work.title as title %}
{% block title %}
— Downloads for {{ work.title }}
{% endblock %}
{% block extra_css %}
<link type="text/css" rel="stylesheet" href="/static/css/download.css" />
{% endblock %}
{% block extra_js %}
<script type="text/javascript" src="/static/js/wishlist.js"></script>
{% endblock %}
{% block content %}
<div class="download_container">
<h2>Downloads for {{ work.title }}</h2>
{% if unglued_ebook %}
<div class="unglued">
<h3>Get the unglued edition!</h3>
<div class="ebook_download">
<img src="{{ unglued_ebook.rights_badge }}">
<a href="{{ unglued_ebook.0.url }}">{{ unglued_ebook.format }}</a>
</div>
</div>
{% endif %}
{% if other_ebooks %}
{% if unglued_ebook %}<h4>Freely available editions</h4>{% endif %}
{% comment %}
the header is only necessary if we have an unglued edition we're distinguishing
non-unglued editions from
{% endcomment %}
{% for edition in other_ebooks %}
<div class="ebook_download clearfix">
{% with edition.url as url %}
<a href="{{ url }}"><img src="{{ edition.rights_badge }}"></a>
<a href="{{ url }}">{{ edition.format }}</a>
{% endwith %}
</div>
{% endfor %}
{% endif %}
{% if unglued_ebook or other_ebooks %}
blah blah download instructions
{% else %}
<p id="content-block">There are no freely available downloads of <I>{{ work.title }}</I> right now. {% if not work in request.user.wishlist.works.all %}Would you like there to be? <a class="add-wishlist"><span class="work_id" id="w{{ work.id }}">Add this book to your wishlist.</span></a>{% else %}Ask your friends to add it to their wishlists!{% endif %}</p>
<p>If you know of a Creative-Commons-licensed or US public domain edition of this book, you can add it through the <a href="{% url work work.id %}?tab=4">Rights tab of the book page</a>.</p>
{% endif %}
</div>
{% endblock %}
{% endwith %}

View File

@ -28,16 +28,6 @@ $j(document).ready(function(){
$j(this).next().toggle();
});
});
$j(document).ready(function(){
$j('.show_more_ebooks').click(function(){
if ($j(this).html() == '<br>hide downloads') {
$j(this).html('<br>more downloads...')
} else {
$j(this).html('<br>hide downloads')
}
$j(this).next().toggle();
});
});
$j(document).ready(function(){
var img = $j('#book-detail-img');
var googimg = $j('#find-google img');
@ -134,33 +124,15 @@ $j(document).ready(function(){
{% else %}
<div class="btn_support"><form action="{% url pledge work_id %}" method="get"><input type="submit" value="Support" /></form></div>
{% endif %}
{% else %}
{% if work.first_ebook %}
<div class="btn_support">
<a href="{% url download work_id %}" id="ebookDownload" class="fakeinput">Download</a>
</div>
{% endif %}
{% endif %}
</div>
</div>
{% if work.first_ebook %}
<div class="get-book">
<label>Read it now!</label>
<span class="find-link">
{% for ebook in work.ebooks %}
{% if forloop.first %}
<span class="first_ebook">
{% endif %}
{% if forloop.counter == 2 %}
</span>
<span class="show_more_ebooks"><br />More downloads...</span>
<span class="more_ebooks">
{% endif %}
{% if not forloop.first %}
<br />
{% endif %}
<a href="{{ ebook.url }}"><img src="/static/images/{{ ebook.format }}32.png" height="32" alt=" {{ ebook.format }} at {{ebook.provider}}" title=" {{ ebook.format }} at {{ebook.provider}}" /><img src="{{ebook.rights_badge}}" height="31" width="88" alt="{{ebook.rights}}" title="{{ebook.rights}}" /></a>
{% if forloop.last %}
</span>
{% endif %}
{% endfor %}
</span>
</div>
{% endif %}
<div class="find-book">
<label>Learn more at...</label>
<div class="find-link">
@ -415,7 +387,7 @@ $j(document).ready(function(){
{% if premium.limit == 0 or premium.limit > premium.premium_count %}
<li class="{% if forloop.first %}first{% else %}{% if forloop.last %}last{% endif %}{% endif %}">
<a href="{% url pledge_modify work_id %}?premium_id={{premium.id}}">
<span class="menu-item-price">${{ premium.amount|floatformat:0|intcomma }}</span>{% if pledged.0.premium == premium %}<div class="you_pledged">Pledged!</div>{% endif %}
<span class="menu-item-price">{% if premium.amount %}${{ premium.amount|floatformat:0|intcomma }}{% else %}Any amount{% endif %}</span>{% if pledged.0.premium == premium %}<div class="you_pledged">Pledged!</div>{% endif %}
<span class="menu-item-desc">{{ premium.description }}</span>
{% ifnotequal premium.limit 0 %}<br /> Only {{ premium.premium_remaining }} remaining! {% endifnotequal %}
</a></li>

View File

@ -44,6 +44,7 @@ urlpatterns = patterns(
url(r"^work/(?P<work_id>\d+)/preview/$", "work", {'action': 'preview'}, name="work_preview"),
url(r"^work/(?P<work_id>\d+)/acks/$", "work", {'action': 'acks'}, name="work_acks"),
url(r"^work/(?P<work_id>\d+)/lockss/$", "lockss", name="lockss"),
url(r"^work/(?P<work_id>\d+)/download/$", "download", name="download"),
url(r"^work/\d+/acks/images/(?P<file_name>[\w\.]*)$", "static_redirect_view",{'dir': 'images'}),
url(r"^work/(?P<work_id>\d+)/librarything/$", "work_librarything", name="work_librarything"),
url(r"^work/(?P<work_id>\d+)/goodreads/$", "work_goodreads", name="work_goodreads"),

View File

@ -95,6 +95,16 @@ def next(request):
return response
else:
return HttpResponseRedirect('/')
def safe_get_work(work_id):
try:
work = models.Work.objects.get(id = work_id)
except models.Work.DoesNotExist:
try:
work = models.WasWork.objects.get(was = work_id).work
except models.WasWork.DoesNotExist:
raise Http404
return work
def home(request, landing=False):
if request.user.is_authenticated() and landing == False:
@ -117,15 +127,10 @@ def acks(request, work):
def work(request, work_id, action='display'):
try:
work = models.Work.objects.get(id = work_id)
except models.Work.DoesNotExist:
try:
work = models.WasWork.objects.get(was = work_id).work
except models.WasWork.DoesNotExist:
raise Http404
work = safe_get_work(work_id)
if action == "acks":
return acks( request, work)
if request.method == 'POST' and not request.user.is_anonymous():
activetab = '4'
else:
@ -136,6 +141,8 @@ def work(request, work_id, action='display'):
activetab = '1';
except:
activetab = '1';
context = {}
campaign = work.last_campaign()
if campaign and campaign.edition:
editions = [campaign.edition]
@ -147,6 +154,12 @@ def work(request, work_id, action='display'):
pledged = None
countdown = ""
try:
assert not (work.last_campaign_status() == 'ACTIVE' and work.first_ebook())
except:
logger.warning("Campaign running for %w when ebooks are already available: why?" % work.title )
if work.last_campaign_status() == 'ACTIVE':
from math import ceil
time_remaining = campaign.deadline - now()
@ -167,6 +180,8 @@ def work(request, work_id, action='display'):
countdown = "in %s minutes" % str(time_remaining.seconds/60 + 1)
else:
countdown = "right now"
context.update({ 'countdown': countdown })
if action == 'preview':
work.last_campaign_status = 'ACTIVE'
@ -174,6 +189,7 @@ def work(request, work_id, action='display'):
pubdate = work.publication_date[:4]
except IndexError:
pubdate = 'unknown'
if not request.user.is_anonymous():
claimform = UserClaimForm( request.user, data={'claim-work':work.pk, 'claim-user': request.user.id}, prefix = 'claim')
for edition in editions:
@ -192,6 +208,7 @@ def work(request, work_id, action='display'):
edition.ebook_form = EbookForm( instance= models.Ebook(user = request.user, edition = edition, provider = 'x' ), prefix = 'ebook_%d'%edition.id)
else:
claimform = None
if campaign:
# pull up premiums explicitly tied to the campaign
# mandatory premiums are only displayed in pledge process
@ -232,7 +249,6 @@ def work(request, work_id, action='display'):
'alert': alert,
'claimstatus': claimstatus,
'rights_holder_name': rights_holder_name,
'countdown': countdown,
})
def new_edition(request, work_id, edition_id, by=None):
@ -2071,14 +2087,35 @@ def campaign_archive_js(request):
return response
def lockss(request, work_id):
try:
work = models.Work.objects.get(id = work_id)
except models.Work.DoesNotExist:
try:
work = models.WasWork.objects.get(was = work_id).work
except models.WasWork.DoesNotExist:
raise Http404
work = safe_get_work(work_id)
ebook = work.ebooks().filter(unglued=True)[0]
authors = list(models.Author.objects.filter(editions__work=work).all())
return render(request, "lockss.html", {'work':work, 'ebook':ebook, 'authors':authors})
def download(request, work_id):
context = {}
work = safe_get_work(work_id)
context.update({'work': work})
unglued_ebook = work.ebooks().filter(unglued=True)
other_ebooks = work.ebooks().filter(unglued=False)
try:
ungluedcount = unglued_ebook.count()
assert (ungluedcount == 1 or ungluedcount == 0)
except:
logger.warning("There is more than one unglued edition for %w" % work.title)
try:
unglued_ebook = unglued_ebook[0]
except:
pass
context.update({
'unglued_ebook': unglued_ebook,
'other_ebooks': other_ebooks
})
return render(request, "download.html", context)

124
static/css/download.css Normal file
View File

@ -0,0 +1,124 @@
/* variables and mixins used in multiple less files go here */
.header-text {
height: 36px;
line-height: 36px;
display: block;
text-decoration: none;
font-weight: bold;
font-size: 13px;
letter-spacing: -0.05em;
}
.panelborders {
border-width: 1px 0px;
border-style: solid none;
border-color: #FFFFFF;
}
.roundedspan {
border: 1px solid #d4d4d4;
-moz-border-radius: 7px;
-webkit-border-radius: 7px;
border-radius: 7px;
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;
}
.google_signup_div {
padding: 14px 0;
}
.google_signup_div div {
height: 24px;
line-height: 24px;
float: left;
padding-left: 5px;
}
.google_signup_div img {
float: left;
height: 24px;
width: 24px;
}
.actionbuttons {
width: auto;
height: 36px;
line-height: 36px;
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: none;
margin: 5px 0;
}
.errors {
-moz-border-radius: 16px 16px 0 0;
-webkit-border-radius: 16px 16px 0 0;
border-radius: 16px 16px 0 0;
border: solid #e35351 3px;
clear: both;
width: 90%;
height: auto;
line-height: 16px;
padding: 7px 0;
font-weight: bold;
font-size: 13px;
text-align: center;
}
.errors li {
list-style: none;
border: none;
}
.ebook_download {
margin-bottom: 15px;
}
.ebook_download a {
margin: auto 5px;
font-size: 15px;
}
.ebook_download img {
vertical-align: middle;
}
.unglued {
border: solid 2px #8dc63f;
margin-left: -2px;
padding: 5px;
}
.unglued h3 {
margin-top: 5px;
}
a.add-wishlist .on-wishlist,
a.success,
a.success:hover {
text-decoration: none;
color: #3d4e53;
}
a.success,
a.success:hover {
cursor: default;
}
.download_container {
width: 50%;
margin: auto;
}

View File

@ -215,17 +215,22 @@ img {
border: none;
}
input,
textarea {
textarea,
a.fakeinput {
border: 2px solid #d6dde0;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
}
input:focus,
textarea:focus {
textarea:focus,
a.fakeinput:focus {
border: 2px solid #8dc63f;
outline: none;
}
a.fakeinput:hover {
text-decoration: none;
}
.js-search input {
-moz-border-radius: 0;
-webkit-border-radius: 0;
@ -259,7 +264,8 @@ h3.jsmod-title span {
padding: 26px 40px 27px 20px;
display: block;
}
input[type="submit"] {
input[type="submit"],
a.fakeinput {
background: #8dc63f;
color: white;
font-weight: bold;

View File

@ -4,7 +4,7 @@ $j().ready(function() {
// only do the lookup once, then cache it
var contentblock = $j('#content-block');
contentblock.on("click", "div.add-wishlist", function () {
contentblock.on("click", ".add-wishlist", function () {
var span = $j(this).find("span");
var id_val = span.attr('id').substring(1);
var id_type = span.attr('class');
@ -25,6 +25,11 @@ $j().ready(function() {
else {
span.html('a type error occurred');
}
// prevent perversities on download page
if ($j(this).is("a")) {
$j(this).removeClass("add-wishlist").addClass("success");
}
});
contentblock.on("click", "div.remove-wishlist", function() {

38
static/less/download.less Normal file
View File

@ -0,0 +1,38 @@
@import "variables.less";
.ebook_download {
a {
margin: auto 5px;
font-size: @font-size-larger;
}
img {
vertical-align: middle;
}
margin-bottom: 15px;
}
.unglued {
border: solid 2px @call-to-action;
margin-left: -2px;
padding: 5px;
h3 {
margin-top: 5px;
}
}
a.add-wishlist .on-wishlist, a.success, a.success:hover {
text-decoration: none;
color: @text-blue;
}
a.success, a.success:hover {
cursor: default;
}
.download_container {
width: 50%;
margin: auto;
}

View File

@ -122,7 +122,7 @@ img {
border:none;
}
input, textarea {
input, textarea, a.fakeinput {
border: 2px solid @blue-grey;
.one-border-radius(5px);
@ -132,6 +132,10 @@ input, textarea {
}
}
a.fakeinput:hover {
text-decoration: none;
}
.js-search input {
.one-border-radius(0);
}
@ -170,7 +174,7 @@ h3 {
}
}
input[type="submit"] {
input[type="submit"], a.fakeinput {
background: @call-to-action;
color: white;
font-weight: bold;