From 55bc643c16dc56cf2377bd5c4d6e924d5fc62698 Mon Sep 17 00:00:00 2001 From: Marcin Koziej Date: Thu, 12 Jan 2012 16:40:27 +0100 Subject: [PATCH] book search - new design - almost ready --- apps/search/index.py | 15 +++-- apps/search/templatetags/__init__.py | 0 apps/search/templatetags/search_tags.py | 45 ++++++++++++++ wolnelektury/static/css/base.css | 2 +- wolnelektury/static/css/book_box.css | 46 ++++++++++---- wolnelektury/static/css/master.css | 4 ++ wolnelektury/static/js/search.js | 4 ++ .../templates/catalogue/book_searched.html | 34 +++++++++++ .../templates/catalogue/book_wide.html | 6 +- .../catalogue/search_multiple_hits.html | 60 ++----------------- 10 files changed, 141 insertions(+), 75 deletions(-) create mode 100644 apps/search/templatetags/__init__.py create mode 100644 apps/search/templatetags/search_tags.py create mode 100644 wolnelektury/templates/catalogue/book_searched.html diff --git a/apps/search/index.py b/apps/search/index.py index cc478ee53..e59c38b17 100644 --- a/apps/search/index.py +++ b/apps/search/index.py @@ -408,7 +408,7 @@ class Index(BaseIndex): doc = add_part(snippets, header_index=position, header_type=header.tag, content=content) self.index.addDocument(doc) - + for start, end in walker(header): if start is not None and start.tag == 'begin': fid = start.attrib['id'][1:] @@ -563,6 +563,8 @@ class SearchResult(object): fragment = stored.get("fragment_anchor") + if snippets: + snippets = snippets.replace("/\n", "\n") hit = (sec + (header_span,), fragment, scoreDocs.score, {'how_found': how_found, 'snippets': snippets and [snippets] or []}) self._hits.append(hit) @@ -630,6 +632,7 @@ class SearchResult(object): frag = catalogue.models.Fragment.objects.get(anchor=f[FRAGMENT]) m = {'score': f[SCORE], 'fragment': frag, + 'section_number': f[POSITION][POSITION_INDEX] + 1, 'themes': frag.tags.filter(category='theme') } m.update(f[OTHER]) @@ -884,7 +887,7 @@ class Search(IndexStore): self.chain_filters([only_in, self.term_filter(Term('is_book', 'true'))]), max_results) for found in top.scoreDocs: - books.append(SearchResult(self.searcher, found)) + books.append(SearchResult(self.searcher, found, how_found="search_perfect_book")) return books def search_book(self, searched, max_results=20, fuzzy=False, hint=None): @@ -910,7 +913,7 @@ class Search(IndexStore): self.chain_filters([only_in, self.term_filter(Term('is_book', 'true'))]), max_results) for found in top.scoreDocs: - books.append(SearchResult(self.searcher, found)) + books.append(SearchResult(self.searcher, found, how_found="search_book")) return books @@ -932,7 +935,7 @@ class Search(IndexStore): flt]), max_results) for found in top.scoreDocs: - books.append(SearchResult(self.searcher, found, snippets=self.get_snippets(found, q))) + books.append(SearchResult(self.searcher, found, snippets=self.get_snippets(found, q), how_found='search_perfect_parts')) return books @@ -964,7 +967,7 @@ class Search(IndexStore): topDocs = self.searcher.search(q, only_in, max_results) for found in topDocs.scoreDocs: - books.append(SearchResult(self.searcher, found)) + books.append(SearchResult(self.searcher, found, how_found='search_everywhere_themesXcontent')) print "* %s theme x content: %s" % (searched, books[-1]._hits) # query themes/content x author/title/tags @@ -983,7 +986,7 @@ class Search(IndexStore): topDocs = self.searcher.search(q, only_in, max_results) for found in topDocs.scoreDocs: - books.append(SearchResult(self.searcher, found)) + books.append(SearchResult(self.searcher, found, how_found='search_everywhere')) print "* %s scatter search: %s" % (searched, books[-1]._hits) return books diff --git a/apps/search/templatetags/__init__.py b/apps/search/templatetags/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/apps/search/templatetags/search_tags.py b/apps/search/templatetags/search_tags.py new file mode 100644 index 000000000..03e33c8d2 --- /dev/null +++ b/apps/search/templatetags/search_tags.py @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later. +# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. +# +# import feedparser +# import datetime + +from django import template +from django.template import Node, Variable +from django.utils.encoding import smart_str +from django.core.urlresolvers import reverse +# from django.contrib.auth.forms import UserCreationForm, AuthenticationForm +# from django.db.models import Q +from django.conf import settings +# from django.utils.translation import ugettext as _ +from catalogue.templatetags.catalogue_tags import book_wide +from catalogue.models import Book +# from catalogue.forms import SearchForm +# from catalogue.utils import split_tags + + +register = template.Library() + + +@register.inclusion_tag('catalogue/book_searched.html') +def book_searched(result): + book = Book.objects.get(pk=result.book_id) + vals = book_wide(book) + + # snippets = [] + # for hit in result.hits: + # if hit['snippets']: + # snippets.append(hit['snippets']) + # elif hit['fragment']: + # snippets.append(hit['fragment'].short_text) + + # We don't need hits which lead to sections but do not have + # snippets. + vals['hits'] = filter(lambda h: 'fragment' in h or + h['snippets'], result.hits) + + for hit in vals['hits']: + hit['snippets'] = map(lambda s: s.replace("\n", "
").replace('---', '—'), hit['snippets']) + + return vals diff --git a/wolnelektury/static/css/base.css b/wolnelektury/static/css/base.css index 5ce2f5a78..556d926c7 100755 --- a/wolnelektury/static/css/base.css +++ b/wolnelektury/static/css/base.css @@ -57,7 +57,7 @@ h2 { .mono { font-family: "Andale Mono", "Lucida Sans Typewriter", "Courier New"; - font-weight: bold; +/* font-weight: bold; */ } .accent1 { diff --git a/wolnelektury/static/css/book_box.css b/wolnelektury/static/css/book_box.css index 12adda1d9..273cde5f1 100755 --- a/wolnelektury/static/css/book_box.css +++ b/wolnelektury/static/css/book_box.css @@ -15,14 +15,28 @@ .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 + * 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; @@ -36,15 +50,17 @@ 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; @@ -197,10 +213,16 @@ 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; @@ -210,16 +232,20 @@ 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; } +.snippets .snippet-text { + font-size: 1.2em; + margin: 1.083em 0em; +} \ No newline at end of file diff --git a/wolnelektury/static/css/master.css b/wolnelektury/static/css/master.css index 85f1a40d7..26c13cc71 100644 --- a/wolnelektury/static/css/master.css +++ b/wolnelektury/static/css/master.css @@ -147,6 +147,10 @@ hr { border-right: none; } +#lang-menu-items { + z-index: 1; +} + /* ======================== */ /* = Footer with sponsors = */ /* ======================== */ diff --git a/wolnelektury/static/js/search.js b/wolnelektury/static/js/search.js index 47b6665a6..5951b8b05 100644 --- a/wolnelektury/static/js/search.js +++ b/wolnelektury/static/js/search.js @@ -43,6 +43,10 @@ var __bind = function (self, fn) { $(function() { $("#search").search().labelify({labelledClass: "blur"}); + + $(".search-result .see-more-snippets").click(function() { + $(this).closest('.search-result').find('.snippets').removeClass('ui-helper-hidden'); + }); }); diff --git a/wolnelektury/templates/catalogue/book_searched.html b/wolnelektury/templates/catalogue/book_searched.html new file mode 100644 index 000000000..d719f30e2 --- /dev/null +++ b/wolnelektury/templates/catalogue/book_searched.html @@ -0,0 +1,34 @@ +{% extends "catalogue/book_wide.html" %} +{% load i18n %} + + +{% block box-class %}book-wide-box search-result{% endblock %} + +{% block quote %} +{% if hits.0.snippets %} +
{{hits.0.snippets.0|safe}}
+{% else %}{% if hits.0.fragment %} +
{{hits.0.fragment.short_text|safe}}
+{% endif %}{% endif %} + +{% if hits.1 %} +

{% trans "See more" %}

+{% endif %} +{% endblock %} + + +{% block box-append %} +
+ +{% for hit in hits %} + {% if hit.snippets %} + + {% else %} + {% if hit.fragment %} + + {% endif %} + {% endif %} +{% endfor %} + +
+{% endblock %} diff --git a/wolnelektury/templates/catalogue/book_wide.html b/wolnelektury/templates/catalogue/book_wide.html index 0506c8ec8..bbdd333e9 100644 --- a/wolnelektury/templates/catalogue/book_wide.html +++ b/wolnelektury/templates/catalogue/book_wide.html @@ -6,11 +6,13 @@ {% block right-column %}
+ {% block quote %}
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.
+ {% endblock %}
-
+

{% trans "See" %}

    {% if extra_info.source_url %} @@ -27,7 +29,7 @@ {% endif %}
-
+

{% trans "Download" %}

  • diff --git a/wolnelektury/templates/catalogue/search_multiple_hits.html b/wolnelektury/templates/catalogue/search_multiple_hits.html index 7a3e580b8..5d222519f 100644 --- a/wolnelektury/templates/catalogue/search_multiple_hits.html +++ b/wolnelektury/templates/catalogue/search_multiple_hits.html @@ -1,75 +1,23 @@ {% extends "base.html" %} {% load i18n %} -{% load catalogue_tags pagination_tags %} +{% load search_tags pagination_tags %} {% block titleextra %}{% trans "Search" %}{% endblock %} {% block bodyid %}tagged-object-list{% endblock %} {% block body %} -

    {% trans "Search" %}

    - {% if did_you_mean %} {% trans "Dod you mean" %} {{did_you_mean|lower}}? {% endif %} + +
    -
      {% for result in results %} -
    1. -

      {{result.book.pretty_title}} (id: {{result.book_id}}, score: {{result.score}})

      -
        - {% for hit in result.hits %} -
      • - {% if hit.fragment %} - Idź do fragmentu -
        Tagi/Motywy: {% for tag in hit.themes %}{{tag.name}} {% endfor %}
        - {# snippets or short html? #} - {% if hit.snippets %} - {% for snip in hit.snippets %} - {{snip|safe}}
        - {% endfor %} - {% else %} - {{hit.fragment.short_text|safe}} - {% endif %} - - {% else %} - {# it's a section #} - {{hit.header_index}} - {% if hit.snippets %} - {% for snip in hit.snippets %} - {{snip|safe}}
        - {% endfor %} - {% else %} - [section matched but no snippets :-(] - {% endif %} - {% endif %} -
      • - {% endfor %} - -
      -
    2. - {% empty %} -

      No results.

      + {% book_searched result %} {% endfor %} -
    -{% comment %} -
    -

    {% trans "More than one result matching the criteria found." %}

    - -
    -{% endcomment %} {% endblock %} -- 2.20.1