From 87e084d47c335cd6f0b3e91d614999f55d148044 Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Thu, 31 Dec 2015 22:07:56 +0100 Subject: [PATCH] Generally working version. --- fabfile.py | 8 + src/ajaxable/templates/ajaxable/form.html | 4 +- .../templates/ajaxable/form_on_page.html | 4 + src/catalogue/constants.py | 10 + src/catalogue/helpers.py | 112 +++-- src/catalogue/locale/pl/LC_MESSAGES/django.mo | Bin 11408 -> 11446 bytes src/catalogue/locale/pl/LC_MESSAGES/django.po | 462 ++++++++++-------- .../management/commands/importbooks.py | 125 ++--- src/catalogue/models/book.py | 12 +- src/catalogue/models/collection.py | 11 + src/catalogue/models/tag.py | 15 +- .../static/jplayer/jplayer.blue.monday.css | 30 +- src/catalogue/static/player/player.js | 45 +- src/catalogue/tasks.py | 6 + .../templates/catalogue/audiobook_list.html | 24 +- .../templates/catalogue/book_detail.html | 42 +- .../templates/catalogue/book_short.html | 158 ++++-- .../templates/catalogue/book_wide.html | 49 -- .../templates/catalogue/catalogue.html | 23 +- .../templates/catalogue/collection.html | 17 +- .../templates/catalogue/collection_box.html | 21 + .../templates/catalogue/collections.html | 22 + .../templates/catalogue/inline_tag_list.html | 36 +- src/catalogue/templates/catalogue/menu.html | 41 -- .../templates/catalogue/plain_list.html | 19 + src/catalogue/templates/catalogue/player.html | 8 +- .../catalogue/search_multiple_hits.html | 42 +- .../snippets/custom_pdf_link_li.html | 5 +- .../templates/catalogue/tag_box.html | 13 + .../templates/catalogue/tag_catalogue.html | 23 + .../catalogue/tagged_object_list.html | 220 ++++----- src/catalogue/templatetags/catalogue_tags.py | 80 ++- src/catalogue/urls.py | 14 +- src/catalogue/utils.py | 12 - src/catalogue/views.py | 271 +++++----- src/picture/models.py | 22 + .../templates/picture/picture_short.html | 10 +- .../templates/picture/picture_viewer.html | 16 +- .../templates/picture/picture_wide.html | 15 - src/search/templatetags/search_tags.py | 7 +- src/wolnelektury/celery.py | 4 +- .../locale/pl/LC_MESSAGES/django.mo | Bin 8707 -> 7526 bytes .../locale/pl/LC_MESSAGES/django.po | 436 +++++++++-------- src/wolnelektury/settings/custom.py | 5 + src/wolnelektury/settings/static.py | 7 + src/wolnelektury/static/js/base.js | 75 ++- .../static/js/contrib/jquery.paging.min.js | 14 + .../static/scss/book_text/menu.scss | 2 + src/wolnelektury/static/scss/main/base.scss | 54 +- .../static/scss/main/book_box.scss | 129 ++--- .../static/scss/main/dialogs.scss | 6 +- src/wolnelektury/static/scss/main/header.scss | 213 +++++--- .../static/scss/main/main_page.scss | 123 ++--- src/wolnelektury/static/scss/main/menu.scss | 251 +++++----- .../static/scss/main/picture_box.scss | 11 +- src/wolnelektury/static/scss/main/tag.scss | 85 +++- .../static/scss/social/shelf_tags.scss | 22 +- src/wolnelektury/templates/account/base.html | 2 + src/wolnelektury/templates/main_page.html | 74 ++- .../templates/socialaccount/connections.html | 3 +- .../socialaccount/login_cancelled.html | 4 +- src/wolnelektury/templates/superbase.html | 89 ++-- src/wolnelektury/templates/user.html | 3 +- src/wolnelektury/views.py | 40 +- 64 files changed, 2196 insertions(+), 1510 deletions(-) create mode 100644 src/catalogue/templates/catalogue/collection_box.html create mode 100644 src/catalogue/templates/catalogue/collections.html delete mode 100644 src/catalogue/templates/catalogue/menu.html create mode 100644 src/catalogue/templates/catalogue/plain_list.html create mode 100644 src/catalogue/templates/catalogue/tag_box.html create mode 100644 src/catalogue/templates/catalogue/tag_catalogue.html create mode 100644 src/wolnelektury/static/js/contrib/jquery.paging.min.js diff --git a/fabfile.py b/fabfile.py index a7bc768ab..e614e9ce5 100644 --- a/fabfile.py +++ b/fabfile.py @@ -19,6 +19,14 @@ def production(): ] +@task +def beta(): + env.hosts = ['giewont.icm.edu.pl'] + env.user = 'lektury' + env.app_path = '/srv/wolnelektury.pl/beta' + env.services = [] + + @task def staging(): env.hosts = ['san.nowoczesnapolska.org.pl:2223'] diff --git a/src/ajaxable/templates/ajaxable/form.html b/src/ajaxable/templates/ajaxable/form.html index 13586ac9d..963f411f7 100755 --- a/src/ajaxable/templates/ajaxable/form.html +++ b/src/ajaxable/templates/ajaxable/form.html @@ -17,4 +17,6 @@ -{% block extra %}{% endblock %} \ No newline at end of file +
+{% block extra %}{% endblock %} +
diff --git a/src/ajaxable/templates/ajaxable/form_on_page.html b/src/ajaxable/templates/ajaxable/form_on_page.html index 61175d507..8e495234a 100755 --- a/src/ajaxable/templates/ajaxable/form_on_page.html +++ b/src/ajaxable/templates/ajaxable/form_on_page.html @@ -5,10 +5,14 @@ {% block body %} +
+ {% include ajax_template %} {% if response_data.message %}

{{ response_data.message }}

