From: Marcin Koziej Date: Wed, 28 Dec 2011 09:14:23 +0000 (+0100) Subject: merge wyszukiwania. X-Git-Url: https://git.mdrn.pl/wolnelektury.git/commitdiff_plain/9fbf0c4158a9427442171629a564e2de7780b5b7?hp=afdd9bc42c8e08e0e2fbade6b9c934a3d65f4885 merge wyszukiwania. Merge branch 'pretty' of github.com:fnp/wolnelektury into pretty Conflicts: lib/librarian wolnelektury/templates/base.html --- diff --git a/apps/api/handlers.py b/apps/api/handlers.py index f99dd90ab..d34806f0a 100644 --- a/apps/api/handlers.py +++ b/apps/api/handlers.py @@ -16,6 +16,7 @@ from api.models import Deleted from catalogue.forms import BookImportForm from catalogue.models import Book, Tag, BookMedia, Fragment from picture.models import Picture +from picture.forms import PictureImportForm from stats.utils import piwik_track @@ -589,11 +590,11 @@ class PictureHandler(BaseHandler): allowed_methods = ('POST',) def create(self, request): - if not request.user.has_perm('catalogue.add_book'): + if not request.user.has_perm('picture.add_picture'): return rc.FORBIDDEN data = json.loads(request.POST.get('data')) - form = BookImportForm(data) + form = PictureImportForm(data) if form.is_valid(): form.save() return rc.CREATED diff --git a/apps/api/tests.py b/apps/api/tests.py index 74417acb9..5a981a26a 100644 --- a/apps/api/tests.py +++ b/apps/api/tests.py @@ -10,9 +10,10 @@ 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 +from picture.models import Picture, picture_storage import picture.tests from django.core.files.uploadedfile import SimpleUploadedFile + from os import path @@ -160,3 +161,4 @@ class PictureTests(ApiTest): import_form.save() pic = Picture.objects.get(slug=slug) + diff --git a/apps/api/urls.py b/apps/api/urls.py index 60b20647c..8f7bed3fe 100644 --- a/apps/api/urls.py +++ b/apps/api/urls.py @@ -57,13 +57,12 @@ urlpatterns = patterns( url(r'^(?P(?:(?:[a-z0-9-]+/){2}){0,6})books/$', book_list_resource), url(r'^(?P(?:(?:[a-z0-9-]+/){2}){0,6})parent_books/$', book_list_resource, {"top_level": True}), + url(r'^pictures/$', picture_resource), + # fragments by book, tags, themes # this should be paged url(r'^(?P(?:(?:[a-z0-9-]+/){2}){1,6})fragments/$', fragment_list_resource), # tags by category url(r'^(?P[a-z0-9-]+)/$', tag_list_resource), - - # picture by slug - url(r'^pictures/$', picture_resource) ) diff --git a/apps/catalogue/models.py b/apps/catalogue/models.py index a180c650c..2effb3bc7 100644 --- a/apps/catalogue/models.py +++ b/apps/catalogue/models.py @@ -515,7 +515,7 @@ class Book(models.Model): for ebook_format in self.ebook_formats: if self.has_media(ebook_format): formats.append(u'%s' % ( - "", #self.get_media(ebook_format).url, + self.get_media(ebook_format).url, ebook_format.upper() )) diff --git a/apps/catalogue/templatetags/catalogue_tags.py b/apps/catalogue/templatetags/catalogue_tags.py index 0ba4476ea..b4a3ec51a 100644 --- a/apps/catalogue/templatetags/catalogue_tags.py +++ b/apps/catalogue/templatetags/catalogue_tags.py @@ -263,6 +263,14 @@ def tag_list(tags, choices=None): one_tag = tags[0] return locals() +@register.inclusion_tag('catalogue/inline_tag_list.html') +def inline_tag_list(tags, choices=None): + if choices is None: + choices = [] + if len(tags) == 1: + one_tag = tags[0] + return locals() + @register.inclusion_tag('catalogue/book_info.html') def book_info(book): diff --git a/apps/catalogue/urls.py b/apps/catalogue/urls.py index e128c60b1..fa472c970 100644 --- a/apps/catalogue/urls.py +++ b/apps/catalogue/urls.py @@ -7,7 +7,12 @@ from catalogue.feeds import AudiobookFeed from catalogue.models import Book from picture.models import Picture -urlpatterns = patterns('catalogue.views', +urlpatterns = patterns('picture.views', + # pictures - currently pictures are coupled with catalogue, hence the url is here + url(r'^obraz/?$', 'picture_list'), + url(r'^obraz/(?P%s)/?$' % Picture.URLID_RE, 'picture_detail') + ) + \ + patterns('catalogue.views', url(r'^$', 'catalogue', name='catalogue'), url(r'^polki/(?P[a-zA-Z0-9-]+)/formaty/$', 'shelf_book_formats', name='shelf_book_formats'), url(r'^polki/(?P[a-zA-Z0-9-]+)/(?P%s)/usun$' % Book.URLID_RE, 'remove_from_shelf', name='remove_from_shelf'), @@ -41,9 +46,4 @@ urlpatterns = patterns('catalogue.views', url(r'^custompdf/(?P%s).pdf' % Book.FILEID_RE, 'download_custom_pdf'), -) + patterns('picture.views', - # pictures - currently pictures are coupled with catalogue, hence the url is here - url(r'^obraz/?$', 'picture_list'), - url(r'^obraz/(?P%s)/?$' % Picture.URLID_RE, 'picture_detail') - ) - +) diff --git a/apps/catalogue/utils.py b/apps/catalogue/utils.py index acbd778cd..145511e06 100644 --- a/apps/catalogue/utils.py +++ b/apps/catalogue/utils.py @@ -164,3 +164,33 @@ def async_build_pdf(book_id, customizations, file_name): if not DefaultStorage().exists(file_name): book.build_pdf(customizations=customizations, file_name=file_name) print "done." + + +class MultiQuerySet(object): + def __init__(self, *args, **kwargs): + self.querysets = args + self._count = None + + def count(self): + if not self._count: + self._count = sum(len(qs) for qs in self.querysets) + return self._count + + def __len__(self): + return self.count() + + def __getitem__(self, item): + indices = (offset, stop, step) = item.indices(self.count()) + items = [] + total_len = stop - offset + for qs in self.querysets: + if len(qs) < offset: + offset -= len(qs) + else: + items += list(qs[offset:stop]) + if len(items) >= total_len: + return items + else: + offset = 0 + stop = total_len - len(items) + continue \ No newline at end of file diff --git a/apps/catalogue/views.py b/apps/catalogue/views.py index 57a4975ac..c34cf29c3 100644 --- a/apps/catalogue/views.py +++ b/apps/catalogue/views.py @@ -26,11 +26,13 @@ from django.views.generic.list_detail import object_list from ajaxable.utils import LazyEncoder, JSONResponse from catalogue import models from catalogue import forms -from catalogue.utils import split_tags, AttachmentHttpResponse, async_build_pdf +from catalogue.utils import (split_tags, AttachmentHttpResponse, + async_build_pdf, MultiQuerySet) from catalogue.tasks import touch_tag from pdcounter import models as pdcounter_models from pdcounter import views as pdcounter_views from suggest.forms import PublishingSuggestForm +from picture.models import Picture from os import path @@ -88,6 +90,7 @@ def differentiate_tags(request, tags, ambiguous_slugs): def tagged_object_list(request, tags=''): + # import pdb; pdb.set_trace() try: tags = models.Tag.get_tag_list(tags) except models.Tag.DoesNotExist: @@ -166,19 +169,20 @@ def tagged_object_list(request, tags=''): only_author = len(tags) == 1 and tags[0].category == 'author' objects = models.Book.objects.none() - return object_list( - request, - objects, - template_name='catalogue/tagged_object_list.html', - extra_context={ + # Add pictures + objects = MultiQuerySet(Picture.tagged.with_all(tags), objects) + + return render_to_response('catalogue/tagged_object_list.html', + { + 'object_list': objects, 'categories': categories, 'only_shelf': only_shelf, 'only_author': only_author, 'only_my_shelf': only_my_shelf, 'formats_form': forms.DownloadFormatsForm(), 'tags': tags, - } - ) + }, + context_instance=RequestContext(request)) def book_fragments(request, book, theme_slug): diff --git a/apps/picture/forms.py b/apps/picture/forms.py index ad5096bf5..9d0c5a54b 100644 --- a/apps/picture/forms.py +++ b/apps/picture/forms.py @@ -6,9 +6,11 @@ from picture.models import Picture class PictureImportForm(forms.Form): picture_xml_file = forms.FileField(required=False) picture_xml = forms.CharField(required=False) - picture_image_file = forms.FileField(required=True) + picture_image_file = forms.FileField(required=False) + picture_image_data = forms.CharField(required=False) def clean(self): + from base64 import b64decode from django.core.files.base import ContentFile if not self.cleaned_data['picture_xml_file']: @@ -17,6 +19,15 @@ class PictureImportForm(forms.Form): ContentFile(self.cleaned_data['picture_xml'].encode('utf-8')) else: raise forms.ValidationError(_("Please supply an XML.")) + + if not self.cleaned_data['picture_image_file']: + if self.cleaned_data['picture_image_data']: + self.cleaned_data['picture_image_file'] = \ + ContentFile(b64decode( + self.cleaned_data['picture_image_data'])) + else: + raise forms.ValidationError(_("Please supply an image.")) + return super(PictureImportForm, self).clean() def save(self, commit=True, **kwargs): diff --git a/apps/picture/models.py b/apps/picture/models.py index 6ac54fe82..862c172c2 100644 --- a/apps/picture/models.py +++ b/apps/picture/models.py @@ -5,7 +5,11 @@ from sorl.thumbnail import ImageField from django.conf import settings from django.core.files.storage import FileSystemStorage from django.utils.datastructures import SortedDict -from librarian import dcparser, picture +from django.template.loader import render_to_string +from django.core.cache import cache +from catalogue.utils import split_tags +from django.utils.safestring import mark_safe +from slughifi import slughifi from django.utils.translation import ugettext_lazy as _ from newtagging import managers @@ -50,6 +54,9 @@ class Picture(models.Model): ret = super(Picture, self).save(force_insert, force_update) + if reset_short_html: + self.reset_short_html() + return ret def __unicode__(self): @@ -66,17 +73,33 @@ class Picture(models.Model): def from_xml_file(cls, xml_file, image_file=None, overwrite=False): """ Import xml and it's accompanying image file. + If image file is missing, it will be fetched by librarian.picture.ImageStore + which looks for an image file in the same directory the xml is, with extension matching + its mime type. """ + from sortify import sortify from django.core.files import File - from librarian.picture import WLPicture + from librarian.picture import WLPicture, ImageStore close_xml_file = False + close_image_file = False + # class SimpleImageStore(object): + # def path(self_, slug, mime_type): + # """Returns the image file. Ignores slug ad mime_type.""" + # return image_file + + if image_file is not None and not isinstance(image_file, File): + image_file = File(open(image_file)) + close_image_file = True if not isinstance(xml_file, File): xml_file = File(open(xml_file)) close_xml_file = True + try: # use librarian to parse meta-data - picture_xml = WLPicture.from_file(xml_file) + picture_xml = WLPicture.from_file(xml_file, + image_store=ImageStore(picture_storage.path('images'))) + # image_store=SimpleImageStore picture, created = Picture.objects.get_or_create(slug=picture_xml.slug) if not created and not overwrite: @@ -84,13 +107,25 @@ class Picture(models.Model): picture.title = picture_xml.picture_info.title - picture.tags = catalogue.models.Tag.tags_from_info(picture_xml.picture_info) + motif_tags = set() + for part in picture_xml.partiter(): + for motif in part['themes']: + tag, created = catalogue.models.Tag.objects.get_or_create(slug=slughifi(motif), category='theme') + if created: + tag.name = motif + tag.sort_key = sortify(tag.name) + tag.save() + motif_tags.add(tag) + + picture.tags = catalogue.models.Tag.tags_from_info(picture_xml.picture_info) + \ + list(motif_tags) if image_file is not None: img = image_file else: img = picture_xml.image_file() + # FIXME: hardcoded extension picture.image_file.save(path.basename(picture_xml.image_path), File(img)) picture.xml_file.save("%s.xml" % picture.slug, File(xml_file)) @@ -98,6 +133,8 @@ class Picture(models.Model): finally: if close_xml_file: xml_file.close() + if close_image_file: + image_file.close() return picture @classmethod @@ -130,6 +167,35 @@ class Picture(models.Model): @property def info(self): if not hasattr(self, '_info'): + from librarian import dcparser + from librarian import picture info = dcparser.parse(self.xml_file.path, picture.PictureInfo) self._info = info return self._info + + def reset_short_html(self): + if self.id is None: + return + + cache_key = "Picture.short_html/%d" % (self.id) + cache.delete(cache_key) + + def short_html(self): + if self.id: + cache_key = "Picture.short_html/%d" % (self.id) + short_html = cache.get(cache_key) + else: + short_html = None + + if short_html is not None: + return mark_safe(short_html) + else: + tags = self.tags.filter(category__in=('author', 'kind', 'epoch')) + tags = split_tags(tags) + + short_html = unicode(render_to_string('picture/picture_short.html', + {'picture': self, 'tags': tags})) + + if self.id: + cache.set(cache_key, short_html, catalogue.models.CACHE_FOREVER) + return mark_safe(short_html) diff --git a/apps/picture/templates/admin/picture/picture/change_list.html b/apps/picture/templates/admin/picture/picture/change_list.html new file mode 100755 index 000000000..e150da51e --- /dev/null +++ b/apps/picture/templates/admin/picture/picture/change_list.html @@ -0,0 +1,11 @@ +{% extends "admin/change_list.html" %} +{% load i18n %} + +{% block content %} +
+

XML:
+ {% trans "Image" %}:
+

+
+ {{ block.super }} +{% endblock content %} \ No newline at end of file diff --git a/apps/picture/tests/__init__.py b/apps/picture/tests/__init__.py index e69de29bb..8817a1c18 100644 --- a/apps/picture/tests/__init__.py +++ b/apps/picture/tests/__init__.py @@ -0,0 +1 @@ +from picture.tests.picture_import import * diff --git a/apps/picture/tests/files/kandinsky-composition-viii.xml b/apps/picture/tests/files/kandinsky-composition-viii.xml index 036bdf7e1..d9e79cbed 100644 --- a/apps/picture/tests/files/kandinsky-composition-viii.xml +++ b/apps/picture/tests/files/kandinsky-composition-viii.xml @@ -19,16 +19,17 @@ 1940 Image image/png - 1090 x 755 px + 1090 x 755 px + 122b590510ce70cc80e617557f82048ce20f1d7b 1923 eng - +
- +
diff --git a/apps/picture/tests/picture_import.py b/apps/picture/tests/picture_import.py new file mode 100644 index 000000000..91fb35f71 --- /dev/null +++ b/apps/picture/tests/picture_import.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +from __future__ import with_statement + +from django.core.files.base import ContentFile, File +from catalogue.test_utils import * +from catalogue import models +from librarian import WLURI +from picture.models import Picture + +from nose.tools import raises +import tempfile +from os import unlink, path, makedirs + + +class PictureTest(TestCase): + + def test_import(self): + picture = Picture.from_xml_file(path.join(path.dirname(__file__), "files/kandinsky-composition-viii.xml")) + + motifs = set([tag.name for tag in picture.tags if tag.category == 'theme']) + assert motifs == set([u'nieporządek']), 'theme tags are wrong. %s' % motifs + + picture.delete() + + def test_import_with_explicit_image(self): + picture = Picture.from_xml_file(path.join(path.dirname(__file__), "files/kandinsky-composition-viii.xml"), + path.join(path.dirname(__file__), "files/kandinsky-composition-viii.png")) + + picture.delete() + diff --git a/apps/picture/views.py b/apps/picture/views.py index c5be3bea3..24457e297 100644 --- a/apps/picture/views.py +++ b/apps/picture/views.py @@ -1,4 +1,5 @@ from picture.models import Picture +from django.contrib.auth.decorators import permission_required from django.utils.datastructures import SortedDict from django.shortcuts import render_to_response, get_object_or_404 from django.template import RequestContext @@ -29,3 +30,29 @@ def picture_detail(request, picture): return render_to_response("catalogue/picture_detail.html", locals(), context_instance=RequestContext(request)) + +# ========= +# = Admin = +# ========= +@permission_required('picture.add_picture') +def import_picture(request): + """docstring for import_book""" + from django.http import HttpResponse + from picture.forms import PictureImportForm + from django.utils.translation import ugettext as _ + + import_form = PictureImportForm(request.POST, request.FILES) + if import_form.is_valid(): + try: + import_form.save() + except: + import sys + import pprint + import traceback + info = sys.exc_info() + exception = pprint.pformat(info[1]) + tb = '\n'.join(traceback.format_tb(info[2])) + return HttpResponse(_("An error occurred: %(exception)s\n\n%(tb)s") % {'exception':exception, 'tb':tb}, mimetype='text/plain') + return HttpResponse(_("Picture imported successfully")) + else: + return HttpResponse(_("Error importing file: %r") % import_form.errors) diff --git a/apps/reporting/templates/reporting/main.html b/apps/reporting/templates/reporting/main.html index c629f105c..3960e79b7 100755 --- a/apps/reporting/templates/reporting/main.html +++ b/apps/reporting/templates/reporting/main.html @@ -14,10 +14,10 @@ - - - + + + {% for mt in media_types %} diff --git a/apps/reporting/templatetags/reporting_stats.py b/apps/reporting/templatetags/reporting_stats.py index dceee0001..6f20c087c 100755 --- a/apps/reporting/templatetags/reporting_stats.py +++ b/apps/reporting/templatetags/reporting_stats.py @@ -49,11 +49,11 @@ def count_books_all(): return Book.objects.all().count() @register_counter -def count_books_nonempty(): +def count_books(): return Book.objects.exclude(html_file='').count() @register_counter -def count_books_empty(): +def count_books_parent(): return Book.objects.filter(html_file='').count() @register_counter diff --git a/lib/librarian b/lib/librarian index 5b407667c..5fed78856 160000 --- a/lib/librarian +++ b/lib/librarian @@ -1 +1 @@ -Subproject commit 5b407667ca47cf4d9752821fd49e5611737146d2 +Subproject commit 5fed78856949474a36bc5e268517775a9a802e27 diff --git a/wolnelektury/settings.py b/wolnelektury/settings.py index fe2572904..f01ab182f 100644 --- a/wolnelektury/settings.py +++ b/wolnelektury/settings.py @@ -172,6 +172,7 @@ COMPRESS_CSS = { 'css/header.css', 'css/main_page.css', 'css/dialogs.css', + 'css/picture_box.css', 'css/book_box.css', 'css/catalogue.css', 'css/sponsors.css', @@ -206,6 +207,7 @@ COMPRESS_JS = { 'js/locale.js', 'js/dialogs.js', 'js/sponsors.js', + 'js/base.js', 'js/pdcounter.js', 'js/search.js', diff --git a/wolnelektury/static/css/base.css b/wolnelektury/static/css/base.css index 35aed2ea8..f55a39e01 100755 --- a/wolnelektury/static/css/base.css +++ b/wolnelektury/static/css/base.css @@ -18,16 +18,32 @@ html { body { margin: 0; background: #f7f7f7; - font-size: .9em; - line-height: 1.4em; + font-size: .625em; + font-family: Georgia; + /*line-height: 1.4em;*/ } a { - color: #02adb7; + color: #01adba; text-decoration: none; } +h1 { + font-size: 3.5em; + font-weight: normal; + margin-top: .4em +} + +.left-column { + width: 48em; + float: left; +} +.right-column { + float:right; + width: 48em; +} + h2 { margin: 0; font-size: 1em; @@ -35,15 +51,8 @@ h2 { } -.grid-line { - height: 2.6em; - padding-top: 1.4em; - padding-bottom: 0; -} - -.mono, .mono-small { +.mono { font-family: "Lucida Sans Typewriter", courier; - font-size: .9em; } @@ -52,15 +61,88 @@ h2 { } #header-content, div#main-content, div#half-header-content { - width: 75em; + width: 97.5em; margin: auto; } +.page-desc { + margin-left: 1.5em; +} +.inline-tag-lists { + font-size: 1.1em; +} +#themes-list-toggle:after { + padding-left: 1em; + content: "↓"; + font-family: WL-Nav; + vertical-align: middle; +} +#themes-list-wrapper { + position: relative; +} +#themes-list { + position: absolute; + display: none; + border: 1px solid #ddd; + padding: 1em; + background: #fff; + -moz-box-shadow: 2px 2px 2px #ddd; + -webkit-box-shadow: 2px 2px 2px #ddd; + box-shadow: 2px 2px 2px #ddd; +} +#themes-list ul { + list-style: none; + padding: 0; + margin: 0; + font-size: 1.1em; + -moz-column-width: 12em; + width: 48em; +} + + +a.cite { + display: block; + color: black; + background: white; + padding: 3em 2em .1em 8em; +} +.cite-body { + font-size: 1.8em; + line-height: 1.3em; +} +.cite p { + color: #444; + font-size: 1.1em; + margin-top: 1.6em; +} + +.see-also { + margin-left: 8em; + float: left; + width: 14.3em; +} +.download { + margin-left: 2em; + float: left; +} + +.see-also, .download { + margin-top: 2em; + margin-bottom: 2em; +} +.see-also h2, .download h2 { + font-size: 1.1em; +} +.see-also ul, .download ul { + list-style: none; + padding: 0; + margin: 0; + font-size: 1.1em; +} #footer { - font-size: .75em; color: #777; border-top: 1px solid #ddd; margin-top: 2.5em; diff --git a/wolnelektury/static/css/book_box.css b/wolnelektury/static/css/book_box.css index 2faa1a2d8..ca2e72696 100755 --- a/wolnelektury/static/css/book_box.css +++ b/wolnelektury/static/css/book_box.css @@ -6,11 +6,11 @@ .book-box { - width: 37.5em; + width: 48.75em; } .book-mini-box { - width: 12.5em; + width: 16.15em; } .book-mini-box a, .book-box-inner { @@ -18,69 +18,97 @@ color: black; border: 1px solid #ddd; height: 20em; - padding: .75em; + padding: .8em 1em; margin: .1em; background: #fff; -moz-box-shadow: 2px 2px 2px #ddd; -webkit-box-shadow: 2px 2px 2px #ddd; box-shadow: 2px 2px 2px #ddd; - overflow: hidden; } .book-mini-box a { - height: 20em; + height: 27.1em; margin: .1em; + overflow: hidden; } .book-box-inner { - height: 14.4em; + height: 19.75em; margin: .5em; } .book-mini-box img, .book-box img { - width: 10.8em; - height: 14.4em; + width: 13.9em; + height: 19.3em; } .book-mini-box img { - margin-bottom: .3em; + margin-bottom: 1.8em; } .book-box img { float: left; margin-right: 1.5em; } +.book-mini-box .desc { + margin-left:0em; +} .book-mini-box .author { + font-size: 1.1em; color: #777; + display: block; +} +.book-mini-box .title { + font-size: 1.4em; } .book-box-body { - height: 13em; + height: 17em; overflow: hidden; } .book-box-head { min-height: 7em; + margin-top: 1.4em; + margin-bottom: 1em; +} +.book-box-head .author { + font-size: 1.1em; +} +.book-box-head .title { + font-size: 2.4em; + margin-top: .3em; +} +.book-box-body .tags { + font-size: 1.1em; } .book-box-tag { - font-size: .8em; margin-right: .5em; + margin-left: .4em; } .book-box-download { position: relative; } .book-box-formats { display: none; - top: -2em; position: absolute; - height: 2em; - width: 100em; + + border: 1px solid #ddd; + padding: .8em 1em; + background: #fff; + -moz-box-shadow: 2px 2px 2px #ddd; + -webkit-box-shadow: 2px 2px 2px #ddd; + box-shadow: 2px 2px 2px #ddd; + } .book-box-formats a { - margin-right: 1em; + display: block; } .book-box-download:hover .book-box-formats { display: block; } +.book-box-tools { + font-size: 1.1em; +} .book-box-tools a:before { content: "⇩"; font-family: WL-Nav; @@ -89,11 +117,11 @@ vertical-align: middle; } .book-box-read { - width: 10em; + width: 11em; } .book-box-download { - width: 6em; + width: 8em; } .book-box-audiobook { - width: 6em; + width: 8em; } diff --git a/wolnelektury/static/css/header.css b/wolnelektury/static/css/header.css index 9e81463df..79e8815d6 100755 --- a/wolnelektury/static/css/header.css +++ b/wolnelektury/static/css/header.css @@ -11,11 +11,15 @@ #header { + height: 3em; + padding-top: 1.9em; + padding-bottom: 0; color: #969696; background: #191919; } #half-header { + padding-bottom: 0; background: url('/static/img/bg-header.png'); background-position: center; background-size: 100%; @@ -33,43 +37,45 @@ #logo { position: absolute; - top: 4em; + top: 1.9em; + margin-left: 1.6em; } #logo a { font-family: WL-Logo; - font-size: 1.9em; + font-size: 2.05em; color:#f7f7f7; } -#logo img { - max-width: 15em; -} - #tagline { display: inline-block; - margin-left: 16em; + margin-left: 24em; +} +#tagline span { + font-size: 1.1em; } -#search { +#search-area { margin: 0; background: #444; - margin-left: 16em; - width: 59em; + margin-left: 24em; + width: 73.5em; } #search-field { display: inline-block; - width: 50em; - padding-left: .5; - padding-right: .5; - padding: .1em .5em 0 .5em; + width: 63.1em; + padding-left: .5em; + padding-right: .5em; + padding-top: 0; + padding-bottom: 0; } #search-field input { - height: 2.8em; + padding: 0; + height: 3.3em; border: none; - width: 49.5em; + width: 62.6em; font-size: 1em; padding-left: .5em; -webkit-border-radius: .5em; @@ -85,12 +91,11 @@ background: #02adb7; padding: 0; margin: 0; - width: 8em; + width: 9.4em; } #search-button button { font-size: 1em; - /* should match grid-line */ - height: 4em; + height: 4.5em; border: none; background: #02adb7; color: white; @@ -99,20 +104,20 @@ } #search-button button span { + font-size: 1.1em; position:relative; - top: -.2em; } #nav-line { background-color: #e2e2e2; - height: 3.95em; + height: 4.9em; } ul#catalogue { list-style: none; padding: 0; - margin: 0; + margin: 0 0 0 .6em; } ul#catalogue li { background-color: #e2e2e2; @@ -120,17 +125,22 @@ ul#catalogue li { } ul#catalogue a { display: block; - padding-left: 1.5em; - padding-right: 1.5em; + padding-left: 1.4em; + padding-right: 1.4em; /* must match grid-line */ - height: 2.7em; - padding-top: 1.3em; + height: 3.1em; + padding-top: 1.8em; +} +ul#catalogue span { + font-size: 1.1em; } - +#lang-button { + color: #aaa; +} #lang-button:after { - padding-left: .5em; + padding-left: 1em; content: "↓"; font-family: WL-Nav; vertical-align: middle; @@ -139,18 +149,18 @@ ul#catalogue a { position: relative; float: right; display: block; - padding-left: 1.5em; - padding-right: 1.5em; + padding-left: 2.5em; + padding-right: 2em; /* must match grid-line */ - height: 2.7em; - padding-top: 1.3em; + height: 3em; + padding-top: 1.9em; background: #f7f7f7; } #lang-menu-items button { display: none; background: #f7f7f7; - color: #444; + color: #777; cursor: pointer; width: 100%; border: solid #ddd; @@ -173,5 +183,5 @@ ul#catalogue a { } #lang-menu .active { - font-weight: bold; + color: #000; } diff --git a/wolnelektury/static/css/main_page.css b/wolnelektury/static/css/main_page.css index 94401cb51..d2ee5d4ff 100755 --- a/wolnelektury/static/css/main_page.css +++ b/wolnelektury/static/css/main_page.css @@ -1,6 +1,6 @@ #big-cite { background-color: white; - padding: 4em 12em; + padding: 10.75em 10em 8.5em 18.2em; margin: 0; } @@ -11,68 +11,101 @@ #big-cite h2 { margin: 0; + font-size: 1.1em; } #big-cite-text { - margin: .5em 0; - font-size: 1.75em; - line-height: 1.3em; + margin: .05em; + font-size: 2.8em; + line-height: 1.2em; } #big-cite-source { color: #02adb7; margin: 0; + font-size: 1.1em; + margin: 1.1em 0.2em; } #promo-box { float: right; - width: 24em; - /* should match grid-line */ - margin-top: -4em; + width: 32em; + margin-top: -5.1em; } #promo-box-header { - padding-left: 2em; - padding-right: 2em; + padding-top: 2em; + height: 3.1em; + padding-bottom: 0; + padding-left: 2.5em; + padding-right: 2.5em; background: #191919; color: white; } +#promo-box-header h2 { + font-size: 1.1em; + padding-top: .1em; +} #promo-box-body { border-bottom: 2px solid #efefef; - padding: 1.3em 2em; - height: 23em; + padding: 2em 2.8em; + height: 30em; background: #efefef; } #promo-box-title { color: #02ADB7; - height: 2.7em; + height: 2.75em; margin: 0; } +#promo-box-title span { + font-size: 1.1em; +} #promo-box-body p { margin-top: 0; } +#promo-box-content { + font-size: 1.2em; + line-height: 1.55em; + color: #666; +} + +.main-last { + padding-top: 1.9em; + height: 3.2em; + padding-left: 1.9em; +} +.main-last span { + font-size: 1.1em; +} + .infopages-box { - width: 16.75em; + width: 20.6em; display: inline-block; margin: .5em 0 0 0; - padding: 0 1em; + padding: 0 1.7em; vertical-align: top; } .infopages-box h2 { color: #02ADB7; + height: 2.8em; + padding-top: 2.5em; +} +.infopages-box h2 span { + font-size: 1.1em; } .infopages-box a { color: black; } .infopages-box ol, .infopages-box ul { - font-size: .8em; + font-size: 1.1em; list-style: none; padding: 0; margin: 0; + line-height: 1.45em; } .social-links { diff --git a/wolnelektury/static/css/picture_box.css b/wolnelektury/static/css/picture_box.css new file mode 100755 index 000000000..06f3e62c8 --- /dev/null +++ b/wolnelektury/static/css/picture_box.css @@ -0,0 +1,90 @@ +.picture-mini-box, .picture-box { + display: inline-block; + margin: 0; + vertical-align: top; +} + + +.picture-box { + width: 37.5em; +} + +.picture-mini-box { + width: 12.5em; +} + +.picture-mini-box a, .picture-box-inner { + display: block; + color: black; + border: 1px solid #ddd; + height: 20em; + padding: .75em; + margin: .1em; + background: #fff; + -moz-box-shadow: 2px 2px 2px #ddd; + -webkit-box-shadow: 2px 2px 2px #ddd; + box-shadow: 2px 2px 2px #ddd; + overflow: hidden; +} + +.picture-mini-box a { + height: 20em; + margin: .1em; +} +.picture-box-inner { + height: 14.4em; + margin: .5em; +} + +.picture-mini-box img, .picture-box img { + width: 10.8em; + height: 14.4em; +} +.picture-mini-box img { + margin-bottom: .3em; +} +.picture-box img { + float: left; + margin-right: 1.5em; +} + +.picture-mini-box .author { + color: #777; +} + + +.picture-box-body { + height: 13em; + overflow: hidden; +} +.picture-box-head { + min-height: 7em; +} +.picture-box-tag { + font-size: .8em; + margin-right: .5em; +} +.picture-box-download { + position: relative; +} +.picture-box-formats { + display: none; + top: -2em; + position: absolute; + height: 2em; + width: 100em; +} +.picture-box-formats a { + margin-right: 1em; +} +.picture-box-download:hover .picture-box-formats { + display: block; +} + +.picture-box-tools a:before { + content: "⇩"; + font-family: WL-Nav; + font-size: 2em; + margin-right: .25em; + vertical-align: middle; +} diff --git a/wolnelektury/static/js/base.js b/wolnelektury/static/js/base.js new file mode 100755 index 000000000..b5693830b --- /dev/null +++ b/wolnelektury/static/js/base.js @@ -0,0 +1,13 @@ +(function($) { + $(function() { + + +$('#themes-list-toggle').click(function(event) { + event.preventDefault(); + $('#themes-list').toggle('slow'); +}); + + + }); +})(jQuery) + diff --git a/wolnelektury/static/js/search.js b/wolnelektury/static/js/search.js index e58d37256..c41a672d0 100644 --- a/wolnelektury/static/js/search.js +++ b/wolnelektury/static/js/search.js @@ -42,7 +42,7 @@ var __bind = function (self, fn) { }); $(function() { - $("#search input[name=q]").search(); + $("#search-area input[name=q]").search(); }); diff --git a/wolnelektury/templates/base.html b/wolnelektury/templates/base.html index d1bf19e8a..48f13adb2 100644 --- a/wolnelektury/templates/base.html +++ b/wolnelektury/templates/base.html @@ -2,6 +2,7 @@ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> {% load i18n compressed catalogue_tags sponsor_tags %} + {% load reporting_stats %} @@ -20,7 +21,7 @@ {% block bodycontent %} - diff --git a/wolnelektury/templates/catalogue/book_short.html b/wolnelektury/templates/catalogue/book_short.html index 1b6466648..c80efff91 100644 --- a/wolnelektury/templates/catalogue/book_short.html +++ b/wolnelektury/templates/catalogue/book_short.html @@ -25,22 +25,19 @@
{% spaceless %} - {% trans "Epoch" %}:  - + {% trans "Epoch" %}:  {% for tag in tags.epoch %} {{ tag.name }} {% endfor %} - {% trans "Kind" %}:  - + {% trans "Kind" %}:  {% for tag in tags.kind %} {{ tag.name }} {% endfor %} - {% trans "Genre" %}:  - + {% trans "Genre" %}:  {% for tag in tags.genre %} {{ tag.name }} {% endfor %} @@ -52,7 +49,7 @@
  • {% if book.html_file %} - {% trans "Read online" %} + {% trans "Read online" %} {% endif %}
  • diff --git a/wolnelektury/templates/catalogue/differentiate_tags.html b/wolnelektury/templates/catalogue/differentiate_tags.html index b40d3fe97..f3bddd397 100644 --- a/wolnelektury/templates/catalogue/differentiate_tags.html +++ b/wolnelektury/templates/catalogue/differentiate_tags.html @@ -17,11 +17,4 @@
{% endfor %} - -
- -
-

* {% trans "Loading" %}

-
-
{% endblock %} \ No newline at end of file diff --git a/wolnelektury/templates/catalogue/inline_tag_list.html b/wolnelektury/templates/catalogue/inline_tag_list.html new file mode 100755 index 000000000..d42f3f945 --- /dev/null +++ b/wolnelektury/templates/catalogue/inline_tag_list.html @@ -0,0 +1,9 @@ +{% load i18n %} +{% load catalogue_tags %} +{% if one_tag %} + {% trans "See full category" %} {{ one_tag }} +{% else %} + {% for tag in tags %} + {{ tag }} ({{ tag.book_count }}) + {% endfor %} +{% endif %} diff --git a/wolnelektury/templates/catalogue/picture_detail.html b/wolnelektury/templates/catalogue/picture_detail.html index f4aabb456..b8b70c6be 100644 --- a/wolnelektury/templates/catalogue/picture_detail.html +++ b/wolnelektury/templates/catalogue/picture_detail.html @@ -22,7 +22,7 @@ {% thumbnail picture.image_file "400x500" upscale="false" as im %} - + {% endthumbnail %} {% if picture.info.license %} @@ -32,7 +32,7 @@ {% if picture.info.description %}
{{ picture.info.description|safe }}
-
{{ picture.info.description|safe|truncatewords_html:30 }}
+{%comment%}
{{ picture.info.description|safe|truncatewords_html:30 }}
{%endcomment%}

