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
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
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
import_form.save()
pic = Picture.objects.get(slug=slug)
+
url(r'^(?P<tags>(?:(?:[a-z0-9-]+/){2}){0,6})books/$', book_list_resource),
url(r'^(?P<tags>(?:(?:[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<tags>(?:(?:[a-z0-9-]+/){2}){1,6})fragments/$', fragment_list_resource),
# tags by category
url(r'^(?P<category>[a-z0-9-]+)/$', tag_list_resource),
-
- # picture by slug
- url(r'^pictures/$', picture_resource)
)
for ebook_format in self.ebook_formats:
if self.has_media(ebook_format):
formats.append(u'<a href="%s">%s</a>' % (
- "", #self.get_media(ebook_format).url,
+ self.get_media(ebook_format).url,
ebook_format.upper()
))
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):
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<picture>%s)/?$' % Picture.URLID_RE, 'picture_detail')
+ ) + \
+ patterns('catalogue.views',
url(r'^$', 'catalogue', name='catalogue'),
url(r'^polki/(?P<shelf>[a-zA-Z0-9-]+)/formaty/$', 'shelf_book_formats', name='shelf_book_formats'),
url(r'^polki/(?P<shelf>[a-zA-Z0-9-]+)/(?P<book>%s)/usun$' % Book.URLID_RE, 'remove_from_shelf', name='remove_from_shelf'),
url(r'^custompdf/(?P<book_fileid>%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<picture>%s)/?$' % Picture.URLID_RE, 'picture_detail')
- )
-
+)
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
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
def tagged_object_list(request, tags=''):
+ # import pdb; pdb.set_trace()
try:
tags = models.Tag.get_tag_list(tags)
except models.Tag.DoesNotExist:
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):
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']:
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):
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
ret = super(Picture, self).save(force_insert, force_update)
+ if reset_short_html:
+ self.reset_short_html()
+
return ret
def __unicode__(self):
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:
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))
finally:
if close_xml_file:
xml_file.close()
+ if close_image_file:
+ image_file.close()
return picture
@classmethod
@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)
--- /dev/null
+{% extends "admin/change_list.html" %}
+{% load i18n %}
+
+{% block content %}
+ <form action="{% url import_picture %}" method="post" enctype="multipart/form-data">
+ <p>XML: <input type="file" id="id_picture_xml_file" name="picture_xml_file" /><br/>
+ {% trans "Image" %}: <input type="file" id="id_picture_image_file" name="picture_image_file" /><br/>
+ <input type="submit" value="{% trans "Import picture" %}"/></p>
+ </form>
+ {{ block.super }}
+{% endblock content %}
\ No newline at end of file
+from picture.tests.picture_import import *
<dc:date.pd xml:lang="pl">1940</dc:date.pd>
<dc:type>Image</dc:type>
<dc:format xml:lang="pl">image/png</dc:format>
- <dc:format.dimensions.digital xml:lang="pl">1090 x 755 px</dc:format.dimensions.digital>
+ <dc:format.dimensions xml:lang="pl">1090 x 755 px</dc:format.dimensions>
+ <dc:format.checksum.sha1 xml:lang="pl">122b590510ce70cc80e617557f82048ce20f1d7b</dc:format.checksum.sha1>
<dc:date xml:lang="pl">1923</dc:date>
<dc:language xml:lang="pl" xmlns:dc="http://purl.org/dc/elements/1.1/">eng</dc:language>
</rdf:Description>
</rdf:RDF>
- <sem type="obiekt" obiekt="kosmos">
+ <sem type="object" object="kosmos">
<div type="area" x1="17" y1="31" x2="275" y2="309"/>
</sem>
- <sem type="obiekt" obiekt="nieporządek">
+ <sem type="theme" theme="nieporządek">
<div type="area" x1="300" y1="138" x2="976" y2="514"/>
</sem>
--- /dev/null
+# -*- 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()
+
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
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)
<table class="stats">
<tr><th>Utwory</th></tr>
- <tr><td>Wszystkie utwory:</td><td>{% count_books_all %}</td></tr>
- <tr><td>Utwory z własną treścią:</td><td>{% count_books_nonempty %}</td></tr>
- <tr><td>Utwory bez własnej treści:</td><td>{% count_books_empty %}</td></tr>
+ <tr><td>Utwory:</td><td>{% count_books %}</td></tr>
<tr><td>Niezależne książki:</td><td>{% count_books_root %}</td></tr>
+ <tr><td>Utwory nadrzędne:</td><td>{% count_books_parent %}</td></tr>
+ <tr><td>Wszystkie utwory:</td><td>{% count_books_all %}</td></tr>
<tr><th>Media</th><th>Liczba</th><th>Rozmiar</th><th>Do wymiany</th></tr>
{% for mt in media_types %}
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
-Subproject commit 5b407667ca47cf4d9752821fd49e5611737146d2
+Subproject commit 5fed78856949474a36bc5e268517775a9a802e27
'css/header.css',
'css/main_page.css',
'css/dialogs.css',
+ 'css/picture_box.css',
'css/book_box.css',
'css/catalogue.css',
'css/sponsors.css',
'js/locale.js',
'js/dialogs.js',
'js/sponsors.js',
+ 'js/base.js',
'js/pdcounter.js',
'js/search.js',
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;
}
-.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;
}
}
#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;
.book-box {
- width: 37.5em;
+ width: 48.75em;
}
.book-mini-box {
- width: 12.5em;
+ width: 16.15em;
}
.book-mini-box a, .book-box-inner {
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;
vertical-align: middle;
}
.book-box-read {
- width: 10em;
+ width: 11em;
}
.book-box-download {
- width: 6em;
+ width: 8em;
}
.book-box-audiobook {
- width: 6em;
+ width: 8em;
}
#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%;
#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;
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;
}
#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;
}
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;
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;
}
#lang-menu .active {
- font-weight: bold;
+ color: #000;
}
#big-cite {
background-color: white;
- padding: 4em 12em;
+ padding: 10.75em 10em 8.5em 18.2em;
margin: 0;
}
#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 {
--- /dev/null
+.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;
+}
--- /dev/null
+(function($) {
+ $(function() {
+
+
+$('#themes-list-toggle').click(function(event) {
+ event.preventDefault();
+ $('#themes-list').toggle('slow');
+});
+
+
+ });
+})(jQuery)
+
});
$(function() {
- $("#search input[name=q]").search();
+ $("#search-area input[name=q]").search();
});
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
{% load i18n compressed catalogue_tags sponsor_tags %}
+ {% load reporting_stats %}
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
{% block bodycontent %}
- <div id="header" class="grid-line">
+ <div id="header">
<div id="header-content">
<div id="logo">
</div>
<div id="tagline">
- <a href=''>1666</a> darmowych lektur do których masz <a href=''>prawo</a>
+ <span>
+ {% count_books book_count %}
+ {% url book_list as b %}
+ {% url book_list as r %}
+ {% blocktrans count book_count as c %}
+ <a href='{{b}}'>{{c}}</a> free reading you have <a href='{{r}}'>right to</a>
+ {% plural %}
+ <a href='{{b}}'>{{c}}</a> free readings you have <a href='{{r}}'>right to</a>
+ {% endblocktrans %}
+ </span>
</div>
<p id="user-info" class="mono">
- <form id="search" action="/fullsearch/">
+ <form id="search-area" action="/fullsearch/">
<span id="search-field" class="grid-line">
<input title="np. Leśmian" name="q" autocomplete="off" data-source="/fullsearch/hint/">
<div id="nav-line">
<ul id="catalogue">
- <li><a href="{% url book_list %}"><span class='mono'>{% trans "All books" %}</span></a></li>
- <li><a href="{% url audiobook_list %}"><span class='mono'>{% trans "Audiobooks" %}</span></a></li>
- <li><a href="{% url daisy_list %}"><span class='mono'>{% trans "DAISY" %}</span></a></li>
<li><a href="{% url catalogue %}#autorzy"><span class='mono'>{% trans "Authors" %}</span></a></li>
- <li><a href="{% url catalogue %}#epoki"><span class='mono'>{% trans "Epochs" %}</span></a></li>
- <li><a href="{% url catalogue %}#rodzaje"><span class='mono'>{% trans "Kinds" %}</span></a></li>
<li><a href="{% url catalogue %}#gatunki"><span class='mono'>{% trans "Genres" %}</span></a></li>
+ <li><a href="{% url catalogue %}#rodzaje"><span class='mono'>{% trans "Kinds" %}</span></a></li>
+ <li><a href="{% url catalogue %}#epoki"><span class='mono'>{% trans "Epochs" %}</span></a></li>
<li><a href="{% url catalogue %}#motywy"><span class='mono'>{% trans "Themes" %}</span></a></li>
+ <li><a href="{% url book_list %}"><span class='mono'>{% trans "All books" %}</span></a></li>
+ <li><a href="{% url audiobook_list %}"><span class='mono'>{% trans "Audiobooks" %}</span></a></li>
+ <li><a href="{% url daisy_list %}"><span class='mono'>{% trans "DAISY" %}</span></a></li>
</ul>
<form action="{% url django.views.i18n.set_language %}" method="post">
<div id="lang-menu">
- <span id='lang-button' class='mono-small'>
+ <span id='lang-button' class='mono'>
{% trans "Language versions" %}</span>
<div id="lang-menu-items">
{% for lang in LANGUAGES %}
<button type="submit" name="language"
- class="{% ifequal lang.0 LANGUAGE_CODE %}active{% endifequal %} {% if forloop.last %}last{% endif %}"
+ class="{% ifequal lang.0 LANGUAGE_CODE %}active{% endifequal %} mono"
value="{{ lang.0 }}">{{ lang.1 }}</button>
{% endfor %}
</div>
</div>
<div class="clearboth"></div>
</div>
- <div id="set-window">
- <div class="header"><a href="#" class="jqmClose">{% trans "Close" %}</a></div>
- <div class="target">
- <p><img src="{{ STATIC_URL }}img/indicator.gif" alt="*"/> {% trans "Loading" %}</p>
- </div>
- </div>
{% endblock %}
</div>
<div class="clearboth"></div>
</div>
- <div id="set-window">
- <div class="header"><a href="#" class="jqmClose">{% trans "Close" %}</a></div>
- <div class="target">
- <p><img src="{{ STATIC_URL }}img/indicator.gif" alt="*"/> {% trans "Loading" %}</p>
- </div>
- </div>
{% endblock %}
\ No newline at end of file
" alt="Cover" />
{% endif %}
{% for author in authors %}
- <div class="mono author">{{ author }}</div>
- {{ book.title }}
+ <div class="desc">
+ <span class="mono author">{{ author }}</span>
+ <span class="title">{{ book.title }}</span>
+ </div>
{% endfor %}
</a>
</div>
<div class="tags">
{% spaceless %}
- <span class="mono">{% trans "Epoch" %}: </span>
- <span class="book-box-tag">
+ <span class="mono">{% trans "Epoch" %}:</span> <span class="book-box-tag">
{% for tag in tags.epoch %}
<a href="{{ tag.get_absolute_url }}">{{ tag.name }} </a>
{% endfor %}
</span>
- <span class="mono">{% trans "Kind" %}: </span>
- <span class="book-box-tag">
+ <span class="mono">{% trans "Kind" %}:</span> <span class="book-box-tag">
{% for tag in tags.kind %}
<a href="{{ tag.get_absolute_url }}">{{ tag.name }} </a>
{% endfor %}
</span>
- <span class="mono">{% trans "Genre" %}: </span>
- <span class="book-box-tag">
+ <span class="mono">{% trans "Genre" %}:</span> <span class="book-box-tag">
{% for tag in tags.genre %}
<a href="{{ tag.get_absolute_url }}">{{ tag.name }} </a>
{% endfor %}
<ul class="book-box-tools">
<li class="book-box-read">
{% if book.html_file %}
- <a href="" class="mono">{% trans "Read online" %}</a>
+ <a href="{% url book_text book.urlid %}" class="mono">{% trans "Read online" %}</a>
{% endif %}
</li>
<li class="book-box-download">
</div>
{% endfor %}
</div>
-
- <div id="set-window">
- <div class="header"><a href="#" class="jqmClose">{% trans "Close" %}</a></div>
- <div class="target">
- <p><img src="{{ STATIC_URL }}img/indicator.gif" alt="*"/> {% trans "Loading" %}</p>
- </div>
- </div>
{% endblock %}
\ No newline at end of file
--- /dev/null
+{% load i18n %}
+{% load catalogue_tags %}
+{% if one_tag %}
+ {% trans "See full category" %} <a href="{% catalogue_url one_tag %}">{{ one_tag }}</a>
+{% else %}
+ {% for tag in tags %}
+ <a href="{% catalogue_url choices tag %}">{{ tag }} ({{ tag.book_count }})</a>
+ {% endfor %}
+{% endif %}
</div>
{% thumbnail picture.image_file "400x500" upscale="false" as im %}
- <img style="margin:{{ im|margin:"400x500" }}" src="{{ im.url }}" width="{{ im.x }}" height="{{ im.y }}" />
+ <img style="margin:{{ im|margin:"500x500" }}" src="{{ im.url }}" width="{{ im.x }}" height="{{ im.y }}" />
{% endthumbnail %}
{% if picture.info.license %}
{% if picture.info.description %}
<div id="description">
<div id='description-long'>{{ picture.info.description|safe }}</div>
- <div id='description-short'>{{ picture.info.description|safe|truncatewords_html:30 }}</div>
+{%comment%} <div id='description-short'>{{ picture.info.description|safe|truncatewords_html:30 }}</div>{%endcomment%}
</div>
<div id="toggle-description"><p></p></div>
{% endif %}
</div>
<div class="clearboth"></div>
</div>
- <div id="set-window">
- <div class="header"><a href="#" class="jqmClose">{% trans "Close" %}</a></div>
- <div class="target">
- <p><img src="{{ STATIC_URL }}img/indicator.gif" alt="*"/> {% trans "Loading" %}</p>
- </div>
- </div>
{% endblock %}
{% block bodyid %}tagged-object-list{% endblock %}
{% block body %}
+ <div class="left-column">
+ <div class="page-desc">
<h1>{% title_from_tags tags %}</h1>
- {% if only_shelf and not object_list %}
- <div id="books-list">
- <h2>{% trans "Your shelf is empty" %}</h2>
- <p>{% trans "You can put a book on a shelf by entering page of the reading and clicking 'Put on the shelf'." %}</p>
+ {% with tags|last as last_tag %}
+ {% if last_tag.has_description %}
+ <div id="description">
+ <div id='description-long'>{{ last_tag.description|safe }}</div>
+ <div id='description-short'>{{ last_tag.description|safe|truncatewords_html:30 }}</div>
+ </div>
+ <div class="clearboth"></div>
+ <div id="toggle-description"><p></p></div>
+ {% endif %}
+
+
+ <div class="inline-tag-lists">
+ {% if categories.author %}
+ <p><span class="mono">{% trans "Authors" %}:</span>
+ {% inline_tag_list categories.author tags %}
+ </p>
+ {% endif %}
+ {% if categories.kind %}
+ <p><span class="mono">{% trans "Kinds" %}:</span>
+ {% inline_tag_list categories.kind tags %}
+ </p>
+ {% endif %}
+ {% if categories.genre %}
+ <p><span class="mono">{% trans "Genres" %}:</span>
+ {% inline_tag_list categories.genre tags %}
+ </p>
+ {% endif %}
+ {% if categories.epoch %}
+ <p><span class="mono">{% trans "Epochs" %}:</span>
+ {% inline_tag_list categories.epoch tags %}
+ </p>
+ {% endif %}
</div>
- {% else %}
- {% autopaginate object_list 10 %}
- <div id="books-list">
- {% with tags|last as last_tag %}
- {% if last_tag.has_description %}
- <div id="description">
- <div id='description-long'>{{ last_tag.description|safe }}</div>
- <div id='description-short'>{{ last_tag.description|safe|truncatewords_html:30 }}</div>
- </div>
- <div class="clearboth"></div>
- <div id="toggle-description"><p></p></div>
- {% endif %}
- {% if only_shelf %}
- <a id="download-shelf" href="{% url download_shelf last_tag.slug %}">
- {% trans "Download all books from this shelf" %}
- </a>
- <div id="download-shelf-menu" style="display:none;">
- <form action="{% url download_shelf last_tag.slug %}" method="get" accept-charset="utf-8" id="download-formats-form" data-formats-feed="{% url shelf_book_formats last_tag.slug %}">
- <p>{% trans "Choose books' formats which you want to download:" %}</p>
- <li data-format="pdf"><label for="id_formats_2"><input type="checkbox" name="formats" value="pdf" id="id_formats_2" /> PDF</label> <em><strong>{% trans "for reading" %}</strong> {% trans "and printing using" %} <a href="http://get.adobe.com/reader/">Adobe Reader</a></em></li>
- <li data-format="epub"><label for="id_formats_5"><input type="checkbox" name="formats" value="epub" id="id_formats_5" /> EPUB</label> <em><strong>{% trans "for reading" %}</strong> {% trans "on mobile devices" %}</em></li>
- <li data-format="mobi"><label for="id_formats_7"><input type="checkbox" name="formats" value="mobi" id="id_formats_7" /> MOBI</label> <em><strong>{% trans "for reading" %}</strong> {% trans "on mobile devices" %}</em></li>
- <li data-format="odt"><label for="id_formats_3"><input type="checkbox" name="formats" value="odt" id="id_formats_3" /> ODT</label> <em><strong>{% trans "for reading" %}</strong> {% trans "and editing using" %} <a href="http://pl.openoffice.org/">OpenOffice.org</a></em></li>
- <li data-format="txt"><label for="id_formats_4"><input type="checkbox" name="formats" value="txt" id="id_formats_4" /> TXT</label> <em><strong>{% trans "for reading" %}</strong> {% trans "on small displays, for example mobile phones" %}</em></li>
- <li data-format="mp3"><label for="id_formats_0"><input type="checkbox" name="formats" value="mp3" id="id_formats_0" /> MP3</label> <em><strong>{% trans "for listening" %}</strong> {% trans "on favourite MP3 player" %}</em></li>
- <li data-format="ogg"><label for="id_formats_1"><input type="checkbox" name="formats" value="ogg" id="id_formats_1" /> Ogg Vorbis</label> <em><strong>{% trans "for listening" %}</strong> — {% trans "open format" %} <a href="http://www.vorbis.com/">{% trans "Xiph.org Foundation" %}</a></em></li>
- <li data-format="daisy"><label for="id_formats_6"><input type="checkbox" name="formats" value="daisy" id="id_formats_6" /> DAISY</label> </li>
- <li id="download-formats-form-submit-li"><label><input type="submit" name="submit" value="{% trans "Download" %}" id="download-formats-form-submit" disabled="disabled" /> <img src="{{ STATIC_URL }}img/indicator.gif" /></label> <span id="updating-formats">{% trans "Updating list of books' formats on the shelf" %}</span><span id="formats-updated" style="display:none;">{% trans "or" %} <a href="#" id="download-formats-form-cancel">{% trans "cancel" %}</a></span></li>
- <div class="clearboth"></div>
- </form>
+
+ {% if categories.theme %}
+ <div id="themes-list-wrapper">
+ <p><a href="#" id="themes-list-toggle" class="mono">{% trans "Motifs and themes" %}</a></p>
+ <div id="themes-list">
+ {% tag_list categories.theme tags %}
</div>
- {% if only_my_shelf %}
- <div id="toggle-share-shelf"><p>{% trans "Share this shelf" %}</p></div>
- <div id="share-shelf">
- <p>{% trans "Copy this link and share it with other people to let them see your shelf." %}
- <input id="share-shelf-url" value='http://{{ request.META.HTTP_HOST }}{{ request.path }}' />
- </p>
+ </div>
+ {% endif %}
+
+ </div>
+ </div>
+
+
+ <div class="right-column">
+ <a href="" class="cite">
+ <div class="cite-body">
+ Dobranoc, obróć jeszcze raz na mnie oczęta,<br/>
+ (…) Daj mi pierś ucałować<br/>
+ Dobranoc, zapięta.
</div>
- {% endif %}
- {% endif %}
+ <p class="mono">Adam Mickiewicz, Dziady część III</p>
+ </a>
+
+ <div class="see-also">
+ <h2 class='mono'>{% trans "See also" %}:</h2>
+ <ul>
+ <li><a href="">Wiki</a></li>
+ <li><a href="">Gazeta</a></li>
+ </ul>
+ </div>
+
+ <div class="download">
+ <h2 class='mono'>{% trans "Download" %}:</h2>
+ <ul>
+ <li><a href="">wszystko</a></li>
+ <li><a href="">część</a></li>
+ </ul>
+ </div>
+
+ </div>
+
+ <div class="clearboth"></div>
+
+
+
+
+ {% autopaginate object_list 10 %}
+ <div id="books-list">
+
+
{% if last_tag.gazeta_link %}
<p><a href="{{ last_tag.gazeta_link }}">
{% switch last_tag.category %}
</div>
{% if object_list %}
{% comment %} If we didn't find anything there will be nothing on the right side as well {% endcomment %}
- <div id="tags-list">
- <div id="categories-list">
- {% if categories.author %}
- <h2>{% trans "Authors" %}</h2>
- {% tag_list categories.author tags %}
- {% endif %}
- {% if categories.kind %}
- <h2>{% trans "Kinds" %}</h2>
- {% tag_list categories.kind tags %}
- {% endif %}
- {% if categories.genre %}
- <h2>{% trans "Genres" %}</h2>
- {% tag_list categories.genre tags %}
- {% endif %}
- {% if categories.epoch %}
- <h2>{% trans "Epochs" %}</h2>
- {% tag_list categories.epoch tags %}
- {% endif %}
- {% if only_shelf %}
- <p><a href="{% url poem_from_set tags.0.slug %}">Miksuj utwory z tej półki</a>
- {% endif %}
- </div>
- <div id="themes-list">
- {% if categories.theme %}
- <h2>{% trans "Themes" %}</h2>
- {% tag_list categories.theme tags %}
- {% endif %}
- </div>
- <div class="clearboth"></div>
- </div>
{% endif %}
- {% endif %}
- <div id="set-window">
- <div class="header"><a href="#" class="jqmClose">{% trans "Close" %}</a></div>
- <div class="target">
- <p><img src="{{ STATIC_URL }}img/indicator.gif" alt="*"/> {% trans "Loading" %}</p>
- </div>
- </div>
{% endblock %}
{% load i18n %}
{% load reporting_stats %}
-{% count_books_nonempty book_count %}
+{% count_books book_count %}
<p>
{% blocktrans count book_count as c %}
We have {{c}} work published in Wolne Lektury!
<h2 class="mono">Trwa konkurs</h2>
</div>
<div id="promo-box-body">
- <p id="promo-box-title" class="mono">Konkurs poezji automatycznej</p>
+ <p id="promo-box-title" class="mono"><span>Konkurs poezji automatycznej</span></p>
+ <div id="promo-box-content">
<p>Znacie Leśmianatora? To niewielki skrypt miskujący na życzenie
wiersze z Wolnych Lektur.</p>
+ </div>
</div>
</div>
- <h2 class="grid-line"><span class="mono">Ostatnie publikacje</span></h2>
+ <h2 class="main-last"><span class="mono">Ostatnie publikacje</span></h2>
{% for book in last_published %}
{{ book.mini_box }}
{% endfor %}
+ <div class="clearboth"></div>
+
<div class="infopages-box">
- <h2 class="grid-line"><span class='mono'>Aktualności</span></h2>
+ <h2><span class='mono'>Aktualności</span></h2>
{% cache 1800 latest-blog-posts %}
{% latest_blog_posts "http://nowoczesnapolska.org.pl/category/wolne-lektury/feed/" %}
{% endcache %}
<div class="infopages-box">
- <h2 class="grid-line"><span class='mono'>Narzędzia</span></h2>
+ <h2><span class='mono'>Narzędzia</span></h2>
<ul>
<li><a href="{% url suggest %}" id="suggest" class="ajaxable">{% trans "Report a bug or suggestion" %}</a></li>
<div class="infopages-box">
- <h2 class="grid-line"><span class='mono'>Informacje</span></h2>
+ <h2><span class='mono'>Informacje</span></h2>
{% infopages_on_main %}
--- /dev/null
+{% load i18n %}
+{% load thumbnail %}
+<div class="picture-box">
+<div class="picture-box-inner">
+ <a href="{{ picture.get_absolute_url }}">
+ {% thumbnail picture.image_file "216x288" as thumb %}
+ <img src="{{thumb.url}}"/>
+ {% endthumbnail %}
+ </a>
+ <div class="picture-box-body">
+ <div class="picture-box-head">
+ <div class="mono author">
+ {% for author in tags.author %}
+ {{ author }}
+ {% endfor %}
+ </div>
+ <div class="title">{{ picture.title }}</div>
+ </div>
+ <div class="tags">
+ {% spaceless %}
+
+ <span class="mono">{% trans "Epoch" %}: </span>
+ <span class="picture-box-tag">
+ {% for tag in tags.epoch %}
+ <a href="{{ tag.get_absolute_url }}">{{ tag.name }} </a>
+ {% endfor %}
+ </span>
+
+ <span class="mono">{% trans "Kind" %}: </span>
+ <span class="picture-box-tag">
+ {% for tag in tags.kind %}
+ <a href="{{ tag.get_absolute_url }}">{{ tag.name }} </a>
+ {% endfor %}
+ </span>
+
+ {% endspaceless %}
+ </div>
+ </div>
+ <ul class="picture-box-tools">
+ </ul>
+</div>
+</div>
# 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)),