Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] Products filtering by channel #11442

Merged
merged 5 commits into from May 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -0,0 +1,33 @@
@managing_products
Feature: Filtering products by a channel
In order to get a more focused view while managing some channel's products
As an Administrator
I want to be able to filter products by channel

Background:
Given the store operates on a channel named "Web-EU"
And the store also operates on a channel named "Web-US"
And the store has a product "MacBook Air" in channel "Web-EU"
And the store also has a product "MacBook Pro" in channel "Web-EU"
And the store also has a product "HP Spectre" in channel "Web-US"
And I am logged in as an administrator

@ui
Scenario: Filtering products by a chosen channel
When I browse products
And I choose "Web-EU" as a channel filter
And I filter
Then I should see 2 products in the list
And I should see a product with name "MacBook Air"
And I should see a product with name "MacBook Pro"
But I should not see any product with name "HP Spectre"

@ui
Scenario: Filtering products by a chosen channel
When I browse products
And I choose "Web-US" as a channel filter
And I filter
Then I should see a single product in the list
And I should not see any product with name "MacBook Air"
And I should not see any product with name "MacBook Pro"
But I should see a product with name "HP Spectre"
11 changes: 11 additions & 0 deletions src/Sylius/Behat/Context/Setup/ProductContext.php
Expand Up @@ -869,6 +869,17 @@ public function productHasVariant(ProductInterface $product, string $productVari
$this->createProductVariant($product, $productVariantName, $priceValue, $code, $channel, null, true, $currentStock);
}

/**
* @Given the store has a product :productName in channel :channel
* @Given the store also has a product :productName in channel :channel
*/
public function theStoreHasAProductWithChannel(string $productName, ChannelInterface $channel): void
{
$product = $this->createProduct($productName, 0, $channel);

$this->saveProduct($product);
}

private function getPriceFromString(string $price): int
{
return (int) round((float) str_replace(['€', '£', '$'], '', $price) * 100, 2);
Expand Down
16 changes: 16 additions & 0 deletions src/Sylius/Behat/Context/Ui/Admin/ManagingProductsContext.php
Expand Up @@ -248,6 +248,22 @@ public function iEnableSlugModification($localeCode = 'en_US')
$this->updateSimpleProductPage->enableSlugModification($localeCode);
}

/**
* @When I choose :channelName as a channel filter
*/
public function iChooseChannelAsAChannelFilter(string $channelName): void
{
$this->indexPage->chooseChannelFilter($channelName);
}

/**
* @When I filter
*/
public function iFilter(): void
{
$this->indexPage->filter();
}