{% endif %} @@ -91,10 +91,4 @@
-
- -
-

* {% trans "Loading" %}

-
-
{% endblock %} diff --git a/wolnelektury/templates/catalogue/tagged_object_list.html b/wolnelektury/templates/catalogue/tagged_object_list.html index 7cae9ebed..fce00dcbd 100644 --- a/wolnelektury/templates/catalogue/tagged_object_list.html +++ b/wolnelektury/templates/catalogue/tagged_object_list.html @@ -7,53 +7,94 @@ {% block bodyid %}tagged-object-list{% endblock %} {% block body %} +
+

{% title_from_tags tags %}

- {% if only_shelf and not object_list %} -
-

{% trans "Your shelf is empty" %}

-

{% trans "You can put a book on a shelf by entering page of the reading and clicking 'Put on the shelf'." %}

+ {% with tags|last as last_tag %} + {% if last_tag.has_description %} +
+
{{ last_tag.description|safe }}
+
{{ last_tag.description|safe|truncatewords_html:30 }}
+
+
+

+ {% endif %} + + +
+ {% if categories.author %} +

{% trans "Authors" %}: + {% inline_tag_list categories.author tags %} +

+ {% endif %} + {% if categories.kind %} +

{% trans "Kinds" %}: + {% inline_tag_list categories.kind tags %} +

+ {% endif %} + {% if categories.genre %} +

{% trans "Genres" %}: + {% inline_tag_list categories.genre tags %} +

+ {% endif %} + {% if categories.epoch %} +

{% trans "Epochs" %}: + {% inline_tag_list categories.epoch tags %} +

+ {% endif %}
- {% else %} - {% autopaginate object_list 10 %} -
- {% with tags|last as last_tag %} - {% if last_tag.has_description %} -
-
{{ last_tag.description|safe }}
-
{{ last_tag.description|safe|truncatewords_html:30 }}
-
-
-

- {% endif %} - {% if only_shelf %} - - {% trans "Download all books from this shelf" %} - - + + + + +
+ + + + + {% autopaginate object_list 10 %} + {% if object_list %} {% comment %} If we didn't find anything there will be nothing on the right side as well {% endcomment %} - {% endif %} - {% endif %} -
- -
-

* {% trans "Loading" %}

-
-
{% endblock %} diff --git a/wolnelektury/templates/info/join_us.html b/wolnelektury/templates/info/join_us.html index 415b13afc..1b980516d 100644 --- a/wolnelektury/templates/info/join_us.html +++ b/wolnelektury/templates/info/join_us.html @@ -1,7 +1,7 @@ {% load i18n %} {% load reporting_stats %} -{% count_books_nonempty book_count %} +{% count_books book_count %}

{% blocktrans count book_count as c %} We have {{c}} work published in Wolne Lektury! diff --git a/wolnelektury/templates/main_page.html b/wolnelektury/templates/main_page.html index ddb90facb..2a63ed57c 100755 --- a/wolnelektury/templates/main_page.html +++ b/wolnelektury/templates/main_page.html @@ -25,20 +25,24 @@

Trwa konkurs

-

Konkurs poezji automatycznej

+

Konkurs poezji automatycznej

+

Znacie Leśmianatora? To niewielki skrypt miskujący na życzenie wiersze z Wolnych Lektur.

+
-

Ostatnie publikacje

+

Ostatnie publikacje

{% for book in last_published %} {{ book.mini_box }} {% endfor %} +
+
-

Aktualności

+

Aktualności

{% cache 1800 latest-blog-posts %} {% latest_blog_posts "http://nowoczesnapolska.org.pl/category/wolne-lektury/feed/" %} {% endcache %} @@ -46,7 +50,7 @@
-

Narzędzia

+

Narzędzia

  • {% trans "Report a bug or suggestion" %}
  • @@ -61,7 +65,7 @@
    -

    Informacje

    +

    Informacje

    {% infopages_on_main %} diff --git a/wolnelektury/templates/picture/picture_short.html b/wolnelektury/templates/picture/picture_short.html new file mode 100644 index 000000000..1f6a4c0e0 --- /dev/null +++ b/wolnelektury/templates/picture/picture_short.html @@ -0,0 +1,42 @@ +{% load i18n %} +{% load thumbnail %} +
    +
    + + {% thumbnail picture.image_file "216x288" as thumb %} + + {% endthumbnail %} + +
    +
    +
    + {% for author in tags.author %} + {{ author }} + {% endfor %} +
    +
    {{ picture.title }}
    +
    +
    + {% spaceless %} + + {% trans "Epoch" %}:  + + {% for tag in tags.epoch %} + {{ tag.name }} + {% endfor %} + + + {% trans "Kind" %}:  + + {% for tag in tags.kind %} + {{ tag.name }} + {% endfor %} + + + {% endspaceless %} +
    +
    +
      +
    +
    +
    diff --git a/wolnelektury/urls.py b/wolnelektury/urls.py index 0cb3eddb7..a3fad8251 100644 --- a/wolnelektury/urls.py +++ b/wolnelektury/urls.py @@ -32,6 +32,7 @@ urlpatterns += patterns('', # Admin panel url(r'^admin/catalogue/book/import$', 'catalogue.views.import_book', name='import_book'), + url(r'^admin/catalogue/picture/import$', 'picture.views.import_picture', name='import_picture'), url(r'^admin/doc/', include('django.contrib.admindocs.urls')), url(r'^admin/', include(admin.site.urls)),
Utwory
Wszystkie utwory:{% count_books_all %}
Utwory z własną treścią:{% count_books_nonempty %}
Utwory bez własnej treści:{% count_books_empty %}
Utwory:{% count_books %}
Niezależne książki:{% count_books_root %}
Utwory nadrzędne:{% count_books_parent %}
Wszystkie utwory:{% count_books_all %}
MediaLiczbaRozmiarDo wymiany