cover previews
authorRadek Czajka <radoslaw.czajka@nowoczesnapolska.org.pl>
Fri, 3 Feb 2012 14:07:51 +0000 (15:07 +0100)
committerRadek Czajka <radoslaw.czajka@nowoczesnapolska.org.pl>
Fri, 3 Feb 2012 14:11:49 +0000 (15:11 +0100)
14 files changed:
apps/catalogue/templates/catalogue/book_detail.html
apps/catalogue/urls.py
apps/cover/__init__.py [new file with mode: 0644]
apps/cover/models.py [new file with mode: 0644]
apps/cover/urls.py [new file with mode: 0644]
apps/cover/views.py [new file with mode: 0644]
apps/wiki/locale/pl/LC_MESSAGES/django.mo
apps/wiki/locale/pl/LC_MESSAGES/django.po
apps/wiki/templates/wiki/tabs/summary_view.html
redakcja/static/css/filelist.css
redakcja/static/css/summary.css
redakcja/static/js/wiki/view_summary.js
redakcja/static/js/wiki/wikiapi.js
redakcja/urls.py

index bfd4ef5..077ec47 100755 (executable)
@@ -41,6 +41,8 @@
 
 <h2>{% trans "Publication" %}</h2>
 
+<img class="cover-preview" src="{% url cover_preview book.slug %}" />
+
 <p>{% trans "Last published" %}: 
     {% if book.last_published %}
         {{ book.last_published }}
@@ -79,6 +81,7 @@
     <ul><li>{{ publishable_error }}</li></ul>
 {% endif %}
 
+<div style="clear: both;"></div>
 </div>
 
 
index 3ea7ffe..9bd56bb 100644 (file)
@@ -32,6 +32,7 @@ urlpatterns = patterns('catalogue.views',
     url(r'^book/(?P<slug>[^/]+)/html$', 'book_html', name="catalogue_book_html"),
     url(r'^book/(?P<slug>[^/]+)/epub$', 'book_epub', name="catalogue_book_epub"),
     url(r'^book/(?P<slug>[^/]+)/pdf$', 'book_pdf', name="catalogue_book_pdf"),
+
     url(r'^chunk_add/(?P<slug>[^/]+)/(?P<chunk>[^/]+)/$',
         'chunk_add', name="catalogue_chunk_add"),
     url(r'^chunk_edit/(?P<slug>[^/]+)/(?P<chunk>[^/]+)/$',
diff --git a/apps/cover/__init__.py b/apps/cover/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/apps/cover/models.py b/apps/cover/models.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/apps/cover/urls.py b/apps/cover/urls.py
new file mode 100644 (file)
index 0000000..24d7448
--- /dev/null
@@ -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<book>[^/]+)/$', 'preview', name='cover_preview'),
+    url(r'^preview/(?P<book>[^/]+)/(?P<chunk>[^/]+)/$',
+            'preview', name='cover_preview'),
+    url(r'^preview/(?P<book>[^/]+)/(?P<chunk>[^/]+)/(?P<rev>\d+)/$',
+            'preview', name='cover_preview'),
+)
diff --git a/apps/cover/views.py b/apps/cover/views.py
new file mode 100644 (file)
index 0000000..29fd117
--- /dev/null
@@ -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))
index d886dce..6f74d92 100644 (file)
Binary files a/apps/wiki/locale/pl/LC_MESSAGES/django.mo and b/apps/wiki/locale/pl/LC_MESSAGES/django.mo differ
index 0182abe..bfd802f 100644 (file)
@@ -7,8 +7,8 @@ msgid ""
 msgstr ""
 "Project-Id-Version: Platforma Redakcyjna\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2011-11-30 16:07+0100\n"
-"PO-Revision-Date: 2011-11-30 16:08+0100\n"
+"POT-Creation-Date: 2012-02-03 15:08+0100\n"
+"PO-Revision-Date: 2012-02-03 15:09+0100\n"
 "Last-Translator: Radek Czajka <radoslaw.czajka@nowoczesnapolska.org.pl>\n"
 "Language-Team: Fundacja Nowoczesna Polska <fundacja@nowoczesnapolska.org.pl>\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"
 
index bcea34d..ade3097 100644 (file)
@@ -3,7 +3,11 @@
     <!-- <div class="toolbar">
     </div> -->
     <div id="summary-view">
-               <img class="book-cover" src="{{ STATIC_URL }}img/sample_cover.png">
+       <div class="summary-cover-area">
+               <p><img id="summary-cover" class="book-cover"
+                       src="{% url cover_preview chunk.book.slug chunk.slug chunk.revision %}"></p>
+               <p><button id="summary-cover-refresh">{% trans "Refresh from working copy" %}</button></p>
+               </div>
 
                <h2>
                        <label for="title">{% trans "Title" %}:</label>
index 166def0..c7a65f3 100644 (file)
@@ -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;
+}
+}
index 6c05e0b..1520c36 100644 (file)
@@ -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 {
index de6fcf1..8fdf4b9 100644 (file)
@@ -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 {
index 4a4da5a..d901e84 100644 (file)
@@ -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";
        };
                });
        };
 
+       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, '<br />$1');
         var parser = new DOMParser();
index 4aedf58..1f8a7ff 100644 (file)
@@ -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<path>.+)$' % settings.MEDIA_URL[1:], 'django.views.static.serve',