Merge branch 'pretty' of github.com:fnp/wolnelektury into pretty
authorRadek Czajka <radoslaw.czajka@nowoczesnapolska.org.pl>
Thu, 19 Jan 2012 14:46:10 +0000 (15:46 +0100)
committerRadek Czajka <radoslaw.czajka@nowoczesnapolska.org.pl>
Thu, 19 Jan 2012 14:46:10 +0000 (15:46 +0100)
Conflicts:
wolnelektury/static/css/book_box.css
wolnelektury/templates/catalogue/book_wide.html

1  2 
apps/catalogue/models.py
wolnelektury/static/css/book_box.css
wolnelektury/templates/catalogue/book_wide.html

diff --combined apps/catalogue/models.py
@@@ -7,7 -7,7 +7,7 @@@ from collections import namedtupl
  from django.db import models
  from django.db.models import permalink, Q
  import django.dispatch
 -from django.core.cache import cache
 +from django.core.cache import get_cache
  from django.core.files.storage import DefaultStorage
  from django.utils.translation import ugettext_lazy as _
  from django.contrib.auth.models import User
@@@ -17,7 -17,6 +17,7 @@@ from django.utils.safestring import mar
  from django.utils.translation import get_language
  from django.core.urlresolvers import reverse
  from django.db.models.signals import post_save, m2m_changed, pre_delete
 +import jsonfield
  
  from django.conf import settings
  
@@@ -31,6 -30,7 +31,6 @@@ from glob import glo
  import re
  from os import path
  
 -
  import search
  
  # Those are hard-coded here so that makemessages sees them.
@@@ -44,8 -44,8 +44,8 @@@ TAG_CATEGORIES = 
      ('book', _('book')),
  )
  
 -# not quite, but Django wants you to set a timeout
 -CACHE_FOREVER = 2419200  # 28 days
 +
 +permanent_cache = get_cache('permanent')
  
  
  class TagSubcategoryManager(models.Manager):
@@@ -372,9 -372,6 +372,9 @@@ class Book(models.Model)
      formats = ebook_formats + ['html', 'xml']
  
      parent        = models.ForeignKey('self', blank=True, null=True, related_name='children')
 +
 +    _related_info = jsonfield.JSONField(blank=True, null=True, editable=False)
 +
      objects  = models.Manager()
      tagged   = managers.ModelTaggedItemManager(Tag)
      tags     = managers.TagDescriptor(Tag)
          if self.id is None:
              return
  
 -        cache_key = "Book.short_html/%d/%s"
 -        for lang, langname in settings.LANGUAGES:
 -            cache.delete(cache_key % (self.id, lang))
 -        cache.delete("Book.mini_box/%d" % (self.id, ))
 +        type(self).objects.filter(pk=self.pk).update(_related_info=None)
          # Fragment.short_html relies on book's tags, so reset it here too
          for fragm in self.fragments.all():
              fragm.reset_short_html()
  
 -    def short_html(self):
 -        if self.id:
 -            cache_key = "Book.short_html/%d/%s" % (self.id, get_language())
 -            short_html = cache.get(cache_key)
 -        else:
 -            short_html = None
 -
 -        if short_html is not None:
 -            return mark_safe(short_html)
 -        else:
 -            tags = self.tags.filter(category__in=('author', 'kind', 'genre', 'epoch'))
 -            tags = split_tags(tags)
 -
 -            formats = {}
 -            # files generated during publication
 -            for ebook_format in self.ebook_formats:
 -                if self.has_media(ebook_format):
 -                    formats[ebook_format] = self.get_media(ebook_format)
 -
 -
 -            short_html = unicode(render_to_string('catalogue/book_short.html',
 -                {'book': self, 'tags': tags, 'formats': formats}))
 -
 -            if self.id:
 -                cache.set(cache_key, short_html, CACHE_FOREVER)
 -            return mark_safe(short_html)
 -
 -    def mini_box(self):
 -        if self.id:
 -            cache_key = "Book.mini_box/%d" % (self.id, )
 -            short_html = cache.get(cache_key)
 -        else:
 -            short_html = None
 -
 -        if short_html is None:
 -            authors = self.tags.filter(category='author')
 -
 -            short_html = unicode(render_to_string('catalogue/book_mini_box.html',
 -                {'book': self, 'authors': authors, 'STATIC_URL': settings.STATIC_URL}))
 -
 -            if self.id:
 -                cache.set(cache_key, short_html, CACHE_FOREVER)
 -        return mark_safe(short_html)
 -
      def has_description(self):
          return len(self.description) > 0
      has_description.short_description = _('description')
              book.build_mobi()
  
          if not settings.NO_SEARCH_INDEX and search_index:
