Added possibility to apply filters to search results.

This commit is contained in:
Jan Böhmer 2022-09-10 00:08:59 +02:00
parent c3f144447f
commit e96db21ceb
6 changed files with 61 additions and 30 deletions

View file

@ -35,6 +35,11 @@ export default class extends Controller {
{
const form = event.target.closest('form');
for(const element of form.elements) {
// Do not clear elements with data-no-clear attribute
if(element.dataset.noClear) {
continue;
}
element.disabled = true;
}

View file

@ -127,13 +127,15 @@ class PartListsController extends AbstractController
/**
* Common implementation for the part list pages.
* @param string $template The template that should be rendered
* @param array $additonal_template_vars Any additional template variables that should be passed to the template
* @param callable $filter_changer A function that is called with the filter object as parameter. This function can be used to customize the filter
* @param callable $form_changer A function that is called with the form object as parameter. This function can be used to customize the form
* @param Request $request The request to parse
* @param string $template The template that should be rendered
* @param callable|null $filter_changer A function that is called with the filter object as parameter. This function can be used to customize the filter
* @param callable|null $form_changer A function that is called with the form object as parameter. This function can be used to customize the form
* @param array $additonal_template_vars Any additional template variables that should be passed to the template
* @param array $additional_table_vars Any additional variables that should be passed to the table creation
* @return Response
*/
protected function showListWithFilter(Request $request, string $template, ?callable $filter_changer = null, ?callable $form_changer = null, array $additonal_template_vars = []): Response
protected function showListWithFilter(Request $request, string $template, ?callable $filter_changer = null, ?callable $form_changer = null, array $additonal_template_vars = [], array $additional_table_vars = []): Response
{
$formRequest = clone $request;
$formRequest->setMethod('GET');
@ -149,7 +151,7 @@ class PartListsController extends AbstractController
$filterForm->handleRequest($formRequest);
$table = $this->dataTableFactory->createFromType(PartsDataTable::class, ['filter' => $filter])
$table = $this->dataTableFactory->createFromType(PartsDataTable::class, array_merge(['filter' => $filter], $additional_table_vars))
->handleRequest($request);
if ($table->isCallback()) {
@ -312,18 +314,18 @@ class PartListsController extends AbstractController
{
$searchFilter = $this->searchRequestToFilter($request);
$table = $dataTable->createFromType(PartsDataTable::class, [
'search' => $searchFilter,
])->handleRequest($request);
if ($table->isCallback()) {
return $table->getResponse();
}
return $this->render('Parts/lists/search_list.html.twig', [
'datatable' => $table,
'keyword' => $searchFilter->getQuery(),
]);
return $this->showListWithFilter($request,
'Parts/lists/search_list.html.twig',
null,
null,
[
'keyword' => $searchFilter->getKeyword(),
'searchFilter' => $searchFilter,
],
[
'search' => $searchFilter,
]
);
}
/**

View file

@ -9,7 +9,7 @@ class PartSearchFilter implements FilterInterface
{
/** @var string The string to query for */
protected $query;
protected $keyword;
/** @var boolean Whether to use regex for searching */
protected $regex = false;
@ -49,7 +49,7 @@ class PartSearchFilter implements FilterInterface
public function __construct(string $query)
{
$this->query = $query;
$this->keyword = $query;
}
protected function getFieldsToSearch(): array
@ -95,7 +95,7 @@ class PartSearchFilter implements FilterInterface
$fields_to_search = $this->getFieldsToSearch();
//If we have nothing to search for, do nothing
if (empty($fields_to_search) || empty($this->query)) {
if (empty($fields_to_search) || empty($this->keyword)) {
return;
}
@ -115,27 +115,27 @@ class PartSearchFilter implements FilterInterface
//For regex we pass the query as is, for like we add % to the start and end as wildcards
if ($this->regex) {
$queryBuilder->setParameter('search_query', $this->query);
$queryBuilder->setParameter('search_query', $this->keyword);
} else {
$queryBuilder->setParameter('search_query', '%' . $this->query . '%');
$queryBuilder->setParameter('search_query', '%' . $this->keyword . '%');
}
}
/**
* @return string
*/
public function getQuery(): string
public function getKeyword(): string
{
return $this->query;
return $this->keyword;
}
/**
* @param string $query
* @param string $keyword
* @return PartSearchFilter
*/
public function setQuery(string $query): PartSearchFilter
public function setKeyword(string $keyword): PartSearchFilter
{
$this->query = $query;
$this->keyword = $keyword;
return $this;
}

View file

@ -65,6 +65,7 @@ use App\Services\MoneyFormatter;
use App\Services\SIFormatter;
use App\Services\Trees\TreeViewGenerator;
use Brick\Math\BigDecimal;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\SerializerInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
use Twig\Extension\AbstractExtension;
@ -87,12 +88,14 @@ class AppExtension extends AbstractExtension
protected $FAIconGenerator;
protected $translator;
protected $objectNormalizer;
public function __construct(EntityURLGenerator $entityURLGenerator, MarkdownParser $markdownParser,
SerializerInterface $serializer, TreeViewGenerator $treeBuilder,
MoneyFormatter $moneyFormatter,
SIFormatter $SIFormatter, AmountFormatter $amountFormatter,
AttachmentURLGenerator $attachmentURLGenerator,
FAIconGenerator $FAIconGenerator, TranslatorInterface $translator)
FAIconGenerator $FAIconGenerator, TranslatorInterface $translator, ObjectNormalizer $objectNormalizer)
{
$this->entityURLGenerator = $entityURLGenerator;
$this->markdownParser = $markdownParser;
@ -104,6 +107,8 @@ class AppExtension extends AbstractExtension
$this->attachmentURLGenerator = $attachmentURLGenerator;
$this->FAIconGenerator = $FAIconGenerator;
$this->translator = $translator;
$this->objectNormalizer = $objectNormalizer;
}
public function getFilters(): array
@ -118,6 +123,8 @@ class AppExtension extends AbstractExtension
new TwigFilter('siFormat', [$this, 'siFormat']),
new TwigFilter('amountFormat', [$this, 'amountFormat']),
new TwigFilter('loginPath', [$this, 'loginPath']),
new TwigFilter('toArray', [$this, 'toArray'])
];
}
@ -174,6 +181,11 @@ class AppExtension extends AbstractExtension
return json_encode($tree, JSON_THROW_ON_ERROR);
}
public function toArray($object): array
{
return $this->objectNormalizer->normalize($object, null);
}
/**
* This function/filter generates an path.
*/

View file

@ -123,6 +123,14 @@
</div>
</div>
{# Retain the query parameters of the search form if it is existing #}
{% if searchFilter is defined %}
{% for property, value in searchFilter|toArray %}
<input type="hidden" name="{{ property }}" data-no-clear="true" value="{{ value }}">
{% endfor %}
{% endif %}
{{ form_end(filterForm) }}
</div>
</div>

View file

@ -1,11 +1,15 @@
{% extends "base.html.twig" %}
{% block title %}
{% trans %}parts_list.search.title{% endtrans %} {{ keyword }}
{% trans %}parts_list.search.title{% endtrans %}: {{ keyword }}
{% endblock %}
{% block content %}
<div class="accordion mb-3">
{% include "Parts/lists/_filter.html.twig" %}
</div>
{% include "Parts/lists/_parts_list.html.twig" %}
{% endblock %}