/**
* @Then I should see the product :productName in the list
* @Then the product :productName should appear in the store
Expand Down
11 changes: 11 additions & 0 deletions src/Sylius/Behat/Page/Admin/Product/IndexPage.php
Expand Up @@ -37,11 +37,21 @@ public function __construct(
$this->imageExistenceChecker = $imageExistenceChecker;
}

public function filter(): void
{
$this->getElement('filter')->press();
}

public function filterByTaxon(string $taxonName): void
{
$this->getElement('taxon_filter', ['%taxon%' => $taxonName])->click();
}

public function chooseChannelFilter(string $channelName): void
{
$this->getElement('channel_filter')->selectOption($channelName);
}

public function hasProductAccessibleImage(string $productCode): bool
{
$productRow = $this->getTableAccessor()->getRowWithFields($this->getElement('table'), ['code' => $productCode]);
Expand All @@ -62,6 +72,7 @@ public function showProductPage(string $productName): void
protected function getDefinedElements(): array
{
return array_merge(parent::getDefinedElements(), [
'channel_filter' => '#criteria_channel',
'taxon_filter' => '.sylius-tree__item a:contains("%taxon%")',
]);
}
Expand Down
5 changes: 5 additions & 0 deletions src/Sylius/Behat/Page/Admin/Product/IndexPageInterface.php
Expand Up @@ -14,6 +14,7 @@
namespace Sylius\Behat\Page\Admin\Product;

use Sylius\Behat\Page\Admin\Crud\IndexPageInterface as CrudIndexPageInterface;
use Sylius\Component\Core\Model\ChannelInterface;

interface IndexPageInterface extends CrudIndexPageInterface
{
Expand All @@ -22,4 +23,8 @@ public function filterByTaxon(string $taxonName): void;
public function hasProductAccessibleImage(string $productCode): bool;

public function showProductPage(string $productName): void;

public function chooseChannelFilter(string $channelName) :void;

public function filter(): void;
}
Expand Up @@ -42,7 +42,9 @@ sylius_grid:
ship_with_tracking_code: "@SyliusAdmin/Shipment/Grid/Action/shipWithTrackingCode.html.twig"
update_product_positions: "@SyliusAdmin/Product/Grid/Action/updatePositions.html.twig"
update_product_variant_positions: "@SyliusAdmin/ProductVariant/Grid/Action/updatePositions.html.twig"

filter:
entities: '@SyliusUi/Grid/Filter/entities.html.twig'

liip_imagine:
filter_sets:
sylius_admin_product_original: ~
Expand Down
Expand Up @@ -44,6 +44,13 @@ sylius_grid:
enabled:
type: boolean
label: sylius.ui.enabled
channel:
type: entities
label: sylius.ui.channel
form_options:
class: "%sylius.model.channel.class%"
options:
field: "channels.id"
lchrusciel marked this conversation as resolved.
Show resolved Hide resolved
actions:
main:
create:
Expand Down
@@ -0,0 +1,45 @@
<?php

declare(strict_types=1);

namespace Sylius\Bundle\CoreBundle\Form\Type\Grid\Filter;

use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\OptionsResolver\OptionsResolver;

/**
* @experimental
*/
final class EntitiesFilterType extends AbstractType
{
/**
* {@inheritdoc}
*/
Comment on lines +16 to +18
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant docblock

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kinda, but I guess we should remove them once and for all soon.

public function configureOptions(OptionsResolver $resolver): void
{
$resolver
->setDefaults([
'class' => null,
'label' => false,
'placeholder' => 'sylius.ui.all',
])
;
}

/**
* {@inheritdoc}
*/
public function getParent(): string
{
return EntityType::class;
}

/**
* {@inheritdoc}
*/
public function getBlockPrefix(): string
{
return 'sylius_grid_filter_entities';
}
}
4 changes: 4 additions & 0 deletions src/Sylius/Bundle/CoreBundle/Resources/config/services.xml
Expand Up @@ -209,5 +209,9 @@

<service id="sylius.order_item_names_setter" class="Sylius\Component\Core\Order\OrderItemNamesSetter" />
<service id="Sylius\Component\Core\Order\OrderItemNamesSetterInterface" alias="sylius.order_item_names_setter" />

<service id="sylius.grid_filter.entities" class="Sylius\Component\Core\Grid\Filter\EntitiesFilter">
<tag name="sylius.grid_filter" type="entities" form-type="Sylius\Bundle\CoreBundle\Form\Type\Grid\Filter\EntitiesFilterType" />
</service>
</services>
</container>
@@ -0,0 +1,3 @@
{% form_theme form '@SyliusUi/Form/theme.html.twig' %}

{{ form_row(form, {'label': filter.label}) }}
28 changes: 28 additions & 0 deletions src/Sylius/Component/Core/Grid/Filter/EntitiesFilter.php
@@ -0,0 +1,28 @@
<?php

declare(strict_types=1);

namespace Sylius\Component\Core\Grid\Filter;

use Sylius\Component\Grid\Data\DataSourceInterface;
use Sylius\Component\Grid\Filtering\FilterInterface;

/**
* @experimental
*/
final class EntitiesFilter implements FilterInterface
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we consider moving this class to GridBundle? Also, perhaps for training purposes, we could add spec for this class as well.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds like a good idea!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Anyway, I'd merge this as it is now and extract it next.

{
/**
* {@inheritdoc}
*/
public function apply(DataSourceInterface $dataSource, string $name, $data, array $options): void
{
if (empty($data)) {
return;
}

$expressionBuilder = $dataSource->getExpressionBuilder();

$dataSource->restrict($expressionBuilder->equals($options['field'], $data));
}
}