mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2025-06-21 09:35:49 +02:00
Added possibility to apply filters to search results.
This commit is contained in:
parent
c3f144447f
commit
e96db21ceb
6 changed files with 61 additions and 30 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -127,13 +127,15 @@ class PartListsController extends AbstractController
|
|||
|
||||
/**
|
||||
* Common implementation for the part list pages.
|
||||
* @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 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 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, [
|
||||
return $this->showListWithFilter($request,
|
||||
'Parts/lists/search_list.html.twig',
|
||||
null,
|
||||
null,
|
||||
[
|
||||
'keyword' => $searchFilter->getKeyword(),
|
||||
'searchFilter' => $searchFilter,
|
||||
],
|
||||
[
|
||||
'search' => $searchFilter,
|
||||
])->handleRequest($request);
|
||||
|
||||
if ($table->isCallback()) {
|
||||
return $table->getResponse();
|
||||
}
|
||||
|
||||
return $this->render('Parts/lists/search_list.html.twig', [
|
||||
'datatable' => $table,
|
||||
'keyword' => $searchFilter->getQuery(),
|
||||
]);
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 %}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue