From: Marcin Koziej Date: Thu, 10 May 2012 09:00:48 +0000 (+0200) Subject: Merge branch 'master' of https://github.com/fnp/wolnelektury X-Git-Url: https://git.mdrn.pl/wolnelektury.git/commitdiff_plain/0c3e8f92c425a22c1b9da737db89977d31312353?hp=e64195821d0f65b6ac9a68684d038164786b1c39 Merge branch 'master' of https://github.com/fnp/wolnelektury --- diff --git a/apps/api/handlers.py b/apps/api/handlers.py index 91a3f4bb9..437b3be4c 100644 --- a/apps/api/handlers.py +++ b/apps/api/handlers.py @@ -106,7 +106,7 @@ class BookDetails(object): @classmethod def author(cls, book): - return ",".join(t[0] for t in book.related_info()['tags']['author']) + return ",".join(t[0] for t in book.related_info()['tags'].get('author', [])) @classmethod def href(cls, book): @@ -410,7 +410,7 @@ class CatalogueHandler(BaseHandler): def book_dict(book, fields=None): all_fields = ['url', 'title', 'description', 'gazeta_link', 'wiki_link', - ] + Book.formats + BookMedia.formats + [ + ] + Book.formats + BookMedia.formats.keys() + [ 'parent', 'parent_number', 'tags', 'license', 'license_description', 'source_name', diff --git a/apps/api/helpers.py b/apps/api/helpers.py index aa22465fc..acb491afc 100644 --- a/apps/api/helpers.py +++ b/apps/api/helpers.py @@ -1,8 +1,14 @@ # -*- coding: utf-8 -*- from time import mktime +from piston.resource import Resource def timestamp(dtime): "converts a datetime.datetime object to a timestamp int" return int(mktime(dtime.timetuple())) +class CsrfExemptResource(Resource): + """A Custom Resource that is csrf exempt""" + def __init__(self, handler, authentication=None): + super(CsrfExemptResource, self).__init__(handler, authentication) + self.csrf_exempt = getattr(self.handler, 'csrf_exempt', True) diff --git a/apps/api/tests.py b/apps/api/tests.py index 5a981a26a..fe8e70f62 100644 --- a/apps/api/tests.py +++ b/apps/api/tests.py @@ -1,31 +1,26 @@ # -*- coding: utf-8 -*- -from datetime import datetime +from os import path +from django.core.files.uploadedfile import SimpleUploadedFile from django.test import TestCase +from django.test.utils import override_settings from django.utils import simplejson as json -from django.conf import settings -from api.helpers import timestamp from catalogue.models import Book, Tag -from picture.tests.utils import RequestFactory from picture.forms import PictureImportForm -from picture.models import Picture, picture_storage +from picture.models import Picture import picture.tests -from django.core.files.uploadedfile import SimpleUploadedFile - - -from os import path +@override_settings( + API_WAIT=-1, + CACHES = {'api': {'BACKEND': 'django.core.cache.backends.dummy.DummyCache'}, + 'default': {'BACKEND': 'django.core.cache.backends.dummy.DummyCache'}, + 'permanent': {'BACKEND': 'django.core.cache.backends.dummy.DummyCache'}} +) class ApiTest(TestCase): - - def setUp(self): - self.old_api_wait = settings.API_WAIT - settings.API_WAIT = -1 - - def tearDown(self): - settings.API_WAIT = self.old_api_wait + pass class ChangesTest(ApiTest): diff --git a/apps/api/urls.py b/apps/api/urls.py index a22f3b772..e24c3c523 100644 --- a/apps/api/urls.py +++ b/apps/api/urls.py @@ -1,10 +1,12 @@ # -*- coding: utf-8 -*- from django.conf.urls.defaults import * -from piston.authentication import OAuthAuthentication +from django.views.decorators.csrf import csrf_exempt +from django.views.generic import TemplateView +from piston.authentication import OAuthAuthentication, oauth_access_token from piston.resource import Resource from api import handlers -from catalogue.models import Book +from api.helpers import CsrfExemptResource auth = OAuthAuthentication(realm="Wolne Lektury") @@ -12,7 +14,7 @@ book_changes_resource = Resource(handler=handlers.BookChangesHandler) tag_changes_resource = Resource(handler=handlers.TagChangesHandler) changes_resource = Resource(handler=handlers.ChangesHandler) -book_list_resource = Resource(handler=handlers.BooksHandler, authentication=auth) +book_list_resource = CsrfExemptResource(handler=handlers.BooksHandler, authentication=auth) #book_list_resource = Resource(handler=handlers.BooksHandler) book_resource = Resource(handler=handlers.BookDetailHandler) @@ -22,17 +24,16 @@ tag_resource = Resource(handler=handlers.TagDetailHandler) fragment_resource = Resource(handler=handlers.FragmentDetailHandler) fragment_list_resource = Resource(handler=handlers.FragmentsHandler) -picture_resource = Resource(handler=handlers.PictureHandler, authentication=auth) +picture_resource = CsrfExemptResource(handler=handlers.PictureHandler, authentication=auth) urlpatterns = patterns( 'piston.authentication', url(r'^oauth/request_token/$', 'oauth_request_token'), url(r'^oauth/authorize/$', 'oauth_user_auth'), - url(r'^oauth/access_token/$', 'oauth_access_token'), + url(r'^oauth/access_token/$', csrf_exempt(oauth_access_token)), ) + patterns('', - url(r'^$', 'django.views.generic.simple.direct_to_template', - {'template': 'api/main.html'}, name='api'), + url(r'^$', TemplateView.as_view(template_name='api/main.html'), name='api'), # changes handlers diff --git a/apps/catalogue/management/commands/checkcovers.py b/apps/catalogue/management/commands/checkcovers.py new file mode 100644 index 000000000..83f2fad8c --- /dev/null +++ b/apps/catalogue/management/commands/checkcovers.py @@ -0,0 +1,131 @@ +# -*- coding: utf-8 -*- +# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later. +# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. +# +from optparse import make_option +from django.contrib.sites.models import Site +from django.core.management.base import BaseCommand + + +def ancestor_has_cover(book): + while book.parent: + book = book.parent + if book.extra_info.get('cover_url'): + return True + return False + + +current_domain = Site.objects.get_current().domain +def full_url(obj): + return 'http://%s%s' % ( + current_domain, + obj.get_absolute_url()) + + +class Command(BaseCommand): + option_list = BaseCommand.option_list + ( + make_option('-q', '--quiet', action='store_false', dest='verbose', default=True, + help='Suppress output'), + ) + help = 'Checks cover sources and licenses.' + + def handle(self, **options): + from collections import defaultdict + import re + from django.db import transaction + from catalogue.models import Book + + verbose = options['verbose'] + + without_cover = [] + with_ancestral_cover = [] + by_flickr_author = defaultdict(list) + not_flickr = [] + by_license = defaultdict(list) + no_license = [] + + re_flickr = re.compile(ur'https?://(?:www.)?flickr.com/photos/([^/]*)/.*') + re_license = re.compile(ur'.*,\s*(CC.*)') + + with transaction.commit_on_success(): + for book in Book.objects.all().order_by('slug').iterator(): + extra_info = book.extra_info + if not extra_info.get('cover_url'): + if ancestor_has_cover(book): + with_ancestral_cover.append(book) + else: + without_cover.append(book) + else: + match = re_flickr.match(extra_info.get('cover_source', '')) + if match: + by_flickr_author[match.group(1)].append(book) + else: + not_flickr.append(book) + match = re_license.match(extra_info.get('cover_by', '')) + if match: + by_license[match.group(1)].append(book) + else: + no_license.append(book) + + print """%d books with no covers, %d with ancestral covers. +Licenses used: %s (%d covers without license). +Flickr authors: %s (%d covers not from flickr). +""" % ( + len(without_cover), + len(with_ancestral_cover), + ", ".join(sorted(by_license.keys())), + len(no_license), + ", ".join(sorted(by_flickr_author.keys())), + len(not_flickr), + ) + + if verbose: + print + print "By license:" + print "===========" + for lic, books in by_license.items(): + print + print lic + for book in books: + print full_url(book) + + print + print "No license:" + print "===========" + for book in no_license: + print + print full_url(book) + print book.extra_info.get('cover_by') + print book.extra_info.get('cover_source') + print book.extra_info.get('cover_url') + + print + print "By Flickr author:" + print "=================" + for author, books in by_flickr_author.items(): + print + print "author: http://flickr.com/photos/%s/" % author + for book in books: + print full_url(book) + + print + print "Not from Flickr or source missing:" + print "==================================" + for book in not_flickr: + print + print full_url(book) + print book.extra_info.get('cover_by') + print book.extra_info.get('cover_source') + print book.extra_info.get('cover_url') + + print + print "No cover:" + print "=========" + for book in without_cover: + print full_url(book) + + print + print "With ancestral cover:" + print "=====================" + for book in with_ancestral_cover: + print full_url(book) diff --git a/apps/catalogue/management/commands/checkintegrity.py b/apps/catalogue/management/commands/checkintegrity.py new file mode 100644 index 000000000..0892a7815 --- /dev/null +++ b/apps/catalogue/management/commands/checkintegrity.py @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later. +# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. +# +from optparse import make_option +from django.core.management.base import BaseCommand + +from catalogue.models import Book + + +class Command(BaseCommand): + option_list = BaseCommand.option_list + ( + make_option('-q', '--quiet', action='store_false', dest='verbose', default=True, + help='Suppress output'), + make_option('-d', '--dry-run', action='store_true', dest='dry_run', default=False, + help="Just check for problems, don't fix them"), + ) + help = 'Checks integrity of catalogue data.' + + def handle(self, **options): + from django.db import transaction + + verbose = options['verbose'] + + with transaction.commit_on_success(): + for book in Book.objects.all().iterator(): + try: + info = book.wldocument().book_info + except: + if verbose: + print "ERROR! Bad XML for book:", book.slug + print "To resolve: republish." + print + else: + should_be = [p.slug for p in info.parts] + is_now = [p.slug for p in book.children.all().order_by('parent_number')] + if should_be != is_now: + if verbose: + print "ERROR! Wrong children for book:", book.slug + print "Is: ", is_now + print "Should be:", should_be + print "To resolve: republish parent book." + print + + # Check for parent l-tags. + parents = [] + parent = book.parent + while parent: + parents.append(parent) + parent = parent.parent + ltags = [b.book_tag() for b in parents] + if set(ltags) != set(book.tags.filter(category='book')): + if options['verbose']: + print "Wrong book tags for book:", book + print "Is: ", ", ".join(sorted(t.slug for t in book.tags.filter(category='book'))) + print "Should be:", ", ".join(sorted(t.slug for t in ltags)) + if not options['dry_run']: + book.tags = ltags + list(book.tags.exclude(category='book')) + if options['verbose']: + print "Fixed." + if options['verbose']: + print + + # TODO: check metadata tags, reset counters diff --git a/apps/catalogue/management/commands/importbooks.py b/apps/catalogue/management/commands/importbooks.py index ff9184e47..b323edc49 100644 --- a/apps/catalogue/management/commands/importbooks.py +++ b/apps/catalogue/management/commands/importbooks.py @@ -21,7 +21,7 @@ class Command(BaseCommand): make_option('-q', '--quiet', action='store_false', dest='verbose', default=True, help='Verbosity level; 0=minimal output, 1=normal output, 2=all output'), make_option('-f', '--force', action='store_true', dest='force', default=False, - help='Print status messages to stdout'), + help='Overwrite works already in the catalogue'), make_option('-E', '--no-build-epub', action='store_false', dest='build_epub', default=True, help='Don\'t build EPUB file'), make_option('-M', '--no-build-mobi', action='store_false', dest='build_mobi', default=True, @@ -31,7 +31,7 @@ class Command(BaseCommand): make_option('-P', '--no-build-pdf', action='store_false', dest='build_pdf', default=True, help='Don\'t build PDF file'), make_option('-S', '--no-search-index', action='store_false', dest='search_index', default=True, - help='Don\'t build PDF file'), + help='Skip indexing imported works for search'), make_option('-w', '--wait-until', dest='wait_until', metavar='TIME', help='Wait until specified time (Y-M-D h:m:s)'), make_option('-p', '--picture', action='store_true', dest='import_picture', default=False, diff --git a/apps/catalogue/static/player/openplayer.js b/apps/catalogue/static/player/openplayer.js new file mode 100644 index 000000000..e8da79c81 --- /dev/null +++ b/apps/catalogue/static/player/openplayer.js @@ -0,0 +1,18 @@ +(function($) { + $(function() { + + + +$('.open-player').click(function(event) { + event.preventDefault(); + window.open($(this).attr('href'), + 'player', + 'width=422, height=500' + ); +}); + + + + }); +})(jQuery); + diff --git a/apps/catalogue/static/player/player.css b/apps/catalogue/static/player/player.css index c449803e5..829a9a1c0 100644 --- a/apps/catalogue/static/player/player.css +++ b/apps/catalogue/static/player/player.css @@ -15,3 +15,7 @@ .play:hover { color: #0D7E85; } + +.daisy-list { + list-style: none; +} diff --git a/apps/catalogue/templates/catalogue/book_info.html b/apps/catalogue/templates/catalogue/book_info.html index e9f351258..c5006f1ed 100755 --- a/apps/catalogue/templates/catalogue/book_info.html +++ b/apps/catalogue/templates/catalogue/book_info.html @@ -28,3 +28,9 @@

{% trans "Edited and annotated by:" %} {% all_editors book.extra_info %}.

{% endif %} + +{% if book.extra_info.cover_by %} +

{% trans "Cover image by:" %} + + {{ book.extra_info.cover_by }}.

+{% endif %} diff --git a/apps/catalogue/templates/catalogue/book_text.html b/apps/catalogue/templates/catalogue/book_text.html index 53a0c6a5f..d2d5d330e 100644 --- a/apps/catalogue/templates/catalogue/book_text.html +++ b/apps/catalogue/templates/catalogue/book_text.html @@ -1,4 +1,5 @@ {% load i18n %} +{% load url from future %} {% load static from staticfiles %} {% load chunks compressed catalogue_tags %} {% trans "Infobox" %}
  • {% trans "Book's page" %}
  • {% trans "Download" %}
  • + {% if related.media.mp3 or related.media.ogg %} +
  • + {% trans "Listen" %}
  • + {% endif %}
    @@ -35,16 +40,20 @@ {% if book.pdf_file %}
  • PDF {% trans "to print" %}
  • {% endif %} - {% if book.epub_file %} + {% if book.epub_file %}
  • EPUB {% trans "for a reader" %}
  • {% endif %} - {% if book.mobi_file %} + {% if book.mobi_file %}
  • MOBI {% trans "for Kindle" %}
  • {% endif %} - {% if book.txt_file %} + {% if book.txt_file %}
  • TXT {% trans "for advanced usage" %}
  • {% endif %} -
  • {% trans "Download a custom PDF" %}
  • + {% custom_pdf_link_li book %} + {% if related.media.mp3 or related.media.ogg or related.media.daisy %} +
  • {% trans "Download all audiobooks for this book" %}: + {% download_audio book %}
  • + {% endif %}
    diff --git a/apps/catalogue/templates/catalogue/inline_tag_list.html b/apps/catalogue/templates/catalogue/inline_tag_list.html index 52e92c443..cd48c3ea1 100755 --- a/apps/catalogue/templates/catalogue/inline_tag_list.html +++ b/apps/catalogue/templates/catalogue/inline_tag_list.html @@ -4,8 +4,14 @@ {% trans "See full category" %} {{ one_tag }} {% else %} {% endif %} diff --git a/apps/catalogue/templates/catalogue/player.html b/apps/catalogue/templates/catalogue/player.html index 7ecf3e669..f32025b83 100755 --- a/apps/catalogue/templates/catalogue/player.html +++ b/apps/catalogue/templates/catalogue/player.html @@ -1,5 +1,6 @@ + {% load static from staticfiles %} {% load i18n compressed %} {% load catalogue_tags %} {% load thumbnail %} @@ -31,10 +32,7 @@

    {% trans "Book's page" %}.

    -

    {% trans "Download as" %} - MP3{% if have_oggs %}, - Ogg Vorbis{% endif %}. -

    +

    {% trans "Download as" %} {% download_audio book False %}.

    {% if book.has_daisy_file %}

    DAISY:

    diff --git a/apps/catalogue/templates/catalogue/snippets/custom_pdf_link_li.html b/apps/catalogue/templates/catalogue/snippets/custom_pdf_link_li.html new file mode 100644 index 000000000..380844adb --- /dev/null +++ b/apps/catalogue/templates/catalogue/snippets/custom_pdf_link_li.html @@ -0,0 +1,8 @@ +{% load i18n %} +{% load url from future %} +{% if not NO_CUSTOM_PDF %} +
  • + {% trans "Download a custom PDF" %} +
  • +{% endif %} diff --git a/apps/catalogue/templatetags/catalogue_tags.py b/apps/catalogue/templatetags/catalogue_tags.py index 78ce04ab5..4f84dadca 100644 --- a/apps/catalogue/templatetags/catalogue_tags.py +++ b/apps/catalogue/templatetags/catalogue_tags.py @@ -5,6 +5,7 @@ import datetime import feedparser +from django.conf import settings from django import template from django.template import Node, Variable, Template, Context from django.core.cache import cache @@ -12,9 +13,8 @@ from django.core.urlresolvers import reverse from django.contrib.auth.forms import UserCreationForm, AuthenticationForm from django.utils.translation import ugettext as _ -from catalogue import forms from catalogue.utils import split_tags -from catalogue.models import Book, Fragment, Tag +from catalogue.models import Book, BookMedia, Fragment, Tag register = template.Library() @@ -387,3 +387,30 @@ def tag_url(category, slug): return reverse('catalogue.views.tagged_object_list', args=[ '/'.join((Tag.categories_dict[category], slug)) ]) + + +@register.simple_tag +def download_audio(book, daisy=True): + related = book.related_info() + links = [] + if related['media'].get('mp3'): + links.append("%s" % + (reverse('download_zip_mp3', args=[book.slug]), + BookMedia.formats['mp3'].name)) + if related['media'].get('ogg'): + links.append("%s" % + (reverse('download_zip_ogg', args=[book.slug]), + BookMedia.formats['ogg'].name)) + if daisy and related['media'].get('daisy'): + for dsy in book.get_media('daisy'): + links.append("%s" % + (dsy.file.url, BookMedia.formats['daisy'].name)) + return ", ".join(links) + + +@register.inclusion_tag("catalogue/snippets/custom_pdf_link_li.html") +def custom_pdf_link_li(book): + return { + 'book': book, + 'NO_CUSTOM_PDF': settings.NO_CUSTOM_PDF, + } diff --git a/apps/catalogue/views.py b/apps/catalogue/views.py index 9687db6fd..fc27e02f3 100644 --- a/apps/catalogue/views.py +++ b/apps/catalogue/views.py @@ -265,6 +265,7 @@ def book_text(request, slug): book_themes = book_themes.items() book_themes.sort(key=lambda s: s[0].sort_key) + related = book.related_info() return render_to_response('catalogue/book_text.html', locals(), context_instance=RequestContext(request)) @@ -535,6 +536,11 @@ class CustomPDFFormView(AjaxableFormView): submit = ugettext_lazy('Download') honeypot = True + def __call__(self, *args, **kwargs): + if settings.NO_CUSTOM_PDF: + raise Http404('Custom PDF is disabled') + return super(CustomPDFFormView, self).__call__(*args, **kwargs) + def form_args(self, request, obj): """Override to parse view args and give additional args to the form.""" return (obj,), {} diff --git a/apps/dictionary/urls.py b/apps/dictionary/urls.py index 435e0bd6b..1a33af966 100755 --- a/apps/dictionary/urls.py +++ b/apps/dictionary/urls.py @@ -3,10 +3,10 @@ # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. # from django.conf.urls.defaults import * - +from dictionary.views import NotesView urlpatterns = patterns('dictionary.views', - url(r'^$', 'letter_notes', name='dictionary_notes'), - url(r'(?P[a-z]|0-9)/$', 'letter_notes', name='dictionary_notes'), + url(r'^$', NotesView.as_view(), name='dictionary_notes'), + url(r'(?P[a-z]|0-9)/$', NotesView.as_view(), name='dictionary_notes'), ) diff --git a/apps/dictionary/views.py b/apps/dictionary/views.py index 47204fd42..a2a814b03 100755 --- a/apps/dictionary/views.py +++ b/apps/dictionary/views.py @@ -2,15 +2,24 @@ # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later. # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. # -from django.views.generic.list_detail import object_list from dictionary.models import Note +from django.views.generic.list import ListView -def letter_notes(request, letter=None): - letters = ["0-9"] + [chr(a) for a in range(ord('a'), ord('z')+1)] - objects = Note.objects.all() - if letter == "0-9": - objects = objects.filter(sort_key__regex=r"^[0-9]") - elif letter: - objects = objects.filter(sort_key__startswith=letter) - return object_list(request, queryset=objects, extra_context=locals()) +class NotesView(ListView): + def get_queryset(self): + self.letters = ["0-9"] + [chr(a) for a in range(ord('a'), ord('z')+1)] + self.letter = self.kwargs.get('letter') + + objects = Note.objects.all() + if self.letter == "0-9": + objects = objects.filter(sort_key__regex=r"^[0-9]") + elif self.letter: + objects = objects.filter(sort_key__startswith=self.letter) + return ListView.get_queryset(self) + + def get_context_data(self, **kwargs): + context = super(NotesView, self).get_context_data(**kwargs) + context['letter'] = self.letter + context['letters'] = self.letters + return context diff --git a/apps/newtagging/admin.py b/apps/newtagging/admin.py index 8ddfd0347..57a76d5d4 100644 --- a/apps/newtagging/admin.py +++ b/apps/newtagging/admin.py @@ -15,7 +15,7 @@ class FilteredSelectMultiple(forms.SelectMultiple): def _media(self): from django.conf import settings js = ['js/SelectBox.js' , 'js/SelectFilter2.js'] - return forms.Media(js=['%s%s' % (settings.ADMIN_MEDIA_PREFIX, url) for url in js]) + return forms.Media(js=['%sadmin/%s' % (settings.STATIC_URL, url) for url in js]) media = property(_media) def __init__(self, verbose_name, is_stacked, attrs=None, choices=()): @@ -30,7 +30,7 @@ class FilteredSelectMultiple(forms.SelectMultiple): # TODO: "id_" is hard-coded here. This should instead use the correct # API to determine the ID dynamically. output.append(u'SelectFilter.init("id_%s", "%s", %s, "%s"); });\n' % \ - (name, self.verbose_name.replace('"', '\\"'), int(self.is_stacked), settings.ADMIN_MEDIA_PREFIX)) + (name, self.verbose_name.replace('"', '\\"'), int(self.is_stacked), settings.STATIC_URL + "admin/")) return mark_safe(u''.join(output)) diff --git a/apps/search/index.py b/apps/search/index.py index b689c763c..f608a5bec 100644 --- a/apps/search/index.py +++ b/apps/search/index.py @@ -18,7 +18,7 @@ from lucene import SimpleFSDirectory, NIOFSDirectory, IndexWriter, IndexReader, # KeywordAnalyzer # Initialize jvm -JVM = initVM(CLASSPATH) +JVM = initVM(CLASSPATH, maxheap=settings.JVM_MAXHEAP) import sys import os diff --git a/apps/sponsors/static/sponsors/js/sponsors.js b/apps/sponsors/static/sponsors/js/sponsors.js index 7674379fe..fbfbaebb3 100755 --- a/apps/sponsors/static/sponsors/js/sponsors.js +++ b/apps/sponsors/static/sponsors/js/sponsors.js @@ -4,5 +4,5 @@ $('.sponsor-logos').cycle({timeout: 3000}); }); -})(jQuery) +})(jQuery); diff --git a/apps/wolnelektury_core/static/css/base.css b/apps/wolnelektury_core/static/css/base.css index 64c5de1de..5c29ef046 100755 --- a/apps/wolnelektury_core/static/css/base.css +++ b/apps/wolnelektury_core/static/css/base.css @@ -1,15 +1,3 @@ -/* Logo font */ -@font-face { - /* IE version */ - font-family: WL-Nav; - src: url(/static/fonts/WL-Nav.eot); -} -@font-face { - font-family: WL-Nav; - src: url(/static/fonts/WL-Nav.ttf) format("truetype"); -} - - html { margin: 0; padding: 0; @@ -131,8 +119,7 @@ h2 { .theme-list-link:after { padding-left: 1em; - content: "↓"; - font-family: WL-Nav; + content: url("/static/img/arrow-teal.png"); vertical-align: middle; } .theme-list-link { diff --git a/apps/wolnelektury_core/static/css/book_box.css b/apps/wolnelektury_core/static/css/book_box.css index 8dee81384..e23847fb1 100755 --- a/apps/wolnelektury_core/static/css/book_box.css +++ b/apps/wolnelektury_core/static/css/book_box.css @@ -212,8 +212,7 @@ .book-box-read a:before { - content: "\2609"; - font-family: WL-Nav; + content: url("/static/img/read.png"); font-size: 2.25em; margin-right: .15em; vertical-align: middle; @@ -221,8 +220,7 @@ } .book-box-download a.downarrow:before { - content: "\21E9"; - font-family: WL-Nav; + content: url("/static/img/download.png"); font-size: 2.25em; margin-right: .15em; vertical-align: middle; @@ -230,8 +228,7 @@ } .book-box-audiobook a:before { - content: "\266B"; - font-family: WL-Nav; + content: url("/static/img/listen.png"); font-size: 2.25em; margin-right: .15em; vertical-align: middle; diff --git a/apps/wolnelektury_core/static/css/cite.css b/apps/wolnelektury_core/static/css/cite.css index 04fdfdd9f..d397da2ee 100755 --- a/apps/wolnelektury_core/static/css/cite.css +++ b/apps/wolnelektury_core/static/css/cite.css @@ -106,7 +106,7 @@ .book-wide-box .cite { position: relative; - top: -0.8em; + top: -1em; right: -1em; background-color: #f7f7f7; vertical-align: middle; diff --git a/apps/wolnelektury_core/static/css/header.css b/apps/wolnelektury_core/static/css/header.css index 891c16318..fefb65ab0 100755 --- a/apps/wolnelektury_core/static/css/header.css +++ b/apps/wolnelektury_core/static/css/header.css @@ -163,8 +163,7 @@ a.menu span { } #lang-button:after { padding-left: 1em; - content: "↓"; - font-family: WL-Nav; + content: url("/static/img/arrow-gray.png"); vertical-align: middle; } #lang-menu { diff --git a/apps/wolnelektury_core/static/css/main_page.css b/apps/wolnelektury_core/static/css/main_page.css index cbfc3db7b..3db1655b7 100755 --- a/apps/wolnelektury_core/static/css/main_page.css +++ b/apps/wolnelektury_core/static/css/main_page.css @@ -88,8 +88,5 @@ } .infopages-box .social-links a { - font-family: WL-Nav, courier; - font-size: 3em; - color: #281d1c; - margin-right: .2em; + margin-right: .6em; } diff --git a/apps/wolnelektury_core/static/css/picture_box.css b/apps/wolnelektury_core/static/css/picture_box.css index 06f3e62c8..83022eb77 100755 --- a/apps/wolnelektury_core/static/css/picture_box.css +++ b/apps/wolnelektury_core/static/css/picture_box.css @@ -82,8 +82,7 @@ } .picture-box-tools a:before { - content: "⇩"; - font-family: WL-Nav; + content: url("/static/img/download.png"); font-size: 2em; margin-right: .25em; vertical-align: middle; diff --git a/apps/wolnelektury_core/static/img/arrow-gray.png b/apps/wolnelektury_core/static/img/arrow-gray.png new file mode 100644 index 000000000..b1c590d04 Binary files /dev/null and b/apps/wolnelektury_core/static/img/arrow-gray.png differ diff --git a/apps/wolnelektury_core/static/img/arrow-gray.svg b/apps/wolnelektury_core/static/img/arrow-gray.svg new file mode 100644 index 000000000..02d7075c3 --- /dev/null +++ b/apps/wolnelektury_core/static/img/arrow-gray.svg @@ -0,0 +1,40 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/apps/wolnelektury_core/static/img/arrow-teal.png b/apps/wolnelektury_core/static/img/arrow-teal.png new file mode 100644 index 000000000..ce406336b Binary files /dev/null and b/apps/wolnelektury_core/static/img/arrow-teal.png differ diff --git a/apps/wolnelektury_core/static/img/arrow-teal.svg b/apps/wolnelektury_core/static/img/arrow-teal.svg new file mode 100644 index 000000000..478ed07c2 --- /dev/null +++ b/apps/wolnelektury_core/static/img/arrow-teal.svg @@ -0,0 +1,41 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/apps/wolnelektury_core/static/img/download.png b/apps/wolnelektury_core/static/img/download.png new file mode 100644 index 000000000..54d1bf904 Binary files /dev/null and b/apps/wolnelektury_core/static/img/download.png differ diff --git a/apps/wolnelektury_core/static/img/download.svg b/apps/wolnelektury_core/static/img/download.svg new file mode 100644 index 000000000..cb49aa2ba --- /dev/null +++ b/apps/wolnelektury_core/static/img/download.svg @@ -0,0 +1,41 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/apps/wolnelektury_core/static/img/listen.png b/apps/wolnelektury_core/static/img/listen.png new file mode 100644 index 000000000..68627221c Binary files /dev/null and b/apps/wolnelektury_core/static/img/listen.png differ diff --git a/apps/wolnelektury_core/static/img/listen.svg b/apps/wolnelektury_core/static/img/listen.svg new file mode 100644 index 000000000..714768f54 --- /dev/null +++ b/apps/wolnelektury_core/static/img/listen.svg @@ -0,0 +1,41 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/apps/wolnelektury_core/static/img/read.png b/apps/wolnelektury_core/static/img/read.png new file mode 100644 index 000000000..1d5ab0e7b Binary files /dev/null and b/apps/wolnelektury_core/static/img/read.png differ diff --git a/apps/wolnelektury_core/static/img/read.svg b/apps/wolnelektury_core/static/img/read.svg new file mode 100644 index 000000000..f3fd5b65c --- /dev/null +++ b/apps/wolnelektury_core/static/img/read.svg @@ -0,0 +1,41 @@ + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/apps/wolnelektury_core/static/img/social/f.png b/apps/wolnelektury_core/static/img/social/f.png new file mode 100644 index 000000000..3261c6d7f Binary files /dev/null and b/apps/wolnelektury_core/static/img/social/f.png differ diff --git a/apps/wolnelektury_core/static/img/social/f.svg b/apps/wolnelektury_core/static/img/social/f.svg new file mode 100644 index 000000000..fd25a0b1e --- /dev/null +++ b/apps/wolnelektury_core/static/img/social/f.svg @@ -0,0 +1,36 @@ + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/apps/wolnelektury_core/static/img/social/facebook.png b/apps/wolnelektury_core/static/img/social/facebook.png deleted file mode 100644 index c46485acc..000000000 Binary files a/apps/wolnelektury_core/static/img/social/facebook.png and /dev/null differ diff --git a/apps/wolnelektury_core/static/img/social/gplus.png b/apps/wolnelektury_core/static/img/social/gplus.png new file mode 100644 index 000000000..c9a98cca4 Binary files /dev/null and b/apps/wolnelektury_core/static/img/social/gplus.png differ diff --git a/apps/wolnelektury_core/static/img/social/gplus.svg b/apps/wolnelektury_core/static/img/social/gplus.svg new file mode 100644 index 000000000..ad8584c48 --- /dev/null +++ b/apps/wolnelektury_core/static/img/social/gplus.svg @@ -0,0 +1,36 @@ + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/apps/wolnelektury_core/static/img/social/naszaklasa.png b/apps/wolnelektury_core/static/img/social/naszaklasa.png deleted file mode 100644 index 6fcd6d53d..000000000 Binary files a/apps/wolnelektury_core/static/img/social/naszaklasa.png and /dev/null differ diff --git a/apps/wolnelektury_core/static/img/social/nk.png b/apps/wolnelektury_core/static/img/social/nk.png new file mode 100644 index 000000000..736918565 Binary files /dev/null and b/apps/wolnelektury_core/static/img/social/nk.png differ diff --git a/apps/wolnelektury_core/static/img/social/nk.svg b/apps/wolnelektury_core/static/img/social/nk.svg new file mode 100644 index 000000000..143701f10 --- /dev/null +++ b/apps/wolnelektury_core/static/img/social/nk.svg @@ -0,0 +1,36 @@ + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/apps/wolnelektury_core/static/img/social/twitter.png b/apps/wolnelektury_core/static/img/social/twitter.png deleted file mode 100644 index 0a75ea8d7..000000000 Binary files a/apps/wolnelektury_core/static/img/social/twitter.png and /dev/null differ diff --git a/apps/wolnelektury_core/static/js/base.js b/apps/wolnelektury_core/static/js/base.js index 77315e6f7..d43f1f23e 100755 --- a/apps/wolnelektury_core/static/js/base.js +++ b/apps/wolnelektury_core/static/js/base.js @@ -97,15 +97,6 @@ $('#themes-list-toggle').click(function(event) { }); -$('.open-player').click(function(event) { - event.preventDefault(); - window.open($(this).attr('href'), - 'player', - 'width=422, height=500' - ); -}); - - $('.book-list-index').click(function(){ $('.book-list-show-index').hide('slow'); if($(this).parent().next('ul:not(:hidden)').length == 0){ diff --git a/apps/wolnelektury_core/templates/main_page.html b/apps/wolnelektury_core/templates/main_page.html index 2947a2f69..87a9c3f0c 100755 --- a/apps/wolnelektury_core/templates/main_page.html +++ b/apps/wolnelektury_core/templates/main_page.html @@ -1,4 +1,5 @@ {% extends "base.html" %} +{% load static from staticfiles %} {% load cache chunks i18n catalogue_tags infopages_tags social_tags %} @@ -67,9 +68,13 @@
    diff --git a/doc/installation.rst b/doc/installation.rst index da0a9a83c..78ca3ccbb 100644 --- a/doc/installation.rst +++ b/doc/installation.rst @@ -8,9 +8,10 @@ Requirements * `Python 2.6+ `_ * Everyting from the ``requirements.txt`` file * a library for your database of choice - (see `DBs supported by Django `_) -* `puLucene `_ for search -* Librarian dependencies, see lib/librarian/README.md + (see `DBs supported by Django `_) +* `pyLucene `_ for search +* Librarian dependencies for generating PDF and MOBI files, + see lib/librarian/README.md Installation diff --git a/fabfile.py b/fabfile.py index 84605a200..7a333c945 100644 --- a/fabfile.py +++ b/fabfile.py @@ -70,6 +70,7 @@ def deploy(): copy_localsettings() symlink_current_release() migrate() + collectstatic() restart_webserver() def deploy_version(version): @@ -160,6 +161,13 @@ def migrate(): if env.use_south: run('../../../ve/bin/python manage.py migrate' % env, pty=True) +def collectstatic(): + """Collect static files""" + print '>>> collectstatic' + require('project_name', provided_by=[staging, production]) + with cd('%(path)s/releases/current/%(project_name)s' % env): + run('../../../ve/bin/python manage.py collectstatic --noinput' % env, pty=True) + def restart_webserver(): "Restart the web server" print '>>> restart webserver' diff --git a/lib/librarian b/lib/librarian index 9e13b0c99..fed2483b3 160000 --- a/lib/librarian +++ b/lib/librarian @@ -1 +1 @@ -Subproject commit 9e13b0c994e9d481008bef7006a74609adfd16f8 +Subproject commit fed2483b39e23ecd91ec2d04495a4caac208e94c diff --git a/wolnelektury/settings/contrib.py b/wolnelektury/settings/contrib.py index ba6603b9e..654066a96 100644 --- a/wolnelektury/settings/contrib.py +++ b/wolnelektury/settings/contrib.py @@ -1 +1,4 @@ HONEYPOT_FIELD_NAME = 'miut' +PAGINATION_INVALID_PAGE_RAISES_404 = True +THUMBNAIL_QUALITY = 95 +TRANSLATION_REGISTRY = "wolnelektury.translation" diff --git a/wolnelektury/settings/custom.py b/wolnelektury/settings/custom.py index 9abb5edd3..e059b8f9a 100644 --- a/wolnelektury/settings/custom.py +++ b/wolnelektury/settings/custom.py @@ -1,19 +1,17 @@ -PAGINATION_INVALID_PAGE_RAISES_404 = True -THUMBNAIL_QUALITY = 95 -TRANSLATION_REGISTRY = "wolnelektury.translation" - - # seconds until a changes appears in the changes api API_WAIT = 10 # limit number of filtering tags MAX_TAG_LIST = 6 +NO_SEARCH_INDEX = False NO_BUILD_EPUB = False NO_BUILD_TXT = False -NO_BUILD_PDF = False -NO_BUILD_MOBI = False -NO_SEARCH_INDEX = False +# You'll need XeLaTeX to generate PDF files. +NO_BUILD_PDF = True +NO_CUSTOM_PDF = True +# You'll need Calibre installed to generate MOBI files. +NO_BUILD_MOBI = True ALL_EPUB_ZIP = 'wolnelektury_pl_epub' ALL_PDF_ZIP = 'wolnelektury_pl_pdf' @@ -31,3 +29,6 @@ CATALOGUE_CUSTOMPDF_RATE_LIMIT = '1/m' # set to 'new' or 'old' to skip time-consuming test # for TeX morefloats library version LIBRARIAN_PDF_MOREFLOATS = None + +# Max memory used by search +JVM_MAXHEAP = '256m' diff --git a/wolnelektury/settings/static.py b/wolnelektury/settings/static.py index 8dcdf8f3b..e1e859442 100644 --- a/wolnelektury/settings/static.py +++ b/wolnelektury/settings/static.py @@ -79,6 +79,7 @@ PIPELINE_JS = { 'js/base.js', 'pdcounter/pdcounter.js', 'sponsors/js/sponsors.js', + 'player/openplayer.js', 'js/search.js', ), @@ -93,7 +94,13 @@ PIPELINE_JS = { 'output_filename': 'js/player.min.js', }, 'book': { - 'source_filenames': ('js/jquery.eventdelegation.js', 'js/jquery.scrollto.js', 'js/jquery.highlightfade.js', 'js/book.js',), + 'source_filenames': [ + 'js/jquery.eventdelegation.js', + 'js/jquery.scrollto.js', + 'js/jquery.highlightfade.js', + 'js/book.js', + 'player/openplayer.js', + ], 'output_filename': 'js/book.min.js', }, 'book_ie': { diff --git a/wolnelektury/urls.py b/wolnelektury/urls.py index 5323ada9b..e501ae1d2 100644 --- a/wolnelektury/urls.py +++ b/wolnelektury/urls.py @@ -4,6 +4,7 @@ import os from django.conf.urls.defaults import * from django.conf import settings from django.contrib import admin +from django.views.generic import RedirectView import wolnelektury_core.views @@ -55,20 +56,20 @@ urlpatterns += patterns('', url(r'^i18n/', include('django.conf.urls.i18n')), ) -urlpatterns += patterns('django.views.generic.simple', +urlpatterns += patterns('', # old static pages - redirected - url(r'^1procent/$', 'redirect_to', - {'url': 'http://nowoczesnapolska.org.pl/wesprzyj_nas/'}), - url(r'^epub/$', 'redirect_to', - {'url': '/katalog/lektury/'}), - url(r'^mozesz-nam-pomoc/$', 'redirect_to', - {'url': '/info/mozesz-nam-pomoc'}), - url(r'^o-projekcie/$', 'redirect_to', - {'url': '/info/o-projekcie'}), - url(r'^widget/$', 'redirect_to', - {'url': '/info/widget'}), - url(r'^wolontariat/$', 'redirect_to', - {'url': '/info/mozesz-nam-pomoc/'}), + url(r'^1procent/$', RedirectView.as_view( + url='http://nowoczesnapolska.org.pl/wesprzyj_nas/')), + url(r'^epub/$', RedirectView.as_view( + url='/katalog/lektury/')), + url(r'^mozesz-nam-pomoc/$', RedirectView.as_view( + url='/info/mozesz-nam-pomoc')), + url(r'^o-projekcie/$', RedirectView.as_view( + url='/info/o-projekcie')), + url(r'^widget/$', RedirectView.as_view( + url='/info/widget')), + url(r'^wolontariat/$', RedirectView.as_view( + url='/info/mozesz-nam-pomoc/')), )