forked from DGNum/gestioCOF
Generic autocompletion view
This commit is contained in:
parent
30783d677b
commit
e7517195cd
20 changed files with 272 additions and 309 deletions
|
@ -1,5 +1,7 @@
|
|||
from django.contrib.auth import get_user_model
|
||||
from django.db.models import Q
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from shared import autocomplete
|
||||
|
||||
|
@ -14,12 +16,16 @@ class KfetAccountSearch(autocomplete.ModelSearch):
|
|||
"last_name",
|
||||
"profile__account_kfet__trigramme",
|
||||
]
|
||||
verbose_name = _("Comptes existants")
|
||||
|
||||
def get_queryset_filter(self, *args, **kwargs):
|
||||
qset_filter = super().get_queryset_filter(*args, **kwargs)
|
||||
qset_filter &= Q(profile__account_kfet__isnull=False)
|
||||
return qset_filter
|
||||
|
||||
def result_verbose_name(self, user):
|
||||
return "{} ({})".format(user, user.profile.account_kfet.trigramme)
|
||||
|
||||
def result_uuid(self, user):
|
||||
return user.username
|
||||
|
||||
|
@ -27,6 +33,7 @@ class KfetAccountSearch(autocomplete.ModelSearch):
|
|||
class COFMemberSearch(autocomplete.ModelSearch):
|
||||
model = User
|
||||
search_fields = ["username", "first_name", "last_name"]
|
||||
verbose_name = _("Membres du COF")
|
||||
|
||||
def get_queryset_filter(self, *args, **kwargs):
|
||||
qset_filter = super().get_queryset_filter(*args, **kwargs)
|
||||
|
@ -36,10 +43,14 @@ class COFMemberSearch(autocomplete.ModelSearch):
|
|||
def result_uuid(self, user):
|
||||
return user.username
|
||||
|
||||
def result_link(self, user):
|
||||
return reverse("kfet.account.create.fromuser", args=(user.username,))
|
||||
|
||||
|
||||
class OthersSearch(autocomplete.ModelSearch):
|
||||
model = User
|
||||
search_fields = ["username", "first_name", "last_name"]
|
||||
verbose_name = _("Non-membres du COF")
|
||||
|
||||
def get_queryset_filter(self, *args, **kwargs):
|
||||
qset_filter = super().get_queryset_filter(*args, **kwargs)
|
||||
|
@ -49,11 +60,25 @@ class OthersSearch(autocomplete.ModelSearch):
|
|||
def result_uuid(self, user):
|
||||
return user.username
|
||||
|
||||
def result_link(self, user):
|
||||
return reverse("kfet.account.create.fromuser", args=(user.username,))
|
||||
|
||||
|
||||
class KfetLDAPSearch(autocomplete.LDAPSearch):
|
||||
def result_link(self, clipper):
|
||||
return reverse(
|
||||
"kfet.account.create.fromclipper", args=(clipper.clipper, clipper.fullname)
|
||||
)
|
||||
|
||||
|
||||
class KfetAutocomplete(autocomplete.Compose):
|
||||
search_units = [
|
||||
("kfet", KfetAccountSearch()),
|
||||
("users_cof", COFMemberSearch()),
|
||||
("users_notcof", OthersSearch()),
|
||||
("clippers", autocomplete.LDAPSearch()),
|
||||
("clippers", KfetLDAPSearch()),
|
||||
]
|
||||
|
||||
|
||||
class KfetAccountOnlyAutocomplete(autocomplete.Compose):
|
||||
search_units = [("kfet", KfetAccountSearch())]
|
||||
|
|
|
@ -159,7 +159,7 @@
|
|||
background:rgba(255,255,255,0.9);
|
||||
}
|
||||
|
||||
#search_results ul li.user_category {
|
||||
#search_results ul li.autocomplete-header {
|
||||
font-weight:bold;
|
||||
background:#c8102e;
|
||||
color:#fff;
|
||||
|
@ -178,7 +178,7 @@
|
|||
text-decoration:none;
|
||||
}
|
||||
|
||||
#search_results ul li span.text {
|
||||
#search_results ul li span.autocomplete-item {
|
||||
display:block;
|
||||
padding:5px 20px;
|
||||
}
|
||||
|
|
|
@ -1,50 +0,0 @@
|
|||
{% load kfet_tags %}
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<a href="{% url "kfet.account.create.empty" %}">
|
||||
Créer un compte
|
||||
</a>
|
||||
</li>
|
||||
{% if kfet %}
|
||||
<li class="user_category"><span class="text">Comptes existants</span></li>
|
||||
{% for user in kfet %}
|
||||
<li><span class="text">{{ user.account_kfet.account }} [{{ user|highlight_user:q }}]</span></li>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if users_cof %}
|
||||
<li class="user_category"><span class="text">Membres du COF</span></li>
|
||||
{% for user in users_cof %}
|
||||
<li>
|
||||
<a href="{% url "kfet.account.create.fromuser" user.username %}">
|
||||
{{ user|highlight_user:q }}
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if users_notcof %}
|
||||
<li class="user_category"><span class="text">Non-membres du COF</span></li>
|
||||
{% for user in users_notcof %}
|
||||
<li>
|
||||
<a href="{% url "kfet.account.create.fromuser" user.username %}">
|
||||
{{ user|highlight_user:q }}
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if clippers %}
|
||||
<li class="user_category"><span class="text">Utilisateurs clipper</span></li>
|
||||
{% for clipper in clippers %}
|
||||
<li>
|
||||
<a href="{% url "kfet.account.create.fromclipper" clipper.clipper clipper.fullname%}">
|
||||
{{ clipper|highlight_clipper:q }}
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if not q %}
|
||||
<li class="user_category"><span class="text">Pas de recherche, pas de résultats !</span></li>
|
||||
{% elif not options %}
|
||||
<li class="user_category"><span class="text">Aucune correspondance trouvée :-(</span></li>
|
||||
{% endif %}
|
||||
</ul>
|
|
@ -1,14 +0,0 @@
|
|||
{% load kfet_tags %}
|
||||
|
||||
<ul>
|
||||
{% if accounts %}
|
||||
{% for trigramme, user in accounts %}
|
||||
<li class='choice'>{{ user|highlight_text:q }} (<span class="trigramme">{{ trigramme }}</span>)</li>
|
||||
{% endfor %}
|
||||
{% elif not q %}
|
||||
<li class="user_category"><span class="text">Pas de recherche, pas de résultats !</span></li>
|
||||
{% else %}
|
||||
<li class="user_category"><span class="text">Aucune correspondance trouvée :-(</span></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
|
|
@ -1,8 +1,4 @@
|
|||
import re
|
||||
|
||||
from django import template
|
||||
from django.utils.html import escape
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from ..utils import to_ukf
|
||||
|
||||
|
@ -11,40 +7,14 @@ register = template.Library()
|
|||
register.filter("ukf", to_ukf)
|
||||
|
||||
|
||||
@register.filter()
|
||||
def highlight_text(text, q):
|
||||
q2 = "|".join(re.escape(word) for word in q.split())
|
||||
pattern = re.compile(r"(?P<filter>%s)" % q2, re.IGNORECASE)
|
||||
regex = r"<span class='highlight_autocomplete'>\g<filter></span>"
|
||||
return mark_safe(re.sub(pattern, regex, escape(text)))
|
||||
|
||||
|
||||
@register.filter(is_safe=True)
|
||||
def highlight_user(user, q):
|
||||
if user.first_name and user.last_name:
|
||||
text = "%s %s (%s)" % (user.first_name, user.last_name, user.username)
|
||||
else:
|
||||
text = user.username
|
||||
return highlight_text(text, q)
|
||||
|
||||
|
||||
@register.filter(is_safe=True)
|
||||
def highlight_clipper(clipper, q):
|
||||
if clipper.fullname:
|
||||
text = "%s (%s)" % (clipper.fullname, clipper.clipper)
|
||||
else:
|
||||
text = clipper.clipper
|
||||
return highlight_text(text, q)
|
||||
|
||||
|
||||
@register.filter()
|
||||
def widget_type(field):
|
||||
return field.field.widget.__class__.__name__
|
||||
|
||||
|
||||
@register.filter()
|
||||
def slice(l, start, end=None):
|
||||
def slice(t, start, end=None):
|
||||
if end is None:
|
||||
end = start
|
||||
start = 0
|
||||
return l[start:end]
|
||||
return t[start:end]
|
||||
|
|
|
@ -181,9 +181,15 @@ class AccountCreateAutocompleteViewTests(ViewTestCaseMixin, TestCase):
|
|||
def test_ok(self):
|
||||
r = self.client.get(self.url, {"q": "first"})
|
||||
self.assertEqual(r.status_code, 200)
|
||||
self.assertEqual(len(r.context["users_notcof"]), 0)
|
||||
self.assertEqual(len(r.context["users_cof"]), 0)
|
||||
self.assertSetEqual(set(r.context["kfet"]), set([self.users["user"]]))
|
||||
self.assertEqual(len(r.context["results"]), 1)
|
||||
(res,) = r.context["results"]
|
||||
self.assertEqual(res.name, "kfet")
|
||||
|
||||
u = self.users["user"]
|
||||
self.assertSetEqual(
|
||||
{e.verbose_name for e in res.entries},
|
||||
{"{} ({})".format(u, u.profile.account_kfet.trigramme)},
|
||||
)
|
||||
|
||||
|
||||
class AccountSearchViewTests(ViewTestCaseMixin, TestCase):
|
||||
|
@ -196,7 +202,12 @@ class AccountSearchViewTests(ViewTestCaseMixin, TestCase):
|
|||
def test_ok(self):
|
||||
r = self.client.get(self.url, {"q": "first"})
|
||||
self.assertEqual(r.status_code, 200)
|
||||
self.assertSetEqual(set(r.context["accounts"]), set([("000", "first last")]))
|
||||
|
||||
u = self.users["user"]
|
||||
self.assertSetEqual(
|
||||
{e.verbose_name for e in r.context["results"][0].entries},
|
||||
{"{} ({})".format(u, u.profile.account_kfet.trigramme)},
|
||||
)
|
||||
|
||||
|
||||
class AccountReadViewTests(ViewTestCaseMixin, TestCase):
|
||||
|
|
|
@ -27,7 +27,7 @@ from django.views.generic.edit import CreateView, DeleteView, UpdateView
|
|||
from gestioncof.models import CofProfile
|
||||
from kfet import KFET_DELETED_TRIGRAMME, consumers
|
||||
from kfet.auth.decorators import kfet_password_auth
|
||||
from kfet.autocomplete import KfetAccountSearch, KfetAutocomplete
|
||||
from kfet.autocomplete import KfetAccountOnlyAutocomplete, KfetAutocomplete
|
||||
from kfet.config import kfet_config
|
||||
from kfet.decorators import teamkfet_required
|
||||
from kfet.forms import (
|
||||
|
@ -79,6 +79,7 @@ from kfet.models import (
|
|||
TransferGroup,
|
||||
)
|
||||
from kfet.statistic import DayScale, MonthScale, ScaleMixin, WeekScale, scale_url_params
|
||||
from shared.views import AutocompleteView
|
||||
|
||||
from .auth import KFET_GENERIC_TRIGRAMME
|
||||
from .auth.views import ( # noqa
|
||||
|
@ -2594,34 +2595,11 @@ class ArticleStatSales(ScaleMixin, JSONDetailView):
|
|||
# ---
|
||||
|
||||
|
||||
class AccountCreateAutocompleteView(PermissionRequiredMixin, TemplateView):
|
||||
template_name = "kfet/account_create_autocomplete.html"
|
||||
class AccountCreateAutocompleteView(PermissionRequiredMixin, AutocompleteView):
|
||||
permission_required = "kfet.is_team"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
ctx = super().get_context_data(**kwargs)
|
||||
if "q" not in self.request.GET:
|
||||
raise Http404
|
||||
q = self.request.GET["q"]
|
||||
ctx["q"] = q
|
||||
results = KfetAutocomplete().search(q.split())
|
||||
ctx["options"] = sum((len(res) for res in results.values()))
|
||||
ctx.update(results)
|
||||
return ctx
|
||||
search_composer = KfetAutocomplete()
|
||||
|
||||
|
||||
class AccountSearchAutocompleteView(PermissionRequiredMixin, TemplateView):
|
||||
template_name = "kfet/account_search_autocomplete.html"
|
||||
class AccountSearchAutocompleteView(PermissionRequiredMixin, AutocompleteView):
|
||||
permission_required = "kfet.is_team"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
ctx = super().get_context_data(**kwargs)
|
||||
if "q" not in self.request.GET:
|
||||
raise Http404
|
||||
q = self.request.GET["q"]
|
||||
ctx["q"] = q
|
||||
ctx["accounts"] = [
|
||||
(user.profile.account_kfet.trigramme, user.get_full_name())
|
||||
for user in KfetAccountSearch().search(q.split())
|
||||
]
|
||||
return ctx
|
||||
search_composer = KfetAccountOnlyAutocomplete()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue