Search hints/javascript
authorMarcin Koziej <marcin.koziej@nowoczesnapolska.org.pl>
Tue, 27 Dec 2011 11:47:29 +0000 (12:47 +0100)
committerMarcin Koziej <marcin.koziej@nowoczesnapolska.org.pl>
Tue, 27 Dec 2011 11:47:29 +0000 (12:47 +0100)
apps/catalogue/models.py
apps/catalogue/tasks.py
apps/search/index.py
apps/search/views.py
wolnelektury/settings.py
wolnelektury/static/js/search.js [new file with mode: 0644]
wolnelektury/templates/base.html
wolnelektury/urls.py

index 4da82ef..e69d231 100644 (file)
@@ -24,7 +24,7 @@ from newtagging.models import TagBase, tags_updated
 from newtagging import managers
 from catalogue.fields import JSONField, OverwritingFileField
 from catalogue.utils import create_zip, split_tags
 from newtagging import managers
 from catalogue.fields import JSONField, OverwritingFileField
 from catalogue.utils import create_zip, split_tags
-from catalogue.tasks import touch_tag
+from catalogue.tasks import touch_tag, index_book
 from shutil import copy
 from glob import glob
 import re
 from shutil import copy
 from glob import glob
 import re
@@ -732,17 +732,15 @@ class Book(models.Model):
         return result.wait()
 
     def search_index(self, book_info=None):
         return result.wait()
 
     def search_index(self, book_info=None):
-        if settings.SEARCH_INDEX_PARALLEL:
-            if instance(settings.SEARCH_INDEX_PARALLEL, int):
-                idx = search.ReusableIndex(threads=4)
-            else:
-                idx = search.ReusableIndex()
+        if settings.CELERY_ALWAYS_EAGER:
+            idx = search.ReusableIndex()
         else:
             idx = search.Index()
             
         idx.open()
         try:
             idx.index_book(self, book_info)
         else:
             idx = search.Index()
             
         idx.open()
         try:
             idx.index_book(self, book_info)
+            idx.index_tags()
         finally:
             idx.close()
 
         finally:
             idx.close()
 
@@ -834,7 +832,7 @@ class Book(models.Model):
             book.build_mobi()
 
         if not settings.NO_SEARCH_INDEX and search_index:
             book.build_mobi()
 
         if not settings.NO_SEARCH_INDEX and search_index:
-            book.search_index(book_info)
+            index_book.delay(book.id, book_info)
 
         book_descendants = list(book.children.all())
         descendants_tags = set()
 
         book_descendants = list(book.children.all())
         descendants_tags = set()
index 5566fe1..86e84a5 100755 (executable)
@@ -4,7 +4,7 @@
 #
 from datetime import datetime
 from celery.task import task
 #
 from datetime import datetime
 from celery.task import task
-
+import catalogue.models
 
 @task
 def touch_tag(tag):
 
 @task
 def touch_tag(tag):
@@ -14,3 +14,8 @@ def touch_tag(tag):
     }
 
     type(tag).objects.filter(pk=tag.pk).update(**update_dict)
     }
 
     type(tag).objects.filter(pk=tag.pk).update(**update_dict)
+
+
+@task
+def index_book(book_id, book_info=None):
+    return catalogue.models.Book.objects.get(id=book_id).search_index(book_info)
index f4da66f..10069e4 100644 (file)
@@ -412,35 +412,23 @@ class ReusableIndex(Index):
     if you cannot rely on atexit, use ReusableIndex.close_reusable() yourself.
     """
     index = None
     if you cannot rely on atexit, use ReusableIndex.close_reusable() yourself.
     """
     index = None
-    pool = None
-    pool_jobs = None
 
     def open(self, analyzer=None, threads=4):
         if ReusableIndex.index is not None:
             self.index = ReusableIndex.index
         else:
             print("opening index")
 
     def open(self, analyzer=None, threads=4):
         if ReusableIndex.index is not None:
             self.index = ReusableIndex.index
         else:
             print("opening index")
-            ReusableIndex.pool = ThreadPool(threads, initializer=lambda: JVM.attachCurrentThread() )
-            ReusableIndex.pool_jobs = []
             Index.open(self, analyzer)
             ReusableIndex.index = self.index
             atexit.register(ReusableIndex.close_reusable)
 
             Index.open(self, analyzer)
             ReusableIndex.index = self.index
             atexit.register(ReusableIndex.close_reusable)
 
-    def index_book(self, *args, **kw):
-        job = ReusableIndex.pool.apply_async(log_exception_wrapper(Index.index_book), (self,) + args, kw)
-        ReusableIndex.pool_jobs.append(job)
+    def index_book(self, *args, **kw):
+        job = ReusableIndex.pool.apply_async(log_exception_wrapper(Index.index_book), (self,) + args, kw)
+        ReusableIndex.pool_jobs.append(job)
 
     @staticmethod
     def close_reusable():
         if ReusableIndex.index is not None:
 
     @staticmethod
     def close_reusable():
         if ReusableIndex.index is not None:
-            print("wait for indexing to finish")
-            for job in ReusableIndex.pool_jobs:
-                job.get()
-                sys.stdout.write('.')
-                sys.stdout.flush()
-            print("done.")
-            ReusableIndex.pool.close()
-
             ReusableIndex.index.optimize()
             ReusableIndex.index.close()
             ReusableIndex.index = None
             ReusableIndex.index.optimize()
             ReusableIndex.index.close()
             ReusableIndex.index = None
index fad5e6f..75cc16a 100644 (file)
@@ -5,6 +5,7 @@ from django.template import RequestContext
 from django.contrib.auth.decorators import login_required
 from django.views.decorators import cache
 from django.http import HttpResponse, HttpResponseRedirect, Http404, HttpResponsePermanentRedirect
 from django.contrib.auth.decorators import login_required
 from django.views.decorators import cache
 from django.http import HttpResponse, HttpResponseRedirect, Http404, HttpResponsePermanentRedirect
+from django.utils.translation import ugettext as _
 
 from catalogue.utils import get_random_hash
 from catalogue.models import Book, Tag, Fragment, TAG_CATEGORIES
 
 from catalogue.utils import get_random_hash
 from catalogue.models import Book, Tag, Fragment, TAG_CATEGORIES
@@ -50,7 +51,7 @@ def category_name(category):
 def hint(request):
     prefix = request.GET.get('term', '')
     if len(prefix) < 2:
 def hint(request):
     prefix = request.GET.get('term', '')
     if len(prefix) < 2:
-        return JSONResponse(dumps(None))
+        return JSONResponse([])
     JVM.attachCurrentThread()
     s = MultiSearch()
 
     JVM.attachCurrentThread()
     s = MultiSearch()
 
@@ -66,6 +67,8 @@ def hint(request):
     # jezeli tagi dot tylko ksiazki, to wazne zeby te nowe byly w tej samej ksiazce
     # jesli zas dotycza themes, to wazne, zeby byly w tym samym fragmencie.
 
     # jezeli tagi dot tylko ksiazki, to wazne zeby te nowe byly w tej samej ksiazce
     # jesli zas dotycza themes, to wazne, zeby byly w tym samym fragmencie.
 
+    # import pdb; pdb.set_trace()
+    
     tags = s.hint_tags(prefix)
     books = s.hint_books(prefix)
 
     tags = s.hint_tags(prefix)
     books = s.hint_books(prefix)
 
@@ -73,12 +76,12 @@ def hint(request):
 
     return JSONResponse(
         [{'label': t.name,
 
     return JSONResponse(
         [{'label': t.name,
-          'category': category_name(t.category),
+          'category': _(category_name(t.category)),
           'id': t.id,
           'url': t.get_absolute_url()}
           for t in tags] + \
           [{'label': b.title,
           'id': t.id,
           'url': t.get_absolute_url()}
           for t in tags] + \
           [{'label': b.title,
-            'category': category_name('book'),
+            'category': _(category_name('book')),
             'id': b.id,
             'url': b.get_absolute_url()}
             for b in books])
             'id': b.id,
             'url': b.get_absolute_url()}
             for b in books])
index 4184c4e..fe25729 100644 (file)
@@ -175,6 +175,8 @@ COMPRESS_CSS = {
             'css/book_box.css',
             'css/catalogue.css',
             'css/sponsors.css',
             'css/book_box.css',
             'css/catalogue.css',
             'css/sponsors.css',
+            
+            'css/ui-lightness/jquery-ui-1.8.16.custom.css',
         ],
         'output_filename': 'css/all.min?.css',
     },
         ],
         'output_filename': 'css/all.min?.css',
     },
@@ -199,11 +201,15 @@ COMPRESS_JS = {
             'js/jquery.countdown-es.js', 'js/jquery.countdown-lt.js',
             'js/jquery.countdown-ru.js', 'js/jquery.countdown-fr.js',
 
             'js/jquery.countdown-es.js', 'js/jquery.countdown-lt.js',
             'js/jquery.countdown-ru.js', 'js/jquery.countdown-fr.js',
 
+            'js/jquery-ui-1.8.16.custom.min.js',
+
             'js/locale.js',
             'js/dialogs.js',
             'js/sponsors.js',
             'js/pdcounter.js',
 
             'js/locale.js',
             'js/dialogs.js',
             'js/sponsors.js',
             'js/pdcounter.js',
 
+            'js/search.js',
+
             #~ 'js/jquery.autocomplete.js',
             #~ 'js/jquery.labelify.js', 'js/catalogue.js',
             ),
             #~ 'js/jquery.autocomplete.js',
             #~ 'js/jquery.labelify.js', 'js/catalogue.js',
             ),
diff --git a/wolnelektury/static/js/search.js b/wolnelektury/static/js/search.js
new file mode 100644 (file)
index 0000000..e58d372
--- /dev/null
@@ -0,0 +1,49 @@
+
+var __bind = function (self, fn) {
+    return function() { fn.apply(self, arguments); };
+};
+
+(function($){
+    $.widget("wl.search", {
+       options: {
+          minLength: 0,
+        },
+
+       _create: function() {
+           var opts = { 
+               minLength: this.options.minLength,
+               select: __bind(this, this.enter),
+               focus: function() { return false; },
+               source: this.element.data('source'),
+           };
+           this.element.autocomplete(opts).data("autocomplete")._renderItem = __bind(this, this.render_item);
+       },
+
+       enter: function(event, ui) {
+           if (ui.item.url != undefined) {
+               location.href = ui.item.url;
+           } else {
+               this.element.closest('form').submit();
+           }
+       },
+   
+       render_item: function (ul, item) {
+           return $("<li></li>").data('item.autocomplete', item)
+               .append('<a href="'+item.url+'">'+item.label+ ' ('+item.category+')</a>')
+               .appendTo(ul);
+       },
+
+       destroy: function() {
+
+       },
+       
+
+
+       });
+
+    $(function() {
+       $("#search input[name=q]").search();
+       
+    });
+
+})(jQuery);
index 534f5cf..8440959 100644 (file)
@@ -65,7 +65,7 @@
             <form id="search">
                 
                 <span id="search-field" class="grid-line">
             <form id="search">
                 
                 <span id="search-field" class="grid-line">
-                    <input title="np. Leśmian" name="q" autocomplete="off">
+                    <input title="np. Leśmian" name="q" autocomplete="off" data-source="/fullsearch/hint/">
                 </span><span id="search-button">
                     <button type='submit'><span class="mono">{% trans "Search" %}</span></button>
                 </span>
                 </span><span id="search-button">
                     <button type='submit'><span class="mono">{% trans "Search" %}</span></button>
                 </span>
index f7d5015..0cb3edd 100644 (file)
@@ -38,7 +38,7 @@ urlpatterns += patterns('',
     # API
     (r'^api/', include('api.urls')),
 
     # API
     (r'^api/', include('api.urls')),
 
-    url(r'^newsearch/', include('search.urls')),
+    url(r'^fullsearch/', include('search.urls')),
 
     # Static files
     url(r'^%s(?P<path>.*)$' % settings.MEDIA_URL[1:], 'django.views.static.serve',
 
     # Static files
     url(r'^%s(?P<path>.*)$' % settings.MEDIA_URL[1:], 'django.views.static.serve',