From c9a43e80f3cd77c20bccec1597660d598d24e3d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Valenta?= <git@imaniti.org> Date: Fri, 30 Jun 2023 22:51:18 +0900 Subject: [PATCH] improved searching --- .../contracts/includes/contract_list.html | 16 +-- contracts/templates/contracts/search.html | 70 +++++++--- contracts/views.py | 131 +++++++++++++++--- 3 files changed, 176 insertions(+), 41 deletions(-) diff --git a/contracts/templates/contracts/includes/contract_list.html b/contracts/templates/contracts/includes/contract_list.html index 5ed2646..e8bcf35 100644 --- a/contracts/templates/contracts/includes/contract_list.html +++ b/contracts/templates/contracts/includes/contract_list.html @@ -12,9 +12,9 @@ </h2> </a> <table class="table-auto border-separate border-spacing-1.5"> - <tbody> + <tbody class="flex flex-col gap-2"> <tr class="flex gap-2 justify-between items-center"> - <td>Typy:</td> + <td class="shrink-0">Typy:</td> <td> <ul class="flex flex-wrap gap-1.5"> {% for type in contract.types.all %} @@ -26,8 +26,8 @@ </td> </tr> <tr class="flex gap-2 justify-between items-center"> - <td class="pt-1.5">Účinná od:</td> - <td class="pt-1.5"> + <td class="shrink-0">Účinná od:</td> + <td> {% if contract.valid_start_date %} {{ contract.valid_start_date }} {% else %} @@ -36,8 +36,8 @@ </td> </tr> <tr class="flex gap-2 justify-between items-center"> - <td class="py-1.5">Účinná do:</td> - <td class="py-1.5"> + <td class="shrink-0">Účinná do:</td> + <td> {% if contract.valid_end_date %} {{ contract.valid_end_date }} {% else %} @@ -46,7 +46,7 @@ </td> </tr> <tr class="flex gap-2 justify-between items-center"> - <td>Platná:</td> + <td class="shrink-0">Platná:</td> <td> <i class="{% if contract.is_valid %}ico--checkmark{% else %}ico--cross{% endif %}" @@ -55,7 +55,7 @@ </td> </tr> <tr class="flex gap-2 justify-between items-center"> - <td>Podpis s:</td> + <td class="shrink-0">Podpis s:</td> <td> <ul class="flex flex-wrap gap-1.5"> {% for signature in contract.signee_signatures.all %} diff --git a/contracts/templates/contracts/search.html b/contracts/templates/contracts/search.html index 1897d99..216f7b0 100644 --- a/contracts/templates/contracts/search.html +++ b/contracts/templates/contracts/search.html @@ -2,33 +2,71 @@ {% load add %} {% block content %} - {% if not query_is_set %} - {% include "contracts/includes/double_heading.html" with icon="ico--search" heading="Vyhledávání" subheading="dle názvu smlouvy" %} - {% else %} - {% include "contracts/includes/double_heading.html" with icon="ico--search" heading="Vyhledávání" subheading="„"|add:query|add:"“" %} - {% endif %} + {% include "contracts/includes/double_heading.html" with icon="ico--search" heading="Vyhledávání" %} - <form method="get" class="flex justify-center mb-10"> - <div class="flex flex-row border border-black"> + <form method="get" class="mb-10"> + <div class="flex flex-col gap-2"> {% csrf_token %} + + <input + id="name" + name="name" + class="border border-black bg-grey-150 h-10 px-4 text-lg xl:h-14 xl:px-5" + type="text" + value="{% if name %}{{ name }}{% endif %}" + placeholder="Název" + aria-label="Vyhledávací box pro název" + > + + <input + id="summary" + name="summary" + class="border border-black bg-grey-150 h-10 px-4 text-lg xl:h-14 xl:px-5" + type="text" + value="{% if summary %}{{ summary }}{% endif %}" + placeholder="Sumarizace" + aria-label="Vyhledávací box pro sumarizaci" + > + <input - id="q" - name="q" - class="bg-grey-150 w-56 h-10 px-4 text-lg xl:h-14 xl:px-5" + id="signing_party_ico_number" + name="signing_party_ico_number" + class="border border-black bg-grey-150 h-10 px-4 text-lg xl:h-14 xl:px-5" type="text" - value="{% if query_is_set %}{{ query }}{% endif %}" - placeholder="Hledaný název" - aria-label="Vyhledávací box" + value="{% if signing_party_ico_number %}{{ signing_party_ico_number }}{% endif %}" + placeholder="IČO smluvních stran" + aria-label="Vyhledávací box pro IČO smluvních stran" > + + <input + id="signing_party_name" + name="signing_party_name" + class="border border-black bg-grey-150 h-10 px-4 text-lg xl:h-14 xl:px-5" + type="text" + value="{% if signing_party_name %}{{ signing_party_name }}{% endif %}" + placeholder="Název smluvních stran" + aria-label="Vyhledávací box pro názvy smluvních stran" + > + + <input + id="signing_party_representative_name" + name="signing_party_representative_name" + class="border border-black bg-grey-150 h-10 px-4 text-lg xl:h-14 xl:px-5" + type="text" + value="{% if signing_party_representative_name %}{{ signing_party_representative_name }}{% endif %}" + placeholder="Zástupce smluvních stran" + aria-label="Vyhledávací box pro zástupce smluvních stran" + > + <button type="submit" class="btn text-lg"> - <div class="btn__body h-10 w-12 min-h-0 min-w-0 xl:h-14 xl:w-14"> - <i class="ico--search"></i> + <div class="btn__body h-10 xl:h-14 flex gap-3"> + <i class="ico--search"></i>Hledat </div> </button> </div> </form> - {% if query_is_set %} + {% if any_query_is_set %} {% if page|length != 0 %} {% include "contracts/includes/contract_list.html" with page=page paginator=paginator %} {% else %} diff --git a/contracts/views.py b/contracts/views.py index 693fca2..94a4b11 100644 --- a/contracts/views.py +++ b/contracts/views.py @@ -123,31 +123,128 @@ def view_contract(request, id: int): def search(request): - query = request.GET.get("q") + request_filter = {} + + for url_parameter in ( + "name", + "summary", + "signing_party_ico_number", + "signing_party_name", + "signing_party_representative_name", + ): + request_filter[url_parameter] = request.GET.get(url_parameter) + + any_query_is_set = False + + for url_parameter_key in request_filter.keys(): + if request_filter[url_parameter_key] is None: + continue + + if request_filter[url_parameter_key].replace(" ", "") == "": + request_filter[url_parameter_key] = None + else: + any_query_is_set = True + + if request_filter["signing_party_ico_number"] is not None: + if not request_filter["signing_party_ico_number"].isnumeric(): + raise HTTPExceptions.BAD_REQUEST + + request_filter["signing_party_ico_number"] = int( + request_filter["signing_party_ico_number"] + ) + page = paginator = None title = "Vyhledávání" - # Query is defined and is more than spaces - query_is_set = query is not None and len(query.replace(" ", "")) != 0 + if any_query_is_set: + filter = models.Q() + annotations = {} - if query_is_set: - title = f"Vyhledávání - „{query}“" + if request_filter["name"] is not None: + filter = filter & models.Q( + lower_name__contains=request_filter["name"].lower() + ) + annotations["lower_name"] = Lower("name") - lower_query = query.lower() + if request_filter["summary"] is not None: + filter = filter & models.Q( + lower_summary__contains=request_filter["summary"].lower() + ) + annotations["lower_summary"] = Lower("summary") + + if request_filter["signing_party_ico_number"] is not None: + filter = filter & models.Q( + models.Q( + contractee_signatures__contractee__ico_number=request_filter[ + "signing_party_ico_number" + ] + ) + | models.Q( + signee_signatures__signee__ico_number=request_filter[ + "signing_party_ico_number" + ] + ) + ) + + if request_filter["signing_party_name"] is not None: + filter = filter & models.Q( + models.Q( + contractee_signatures__contractee__name_lower__contains=request_filter[ + "signing_party_name" + ].lower() + ) + | models.Q( + signee_signatures__signee__name_lower__contains=request_filter[ + "signing_party_name" + ].lower() + ) + ) + + annotations.update( + { + "contractee_signatures__contractee__name_lower": Lower( + "contractee_signatures__contractee__name" + ), + "signee_signatures__signee__name_lower": Lower( + "signee_signatures__signee__name" + ), + } + ) + + if request_filter["signing_party_representative_name"] is not None: + filter = filter & models.Q( + models.Q( + contractee_signatures__representatives__name_lower__contains=request_filter[ + "signing_party_representative_name" + ].lower() + ) + | models.Q( + signee_signatures__representatives__name_lower__contains=request_filter[ + "signing_party_representative_name" + ].lower() + ) + ) + + annotations.update( + { + "contractee_signatures__representatives__name_lower": Lower( + "contractee_signatures__representatives__name" + ), + "signee_signatures__representatives__name_lower": Lower( + "signee_signatures__representatives__name" + ), + } + ) # WARNING: PostgreSQL-dependent page, paginator = get_paginated_contracts( request, - ( - models.Q(lower_name__contains=lower_query) - | models.Q(lower_summary__contains=lower_query) - ), - { - "lower_name": Lower("name"), - "lower_summary": Lower("summary"), - }, + filter, + annotations, ) + print(filter) + return render( request, "contracts/search.html", @@ -157,8 +254,8 @@ def search(request): "description": "", "page": page, "paginator": paginator, - "query": query, - "query_is_set": query_is_set, + "any_query_is_set": any_query_is_set, + **request_filter, }, ) @@ -364,7 +461,7 @@ def view_contractees(request): contractees = get_objects_for_user( request.user, "contracts.view_contractee", - ).order_by("name") + ).order_by("name", "department") page, paginator = get_pagination(request, contractees) -- GitLab