From: Lukasz Date: Tue, 18 May 2010 08:30:32 +0000 (+0200) Subject: Merge branch 'master' of http://github.com/fnp/wolnelektury X-Git-Url: https://git.mdrn.pl/wolnelektury.git/commitdiff_plain/735368cfb54c8954518179993dcd3bc55e3878e7?hp=fadccea9dfcbacc70e113abb17444654e2e926c3 Merge branch 'master' of github.com/fnp/wolnelektury Conflicts: wolnelektury/settings.py wolnelektury/templates/catalogue/book_stub_detail.html wolnelektury/templates/catalogue/search_no_hits.html wolnelektury/templates/catalogue/tagged_object_list.html --- diff --git a/apps/catalogue/views.py b/apps/catalogue/views.py index 7cbba2748..07fb7d349 100644 --- a/apps/catalogue/views.py +++ b/apps/catalogue/views.py @@ -7,6 +7,7 @@ import zipfile import sys import pprint import traceback +import re from django.conf import settings from django.template import RequestContext @@ -22,7 +23,9 @@ from django.contrib.auth.forms import UserCreationForm, AuthenticationForm from django.utils import simplejson from django.utils.functional import Promise from django.utils.encoding import force_unicode +from django.utils.http import urlquote_plus from django.views.decorators import cache +from django.utils.translation import ugettext as _ from catalogue import models from catalogue import forms @@ -170,16 +173,24 @@ def book_text(request, slug): # ========== # = Search = # ========== + +def _no_diacritics_regexp(query): + """ returns a regexp for searching for a query without diacritics + + should be locale-aware """ + names = {'a':u'ą', 'c':u'ć', 'e':u'ę', 'l': u'ł', 'n':u'ń', 'o':u'ó', 's':u'ś', 'z':u'ź|ż'} + def repl(m): + l = m.group() + return "(%s|%s)" % (l, names[l]) + return re.sub('[%s]'%(''.join(names.keys())), repl, query) + def _word_starts_with(name, prefix): - """returns a Q object gettings models having `name` contain a word + """returns a Q object getting models having `name` contain a word starting with `prefix` """ kwargs = {} if settings.DATABASE_ENGINE in ('mysql', 'postgresql_psycopg2', 'postgresql'): - # we must escape `prefix` so that it only matches literally - for special in r'\^$.*+?|(){}[]': - prefix = prefix.replace(special, '\\' + special) - + prefix = _no_diacritics_regexp(re.escape(prefix)) # we could use a [[:<:]] (word start), # but we want both `xy` and `(xy` to catch `(xyz)` kwargs['%s__iregex' % name] = u"(^|[^[:alpha:]])%s" % prefix @@ -190,6 +201,19 @@ def _word_starts_with(name, prefix): return Q(**kwargs) +def _tags_exact_matches(prefix, user): + book_stubs = models.BookStub.objects.filter(title__iexact = prefix) + books = models.Book.objects.filter(title__iexact = prefix) + book_stubs = filter(lambda x: x not in books, book_stubs) + tags = models.Tag.objects.filter(name__iexact = prefix) + if user.is_authenticated(): + tags = tags.filter(~Q(category='book') & (~Q(category='set') | Q(user=user))) + else: + tags = tags.filter(~Q(category='book') & ~Q(category='set')) + + return list(books) + list(tags) + list(book_stubs) + + def _tags_starting_with(prefix, user): book_stubs = models.BookStub.objects.filter(_word_starts_with('title', prefix)) books = models.Book.objects.filter(_word_starts_with('title', prefix)) @@ -203,6 +227,24 @@ def _tags_starting_with(prefix, user): return list(books) + list(tags) + list(book_stubs) + +def _get_result_link(match, tag_list): + if isinstance(match, models.Book) or isinstance(match, models.BookStub): + return match.get_absolute_url() + else: + return reverse('catalogue.views.tagged_object_list', + kwargs={'tags': '/'.join(tag.slug for tag in tag_list + [match])} + ) + +def _get_result_type(match): + if isinstance(match, models.Book) or isinstance(match, models.BookStub): + type = 'book' + else: + type = match.category + return dict(models.TAG_CATEGORIES)[type] + + + def search(request): tags = request.GET.get('tags', '') prefix = request.GET.get('q', '') @@ -214,22 +256,25 @@ def search(request): # Prefix must have at least 2 characters if len(prefix) < 2: - return render_to_response('catalogue/search_no_hits.html', {'query':prefix, 'tags':tag_list}, + return render_to_response('catalogue/search_too_short.html', {'tags':tag_list, 'prefix':prefix}, context_instance=RequestContext(request)) - result = _tags_starting_with(prefix, request.user) - if len(result) > 0: - tag = result[0] - if isinstance(tag, models.Book) or isinstance(tag, models.BookStub): - return HttpResponseRedirect(tag.get_absolute_url()) - else: - tag_list.append(tag) - - return HttpResponseRedirect(reverse('catalogue.views.tagged_object_list', - kwargs={'tags': '/'.join(tag.slug for tag in tag_list)} - )) + result = _tags_exact_matches(prefix, request.user) + + if len(result) > 1: + # multiple exact matches + return render_to_response('catalogue/search_multiple_hits.html', + {'tags':tag_list, 'prefix':prefix, 'results':((x, _get_result_link(x, tag_list), _get_result_type(x)) for x in result)}, + context_instance=RequestContext(request)) + + if not result: + # no exact matches + result = _tags_starting_with(prefix, request.user) + + if result: + return HttpResponseRedirect(_get_result_link(result[0], tag_list)) else: - return render_to_response('catalogue/search_no_hits.html', {'query':prefix, 'tags':tag_list}, + return render_to_response('catalogue/search_no_hits.html', {'tags':tag_list, 'prefix':prefix}, context_instance=RequestContext(request)) @@ -455,7 +500,7 @@ def register(request): @cache.never_cache def logout_then_redirect(request): auth.logout(request) - return HttpResponseRedirect(request.GET.get('next', '/')) + return HttpResponseRedirect(urlquote_plus(request.GET.get('next', '/'), safe='/?=')) diff --git a/deployment.py b/deployment.py index b156b9385..ab198801c 100644 --- a/deployment.py +++ b/deployment.py @@ -31,7 +31,7 @@ def update_application(): os.system("%s install -r %s" % (PIP, os.path.join(ROOT, 'etc', 'requirements.txt'))) print "done." -ROOT = os.path.dirname(os.path.abspath(__file__)) +ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) PYTHON = os.path.join(ROOT, 'pythonenv', 'bin', 'python') PIP = os.path.join(ROOT, 'pythonenv', 'bin', 'pip') diff --git a/wolnelektury.vhost.tmpl b/wolnelektury.vhost.tmpl index fbd21a9a1..6fac7562d 100644 --- a/wolnelektury.vhost.tmpl +++ b/wolnelektury.vhost.tmpl @@ -1,6 +1,5 @@ ServerName $DOMAIN - ServerAlias $DOMAIN_ALIASES ServerAdmin $ADMIN_EMAIL WSGIDaemonProcess $PROJECT_NAME user=$WSGI_USER group=$WSGI_USER processes=$WSGI_PROCESSES threads=$WSGI_THREADS display-name=%{GROUP} @@ -14,7 +13,6 @@ Alias /media $MEDIA_ROOT - Options Indexes, FollowLinks Order allow,deny Allow from all diff --git a/wolnelektury/context_processors.py b/wolnelektury/context_processors.py new file mode 100644 index 000000000..0cbf60513 --- /dev/null +++ b/wolnelektury/context_processors.py @@ -0,0 +1,6 @@ + +def extra_settings(request): + from django.conf import settings + return { + 'STATIC_URL': settings.STATIC_URL, + } diff --git a/wolnelektury/settings.py b/wolnelektury/settings.py index ef6887e20..888ea34e4 100644 --- a/wolnelektury/settings.py +++ b/wolnelektury/settings.py @@ -67,6 +67,7 @@ TEMPLATE_CONTEXT_PROCESSORS = [ 'django.core.context_processors.i18n', 'django.core.context_processors.media', 'django.core.context_processors.request', + 'wolnelektury.context_processors.extra_settings', ] MIDDLEWARE_CLASSES = [ @@ -96,7 +97,7 @@ INSTALLED_APPS = [ 'django.contrib.sites', 'django.contrib.admin', 'django.contrib.admindocs', - + # external 'south', 'sorl.thumbnail', diff --git a/wolnelektury/static/css/master.book.css b/wolnelektury/static/css/master.book.css index b0d354296..26a11c62c 100644 --- a/wolnelektury/static/css/master.book.css +++ b/wolnelektury/static/css/master.book.css @@ -194,10 +194,13 @@ blockquote { /* ============= */ /* = Numbering = */ /* ============= */ +.verse { + position:relative; +} .anchor { position: absolute; margin: -0.25em -0.5em; - left: 1em; + left: -3em; color: #777; font-size: 12px; width: 2em; @@ -317,3 +320,11 @@ em.person { font-variant: small-caps; } + +/* =================================== */ +/* = Hide some elements for printing = */ +/* =================================== */ + +@media print { + #menu {display: none;} +} diff --git a/wolnelektury/static/css/sponsors.css b/wolnelektury/static/css/sponsors.css index 9f6a9bb2c..f780972e2 100644 --- a/wolnelektury/static/css/sponsors.css +++ b/wolnelektury/static/css/sponsors.css @@ -5,4 +5,4 @@ .sponsors-sponsor-logo { float: left; -}c \ No newline at end of file +} \ No newline at end of file diff --git a/wolnelektury/static/js/catalogue.js b/wolnelektury/static/js/catalogue.js index b356183fa..d57f74339 100644 --- a/wolnelektury/static/js/catalogue.js +++ b/wolnelektury/static/js/catalogue.js @@ -1,4 +1,3 @@ -alert(LANGUAGE_CODE); var LOCALE_TEXTS = { "pl": { "DELETE_SHELF": "Czy na pewno usunąć półkę", @@ -43,8 +42,6 @@ var LOCALE_TEXTS = { "LOADING": "Translate me!", } } - -alert(LOCALE_TEXTS[LANGUAGE_CODE]['DELETE_SHELF']); var BANNER_TEXTS = [ 'Przekaż 1% żeby ukryć ten baner.', 'Jak dobrze wydać 1% swojego podatku? Poradnik dla opornych.', @@ -126,14 +123,16 @@ function serverTime() { function() { $(this).css({background: '#FFF'}); } ).click(function() { $(this).fadeOut(function() { - $(this).prev().fadeIn() + $(this).prev().fadeIn(); }); + return false; }) } }); $('.fragment-short-text').click(function() { $(this).fadeOut(function() { $(this).next().fadeIn() }); + return false; }).hover( function() { $(this).css({background: '#F3F3F3', cursor: 'pointer'}); }, function() { $(this).css({background: '#FFF'}); } diff --git a/wolnelektury/static/js/jquery.autocomplete.js b/wolnelektury/static/js/jquery.autocomplete.js index 7cdb359d5..4e425e8bd 100644 --- a/wolnelektury/static/js/jquery.autocomplete.js +++ b/wolnelektury/static/js/jquery.autocomplete.js @@ -430,8 +430,22 @@ $.Autocompleter.defaults = { width: 0, multiple: false, multipleSeparator: ", ", + regex_escape: function(term) { + term = term.replace(/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi, "\\$1"); + /* no polish diacritics; should be more locale-aware */ + term = term.replace(/a/g, '[aą]') + .replace(/c/g, '[cć]') + .replace(/e/g, '[eę]') + .replace(/l/g, '[lł]') + .replace(/n/g, '[nń]') + .replace(/o/g, '[oó]') + .replace(/s/g, '[sś]') + .replace(/z/g, '[zźż]'); + return term; + }, highlight: function(value, term) { - return value.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + term.replace(/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi, "\\$1") + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "$1"); + term = $.Autocompleter.defaults.regex_escape(term); + return value.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + term + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "$1"); }, scroll: true, scrollHeight: 180 @@ -447,7 +461,8 @@ $.Autocompleter.Cache = function(options) { s = s.toLowerCase(); var i = s.indexOf(sub); if (options.matchContains == "word"){ - i = s.toLowerCase().search("\\b" + sub.replace(/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi, "\\$1").toLowerCase()); + query = $.Autocompleter.defaults.regex_escape(sub.toLowerCase()); + i = s.toLowerCase().search("\\b" + query); } if (i == -1) return false; return i == 0 || options.matchContains; diff --git a/wolnelektury/templates/1percent.html b/wolnelektury/templates/1percent.html index e53caeefd..d7bbdc0aa 100644 --- a/wolnelektury/templates/1percent.html +++ b/wolnelektury/templates/1percent.html @@ -4,10 +4,10 @@ {% block title %}1% podatku na WolneLektury.pl{% endblock title %} {% block extrahead %} - - - - + + + + {% endblock extrahead %} {% block bodycontent %} @@ -15,11 +15,11 @@ @@ -41,7 +41,7 @@

Przy wypełnianiu formularza PIT w polu wniosek o przekazanie 1% podatku na rzecz OPP wpisz:

Fundacja Nowoczesna Polska
 KRS 0000070056
- + 1% dla OPP

Skorzystaj z programu ułatwiającego przygotowanie deklaracji podatkowej on-line.

diff --git a/wolnelektury/templates/404.html b/wolnelektury/templates/404.html index 288e050ed..ebf7d155b 100644 --- a/wolnelektury/templates/404.html +++ b/wolnelektury/templates/404.html @@ -6,12 +6,12 @@ 404 - {% trans "Site does not exist" %} - WolneLektury.pl - + - +

{% trans "Site does not exist" %}

{% trans "We are sorry, but this site does not exist. Please check if you entered correct address or go to "%} {% trans "main page" %}. diff --git a/wolnelektury/templates/500.html b/wolnelektury/templates/500.html index 412ea10b8..964b905b4 100644 --- a/wolnelektury/templates/500.html +++ b/wolnelektury/templates/500.html @@ -6,12 +6,12 @@ 500 - {% trans "Server error" %} WolneLektury.pl - + - +

{% trans "Server error" %}

{% trans "We are sorry for your inconvenience, but server error occured. We are working on fixing it as soon as possible. Meanwhile, please go to " %}{% trans "main page" %}. diff --git a/wolnelektury/templates/base.html b/wolnelektury/templates/base.html index 47d84d604..7ba33b9a5 100644 --- a/wolnelektury/templates/base.html +++ b/wolnelektury/templates/base.html @@ -6,7 +6,7 @@ {% block title %}WolneLektury.pl{% endblock %} - + {% compressed_css "all" %} {% compressed_js "jquery" %} @@ -15,10 +15,10 @@ {% endblock %} - +

{% block bodycontent %}
{% chunk "top-message" %} @@ -29,7 +29,7 @@