From 0da29a22a23a90561df3d201a299f3007c84d524 Mon Sep 17 00:00:00 2001 From: Radek Czajka Date: Fri, 3 Feb 2012 15:07:51 +0100 Subject: [PATCH 1/1] cover previews --- .../templates/catalogue/book_detail.html | 3 + apps/catalogue/urls.py | 1 + apps/cover/__init__.py | 0 apps/cover/models.py | 0 apps/cover/urls.py | 12 ++++ apps/cover/views.py | 66 ++++++++++++++++++ apps/wiki/locale/pl/LC_MESSAGES/django.mo | Bin 3648 -> 3744 bytes apps/wiki/locale/pl/LC_MESSAGES/django.po | 24 ++++--- .../templates/wiki/tabs/summary_view.html | 6 +- redakcja/static/css/filelist.css | 10 ++- redakcja/static/css/summary.css | 7 +- redakcja/static/js/wiki/view_summary.js | 21 ++++++ redakcja/static/js/wiki/wikiapi.js | 22 ++++++ redakcja/urls.py | 1 + 14 files changed, 157 insertions(+), 16 deletions(-) create mode 100644 apps/cover/__init__.py create mode 100644 apps/cover/models.py create mode 100644 apps/cover/urls.py create mode 100644 apps/cover/views.py diff --git a/apps/catalogue/templates/catalogue/book_detail.html b/apps/catalogue/templates/catalogue/book_detail.html index bfd4ef5c..077ec475 100755 --- a/apps/catalogue/templates/catalogue/book_detail.html +++ b/apps/catalogue/templates/catalogue/book_detail.html @@ -41,6 +41,8 @@

{% trans "Publication" %}

+ +

{% trans "Last published" %}: {% if book.last_published %} {{ book.last_published }} @@ -79,6 +81,7 @@

{% endif %} +
diff --git a/apps/catalogue/urls.py b/apps/catalogue/urls.py index 3ea7ffe5..9bd56bbe 100644 --- a/apps/catalogue/urls.py +++ b/apps/catalogue/urls.py @@ -32,6 +32,7 @@ urlpatterns = patterns('catalogue.views', url(r'^book/(?P[^/]+)/html$', 'book_html', name="catalogue_book_html"), url(r'^book/(?P[^/]+)/epub$', 'book_epub', name="catalogue_book_epub"), url(r'^book/(?P[^/]+)/pdf$', 'book_pdf', name="catalogue_book_pdf"), + url(r'^chunk_add/(?P[^/]+)/(?P[^/]+)/$', 'chunk_add', name="catalogue_chunk_add"), url(r'^chunk_edit/(?P[^/]+)/(?P[^/]+)/$', diff --git a/apps/cover/__init__.py b/apps/cover/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/apps/cover/models.py b/apps/cover/models.py new file mode 100644 index 00000000..e69de29b diff --git a/apps/cover/urls.py b/apps/cover/urls.py new file mode 100644 index 00000000..24d7448a --- /dev/null +++ b/apps/cover/urls.py @@ -0,0 +1,12 @@ +# -*- coding: utf-8 +from django.conf.urls.defaults import patterns, url + + +urlpatterns = patterns('cover.views', + url(r'^preview/$', 'preview_from_xml', name='cover_preview'), + url(r'^preview/(?P[^/]+)/$', 'preview', name='cover_preview'), + url(r'^preview/(?P[^/]+)/(?P[^/]+)/$', + 'preview', name='cover_preview'), + url(r'^preview/(?P[^/]+)/(?P[^/]+)/(?P\d+)/$', + 'preview', name='cover_preview'), +) diff --git a/apps/cover/views.py b/apps/cover/views.py new file mode 100644 index 00000000..29fd117a --- /dev/null +++ b/apps/cover/views.py @@ -0,0 +1,66 @@ +# Create your views here. +import os.path +from django.conf import settings +from django.http import HttpResponse, Http404 +from catalogue.models import Chunk +from django.views.decorators.http import require_POST +from django.views.decorators.csrf import csrf_exempt +from django.shortcuts import render + + +PREVIEW_SIZE = (216, 300) + +def preview(request, book, chunk=None, rev=None): + """Creates a cover image. + + If chunk and rev number are given, use version from given revision. + If rev is not given, use publishable version. + """ + import Image + from librarian.cover import WLCover + from librarian.dcparser import BookInfo + + chunk = Chunk.get(book, chunk) + if rev is not None: + try: + revision = chunk.at_revision(rev) + except Chunk.change_model.DoesNotExist: + raise Http404 + else: + revision = chunk.publishable() + if revision is None: + raise Http404 + xml = revision.materialize().encode('utf-8') + + info = BookInfo.from_string(xml) + cover = WLCover(info) + response = HttpResponse(mimetype=cover.mime_type()) + image = cover.image().resize(PREVIEW_SIZE, Image.ANTIALIAS) + image.save(response, cover.format) + return response + + +@csrf_exempt +@require_POST +def preview_from_xml(request): + from hashlib import sha1 + import Image + from os import makedirs + from lxml import etree + from librarian.cover import WLCover + from librarian.dcparser import BookInfo + + xml = request.POST['xml'] + info = BookInfo.from_string(xml.encode('utf-8')) + coverid = sha1(etree.tostring(info.to_etree())).hexdigest() + cover = WLCover(info) + + cover_dir = 'cover/preview' + try: + makedirs(os.path.join(settings.MEDIA_ROOT, cover_dir)) + except OSError: + pass + fname = os.path.join(cover_dir, "%s.%s" % (coverid, cover.ext())) + image = cover.image().resize(PREVIEW_SIZE, Image.ANTIALIAS) + image.save(os.path.join(settings.MEDIA_ROOT, fname)) + return HttpResponse(os.path.join(settings.MEDIA_URL, fname)) diff --git a/apps/wiki/locale/pl/LC_MESSAGES/django.mo b/apps/wiki/locale/pl/LC_MESSAGES/django.mo index d886dcecd0cc8b1f59469d0a1177d016c2f413fa..6f74d92622efe3cedb893320dc6b054c045dc952 100644 GIT binary patch delta 1516 zcmaLXO-NKx7{>AAs7>maX_lEqu&v;z4>2TlsJ7@09Iq!Y%xieNgR1%xa zOS@@kO++z~?=t2vdeS)2y3>ux!X8|J=W!8Uw&S=R58^UDzlTLQhKundX5cjD;4fT( zZYC==CT2?MXo0=fR&+Byic8Ut%H^E>{32E{zJj?piXMD{N^AnP&=fAg8Dt@o$)sAx zi<++ib6DT(v=^F@!yMtX5Rcij3%~528x_67{=x$YDNlO2sKu zVxLj-f5VtMKj|pL-^gKH%yKn_EK%cInR7oFLM=Ru`u;;K!N-`7A5f+KihB0B+$LR9 zimH$oRe>F-J<^gz{dGsD?S&{R^8wUmyn#yaJ}Qw%sAoThO5{6om|0FLbtaQ(p)yoL zwOEP!P~VH7Ds%}8@S2DE(>HfHX`u(Gj7L!uJVV{#dsJdG_WG^Rm>M+*+1GKwRQKDi;mR1<57EgI0a&XGK?sbvqKVKOXstA>Q zCo$g|=+qK=9nJ1wFqGJzp5`j(4EuXeI-TLr87C47cLjncoa3SHXrkHuCMCPZ>*J_( zs_Pnk_3?^~qJKVVNF2=AlUj73WBg7e;2(eDoOS#i(Y{cmJ?KB>MEv32MBFoy@)vw< BgCqa| delta 1416 zcmY+^Ur3Wt7{~EvbJLb{rrB!g(*Dg{PB)j%mPUVW$}WUN@**Ng=t8m(Dk5-r84?I1 z3!;eVA|or9H$j9DQQf%9x=QOdh`cGtF8co5DeCY(@8_I%d(U&;=e*m!=zK%&W3BIo z(e@J!M9^zCfWOK((T@1dD)A_m;~<9cq#KX8@fe1=K7sXk3)kTs2JkgjV-YvwB5pIw z*-tu35M_4Rf)&__8?YCBIN+`iVLRi~Sc6j-#QUg)Jw+vYiR*CzNo1c<^ZS`x^VMKA z`7KOGAHB|f&a0@2Cvg)_p}seRwfGE`=M{2TkyDub z_MT20zaqu32-)?8MrSiBaXVIFkFyVxjE7JqzJ|Ilj~sTJlXmd|YGDsi^Upd9n9~ZM z)8VjrPLm$9cWykmwsgZORN`UO_s1}bSFjFmqDuT2wdY0Tuq95a&=*t%R#5Loh%)Gb z;+522A7r?omG_}u!sDowo<}Y0B5KdaQ44v39QJ~fO8pj<=o4x|%h-nHWT9)Fs0tm# zjd%<>>`ajQE71i;TJa^+1QVzQO}p!NoinHf&!L|54XPp^+<4KAzoA~vAE<=|ST$XX zU<6|r!vi@wn&2$zNk`rIGU{y}M@?|uc?UZf&!QHvgnF`N)cq@N?BixVSO~R{Iya7? z^0lHCluOfL%l|g5PE9|(p4DEdgzD;L(oM}8(6pCIs>*5q^+b9hl|YTDZ7ZRz)3*NG z+DZex|D`AKVtjSPeqk@6Eztg|0!>7k(Ejm|mLT>KdJ%ULJBU9`6;jI*`m^aGRE;f! zehF%-npuD8UrT$wm)Ndrv{qslp}p3hh*~$%La3Z6LTwMxNbDx`51J{Q^9Q|!e8qyN iDwRm366s`9sw\n" "Language-Team: Fundacja Nowoczesna Polska \n" "Language: \n" @@ -219,38 +219,42 @@ msgid "Source code" msgstr "Kod źródłowy" #: templates/wiki/tabs/summary_view.html:9 +msgid "Refresh from working copy" +msgstr "Odśwież z edytowanej wersji" + +#: templates/wiki/tabs/summary_view.html:13 msgid "Title" msgstr "Tytuł" -#: templates/wiki/tabs/summary_view.html:13 +#: templates/wiki/tabs/summary_view.html:17 msgid "Go to the book's page" msgstr "Przejdź do strony książki" -#: templates/wiki/tabs/summary_view.html:16 +#: templates/wiki/tabs/summary_view.html:20 msgid "Document ID" msgstr "ID dokumentu" -#: templates/wiki/tabs/summary_view.html:20 +#: templates/wiki/tabs/summary_view.html:24 msgid "Current version" msgstr "Aktualna wersja" -#: templates/wiki/tabs/summary_view.html:23 +#: templates/wiki/tabs/summary_view.html:27 msgid "Last edited by" msgstr "Ostatnio edytowane przez" -#: templates/wiki/tabs/summary_view.html:27 +#: templates/wiki/tabs/summary_view.html:31 msgid "Link to gallery" msgstr "Link do galerii" -#: templates/wiki/tabs/summary_view.html:32 +#: templates/wiki/tabs/summary_view.html:36 msgid "Characters in document" msgstr "Znaków w dokumencie" -#: templates/wiki/tabs/summary_view.html:33 +#: templates/wiki/tabs/summary_view.html:37 msgid "pages" msgstr "stron maszynopisu" -#: templates/wiki/tabs/summary_view.html:33 +#: templates/wiki/tabs/summary_view.html:37 msgid "untagged" msgstr "nieotagowane" diff --git a/apps/wiki/templates/wiki/tabs/summary_view.html b/apps/wiki/templates/wiki/tabs/summary_view.html index bcea34da..ade3097f 100644 --- a/apps/wiki/templates/wiki/tabs/summary_view.html +++ b/apps/wiki/templates/wiki/tabs/summary_view.html @@ -3,7 +3,11 @@
- +
+

+

+

diff --git a/redakcja/static/css/filelist.css b/redakcja/static/css/filelist.css index 166def07..c7a65f31 100644 --- a/redakcja/static/css/filelist.css +++ b/redakcja/static/css/filelist.css @@ -223,4 +223,12 @@ a:hover { .wall .publish { background-color: #fdc; -} \ No newline at end of file +} + +.cover-preview { + width: 216px; + height: 300px; + float: left; + margin-right: 2em; +} +} diff --git a/redakcja/static/css/summary.css b/redakcja/static/css/summary.css index 6c05e0be..1520c36b 100644 --- a/redakcja/static/css/summary.css +++ b/redakcja/static/css/summary.css @@ -6,16 +6,15 @@ padding: 1em; } -#summary-view .book-cover { +#summary-view .summary-cover-area { float: left; margin: 1em; margin-right: 2em; +} +#summary-view .book-cover { height: 300px; width: 212px; - - - border: 1px dashed black; } #summary-view p { diff --git a/redakcja/static/js/wiki/view_summary.js b/redakcja/static/js/wiki/view_summary.js index de6fcf15..8fdf4b96 100644 --- a/redakcja/static/js/wiki/view_summary.js +++ b/redakcja/static/js/wiki/view_summary.js @@ -1,11 +1,32 @@ (function($){ function SummaryPerspective(options) { + var old_callback = options.callback || function() {}; + + options.callback = function() { + var self = this; + + // first time page is rendered + $('#summary-cover-refresh').click(function() { + self.refreshCover(); + }); + + old_callback.call(this); + } + $.wiki.Perspective.call(this, options); }; SummaryPerspective.prototype = new $.wiki.Perspective(); + SummaryPerspective.prototype.refreshCover = function() { + this.doc.refreshCover({ + success: function(text) { + $('#summary-cover').attr('src', text); + } + }); + }; + SummaryPerspective.prototype.showCharCount = function() { var cc; try { diff --git a/redakcja/static/js/wiki/wikiapi.js b/redakcja/static/js/wiki/wikiapi.js index 4a4da5a7..d901e847 100644 --- a/redakcja/static/js/wiki/wikiapi.js +++ b/redakcja/static/js/wiki/wikiapi.js @@ -50,6 +50,9 @@ if (vname == "ajax_document_pubmark") return base_path + "/pubmark/" + arguments[1] + '/'; + if (vname == "ajax_cover_preview") + return "/cover/preview/"; + console.log("Couldn't reverse match:", vname); return "/404.html"; }; @@ -383,6 +386,25 @@ }); }; + WikiDocument.prototype.refreshCover = function(params) { + var self = this; + var data = { + xml: self.text // TODO: send just DC + }; + $.ajax({ + url: reverse("ajax_cover_preview"), + type: "POST", + data: data, + success: function(data) { + params.success(data); + }, + error: function(xhr) { + // params.failure("Nie udało się odświeżyć okładki - błąd serwera."); + } + }); + }; + + WikiDocument.prototype.getLength = function(params) { var xml = this.text.replace(/\/(\s+)/g, '
$1'); var parser = new DOMParser(); diff --git a/redakcja/urls.py b/redakcja/urls.py index 4aedf58f..1f8a7ff3 100644 --- a/redakcja/urls.py +++ b/redakcja/urls.py @@ -26,6 +26,7 @@ urlpatterns = patterns('', url(r'^documents/', include('catalogue.urls')), url(r'^apiclient/', include('apiclient.urls')), url(r'^editor/', include('wiki.urls')), + url(r'^cover/', include('cover.urls')), # Static files (should be served by Apache) url(r'^%s(?P.+)$' % settings.MEDIA_URL[1:], 'django.views.static.serve', -- 2.20.1