-             index_book.delay(book.id, book_info)
+             book.search_index()
+             #index_book.delay(book.id, book_info)
  
          book_descendants = list(book.children.all())
          descendants_tags = set()
          cls.published.send(sender=book)
          return book
  
 +    def related_info(self):
 +        """Keeps info about related objects (tags, media) in cache field."""
 +        if self._related_info is not None:
 +            return self._related_info
 +        else:
 +            rel = {'tags': {}, 'media': {}}
 +            tags = self.tags.filter(category__in=(
 +                    'author', 'kind', 'genre', 'epoch'))
 +            tags = split_tags(tags)
 +            for category in tags:
 +                rel['tags'][category] = [
 +                        (t.name, t.get_absolute_url()) for t in tags[category]]
 +            for media_format in BookMedia.formats:
 +                rel['media'][media_format] = self.has_media(media_format)
 +            if self.pk:
 +                type(self).objects.filter(pk=self.pk).update(_related_info=rel)
 +            return rel
 +
      def reset_tag_counter(self):
          if self.id is None:
              return
  
          cache_key = "Book.tag_counter/%d" % self.id
 -        cache.delete(cache_key)
 +        permanent_cache.delete(cache_key)
          if self.parent:
              self.parent.reset_tag_counter()
  
      def tag_counter(self):
          if self.id:
              cache_key = "Book.tag_counter/%d" % self.id
 -            tags = cache.get(cache_key)
 +            tags = permanent_cache.get(cache_key)
          else:
              tags = None
  
                  tags[tag.pk] = 1
  
              if self.id:
 -                cache.set(cache_key, tags, CACHE_FOREVER)
 +                permanent_cache.set(cache_key, tags)
          return tags
  
      def reset_theme_counter(self):
              return
  
          cache_key = "Book.theme_counter/%d" % self.id
 -        cache.delete(cache_key)
 +        permanent_cache.delete(cache_key)
          if self.parent:
              self.parent.reset_theme_counter()
  
      def theme_counter(self):
          if self.id:
              cache_key = "Book.theme_counter/%d" % self.id
 -            tags = cache.get(cache_key)
 +            tags = permanent_cache.get(cache_key)
          else:
              tags = None
  
                      tags[tag.pk] = tags.get(tag.pk, 0) + 1
  
              if self.id:
 -                cache.set(cache_key, tags, CACHE_FOREVER)
 +                permanent_cache.set(cache_key, tags)
          return tags
  
      def pretty_title(self, html_links=False):
@@@ -977,12 -1004,12 +978,12 @@@ class Fragment(models.Model)
  
          cache_key = "Fragment.short_html/%d/%s"
          for lang, langname in settings.LANGUAGES:
 -            cache.delete(cache_key % (self.id, lang))
 +            permanent_cache.delete(cache_key % (self.id, lang))
  
      def short_html(self):
          if self.id:
              cache_key = "Fragment.short_html/%d/%s" % (self.id, get_language())
 -            short_html = cache.get(cache_key)
 +            short_html = permanent_cache.get(cache_key)
          else:
              short_html = None
  
              short_html = unicode(render_to_string('catalogue/fragment_short.html',
                  {'fragment': self}))
              if self.id:
 -                cache.set(cache_key, short_html, CACHE_FOREVER)
 +                permanent_cache.set(cache_key, short_html)
              return mark_safe(short_html)
  
  
 +class Collection(models.Model):
 +    """A collection of books, which might be defined before publishing them."""
 +    title = models.CharField(_('title'), max_length=120, db_index=True)
 +    slug = models.SlugField(_('slug'), max_length=120, primary_key=True)
 +    description = models.TextField(_('description'), null=True, blank=True)
 +
 +    models.SlugField(_('slug'), max_length=120, unique=True, db_index=True)
 +    book_slugs = models.TextField(_('book slugs'))
 +
 +    class Meta:
 +        ordering = ('title',)
 +        verbose_name = _('collection')
 +        verbose_name_plural = _('collections')
 +
 +    def __unicode__(self):
 +        return self.title
 +
 +
  ###########
  #
  # SIGNALS
@@@ -1,8 -1,5 +1,8 @@@
 -.book-wide-box, .book-mini-box, .book-box {
 +.book-mini-box, .Book-item {
      display: inline-block;
 +}
 +
 +.book-wide-box, .book-box {
      margin: 0;
      vertical-align: top;
  }
  
  .book-wide-box {
      width: 98.5em;
+     /** This is a fullpage box, it must be aligned with the top menu. 
+         This corresponds to a .1em margin below **/
      margin-left: -0.1em;
  }
  
+ /* 
+  * A mini-box wraps it's contents (image + label) in an <a>
+  * other boxes have an inner box as a wrapper.
+  */
+ .book-box-inner {
+     /* min, so it can grow */
+     min-height: 19.75em; 
+     margin: .5em;
+ }
  .book-mini-box a, .book-box-inner {
      display: block;
      color: black;
      border: 1px solid #ddd;
-     height: 20em;
+ /*    height: 20em; */
      padding: .8em 1em;
      margin: .1em;
      background: #fff;
      margin: .1em;
      overflow: hidden;
  }
- .book-box-inner {
-     height: 19.75em;
-     margin: .5em;
- }
  
  .book-wide-box .book-box-inner {
-     height: 24.4em;
+    /* min, so it can grow */ 
+    min-height: 24.4em;
  }
  
+ /*.book-wide-box.search-result .book-box-inner, .book-wide-box.search-result blockquote {
+     height: auto !important;
+ }*/
  .book-mini-box img, .book-box img, .book-wide-box img {
      width: 13.9em;
      height: 19.3em;
@@@ -77,7 -90,6 +93,7 @@@
  .book-box-body {
      height: 17em;
      overflow: hidden;
 +    position: relative;
  }
  
  .book-wide-box .book-box-body {
      margin-left: 14em;
  }
  
 -.book-box-tools a.downarrow:before {
 +.book-box-read a:before {
      content: "\2609";
      font-family: WL-Nav;
      font-size: 2.25em;
      margin-right: .15em;
      vertical-align: middle;
 +    font-weight: normal;
 +}
 +
 +.book-box-download a:before {
 +    content: "\21E9";
 +    font-family: WL-Nav;
 +    font-size: 2.25em;
 +    margin-right: .15em;
 +    vertical-align: middle;
 +    font-weight: normal;
  }
  
  .book-box-audiobook a:before {
      font-size: 2.25em;
      margin-right: .15em;
      vertical-align: middle;
 +    font-weight: normal;
  }
  
  ul.book-box-tools {
      vertical-align: center;
  }
  
- .book-wide-box blockquote div {
+ .book-wide-box blockquote div.cite-text {
      padding: 0.888em;
  }
  
+ .book-wide-box blockquote p.cite-more {
+     display: inline;
+     font-size: 0.611em;
+     float: right;
+ }
  ul.inline-items, ul.inline-items li {
      margin: 0;
      padding: 0;
@@@ -225,52 -232,20 +247,54 @@@ ul.inline-items li 
      display: inline-block;
  }
  
- .book-wide-box #other-tools {
+ .book-wide-box .other-tools {
      float: left;
      width: 14.5em;
      margin: 6em 0 0 1.5em;
      
  }
  
- .book-wide-box #other-download {
+ .book-wide-box .other-download {
      float: left;
      width: 22.5em;
-     margin: 6em 1.5em 0em 1.5em
+     margin: 6em 1.5em 0em 1.5em;
  }
  
 +
 -}
 +.star {
 +    font-size: 2.25em;
 +    margin-right: .5em;
 +    position: absolute;
 +    right: 0;
 +}
 +.star button::-moz-focus-inner {
 +    padding: 0;
 +    border: 0
 +}
 +.if-unlike button {
 +    font-size: 1em;
 +    font-family: inherit;
 +    border: 0;
 +    background: none;
 +    margin: 0;
 +    padding: 0;
 +}
 +
 +.if-like a {
 +    display:block;
 +    text-align:right;
 +    padding: 0;
 +}
 +
 +.like .if-unlike {
 +    display: none;
 +}
 +
 +.unlike .if-like {
 +    display: none;
 +}
 +
+ .snippets .snippet-text {
+     font-size: 1.2em;
+     margin: 1.083em 0em;
++}
@@@ -6,12 -6,13 +6,13 @@@
  {% block right-column %}
  <div class="right-column">
    <blockquote id="quote" class="cite-body">
+     {% block quote %}
      <div>Ten, który walczy z potworami powinien zadbać, by sam nie stał się potworem. 
      Gdy długo spoglądamy w otchłań, otchłań spogląda również w nas.</div>
+     {% endblock %}
    </blockquote>
  
-   <div id="other-tools">
+   <div class="other-tools">
      <h2 class="mono">{% trans "See" %}</h2>
      <ul class="inline-items">
        {% if extra_info.source_url %}
        {% endif %}
      </ul>
    </div>
-   <div id="other-download">
+   <div class="other-download">
      <h2 class="mono">{% trans "Download" %}</h2>
      <ul class="inline-items">
        <li>
 -      {% if has_media.mp3 or has_media.ogg %}
 +      {% if related.media.mp3 or related.media.ogg %}
        {% trans "Download all audiobooks for this book" %}: 
 -      {% if has_media.mp3 %}<a href="{% url download_zip_mp3 book.slug %}">MP3</a>{% endif %}{% if has_media.mp4 and has_media.ogg %},{% endif %}
 -      {% if has_media.ogg %}<a href="{% url download_zip_ogg book.slug %}">OGG</a>{% endif %}.
 +      {% if related.media.mp3 %}<a href="{% url download_zip_mp3 book.slug %}">MP3</a>{% endif %}{% if related.media.mp3 and related.media.ogg %},{% endif %}
 +      {% if related.media.ogg %}<a href="{% url download_zip_ogg book.slug %}">OGG</a>{% endif %}.
        {% endif %}
        </li>
        <li>