diff --git a/kfet/autocomplete.py b/kfet/autocomplete.py index 2a24a51e..896eff6e 100644 --- a/kfet/autocomplete.py +++ b/kfet/autocomplete.py @@ -1,9 +1,5 @@ # -*- coding: utf-8 -*- -from __future__ import (absolute_import, division, - print_function, unicode_literals) -from builtins import * - from django.shortcuts import render from django.http import Http404 from django.db.models import Q @@ -11,6 +7,7 @@ from gestioncof.models import User, Clipper from kfet.decorators import teamkfet_required from kfet.models import Account + @teamkfet_required def account_create(request): if "q" not in request.GET: @@ -25,48 +22,48 @@ def account_create(request): queries = {} search_words = q.split() - queries['kfet'] = Account.objects - queries['users_cof'] = User.objects.filter(Q(profile__is_cof = True)) - queries['users_notcof'] = User.objects.filter(Q(profile__is_cof = False)) - queries['clippers'] = Clipper.objects + queries['kfet'] = Account.objects + queries['users_cof'] = User.objects.filter(Q(profile__is_cof=True)) + queries['users_notcof'] = User.objects.filter(Q(profile__is_cof=False)) + queries['clippers'] = Clipper.objects for word in search_words: queries['kfet'] = queries['kfet'].filter( - Q(cofprofile__user__username__icontains = word) - | Q(cofprofile__user__first_name__icontains = word) - | Q(cofprofile__user__last_name__icontains = word) + Q(cofprofile__user__username__icontains=word) | + Q(cofprofile__user__first_name__icontains=word) | + Q(cofprofile__user__last_name__icontains=word) ) queries['users_cof'] = queries['users_cof'].filter( - Q(username__icontains = word) - | Q(first_name__icontains = word) - | Q(last_name__icontains = word) + Q(username__icontains=word) | + Q(first_name__icontains=word) | + Q(last_name__icontains=word) ) queries['users_notcof'] = queries['users_notcof'].filter( - Q(username__icontains = word) - | Q(first_name__icontains = word) - | Q(last_name__icontains = word) + Q(username__icontains=word) | + Q(first_name__icontains=word) | + Q(last_name__icontains=word) ) - queries['clippers'] = queries['clippers'].filter( - Q(username__icontains = word) - | Q(fullname__icontains = word) + queries['clippers'] = queries['clippers'].filter( + Q(username__icontains=word) | + Q(fullname__icontains=word) ) queries['kfet'] = queries['kfet'].distinct() - usernames = list( \ + usernames = list( queries['kfet'].values_list('cofprofile__user__username', flat=True)) - queries['kfet'] = [ (account, account.cofprofile.user) \ - for account in queries['kfet'] ] + queries['kfet'] = [(account, account.cofprofile.user) + for account in queries['kfet']] - queries['users_cof'] = \ + queries['users_cof'] = \ queries['users_cof'].exclude(username__in=usernames).distinct() - queries['users_notcof'] = \ + queries['users_notcof'] = \ queries['users_notcof'].exclude(username__in=usernames).distinct() - usernames += list( \ + usernames += list( queries['users_cof'].values_list('username', flat=True)) - usernames += list( \ + usernames += list( queries['users_notcof'].values_list('username', flat=True)) queries['clippers'] = \ @@ -80,3 +77,25 @@ def account_create(request): data['options'] = options return render(request, "kfet/account_create_autocomplete.html", data) + + +def account_search(request): + if "q" not in request.GET: + raise Http404 + q = request.GET.get("q") + words = q.split() + + data = {'q': q} + + for word in words: + query = Account.objects.filter( + Q(cofprofile__user__username__icontains=word) | + Q(cofprofile__user__first_name__icontains=word) | + Q(cofprofile__user__last_name__icontains=word) + ).distinct() + + query = [(account.trigramme, account.cofprofile.user.get_full_name()) + for account in query] + + data['accounts'] = query + return render(request, 'kfet/account_search_autocomplete.html', data) diff --git a/kfet/static/kfet/css/jconfirm-kfet.css b/kfet/static/kfet/css/jconfirm-kfet.css index 4269fbcc..0bd53ab7 100644 --- a/kfet/static/kfet/css/jconfirm-kfet.css +++ b/kfet/static/kfet/css/jconfirm-kfet.css @@ -83,3 +83,24 @@ padding-right: 50px; padding-left: 50px; } + +/* Account autocomplete window */ + +#account_results ul { + list-style-type:none; + background:rgba(255,255,255,0.9); + padding:0; +} + +#account_results li { + display:block; + padding:5px 20px; + height:100%; + width:100%; +} + +#account_results .hilight { + background:rgba(200,16,46,0.9); + color:#fff; + text-decoration:none; +} diff --git a/kfet/templates/kfet/account_create_autocomplete.html b/kfet/templates/kfet/account_create_autocomplete.html index 1185c3a8..1a869c86 100644 --- a/kfet/templates/kfet/account_create_autocomplete.html +++ b/kfet/templates/kfet/account_create_autocomplete.html @@ -7,7 +7,7 @@ {% if kfet %} -
  • Comptes existant
  • +
  • Comptes existants
  • {% for account, user in kfet %}
  • {{ account }} [{{ user|highlight_user:q }}]
  • {% endfor %} diff --git a/kfet/templates/kfet/account_search_autocomplete.html b/kfet/templates/kfet/account_search_autocomplete.html new file mode 100644 index 00000000..e18eb1eb --- /dev/null +++ b/kfet/templates/kfet/account_search_autocomplete.html @@ -0,0 +1,14 @@ +{% load kfet_tags %} + + + diff --git a/kfet/templates/kfet/kpsul.html b/kfet/templates/kfet/kpsul.html index 7c0437fa..70cf4ba9 100644 --- a/kfet/templates/kfet/kpsul.html +++ b/kfet/templates/kfet/kpsul.html @@ -4,6 +4,7 @@ {% block extra_head %} + @@ -260,12 +261,56 @@ $(document).ready(function() { buttons += ''; } else { var url_base = '{% url 'kfet.account' %}' - buttons += ''; + buttons += ''; } } account_container.find('.buttons').html(buttons); } + // Search for an account + function searchAccount() { + var content = '
    ' ; + $.dialog({ + title: 'Recherche de compte', + content: content, + backgroundDismiss: true, + animation: 'top', + closeAnimation: 'bottom', + keyboardEnabled: true, + onOpen: function() { + var that=this ; + $('input#search_autocomplete').yourlabsAutocomplete({ + url: '{% url "kfet.account.search.autocomplete" %}', + minimumCharacters: 2, + id: 'search_autocomplete', + choiceSelector: '.choice', + placeholder: "Chercher un utilisateur K-Fêt", + box: $("#account_results"), + }); + $('input#search_autocomplete').bind( + 'selectChoice', + function(e, choice, autocomplete) { + autocomplete.hide() ; + triInput.val(choice.find('.trigramme').text()) ; + triInput.trigger('input') ; + that.close() ; + }); + } + }); + } + + account_container.on('click', '.search', function () { + searchAccount() ; + }) ; + + account_container.on('keydown', function(e) { + if (e.which == 70 && e.ctrlKey) { + // Ctrl + F : universal search shortcut + searchAccount() ; + e.preventDefault() ; + } + }); + // Clear data function resetAccountData() { account_data = account_data_default; diff --git a/kfet/templatetags/kfet_tags.py b/kfet/templatetags/kfet_tags.py index 66152dfe..59840b27 100644 --- a/kfet/templatetags/kfet_tags.py +++ b/kfet/templatetags/kfet_tags.py @@ -1,23 +1,24 @@ # -*- coding: utf-8 -*- -from __future__ import (absolute_import, division, - print_function, unicode_literals) -from builtins import * - from django import template from django.utils.html import escape from django.utils.safestring import mark_safe -from django.core.cache import cache from kfet.models import Settings from math import floor import re register = template.Library() + +@register.filter() def highlight_text(text, q): q2 = "|".join(q.split()) pattern = re.compile(r"(?P%s)" % q2, re.IGNORECASE) - return mark_safe(re.sub(pattern, r"\g", text)) + return mark_safe( + re.sub(pattern, + r"\g", + escape(text))) + @register.filter(is_safe=True) def highlight_user(user, q): @@ -25,7 +26,8 @@ def highlight_user(user, q): text = "%s %s (%s)" % (user.first_name, user.last_name, user.username) else: text = user.username - return highlight_text(escape(text), q) + return highlight_text(text, q) + @register.filter(is_safe=True) def highlight_clipper(clipper, q): @@ -33,7 +35,8 @@ def highlight_clipper(clipper, q): text = "%s (%s)" % (clipper.fullname, clipper.username) else: text = clipper.username - return highlight_text(escape(text), q) + return highlight_text(text, q) + @register.filter() def ukf(balance, is_cof): diff --git a/kfet/urls.py b/kfet/urls.py index d0605548..d98d075d 100644 --- a/kfet/urls.py +++ b/kfet/urls.py @@ -1,9 +1,5 @@ # -*- coding: utf-8 -*- -from __future__ import (absolute_import, division, - print_function, unicode_literals) -from builtins import * - from django.conf.urls import url from django.contrib.auth.decorators import permission_required from kfet import views @@ -12,11 +8,11 @@ from kfet.decorators import teamkfet_required urlpatterns = [ url(r'^$', views.home, - name = 'kfet.home'), + name='kfet.home'), url(r'^login/genericteam$', views.login_genericteam, - name = 'kfet.login.genericteam'), + name='kfet.login.genericteam'), url(r'^history$', views.history, - name = 'kfet.history'), + name='kfet.history'), # ----- # Account urls @@ -24,45 +20,53 @@ urlpatterns = [ # Account - General url(r'^accounts/$', views.account, - name = 'kfet.account'), + name='kfet.account'), url(r'^accounts/is_validandfree$', views.account_is_validandfree_ajax, - name = 'kfet.account.is_validandfree.ajax'), + name='kfet.account.is_validandfree.ajax'), # Account - Create url(r'^accounts/new$', views.account_create, - name = 'kfet.account.create'), + name='kfet.account.create'), url(r'^accounts/new_special$', views.account_create_special, - name = 'kfet.account.create_special'), + name='kfet.account.create_special'), url(r'^accounts/new/user/(?P.+)$', views.account_create_ajax, - name = 'kfet.account.create.fromuser'), - url(r'^accounts/new/clipper/(?P.+)$', views.account_create_ajax, - name = 'kfet.account.create.fromclipper'), + name='kfet.account.create.fromuser'), + url(r'^accounts/new/clipper/(?P.+)$', + views.account_create_ajax, + name='kfet.account.create.fromclipper'), url(r'^accounts/new/empty$', views.account_create_ajax, - name = 'kfet.account.create.empty'), + name='kfet.account.create.empty'), url(r'^autocomplete/account_new$', autocomplete.account_create, - name = 'kfet.account.create.autocomplete'), + name='kfet.account.create.autocomplete'), + + # Account - Search + url(r'^autocomplete/account_search$', autocomplete.account_search, + name='kfet.account.search.autocomplete'), # Account - Read url(r'^accounts/(?P.{3})$', views.account_read, - name = 'kfet.account.read'), + name='kfet.account.read'), # Account - Update url(r'^accounts/(?P.{3})/edit$', views.account_update, - name = 'kfet.account.update'), + name='kfet.account.update'), # Account - Groups url(r'^accounts/groups$', views.account_group, - name = 'kfet.account.group'), + name='kfet.account.group'), url(r'^accounts/groups/new$', - permission_required('kfet.manage_perms')(views.AccountGroupCreate.as_view()), - name = 'kfet.account.group.create'), + permission_required('kfet.manage_perms') + (views.AccountGroupCreate.as_view()), + name='kfet.account.group.create'), url(r'^accounts/groups/(?P\d+)/edit$', - permission_required('kfet.manage_perms')(views.AccountGroupUpdate.as_view()), - name = 'kfet.account.group.update'), + permission_required('kfet.manage_perms') + (views.AccountGroupUpdate.as_view()), + name='kfet.account.group.update'), url(r'^accounts/negatives$', - permission_required('kfet.view_negs')(views.AccountNegativeList.as_view()), - name = 'kfet.account.negative'), + permission_required('kfet.view_negs') + (views.AccountNegativeList.as_view()), + name='kfet.account.negative'), # Account - Statistics url('^accounts/(?P.{3})/stat/last/$', @@ -95,34 +99,36 @@ urlpatterns = [ # Checkout - General url('^checkouts/$', teamkfet_required(views.CheckoutList.as_view()), - name = 'kfet.checkout'), + name='kfet.checkout'), # Checkout - Create url('^checkouts/new$', teamkfet_required(views.CheckoutCreate.as_view()), - name = 'kfet.checkout.create'), + name='kfet.checkout.create'), # Checkout - Read url('^checkouts/(?P\d+)$', teamkfet_required(views.CheckoutRead.as_view()), - name = 'kfet.checkout.read'), + name='kfet.checkout.read'), # Checkout - Update url('^checkouts/(?P\d+)/edit$', teamkfet_required(views.CheckoutUpdate.as_view()), - name = 'kfet.checkout.update'), + name='kfet.checkout.update'), - ### Checkout Statements urls + # ----- + # Checkout Statement urls + # ----- # Checkout Statement - General url('^checkouts/statements/$', teamkfet_required(views.CheckoutStatementList.as_view()), - name = 'kfet.checkoutstatement'), + name='kfet.checkoutstatement'), # Checkout Statement - Create url('^checkouts/(?P\d+)/statements/add', teamkfet_required(views.CheckoutStatementCreate.as_view()), - name = 'kfet.checkoutstatement.create'), + name='kfet.checkoutstatement.create'), # Checkout Statement - Update url('^checkouts/(?P\d+)/statements/(?P\d+)/edit', teamkfet_required(views.CheckoutStatementUpdate.as_view()), - name = 'kfet.checkoutstatement.update'), + name='kfet.checkoutstatement.update'), # ----- # Article urls @@ -131,15 +137,15 @@ urlpatterns = [ # Article - General url('^articles/$', teamkfet_required(views.ArticleList.as_view()), - name = 'kfet.article'), + name='kfet.article'), # Article - Create url('^articles/new$', teamkfet_required(views.ArticleCreate.as_view()), - name = 'kfet.article.create'), + name='kfet.article.create'), # Article - Read url('^articles/(?P\d+)$', teamkfet_required(views.ArticleRead.as_view()), - name = 'kfet.article.read'), + name='kfet.article.read'), # Article - Update url('^articles/(?P\d+)/edit$', teamkfet_required(views.ArticleUpdate.as_view()), @@ -162,28 +168,28 @@ urlpatterns = [ # K-Psul urls # ----- - url('^k-psul/$', views.kpsul, name = 'kfet.kpsul'), + url('^k-psul/$', views.kpsul, name='kfet.kpsul'), url('^k-psul/checkout_data$', views.kpsul_checkout_data, - name = 'kfet.kpsul.checkout_data'), + name='kfet.kpsul.checkout_data'), url('^k-psul/perform_operations$', views.kpsul_perform_operations, - name = 'kfet.kpsul.perform_operations'), + name='kfet.kpsul.perform_operations'), url('^k-psul/cancel_operations$', views.kpsul_cancel_operations, - name = 'kfet.kpsul.cancel_operations'), + name='kfet.kpsul.cancel_operations'), url('^k-psul/articles_data', views.kpsul_articles_data, - name = 'kfet.kpsul.articles_data'), + name='kfet.kpsul.articles_data'), url('^k-psul/update_addcost$', views.kpsul_update_addcost, - name = 'kfet.kpsul.update_addcost'), + name='kfet.kpsul.update_addcost'), url('^k-psul/get_settings$', views.kpsul_get_settings, - name = 'kfet.kpsul.get_settings'), + name='kfet.kpsul.get_settings'), # ----- # JSON urls # ----- url(r'^history.json$', views.history_json, - name = 'kfet.history.json'), + name='kfet.history.json'), url(r'^accounts/read.json$', views.account_read_json, - name = 'kfet.account.read.json'), + name='kfet.account.read.json'), # ----- @@ -191,24 +197,26 @@ urlpatterns = [ # ----- url(r'^settings/$', - permission_required('kfet.change_settings')(views.SettingsList.as_view()), - name = 'kfet.settings'), + permission_required('kfet.change_settings') + (views.SettingsList.as_view()), + name='kfet.settings'), url(r'^settings/(?P\d+)/edit$', - permission_required('kfet.change_settings')(views.SettingsUpdate.as_view()), - name = 'kfet.settings.update'), + permission_required('kfet.change_settings') + (views.SettingsUpdate.as_view()), + name='kfet.settings.update'), # ----- # Transfers urls # ----- url(r'^transfers/$', views.transfers, - name = 'kfet.transfers'), + name='kfet.transfers'), url(r'^transfers/new$', views.transfers_create, - name = 'kfet.transfers.create'), + name='kfet.transfers.create'), url(r'^transfers/perform$', views.perform_transfers, - name = 'kfet.transfers.perform'), + name='kfet.transfers.perform'), url(r'^transfers/cancel$', views.cancel_transfers, - name = 'kfet.transfers.cancel'), + name='kfet.transfers.cancel'), # ----- # Inventories urls @@ -216,12 +224,12 @@ urlpatterns = [ url(r'^inventaires/$', teamkfet_required(views.InventoryList.as_view()), - name = 'kfet.inventory'), + name='kfet.inventory'), url(r'^inventaires/new$', views.inventory_create, - name = 'kfet.inventory.create'), + name='kfet.inventory.create'), url(r'^inventaires/(?P\d+)$', teamkfet_required(views.InventoryRead.as_view()), - name = 'kfet.inventory.read'), + name='kfet.inventory.read'), # ----- # Order urls @@ -229,15 +237,15 @@ urlpatterns = [ url(r'^orders/$', teamkfet_required(views.OrderList.as_view()), - name = 'kfet.order'), + name='kfet.order'), url(r'^orders/(?P\d+)$', teamkfet_required(views.OrderRead.as_view()), - name = 'kfet.order.read'), + name='kfet.order.read'), url(r'^orders/suppliers/(?P\d+)/edit$', teamkfet_required(views.SupplierUpdate.as_view()), - name = 'kfet.order.supplier.update'), + name='kfet.order.supplier.update'), url(r'^orders/suppliers/(?P\d+)/new-order$', views.order_create, - name = 'kfet.order.new'), + name='kfet.order.new'), url(r'^orders/(?P\d+)/to_inventory$', views.order_to_inventory, - name = 'kfet.order.to_inventory'), + name='kfet.order.to_inventory'), ]