Przeglądaj źródła

Make select2 search bars case insensitive

omassot 6 lat temu
rodzic
commit
47b06cdf8b
5 zmienionych plików z 49 dodań i 16 usunięć
  1. 0 1
      main/forms.py
  2. 26 1
      main/models.py
  3. 20 1
      main/static/js/custom.js
  4. 1 5
      main/templates/story_form.html
  5. 2 8
      main/views.py

+ 0 - 1
main/forms.py

@@ -48,7 +48,6 @@ class StoryForm(forms.ModelForm):
     epic = ChoiceField(choices=[(epic.id, epic.name) for epic in Epic.objects.filter(closed=False).order_by('-value')],
                        widget=forms.Select(attrs={'class':'filtered-dropdown'}))
 
-    
     class Meta:
         model = Story
         widgets = {'author': forms.HiddenInput()}

+ 26 - 1
main/models.py

@@ -11,6 +11,9 @@ from django.db import models, connection
 from django.db.models.aggregates import Sum
 from martor.models import MartorField
 
+def norm(s):
+    return s.lower().replace('é', 'e').replace('è', 'e').replace('ê', 'e').replace('à', 'a').replace('â', 'a').replace('ç', 'c').replace('ô', 'o');
+
 class Member(models.Model):
     user = models.OneToOneField(User, on_delete=models.CASCADE)
     trigram = models.CharField(max_length=5)
@@ -123,6 +126,12 @@ class Epic(BaseModel):
     def reopen(self):
         self.closed = False
         self.save()
+    
+    @classmethod
+    def search(cls, qstr):
+        qstr = norm(qstr)
+        dataset = cls.objects.order_by("-updated")
+        return [item for item in dataset if qstr in norm(item.name)]
         
 class Sprint(BaseModel):
     class Meta:
@@ -235,7 +244,23 @@ class Story(BaseModel):
     
     def __str__(self):
         return self.name
-                
+    
+    @property
+    def normedname(self):
+        return self.name.lower().replace('é', 'e') \
+                                .replace('è', 'e') \
+                                .replace('ê', 'e') \
+                                .replace('à', 'a') \
+                                .replace('â', 'a') \
+                                .replace('ç', 'c') \
+                                .replace('ô', 'o');
+    
+    @classmethod
+    def search(cls, qstr):
+        qstr = norm(qstr)
+        dataset = cls.objects.order_by("-updated")
+        return [item for item in dataset if qstr in norm(item.name)]
+        
     def running(self):
         for sprint in self.sprints.all():
             if sprint.running():

+ 20 - 1
main/static/js/custom.js

@@ -22,10 +22,29 @@ $(document).ready( function () {
 		}
 	});
 	
+	function norm(s) {
+		return s.toLowerCase().replace(/[éèê]/g, 'e').replace(/[àâ]/g, 'a').replace(/ç/g, 'c').replace(/ô/g, 'o');
+	}
+	
+	function custom_search2_match(params, data) {
+		// https://select2.org/searching#customizing-how-results-are-matched
+	    if ($.trim(params.term) === '') {
+	      return data;
+	    }
+	    if (typeof data.text === 'undefined') {
+	      return null;
+	    }
+	    if (norm(data.text).indexOf(norm(params.term)) > -1) {
+	      return data;
+	    }
+	    return null;
+	}
+	
 	$('.filtered-dropdown').select2({
 		  theme: 'bootstrap',
 		  placeholder: 'Rechercher...',
-		  minimumInputLength: 1,
+		  minimumInputLength: 0,
+		  matcher: custom_search2_match,
 		  language: {
 	    	  inputTooShort: function () { return "Veuillez saisir votre recherche..."; },
 	    	  errorLoading: function () { return "Erreur de chargement"; },

+ 1 - 5
main/templates/story_form.html

@@ -33,15 +33,11 @@
 		{{ form.non_field_errors }}
     	{{ form.author }}
 
-		{% if not form.instance.epic %}
-		<p>
+		<p {% if form.instance.epic_id %}class="hidden"{% endif %}>
 		    {{ form.epic.errors }}
 		    {{ form.epic.label_tag }}
 		    {{ form.epic }}
 		</p>
-		{% else %}
-			{{ form.epic.as_hidden }}
-		{% endif %}
 		
 		<p>
 		    {{ form.name.errors }}

+ 2 - 8
main/views.py

@@ -222,7 +222,7 @@ def story_create(request, epic_id=None):
     else:
         story = Story()
         if epic_id is not None:
-            story.epic = get_object_or_404(Epic, id=epic_id)           
+            story.epic = get_object_or_404(Epic, id=epic_id)
         story.author = User.objects.get(username=request.user)
         form = StoryForm(instance=story)
         
@@ -471,13 +471,7 @@ def search_api(request):
     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.search(qstr) + Story.search(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]