Browse Source

Dropdown list for search-bar (#5)

omassot 6 years ago
parent
commit
f071833019
5 changed files with 48 additions and 25 deletions
  1. 22 0
      main/static/js/custom.js
  2. 3 0
      main/static/js/select2-fr.min.js
  3. 3 2
      main/templates/_layout.html
  4. 1 1
      main/urls.py
  5. 19 22
      main/views.py

+ 22 - 0
main/static/js/custom.js

@@ -22,6 +22,28 @@ $(document).ready( function () {
 		}
 	});
 	
+	$('#search-bar').select2({
+		  placeholder: 'Rechercher...',
+		  language: "fr",
+		  minimumInputLength: 2,
+		  ajax: {
+		    url: '/search/',
+		    dataType: 'json',
+		    cache: true,
+//		    delay: 100
+		  },
+//	      closeOnSelect: false,
+	      width : '220px',
+	      templateResult: function (state) { return $('<a href="' + state.id + '">' + state.text + '</a>'); },
+	      language: {
+	    	  inputTooShort: function () { return "Veuillez saisir votre recherche..."; },
+	    	  errorLoading: function () { return "Erreur de chargement"; },
+	    	  searching: function () { return "Recherche en cours…"; },
+	    	  noResults: function () { return "Aucun résultat"; },
+	    	  loadingMore: function () { return "Chargement de résultats supplémentaires…"; }
+	      }
+	});
+	
 	$('#stories').on('change', 'select[data-filter]', function() {
 		
 		var filters = [];

+ 3 - 0
main/static/js/select2-fr.min.js

@@ -0,0 +1,3 @@
+/*! Select2 4.0.7 | https://github.com/select2/select2/blob/master/LICENSE.md */
+
+(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define("select2/i18n/fr",[],function(){return{errorLoading:function(){return"Les résultats ne peuvent pas être chargés."},inputTooLong:function(e){var t=e.input.length-e.maximum;return"Supprimez "+t+" caractère"+(t>1?"s":"")},inputTooShort:function(e){var t=e.minimum-e.input.length;return"Saisissez au moins "+t+" caractère"+(t>1?"s":"")},loadingMore:function(){return"Chargement de résultats supplémentaires…"},maximumSelected:function(e){return"Vous pouvez seulement sélectionner "+e.maximum+" élément"+(e.maximum>1?"s":"")},noResults:function(){return"Aucun résultat trouvé"},searching:function(){return"Recherche en cours…"},removeAllItems:function(){return"Supprimer tous les articles"}}}),{define:e.define,require:e.require}})();

+ 3 - 2
main/templates/_layout.html

@@ -62,10 +62,11 @@
 			
 	        <nav class="right">
 	        	{% if request.user.is_authenticated %}
-	        	    <form id="search-bar" action="{% url 'search' %}" method="get" accept-charset="utf-8">
+<!-- 	        	    <form id="search-bar" action="{% url 'search' %}" method="get" accept-charset="utf-8">
 	        	    	<i class="fa fa-search"></i>
 				    	<input name="q" type="text" placeholder="Rechercher...">
-				    </form>
+				    </form> -->
+				    <select id="search-bar"></select>
 	        		
 	        		<div id="notif-panel" class="dropdown">
 	        			<a href="#" id="notif-show-btn">

+ 1 - 1
main/urls.py

@@ -48,7 +48,7 @@ urlpatterns = [
     path('comment-post/', views.comment_post, name='comment_post'),
     path('comment-edit/<int:comment_id>/', views.comment_edit, name='comment_edit'),
     path('comment-del/<int:comment_id>/', views.comment_del, name='comment_del'),
-    path('search/', views.search, name='search'),
+    path('search/', views.search_api, name='search'),
     path('notif/seen/<int:notif_id>/', views.notif_seen, name='notif_seen'),
     path('notif/allseen/', views.notif_all_seen, name='notif_all_seen'),
     path('upload/', views.md_upload_file, name='md_upload_file'),

+ 19 - 22
main/views.py

@@ -14,6 +14,7 @@ from django.db.models.aggregates import Sum
 from django.http.response import HttpResponse
 from django.shortcuts import render, get_object_or_404, redirect
 from django.urls.base import reverse
+from django.utils import datastructures
 from martor.utils import LazyEncoder
 from notifications.models import Notification
 from notifications.signals import notify
@@ -464,30 +465,26 @@ def comment_del(request, comment_id):
     return redirect(request.META['HTTP_REFERER'].split("#")[0] + "#a-comment-section")
 
 @login_required
-def search(request):
-    qstr = request.GET["q"]
-    
-    results = []
-    results += Epic.objects.filter(name__icontains=qstr)
-    results += Story.objects.filter(name__icontains=qstr)
+def search_api(request):
+    try:
+        qstr = request.GET["q"]
+    except datastructures.MultiValueDictKeyError:
+        qstr = ""
+    
+    results = set()
+    results |= set(Epic.objects.filter(name__icontains=qstr).order_by("-updated"))
+    results |= set(Story.objects.filter(name__icontains=qstr).order_by("-updated"))
+     
+    results |= set(Epic.objects.filter(description__icontains=qstr).order_by("-updated"))
+    results |= set(Story.objects.filter(description__icontains=qstr).order_by("-updated"))
     
-    results += Epic.objects.filter(description__icontains=qstr)
-    results += Story.objects.filter(description__icontains=qstr)
+    fmt_results = [{"id": reverse(f"{r.model_name()}_details", args=[r.id]), 
+                     "text": f"{r.model_name().title()}: {r.name}"} 
+                    for r in results]
     
-    if len(results) == 1:
-        r = results[0]
-        if isinstance(r, Epic):
-            return redirect("epic_details", r.id)
-        else:
-            return redirect("story_details", r.id)
-    else:
-        
-        paginator = Paginator(results, 10)
-        page = request.GET.get('page')
-        results = paginator.get_page(page)
-        
-        return render(request, 'search_results.html', {'results': results, 'pages': range(1, paginator.num_pages + 1)})
-
+    return HttpResponse(json.dumps({"results": fmt_results,
+            "pagination": { "more": True }
+            }))
 
 # notifications