{% endif %} +
+ {% endblock %} diff --git a/src/catalogue/constants.py b/src/catalogue/constants.py index 36f4f5dd3..d1a5ddee3 100644 --- a/src/catalogue/constants.py +++ b/src/catalogue/constants.py @@ -36,3 +36,13 @@ LANGUAGES_3TO2 = { 'rus': 'ru', 'ukr': 'uk', } + +CATEGORIES_NAME_PLURAL = { + 'author': _('authors'), + 'epoch': _('epochs'), + 'kind': _('kinds'), + 'genre': _('genres'), + 'theme': _('themes'), + 'set': _('sets'), + 'thing': _('things'), +} diff --git a/src/catalogue/helpers.py b/src/catalogue/helpers.py index 7ca2cbd3a..b48c483ea 100644 --- a/src/catalogue/helpers.py +++ b/src/catalogue/helpers.py @@ -2,57 +2,91 @@ # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later. # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. # +from django.conf import settings from django.contrib.contenttypes.models import ContentType from django.db.models import Count from .models import Tag, Book +from os.path import getmtime +import cPickle +from collections import defaultdict + BOOK_CATEGORIES = ('author', 'epoch', 'genre', 'kind') -def get_top_level_related_tags(tags=None, categories=BOOK_CATEGORIES): +_COUNTERS = None +_COUNTER_TIME = None +def get_top_level_related_tags(tags, categories=None): """ Finds tags related to given tags through books, and counts their usage. Takes ancestry into account: if a tag is applied to a book, its usage on the book's descendants is ignored. + """ + global _COUNTERS, _COUNTER_TIME + # First, check that we have a valid and recent version of the counters. + if getmtime(settings.CATALOGUE_COUNTERS_FILE) > _COUNTER_TIME: + with open(settings.CATALOGUE_COUNTERS_FILE) as f: + _COUNTERS = cPickle.load(f) - This is tested for PostgreSQL 9.1+, and might not work elsewhere. - It particular, it uses raw SQL using WITH clause, which is - supported in SQLite from v. 3.8.3, and is missing in MySQL. - http://bugs.mysql.com/bug.php?id=16244 + tagids = tuple(sorted(t.pk for t in tags)) + try: + related_ids = _COUNTERS['next'][tagids] + except KeyError: + return - """ - # First, find all tag relations of relevant books. - bct = ContentType.objects.get_for_model(Book) - relations = Tag.intermediary_table_model.objects.filter( - content_type=bct) - if tags is not None: - tagged_books = Book.tagged.with_all(tags).only('pk') - relations = relations.filter( - object_id__in=tagged_books).exclude( - tag_id__in=[tag.pk for tag in tags]) - - rel_sql, rel_params = relations.query.sql_with_params() - - # Exclude those relations between a book and a tag, - # for which there is a relation between the book's ancestor - # and the tag and - - return Tag.objects.raw(''' - WITH AllTagged AS (''' + rel_sql + ''') - SELECT catalogue_tag.*, COUNT(catalogue_tag.id) AS count - FROM catalogue_tag, AllTagged - WHERE catalogue_tag.id=AllTagged.tag_id - AND catalogue_tag.category IN %s - AND NOT EXISTS ( - SELECT AncestorTagged.id - FROM catalogue_book_ancestor Ancestor, - AllTagged AncestorTagged - WHERE Ancestor.from_book_id=AllTagged.object_id - AND AncestorTagged.content_type_id=%s - AND AncestorTagged.object_id=Ancestor.to_book_id - AND AncestorTagged.tag_id=AllTagged.tag_id - ) - GROUP BY catalogue_tag.id - ORDER BY sort_key''', rel_params + (categories, bct.pk)) + related = Tag.objects.filter(pk__in=related_ids) + + # TODO: do we really need that? + if categories is not None: + related = related.filter(category__in=categories) + + for tag in related: + tag.count = _COUNTERS['count'][tuple(sorted(tagids + (tag.pk,)))] + yield tag + + #~ return related + + +def update_counters(): + def combinations(things): + if len(things): + for c in combinations(things[1:]): + yield c + yield (things[0],) + c + else: + yield () + + def count_for_book(book, count_by_combination=None, parent_combinations=None): + if not parent_combinations: + parent_combinations = set() + tags = sorted(tuple(t.pk for t in book.tags.filter(category__in=('author', 'genre', 'epoch', 'kind')))) + combs = list(combinations(tags)) + for c in combs: + if c not in parent_combinations: + count_by_combination[c] += 1 + combs_for_child = set(list(parent_combinations) + combs) + for child in book.children.all(): + count_for_book(child, count_by_combination, combs_for_child) + + count_by_combination = defaultdict(lambda: 0) + for b in Book.objects.filter(parent=None): + count_for_book(b, count_by_combination) + + next_combinations = defaultdict(set) + # Now build an index of all combinations. + for c in count_by_combination.keys(): + if not c: + continue + for n in c: + rest = tuple(x for x in c if x != n) + next_combinations[rest].add(n) + + counters = { + "count": dict(count_by_combination), + "next": dict(next_combinations), + } + + with open(settings.CATALOGUE_COUNTERS_FILE, 'w') as f: + cPickle.dump(counters, f) diff --git a/src/catalogue/locale/pl/LC_MESSAGES/django.mo b/src/catalogue/locale/pl/LC_MESSAGES/django.mo index 739f69b2dc8f80c2682a68903642c812357744f6..b45c14e211736437b73786eeb1a37f5d99f7b3b5 100644 GIT binary patch delta 4399 zcmYk833OD|8OLuRtYHa+lqEn0NFX7sh9HZ|S_Ncnltn5qnLNm3nK#S=CejXztVIew z5Rk1EutJNL2EkMC^iV>}Dabk1+DcViDn$=;q1IC9Y3c7jb2)Gi|M}f}-@V`cmiu1V zJm>hF#O3zs+YIe>)D>-QV$7GYRR%w_pSCfk6Fdr=!Qa5P@EzD5eg<2>uVDea1DnDE z7PW)};UqW$4u`8@G5iH&UBY}tM}}`h8ETYiOmo-@Hip@-Gwck%0gGWioCLeUFzf<1 zLD@M3<@-@6dv8HG^lM0L<|6C}e+OG~zPV0E8*V~;Fpb+8GX!Qq8Ju7_9kyaT8_Gck z^3R0$=>V5Qf;Zb>7Cd0*--HU_ZTtKx)c$|LY|b}#=*WR=@~MqIpdu`RO5t3n5-hai z1Z0cZ02R@0s0d$%T6YL4kY7S&;2kK(KZFYCOQ?M}U_u*j(rFF<2fM>oc%g+wP^m43 z>2NC4#!{#V=0K&g3~GHH)cTcB5$}P@%n7JKE6zj`~u4GHAorFEvVbwhPr8g4wSt-sQrad>j&ET zhoLe(HaVvLrF0a*Z2O=bYC{~#;3}vO(MBl4n=QB5=PyAyxF0HmhoRR03~K#xC`V30 ztvhYU=QP&)f6-372esh?D2G0Q=cw^@*pu-a6j}$o4|O>|fr{iS%XHq|0>;@;2R;H- z!tro2oCXKO-LN0L2oqZPA38FemYYg_3#gQ4K|S|D?u+RS$+j5{eQ+++2WJ`7CEEs7 zx+72-JOO3*tmWI5??LXj`6!qAE5-k0Li{h3p{Bl+$K9bKsDd)Q1S<07P#N-|?!Z1M zgU6trpN9(IGSscV24(j))cW>4QjYcMkw`@_kO^&=0QEXP3Gu}Qp$=XTRRRyn&~c~( zFG6MLisdz!&-eyZX*#k=4is2E2$hjXEvHVmotbvQJg9?fpdx=B%HthSm*)tSfn#=j z3KlUw1GWBd-p*zt6UxnoUa4HX2<7r2sM~eg&i@K(-6hK_cK!xbEzS724Xx1o7u zqBq@TefZmu#;XN+YPJ-nww{10*99maEW zK2|58%5>h&|FJI@Qwu(4Ldp26fmRg4q5@VejU^SFWC7# zQ2P!*Iq)i^!pWP`AF2fr@u&U*mP38Dwxc0PckDs*Fe*iABT_JZ;5-ztV`V@s1L*^% zQt_AC)FHJgXd9Y{UP5X=L2LN)kR0eob-usp`=FBCZS!qs6?`5YLcLMMYu7r<^R-S- z%w(iC1C2&}uam8U-yLWa+JmT3^3{44s?A2PqAjQpsf|N?T+C7pXg^5)@*e~kM=ek# zdJ(BnyM%d^jy}{+BNgYnNNsuw$wH{B!n}rdqL)TW|^$sX^PrBH*y zXee5a_99!#)Gg3(B>JH`v>ze8cz4@6I&;u0H0Wf+-ADWEH&>$2;!_hP7FlvN$qgtf)N(#w8 z>c#Yzp#f+kit6p?NoOBY`yT3!(lxN{09=f6&>~cYzK@!FC2b0O2i)pvClCv|p{N;C zUG1y!#{w0>&?4VbH&T_FqF3*4(=@Hcm?i#TwZE*|@fNmyt4W0$bwb{V%tCK=W~p~H z^Y`A7cE`M$_6xd93@vmc7{aK}U*^VRzF38mH0WJuKfvpsmEn!bdbYK%+=&Jv!LZg1 z@J?j)^FGR&)Yu=1dHEgs)X(j(GOhm8?7?aEc^%(q)HPJ@%P$BNMtwDI#4-MOtip|0 zM7_(MYrBTsKtM2_jT#gbdeK^I8pD-E@PWi1w-Xg?^c)mF(Eb> zcVW`OGS{s#xID|P4mrNbPE{-(sWoAL#0kZGp?FQ16EWe4vn1%oqbBOaq^LJCXJALC z#)+Dk(w6#V5R7r`vYZ8(CH)6K(7$-FZ}89&LrRJU4fd|*bZT|~WPN7Wv1w_;ywYyN zJ6E~YPF0}NG1L9gcxA)tfa8nD$bW79if$BOyc>-*>Mf~(jbNi(E zy-04@`y%&q?`z-t-lZPlEL#MO`P`I|I`6Tb<6BM)#hgfWFckEAw|Z{L7#s0d`P^_Y z8Xw@T@6|7TVhD@JdW~v6uC8I{*h!*yl$4b+#N! zgAF?aPNhnbDu^4YtMv}{UDLz~yH!E2Z&8j{SCrFikv|p>G2U8K+AQLh*ZC_Q@6SaA zQ$qe!NPd$HG;WqA^IsdNuodtJDh$bYB0g;k2K*-Mh9h-OIT4ufnfkLUtL~E1`i&^5 mabvYhshif+1l`!ZUag7M#^PsJg0T5)%@*IHGxgjSdglLun_Qg$ delta 4310 zcmY+G3vg7`8OKi`2q6$42@ewvRRVs#@)L>QgAUK zRuBrkV5zN&MQLeeN}Jj$Wu{n4wRRY%t##0;DB2O}XkXSkQ2O}&vxkRg=D)x5{LXj2 z@7y!{lbXFXsq?v+2MpyX8i+z&jCmhE*PS2Aq#R=gz{#*HTne+`N;ndR;4N@B)RO&h zK70yJhJS|RVR5hYycJM(*1&GYq)eDfXF8hUt_Ph!#6xoy_JMD}eE1>c zQ06}{5B6YC{SMRtCP0lZhFZTG_Jv`n18sqF=rGJ4BDErBw;7Ahi*PzTunb--;<>vut|-v?7YsT`y-7#@L|cm`&|vrr3u z2X&HjP$9hlb)w5qccvF%(7Mr3hO3}bH5Do%%b_CF40XVVpyuz*BmNx@(7|EN5vb6; z0CfjmhC11KsCj>}<5!_J$i}K1DS=uy&2juHE~t$TLEYk`P#d(vPVhyj4NgMMe--MMzXP@IBd85Ng_?K8 zw!4vEMYt!FA_l)zNSv)Vvlb2UAdy zc-Z#uhh)t>4he$!F?8T-Q18ayU`m%FYe+iOL!m-e24!$ERBEbi`!2|RH1|QBFafoG zGn9k-p&YsZ<@iOY6#fIs&Q+*L^m5XvD|Cpz3|7#g33H%MuoCK)hM_jt0F~=KP>vmj zI>Gm$BKAwDbss~0O;;d$nVg|%2gX2!d=iwsd!hDC3{9my-bsf%-wTJs$DmSj63XMV zP!7Fm`5}}epIQFTvMal2UN0yI217++I@Dd72eodAZLb(frHqa>a1`7HE8z1`3qODg z_1}Y+x=u|gMmvY4&+r6P`*|oAU$K1M_P+}ii%)F3YjJvh0n`!8;WW4mD(QP6H`6=` zbz4qAt^WhmQ7#pm+d4MPVzq)d5GpC-E$2d=aTPoQL$;k=5}fF^KBdQD^N93&{3!f5 zgKru#%RJ4|W$I<9JpK{Nr%O=dpFyQ#P$_RY90R++Lof>-fwF%bD*UHx|7(_SmU7V) z#`ozEKeGH3>Q(wLl!4ylA`?1L8w`hXtjzY$fZFg5$kT2X+i?%dZmS*N29@XCusb|Z z#zoV~4$+}^`xwlIuRPkdZKUesSJJJ+|htUJ*4y2-sH5Tc5&>h*#9a(M+@ieF3TH;|X`v z^k0GfYiaO=n|bIi^b8t_79xExx)&-6`9r_nc&UX<^khtcDj-b_X1A;k6P-Ak7zz&=~Q7v74#if%`} zk;-(m3iU%J=vtX(D{Emc+GyK#un6r!U+?JCy`jwL_~mbh7#zzP)wwnnYrmRvOGeP6 z_sRaQ?>5H5NzaL`bNqVGX^hmy-FQoIw)dzYqtD#T>Uqm*f;oN86*e|HZZZ^!vAQAQ ztc%5&9!WTA2Kl)^?;ff1BeCdAHGi918{C;!UgG**!gm%e8GqACvoPJeI2?AC$Kth- zL=epz(8-Gi59VzR`s9xaX5`Nb9?2ixv(a-Cp0m-7`0s5!(*9ij_Kfz?{U&7Ocuiiy zaibx}k2Oc?+E?{|u~V0%UmuGH;|f}W9~JbUk8cYi(NLpjjdcz&?I zaBOZQ8a95!XH!4sG{+-RKX|KfZB-2s<=?~!8a0Q=0$xk-WZ8ST(j&2v~!c|x3`Yy*SU+E^vTch(jCFHvVz4?_ga2JF{jlHxo5UJiDs{E zz1tXVsjD}P*R{6z(MW?$)9Ln&*E4gy(qh7{pNx79!KSih!SBmP3{0QWkQguS#ABh> zNS$k%Pq&|GYjA@(qo<5+j<\n" "Language-Team: Fundacja Nowoczesna Polska \n" @@ -15,13 +15,41 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Translated-Using: django-rosetta 0.5.6\n" -"X-Generator: Poedit 1.5.4\n" +"X-Generator: Poedit 1.8.4\n" #: constants.py:10 msgid "Creative Commons Attribution-ShareAlike 3.0 Unported" msgstr "" "Creative Commons Uznanie autorstwa – Na tych samych warunkach 3.0 Unported" +#: constants.py:41 +msgid "authors" +msgstr "autorzy" + +#: constants.py:42 +msgid "epochs" +msgstr "epoki" + +#: constants.py:43 +msgid "kinds" +msgstr "rodzaje" + +#: constants.py:44 +msgid "genres" +msgstr "gatunki" + +#: constants.py:45 +msgid "themes" +msgstr "motywy" + +#: constants.py:46 +msgid "sets" +msgstr "półki" + +#: constants.py:47 +msgid "things" +msgstr "przedmioty" + #: forms.py:27 msgid "Please supply an XML." msgstr "Proszę podać XML." @@ -74,7 +102,7 @@ msgstr "Duży" msgid "Queue is full. Please try again later." msgstr "Kolejka jest pełna. Proszę spróbować ponownie później." -#: models/book.py:43 models/collection.py:13 +#: models/book.py:43 models/collection.py:14 msgid "title" msgstr "tytuł" @@ -87,8 +115,8 @@ msgstr "klucz sortowania" msgid "sort key by author" msgstr "Znalezieni autorzy" -#: models/book.py:46 models/book.py:48 models/collection.py:14 -#: models/collection.py:17 models/tag.py:34 +#: models/book.py:46 models/book.py:48 models/collection.py:15 +#: models/collection.py:18 models/tag.py:34 msgid "slug" msgstr "slug" @@ -96,8 +124,8 @@ msgstr "slug" msgid "language code" msgstr "Kod języka" -#: models/book.py:51 models/book.py:160 models/collection.py:15 -#: models/tag.py:38 models/tag.py:144 +#: models/book.py:51 models/book.py:169 models/collection.py:16 +#: models/tag.py:38 models/tag.py:154 msgid "description" msgstr "opis" @@ -122,7 +150,7 @@ msgstr "okładka" msgid "cover thumbnail" msgstr "podgląd okładki" -#: models/book.py:92 models/collection.py:20 +#: models/book.py:92 models/collection.py:21 msgid "book" msgstr "książka" @@ -130,21 +158,21 @@ msgstr "książka" msgid "books" msgstr "książki" -#: models/book.py:258 +#: models/book.py:267 #, python-format msgid "Book \"%s\" does not exist." msgstr "Utwór \"%s\" nie istnieje." -#: models/book.py:272 +#: models/book.py:281 #, python-format msgid "Book %s already exists" msgstr "Książka %s już istnieje" -#: models/book.py:519 +#: models/book.py:529 msgid "This work needs modernisation" msgstr "Ten utwór wymaga uwspółcześnienia" -#: models/book.py:546 models/bookmedia.py:27 +#: models/book.py:556 models/bookmedia.py:27 #, python-format msgid "%s file" msgstr "plik %s" @@ -165,19 +193,19 @@ msgstr "plik" msgid "book media" msgstr "media książki" -#: models/collection.py:18 +#: models/collection.py:19 msgid "book slugs" msgstr "slugi utworów" -#: models/collection.py:20 models/tag.py:20 +#: models/collection.py:21 models/tag.py:20 msgid "kind" msgstr "rodzaj" -#: models/collection.py:24 +#: models/collection.py:25 msgid "collection" msgstr "kolekcja" -#: models/collection.py:25 +#: models/collection.py:26 msgid "collections" msgstr "kolekcje" @@ -237,18 +265,20 @@ msgstr "tag" msgid "tags" msgstr "tagi" -#: templates/catalogue/audiobook_list.html:8 -#: templates/catalogue/audiobook_list.html:17 +#: templates/catalogue/audiobook_list.html:6 +#: templates/catalogue/audiobook_list.html:11 +msgid "Audiobooks" +msgstr "Audiobooki" + +#: templates/catalogue/audiobook_list.html:14 msgid "Listing of all audiobooks" msgstr "Spis wszystkich audiobooków" -#: templates/catalogue/audiobook_list.html:13 -msgid "Latest MP3 audiobooks" -msgstr "Ostatnio dodane audiobooki w formacie MP3" - -#: templates/catalogue/audiobook_list.html:14 -msgid "Latest Ogg Vorbis audiobooks" -msgstr "Ostatnio dodane audiobooki w formacie Ogg Vorbis" +#: templates/catalogue/audiobook_list.html:17 +#: templates/catalogue/daisy_list.html:7 +#: templates/catalogue/daisy_list.html:13 +msgid "Listing of all DAISY files" +msgstr "Spis wszystkich plików DAISY" #: templates/catalogue/book_detail.html:23 #: templates/catalogue/book_text.html:20 @@ -256,11 +286,55 @@ msgid "Other versions" msgstr "Inne wersje" #: templates/catalogue/book_detail.html:31 -#: templates/catalogue/tagged_object_list.html:75 -#: templates/catalogue/tagged_object_list.html:118 msgid "See also" msgstr "Zobacz też" +#: templates/catalogue/book_detail.html:40 +#: templates/catalogue/book_text.html:30 +#: templates/catalogue/tagged_object_list.html:24 +msgid "Themes" +msgstr "Motywy" + +#: templates/catalogue/book_detail.html:47 +msgid "Information about the work" +msgstr "Informacje o utworze" + +#: templates/catalogue/book_detail.html:58 +msgid "Source" +msgstr "Źródło" + +#: templates/catalogue/book_detail.html:58 +msgid "of the book" +msgstr "utworu" + +#: templates/catalogue/book_detail.html:59 +msgid "in" +msgstr "w serwisie" + +#: templates/catalogue/book_detail.html:61 +msgid "Source XML file" +msgstr "Źródłowy plik XML" + +#: templates/catalogue/book_detail.html:63 +msgid "Book on" +msgstr "Utwór na" + +#: templates/catalogue/book_detail.html:63 +msgid "Editor's Platform" +msgstr "Platformie Redakcyjnej" + +#: templates/catalogue/book_detail.html:66 +msgid "Book description on Lektury.Gazeta.pl" +msgstr "Opis lektury w Lektury.Gazeta.pl" + +#: templates/catalogue/book_detail.html:69 +msgid "Book description on Wikipedia" +msgstr "Opis lektury w Wikipedii" + +#: templates/catalogue/book_detail.html:71 +msgid "Mix this book" +msgstr "Miksuj treść utworu" + #: templates/catalogue/book_fragments.html:5 #: templates/catalogue/book_fragments.html:11 msgid "Theme" @@ -350,43 +424,34 @@ msgstr "Język" msgid "Read online" msgstr "Czytaj online" -#: templates/catalogue/book_short.html:101 -#: templates/catalogue/book_wide.html:72 views.py:594 +#: templates/catalogue/book_short.html:101 views.py:588 msgid "Download" msgstr "Pobierz" -#: templates/catalogue/book_short.html:104 -msgid "to print" -msgstr "do druku" - -#: templates/catalogue/book_short.html:107 -msgid "for an e-book reader" -msgstr "na czytnik e-booków" +#: templates/catalogue/book_short.html:173 templates/catalogue/player.html:84 +msgid "Artist" +msgstr "Czyta" -#: templates/catalogue/book_short.html:110 -msgid "for Kindle" -msgstr "na Kindle" +#: templates/catalogue/book_short.html:174 templates/catalogue/player.html:85 +msgid "Director" +msgstr "Reżyseruje" -#: templates/catalogue/book_short.html:113 -msgid "FictionBook" -msgstr "FictionBook" +#: templates/catalogue/book_short.html:190 +msgid "previous" +msgstr "poprzednia" -#: templates/catalogue/book_short.html:116 -msgid "for advanced usage" -msgstr "do zadań specjalnych" +#: templates/catalogue/book_short.html:191 +msgid "Part" +msgstr "Część" -#: templates/catalogue/book_short.html:122 -msgid "Listen" -msgstr "Słuchaj" +#: templates/catalogue/book_short.html:192 +msgid "next" +msgstr "następna" #: templates/catalogue/book_text.html:26 msgid "Table of contents" msgstr "Spis treści" -#: templates/catalogue/book_text.html:30 templatetags/catalogue_tags.py:336 -msgid "Themes" -msgstr "Motywy" - #: templates/catalogue/book_text.html:34 templates/catalogue/book_text.html:91 msgid "Settings" msgstr "Ustawienia" @@ -428,104 +493,50 @@ msgstr "Wyświetlaj motywy" msgid "Display footnotes" msgstr "Wyświetlaj przypisy" -#: templates/catalogue/book_wide.html:23 -#: templates/catalogue/tagged_object_list.html:61 -msgid "Motifs and themes" -msgstr "Motywy i tematy" - -#: templates/catalogue/book_wide.html:52 -msgid "See" -msgstr "Zobacz" - -#: templates/catalogue/book_wide.html:55 -msgid "Source" -msgstr "Źródło" - -#: templates/catalogue/book_wide.html:55 -msgid "of the book" -msgstr "utworu" - -#: templates/catalogue/book_wide.html:56 -msgid "in" -msgstr "w serwisie" - -#: templates/catalogue/book_wide.html:58 -msgid "Source XML file" -msgstr "Źródłowy plik XML" - -#: templates/catalogue/book_wide.html:60 -msgid "Book on" -msgstr "Utwór na" - -#: templates/catalogue/book_wide.html:60 -msgid "Editor's Platform" -msgstr "Platformie Redakcyjnej" - -#: templates/catalogue/book_wide.html:63 -msgid "Book description on Lektury.Gazeta.pl" -msgstr "Opis lektury w Lektury.Gazeta.pl" - -#: templates/catalogue/book_wide.html:66 -msgid "Book description on Wikipedia" -msgstr "Opis lektury w Wikipedii" - -#: templates/catalogue/book_wide.html:68 -msgid "Mix this book" -msgstr "Miksuj treść utworu" - -#: templates/catalogue/book_wide.html:76 -msgid "Download all audiobooks for this book" -msgstr "Pobierz wszystkie audiobooki tego utworu" - -#: templates/catalogue/catalogue.html:6 templates/catalogue/catalogue.html:11 -#: templates/catalogue/menu.html:6 +#: templates/catalogue/catalogue.html:6 msgid "Catalogue" msgstr "Katalog" -#: templates/catalogue/catalogue.html:16 +#: templates/catalogue/catalogue.html:11 +msgid "All works" +msgstr "Wszystkie utwory" + +#: templates/catalogue/catalogue.html:17 msgid "Download the catalogue in PDF format." msgstr "Pobierz katalog w formacie PDF." -#: templates/catalogue/catalogue.html:19 -#: templates/catalogue/search_multiple_hits.html:20 -#: templates/catalogue/tagged_object_list.html:27 -#: templatetags/catalogue_tags.py:332 -msgid "Authors" -msgstr "Autorzy" - -#: templates/catalogue/catalogue.html:22 -#: templates/catalogue/search_multiple_hits.html:28 -#: templates/catalogue/tagged_object_list.html:35 -#: templatetags/catalogue_tags.py:334 -msgid "Kinds" -msgstr "Rodzaje" +#: templates/catalogue/catalogue.html:20 +#: templates/catalogue/tag_list_split.html:3 +#: templates/catalogue/tagged_object_list.html:6 +#: templates/catalogue/tagged_object_list.html:14 +msgid "Literature" +msgstr "Literatura" -#: templates/catalogue/catalogue.html:25 -#: templates/catalogue/search_multiple_hits.html:36 -#: templates/catalogue/tagged_object_list.html:43 -#: templatetags/catalogue_tags.py:333 -msgid "Genres" -msgstr "Gatunki" +#: templates/catalogue/catalogue.html:23 +#: templates/catalogue/collections.html:6 +#: templates/catalogue/collections.html:11 +msgid "Collections" +msgstr "Kolekcje" -#: templates/catalogue/catalogue.html:28 -#: templates/catalogue/search_multiple_hits.html:44 -#: templates/catalogue/tagged_object_list.html:51 -#: templatetags/catalogue_tags.py:335 -msgid "Epochs" -msgstr "Epoki" +#: templates/catalogue/catalogue.html:26 +#: templates/catalogue/tag_list_split.html:8 +#: templates/catalogue/tagged_object_list.html:6 +#: templates/catalogue/tagged_object_list.html:14 +msgid "Gallery" +msgstr "Galeria" -#: templates/catalogue/catalogue.html:31 -msgid "Themes and topics" -msgstr "Motywy i tematy" +#: templates/catalogue/collection_box.html:5 +msgid "Collection" +msgstr "Kolekcja" -#: templates/catalogue/catalogue.html:34 templates/catalogue/menu.html:19 -msgid "Collections" -msgstr "Kolekcje" +#: templates/catalogue/collection_box.html:15 +#, python-format +msgid "and %(c)s more" +msgstr "oraz %(c)s więcej" -#: templates/catalogue/daisy_list.html:7 -#: templates/catalogue/daisy_list.html:13 -msgid "Listing of all DAISY files" -msgstr "Spis wszystkich plików DAISY" +#: templates/catalogue/collections.html:17 +msgid "All collections" +msgstr "Wszystkie kolekcje" #: templates/catalogue/daisy_list.html:10 msgid "Latest DAISY audiobooks" @@ -545,34 +556,18 @@ msgstr "Rozwiń fragment" msgid "Hide fragment" msgstr "Zwiń fragment" -#: templates/catalogue/inline_tag_list.html:4 -#: templates/catalogue/tag_list.html:6 -msgid "See full category" -msgstr "Zobacz całą kategorię" - -#: templates/catalogue/menu.html:5 -msgid "Catalogue of the library" -msgstr "Katalog biblioteki" +#: templates/catalogue/inline_tag_list.html:6 +msgid "Chosen" +msgstr "Wybrane" -#: templates/catalogue/menu.html:13 templates/catalogue/menu.html.py:21 -msgid "Please wait…" -msgstr "Proszę czekać…" +#: templates/catalogue/inline_tag_list.html:14 +#: templates/catalogue/inline_tag_list.html:23 +msgid "Available" +msgstr "Dostępne" -#: templates/catalogue/menu.html:26 -msgid "All books" -msgstr "Wszystkie utwory" - -#: templates/catalogue/menu.html:29 -msgid "Audiobooks" -msgstr "Audiobooki" - -#: templates/catalogue/menu.html:32 -msgid "DAISY" -msgstr "DAISY" - -#: templates/catalogue/menu.html:36 templates/catalogue/tag_list_split.html:8 -msgid "Gallery" -msgstr "Galeria" +#: templates/catalogue/inline_tag_list.html:32 +msgid "Other" +msgstr "Inne" #: templates/catalogue/picture_detail.html:29 msgid "Work is licensed under " @@ -622,31 +617,23 @@ msgstr "Strona utworu" msgid "Download as" msgstr "Pobierz jako" -#: templates/catalogue/player.html:88 -msgid "Artist" -msgstr "Czyta" - -#: templates/catalogue/player.html:89 -msgid "Director" -msgstr "Reżyseruje" - -#: templates/catalogue/player.html:108 +#: templates/catalogue/player.html:104 msgid "Audiobooks were prepared as a part of the projects:" msgstr "Audiobooki przygotowane w ramach projektów:" -#: templates/catalogue/player.html:113 +#: templates/catalogue/player.html:109 #, python-format msgid "%(cs)s, funded by %(fb)s" msgstr "%(cs)s, finansowanego przez %(fb)s" -#: templates/catalogue/player.html:125 +#: templates/catalogue/player.html:121 #, python-format msgid "" "Audiobooks were prepared as a part of the %(cs)s project funded by %(fb)s." msgstr "" "Audiobooki przygotowane w ramach projektu %(cs)s finansowanego przez %(fb)s." -#: templates/catalogue/player.html:127 +#: templates/catalogue/player.html:123 #, python-format msgid "Audiobooks were prepared as a part of the %(cs)s project." msgstr "Audiobooki przygotowane w ramach projektu %(cs)s." @@ -688,28 +675,48 @@ msgstr "Szukaj" msgid "Did you mean" msgstr "Czy chodziło Ci o" -#: templates/catalogue/search_multiple_hits.html:55 +#: templates/catalogue/search_multiple_hits.html:20 +#: templates/catalogue/tagged_object_list.html:19 +msgid "Authors" +msgstr "Autorzy" + +#: templates/catalogue/search_multiple_hits.html:30 +#: templates/catalogue/tagged_object_list.html:22 +msgid "Kinds" +msgstr "Rodzaje" + +#: templates/catalogue/search_multiple_hits.html:40 +#: templates/catalogue/tagged_object_list.html:21 +msgid "Genres" +msgstr "Gatunki" + +#: templates/catalogue/search_multiple_hits.html:50 +#: templates/catalogue/tagged_object_list.html:20 +msgid "Epochs" +msgstr "Epoki" + +#: templates/catalogue/search_multiple_hits.html:63 msgid "Results by title" msgstr "Znalezione w tytułach" -#: templates/catalogue/search_multiple_hits.html:70 +#: templates/catalogue/search_multiple_hits.html:78 msgid "Results by authors" msgstr "Znalezieni autorzy" -#: templates/catalogue/search_multiple_hits.html:83 +#: templates/catalogue/search_multiple_hits.html:91 msgid "Results by translators" msgstr "Znalezieni tłumacze" -#: templates/catalogue/search_multiple_hits.html:96 +#: templates/catalogue/search_multiple_hits.html:104 msgid "Results in text" msgstr "Znalezione w treści" -#: templates/catalogue/search_multiple_hits.html:113 +#: templates/catalogue/search_multiple_hits.html:121 msgid "Other results" msgstr "Inne wyniki" #: templates/catalogue/search_no_hits.html:19 -#: templates/catalogue/tagged_object_list.html:162 +#: templates/catalogue/tagged_object_list.html:61 msgid "Sorry! Search cirteria did not match any resources." msgstr "Przepraszamy! Brak wyników spełniających kryteria podane w zapytaniu." @@ -727,7 +734,7 @@ msgstr "" msgid "Sorry! Search query must have at least two characters." msgstr "Przepraszamy! Zapytanie musi zawierać co najmniej dwa znaki." -#: templates/catalogue/snippets/custom_pdf_link_li.html:5 +#: templates/catalogue/snippets/custom_pdf_link_li.html:3 msgid "Download a custom PDF" msgstr "Stwórz własny plik PDF" @@ -736,30 +743,43 @@ msgstr "Stwórz własny plik PDF" msgid "Free license" msgstr "Wolna licencja" -#: templates/catalogue/tag_list_split.html:3 -msgid "Literature" -msgstr "Literatura" +#: templates/catalogue/tag_catalogue.html:11 +msgid "on Wolne Lektury" +msgstr "w Wolnych Lekturach" -#: templates/catalogue/tagged_object_list.html:79 -#: templates/catalogue/tagged_object_list.html:132 -msgid "in Culture.pl" -msgstr "w Culture.pl" +#: templates/catalogue/tag_list.html:6 +msgid "See full category" +msgstr "Zobacz całą kategorię" -#: templates/catalogue/tagged_object_list.html:84 -#: templates/catalogue/tagged_object_list.html:122 +#: templates/catalogue/tagged_object_list.html:58 +msgid "All matching works" +msgstr "Pasujące utwory" + +#: templates/catalogue/tagged_object_list.html:70 +msgid "Motifs and themes" +msgstr "Motywy i tematy" + +#: templates/catalogue/tagged_object_list.html:87 +msgid "No description." +msgstr "Brak opisu." + +#: templates/catalogue/tagged_object_list.html:93 msgid "in Lektury.Gazeta.pl" msgstr "w serwisie Lektury.Gazeta.pl" -#: templates/catalogue/tagged_object_list.html:89 -#: templates/catalogue/tagged_object_list.html:127 +#: templates/catalogue/tagged_object_list.html:99 msgid "in Wikipedia" msgstr "w Wikipedii" +#: templates/catalogue/tagged_object_list.html:105 +msgid "in Culture.pl" +msgstr "w Culture.pl" + #: templates/catalogue/viewer_base.html:55 msgid "Loading" msgstr "Ładowanie" -#: views.py:558 +#: views.py:552 #, python-format msgid "" "An error occurred: %(exception)s\n" @@ -770,19 +790,61 @@ msgstr "" "\n" "%(tb)s" -#: views.py:559 +#: views.py:553 msgid "Book imported successfully" msgstr "Książka zaimportowana" -#: views.py:561 +#: views.py:555 #, python-format msgid "Error importing file: %r" msgstr "Błąd podczas importowania pliku: %r" -#: views.py:593 +#: views.py:587 msgid "Download custom PDF" msgstr "Stwórz własny PDF" +#~ msgid "Latest MP3 audiobooks" +#~ msgstr "Ostatnio dodane audiobooki w formacie MP3" + +#~ msgid "Latest Ogg Vorbis audiobooks" +#~ msgstr "Ostatnio dodane audiobooki w formacie Ogg Vorbis" + +#~ msgid "to print" +#~ msgstr "do druku" + +#~ msgid "for an e-book reader" +#~ msgstr "na czytnik e-booków" + +#~ msgid "for Kindle" +#~ msgstr "na Kindle" + +#~ msgid "FictionBook" +#~ msgstr "FictionBook" + +#~ msgid "for advanced usage" +#~ msgstr "do zadań specjalnych" + +#~ msgid "Listen" +#~ msgstr "Słuchaj" + +#~ msgid "See" +#~ msgstr "Zobacz" + +#~ msgid "Download all audiobooks for this book" +#~ msgstr "Pobierz wszystkie audiobooki tego utworu" + +#~ msgid "Themes and topics" +#~ msgstr "Motywy i tematy" + +#~ msgid "Catalogue of the library" +#~ msgstr "Katalog biblioteki" + +#~ msgid "Please wait…" +#~ msgstr "Proszę czekać…" + +#~ msgid "DAISY" +#~ msgstr "DAISY" + #~ msgid "book count" #~ msgstr "liczba książek" diff --git a/src/catalogue/management/commands/importbooks.py b/src/catalogue/management/commands/importbooks.py index 338fea6aa..559124bdf 100644 --- a/src/catalogue/management/commands/importbooks.py +++ b/src/catalogue/management/commands/importbooks.py @@ -4,13 +4,11 @@ # import os import sys -import time from optparse import make_option from django.conf import settings from django.core.management.base import BaseCommand from django.core.management.color import color_style from django.core.files import File -from catalogue.utils import trim_query_log from librarian.picture import ImageStore from wolnelektury.management.profile import profile @@ -31,8 +29,6 @@ class Command(BaseCommand): help="Skip building specified formats"), make_option('-S', '--no-search-index', action='store_false', dest='search_index', default=True, 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, help='Import pictures'), ) @@ -81,14 +77,6 @@ class Command(BaseCommand): verbose = options.get('verbose') import_picture = options.get('import_picture') - wait_until = None - if options.get('wait_until'): - wait_until = time.mktime(time.strptime(options.get('wait_until'), '%Y-%m-%d %H:%M:%S')) - if verbose > 0: - print "Will wait until %s; it's %f seconds from now" % ( - time.strftime('%Y-%m-%d %H:%M:%S', - time.localtime(wait_until)), wait_until - time.time()) - index = None if options.get('search_index') and not settings.NO_SEARCH_INDEX: index = Index() @@ -100,74 +88,59 @@ class Command(BaseCommand): raise e # Start transaction management. - transaction.commit_unless_managed() - transaction.enter_transaction_management() - transaction.managed(True) - - files_imported = 0 - files_skipped = 0 - - for dir_name in directories: - if not os.path.isdir(dir_name): - print self.style.ERROR("%s: Not a directory. Skipping." % dir_name) - else: - # files queue - files = sorted(os.listdir(dir_name)) - postponed = {} - while files: - trim_query_log(0) - file_name = files.pop(0) - file_path = os.path.join(dir_name, file_name) - file_base, ext = os.path.splitext(file_path) - - # Skip files that are not XML files - if not ext == '.xml': - continue - - if verbose > 0: - print "Parsing '%s'" % file_path - else: - sys.stdout.write('.') - sys.stdout.flush() - - # Import book files - try: - if import_picture: - self.import_picture(file_path, options) + with transaction.atomic(): + files_imported = 0 + files_skipped = 0 + + for dir_name in directories: + if not os.path.isdir(dir_name): + print self.style.ERROR("%s: Not a directory. Skipping." % dir_name) + else: + # files queue + files = sorted(os.listdir(dir_name)) + postponed = {} + while files: + file_name = files.pop(0) + file_path = os.path.join(dir_name, file_name) + file_base, ext = os.path.splitext(file_path) + + # Skip files that are not XML files + if not ext == '.xml': + continue + + if verbose > 0: + print "Parsing '%s'" % file_path else: - self.import_book(file_path, options) - - files_imported += 1 - transaction.commit() - - except (Book.AlreadyExists, Picture.AlreadyExists): - print self.style.ERROR('%s: Book or Picture already imported. Skipping. To overwrite use --force.' % - file_path) - files_skipped += 1 - - except Book.DoesNotExist, e: - if file_name not in postponed or postponed[file_name] < files_imported: - # push it back into the queue, maybe the missing child will show up - if verbose: - print self.style.NOTICE('Waiting for missing children') - files.append(file_name) - postponed[file_name] = files_imported - else: - # we're in a loop, nothing's being imported - some child is really missing - raise e + sys.stdout.write('.') + sys.stdout.flush() + + # Import book files + try: + if import_picture: + self.import_picture(file_path, options) + else: + self.import_book(file_path, options) + + files_imported += 1 + + except (Book.AlreadyExists, Picture.AlreadyExists): + print self.style.ERROR('%s: Book or Picture already imported. Skipping. To overwrite use --force.' % + file_path) + files_skipped += 1 + + except Book.DoesNotExist, e: + if file_name not in postponed or postponed[file_name] < files_imported: + # push it back into the queue, maybe the missing child will show up + if verbose: + print self.style.NOTICE('Waiting for missing children') + files.append(file_name) + postponed[file_name] = files_imported + else: + # we're in a loop, nothing's being imported - some child is really missing + raise e # Print results print print "Results: %d files imported, %d skipped, %d total." % ( files_imported, files_skipped, files_imported + files_skipped) print - - if wait_until: - print 'Waiting...' - try: - time.sleep(wait_until - time.time()) - except IOError: - print "it's already too late" - - transaction.commit() - transaction.leave_transaction_management() diff --git a/src/catalogue/models/book.py b/src/catalogue/models/book.py index 5f68e09ff..1524c3456 100644 --- a/src/catalogue/models/book.py +++ b/src/catalogue/models/book.py @@ -55,8 +55,8 @@ class Book(models.Model): extra_info = jsonfield.JSONField(_('extra information'), default={}) gazeta_link = models.CharField(blank=True, max_length=240) wiki_link = models.CharField(blank=True, max_length=240) - # files generated during publication + # files generated during publication cover = EbookField('cover', _('cover'), null=True, blank=True, upload_to=_cover_upload_to, @@ -96,6 +96,15 @@ class Book(models.Model): def __unicode__(self): return self.title + def get_initial(self): + try: + return re.search(r'\w', self.title, re.U).group(0) + except AttributeError: + return None + + def author_str(self): + return ", ".join(str(t) for t in self.tags.filter(category='author')) + def save(self, force_insert=False, force_update=False, **kwargs): from sortify import sortify @@ -311,6 +320,7 @@ class Book(models.Model): notify_cover_changed.append(child) cls.repopulate_ancestors() + tasks.update_counters.delay() # No saves beyond this point. diff --git a/src/catalogue/models/collection.py b/src/catalogue/models/collection.py index 098501eba..bae1cc418 100644 --- a/src/catalogue/models/collection.py +++ b/src/catalogue/models/collection.py @@ -6,6 +6,7 @@ from django.conf import settings from django.db import models from django.utils.translation import ugettext_lazy as _ from ssify import flush_ssi_includes +import re class Collection(models.Model): @@ -28,6 +29,12 @@ class Collection(models.Model): def __unicode__(self): return self.title + def get_initial(self): + try: + return re.search(r'\w', self.title, re.U).group(0) + except AttributeError: + return None + @models.permalink def get_absolute_url(self): return ("collection", [self.slug]) @@ -39,6 +46,10 @@ class Collection(models.Model): for slug in slugs] return models.Q(slug__in=slugs) + def get_books(self): + from catalogue.models import Book + return Book.objects.filter(self.get_query()) + def flush_includes(self, languages=True): if not languages: return diff --git a/src/catalogue/models/tag.py b/src/catalogue/models/tag.py index 02bf6c07d..5575d6a14 100644 --- a/src/catalogue/models/tag.py +++ b/src/catalogue/models/tag.py @@ -128,9 +128,21 @@ class Tag(TagBase): def __repr__(self): return "Tag(slug=%r)" % self.slug + def get_initial(self): + if self.category == 'author': + return self.sort_key[0] + elif self.name: + return self.name[0] + else: + return None + @permalink def get_absolute_url(self): - return ('catalogue.views.tagged_object_list', [self.url_chunk]) + return ('tagged_object_list', [self.url_chunk]) + + @permalink + def get_absolute_gallery_url(self): + return ('tagged_object_list_gallery', [self.url_chunk]) @classmethod @permalink @@ -147,6 +159,7 @@ class Tag(TagBase): @staticmethod def get_tag_list(tags): if isinstance(tags, basestring): + if not tags: return [] real_tags = [] ambiguous_slugs = [] category = None diff --git a/src/catalogue/static/jplayer/jplayer.blue.monday.css b/src/catalogue/static/jplayer/jplayer.blue.monday.css index f8b314b6e..d1214c554 100644 --- a/src/catalogue/static/jplayer/jplayer.blue.monday.css +++ b/src/catalogue/static/jplayer/jplayer.blue.monday.css @@ -14,6 +14,17 @@ * Date: 1st September 2011 */ +.jp-audio .title { + font-size: 11px; + position: relative; + left: 10px; + top: 5px; + z-index: 100; +} +.play-prev, .play-next { + cursor: pointer; +} + div.jp-audio, div.jp-video { @@ -31,7 +42,7 @@ div.jp-video { position:relative; } div.jp-audio { - width:420px; + width: 340px; } div.jp-video-270p { width:480px; @@ -111,7 +122,7 @@ div.jp-interface ul.jp-controls { } div.jp-audio ul.jp-controls { - width: 380px; + width: 320px; padding:20px 20px 0 20px; } @@ -198,8 +209,8 @@ div.jp-audio div.jp-progress { height:15px; } div.jp-audio div.jp-type-single div.jp-progress { - left:110px; - width:186px; + left:70px; + width:150px; } div.jp-audio div.jp-type-playlist div.jp-progress { left:166px; @@ -243,7 +254,7 @@ a.jp-volume-max { div.jp-audio div.jp-type-single a.jp-mute, div.jp-audio div.jp-type-single a.jp-unmute { - margin-left: 210px; + margin-left: 180px; } div.jp-audio div.jp-type-playlist a.jp-mute, @@ -252,7 +263,7 @@ div.jp-audio div.jp-type-playlist a.jp-unmute { } div.jp-audio a.jp-volume-max { - margin-left: 56px; + margin-left: 56px; } div.jp-video a.jp-mute, @@ -302,7 +313,7 @@ div.jp-volume-bar { } div.jp-audio div.jp-volume-bar { top:37px; - left:330px; + left:260px; } div.jp-video div.jp-volume-bar { top:17px; @@ -323,8 +334,8 @@ div.jp-audio div.jp-time-holder { top:50px; } div.jp-audio div.jp-type-single div.jp-time-holder { - left:110px; - width:186px; + left:70px; + width:150px; } div.jp-audio div.jp-type-playlist div.jp-time-holder { left:166px; @@ -387,6 +398,7 @@ div.jp-title li { font-weight:bold; } div.jp-playlist li { + display: none; padding:5px 0 4px 20px; border-bottom:1px solid #eee; } diff --git a/src/catalogue/static/player/player.js b/src/catalogue/static/player/player.js index 69dceed55..a41d2c0ae 100755 --- a/src/catalogue/static/player/player.js +++ b/src/catalogue/static/player/player.js @@ -1,34 +1,53 @@ (function($) { $(function() { - $("#jplayer").each(function() { + $(".jp-jplayer").each(function() { var $self = $(this); + var $root = $self.parent(); + var $number = $('.number', $root); $self.jPlayer({ swfPath: "/static/jplayer/", solution: "html,flash", supplied: $self.attr('data-supplied'), - + cssSelectorAncestor: "#" + $self.attr("data-player"), + ready: function() { var player = $(this); var setMedia = function(elem) { var li = $(elem).parent(); - $('.jp-playlist-current').removeClass('jp-playlist-current'); - $(li).addClass('jp-playlist-current'); var media = {} - - $('.mp3', li).each(function() {media['mp3'] = $(this).attr('href')}); - $('.ogg', li).each(function() {media['oga'] = $(this).attr('href')}); - + + media['mp3'] = li.attr('data-mp3'); + media['oga'] = li.attr('data-ogg'); + + $(".title", $root).html(li.html()); return player.jPlayer("setMedia", media); }; - setMedia($('.play').first()).jPlayer("play"); - - $('.play').click(function() { - setMedia(this).jPlayer("play"); + + $('.play-next', $root).click(function() { + var next = parseInt($number.text()) + 1; + var p = $('.play:eq(' + next + ')', $root); + if (p.length) { + setMedia(p).jPlayer("play"); + $number.text(next) + } + }); + $('.play-prev', $root).click(function() { + var next = parseInt($number.text()) - 1; + if (next < 1) + return; + var p = $('.play:eq(' + next + ')', $root); + setMedia(p).jPlayer("play"); + $number.text(next) }); + + setMedia($('.play', $root).first()); + } }); }); + + }); -})(jQuery) \ No newline at end of file +})(jQuery) diff --git a/src/catalogue/tasks.py b/src/catalogue/tasks.py index a2b8be088..4807339ba 100644 --- a/src/catalogue/tasks.py +++ b/src/catalogue/tasks.py @@ -57,3 +57,9 @@ def build_custom_pdf(book_id, customizations, file_name, waiter_id=None): finally: if waiter_id is not None: WaitedFile.objects.filter(pk=waiter_id).delete() + + +@task(ignore_result=True) +def update_counters(): + from .helpers import update_counters + update_counters() diff --git a/src/catalogue/templates/catalogue/audiobook_list.html b/src/catalogue/templates/catalogue/audiobook_list.html index 75576f4ad..7eda46e4b 100644 --- a/src/catalogue/templates/catalogue/audiobook_list.html +++ b/src/catalogue/templates/catalogue/audiobook_list.html @@ -1,21 +1,21 @@ -{% extends "catalogue/book_list.html" %} +{% extends "base.html" %} {% load i18n %} -{% load catalogue_tags %} +{% load catalogue_tags switch_tag social_tags %} {% load ssi_include from ssify %} -{% block bodyid %}book-a-list{% endblock %} +{% block titleextra %}{% trans "Audiobooks" %}{% endblock %} -{% block titleextra %}{% trans "Listing of all audiobooks" %}{% endblock %} +{% block bodyid %}audiobooks{% endblock %} -{% block metadescription %}Darmowe audiobooki na wolnej licencji. Lektury czytane przez znanych aktorów.{% endblock %} +{% block body %} +

{% trans "Audiobooks" %}

-{% block extrahead %} - - -{% endblock %} + {% work_list best %} +

{% trans "Listing of all audiobooks" %}

+ {% plain_list books by_author=True %} + +

{% trans "Listing of all DAISY files" %}

+ {% plain_list daisy by_author=True %} -{% block book_list_header %}{% trans "Listing of all audiobooks" %}{% endblock %} -{% block book_list_info %} -{% ssi_include 'chunk' key='audiobook-list' %} {% endblock %} diff --git a/src/catalogue/templates/catalogue/book_detail.html b/src/catalogue/templates/catalogue/book_detail.html index 7e8128fa7..b87e9eb1f 100644 --- a/src/catalogue/templates/catalogue/book_detail.html +++ b/src/catalogue/templates/catalogue/book_detail.html @@ -28,9 +28,49 @@ {% endif %}
-

{% trans "See also" %}:

+

{% trans "See also" %}:

{% related_books book taken=book.other_versions|length %}
{% endspaceless %} + + +{% with book.related_themes as themes %} +{% if themes %} +

{% trans "Themes" %}

+ {% plain_list themes book=book %} +{% endif %} +{% endwith %} + + + +

{% trans "Information about the work" %}

+{% for tag in tags %} + +{% endfor %} + + + {% if extra_info.source_url %} +
{% trans "Source" %} {% trans "of the book" %} + {% trans "in" %} {% source_name extra_info.source_url %}
+ {% endif %} + + {% if extra_info.about and not hide_about %} +
{% trans "Book on" %} {% trans "Editor's Platform" %}
+ {% endif %} + {% if book.gazeta_link %} + + {% endif %} + {% if book.wiki_link %} + + {% endif %} + + + + + {% endblock %} diff --git a/src/catalogue/templates/catalogue/book_short.html b/src/catalogue/templates/catalogue/book_short.html index b069cb585..a2b0a5c41 100644 --- a/src/catalogue/templates/catalogue/book_short.html +++ b/src/catalogue/templates/catalogue/book_short.html @@ -12,40 +12,40 @@
-{% likes_book book.pk as likes %} -
-
- ★ -
-
-
- {% ssi_csrf_token %} - -
+ {% likes_book book.pk as likes %} +
+
+ ★ +
+
+
+ {% ssi_csrf_token %} + +
+
-
- -
-
- {% for tag in tags.author %} - {{ tag.name }}{% if not forloop.last %}, - {% endif %}{% endfor %}{% for parent in parents %}, - {{ parent.title }}{% endfor %} -
-
- {% if main_link %}{% endif %}{{ book.title }}{% if main_link %}{% endif %} -
+
+
+ {% for tag in tags.author %} + {{ tag.name }}{% if not forloop.last %}, + {% endif %}{% endfor %}{% for parent in parents %}, + {{ parent.title }}{% endfor %} +
+
+ {% if main_link %}{% endif %}{{ book.title }}{% if main_link %}{% endif %}
+
+ +
+ {% if book.cover_thumb %} + {% if main_link %}{% endif %} + Cover + {% if main_link %}{% endif %} + {% endif %} + {% block cover-area-extra %}{% endblock %} +
-
- {% if book.cover_thumb %} - {% if main_link %}{% endif %} - Cover - {% if main_link %}{% endif %} - {% endif %} - {% block cover-area-extra %}{% endblock %} -
{% spaceless %} @@ -97,39 +97,107 @@ {% trans "Read online" %} {% endif %} -
  • - {% trans "Download" %} +
  • + {% trans "Download" %}:
    {% if book.pdf_file %} - PDF {% trans "to print" %} + PDF {% endif %} - {% if book.epub_file %} - EPUB {% trans "for an e-book reader" %} + {% custom_pdf_link_li book %} + {% if book.epub_file %} + EPUB {% endif %} - {% if book.mobi_file %} - MOBI {% trans "for Kindle" %} + {% if book.mobi_file %} + MOBI {% endif %} {% if book.fb2_file %} - FB2 {% trans "FictionBook" %} + FB2 {% endif %} {% if book.txt_file %} - TXT {% trans "for advanced usage" %} + TXT {% endif %} + {% download_audio book %}
    -
  • -
  • - {% if has_audio %} - {% trans "Listen" %} - {% endif %} + +
  • {% block book-box-extra-info %}{% endblock %} {% block box-append %} {% endblock %}
    + + + + + + {% block right-column %} {% endblock %} + + +{% if audiobooks %} + + + +{% endif %} + +
    -{% endspaceless %} \ No newline at end of file +{% endspaceless %} diff --git a/src/catalogue/templates/catalogue/book_wide.html b/src/catalogue/templates/catalogue/book_wide.html index b84acdb53..4d5617566 100644 --- a/src/catalogue/templates/catalogue/book_wide.html +++ b/src/catalogue/templates/catalogue/book_wide.html @@ -16,23 +16,6 @@ -{% block book-box-extra-info %} -{% if themes %} -
    -

    {% trans "Motifs and themes" %}

    -
    - -
    -
    -{% else %} -

     

    -{% endif %} -{% endblock %} {% block right-column %} @@ -48,37 +31,5 @@ {{ fragment_promo.endif }}
    -
    -

    {% trans "See" %}

    - -
    -
    -

    {% trans "Download" %}

    -
      -
    • - {% if related.media.mp3 or related.media.ogg or related.media.daisy %} - {% trans "Download all audiobooks for this book" %}: - {% download_audio book %}. - {% endif %} -
    • - {% custom_pdf_link_li book %} -
    -
    {% endblock %} diff --git a/src/catalogue/templates/catalogue/catalogue.html b/src/catalogue/templates/catalogue/catalogue.html index c7cee4096..6b6957852 100644 --- a/src/catalogue/templates/catalogue/catalogue.html +++ b/src/catalogue/templates/catalogue/catalogue.html @@ -8,7 +8,8 @@ {% block bodyid %}catalogue-catalogue{% endblock %} {% block body %} -

    {% trans "Catalogue" %}

    +

    {% trans "All works" %}

    +
    @@ -16,23 +17,15 @@ {% trans "Download the catalogue in PDF format." %}

    -

    {% trans "Authors" %}

    -
    {{ output.author }}
    - -

    {% trans "Kinds" %}

    -
    {{ output.kind }}
    - -

    {% trans "Genres" %}

    -
    {{ output.genre }}
    +

    {% trans "Literature" %}

    + {% plain_list books by_author=True paged=False %} -

    {% trans "Epochs" %}

    -
    {{ output.epoch }}
    +

    {% trans "Collections" %}

    + {% plain_list collections paged=False %} -

    {% trans "Themes and topics" %}

    -
    {{ output.theme }}
    +

    {% trans "Gallery" %}

    + {% plain_list pictures by_author=True paged=False %} -

    {% trans "Collections" %}

    -
    {{ output.collections }}
    {% endblock %} diff --git a/src/catalogue/templates/catalogue/collection.html b/src/catalogue/templates/catalogue/collection.html index 4bb12c938..cf43ef36b 100755 --- a/src/catalogue/templates/catalogue/collection.html +++ b/src/catalogue/templates/catalogue/collection.html @@ -1,10 +1,17 @@ -{% extends "catalogue/book_list.html" %} +{% extends "base.html" %} {% load i18n %} +{% load catalogue_tags %} -{% block titleextra %}{{ context.collection.title }}{% endblock %} +{% block titleextra %}{{ collection.title }}{% endblock %} + +{% block bodyid %}collection{% endblock %} + +{% block body %} +

    {{ collection.title }}

    + + {{ collection.description|safe }} + + {% plain_list collection.get_books by_author=True %} -{% block book_list_header %}{{ context.collection.title }}{% endblock %} -{% block book_list_info %} -{{ context.collection.description|safe }} {% endblock %} diff --git a/src/catalogue/templates/catalogue/collection_box.html b/src/catalogue/templates/catalogue/collection_box.html new file mode 100644 index 000000000..7c092943c --- /dev/null +++ b/src/catalogue/templates/catalogue/collection_box.html @@ -0,0 +1,21 @@ +{% spaceless %} +{% load i18n %} +{% load ssi_include from ssify %} +
    +

    {% trans "Collection" %}: {{ obj }}

    + {% if obj.description %} + {{ obj.description|safe|truncatewords_html:40 }} + {% endif %} + {% for b in obj.get_books|slice:":5" %} + {% ssi_include 'catalogue_book_mini' pk=b.pk %} + {% endfor %} + {% with obj.get_books.count|add:-5 as more %} + {% if more > 0 %} + + {% blocktrans with c=more %}and {{ c }} more{% endblocktrans %} + + {% endif %} + {% endwith %} + +
    +{% endspaceless %} diff --git a/src/catalogue/templates/catalogue/collections.html b/src/catalogue/templates/catalogue/collections.html new file mode 100644 index 000000000..1c6987278 --- /dev/null +++ b/src/catalogue/templates/catalogue/collections.html @@ -0,0 +1,22 @@ +{% extends "base.html" %} +{% load i18n %} +{% load catalogue_tags %} +{% load ssi_include from ssify %} + +{% block titleextra %}{% trans "Collections" %}{% endblock %} + +{% block bodyid %}collections{% endblock %} + +{% block body %} +

    {% trans "Collections" %}

    + + {% for obj in best %} + {% ssi_include 'catalogue_collection_box' pk=obj.pk %} + {% endfor %} + +

    {% trans "All collections" %}

    + {% plain_list objects %} + + + +{% endblock %} diff --git a/src/catalogue/templates/catalogue/inline_tag_list.html b/src/catalogue/templates/catalogue/inline_tag_list.html index 59b1acce9..920b55500 100755 --- a/src/catalogue/templates/catalogue/inline_tag_list.html +++ b/src/catalogue/templates/catalogue/inline_tag_list.html @@ -1,17 +1,37 @@ {% load i18n %} {% load catalogue_tags %} -{% if one_tag %} - {% trans "See full category" %} {{ one_tag }} -{% else %} -
      {% if choices %} + {% if category_choices %} +
        +
      • {% trans "Chosen" %}:
      • + {% for tag in category_choices %} +
      • {{ tag }} X
      • + {% endfor %} +
      + {% endif %} + {% if tags %} + + {% endif %} + {% else %} + {% if tags %} + + {% endif %} {% endif %} + {% if other %} +
        +
      • {% trans "Other" %}:
      • + {% for tag in other %} +
      • {{ tag }}
      • + {% endfor %}
      -{% endif %} + {% endif %} diff --git a/src/catalogue/templates/catalogue/menu.html b/src/catalogue/templates/catalogue/menu.html deleted file mode 100644 index 5ddbd3b23..000000000 --- a/src/catalogue/templates/catalogue/menu.html +++ /dev/null @@ -1,41 +0,0 @@ -{% spaceless %} -{% load i18n static %} - - - {% trans "Catalogue of the library" %} - {% trans "Catalogue" %} - - - -{% endspaceless %} \ No newline at end of file diff --git a/src/catalogue/templates/catalogue/plain_list.html b/src/catalogue/templates/catalogue/plain_list.html new file mode 100644 index 000000000..276e55e42 --- /dev/null +++ b/src/catalogue/templates/catalogue/plain_list.html @@ -0,0 +1,19 @@ +{% spaceless %} +{% load catalogue_tags %} + + +
      +
      +{% for initial, object_list in names %} + {% if initial %} +

      {{ initial }}

      + {% endif %} + {% for item in object_list %} +

      {{ item }}{% if item.count %} ({{ item.count}}){% endif %}

      + {% endfor %} +{% endfor %} +
      +
      +
      + +{% endspaceless %} diff --git a/src/catalogue/templates/catalogue/player.html b/src/catalogue/templates/catalogue/player.html index 701fbe850..5ddb91306 100755 --- a/src/catalogue/templates/catalogue/player.html +++ b/src/catalogue/templates/catalogue/player.html @@ -6,7 +6,7 @@ {% load thumbnail %} - {% trans "Wolne Lektury" %} :: {{ book.title }} - {{ audiobook }} @@ -26,7 +26,7 @@ {% endthumbnail %} " alt="Cover" style="float: left; margin: .5em 1em 1em 1em;" /> {% endif %} - +

      {% book_title book %}

      @@ -79,10 +79,6 @@ {% for i in audiobooks %}
    • -
      {{ i.mp3.name }}
      {% trans "Artist" %}: {{ i.mp3.extra_info.artist_name }}, diff --git a/src/catalogue/templates/catalogue/search_multiple_hits.html b/src/catalogue/templates/catalogue/search_multiple_hits.html index d1e1dedf7..24a7a7930 100644 --- a/src/catalogue/templates/catalogue/search_multiple_hits.html +++ b/src/catalogue/templates/catalogue/search_multiple_hits.html @@ -17,34 +17,42 @@
      {% if tags.author %}
      -
      {% trans "Authors" %}:
      -
      - {% inline_tag_list tags.author %} -
      +

      {% trans "Authors" %}:

      + {% for tag in tags.author %} + + {% ssi_include "catalogue_tag_box" pk=tag.pk %} + + {% endfor %}
      {% endif %} {% if tags.kind %}
      -
      {% trans "Kinds" %}:
      -
      - {% inline_tag_list tags.kind %} -
      +

      {% trans "Kinds" %}:

      + {% for tag in tags.kind %} + + {% ssi_include "catalogue_tag_box" pk=tag.pk %} + + {% endfor %}
      {% endif %} {% if tags.genre %}
      -
      {% trans "Genres" %}:
      -
      - {% inline_tag_list tags.genre %} -
      +

      {% trans "Genres" %}:

      + {% for tag in tags.genre %} + + {% ssi_include "catalogue_tag_box" pk=tag.pk %} + + {% endfor %}
      {% endif %} {% if tags.epoch %}
      -
      {% trans "Epochs" %}:
      -
      - {% inline_tag_list tags.epoch %} -
      +

      {% trans "Epochs" %}:

      + {% for tag in tags.epoch %} + + {% ssi_include "catalogue_tag_box" pk=tag.pk %} + + {% endfor %}
      {% endif %}
      @@ -63,7 +71,7 @@
      {% endif %} - + {% if results.author %}
      diff --git a/src/catalogue/templates/catalogue/snippets/custom_pdf_link_li.html b/src/catalogue/templates/catalogue/snippets/custom_pdf_link_li.html index 353ad8bdf..1528f3a30 100644 --- a/src/catalogue/templates/catalogue/snippets/custom_pdf_link_li.html +++ b/src/catalogue/templates/catalogue/snippets/custom_pdf_link_li.html @@ -1,7 +1,4 @@ {% load i18n %} {% if not NO_CUSTOM_PDF %} -
    • - {% trans "Download a custom PDF" %} -
    • + {% trans "Download a custom PDF" %} {% endif %} diff --git a/src/catalogue/templates/catalogue/tag_box.html b/src/catalogue/templates/catalogue/tag_box.html new file mode 100644 index 000000000..122b67057 --- /dev/null +++ b/src/catalogue/templates/catalogue/tag_box.html @@ -0,0 +1,13 @@ +{% spaceless %} +{% load i18n %} +{% load catalogue_tags %} +
      +

      {% trans tag.category as c %}{{ c|capfirst }}: {{ tag }}

      + {% if tag.description %} + {{ tag.description|safe|truncatewords_html:40 }} + {% else %} + No description + {% endif %} + +
      +{% endspaceless %} diff --git a/src/catalogue/templates/catalogue/tag_catalogue.html b/src/catalogue/templates/catalogue/tag_catalogue.html new file mode 100644 index 000000000..0279a0e64 --- /dev/null +++ b/src/catalogue/templates/catalogue/tag_catalogue.html @@ -0,0 +1,23 @@ +{% extends "base.html" %} +{% load i18n %} +{% load plain_list from catalogue_tags %} +{% load ssi_include from ssify %} + +{% block titleextra %}{{ title }}{% endblock %} + +{% block bodyid %}tag-catalogue{% endblock %} + +{% block body %} +

      {{ title|title }} {% trans "on Wolne Lektury" %}

      + +{% for tag in best %} + + {% ssi_include "catalogue_tag_box" pk=tag.pk %} + +{% endfor %} + +

      All {{ title }}

      + +{% plain_list tags %} + +{% endblock %} diff --git a/src/catalogue/templates/catalogue/tagged_object_list.html b/src/catalogue/templates/catalogue/tagged_object_list.html index 3df560a6f..033cf9a5a 100644 --- a/src/catalogue/templates/catalogue/tagged_object_list.html +++ b/src/catalogue/templates/catalogue/tagged_object_list.html @@ -3,165 +3,113 @@ {% load catalogue_tags switch_tag social_tags %} {% load ssi_include from ssify %} -{% block titleextra %}{% title_from_tags tags %}{% endblock %} +{% block titleextra %}{% if tags %}{% title_from_tags tags %}{% elif gallery %}{% trans "Gallery" %}{% else %}{% trans "Literature" %}{% endif %}{% endblock %} {% block bodyid %}tagged-object-list{% endblock %} {% block body %} -
      -
      -

      {% html_title_from_tags tags %}

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

      {% if tags %} + {% html_title_from_tags tags %} + {% elif gallery %}{% trans "Gallery" %}{% else %}{% trans "Literature" %} + {% endif %} +

      + + - {% 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 %} - - {% if categories.theme %} -
      -

      - {% trans "Motifs and themes" %}

      -
      - {% tag_list categories.theme tags %} -
      -
      - {% endif %} +
      +
      +
      + {% inline_tag_list categories.author tags 'author' gallery=gallery %} +
      +
      + {% inline_tag_list categories.epoch tags 'epoch' gallery=gallery %}
      +
      + {% inline_tag_list categories.genre tags 'genre' gallery=gallery %} +
      +
      + {% inline_tag_list categories.kind tags 'kind' gallery=gallery %} +
      + {% if theme_is_set %} +
      + {% inline_tag_list categories.theme tags 'theme' gallery=gallery %} +
      + {% endif %} +
      -
      - {% if theme_is_set %} -
      - {% if last_tag.gazeta_link or last_tag.wiki_link %} -

      {% trans "See also" %}:

      -
        - {% if last_tag.culturepl_link %} -
      • - {% trans "in Culture.pl" %} -
      • - {% endif %} - {% if last_tag.gazeta_link %} -
      • - {% trans "in Lektury.Gazeta.pl" %} -
      • - {% endif %} - {% if last_tag.wiki_link %} -
      • - {% trans "in Wikipedia" %} -
      • + + {% if theme_is_set %} + {% work_list object_list %} + {% else %} +
        + {% if object_list %} + {% work_list best %} +

        {% trans "All matching works" %}

        + {% plain_list object_list by_author=True gallery=gallery %} + {% else %} + {% trans "Sorry! Search cirteria did not match any resources." %} + {% include "info/join_us.html" %} {% endif %} -
      - {% endif %} -
      - {% endif %} +
      -
      -
      -
      - {% if theme_is_set %} - {% work_list object_list %} - {% else %} +{% if categories.theme %} +

      {% trans "Motifs and themes" %}

      + {% plain_list categories.theme choice=tags gallery=gallery %} +{% endif %} - {% choose_cite tag_ids=tag_ids as cite_promo_pk %} - {% choose_fragment tag_ids=tag_ids unless=cite_promo_pk as fragment_promo_pk %} - {{ cite_promo_pk.if }} - {% ssi_include 'social_cite' pk=cite_promo_pk %} - {{ cite_promo_pk.endif }} - {{ fragment_promo_pk.if }} - {% ssi_include 'catalogue_fragment_promo' pk=fragment_promo_pk %} - {{ fragment_promo_pk.endif }} - -
      - {% if last_tag.gazeta_link or last_tag.wiki_link %} -

      {% trans "See also" %}:

      - - {% endif %}
      -
      - {% comment %} -

      {% trans "Download" %}:

      - - {% endcomment %} -
      + {% if tag.gazeta_link %} + {% endif %} + {% if tag.wiki_link %} + + {% endif %} + {% if tag.culturepl_link %} + + {% endif %} + {% endif %} + {% endfor %} -
      -
      - {% if not theme_is_set %} -
      - {% if object_list %} - {% work_list object_list %} - {% else %} - {% trans "Sorry! Search cirteria did not match any resources." %} - {% include "info/join_us.html" %} - {% endif %} -
      - {% endif %} - {% endwith %} {% endblock %} diff --git a/src/catalogue/templatetags/catalogue_tags.py b/src/catalogue/templatetags/catalogue_tags.py index 6e81caec2..fd914e321 100644 --- a/src/catalogue/templatetags/catalogue_tags.py +++ b/src/catalogue/templatetags/catalogue_tags.py @@ -4,6 +4,7 @@ # from random import randint, random from urlparse import urlparse +from django.contrib.contenttypes.models import ContentType from django.conf import settings from django import template @@ -242,10 +243,26 @@ def catalogue_url(parser, token): return CatalogueURLNode(tags_to_add, tags_to_remove) +@register.tag +def catalogue_url_gallery(parser, token): + bits = token.split_contents() + + tags_to_add = [] + tags_to_remove = [] + for bit in bits[1:]: + if bit[0] == '-': + tags_to_remove.append(bit[1:]) + else: + tags_to_add.append(bit) + + return CatalogueURLNode(tags_to_add, tags_to_remove, gallery=True) + + class CatalogueURLNode(Node): - def __init__(self, tags_to_add, tags_to_remove): + def __init__(self, tags_to_add, tags_to_remove, gallery=False): self.tags_to_add = [Variable(tag) for tag in tags_to_add] self.tags_to_remove = [Variable(tag) for tag in tags_to_remove] + self.gallery = gallery def render(self, context): tags_to_add = [] @@ -273,23 +290,40 @@ class CatalogueURLNode(Node): pass if len(tag_slugs) > 0: - return reverse('tagged_object_list', kwargs={'tags': '/'.join(tag_slugs)}) + if self.gallery: + return reverse('tagged_object_list_gallery', kwargs={'tags': '/'.join(tag_slugs)}) + else: + return reverse('tagged_object_list', kwargs={'tags': '/'.join(tag_slugs)}) else: - return reverse('main_page') + return reverse('book_list') @register.inclusion_tag('catalogue/tag_list.html') -def tag_list(tags, choices=None): +def tag_list(tags, choices=None, category=None, gallery=False): + print(tags, choices, category) if choices is None: choices = [] - if len(tags) == 1 and tags[0].category not in [t.category for t in choices]: + + if category is None and tags: + category = tags[0].category + + category_choices = [tag for tag in choices if tag.category == category] + + if len(tags) == 1 and category not in [t.category for t in choices]: one_tag = tags[0] + + if category is not None: + other = Tag.objects.filter(category=category).exclude(pk__in=[t.pk for t in tags]).exclude(pk__in=[t.pk for t in category_choices]) + # Filter out empty tags. + ct = ContentType.objects.get_for_model(Picture if gallery else Book) + other = other.filter(items__content_type=ct).distinct() + return locals() @register.inclusion_tag('catalogue/inline_tag_list.html') -def inline_tag_list(tags, choices=None): - return tag_list(tags, choices) +def inline_tag_list(tags, choices=None, category=None, gallery=False): + return tag_list(tags, choices, category, gallery) @register.inclusion_tag('catalogue/collection_list.html') @@ -311,6 +345,25 @@ def work_list(context, object_list): return locals() + +@register.inclusion_tag('catalogue/plain_list.html', takes_context=True) +def plain_list(context, object_list, with_initials=True, by_author=False, choice=None, book=None, gallery=False, paged=True): + names = [(None, [])] + last_initial = None + for obj in object_list: + if with_initials: + if by_author: + initial = obj.sort_key_author + else: + initial = obj.get_initial().upper() + if initial != last_initial: + last_initial = initial + names.append((obj.author_str() if by_author else initial, [])) + names[-1][1].append(obj) + return locals() + + + # TODO: These are no longer just books. @register.inclusion_tag('catalogue/related_books.html', takes_context=True) def related_books(context, instance, limit=6, random=1, taken=0): @@ -347,17 +400,6 @@ def related_books(context, instance, limit=6, random=1, taken=0): } -@register.inclusion_tag('catalogue/menu.html') -def catalogue_menu(): - return {'categories': [ - ('author', _('Authors'), 'autorzy'), - ('genre', _('Genres'), 'gatunki'), - ('kind', _('Kinds'), 'rodzaje'), - ('epoch', _('Epochs'), 'epoki'), - ('theme', _('Themes'), 'motywy'), - ]} - - @register.simple_tag def download_audio(book, daisy=True): links = [] @@ -373,7 +415,7 @@ def download_audio(book, daisy=True): for dsy in book.get_media('daisy'): links.append("%s" % (dsy.file.url, BookMedia.formats['daisy'].name)) - return ", ".join(links) + return "".join(links) @register.inclusion_tag("catalogue/snippets/custom_pdf_link_li.html") diff --git a/src/catalogue/urls.py b/src/catalogue/urls.py index b7c59a055..35a08e11d 100644 --- a/src/catalogue/urls.py +++ b/src/catalogue/urls.py @@ -32,7 +32,16 @@ urlpatterns += patterns('', urlpatterns += patterns('catalogue.views', url(r'^$', 'catalogue', name='catalogue'), - url(r'^lektury/$', 'book_list', name='book_list'), + url(r'^autor/$', 'tag_catalogue', {'category': 'author'}, name='author_catalogue'), + url(r'^epoka/$', 'tag_catalogue', {'category': 'epoch'}, name='epoch_catalogue'), + url(r'^gatunek/$', 'tag_catalogue', {'category': 'genre'}, name='genre_catalogue'), + url(r'^rodzaj/$', 'tag_catalogue', {'category': 'kind'}, name='kind_catalogue'), + url(r'^motyw/$', 'tag_catalogue', {'category': 'theme'}, name='theme_catalogue'), + + url(r'^galeria/$', 'tagged_object_list', {'gallery': True}, name='gallery'), + url(r'^kolekcje/$', 'collections', name='catalogue_collections'), + + url(r'^lektury/$', 'tagged_object_list', name='book_list'), url(r'^lektury/(?P[a-zA-Z0-9-]+)/$', 'collection', name='collection'), url(r'^audiobooki/$', 'audiobook_list', name='audiobook_list'), url(r'^daisy/$', 'daisy_list', name='daisy_list'), @@ -75,7 +84,10 @@ urlpatterns += patterns('catalogue.views', url(r'^b/(?P\d+)/wide\.(?P.+)\.html', 'book_wide', name='catalogue_book_wide'), url(r'^f/(?P\d+)/promo\.(?P.+)\.html', 'fragment_promo', name='catalogue_fragment_promo'), url(r'^f/(?P\d+)/short\.(?P.+)\.html', 'fragment_short', name='catalogue_fragment_short'), + url(r'^t/(?P\d+)/box\.(?P.+)\.html', 'tag_box', name='catalogue_tag_box'), + url(r'^c/(?P.+)/box\.(?P.+)\.html', 'collection_box', name='catalogue_collection_box'), # This should be the last pattern. + url(r'^galeria/(?P[a-zA-Z0-9-/]*)/$', 'tagged_object_list', {'gallery': True}, name='tagged_object_list_gallery'), url(r'^(?P[a-zA-Z0-9-/]*)/$', 'tagged_object_list', name='tagged_object_list'), ) diff --git a/src/catalogue/utils.py b/src/catalogue/utils.py index bcc5a0b33..71cd8907a 100644 --- a/src/catalogue/utils.py +++ b/src/catalogue/utils.py @@ -342,17 +342,5 @@ class AppSettings(object): return value -def trim_query_log(trim_to=25): - """ -connection.queries includes all SQL statements -- INSERTs, UPDATES, SELECTs, etc. Each time your app hits the database, the query will be recorded. -This can sometimes occupy lots of memory, so trim it here a bit. - """ - if settings.DEBUG: - from django.db import connection - connection.queries = trim_to > 0 \ - and connection.queries[-trim_to:] \ - or [] - - def delete_from_cache_by_language(cache, key_template): cache.delete_many([key_template % lc for lc, ln in settings.LANGUAGES]) diff --git a/src/catalogue/views.py b/src/catalogue/views.py index a25a08ffa..5a8277f88 100644 --- a/src/catalogue/views.py +++ b/src/catalogue/views.py @@ -4,11 +4,12 @@ # from collections import OrderedDict import re +import random from django.conf import settings from django.template import RequestContext from django.template.loader import render_to_string -from django.shortcuts import render_to_response, get_object_or_404, render +from django.shortcuts import render_to_response, get_object_or_404, render, redirect from django.http import HttpResponse, HttpResponseRedirect, Http404, HttpResponsePermanentRedirect, JsonResponse from django.core.urlresolvers import reverse from django.db.models import Q @@ -24,67 +25,21 @@ from picture.models import Picture, PictureArea from picture.views import picture_list_thumb from ssify import ssi_included, ssi_expect, SsiVariable as V from suggest.forms import PublishingSuggestForm +from catalogue import constants from catalogue import forms from catalogue.helpers import get_top_level_related_tags from catalogue import models -from catalogue.utils import split_tags, MultiQuerySet, SortedMultiQuerySet +from catalogue.utils import split_tags from catalogue.templatetags.catalogue_tags import tag_list, collection_list staff_required = user_passes_test(lambda user: user.is_staff) def catalogue(request, as_json=False): - common_categories = ('author',) - split_categories = ('epoch', 'genre', 'kind') - - categories = split_tags( - get_top_level_related_tags(categories=common_categories), - models.Tag.objects.usage_for_model( - models.Fragment, counts=True).filter(category='theme'), - models.Tag.objects.usage_for_model( - Picture, counts=True).filter(category__in=common_categories), - models.Tag.objects.usage_for_model( - PictureArea, counts=True).filter( - category='theme') - ) - book_categories = split_tags( - get_top_level_related_tags(categories=split_categories) - ) - picture_categories = split_tags( - models.Tag.objects.usage_for_model( - Picture, counts=True).filter( - category__in=split_categories), - ) - + books = models.Book.objects.filter(parent=None) + pictures = Picture.objects.all() collections = models.Collection.objects.all() - - def render_tag_list(tags): - return render_to_string('catalogue/tag_list.html', tag_list(tags)) - - def render_split(with_books, with_pictures): - ctx = {} - if with_books: - ctx['books'] = render_tag_list(with_books) - if with_pictures: - ctx['pictures'] = render_tag_list(with_pictures) - return render_to_string('catalogue/tag_list_split.html', ctx) - - output = {} - output['theme'] = render_tag_list(categories.get('theme', [])) - for category in common_categories: - output[category] = render_tag_list(categories.get(category, [])) - for category in split_categories: - output[category] = render_split( - book_categories.get(category, []), - picture_categories.get(category, [])) - - output['collections'] = render_to_string( - 'catalogue/collection_list.html', collection_list(collections)) - if as_json: - return JsonResponse(output) - else: - return render_to_response('catalogue/catalogue.html', locals(), - context_instance=RequestContext(request)) + return render(request, 'catalogue/catalogue.html', locals()) @ssi_included @@ -113,10 +68,20 @@ def book_list(request, filter=None, get_filter=None, def audiobook_list(request): - return book_list(request, Q(media__type='mp3') | Q(media__type='ogg'), - template_name='catalogue/audiobook_list.html', - list_template_name='catalogue/snippets/audiobook_list.html', - ) + books = models.Book.objects.filter(Q(media__type='mp3') | Q(media__type='ogg')).distinct() + books = list(books) + if len(books) > 3: + best = random.sample(books, 3) + else: + best = books + + daisy = models.Book.objects.filter(media__type='daisy').distinct() + + return render(request, 'catalogue/audiobook_list.html', { + 'books': books, + 'best': best, + 'daisy': daisy, + }) def daisy_list(request): @@ -127,17 +92,8 @@ def daisy_list(request): def collection(request, slug): coll = get_object_or_404(models.Collection, slug=slug) - if coll.kind == 'book': - view = book_list - tmpl = "catalogue/collection.html" - elif coll.kind == 'picture': - view = picture_list_thumb - tmpl = "picture/collection.html" - else: - raise ValueError('How do I show this kind of collection? %s' % coll.kind) - return view(request, get_filter=coll.get_query, - template_name=tmpl, - context={'collection': coll}) + return render(request, 'catalogue/collection.html', + {'collection': coll}) def differentiate_tags(request, tags, ambiguous_slugs): @@ -155,7 +111,8 @@ def differentiate_tags(request, tags, ambiguous_slugs): # TODO: Rewrite this hellish piece of code which tries to do everything -def tagged_object_list(request, tags=''): +def tagged_object_list(request, tags='', gallery=False): + raw_tags = tags # preliminary tests and conditions try: tags = models.Tag.get_tag_list(tags) @@ -189,58 +146,87 @@ def tagged_object_list(request, tags=''): objects = None if theme_is_set: + # Only fragments (or pirctureareas) here. shelf_tags = [tag for tag in tags if tag.category == 'set'] fragment_tags = [tag for tag in tags if tag.category != 'set'] - fragments = models.Fragment.tagged.with_all(fragment_tags) - areas = PictureArea.tagged.with_all(fragment_tags) + if gallery: + fragments = PictureArea.tagged.with_all(fragment_tags) + else: + fragments = models.Fragment.tagged.with_all(fragment_tags) if shelf_tags: - books = models.Book.tagged.with_all(shelf_tags).order_by() - fragments = fragments.filter(Q(book__in=books) | Q(book__ancestor__in=books)) - areas = PictureArea.objects.none() + if gallery: + # TODO: Pictures on shelves not supported yet. + raise Http404 + else: + books = models.Book.tagged.with_all(shelf_tags).order_by() + fragments = fragments.filter(Q(book__in=books) | Q(book__ancestor__in=books)) categories = split_tags( models.Tag.objects.usage_for_queryset(fragments, counts=True ).exclude(pk__in=tags_pks), - models.Tag.objects.usage_for_queryset(areas, counts=True - ).exclude(pk__in=tags_pks) ) - # we want the Pictures to go first - objects = MultiQuerySet(areas, fragments) + objects = fragments else: - all_books = models.Book.tagged.with_all(tags) - if shelf_is_set: - books = all_books.order_by('sort_key_author', 'title') - pictures = Picture.objects.none() - related_book_tags = models.Tag.objects.usage_for_queryset( - books, counts=True).exclude( - category='set').exclude(pk__in=tags_pks) + if gallery: + if shelf_is_set: + # TODO: Pictures on shelves not supported yet. + raise Http404 + else: + if tags: + objects = Picture.tagged.with_all(tags).order_by( + 'sort_key_author', 'title') + else: + objects = Picture.objects.all().order_by( + 'sort_key_author', 'title') + areas = PictureArea.objects.filter(picture__in=objects) + categories = split_tags( + models.Tag.objects.usage_for_queryset( + objects, counts=True).exclude(pk__in=tags_pks), + models.Tag.objects.usage_for_queryset( + areas, counts=True).filter( + category__in=('theme', 'thing')).exclude( + pk__in=tags_pks), + ) else: - books = models.Book.tagged_top_level(tags).order_by( - 'sort_key_author', 'title') - pictures = Picture.tagged.with_all(tags).order_by( - 'sort_key_author', 'title') + if tags: + all_books = models.Book.tagged.with_all(tags) + else: + all_books = models.Book.objects.filter(parent=None) + if shelf_is_set: + objects = all_books.order_by('sort_key_author', 'title') + related_book_tags = models.Tag.objects.usage_for_queryset( + objects, counts=True).exclude( + category='set').exclude(pk__in=tags_pks) + else: + if tags: + objects = models.Book.tagged_top_level(tags).order_by( + 'sort_key_author', 'title') + else: + objects = all_books.order_by('sort_key_author', 'title') related_book_tags = get_top_level_related_tags(tags) - fragments = models.Fragment.objects.filter(book__in=all_books) - areas = PictureArea.objects.filter(picture__in=pictures) + fragments = models.Fragment.objects.filter(book__in=all_books) - categories = split_tags( - related_book_tags, - models.Tag.objects.usage_for_queryset( - pictures, counts=True).exclude(pk__in=tags_pks), - models.Tag.objects.usage_for_queryset( - fragments, counts=True).filter( - category='theme').exclude(pk__in=tags_pks), - models.Tag.objects.usage_for_queryset( - areas, counts=True).filter( - category__in=('theme', 'thing')).exclude( - pk__in=tags_pks), - ) + categories = split_tags( + related_book_tags, + models.Tag.objects.usage_for_queryset( + fragments, counts=True).filter( + category='theme').exclude(pk__in=tags_pks), + ) - objects = SortedMultiQuerySet(pictures, books, - order_by=('sort_key_author', 'title')) + objects = list(objects) + if len(objects) > 3: + best = random.sample(objects, 3) + else: + best = objects + + if not gallery and not objects and len(tags) == 1: + tag = tags[0] + if (tag.category in ('theme', 'thing') and PictureArea.tagged.with_any([tag]).exists() or + Picture.tagged.with_any([tag]).exists()): + return redirect('tagged_object_list_gallery', raw_tags, permanent=False) return render_to_response('catalogue/tagged_object_list.html', { @@ -252,6 +238,8 @@ def tagged_object_list(request, tags=''): 'tags': tags, 'tag_ids': tags_pks, 'theme_is_set': theme_is_set, + 'best': best, + 'gallery': gallery, }, context_instance=RequestContext(request)) @@ -272,16 +260,13 @@ def book_detail(request, slug): except models.Book.DoesNotExist: return pdcounter_views.book_stub_detail(request, slug) + tags = book.tags.exclude(category__in=('set', 'theme')) book_children = book.children.all().order_by('parent_number', 'sort_key') return render_to_response('catalogue/book_detail.html', locals(), context_instance=RequestContext(request)) -def player(request, slug): - book = get_object_or_404(models.Book, slug=slug) - if not book.has_media('mp3'): - raise Http404 - +def get_audiobooks(book): ogg_files = {} for m in book.media.filter(type='ogg').order_by().iterator(): ogg_files[m.name] = m @@ -309,6 +294,15 @@ def player(request, slug): audiobooks.append(media) projects = sorted(projects) + return audiobooks, projects, have_oggs + + +def player(request, slug): + book = get_object_or_404(models.Book, slug=slug) + if not book.has_media('mp3'): + raise Http404 + + audiobooks, projects, have_oggs = get_audiobooks(book) extra_info = book.extra_info @@ -636,6 +630,7 @@ def book_mini(request, pk, with_link=True): def book_short(request, pk): book = get_object_or_404(models.Book, pk=pk) stage_note, stage_note_url = book.stage_note() + audiobooks, projects, have_oggs = get_audiobooks(book) return render(request, 'catalogue/book_short.html', { 'book': book, @@ -646,6 +641,8 @@ def book_short(request, pk): 'show_lang': book.language_code() != settings.LANGUAGE_CODE, 'stage_note': stage_note, 'stage_note_url': stage_note_url, + 'audiobooks': audiobooks, + 'have_oggs': have_oggs, }) @@ -659,6 +656,7 @@ def book_wide(request, pk): book = get_object_or_404(models.Book, pk=pk) stage_note, stage_note_url = book.stage_note() extra_info = book.extra_info + audiobooks, projects, have_oggs = get_audiobooks(book) return render(request, 'catalogue/book_wide.html', { 'book': book, @@ -672,7 +670,8 @@ def book_wide(request, pk): 'main_link': reverse('book_text', args=[book.slug]) if book.html_file else None, 'extra_info': extra_info, 'hide_about': extra_info.get('about', '').startswith('http://wiki.wolnepodreczniki.pl'), - 'themes': book.related_themes(), + 'audiobooks': audiobooks, + 'have_oggs': have_oggs, }) @@ -689,3 +688,55 @@ def fragment_promo(request, pk): return render(request, 'catalogue/fragment_promo.html', { 'fragment': fragment }) + + +@ssi_included +def tag_box(request, pk): + tag = get_object_or_404(models.Tag, pk=pk) + assert tag.category != 'set' + + return render(request, 'catalogue/tag_box.html', { + 'tag': tag, + }) + + +@ssi_included +def collection_box(request, pk): + obj = get_object_or_404(models.Collection, pk=pk) + + return render(request, 'catalogue/collection_box.html', { + 'obj': obj, + }) + + +def tag_catalogue(request, category): + if category == 'theme': + tags = models.Tag.objects.usage_for_model( + models.Fragment, counts=True).filter(category='theme') + else: + tags = list(get_top_level_related_tags((), categories=(category,))) + + if len(tags) > 3: + best = random.sample(tags, 3) + else: + best = tags + + return render(request, 'catalogue/tag_catalogue.html', { + 'tags': tags, + 'best': best, + 'title': constants.CATEGORIES_NAME_PLURAL[category], + }) + + +def collections(request): + objects = models.Collection.objects.all() + + if len(objects) > 3: + best = random.sample(objects, 3) + else: + best = objects + + return render(request, 'catalogue/collections.html', { + 'objects': objects, + 'best': best, + }) diff --git a/src/picture/models.py b/src/picture/models.py index 5aabe3c89..bffb63912 100644 --- a/src/picture/models.py +++ b/src/picture/models.py @@ -17,6 +17,7 @@ from StringIO import StringIO import jsonfield import itertools import logging +import re from PIL import Image @@ -123,10 +124,31 @@ class Picture(models.Model): def __unicode__(self): return self.title + def author_str(self): + return ", ".join(str(t) for t in self.tags.filter(category='author')) + @permalink def get_absolute_url(self): return ('picture.views.picture_detail', [self.slug]) + def get_initial(self): + try: + return re.search(r'\w', self.title, re.U).group(0) + except AttributeError: + return '' + + def get_next(self): + try: + return type(self).objects.filter(sort_key__gt=self.sort_key)[0] + except IndexError: + return None + + def get_previous(self): + try: + return type(self).objects.filter(sort_key__lt=self.sort_key).order_by('-sort_key')[0] + except IndexError: + return None + @classmethod def from_xml_file(cls, xml_file, image_file=None, image_store=None, overwrite=False): """ diff --git a/src/picture/templates/picture/picture_short.html b/src/picture/templates/picture/picture_short.html index 1bd70a11b..35fba77b0 100644 --- a/src/picture/templates/picture/picture_short.html +++ b/src/picture/templates/picture/picture_short.html @@ -10,7 +10,7 @@
      {% for tag in tags.author %} - {{ tag }}{% if not forloop.last %}, + {{ tag }}{% if not forloop.last %}, {% endif %}{% endfor %}
      @@ -32,14 +32,14 @@ {% endblock %} {# what about licensing icons here #}
      - +
      {% spaceless %} {% trans "Epoch" %}:  {% for tag in tags.epoch %} - {{ tag }} + {{ tag }} {% if not forloop.last %}, {% endif %} {% endfor %} @@ -47,7 +47,7 @@ {% trans "Kind" %}:  {% for tag in tags.kind %} - {{ tag }} + {{ tag }} {% if not forloop.last %}, {% endif %} {% endfor %} @@ -55,7 +55,7 @@ {% trans "Genre" %}:  {% for tag in tags.genre %} - {{ tag }} + {{ tag }} {% if not forloop.last %}, {% endif %} {% endfor %} diff --git a/src/picture/templates/picture/picture_viewer.html b/src/picture/templates/picture/picture_viewer.html index e169dbe0f..937ef689f 100644 --- a/src/picture/templates/picture/picture_viewer.html +++ b/src/picture/templates/picture/picture_viewer.html @@ -3,6 +3,7 @@ {% load static from staticfiles %} {% load catalogue_tags %} {% load thumbnail %} +{% load ssi_include from ssify %} {% block title %}{{ picture.pretty_title }}{% endblock %} @@ -24,6 +25,17 @@ {% block menu %}
    • +-
    • +{% spaceless %} +
    • + {% with picture.get_previous as prev %} + {% if prev %}<{%endif %} + {% endwith %} + {% with picture.get_next as next %} + {% if next %}>{% endif %} + {% endwith %} +
    • +{% endspaceless %} +
    • {% thumbnail picture.image_file "700x500" as pic %} -
      @@ -82,7 +94,7 @@
      - {{ picture.short_html }} + {% ssi_include 'picture_short' pk=picture.pk %}
      {% endblock %} diff --git a/src/picture/templates/picture/picture_wide.html b/src/picture/templates/picture/picture_wide.html index 9f47c7baa..462e8b0e2 100644 --- a/src/picture/templates/picture/picture_wide.html +++ b/src/picture/templates/picture/picture_wide.html @@ -93,20 +93,5 @@ {% endif %}
    - - {% comment %} -
    -

    {% trans "Download" %}

    -
      -
    • - {% if related.media.mp3 or related.media.ogg or related.media.daisy %} - {% trans "Download all audiobooks for this book" %}: - {% download_audio book %}. - {% endif %} -
    • - {% custom_pdf_link_li book %} -
    -
    - {% endcomment %} {% endblock %} diff --git a/src/search/templatetags/search_tags.py b/src/search/templatetags/search_tags.py index 8dbad9dae..8302379cd 100644 --- a/src/search/templatetags/search_tags.py +++ b/src/search/templatetags/search_tags.py @@ -32,12 +32,15 @@ def book_searched(context, result): # We don't need hits which lead to sections but do not have # snippets. hits = filter(lambda (idx, h): - result.snippets[idx] is not None - or 'fragment' in h, enumerate(result.hits)) + 'fragment' in h or + result.snippets[idx] is not None, + enumerate(result.hits)) # print "[tmpl: from %d hits selected %d]" % (len(result.hits), len(hits)) for (idx, hit) in hits: # currently we generate one snipper per hit though. + if len(result.snippets) <= idx: + break if result.snippets[idx] is None: continue snip = result.snippets[idx] diff --git a/src/wolnelektury/celery.py b/src/wolnelektury/celery.py index ae5ce20ce..094a7a7c2 100644 --- a/src/wolnelektury/celery.py +++ b/src/wolnelektury/celery.py @@ -3,10 +3,8 @@ from __future__ import absolute_import import os import sys -ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) sys.path = [ - os.path.join(ROOT, 'apps'), - os.path.join(ROOT, 'lib'), os.path.join(ROOT, 'lib/librarian'), ] + sys.path diff --git a/src/wolnelektury/locale/pl/LC_MESSAGES/django.mo b/src/wolnelektury/locale/pl/LC_MESSAGES/django.mo index b6919642fd37cf4943a3c6f2218b90d18f495192..25437326d65e0db8bbdbce9c483894b8f55a9efd 100644 GIT binary patch delta 1851 zcmaLXTWl0n9LMp0TgsMRC~QkDmX)oFf@Rxntw2kqMH;}SgjG<9a&g#B%G%2`yW5mS z&5{TapHK!&8Xh1q(HI|BjX`)2Z?P{J3=ae~A_>MAjWKGX!OQp89n>dJ_CKF9vuDob zf6nf6{nxwmUxw$LFiJnMgy<#r#e zFn~O=hfovWjmlgSwS{BI$1ZTW4Zpwy-oVYcg~9Ttsk}_(PF&4sTH#JqM=q*k4@rh) zgYOTbQvCw{$eB2f&*0&OW*>2WN?G1jzW-#A8ISCZhT<7HhnmnO)D~Q8Aph#<1`jlW z5GUy(u0&>_HMuTc~H6}6S+ zdEVB~t_tWNlD2U7nl>;Q%RS5XT8udL_G2MCg4_YnGryPs$$v~9|uvZ4|uR?XJTqJjDq-7KrA ztR=dL+7T|=52Z>)sZ=3rv*}j7kLV%R5O)(R36&ON*=&vUqt1=ahDv{tf37iVexf1n zU#X}rOjNvA78*)=q;28A2h#^~BmXYN@lQks7e&2H*2#{ilKYCQ8F7+Nr3#lLXG^NLc-h>P R&0cf<@ui0f@#tqIe*@9E<(~im delta 2901 zcmb7^TWl0n7{||YtKGIx3bd4p94c4Ydt0DOY0E+>Bugm-Qcb*_-96o%?q!;psY5r0 zjgT6NCPXG^+C&3B@ZbYR7mSif5L?5Gh$b2}hQvgQJ|K~3j1P+cZ+BV>l&B~D_IJ*l zneTS~r{lrH+j3W{W*ui3A=tw(*9^v<09$6^2jj$S#=Zwng6}&RJ2;22U$Aa^h_Q=U zuP9~gXRNO~8Cw8;QN~yecnzEj{sq>9<>ibm2fg4Ka1RKVIX0()vEB3nxDtF4L=1Ka ztOSpM@WDoGp0fEKI3Lf?gC*bw?X90N{|)RRte5Ue6|P^%6vuP z0b?6Mda=`9cZ1~k8Iayn?ft_b1$qTs0$TR^G>GEZS&-hp2vUMy+q??mkB#GJ0phdY zF`)pZ_}LEDg5=;?kTOk!=rYql0X`3s!>b^5W*nqMZh&V!e*zKHV1pn;bcA}MfBHDjM* z|1t#d1NM)jEqIlgbwy1a0V%;jZXnO_2zfwfDE6*hy2 z!P-G;VGl?x?gc5qEQsRRkiCA*-aiSF-?Jcz{3Cn+yQSzqwfY(!5O0AL;5JBST8%y~ z0{tMhxYJ&Df#@=efs}v&QbI3*P&IoUq(EqH zF`2QvD4Js+1$q~xR-Ok*8=r%e`M37^21tqg0XjgOTw%~%M-2>;C=4Hdo9#K8S}4j7 zQn8QH{cph}2txsd$|>vhFd9@536KJXU`;USYjPkqbHgaXwXk*=4LS;{mc&fQL}x#B zY_Jyry8m7**1)Jb7i=SpDsO;M>$bpXG#0^HLFy3cgT_i2seEG4u}qAri3wN>dknT2 zwi?z3+l2UR6>KKV10(U#SO+5kO$<&GXDP-mH72zT?^aVH6XV;}flN#oikfk8pU>Uo zZ{$5f(}n5c11S&Rg?Uzt9ZIUEo)mmzqqjN0Q)<$~{edPIH{^ztw^tkp@->0LTE0Hu zcQ^Rl{tZrk&yeo4P*OqOB6vcRy_@STSLy1q`qo~G9_C>0EU zn&fE_lkjvWvxH&v2fbd?G(C}wN7dq<{*<@AbzegAu0o^WCagp>p$(FMS8n=Gbx%?l zs;NX}@%xYxNhzu!(Z#Wm)aVe}NuP5%gvqW6Q6P#Q{pPov`5AUioten-F2sjmZQp- zublJQOzVnsS-!-%$uU=ps|N2Dx^Ajktj&s)xl8$TQq!rs)<{`n{(9Nd4r_14!CIM$ zs%go362e%m^NcjxSdS8mOCx`|V&RO62Dd-p_OIu@=3u~Q-JDlf-r)8%x_!;u?+Z3s z)s;O<-20?R2YGl)SLgmMogKU-9Bxl3bU;?L@>uQT?rv4a6vG`BnfQQ+%OFWy(G%8h zm9d^KOwF zYEj}zgJ_CaR?Q4znw42w>-LQq9lpPg!clSO-lE2n(LTwegS~JgxjC3rGXl4%;A(oo zO%eN~SSgIajZw|fA-K=Ax~Bj3fog{XTkZu1tz4Pj!M~{;ejxW;;o{hyvRuZqGTomN zS{6N0qX{*Z9UY1eMiV?Mc{ZY`+9!FFhq{WFLE)hekMsYFpWXRyW|dd1%b%Mcnw>AH zIpC=7QqWM5Rz`;np=WtQ=wpXOn{{fjx3UMf0R8V99nPZlrnJTvhx5B@&p52gy2I7@ VU)0C8syu_8xH@?iUakAe@eicWSM2}* diff --git a/src/wolnelektury/locale/pl/LC_MESSAGES/django.po b/src/wolnelektury/locale/pl/LC_MESSAGES/django.po index 6a6ad3450..dd6f34fcc 100644 --- a/src/wolnelektury/locale/pl/LC_MESSAGES/django.po +++ b/src/wolnelektury/locale/pl/LC_MESSAGES/django.po @@ -7,35 +7,18 @@ msgid "" msgstr "" "Project-Id-Version: WolneLektury\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-12-16 09:20+0100\n" -"PO-Revision-Date: 2013-04-09 10:43+0100\n" +"POT-Creation-Date: 2015-12-31 16:45+0100\n" +"PO-Revision-Date: 2015-12-31 16:45+0100\n" "Last-Translator: Radek Czajka \n" -"Language-Team: LANGUAGE \n" "Language: pl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Translated-Using: django-rosetta 0.5.6\n" -"X-Poedit-Language: Polish\n" "Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " -"|| n%100>=20) ? 1 : 2)\n" - -#: views.py:34 views.py:35 templates/superbase.html:85 -msgid "Sign in" -msgstr "Zaloguj się" - -#: views.py:41 views.py:62 -#, python-format -msgid "Already logged in as user %(user)s" -msgstr "Zalogowano jako %(user)s" - -#: views.py:53 views.py:54 views.py:82 templates/superbase.html:89 -msgid "Register" -msgstr "Załóż konto" - -#: views.py:77 -msgid "You have to be logged in to continue" -msgstr "Zaloguj się, aby kontynuować" +"|| n%100>=20) ? 1 : 2);\n" +"Language-Team: \n" +"X-Generator: Poedit 1.8.4\n" #: templates/404.html:5 msgid "Page does not exist" @@ -83,175 +66,6 @@ msgstr "" "Serwis Wolnelektury.pl jest obecnie niedostępny z powodu prac " "konserwacyjnych." -#: templates/main_page.html:6 templates/main_page.html.py:7 -msgid "Wolne Lektury internet library" -msgstr "Biblioteka internetowa Wolne Lektury" - -#: templates/main_page.html:23 -msgid "What's new?" -msgstr "Co nowego?" - -#: templates/main_page.html:31 -msgid "Recent publications" -msgstr "Ostatnie publikacje" - -#: templates/main_page.html:41 -msgid "News" -msgstr "Aktualności" - -#: templates/main_page.html:50 -msgid "Utilities" -msgstr "Narzędzia" - -#: templates/main_page.html:53 -msgid "Report a bug or suggestion" -msgstr "Zgłoś błąd lub sugestię" - -#: templates/main_page.html:56 -msgid "Download the catalogue in PDF format." -msgstr "Pobierz katalog w formacie PDF." - -#: templates/main_page.html:58 -msgid "Widget" -msgstr "Widget" - -#: templates/main_page.html:59 -msgid "Missing a book?" -msgstr "Nie znalazłeś/-aś utworu?" - -#: templates/main_page.html:60 templates/publish_plan.html:4 -#: templates/publish_plan.html.py:8 -msgid "Publishing plan" -msgstr "Plan publikacji" - -#: templates/main_page.html:71 -msgid "Information" -msgstr "Informacje" - -#: templates/main_page.html:73 -msgid "Privacy policy" -msgstr "Polityka prywatności" - -#: templates/main_page.html:98 -msgid "Image used:" -msgstr "Użyto obrazu:" - -#: templates/superbase.html:18 -msgid "Wolne Lektury" -msgstr "Wolne Lektury" - -#: templates/superbase.html:55 -#, python-format -msgid "" -"\n" -"
    %(c)s free reading you have right to\n" -" " -msgid_plural "" -"\n" -" %(c)s free readings you have right to\n" -" " -msgstr[0] "" -"\n" -" %(c)s darmowy utwór do której masz prawo\n" -" " -msgstr[1] "" -"\n" -" %(c)s darmowe utwory do których masz prawo\n" -" " -msgstr[2] "" -"\n" -" %(c)s darmowych utworów do których " -"masz prawo\n" -" " - -#: templates/superbase.html:66 -msgid "Welcome" -msgstr "Witaj" - -#: templates/superbase.html:72 templates/user.html:12 -msgid "Password" -msgstr "Hasło" - -#: templates/superbase.html:73 templates/user.html:13 -msgid "E-mail" -msgstr "E-mail" - -#: templates/superbase.html:74 templates/user.html:14 -msgid "Social accounts" -msgstr "Konta społecznościowe" - -#: templates/superbase.html:77 -msgid "My shelf" -msgstr "Moja półka" - -#: templates/superbase.html:79 -msgid "Administration" -msgstr "Administracja" - -#: templates/superbase.html:81 -msgid "Logout" -msgstr "Wyloguj" - -#: templates/superbase.html:111 -msgid "Search" -msgstr "Szukaj" - -#: templates/superbase.html:131 -msgid "Language versions" -msgstr "Wersje językowe" - -#: templates/superbase.html:165 -msgid "" -"\n" -"\t\t\t\tWolne Lektury is a project lead by Modern Poland Foundation.\n" -"\t\t\t\tDigital reproductions are made by The National Library, Biblioteka Śląska and Biblioteka Elbląska, based on TNL, BŚ and BE resources.\n" -"\t\t\t\tHosting: ICM.\n" -"\t\t\t\t" -msgstr "" -"\n" -"Wolne Lektury to projekt prowadzony przez fundację Nowoczesna Polska. \n" -"Reprodukcje cyfrowe wykonane przez Bibliotekę Narodową, Bibliotekę Śląską i Bibliotekę Elbląską z egzemplarzy pochodzących ze zbiorów BN, BŚ i " -"BE.\n" -"Hosting: ICM." - -#: templates/superbase.html:172 -msgid "" -"\n" -"\t\t\t\tModern Poland Foundation, 00-514 Warsaw, ul. Marszałkowska 84/92 " -"lok. 125, tel/fax: (22) 621-30-17\n" -" e-mail: fundacja@nowoczesnapolska.org.pl\n" -"\t\t\t\t" -msgstr "" -"\n" -"Fundacja Nowoczesna Polska, 00-514 Warszawa, ul. Marszałkowska 84/92 lok. " -"125, tel/fax: (22) 621-30-17, e-mail: fundacja@nowoczesnapolska.org.pl" - -#: templates/superbase.html:189 -msgid "Close" -msgstr "Zamknij" - -#: templates/superbase.html:191 -msgid "Loading" -msgstr "Ładowanie" - -#: templates/user.html:5 templates/user.html.py:9 -msgid "User" -msgstr "Użytkownik" - #: templates/admin/base_site.html:4 templates/admin/base_site.html.py:7 msgid "Site administration" msgstr "Administracja stroną" @@ -273,15 +87,15 @@ msgstr "uproszczone" msgid "Import book" msgstr "Importuj książkę" -#: templates/auth/login.html:10 +#: templates/auth/login.html:12 msgid "Forgot Password?" msgstr "Nie pamiętasz hasła?" -#: templates/auth/login.html:15 templates/auth/register.html:7 +#: templates/auth/login.html:17 templates/auth/register.html:7 msgid "Sign in using:" msgstr "Zaloguj się używając:" -#: templates/auth/login_register.html:9 +#: templates/auth/login_register.html:10 msgid "or register" msgstr "albo załóż konto" @@ -332,6 +146,63 @@ msgstr "" msgid "More..." msgstr "Więcej..." +#: templates/main_page.html:7 templates/main_page.html.py:8 +msgid "Wolne Lektury internet library" +msgstr "Biblioteka internetowa Wolne Lektury" + +#: templates/main_page.html:34 +msgid "Theme" +msgstr "Motyw" + +#: templates/main_page.html:85 +msgid "Recent publications" +msgstr "Ostatnie publikacje" + +#: templates/main_page.html:89 +msgid "More recent publications" +msgstr "Więcej ostatnich publikacji" + +#: templates/main_page.html:95 +msgid "News" +msgstr "Aktualności" + +#: templates/main_page.html:101 +msgid "Utilities" +msgstr "Narzędzia" + +#: templates/main_page.html:104 +msgid "Report a bug or suggestion" +msgstr "Zgłoś błąd lub sugestię" + +#: templates/main_page.html:106 +msgid "Download the catalogue in PDF format." +msgstr "Pobierz katalog w formacie PDF." + +#: templates/main_page.html:107 +msgid "Footnotes" +msgstr "Przypisy" + +#: templates/main_page.html:108 +msgid "Missing a book?" +msgstr "Nie znalazłeś/-aś utworu?" + +#: templates/main_page.html:109 templates/publish_plan.html:4 +#: templates/publish_plan.html.py:8 +msgid "Publishing plan" +msgstr "Plan publikacji" + +#: templates/main_page.html:120 +msgid "Information" +msgstr "Informacje" + +#: templates/main_page.html:122 +msgid "Privacy policy" +msgstr "Polityka prywatności" + +#: templates/main_page.html:142 +msgid "Image used:" +msgstr "Użyto obrazu:" + #: templates/openid/login.html:6 templates/openid/login.html.py:10 msgid "OpenID Sign In" msgstr "Logowanie przez OpenID" @@ -364,32 +235,32 @@ msgstr "" "Potwierdź dostęp do Wolnych Lektur jako użytkownik %(user)s." #: templates/socialaccount/connections.html:5 -#: templates/socialaccount/connections.html:8 +#: templates/socialaccount/connections.html:10 msgid "Account Connections" msgstr "Powiązania konta" -#: templates/socialaccount/connections.html:12 +#: templates/socialaccount/connections.html:13 msgid "" "You can sign in to your account using any of the following third party " "accounts:" msgstr "" "Możesz się zalogować na swoje konto używając następujących kont zewnętrznych:" -#: templates/socialaccount/connections.html:36 +#: templates/socialaccount/connections.html:37 msgid "Remove" msgstr "Usuń" -#: templates/socialaccount/connections.html:44 +#: templates/socialaccount/connections.html:45 msgid "" "You currently have no social network accounts connected to this account." msgstr "Aktualnie do Twojego konta nie są podłączone żadne konta zewnętrzne." -#: templates/socialaccount/connections.html:47 +#: templates/socialaccount/connections.html:48 msgid "Add a 3rd Party Account" msgstr "Dodaj konto zewnętrzne" #: templates/socialaccount/login_cancelled.html:5 -#: templates/socialaccount/login_cancelled.html:9 +#: templates/socialaccount/login_cancelled.html:10 msgid "Login Cancelled" msgstr "Anulowano logowanie" @@ -403,6 +274,158 @@ msgstr "" "Logowanie przy użyciu zewnętrznego konta zostało anulowane. Jeśli był to " "błąd, przejdź do strony logowania." +#: templates/superbase.html:21 +msgid "Wolne Lektury" +msgstr "Wolne Lektury" + +#: templates/superbase.html:51 +#, python-format +msgid "" +"\n" +" %(c)s free reading you have right to\n" +" " +msgid_plural "" +"\n" +" %(c)s free readings you have right to\n" +" " +msgstr[0] "" +"\n" +" %(c)s darmowy utwór do której masz prawo\n" +" " +msgstr[1] "" +"\n" +" %(c)s darmowe utwory do których masz prawo\n" +" " +msgstr[2] "" +"\n" +" %(c)s darmowych utworów do których " +"masz prawo\n" +" " + +#: templates/superbase.html:61 +msgid "Language" +msgstr "Język" + +#: templates/superbase.html:85 +msgid "My shelf" +msgstr "Moja półka" + +#: templates/superbase.html:88 +msgid "Administration" +msgstr "Administracja" + +#: templates/superbase.html:90 +msgid "Logout" +msgstr "Wyloguj" + +#: templates/superbase.html:93 views.py:67 views.py:68 +msgid "Sign in" +msgstr "Zaloguj się" + +#: templates/superbase.html:93 views.py:86 views.py:87 views.py:115 +msgid "Register" +msgstr "Załóż konto" + +#: templates/superbase.html:100 +msgid "Literature" +msgstr "Literatura" + +#: templates/superbase.html:101 +msgid "Themes" +msgstr "Motywy" + +#: templates/superbase.html:102 +msgid "Audiobooks" +msgstr "Audiobooki" + +#: templates/superbase.html:103 +msgid "Gallery" +msgstr "Galeria" + +#: templates/superbase.html:114 +msgid "Search" +msgstr "Szukaj" + +#: templates/superbase.html:142 +msgid "Close" +msgstr "Zamknij" + +#: templates/superbase.html:144 +msgid "Loading" +msgstr "Ładowanie" + +#: templates/user.html:5 templates/user.html.py:11 +msgid "User" +msgstr "Użytkownik" + +#: templates/user.html:13 +msgid "Password" +msgstr "Hasło" + +#: templates/user.html:14 +msgid "E-mail" +msgstr "E-mail" + +#: templates/user.html:15 +msgid "Social accounts" +msgstr "Konta społecznościowe" + +#: views.py:74 views.py:95 +#, python-format +msgid "Already logged in as user %(user)s" +msgstr "Zalogowano jako %(user)s" + +#: views.py:110 +msgid "You have to be logged in to continue" +msgstr "Zaloguj się, aby kontynuować" + +#~ msgid "What's new?" +#~ msgstr "Co nowego?" + +#~ msgid "Widget" +#~ msgstr "Widget" + +#~ msgid "Welcome" +#~ msgstr "Witaj" + +#~ msgid "" +#~ "\n" +#~ "\t\t\t\tWolne Lektury is a project lead by Modern Poland Foundation.\n" +#~ "\t\t\t\tDigital reproductions are made by The National Library, Biblioteka Śląska and Biblioteka Elbląska, based on TNL, BŚ and BE resources.\n" +#~ "\t\t\t\tHosting: ICM.\n" +#~ "\t\t\t\t" +#~ msgstr "" +#~ "\n" +#~ "Wolne Lektury to projekt prowadzony przez fundację Nowoczesna Polska. \n" +#~ "Reprodukcje cyfrowe wykonane przez Bibliotekę Narodową, Bibliotekę Śląską i Bibliotekę Elbląską z egzemplarzy pochodzących ze zbiorów BN, BŚ i " +#~ "BE.\n" +#~ "Hosting: ICM." + +#~ msgid "" +#~ "\n" +#~ "\t\t\t\tModern Poland Foundation, 00-514 Warsaw, ul. Marszałkowska 84/92 " +#~ "lok. 125, tel/fax: (22) 621-30-17\n" +#~ " e-mail: fundacja@nowoczesnapolska.org.pl\n" +#~ "\t\t\t\t" +#~ msgstr "" +#~ "\n" +#~ "Fundacja Nowoczesna Polska, 00-514 Warszawa, ul. Marszałkowska 84/92 lok. " +#~ "125, tel/fax: (22) 621-30-17, e-mail: fundacja@nowoczesnapolska.org.pl" + #~ msgid "Listing of all audiobooks" #~ msgstr "Spis wszystkich audiobooków" @@ -424,9 +447,6 @@ msgstr "" #~ msgid "See also" #~ msgstr "Zobacz też" -#~ msgid "Theme" -#~ msgstr "Motyw" - #~ msgid "in work " #~ msgstr "w utworze" @@ -515,9 +535,6 @@ msgstr "" #~ msgid "Table of contents" #~ msgstr "Spis treści" -#~ msgid "Themes" -#~ msgstr "Motywy" - #~ msgid "Edit. note" #~ msgstr "Nota red." @@ -631,9 +648,6 @@ msgstr "" #~ msgid "All books" #~ msgstr "Wszystkie utwory" -#~ msgid "Audiobooks" -#~ msgstr "Audiobooki" - #~ msgid "DAISY" #~ msgstr "DAISY" @@ -685,8 +699,8 @@ msgstr "" #~ msgid "" #~ "Audiobooks were prepared as a part of the %(cs)s project funded by %(fb)s." #~ msgstr "" -#~ "Audiobooki przygotowane w ramach projektu %(cs)s finansowanego przez %(fb)" -#~ "s." +#~ "Audiobooki przygotowane w ramach projektu %(cs)s finansowanego przez " +#~ "%(fb)s." #~ msgid "Audiobooks were prepared as a part of the %(cs)s project." #~ msgstr "Audiobooki przygotowane w ramach projektu %(cs)s." diff --git a/src/wolnelektury/settings/custom.py b/src/wolnelektury/settings/custom.py index 8830ebe6f..fd8a42602 100644 --- a/src/wolnelektury/settings/custom.py +++ b/src/wolnelektury/settings/custom.py @@ -1,3 +1,6 @@ +import os +from .paths import VAR_DIR + # limit number of filtering tags MAX_TAG_LIST = 6 @@ -15,3 +18,5 @@ CATALOGUE_CUSTOMPDF_RATE_LIMIT = '1/m' LIBRARIAN_PDF_MOREFLOATS = None LATEST_BLOG_POSTS = "http://nowoczesnapolska.org.pl/feed/?cat=-135" + +CATALOGUE_COUNTERS_FILE = os.path.join(VAR_DIR, 'catalogue_counters.p') diff --git a/src/wolnelektury/settings/static.py b/src/wolnelektury/settings/static.py index 027879a33..625b4c77f 100644 --- a/src/wolnelektury/settings/static.py +++ b/src/wolnelektury/settings/static.py @@ -16,11 +16,13 @@ STATIC_URL = '/static/' # CSS and JavaScript file groups PIPELINE = { + 'PIPELINE_ENABLED': False, 'STYLESHEETS': { 'main': { # styles both for mobile and for big screen 'source_filenames': [ 'css/jquery.countdown.css', + 'jplayer/jplayer.blue.monday.css', 'sponsors/css/sponsors.css', @@ -77,6 +79,7 @@ PIPELINE = { 'js/contrib/jquery.cycle.min.js', 'js/contrib/jquery.jqmodal.js', 'js/contrib/jquery.form.js', + 'js/contrib/jquery.paging.min.js', 'js/contrib/jquery.countdown.js', 'js/contrib/jquery.countdown-pl.js', 'js/contrib/jquery.countdown-de.js', 'js/contrib/jquery.countdown-uk.js', 'js/contrib/jquery.countdown-es.js', 'js/contrib/jquery.countdown-lt.js', @@ -84,6 +87,10 @@ PIPELINE = { 'js/contrib/jquery-ui-1.8.16.custom.min.js', + 'jplayer/jquery.jplayer.min.js', + 'jplayer/jplayer.playlist.min.js', + 'player/player.js', + 'js/locale.js', 'js/dialogs.js', 'js/base.js', diff --git a/src/wolnelektury/static/js/base.js b/src/wolnelektury/static/js/base.js index f2a8e262a..52834687b 100644 --- a/src/wolnelektury/static/js/base.js +++ b/src/wolnelektury/static/js/base.js @@ -98,7 +98,7 @@ menu_loaded = true; }); } - } + } }); }); /* this kinda breaks the whole page. */ @@ -108,7 +108,7 @@ while (p.length) { if (p == $current) return; - if (p.hasClass('hidden-box-trigger') + if (p.hasClass('hidden-box-trigger') || p.hasClass('simple-toggler') || p.hasClass('mini-search')) return; @@ -118,12 +118,15 @@ $current = null; }); })(); - + $('#show-menu').click(function(event) { event.preventDefault(); - $('#menu').toggle('slow'); + //$('#menu').toggle('slow'); + $('body').toggleClass('menu-on'); }); + + $('#book-list-nav h2').click(function(event) { event.preventDefault(); $('#book-list-nav-index').toggle(); @@ -152,16 +155,76 @@ $('#themes-list-toggle').click(function(event) { $('body').on('click', '.simple-toggler' , function(ev) { ev.preventDefault(); var scope = $(this).closest('.simple-toggler-scope'); - scope.find('.simple-hidden-box').each(function(){ + scope.find('.simple-hidden-box').each(function(){ var $this = $(this); if ($this.is(':hidden')) { $this.show(); - } else { + } else { $this.hide(); } }); }); + + $('.tabbed-filter').each(function() { + var tf = this; + $('.tab').click(function() { + if ($(this).hasClass('active')) { + $(this).removeClass('active'); + $('#' + $(this).attr('data-id')).hide(); + } + else { + var $active = $('.active', tf); + $active.removeClass('active'); + $('#' + $active.attr('data-id')).hide(); + $(this).addClass('active'); + $('#' + $(this).attr('data-id')).show(); + } + }); + }); + + + $('.plain-list-paged').each(function() { + // should change on resize? + var $plc = $(this); + var $pl = $('.plain-list', this); + + var $items = $('p', $pl); + + if ($items.length > 40) { + $items.hide(); + var prev = [0, 0]; + + $('.pager', $plc).paging($items.length, { + format: '[< ncnnn >]', // define how the navigation should look like and in which order onFormat() get's called + perpage: 40, + lapping: 0, // don't overlap pages for the moment + page: 1, // start at page, can also be "null" or negative + onSelect: function (page) { + var data = this.slice; + $items.slice(prev[0], prev[1]).hide(); + $items.slice(data[0], data[1]).show(); + prev = data; + }, + onFormat: function (type) { + switch (type) { + case 'block': // n and c + return ' ' + this.value + ' '; + case 'next': // > + return ' > '; + case 'prev': // < + return ' < '; + case 'first': // [ + return '« '; + case 'last': // ] + return ' »'; + } + } + }); + } + }); + + }); })(jQuery); diff --git a/src/wolnelektury/static/js/contrib/jquery.paging.min.js b/src/wolnelektury/static/js/contrib/jquery.paging.min.js new file mode 100644 index 000000000..da169cb26 --- /dev/null +++ b/src/wolnelektury/static/js/contrib/jquery.paging.min.js @@ -0,0 +1,14 @@ +/* +jQuery paging plugin v1.3.0 23/06/2014 +http://www.xarg.org/2011/09/jquery-pagination-revised/ + +Copyright (c) 2011, Robert Eisele (robert@xarg.org) +Dual licensed under the MIT or GPL Version 2 licenses. +*/ +(function(n,v,r){n.fn.paging=function(z,A){var t=this,b={setOptions:function(a){b.a=n.extend(b.a||{lapping:0,perpage:10,page:1,refresh:{interval:10,url:null},format:"",lock:!1,circular:!1,onClick:null,onFormat:function(){},onSelect:function(){return!0},onRefresh:function(){}},a||{});b.a.lapping|=0;b.a.perpage|=0;null!==b.a.page&&(b.a.page|=0);1>b.a.perpage&&(b.a.perpage=10);b.interval&&v.clearInterval(b.interval);b.a.refresh.url&&(b.interval=v.setInterval(function(){n.ajax({url:b.a.refresh.url,success:function(a){if("string"=== +typeof a)try{a=n.parseJSON(a)}catch(m){return}b.a.onRefresh(a)}})},1E3*b.a.refresh.interval));b.format=function(a){for(var b=0,f=0,h=1,g={g:[],i:0,h:0,b:5,current:3,l:0,m:0},c,p=/[*<>pq\[\]().-]|[nc]+!?/g,n={"[":"first","]":"last","<":"prev",">":"next",q:"left",p:"right","-":"fill",".":"leap"},e={};c=p.exec(a);)c=""+c,r===n[c]?"("===c?f=++b:")"===c?f=0:h&&("*"===c?(g.i=1,g.h=0):(g.i=0,g.h="!"===c.charAt(c.length-1),g.b=c.length-g.h,(g.current=1+c.indexOf("c"))||(g.current=1+g.b>>1)),g.g.push({f:"block", +j:0,c:0}),h=0):(g.g.push({f:n[c],j:f,c:r===e[c]?e[c]=1:++e[c]}),"q"===c?++g.m:"p"===c&&++g.l);return g}(b.a.format);return b},setNumber:function(a){b.s=r===a||0>a?-1:a;return b},setPage:function(a){function w(a,b,c){c=""+a.onFormat.call(b,c);p=b.value?p+c.replace(/m?(c=m=-1,h=Math.max(1,a-e.current+1-q),g=h+e.b):(c=1+Math.ceil((m-f.perpage)/(f.perpage-q)),a=Math.max(1,Math.min(0>a?1+c+a:a,c)),e.i?(h=1,g=1+c,e.current=a,e.b=c):(h=Math.max(1,Math.min(a-e.current,c-e.b)+1),g=e.h?h+e.b:Math.min(h+e.b,1+c)));for(;u--;){k=0;l=e.g[u];switch(l.f){case "left":k=l.c>l.j&1;switch(l.f){case "block":for(;hm,d.first=1===h,d.last=h===c&&0m)?d.value=1+a:(d.value=c,d.active=k&&am)?d.value=1+a:(d.value=Math.min(1+a,c),d.active=k&&a"; - } + .note { + position: absolute; + right: 0; + top: 1px; + width: 139px; + height: 289px - 22px; } } } @@ -254,3 +211,53 @@ } } } + +.more { + display: block; + margin-top: .5em; +} + + +section { + margin-top: 2em; +} + + +.tag-box-section { + @media screen and (min-width: 768px) { + display: inline-block; + width: 48%; + margin-right: 2%; + vertical-align: top; + + .tag-box { + display: block; + width: 100%; + } + } +} + +#main-theme { + .white-box { + position: relative; + + .cite { + display: none; + + @media screen and (min-width: 768px) { + display: block; + position: absolute; + right: 1em; + top: 7em; + background: #F7F7F7; + width: 200px; + padding-left: 20px; + } + + @media screen and (min-width: 1024px) { + width: 340px; + padding-left: 80px; + } + } + } +} diff --git a/src/wolnelektury/static/scss/main/menu.scss b/src/wolnelektury/static/scss/main/menu.scss index 846e4c88c..c2f708a0e 100755 --- a/src/wolnelektury/static/scss/main/menu.scss +++ b/src/wolnelektury/static/scss/main/menu.scss @@ -1,175 +1,146 @@ -#nav-line { - background-color: #e2e2e2; - position: relative; +/* ok */ - @media screen and (min-width: 62.5em) { - @include size(width, 975px); - margin: auto; - } +$menu_width: 200px; - #show-menu { - display: block; - float: left; - @include size(line-height, 13px); - @include size(padding, 18px 13px); - color: #0c7076; - @include size(font-size, 11px); - @include mono; - .long { - display: none; - - &:after { - @include size(padding-left, 10px); - content: url("/static/img/arrow-gray.png"); - vertical-align: top; - } - } +/* This is duplication of code for reader menu button. */ +%menu-toggle { + position: relative; + padding: 0; + &:before { + content: ""; + position: absolute; + top: 8px; + height: 5px; + border-top: 15px double #ddd; + border-bottom: 5px solid #ddd; + } +} - @media screen and (min-width: 20em) { - .long { display: inline; } - .short { display: none; } - } - @media screen and (min-width: 53em) { - display: none; - } +#show-menu { + @extend %menu-toggle; + display: block; + background: #191919; + color: #ddd; + text-align: center; + z-index: 100; + @include size(width, 44px); + @include size(height, 44px); + padding: 0; + position: absolute; + left: 10px; + top: 25px; + + &:before { + left: 8px; + right: 8px; } - ul#menu { - list-style: none; - padding: 0; - margin: 0; - + @media screen and (min-width: 1024px) { display: none; - position: absolute; - @include size(top, 49px); - left: 0; - @include size(right, 10px); - z-index: 400; - - @media screen and (min-width: 24em) { - right: auto; - } - - @media screen and (min-width: 53em) { - display: block !important; - position: static; - @include size(margin-left, 6px); - } - - li.menu { - background-color: #e2e2e2; + } +} - @media screen and (min-width: 53em) { - float: left; - } +body.menu-on { + margin-left: $menu_width; + margin-right: -$menu_width; - a.menu { - display: block; - @include size(line-height, 13px); - @include size(padding, 18px 12px 15px); - @include size(border-bottom, 3px solid #e2e2e2); - color: #0c7076; - @include size(font-size, 11px); - @include mono; - } + @media screen and (min-width: 1024px) { + margin-left: 0; + margin-right: 0; + } - a.hidden-box-trigger:hover { - border-bottom-color: white; - } - } + #menu { + display: block; } +} - #lang-menu { +#menu { + display: none; + position: fixed; + left: 0; + top: 0; + width: $menu_width; + background: #141414; + height: 100%; + overflow-y: auto; + z-index: 90; + + @media screen and (min-width: 1024px) { display: block; - float: right; + width: 975px; + height: 0; + overflow: visible; + margin: auto; + position: absolute; + top: 0; + } - background: #f7f7f7; - @include mono; + ul { + list-style: none; + padding: 0; - @media screen and (min-width: 15em) { - position: relative; + li { + padding: .5em 1em; + + @media screen and (min-width: 1024px) { + padding: 0; + } } + } +} - #lang-button { - @include size(padding-left, 25px); - @include size(padding-right, 20px); - display:block; - @include size(line-height, 17px); - @include size(padding-top, 16px); - @include size(padding-bottom, 16px); - @include size(font-size, 10px); - color: #717171; - .label { - display: none; +@media screen and (min-width: 1024px) { + #user-info { + @include mono; + position: absolute; + right: 150px; + top: 4px; + @include size(font-size, 10px); + list-style: none; - @media screen and (min-width: 62.5em) { - display: inline; - } + li { + display: inline; - &:after { - @include size(padding-left, 10px); - content: url("/static/img/arrow-gray.png"); - vertical-align: top; - } + &:after { + content: " | "; } - - .lang-flag { - @include size(font-size, 13px); - @include size(line-height, 15px); + &:last-child:after { + content: ""; } } + } - #lang-menu-items { - z-index: 9999; + #main-menu { + list-style: none; + padding: 0; + margin: 0; - button { - @include mono; - display: none; - background: #f7f7f7; - color: #6f6f6f; - cursor: pointer; - width: 100%; - margin: 0; - @include size(padding, 10px 0); - - @media screen and (min-width: 62.5em) { - @include size(padding, 5px 0); - } + background-color: #e2e2e2; + position: absolute; + top: 94px; + @include size(width, 975px); - border-width: 0; - @include size(border-bottom, 1px solid #ddd); + li { + display: inline-block; + @include size(width, 20%); - @include size(font-size, 13px); + a { + text-align: center; + display: block; + @include size(line-height, 13px); + @include size(padding, 18px 0 15px); + @include size(border-bottom, 3px solid #e2e2e2); + color: #0c7076; + @include size(font-size, 11px); + @include mono; &.active { - color: #000; - } - } - } - - &:hover, &.hover { - #lang-menu-items { - position: absolute; - padding: 0; - left: 0; - right: 0; - - @media screen and (min-width: 15em) { - left: auto; - @include size(width, 180px); - @include size(top, 49px); - } - @media screen and (min-width: 62.5em) { - width: 100%; - } - - button { - display: block; + border-bottom-color: white; } } } diff --git a/src/wolnelektury/static/scss/main/picture_box.scss b/src/wolnelektury/static/scss/main/picture_box.scss index 69d34a398..037774179 100644 --- a/src/wolnelektury/static/scss/main/picture_box.scss +++ b/src/wolnelektury/static/scss/main/picture_box.scss @@ -17,7 +17,7 @@ margin-left: 0; } - + @media screen and (min-width: 62.5em) { .book-box-head, .tags, .book-box-tools { float: right; @@ -60,12 +60,3 @@ } } - -.work-list { - .Picture-item { - @include min-screen($S_BOOK_SHORT_FULL) { - display: inline-block; - } - vertical-align: top; - } -} diff --git a/src/wolnelektury/static/scss/main/tag.scss b/src/wolnelektury/static/scss/main/tag.scss index d120a3f97..1e1801c13 100755 --- a/src/wolnelektury/static/scss/main/tag.scss +++ b/src/wolnelektury/static/scss/main/tag.scss @@ -1,8 +1,89 @@ -.page-desc { - @include size(margin-left, 15px); +.tabbed-filter { + position: relative; + border-bottom: 1px solid #ddd; + padding-bottom: 4em; + + @media screen and (min-width: 375px) { + padding-bottom: 2em; + } + + @media screen and (min-width: 1024px) { + padding-bottom: 0; + } + + + .tabs { + position: absolute; + right: 0; + bottom: 0; + float: right; + text-align: right; + + .tab { + cursor: pointer; + display: inline-block; + margin-bottom: -1px; + box-shadow: none; + + &.active { + border-bottom-color: white; + } + } + } } +.tabbed-filter-contents { + margin-bottom: 2em; + .tab-content { + display: none; + border-top: none; + + ul { + list-style: none; + margin-left: 0; + padding-left: 10px; + + li { + display: inline-block; + margin-right: 1em; + border-radius: 1em; + padding: .5em; + + &.header { + width: 6em; + } + + &.active { + background: #0D7E85; + color: #ddd; + + a { + display: inline-block; + width: 1.5em; + text-align: center; + margin-left: .5em; + border-radius: 1em; + background: white; + } + } + + &.other { + a { + color: #ddd; + } + } + } + } + } +} + + #tagged-object-list { + + + + + @media screen and (min-width: 62.5em) { .left-column, .right-column { @include size(width, 480px); diff --git a/src/wolnelektury/static/scss/social/shelf_tags.scss b/src/wolnelektury/static/scss/social/shelf_tags.scss index f20fba8b6..9872140bb 100644 --- a/src/wolnelektury/static/scss/social/shelf_tags.scss +++ b/src/wolnelektury/static/scss/social/shelf_tags.scss @@ -1,29 +1,13 @@ .social-shelf-tags { list-style: none; padding: 0; - margin: 10px 0; - @include min-screen($S_BOOK_SHORT_FULL) { - position: absolute; - top: 134px; - left: 152px; - padding: 10px 10px 5px 10px; - margin: 10px 0; - width: 310px; - overflow: hidden; + position: absolute; + top: 10px; + right: 50px; text-overflow: ellipsis; white-space: nowrap; - &:hover { - overflow: visible; - text-overflow: ellipsis; - white-space: normal; - z-index: 1000; - background: #fff; - box-shadow: 0 0 2px #ddd; - } - } - li { display: inline-block; margin-right: .5em; diff --git a/src/wolnelektury/templates/account/base.html b/src/wolnelektury/templates/account/base.html index 6bcdf12cf..ebd628603 100755 --- a/src/wolnelektury/templates/account/base.html +++ b/src/wolnelektury/templates/account/base.html @@ -1,7 +1,9 @@ {% extends "site_base.html" %} {% block body %} +
    {% block content %} {% endblock %} +
    {% endblock %} {% block extrabody %} diff --git a/src/wolnelektury/templates/main_page.html b/src/wolnelektury/templates/main_page.html index f1450cbd6..44f05a8b5 100755 --- a/src/wolnelektury/templates/main_page.html +++ b/src/wolnelektury/templates/main_page.html @@ -14,21 +14,79 @@ {% ssi_include 'social_cite_main' pk=cite_pk %} {{ cite_pk.endif }} +
    +

    W naszej cyfrowej bibliotece znajdziesz

    +
    +
    + {% for b in best %} + {% ssi_include 'catalogue_book_mini' pk=b.pk %} + {% endfor %} +
    +
    + i wiele innych książek, wierszy, obrazów, audiobooków… +
    +
    +
    - -
    -

    {% trans "What's new?" %}

    -
    - {% ssi_include 'chunk' key='promo' %} +
    +

    Motywy i tematy

    +
    +

    {% trans "Theme" %}: {{ theme }}

    +

    Utwory, w których występuje ten motyw:

    + {% for book in theme_books %} + {% ssi_include 'catalogue_book_mini' pk=book.pk %} + {% endfor %} + {% if theme_fragment %} + {% ssi_include 'catalogue_fragment_promo' pk=theme_fragment.pk %} + {% endif %}
    +
    Zobacz katalog motywów +
    + +
    +

    Autorzy

    + + {% ssi_include "catalogue_tag_box" pk=author.pk %} + + Zobacz katalog autorów +
    + +
    +

    Gatunki

    + + {% ssi_include "catalogue_tag_box" pk=genre.pk %} + + Zobacz katalog gatunków +
    + +
    +

    Rodzaje

    + + {% ssi_include "catalogue_tag_box" pk=kind.pk %} + + Zobacz katalog rodzajów
    +
    +

    Epoki

    + + {% ssi_include "catalogue_tag_box" pk=epoch.pk %} + + Zobacz katalog epok +
    -
    -

    {% trans "Recent publications" %}

    +
    +

    Kolekcje

    + {% ssi_include 'catalogue_collection_box' pk=collection.pk %} + Zobacz katalog kolekcji +
    + +
    +

    {% trans "Recent publications" %}

    {% for book in last_published %} {% ssi_include 'catalogue_book_mini' pk=book.pk %} {% endfor %} + {% trans "More recent publications" %}
    @@ -53,7 +111,7 @@
  • OAI-PMH
  • Leśmianator
  • Materiały do nauki j. polskiego
  • - +
    diff --git a/src/wolnelektury/templates/socialaccount/connections.html b/src/wolnelektury/templates/socialaccount/connections.html index 3df16a8c5..0c7316ed4 100644 --- a/src/wolnelektury/templates/socialaccount/connections.html +++ b/src/wolnelektury/templates/socialaccount/connections.html @@ -5,9 +5,10 @@ {% block head_title %}{% trans "Account Connections" %}{% endblock %} {% block body %} +
    +

    {% trans "Account Connections" %}

    -
    {% if form.accounts %}

    {% blocktrans %}You can sign in to your account using any of the following third party accounts:{% endblocktrans %}

    diff --git a/src/wolnelektury/templates/socialaccount/login_cancelled.html b/src/wolnelektury/templates/socialaccount/login_cancelled.html index 7e29b65c7..bee55649a 100644 --- a/src/wolnelektury/templates/socialaccount/login_cancelled.html +++ b/src/wolnelektury/templates/socialaccount/login_cancelled.html @@ -5,10 +5,10 @@ {% block head_title %}{% trans "Login Cancelled" %}{% endblock %} {% block body %} - +
    +

    {% trans "Login Cancelled" %}

    -
    {% url 'socialaccount_login' as login_url %} {{ login_url }} diff --git a/src/wolnelektury/templates/superbase.html b/src/wolnelektury/templates/superbase.html index 08d60a32a..d36f22267 100644 --- a/src/wolnelektury/templates/superbase.html +++ b/src/wolnelektury/templates/superbase.html @@ -36,34 +36,14 @@ {{ current_offer.endif }} {% endif %} +
    + -

    - {% user_username as user_username %} - {% user_is_staff as user_is_staff %} - {{ user_username.if }}{% trans "Welcome" %}, - - {{ user_username }} - - - {% trans "Password" %}
    - {% trans "E-mail" %}
    - {% trans "Social accounts" %}
    -
    -
    | {% trans "My shelf" %} - {{ user_username.endif }} - {{ user_is_staff.if }} | {% trans "Administration" %} - {{ user_is_staff.endif }} - {{ user_username.if }} | {% trans "Logout" %} - {{ user_username.else }} - {% trans "Sign in" %} / {% trans "Register" %} - {{ user_username.endif }} -

    -

    {% url 'book_list' as b %} {% url 'infopage' 'prawa' as r %} @@ -75,24 +55,10 @@ {% endblocktrans %}

    -
    -
    - - {{search_form.q}} -
    -
    - -
    -
    - - - + + + +
    +
    + + {{search_form.q}} +
    +
    + + +
    +
    +
    diff --git a/src/wolnelektury/templates/user.html b/src/wolnelektury/templates/user.html index 0ffdd62a9..fa2f66035 100644 --- a/src/wolnelektury/templates/user.html +++ b/src/wolnelektury/templates/user.html @@ -6,9 +6,10 @@ {% block body %} +
    +

    {% trans "User" %}

    -

    {% trans "Password" %}

    {% trans "E-mail" %}

    {% trans "Social accounts" %}

    diff --git a/src/wolnelektury/views.py b/src/wolnelektury/views.py index 51371735a..0ff2d67fe 100644 --- a/src/wolnelektury/views.py +++ b/src/wolnelektury/views.py @@ -18,16 +18,46 @@ from django.views.decorators.cache import never_cache from ajaxable.utils import AjaxableFormView from ajaxable.utils import placeholdized -from catalogue.models import Book +from catalogue.models import Book, Collection, Tag, Fragment from ssify import ssi_included def main_page(request): - last_published = Book.objects.exclude(cover_thumb='').filter(parent=None).order_by('-created_at')[:4] + ctx = { + 'last_published': Book.objects.exclude(cover_thumb='').filter(parent=None).order_by('-created_at')[:6], + } - return render(request, "main_page.html", { - 'last_published': last_published, - }) + for category in ('author', 'epoch', 'genre', 'kind'): + try: + ctx[category] = Tag.objects.filter(category=category).order_by('?')[:1][0] + except IndexError: + pass + + # FIXME: find this theme and books properly. + ctx['theme_books'] = [] + if Fragment.objects.count(): + while True: + ctx['theme'] = Tag.objects.filter(category='theme').order_by('?')[:1][0] + tf = Fragment.tagged.with_any([ctx['theme']]).order_by('?')[:100] + if not tf: + continue + ctx['theme_fragment'] = tf[0] + for f in tf: + if not f.book in ctx['theme_books']: + ctx['theme_books'].append(f.book) + if len(ctx['theme_books']) == 3: + break + break + + # Choose a collection for main. + try: + ctx['collection'] = Collection.objects.order_by('?')[:1][0] + except IndexError: + pass + + ctx['best'] = Book.objects.order_by('?')[:5] + + return render(request, "main_page.html", ctx) class LoginFormView(AjaxableFormView): -- 2.20.1