mirror of
https://github.com/Sylius/Sylius.git
synced 2026-07-14 17:10:53 +00:00
Merge pull request #7651 from NeverResponse/autocomplete-promotions
[Admin] Reduced query size while creating/editing promotions
This commit is contained in:
commit
720068906b
32 changed files with 275 additions and 59 deletions
|
|
@ -156,7 +156,7 @@ final class ManagingPromotionsContext implements Context
|
|||
$this->createPage->addRule('Has at least one from taxons');
|
||||
|
||||
foreach ($taxons as $taxon) {
|
||||
$this->createPage->selectRuleOption('Taxons', $taxon, true);
|
||||
$this->createPage->selectAutocompleteRuleOption('Taxons', $taxon, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -166,7 +166,7 @@ final class ManagingPromotionsContext implements Context
|
|||
public function iAddTheRuleConfiguredWith($taxonName, $amount, $channelName)
|
||||
{
|
||||
$this->createPage->addRule('Total price of items from taxon');
|
||||
$this->createPage->selectRuleOption('Taxon', $taxonName);
|
||||
$this->createPage->selectAutocompleteRuleOption('Taxon', $taxonName);
|
||||
$this->createPage->fillRuleOptionForChannel($channelName, 'Amount', $amount);
|
||||
}
|
||||
|
||||
|
|
@ -231,7 +231,7 @@ final class ManagingPromotionsContext implements Context
|
|||
*/
|
||||
public function iSpecifyThatThisActionShouldBeAppliedToItemsFromCategory($taxonName)
|
||||
{
|
||||
$this->createPage->selectFilterOption('Taxons filter', $taxonName);
|
||||
$this->createPage->selectAutoCompleteFilterOption('Taxons', $taxonName);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -556,7 +556,7 @@ final class ManagingPromotionsContext implements Context
|
|||
public function iAddTheRuleConfiguredWithTheProduct($productName)
|
||||
{
|
||||
$this->createPage->addRule('Contains product');
|
||||
$this->createPage->selectRuleOption('Product', $productName);
|
||||
$this->createPage->selectAutocompleteRuleOption('Product code', $productName);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -564,7 +564,7 @@ final class ManagingPromotionsContext implements Context
|
|||
*/
|
||||
public function iSpecifyThatThisActionShouldBeAppliedToTheProduct($productName)
|
||||
{
|
||||
$this->createPage->selectFilterOption('Products filter', $productName);
|
||||
$this->createPage->selectAutoCompleteFilterOption('Products', $productName);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
namespace Sylius\Behat\Page\Admin\Promotion;
|
||||
|
||||
use Behat\Mink\Driver\Selenium2Driver;
|
||||
use Behat\Mink\Element\NodeElement;
|
||||
use Behat\Mink\Exception\ElementNotFoundException;
|
||||
use Sylius\Behat\Behaviour\NamesIt;
|
||||
|
|
@ -51,6 +52,22 @@ class CreatePage extends BaseCreatePage implements CreatePageInterface
|
|||
$this->getLastCollectionItem('rules')->find('named', array('select', $option))->selectOption($value, $multiple);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function selectAutocompleteRuleOption($option, $value, $multiple = false)
|
||||
{
|
||||
$option = strtolower(str_replace(' ', '_', $option));
|
||||
|
||||
$ruleAutoComplete = $this
|
||||
->getLastCollectionItem('rules')
|
||||
->find('css', sprintf('input[type="hidden"][name*="[%s]"]', $option))
|
||||
->getParent()
|
||||
;
|
||||
|
||||
$this->selectAutocompleteValue($ruleAutoComplete, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
|
@ -172,9 +189,17 @@ class CreatePage extends BaseCreatePage implements CreatePageInterface
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function selectFilterOption($option, $value, $multiple = false)
|
||||
public function selectAutoCompleteFilterOption($option, $value, $multiple = false)
|
||||
{
|
||||
$this->getLastCollectionItem('actions')->find('named', array('select', $option))->selectOption($value, $multiple);
|
||||
$option = strtolower(str_replace(' ', '_', $option));
|
||||
|
||||
$filterAutoComplete = $this
|
||||
->getLastCollectionItem('actions')
|
||||
->find('css', sprintf('input[type="hidden"][name*="[%s_filter]"]', $option))
|
||||
->getParent()
|
||||
;
|
||||
|
||||
$this->selectAutocompleteValue($filterAutoComplete, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -217,7 +242,7 @@ class CreatePage extends BaseCreatePage implements CreatePageInterface
|
|||
return $this
|
||||
->getLastCollectionItem('rules')
|
||||
->find('css', sprintf('[id*="sylius_promotion_rules"] .configuration .field:contains("%s")', $channelName))
|
||||
;
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -247,4 +272,41 @@ class CreatePage extends BaseCreatePage implements CreatePageInterface
|
|||
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param NodeElement $autocomplete
|
||||
* @param string $value
|
||||
*/
|
||||
private function selectAutocompleteValue(NodeElement $autocomplete, $value)
|
||||
{
|
||||
Assert::isInstanceOf($this->getDriver(), Selenium2Driver::class);
|
||||
|
||||
$isAnyAsyncActionInProgressScript = 'jQuery.active';
|
||||
$isVisibleScript = sprintf(
|
||||
'$(document.evaluate("%s", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue).dropdown("is visible")',
|
||||
$autocomplete->getXpath()
|
||||
);
|
||||
|
||||
$this->getDocument()->waitFor(5, function () use ($isAnyAsyncActionInProgressScript) {
|
||||
return !(bool) $this->getDriver()->evaluateScript($isAnyAsyncActionInProgressScript);
|
||||
});
|
||||
|
||||
$autocomplete->click();
|
||||
|
||||
$this->getDocument()->waitFor(5, function () use ($isAnyAsyncActionInProgressScript) {
|
||||
return !(bool) $this->getDriver()->evaluateScript($isAnyAsyncActionInProgressScript);
|
||||
});
|
||||
|
||||
$this->getDocument()->waitFor(5, function () use ($isVisibleScript) {
|
||||
return $this->getDriver()->evaluateScript($isVisibleScript);
|
||||
});
|
||||
|
||||
$autocompleteItem = $autocomplete->find('css', sprintf('div.item:contains("%s")', $value));
|
||||
|
||||
$autocompleteItem->click();
|
||||
|
||||
$this->getDocument()->waitFor(5, function () use ($isVisibleScript) {
|
||||
return !$this->getDriver()->evaluateScript($isVisibleScript);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,6 +42,13 @@ interface CreatePageInterface extends BaseCreatePageInterface
|
|||
*/
|
||||
public function selectRuleOption($option, $value, $multiple = false);
|
||||
|
||||
/**
|
||||
* @param string $option
|
||||
* @param string $value
|
||||
* @param bool $multiple
|
||||
*/
|
||||
public function selectAutocompleteRuleOption($option, $value, $multiple = false);
|
||||
|
||||
/**
|
||||
* @param string $option
|
||||
* @param string $value
|
||||
|
|
@ -116,5 +123,5 @@ interface CreatePageInterface extends BaseCreatePageInterface
|
|||
* @param string $value
|
||||
* @param bool $multiple
|
||||
*/
|
||||
public function selectFilterOption($option, $value, $multiple = false);
|
||||
public function selectAutoCompleteFilterOption($option, $value, $multiple = false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,30 @@ sylius_admin_ajax_generate_product_slug:
|
|||
defaults:
|
||||
_controller: sylius.controller.product_slug:generateAction
|
||||
|
||||
sylius_admin_ajax_product_by_name_phrase:
|
||||
path: /search
|
||||
methods: [GET]
|
||||
defaults:
|
||||
_controller: sylius.controller.product:indexAction
|
||||
_sylius:
|
||||
serialization_groups: [Autocomplete]
|
||||
repository:
|
||||
method: findByNamePart
|
||||
arguments:
|
||||
phrase: $phrase
|
||||
locale: expr:service('sylius.context.locale').getLocaleCode()
|
||||
|
||||
sylius_admin_ajax_product_by_code:
|
||||
path: /code
|
||||
methods: [GET]
|
||||
defaults:
|
||||
_controller: sylius.controller.product:indexAction
|
||||
_sylius:
|
||||
serialization_groups: [Autocomplete]
|
||||
repository:
|
||||
method: findBy
|
||||
arguments: [code: $code]
|
||||
|
||||
sylius_admin_ajax_product_index:
|
||||
path: /
|
||||
methods: [GET]
|
||||
|
|
|
|||
|
|
@ -8,13 +8,13 @@
|
|||
*/
|
||||
|
||||
(function($) {
|
||||
$(document).ready(function() {
|
||||
$(document).ready(function () {
|
||||
$('#sylius_product_variant_pricingCalculator').handlePrototypes({
|
||||
'prototypePrefix': 'sylius_product_variant_pricingCalculator',
|
||||
'containerSelector': '#sylius_calculator_container'
|
||||
});
|
||||
|
||||
$('#sylius_customer_createUser').change(function(){
|
||||
$('#sylius_customer_createUser').change(function () {
|
||||
$('#user-form').toggle();
|
||||
});
|
||||
|
||||
|
|
@ -37,18 +37,25 @@
|
|||
'containerSelector': '.configuration'
|
||||
});
|
||||
|
||||
$('#actions a[data-form-collection="add"]').on('click', function(){
|
||||
$('#actions a[data-form-collection="add"]').on('click', function () {
|
||||
setTimeout(function(){
|
||||
$('select[name^="sylius_promotion[actions]"][name$="[type]"]').last().change();
|
||||
}, 50);
|
||||
});
|
||||
|
||||
$('#rules a[data-form-collection="add"]').on('click', function(){
|
||||
$('#rules a[data-form-collection="add"]').on('click', function () {
|
||||
setTimeout(function(){
|
||||
$('select[name^="sylius_promotion[rules]"][name$="[type]"]').last().change();
|
||||
}, 50);
|
||||
});
|
||||
|
||||
$(document).on('collection-form-update', function () {
|
||||
$.each($('.sylius-autocomplete'), function (index, element) {
|
||||
if ($._data($(element).get(0), 'events') == undefined) {
|
||||
$(element).autoComplete();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$('.sylius-tabular-form').addTabErrors();
|
||||
$('.ui.accordion').addAccordionErrors();
|
||||
$('#sylius-product-taxonomy-tree').choiceTree('productTaxon', true, 1);
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
{% block title %}{{ parent() }} {{ header|trans }}{% endblock %}
|
||||
|
||||
{% form_theme form 'SyliusUiBundle:Form:theme.html.twig' %}
|
||||
{% form_theme form '@SyliusAdmin/Form/theme.html.twig' %}
|
||||
|
||||
{% block content %}
|
||||
{% include '@SyliusAdmin/Crud/Create/_header.html.twig' %}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
{% block title %}{{ parent() }} {{ header|trans }}{% endblock %}
|
||||
|
||||
{% form_theme form 'SyliusUiBundle:Form:theme.html.twig' %}
|
||||
{% form_theme form '@SyliusAdmin/Form/theme.html.twig' %}
|
||||
|
||||
{% block content %}
|
||||
{% include '@SyliusAdmin/Crud/Update/_header.html.twig' %}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
{% extends '@SyliusUi/Form/theme.html.twig' %}
|
||||
|
||||
{% block _sylius_promotion_rules_entry_configuration_entry_taxon_row %}
|
||||
{{ form_row(form, {'remote_url': path('sylius_admin_ajax_taxon_by_name_phrase'), 'remote_criteria_type': 'contains', 'remote_criteria_name': 'phrase', 'load_edit_url': path('sylius_admin_ajax_taxon_by_code')}) }}
|
||||
{% endblock %}
|
||||
|
||||
{% block _sylius_promotion_rules_entry_configuration_taxons_row %}
|
||||
{{ form_row(form, {'remote_url': path('sylius_admin_ajax_taxon_by_name_phrase'), 'remote_criteria_type': 'contains', 'remote_criteria_name': 'phrase', 'load_edit_url': path('sylius_admin_ajax_taxon_by_code')}) }}
|
||||
{% endblock %}
|
||||
|
||||
{% block _sylius_promotion_actions_entry_configuration_entry_filters_taxons_filter_taxons_row %}
|
||||
{{ form_row(form, {'remote_url': path('sylius_admin_ajax_taxon_by_name_phrase'), 'remote_criteria_type': 'contains', 'remote_criteria_name': 'phrase', 'load_edit_url': path('sylius_admin_ajax_taxon_by_code')}) }}
|
||||
{% endblock %}
|
||||
|
||||
{% block _sylius_promotion_rules_entry_configuration_product_code_row %}
|
||||
{{ form_row(form, {'remote_url': path('sylius_admin_ajax_product_by_name_phrase'), 'remote_criteria_type': 'contains', 'remote_criteria_name': 'phrase', 'load_edit_url': path('sylius_admin_ajax_product_by_code')}) }}
|
||||
{% endblock %}
|
||||
|
||||
{% block _sylius_promotion_actions_entry_configuration_entry_filters_products_filter_products_row %}
|
||||
{{ form_row(form, {'remote_url': path('sylius_admin_ajax_product_by_name_phrase'), 'remote_criteria_type': 'contains', 'remote_criteria_name': 'phrase', 'load_edit_url': path('sylius_admin_ajax_product_by_code')}) }}
|
||||
{% endblock %}
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
{% for associationForm in form.associations %}
|
||||
<div class="field">
|
||||
{{ form_label(associationForm) }}
|
||||
{{- form_label(associationForm) -}}
|
||||
<div class="product-select ui fluid multiple search selection dropdown" data-url="{{ path('sylius_admin_ajax_product_index') }}">
|
||||
{{ form_widget(associationForm, {'attr': {'class' : 'autocomplete'}}) }}
|
||||
<i class="dropdown icon"></i>
|
||||
|
|
@ -18,6 +18,7 @@
|
|||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{{ form_errors(associationForm) }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ final class BuildChannelBasedPromotionActionFormSubscriber extends AbstractConfi
|
|||
$configurationCollection = $this->factory->createNamed('configuration', PromotionConfigurationType::class, [], [
|
||||
'compound' => true,
|
||||
'auto_initialize' => false,
|
||||
'error_bubbling' => false,
|
||||
]);
|
||||
|
||||
/** @var ChannelInterface $channel */
|
||||
|
|
@ -107,6 +108,9 @@ final class BuildChannelBasedPromotionActionFormSubscriber extends AbstractConfi
|
|||
'auto_initialize' => false,
|
||||
'label' => $channel->getName(),
|
||||
'currency' => $channel->getBaseCurrency()->getCode(),
|
||||
'property_path' => '[' . $channel->getCode() . ']',
|
||||
'block_name' => 'entry',
|
||||
'error_bubbling' => false,
|
||||
];
|
||||
|
||||
$data = array_key_exists($channel->getCode(), $data) ? $data[$channel->getCode()] : [];
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ use Sylius\Component\Core\Model\ChannelInterface;
|
|||
use Sylius\Component\Core\Promotion\Checker\Rule\ChannelBasedRuleCheckerInterface;
|
||||
use Sylius\Component\Promotion\Model\PromotionRuleInterface;
|
||||
use Sylius\Component\Registry\ServiceRegistryInterface;
|
||||
use Symfony\Component\Form\FormFactoryIntegrface;
|
||||
use Symfony\Component\Form\FormFactoryInterface;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
|
||||
|
|
@ -68,6 +67,7 @@ final class BuildChannelBasedPromotionRuleFormSubscriber extends AbstractConfigu
|
|||
$configurationCollection = $this->factory->createNamed('configuration', PromotionConfigurationType::class, [], [
|
||||
'compound' => true,
|
||||
'auto_initialize' => false,
|
||||
'error_bubbling' => false,
|
||||
]);
|
||||
|
||||
/** @var ChannelInterface $channel */
|
||||
|
|
@ -108,6 +108,9 @@ final class BuildChannelBasedPromotionRuleFormSubscriber extends AbstractConfigu
|
|||
'auto_initialize' => false,
|
||||
'label' => $channel->getName(),
|
||||
'currency' => $channel->getBaseCurrency()->getCode(),
|
||||
'property_path' => '[' . $channel->getCode() . ']',
|
||||
'block_name' => 'entry',
|
||||
'error_bubbling' => false,
|
||||
];
|
||||
|
||||
$data = array_key_exists($channel->getCode(), $data) ? $data[$channel->getCode()] : [];
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@
|
|||
namespace Sylius\Bundle\CoreBundle\Form\Extension;
|
||||
|
||||
use Sylius\Bundle\CoreBundle\Form\EventSubscriber\BuildChannelBasedPromotionRuleFormSubscriber;
|
||||
use Sylius\Bundle\PromotionBundle\Form\Type\Core\AbstractConfigurationType;
|
||||
use Sylius\Bundle\PromotionBundle\Form\Type\PromotionRuleChoiceType;
|
||||
use Sylius\Bundle\PromotionBundle\Form\Type\PromotionRuleType;
|
||||
use Sylius\Component\Channel\Repository\ChannelRepositoryInterface;
|
||||
|
|
|
|||
|
|
@ -11,8 +11,7 @@
|
|||
|
||||
namespace Sylius\Bundle\CoreBundle\Form\Type\Promotion\Filter;
|
||||
|
||||
use Sylius\Bundle\ProductBundle\Form\Type\ProductChoiceType;
|
||||
use Sylius\Component\Core\Repository\ProductRepositoryInterface;
|
||||
use Sylius\Bundle\ResourceBundle\Form\Type\ResourceAutocompleteChoiceType;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\DataTransformerInterface;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
|
@ -41,10 +40,12 @@ final class ProductFilterConfigurationType extends AbstractType
|
|||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder
|
||||
->add('products', ProductChoiceType::class, [
|
||||
->add('products', ResourceAutocompleteChoiceType::class, [
|
||||
'label' => 'sylius.form.promotion_filter.products',
|
||||
'resource' => 'sylius.product',
|
||||
'choice_name' => 'name',
|
||||
'choice_value' => 'code',
|
||||
'multiple' => true,
|
||||
'required' => false,
|
||||
])
|
||||
;
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
namespace Sylius\Bundle\CoreBundle\Form\Type\Promotion\Filter;
|
||||
|
||||
use Sylius\Bundle\TaxonomyBundle\Form\Type\TaxonChoiceType;
|
||||
use Sylius\Bundle\ResourceBundle\Form\Type\ResourceAutocompleteChoiceType;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\DataTransformerInterface;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
|
@ -41,10 +41,13 @@ final class TaxonFilterConfigurationType extends AbstractType
|
|||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder
|
||||
->add('taxons', TaxonChoiceType::class, [
|
||||
->add('taxons', ResourceAutocompleteChoiceType::class, [
|
||||
'label' => 'sylius.form.promotion_filter.taxons',
|
||||
'multiple' => true,
|
||||
'required' => false,
|
||||
'resource' => 'sylius.taxon',
|
||||
'choice_name' => 'name',
|
||||
'choice_value' => 'code',
|
||||
])
|
||||
;
|
||||
|
||||
|
|
|
|||
|
|
@ -11,9 +11,12 @@
|
|||
|
||||
namespace Sylius\Bundle\CoreBundle\Form\Type\Promotion\Rule;
|
||||
|
||||
use Sylius\Bundle\ProductBundle\Form\Type\ProductCodeChoiceType;
|
||||
use Sylius\Bundle\ResourceBundle\Form\DataTransformer\ResourceToIdentifierTransformer;
|
||||
use Sylius\Bundle\ResourceBundle\Form\Type\ResourceAutocompleteChoiceType;
|
||||
use Sylius\Component\Resource\Repository\RepositoryInterface;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\ReversedTransformer;
|
||||
use Symfony\Component\Validator\Constraints\NotBlank;
|
||||
use Symfony\Component\Validator\Constraints\Type;
|
||||
|
||||
|
|
@ -23,20 +26,38 @@ use Symfony\Component\Validator\Constraints\Type;
|
|||
*/
|
||||
final class ContainsProductConfigurationType extends AbstractType
|
||||
{
|
||||
/**
|
||||
* @var RepositoryInterface
|
||||
*/
|
||||
private $productRepository;
|
||||
|
||||
/**
|
||||
* @param RepositoryInterface $productRepository
|
||||
*/
|
||||
public function __construct(RepositoryInterface $productRepository)
|
||||
{
|
||||
$this->productRepository = $productRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder
|
||||
->add('product_code', ProductCodeChoiceType::class, [
|
||||
->add('product_code', ResourceAutocompleteChoiceType::class, [
|
||||
'label' => 'sylius.form.promotion_action.add_product_configuration.product',
|
||||
'resource' => 'sylius.product',
|
||||
'choice_name' => 'name',
|
||||
'choice_value' => 'code',
|
||||
'constraints' => [
|
||||
new NotBlank(['groups' => ['sylius']]),
|
||||
new Type(['type' => 'string', 'groups' => ['sylius']]),
|
||||
],
|
||||
])
|
||||
;
|
||||
|
||||
$builder->get('product_code')->addModelTransformer(new ReversedTransformer(new ResourceToIdentifierTransformer($this->productRepository, 'code')));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
namespace Sylius\Bundle\CoreBundle\Form\Type\Promotion\Rule;
|
||||
|
||||
use Sylius\Bundle\TaxonomyBundle\Form\Type\TaxonChoiceType;
|
||||
use Sylius\Bundle\ResourceBundle\Form\Type\ResourceAutocompleteChoiceType;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\DataTransformerInterface;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
|
@ -40,9 +40,12 @@ final class HasTaxonConfigurationType extends AbstractType
|
|||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder
|
||||
->add('taxons', TaxonChoiceType::class, [
|
||||
->add('taxons', ResourceAutocompleteChoiceType::class, [
|
||||
'label' => 'sylius.form.promotion_rule.has_taxon.taxons',
|
||||
'resource' => 'sylius.taxon',
|
||||
'multiple' => true,
|
||||
'choice_name' => 'name',
|
||||
'choice_value' => 'code',
|
||||
])
|
||||
;
|
||||
|
||||
|
|
|
|||
|
|
@ -12,9 +12,12 @@
|
|||
namespace Sylius\Bundle\CoreBundle\Form\Type\Promotion\Rule;
|
||||
|
||||
use Sylius\Bundle\MoneyBundle\Form\Type\MoneyType;
|
||||
use Sylius\Bundle\TaxonomyBundle\Form\Type\TaxonCodeChoiceType;
|
||||
use Sylius\Bundle\ResourceBundle\Form\DataTransformer\ResourceToIdentifierTransformer;
|
||||
use Sylius\Bundle\ResourceBundle\Form\Type\ResourceAutocompleteChoiceType;
|
||||
use Sylius\Component\Resource\Repository\RepositoryInterface;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\Form\ReversedTransformer;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
/**
|
||||
|
|
@ -22,20 +25,39 @@ use Symfony\Component\OptionsResolver\OptionsResolver;
|
|||
*/
|
||||
final class TotalOfItemsFromTaxonConfigurationType extends AbstractType
|
||||
{
|
||||
/**
|
||||
* @var RepositoryInterface
|
||||
*/
|
||||
private $taxonRepository;
|
||||
|
||||
/**
|
||||
* @param RepositoryInterface $taxonRepository
|
||||
*/
|
||||
public function __construct(RepositoryInterface $taxonRepository)
|
||||
{
|
||||
$this->taxonRepository = $taxonRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder
|
||||
->add('taxon', TaxonCodeChoiceType::class, [
|
||||
->add('taxon', ResourceAutocompleteChoiceType::class, [
|
||||
'label' => 'sylius.form.promotion_rule.total_of_items_from_taxon.taxon',
|
||||
'resource' => 'sylius.taxon',
|
||||
'multiple' => false,
|
||||
'choice_name' => 'name',
|
||||
'choice_value' => 'code',
|
||||
])
|
||||
->add('amount', MoneyType::class, [
|
||||
'label' => 'sylius.form.promotion_rule.total_of_items_from_taxon.amount',
|
||||
'currency' => $options['currency'],
|
||||
])
|
||||
;
|
||||
|
||||
$builder->get('taxon')->addModelTransformer(new ReversedTransformer(new ResourceToIdentifierTransformer($this->taxonRepository, 'code')));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -156,9 +156,11 @@
|
|||
<tag name="form.type" />
|
||||
</service>
|
||||
<service id="sylius.form.type.promotion_rule.total_of_items_from_taxon_configuration" class="Sylius\Bundle\CoreBundle\Form\Type\Promotion\Rule\TotalOfItemsFromTaxonConfigurationType">
|
||||
<argument type="service" id="sylius.repository.taxon" />
|
||||
<tag name="form.type" />
|
||||
</service>
|
||||
<service id="sylius.form.type.promotion_rule.contains_product_configuration" class="Sylius\Bundle\CoreBundle\Form\Type\Promotion\Rule\ContainsProductConfigurationType">
|
||||
<argument type="service" id="sylius.repository.product" />
|
||||
<tag name="form.type" />
|
||||
</service>
|
||||
<service id="sylius.form.type.promotion.configuration" class="Sylius\Bundle\CoreBundle\Form\Type\Promotion\PromotionConfigurationType" />
|
||||
|
|
|
|||
|
|
@ -26,13 +26,27 @@ class ProductRepository extends EntityRepository implements ProductRepositoryInt
|
|||
public function findByName($name, $locale)
|
||||
{
|
||||
return $this->createQueryBuilder('o')
|
||||
->innerJoin('o.translations', 'translation')
|
||||
->innerJoin('o.translations', 'translation', 'WITH', 'translation.locale = :locale')
|
||||
->andWhere('translation.name = :name')
|
||||
->andWhere('translation.locale = :locale')
|
||||
->setParameter('name', $name)
|
||||
->setParameter('locale', $locale)
|
||||
->getQuery()
|
||||
->getResult()
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function findByNamePart($phrase, $locale)
|
||||
{
|
||||
return $this->createQueryBuilder('o')
|
||||
->innerJoin('o.translations', 'translation', 'WITH', 'translation.locale = :locale')
|
||||
->andWhere('translation.name LIKE :name')
|
||||
->setParameter('name', '%'.$phrase.'%')
|
||||
->setParameter('locale', $locale)
|
||||
->getQuery()
|
||||
->getResult()
|
||||
;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,11 +6,11 @@ Sylius\Component\Product\Model\Product:
|
|||
expose: true
|
||||
type: integer
|
||||
xml_attribute: true
|
||||
groups: [Default, Detailed]
|
||||
groups: [Default, Detailed, Autocomplete]
|
||||
code:
|
||||
expose: true
|
||||
type: string
|
||||
groups: [Default, Detailed]
|
||||
groups: [Default, Detailed, Autocomplete]
|
||||
options:
|
||||
expose: true
|
||||
type: array
|
||||
|
|
@ -30,6 +30,7 @@ Sylius\Component\Product\Model\Product:
|
|||
virtual_properties:
|
||||
getName:
|
||||
serialized_name: name
|
||||
groups: [Default, Detailed, Autocomplete]
|
||||
relations:
|
||||
- rel: self
|
||||
href:
|
||||
|
|
|
|||
|
|
@ -129,7 +129,7 @@ abstract class AbstractConfigurationSubscriber implements EventSubscriberInterfa
|
|||
}
|
||||
|
||||
/**
|
||||
* @param PromotionDynamicTypeInterface|null $type
|
||||
* @param PromotionDynamicTypeInterface|null $modelType
|
||||
* @param FormInterface $form
|
||||
*
|
||||
* @return null|string
|
||||
|
|
|
|||
|
|
@ -80,6 +80,7 @@ abstract class AbstractConfigurationCollectionType extends AbstractType
|
|||
'allow_add' => true,
|
||||
'allow_delete' => true,
|
||||
'by_reference' => false,
|
||||
'error_bubbling' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,10 +11,7 @@
|
|||
|
||||
namespace Sylius\Bundle\PromotionBundle\Form\Type;
|
||||
|
||||
use Sylius\Bundle\PromotionBundle\Form\EventListener\BuildPromotionActionFormSubscriber;
|
||||
use Sylius\Bundle\PromotionBundle\Form\Type\Core\AbstractConfigurationType;
|
||||
use Sylius\Bundle\ResourceBundle\Form\Type\AbstractResourceType;
|
||||
use Sylius\Component\Registry\ServiceRegistryInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
|
|
|||
|
|
@ -11,11 +11,8 @@
|
|||
|
||||
namespace Sylius\Bundle\PromotionBundle\Form\Type;
|
||||
|
||||
use Sylius\Bundle\PromotionBundle\Form\EventListener\BuildPromotionRuleFormSubscriber;
|
||||
use Sylius\Bundle\PromotionBundle\Form\Type\Core\AbstractConfigurationType;
|
||||
use Sylius\Bundle\ResourceBundle\Form\Type\AbstractResourceType;
|
||||
use Sylius\Component\Promotion\Checker\Rule\ItemTotalRuleChecker;
|
||||
use Sylius\Component\Registry\ServiceRegistryInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
|
@ -39,7 +36,6 @@ final class PromotionRuleType extends AbstractResourceType
|
|||
public function __construct(
|
||||
$dataClass,
|
||||
array $validationGroups,
|
||||
ServiceRegistryInterface $registry,
|
||||
EventSubscriberInterface $buildRuleSubscriber
|
||||
) {
|
||||
parent::__construct($dataClass, $validationGroups);
|
||||
|
|
|
|||
|
|
@ -44,7 +44,6 @@
|
|||
<service id="sylius.form.type.promotion_rule" class="Sylius\Bundle\PromotionBundle\Form\Type\PromotionRuleType">
|
||||
<argument>%sylius.model.promotion_rule.class%</argument>
|
||||
<argument>%sylius.form.type.promotion_rule.validation_groups%</argument>
|
||||
<argument type="service" id="sylius.registry_promotion_rule_checker" />
|
||||
<argument type="service" id="sylius.form.event_subscriber.build_promotion_rule" />
|
||||
<tag name="form.type" />
|
||||
</service>
|
||||
|
|
|
|||
|
|
@ -58,5 +58,8 @@
|
|||
<property name="actions">
|
||||
<constraint name="Valid" />
|
||||
</property>
|
||||
<property name="rules">
|
||||
<constraint name="Valid" />
|
||||
</property>
|
||||
</class>
|
||||
</constraint-mapping>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!--
|
||||
|
||||
This file is part of the Sylius package.
|
||||
|
||||
(c) Paweł Jędrzejewski
|
||||
|
||||
For the full copyright and license information, please view the LICENSE
|
||||
file that was distributed with this source code.
|
||||
|
||||
-->
|
||||
|
||||
<constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping http://symfony.com/schema/dic/services/constraint-mapping-1.0.xsd">
|
||||
<class name="Sylius\Component\Promotion\Model\PromotionRule">
|
||||
<property name="configuration">
|
||||
<constraint name="Valid" />
|
||||
</property>
|
||||
</class>
|
||||
</constraint-mapping>
|
||||
|
|
@ -94,6 +94,7 @@ class ResourceAutocompleteChoiceType extends AbstractType
|
|||
])
|
||||
->setDefaults([
|
||||
'multiple' => false,
|
||||
'error_bubbling' => false,
|
||||
'placeholder' => '',
|
||||
'repository' => function (Options $options) {
|
||||
return $this->resourceRepositoryRegistry->get($options['resource']);
|
||||
|
|
|
|||
|
|
@ -203,9 +203,10 @@
|
|||
data-criteria-name="{{ remote_criteria_name }}"
|
||||
data-load-edit-url="{{ load_edit_url }}"
|
||||
>
|
||||
{{ form_row(form, {'attr': {'class' : 'autocomplete'}}) }}
|
||||
{{ form_widget(form, {'attr': {'class' : 'autocomplete'}}) }}
|
||||
<i class="dropdown icon"></i>
|
||||
<div class="default text">{% if placeholder is defined %} {{ placeholder|trans }} {% endif %}</div>
|
||||
<div class="menu"></div>
|
||||
</div>
|
||||
{{ form_errors(form) }}
|
||||
{% endblock %}
|
||||
|
|
|
|||
|
|
@ -26,4 +26,12 @@ interface ProductRepositoryInterface extends RepositoryInterface
|
|||
* @return ProductInterface[]
|
||||
*/
|
||||
public function findByName($name, $locale);
|
||||
|
||||
/**
|
||||
* @param string $phrase
|
||||
* @param string $locale
|
||||
*
|
||||
* @return ProductInterface[]
|
||||
*/
|
||||
public function findByNamePart($phrase, $locale);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -357,15 +357,10 @@ EOT;
|
|||
"max": 12000
|
||||
},
|
||||
"taxons_filter": {
|
||||
"taxons": [
|
||||
"mugs"
|
||||
]
|
||||
"taxons": "mugs"
|
||||
},
|
||||
"products_filter": {
|
||||
"products": [
|
||||
"MUG_SW",
|
||||
"MUG_LOTR"
|
||||
]
|
||||
"products": "MUG_SW,MUG_LOTR"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -373,9 +368,7 @@ EOT;
|
|||
"percentage": 20,
|
||||
"filters": {
|
||||
"products_filter": {
|
||||
"products": [
|
||||
"MUG_SW"
|
||||
]
|
||||
"products": "MUG_SW"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -395,13 +388,13 @@ EOT;
|
|||
]
|
||||
}
|
||||
EOT;
|
||||
|
||||
$this->client->request('POST', '/api/v1/promotions/', [], [], static::$authorizedHeaderWithContentType, $data);
|
||||
|
||||
$response = $this->client->getResponse();
|
||||
$this->assertResponse($response, 'promotion/create_response_with_actions', Response::HTTP_CREATED);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
|
|
@ -457,7 +450,8 @@ EOT;
|
|||
$data =
|
||||
<<<EOT
|
||||
{
|
||||
"name": "Monday promotion"
|
||||
"name": "Monday promotion",
|
||||
"priority": 0
|
||||
}
|
||||
EOT;
|
||||
$this->client->request('PUT', $this->getPromotionUrl($promotion), [], [], static::$authorizedHeaderWithContentType, $data);
|
||||
|
|
@ -483,8 +477,7 @@ EOT;
|
|||
$data =
|
||||
<<<EOT
|
||||
{
|
||||
"exclusive": true,
|
||||
"priority": 0
|
||||
"exclusive": true
|
||||
}
|
||||
EOT;
|
||||
$this->client->request('PATCH', $this->getPromotionUrl($promotion), [], [], static::$authorizedHeaderWithContentType, $data);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ Sylius\Component\Core\Model\Channel:
|
|||
description: "Lorem ipsum"
|
||||
baseCurrency: "@currency1"
|
||||
defaultLocale: "@locale"
|
||||
locales: ["@locale"]
|
||||
color: "black"
|
||||
enabled: true
|
||||
taxCalculationStrategy: "order_items_based"
|
||||
|
|
@ -16,6 +17,7 @@ Sylius\Component\Core\Model\Channel:
|
|||
description: "Lorem ipsum psore"
|
||||
baseCurrency: "@currency2"
|
||||
defaultLocale: "@locale"
|
||||
locales: ["@locale"]
|
||||
color: "yellow"
|
||||
enabled: true
|
||||
taxCalculationStrategy: "order_items_based"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue