Skip to content

Commit

Permalink
Feat view more
Browse files Browse the repository at this point in the history
  • Loading branch information
PierreGauthier committed Mar 11, 2024
1 parent 77cfd63 commit fe49925
Show file tree
Hide file tree
Showing 18 changed files with 379 additions and 41 deletions.
82 changes: 82 additions & 0 deletions src/Controller/Filter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<?php
/**
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade Gally to newer versions in the future.
*
* @package Gally
* @author Stephan Hochdörfer <S.Hochdoerfer@bitexpert.de>, Gally Team <elasticsuite@smile.fr>
* @copyright 2022-present Smile
* @license Open Software License v. 3.0 (OSL-3.0)
*/

declare(strict_types=1);

namespace Gally\SyliusPlugin\Controller;

use Gally\SyliusPlugin\Form\Type\Filter\GallyDynamicFilterType;
use Gally\SyliusPlugin\Grid\Filter\Type\SelectFilterType;
use Gally\SyliusPlugin\Search\Adapter;
use Gally\SyliusPlugin\Service\FilterConverter;
use Sylius\Bundle\TaxonomyBundle\Doctrine\ORM\TaxonRepository;
use Sylius\Component\Channel\Context\ChannelContextInterface;
use Sylius\Component\Locale\Context\LocaleContextInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

final class Filter extends AbstractController
{
public function __construct(
private Adapter $adapter,
private ChannelContextInterface $channelContext,
private LocaleContextInterface $localeContext,
private TaxonRepository $taxonRepository,
private FormFactoryInterface $formFactory,
private FilterConverter $filterConverter,
) {
}

public function viewMore(Request $request, string $filterField): Response
{
$search = $request->get('search');
$filters = $request->get('filters')['gally'] ?? [];
$gallyFilters = [];
foreach ($filters as $field => $value) {
$gallyFilter = $this->filterConverter->convert($field, $value);
if ($gallyFilter) {
$gallyFilters[] = $gallyFilter;
}
}

$choices = [];
$currentTaxonId = $request->get('taxon');
$aggregationOptions = $this->adapter->viewMoreOption(
$this->channelContext->getChannel(),
$currentTaxonId ? $this->taxonRepository->find($currentTaxonId) : null,
$this->localeContext->getLocaleCode(),
$filterField,
$gallyFilters,
$search,
);

foreach ($aggregationOptions as $option) {
$choices[$option['label']] = $option['value'];
}

$options = [
'block_prefix' => 'sylius_gally_filter_checkbox',
'choices' => $choices,
'expanded' => true,
'multiple' => true,
];

$form = $this->formFactory->createNamed('criteria')->add('gally', GallyDynamicFilterType::class);
$form->get('gally')->add($filterField, SelectFilterType::class, $options);
$form->get('gally')->get($filterField)->setData($filters[$filterField] ?? null);
$html = $this->renderView('@GallySyliusPlugin/Grid/Filter/gally_dynamic_filter.html.twig', ['form' => $form]);

return $this->json(['html' => $html]);
}
}
53 changes: 45 additions & 8 deletions src/Form/Type/Filter/GallyDynamicFilterType.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,29 @@
namespace Gally\SyliusPlugin\Form\Type\Filter;

use Gally\SyliusPlugin\Event\GridFilterUpdateEvent;
use Gally\SyliusPlugin\Grid\Filter\Type\SelectFilterType;
use Gally\SyliusPlugin\Search\Aggregation\Aggregation;
use Gally\SyliusPlugin\Search\Aggregation\AggregationOption;
use Sylius\Bundle\GridBundle\Form\Type\Filter\BooleanFilterType;
use Sylius\Bundle\GridBundle\Form\Type\Filter\SelectFilterType;
use Sylius\Bundle\TaxonomyBundle\Doctrine\ORM\TaxonRepository;
use Sylius\Component\Grid\Parameters;
use Sylius\Component\Locale\Context\LocaleContextInterface;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\RangeType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;

class GallyDynamicFilterType extends AbstractType
{
public function __construct(
private UrlGeneratorInterface $router,
private RequestStack $requestStack,
private TaxonRepository $taxonRepository,
private LocaleContextInterface $localeContext,
) {
}

/**
* @var Aggregation[]
*/
Expand Down Expand Up @@ -78,16 +91,20 @@ public function buildForm(FormBuilderInterface $builder, array $options): void
/** @var AggregationOption $option */
$choices[$option->getLabel()] = $option->getId();
}
$options = [
'block_prefix' => 'sylius_gally_filter_checkbox',
'label' => $aggregation->getLabel(),
'choices' => $choices,
'expanded' => true,
'multiple' => true,
];
if ($aggregation->hasMore()) {
$options['has_more_url'] = $this->buildHasMoreUrl($aggregation->getField());
}
$builder->add(
$aggregation->getField(),
SelectFilterType::class,
[
'block_prefix' => 'sylius_gally_filter_checkbox',
'label' => $aggregation->getLabel(),
'choices' => $choices,
'expanded' => true,
'multiple' => true,
]
$options
);
break;
default:
Expand All @@ -100,4 +117,24 @@ public function onFilterUpdate(GridFilterUpdateEvent $event): void
{
$this->aggregations = $event->getAggregations();
}

private function buildHasMoreUrl(string $field): string
{
$request = $this->requestStack->getCurrentRequest();
$parameters = new Parameters($request->query->all());
$criteria = $parameters->get('criteria', []);
$search = (isset($criteria['search'], $criteria['search']['value'])) ? $criteria['search']['value'] : '';
unset($criteria['search']);
$taxon = $this->taxonRepository->findOneBySlug($request->attributes->get('slug'), $this->localeContext->getLocaleCode());

return $this->router->generate(
'gally_filter_view_more_ajax',
[
'filterField' => $field,
'search' => $search,
'filters' => $criteria,
'taxon' => $taxon->getId(),
]
);
}
}
29 changes: 8 additions & 21 deletions src/Grid/Filter/GallyDynamicFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,35 +14,22 @@

namespace Gally\SyliusPlugin\Grid\Filter;

use Gally\SyliusPlugin\Service\FilterConverter;
use Sylius\Component\Grid\Data\DataSourceInterface;
use Sylius\Component\Grid\Filtering\FilterInterface;

class GallyDynamicFilter implements FilterInterface
{
public function __construct(private FilterConverter $filterConverter)
{
}

public function apply(DataSourceInterface $dataSource, string $name, $data, array $options): void
{
foreach ($data as $field => $value) {
if ('' === $value) {
continue;
}

if (str_contains($field, '_slider')) {
$field = str_replace('_slider', '', $field);
$values = explode(';', $value, 2);
$dataSource->restrict($dataSource->getExpressionBuilder()->andX(
$dataSource->getExpressionBuilder()->greaterThanOrEqual($field, (int) $values[0]),
$dataSource->getExpressionBuilder()->lessThanOrEqual($field, (int) $values[1]),
));
} elseif (str_contains($field, '_boolean')) {
$field = str_replace('_boolean', '', $field);
$value = ('true' === $value);
$dataSource->restrict($dataSource->getExpressionBuilder()->equals($field, $value));
} else {
if (\is_array($value)) {
$dataSource->restrict($dataSource->getExpressionBuilder()->in($field, $value));
} else {
$dataSource->restrict($dataSource->getExpressionBuilder()->equals($field, $value));
}
$gallyFilter = $this->filterConverter->convert($field, $value);
if ($gallyFilter) {
$dataSource->restrict($gallyFilter);
}
}
}
Expand Down
40 changes: 40 additions & 0 deletions src/Grid/Filter/Type/SelectFilterType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php
/**
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade Gally to newer versions in the future.
*
* @package Gally
* @author Stephan Hochdörfer <S.Hochdoerfer@bitexpert.de>, Gally Team <elasticsuite@smile.fr>
* @copyright 2022-present Smile
* @license Open Software License v. 3.0 (OSL-3.0)
*/

declare(strict_types=1);

namespace Gally\SyliusPlugin\Grid\Filter\Type;

use Sylius\Bundle\GridBundle\Form\Type\Filter\SelectFilterType as BaseSelectFilterType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\Form\FormView;
use Symfony\Component\OptionsResolver\OptionsResolver;

final class SelectFilterType extends AbstractType
{
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefined(['has_more_url'])
->addAllowedTypes('has_more_url', 'string');
}

public function getParent(): string
{
return BaseSelectFilterType::class;
}

public function buildView(FormView $view, FormInterface $form, array $options): void
{
$view->vars['has_more_url'] = $options['has_more_url'] ?? null;
}
}
25 changes: 25 additions & 0 deletions src/Resources/config/services.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@
<argument type="service" id="Gally\SyliusPlugin\Synchronizer\LocalizedCatalogSynchronizer" />
</service>


<service id="Gally\SyliusPlugin\Service\FilterConverter" />

<service id="Gally\SyliusPlugin\Controller\AdminGallyController">
<argument type="service" id="Gally\SyliusPlugin\Repository\GallyConfigurationRepository" />
<argument type="service" id="Gally\SyliusPlugin\Api\AuthenticationTokenProvider" />
Expand All @@ -42,6 +45,19 @@
<tag name="controller.service_arguments" />
</service>

<service id="Gally\SyliusPlugin\Controller\Filter">
<argument type="service" id="Gally\SyliusPlugin\Search\Adapter" />
<argument type="service" id="sylius.context.channel" />
<argument type="service" id="sylius.context.locale" />
<argument type="service" id="sylius.repository.taxon" />
<argument type="service" id="form.factory" />
<argument type="service" id="Gally\SyliusPlugin\Service\FilterConverter" />
<call method="setContainer">
<argument type="service" id="service_container" />
</call>
<tag name="controller.service_arguments" />
</service>

<service id="Gally\SyliusPlugin\Form\Extension\ChannelTypeExtension">
<tag name="form.type_extension"/>
</service>
Expand All @@ -64,11 +80,20 @@
</service>

<service id="Gally\SyliusPlugin\Grid\Filter\GallyDynamicFilter">
<argument type="service" id="Gally\SyliusPlugin\Service\FilterConverter" />
<tag name="sylius.grid_filter" type="gally_dynamic_filter" form_type="Gally\SyliusPlugin\Form\Type\Filter\GallyDynamicFilterType" />
</service>

<service id="Gally\SyliusPlugin\Form\Type\Filter\GallyDynamicFilterType" autoconfigure="true">
<argument type="service" id="router" />
<argument type="service" id="request_stack" />
<argument type="service" id="sylius.repository.taxon" />
<argument type="service" id="sylius.context.locale" />
<tag name="kernel.event_listener" event="gally.grid.configure_filter" method="onFilterUpdate" />
</service>

<service id="sylius.form.type.grid_filter.select" class="Sylius\Bundle\GridBundle\Form\Type\Filter\SelectFilterType">
<tag name="form.type" />
</service>
</services>
</container>
8 changes: 7 additions & 1 deletion src/Resources/config/shop_routing.yml
Original file line number Diff line number Diff line change
@@ -1 +1,7 @@
# Define your own shop routes here
#sylius_shop_partial_cart_add_item_ajax:
gally_filter_view_more_ajax:
path: /viewMore/{filterField}
methods: [ GET ]
defaults:
_controller: Gally\SyliusPlugin\Controller\Filter::viewMore
_format: json
4 changes: 4 additions & 0 deletions src/Resources/public/view-more.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#searchbar .field .view-more {
color: rgba(0, 0, 0, 0.87);
cursor: pointer;
}
25 changes: 25 additions & 0 deletions src/Resources/public/view-more.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
$(document).ready(function() {
$(document).on(
'click',
'#searchbarTextField .view-more',
function (event) {
event. preventDefault();

let linkEl = $(event.target),
form = linkEl.closest('form'),
choicesEl = $('#' + linkEl.data('for') + ' > .fields');

form.addClass('loading');

$.get(
linkEl.data('href'),
function( data ) {
choicesEl.replaceWith($(data.html).find('.fields'));
linkEl.hide();
}
).always(function() {
form.removeClass('loading');
});
}
);
});
1 change: 1 addition & 0 deletions src/Resources/translations/messages.en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ gally_sylius:
header: Gally configuration
filters:
headline: Filters
view_more: View more
form:
active: Enable Gally
product_index_batch_size: Product Indexing Batch Size
Expand Down
3 changes: 3 additions & 0 deletions src/Resources/views/Form/_checkbox.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,8 @@
{{- form_label(form) -}}
{% set attr = attr|merge({'class': attr.class|default ~ ' ui'}) %}
{{- form_widget(form, {'attr': attr}) -}}
{% if has_more_url %}
<a class="view-more" data-for="{{ form.vars.id }}" data-href="{{ has_more_url }}">{{ 'gally_sylius.ui.filters.view_more'|trans }}</a>
{% endif %}
</div>
{%- endblock sylius_gally_filter_checkbox_row %}
4 changes: 4 additions & 0 deletions src/Resources/views/Product/Index/_filters.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
<div class="four wide column">
<div class="ui segment">
<form method="get" action="{{ path('sylius_shop_product_index', {'slug': app.request.attributes.get('slug')}) }}" class="ui loadable form">
{# Keep the current search in the query on filtering #}
{% if products.parameters.get('criteria').search is defined %}
<input type="hidden" name="criteria[search][value]" value="{{ products.parameters.get('criteria').search.value }}" />
{% endif %}
<div class="ui stackable grid" id="searchbar">
<div class="column" id="searchbarTextField">
{% for filter in products.definition.enabledFilters %}
Expand Down
1 change: 1 addition & 0 deletions src/Resources/views/events_javascript.html.twig
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
{% include '@SyliusUi/_javascripts.html.twig' with {'path': 'bundles/gallysyliusplugin/nouislider.min.js'} %}
{% include '@SyliusUi/_javascripts.html.twig' with {'path': 'bundles/gallysyliusplugin/range-slider.js'} %}
{% include '@SyliusUi/_javascripts.html.twig' with {'path': 'bundles/gallysyliusplugin/view-more.js'} %}
1 change: 1 addition & 0 deletions src/Resources/views/events_stylesheets.html.twig
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
{% include '@SyliusUi/_stylesheets.html.twig' with {'path': 'bundles/gallysyliusplugin/nouislider.min.css'} %}
{% include '@SyliusUi/_stylesheets.html.twig' with {'path': 'bundles/gallysyliusplugin/slider.css'} %}
{% include '@SyliusUi/_stylesheets.html.twig' with {'path': 'bundles/gallysyliusplugin/view-more.css'} %}
Loading

0 comments on commit fe49925

Please sign in to comment.