mirror of
https://github.com/Sylius/Sylius.git
synced 2026-07-15 01:20:59 +00:00
Merge pull request #6607 from Arminek/moving-taxon-leafs
[Taxon] Changing order of the taxon
This commit is contained in:
commit
1202e0dd5c
22 changed files with 543 additions and 50 deletions
72
app/migrations/Version20161102145826.php
Normal file
72
app/migrations/Version20161102145826.php
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
<?php
|
||||
|
||||
namespace Sylius\Migrations;
|
||||
|
||||
use Doctrine\DBAL\Migrations\AbstractMigration;
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Sylius\Component\Core\Model\TaxonInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
class Version20161102145826 extends AbstractMigration implements ContainerAwareInterface
|
||||
{
|
||||
/**
|
||||
* @var ContainerInterface
|
||||
*/
|
||||
private $container;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function setContainer(ContainerInterface $container = null)
|
||||
{
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Schema $schema
|
||||
*/
|
||||
public function postUp(Schema $schema)
|
||||
{
|
||||
$rootNodes = $this->container->get('sylius.repository.taxon')->findRootNodes();
|
||||
$this->updatePosition($rootNodes);
|
||||
$this->container->get('sylius.manager.taxon')->flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Schema $schema
|
||||
*/
|
||||
public function up(Schema $schema)
|
||||
{
|
||||
$this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.');
|
||||
|
||||
$this->addSql('ALTER TABLE sylius_taxon ADD position INT NOT NULL');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Schema $schema
|
||||
*/
|
||||
public function down(Schema $schema)
|
||||
{
|
||||
$this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.');
|
||||
|
||||
$this->addSql('ALTER TABLE sylius_taxon DROP position');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $rootNodes
|
||||
*/
|
||||
private function updatePosition($rootNodes)
|
||||
{
|
||||
/** @var TaxonInterface $rootNode */
|
||||
foreach ($rootNodes as $key => $rootNode) {
|
||||
$rootNode->setPosition($key);
|
||||
if (!$rootNode->getChildren()->isEmpty()) {
|
||||
$this->updatePosition($rootNode->getChildren());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7,9 +7,8 @@ Feature: Deleting a taxon
|
|||
Background:
|
||||
Given I am logged in as an administrator
|
||||
|
||||
@ui
|
||||
@ui @javascript
|
||||
Scenario: Deleted taxon should disappear from the registry
|
||||
Given the store classifies its products as "T-Shirts"
|
||||
When I delete taxon named "T-Shirts"
|
||||
Then I should be notified that it has been successfully deleted
|
||||
And the taxon named "T-Shirts" should no longer exist in the registry
|
||||
Then the taxon named "T-Shirts" should no longer exist in the registry
|
||||
|
|
|
|||
24
features/taxonomy/managing_taxons/reordering_taxon.feature
Normal file
24
features/taxonomy/managing_taxons/reordering_taxon.feature
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
@managing_taxons
|
||||
Feature: Reordering taxons
|
||||
In order to see all ordered taxons in the store
|
||||
As an Administrator
|
||||
I want to browse ordered taxons
|
||||
|
||||
Background:
|
||||
Given the store classifies its products as "T-Shirts", "Watches", "Belts" and "Wallets"
|
||||
And I am logged in as an administrator
|
||||
|
||||
@ui @javascript
|
||||
Scenario: Changing order of the taxon
|
||||
When I want to see all taxons in store
|
||||
And I move up "Watches" taxon
|
||||
Then I should see 4 taxons on the list
|
||||
And I should see the taxon named "T-Shirts" in the list
|
||||
But the first taxon on the list should be "Watches"
|
||||
|
||||
@ui @javascript
|
||||
Scenario: Changing order of the taxons by dragging
|
||||
When I want to see all taxons in store
|
||||
And I move "Wallets" taxon before "T-shirts" taxon
|
||||
Then I should see 4 taxons on the list
|
||||
And they should have order like "Wallets", "T-Shirts", "Watches" and "Belts"
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
{
|
||||
"dependencies": {
|
||||
"jquery": "^2.2.0",
|
||||
"semantic-ui-css": "^2.2.0"
|
||||
"semantic-ui-css": "^2.2.0",
|
||||
"sortablejs": "^1.4.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"gulp": "^3.9.0",
|
||||
|
|
@ -15,6 +16,7 @@
|
|||
"gulp-sourcemaps": "^1.6.0",
|
||||
"gulp-uglify": "^1.5.1",
|
||||
"gulp-uglifycss": "^1.0.5",
|
||||
"jquery-simulate-ext": "^1.3.0",
|
||||
"merge-stream": "^1.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
|
|
|
|||
|
|
@ -154,6 +154,22 @@ final class ManagingTaxonsContext implements Context
|
|||
$this->createPage->describeItAs($description, $language);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When /^I move up ("[^"]+" taxon)$/
|
||||
*/
|
||||
public function iWantToMoveUpTaxon(TaxonInterface $taxon)
|
||||
{
|
||||
$this->createPage->moveUp($taxon);
|
||||
}
|
||||
|
||||
/**
|
||||
* @When /^I move ("[^"]+" taxon) before ("[^"]+" taxon)$/
|
||||
*/
|
||||
public function iMoveTaxonBeforeTaxon(TaxonInterface $taxonToMove, TaxonInterface $targetTaxon)
|
||||
{
|
||||
$this->createPage->insertBefore($taxonToMove, $targetTaxon);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given /^I choose ("[^"]+" as a parent taxon)$/
|
||||
*/
|
||||
|
|
@ -478,4 +494,32 @@ final class ManagingTaxonsContext implements Context
|
|||
'Image code must be unique within this taxon.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then the first taxon on the list should be :taxon
|
||||
*/
|
||||
public function theFirstTaxonOnTheListShouldBe(TaxonInterface $taxon)
|
||||
{
|
||||
Assert::same(
|
||||
$this->createPage->getFirstLeafName(),
|
||||
$taxon->getName(),
|
||||
sprintf(
|
||||
'Expected %s as a first taxon, but got %s.',
|
||||
$taxon->getName(),
|
||||
$this->createPage->getFirstLeafName()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Then they should have order like :firstTaxonName, :secondTaxonName, :thirdTaxonName and :fourthTaxonName
|
||||
*/
|
||||
public function theyShouldHaveOrderLikeAnd(...$taxonsNames)
|
||||
{
|
||||
$leaves = $this->createPage->getLeaves();
|
||||
|
||||
foreach ($leaves as $key => $leaf) {
|
||||
Assert::contains($taxonsNames[$key], $leaf->getText());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,8 +11,10 @@
|
|||
|
||||
namespace Sylius\Behat\Page\Admin\Taxon;
|
||||
|
||||
use Behat\Mink\Driver\Selenium2Driver;
|
||||
use Behat\Mink\Element\NodeElement;
|
||||
use Behat\Mink\Exception\ElementNotFoundException;
|
||||
use Behat\Mink\Exception\UnsupportedDriverActionException;
|
||||
use Sylius\Behat\Behaviour\SpecifiesItsCode;
|
||||
use Sylius\Behat\Page\Admin\Crud\CreatePage as BaseCreatePage;
|
||||
use Sylius\Component\Core\Model\TaxonInterface;
|
||||
|
|
@ -30,7 +32,7 @@ class CreatePage extends BaseCreatePage implements CreatePageInterface
|
|||
*/
|
||||
public function countTaxons()
|
||||
{
|
||||
return count($this->getLeafs());
|
||||
return count($this->getLeaves());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -38,15 +40,15 @@ class CreatePage extends BaseCreatePage implements CreatePageInterface
|
|||
*/
|
||||
public function countTaxonsByName($name)
|
||||
{
|
||||
$matchedLeafsCounter = 0;
|
||||
$leafs = $this->getLeafs();
|
||||
foreach ($leafs as $leaf) {
|
||||
if ($leaf->getText() === $name) {
|
||||
$matchedLeafsCounter++;
|
||||
$matchedLeavesCounter = 0;
|
||||
$leaves = $this->getLeaves();
|
||||
foreach ($leaves as $leaf) {
|
||||
if (strpos($leaf->getText(), $name) !== false) {
|
||||
$matchedLeavesCounter++;
|
||||
}
|
||||
}
|
||||
|
||||
return $matchedLeafsCounter;
|
||||
return $matchedLeavesCounter;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -62,10 +64,18 @@ class CreatePage extends BaseCreatePage implements CreatePageInterface
|
|||
*/
|
||||
public function deleteTaxonOnPageByName($name)
|
||||
{
|
||||
$leafs = $this->getLeafs();
|
||||
foreach ($leafs as $leaf) {
|
||||
$leaves = $this->getLeaves();
|
||||
foreach ($leaves as $leaf) {
|
||||
if ($leaf->getText() === $name) {
|
||||
$leaf->getParent()->find('css', '.ui.red.button')->press();
|
||||
$leaf = $leaf->getParent();
|
||||
$menuButton = $leaf->find('css', '.wrench');
|
||||
$menuButton->click();
|
||||
$deleteButton = $leaf->find('css', '.sylius-delete-resource');
|
||||
$deleteButton->click();
|
||||
|
||||
$deleteButton->waitFor(5, function () {
|
||||
return false;
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
@ -120,6 +130,75 @@ class CreatePage extends BaseCreatePage implements CreatePageInterface
|
|||
$imageForm->find('css', 'input[type="file"]')->attachFile($filesPath.$path);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function moveUp(TaxonInterface $taxon)
|
||||
{
|
||||
$this->moveLeaf($taxon, self::MOVE_DIRECTION_UP);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function moveDown(TaxonInterface $taxon)
|
||||
{
|
||||
$this->moveLeaf($taxon, self::MOVE_DIRECTION_DOWN);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getFirstLeafName(TaxonInterface $parentTaxon = null)
|
||||
{
|
||||
return $this->getLeaves($parentTaxon)[0]->getText();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function insertBefore(TaxonInterface $draggableTaxon, TaxonInterface $targetTaxon)
|
||||
{
|
||||
$seleniumDriver = $this->getSeleniumDriver();
|
||||
$draggableTaxonLocator = sprintf('.item[data-id="%s"]', $draggableTaxon->getId());
|
||||
$targetTaxonLocator = sprintf('.item[data-id="%s"]', $targetTaxon->getId());
|
||||
|
||||
$script = <<<JS
|
||||
(function ($) {
|
||||
$('$draggableTaxonLocator').simulate('drag-n-drop',{
|
||||
dragTarget: $('$targetTaxonLocator'),
|
||||
interpolation: {stepWidth: 10, stepDelay: 30}
|
||||
});
|
||||
})(jQuery);
|
||||
JS;
|
||||
|
||||
$seleniumDriver->executeScript($script);
|
||||
$this->getDocument()->waitFor(5, function () {
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getLeaves(TaxonInterface $parentTaxon = null)
|
||||
{
|
||||
$tree = $this->getElement('tree');
|
||||
Assert::notNull($tree);
|
||||
/** @var NodeElement[] $leaves */
|
||||
$leaves = $tree->findAll('css', '.item > .content > .header');
|
||||
|
||||
if (null === $parentTaxon) {
|
||||
return $leaves;
|
||||
}
|
||||
|
||||
foreach ($leaves as $leaf) {
|
||||
if ($leaf->getText() === $parentTaxon->getName()) {
|
||||
return $leaf->findAll('css', '.item > .content > .header');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
|
@ -137,16 +216,35 @@ class CreatePage extends BaseCreatePage implements CreatePageInterface
|
|||
}
|
||||
|
||||
/**
|
||||
* @return NodeElement[]
|
||||
* @param TaxonInterface $taxon
|
||||
* @param string $direction
|
||||
*
|
||||
* @throws ElementNotFoundException
|
||||
*/
|
||||
private function getLeafs()
|
||||
private function moveLeaf(TaxonInterface $taxon, $direction)
|
||||
{
|
||||
$tree = $this->getElement('tree');
|
||||
Assert::notNull($tree);
|
||||
Assert::oneOf($direction, [self::MOVE_DIRECTION_UP, self::MOVE_DIRECTION_DOWN]);
|
||||
|
||||
return $tree->findAll('css', '.item > .content > .header');
|
||||
$leaves = $this->getLeaves();
|
||||
foreach ($leaves as $leaf) {
|
||||
if ($leaf->getText() === $taxon->getName()) {
|
||||
$leaf = $leaf->getParent();
|
||||
$menuButton = $leaf->find('css', '.wrench');
|
||||
$menuButton->click();
|
||||
$moveButton = $leaf->find('css', sprintf('.%s', $direction));
|
||||
$moveButton->click();
|
||||
$moveButton->waitFor(5, function () use ($taxon) {
|
||||
return $this->getFirstLeafName() === $taxon->getName();
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throw new ElementNotFoundException(
|
||||
$this->getDriver(),
|
||||
sprintf('Move %s button for %s taxon', $direction, $taxon->getName())
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -161,4 +259,20 @@ class CreatePage extends BaseCreatePage implements CreatePageInterface
|
|||
|
||||
return end($items);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Selenium2Driver
|
||||
*
|
||||
* @throws UnsupportedDriverActionException
|
||||
*/
|
||||
private function getSeleniumDriver()
|
||||
{
|
||||
/** @var Selenium2Driver $driver */
|
||||
$driver = $this->getDriver();
|
||||
if (!$driver instanceof Selenium2Driver) {
|
||||
throw new UnsupportedDriverActionException('This action is not supported by %s', $driver);
|
||||
}
|
||||
|
||||
return $driver;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@
|
|||
|
||||
namespace Sylius\Behat\Page\Admin\Taxon;
|
||||
|
||||
use Behat\Mink\Element\NodeElement;
|
||||
use Behat\Mink\Exception\ElementNotFoundException;
|
||||
use Sylius\Behat\Page\Admin\Crud\CreatePageInterface as BaseCreatePageInterface;
|
||||
use Sylius\Component\Core\Model\TaxonInterface;
|
||||
|
||||
|
|
@ -19,6 +21,9 @@ use Sylius\Component\Core\Model\TaxonInterface;
|
|||
*/
|
||||
interface CreatePageInterface extends BaseCreatePageInterface
|
||||
{
|
||||
const MOVE_DIRECTION_UP = 'up';
|
||||
const MOVE_DIRECTION_DOWN = 'down';
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
|
|
@ -76,4 +81,36 @@ interface CreatePageInterface extends BaseCreatePageInterface
|
|||
* @param string $code
|
||||
*/
|
||||
public function attachImage($path, $code = null);
|
||||
|
||||
/**
|
||||
* @param TaxonInterface $taxon
|
||||
*/
|
||||
public function moveUp(TaxonInterface $taxon);
|
||||
|
||||
/**
|
||||
* @param TaxonInterface $taxon
|
||||
*/
|
||||
public function moveDown(TaxonInterface $taxon);
|
||||
|
||||
/**
|
||||
* @param TaxonInterface|null $parentTaxon
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFirstLeafName(TaxonInterface $parentTaxon = null);
|
||||
|
||||
/**
|
||||
* @param TaxonInterface $draggableTaxon
|
||||
* @param TaxonInterface $targetTaxon
|
||||
*/
|
||||
public function insertBefore(TaxonInterface $draggableTaxon, TaxonInterface $targetTaxon);
|
||||
|
||||
/**
|
||||
* @param TaxonInterface|null $parentTaxon
|
||||
*
|
||||
* @return NodeElement[]
|
||||
*
|
||||
* @throws ElementNotFoundException
|
||||
*/
|
||||
public function getLeaves(TaxonInterface $parentTaxon = null);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,12 +17,17 @@ var paths = {
|
|||
admin: {
|
||||
js: [
|
||||
'../../../../node_modules/jquery/dist/jquery.min.js',
|
||||
'../../../../node_modules/sortablejs/Sortable.js',
|
||||
'../../../../node_modules/sortablejs/jquery.binding.js',
|
||||
'../../../../node_modules/semantic-ui-css/semantic.min.js',
|
||||
'../PromotionBundle/Resources/public/js/sylius-promotion.js',
|
||||
'../ShippingBundle/Resources/public/js/**',
|
||||
'../UiBundle/Resources/private/js/**',
|
||||
'../UserBundle/Resources/public/js/sylius-user.js',
|
||||
'Resources/private/js/**'
|
||||
'Resources/private/js/**',
|
||||
'../../../../node_modules/jquery-simulate-ext/libs/jquery.simulate.js',
|
||||
'../../../../node_modules/jquery-simulate-ext/src/jquery.simulate.ext.js',
|
||||
'../../../../node_modules/jquery-simulate-ext/src/jquery.simulate.drag-n-drop.js'
|
||||
],
|
||||
sass: [
|
||||
'../UiBundle/Resources/private/sass/**'
|
||||
|
|
|
|||
|
|
@ -1,7 +1,3 @@
|
|||
sylius_admin_api_taxon:
|
||||
resource: "@SyliusAdminBundle/Resources/config/routing/api/taxon.yml"
|
||||
prefix: /taxons
|
||||
|
||||
sylius_admin_api_product:
|
||||
resource: "@SyliusAdminBundle/Resources/config/routing/api/product.yml"
|
||||
prefix: /products
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
sylius_admin_api_taxon_index:
|
||||
path: /
|
||||
methods: [GET]
|
||||
defaults:
|
||||
_controller: sylius.controller.taxon:indexAction
|
||||
_format: json
|
||||
_sylius:
|
||||
grid: sylius_admin_taxon
|
||||
|
|
@ -20,6 +20,14 @@ sylius_admin_taxon_index:
|
|||
route: sylius_admin_taxon_create
|
||||
permanent: true
|
||||
|
||||
sylius_admin_taxon_move:
|
||||
path: /taxons/{id}/move
|
||||
methods: [PUT]
|
||||
defaults:
|
||||
_controller: sylius.controller.taxon:updateAction
|
||||
_sylius:
|
||||
form: sylius_taxon_position
|
||||
|
||||
sylius_admin_taxon_create_for_parent:
|
||||
path: /taxons/new/{id}
|
||||
defaults:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
(function ($) {
|
||||
'use strict';
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
$('.sylius-delete-resource').api({
|
||||
method: 'delete',
|
||||
onSuccess: function (response) {
|
||||
var redirectUrl = $(this).data('success-redirect-url');
|
||||
|
||||
if (redirectUrl) {
|
||||
location.replace(redirectUrl);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
throw 'You need to define data-success-redirect-url on "' + $(this).attr('class') +'"';
|
||||
},
|
||||
onFailure: function (response) {
|
||||
var message = $(this).parent().parent().popup({
|
||||
inline: true,
|
||||
content: response.error.message,
|
||||
on: 'manual'
|
||||
});
|
||||
message.popup('show');
|
||||
setTimeout(function() { message.popup('hide'); }, 3000);
|
||||
}
|
||||
});
|
||||
});
|
||||
})( jQuery );
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
(function ($) {
|
||||
'use strict';
|
||||
|
||||
$(document).ready(function() {
|
||||
|
||||
$('.sylius-sortable-list').sortable({
|
||||
forceFallback: true,
|
||||
onEnd: function (event) {
|
||||
$(this).api({
|
||||
throttle: 500,
|
||||
method: 'PUT',
|
||||
action: 'move taxon',
|
||||
on: 'now',
|
||||
urlData: {
|
||||
id: $(event.item).data('id')
|
||||
},
|
||||
beforeSend: function (settings) {
|
||||
settings.data = {
|
||||
position: event.newIndex
|
||||
};
|
||||
|
||||
return settings;
|
||||
},
|
||||
onSuccess: function (response) {
|
||||
$(event.item).find('.sylius-taxon-move-up').data('position', event.newIndex);
|
||||
$(event.item).find('.sylius-taxon-move-down').data('position', event.newIndex);
|
||||
},
|
||||
onFailure: function (response) {
|
||||
throw 'Something went wrong with api call.';
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$('.sylius-taxon-move-up').api({
|
||||
method: 'PUT',
|
||||
on: 'click',
|
||||
beforeSend: function (settings) {
|
||||
settings.data = {
|
||||
position: $(this).data('position') - 1
|
||||
};
|
||||
|
||||
return settings;
|
||||
},
|
||||
onSuccess: function (response) {
|
||||
location.reload();
|
||||
}
|
||||
});
|
||||
|
||||
$('.sylius-taxon-move-down').api({
|
||||
method: 'PUT',
|
||||
on: 'click',
|
||||
beforeSend: function (settings) {
|
||||
settings.data = {
|
||||
position: $(this).data('position') + 1
|
||||
};
|
||||
|
||||
return settings;
|
||||
},
|
||||
onSuccess: function (response) {
|
||||
location.reload();
|
||||
}
|
||||
});
|
||||
});
|
||||
})( jQuery );
|
||||
|
|
@ -11,6 +11,7 @@
|
|||
'use strict';
|
||||
|
||||
$.fn.api.settings.api = {
|
||||
'get taxons' : '/admin/api/taxons'
|
||||
'get taxons': '/admin/taxons?_format=json',
|
||||
'move taxon': '/admin/taxons/{id}/move?_format=json'
|
||||
};
|
||||
})(jQuery);
|
||||
|
|
|
|||
|
|
@ -6,20 +6,40 @@
|
|||
{% import _self as tree %}
|
||||
|
||||
{% for taxon in taxons if taxon.id != null %}
|
||||
<div class="item">
|
||||
<div class="item" data-id="{{ taxon.id }}">
|
||||
<i class="folder icon"></i>
|
||||
<div class="content">
|
||||
<div class="header">
|
||||
<a href="{{ path('sylius_admin_product_index_per_taxon', {'taxonId': taxon.id}) }}">
|
||||
{{ taxon.name }}
|
||||
</a>
|
||||
<div class="ui inline dropdown icon button mini">
|
||||
<i class="wrench icon"></i>
|
||||
<div class="menu">
|
||||
<a class="item" href="{{ path('sylius_admin_taxon_create_for_parent', { 'id': taxon.id }) }}">
|
||||
<i class="plus icon"></i>
|
||||
{{ 'sylius.ui.add'|trans }}
|
||||
</a>
|
||||
<a class="item" href="{{ path('sylius_admin_taxon_update', { 'id': taxon.id }) }}">
|
||||
<i class="edit icon"></i>
|
||||
{{ 'sylius.ui.edit'|trans }}
|
||||
</a>
|
||||
<div class="item sylius-taxon-move-up" data-action="move taxon" data-id="{{ taxon.id }}" data-position="{{ taxon.position }}">
|
||||
<i class="icon arrow up"></i>
|
||||
{{ 'sylius.ui.move_up'|trans }}
|
||||
</div>
|
||||
<div class="item sylius-taxon-move-down" data-action="move taxon" data-id="{{ taxon.id }}" data-position="{{ taxon.position }}">
|
||||
<i class="icon arrow down"></i>
|
||||
{{ 'sylius.ui.move_down'|trans }}
|
||||
</div>
|
||||
<div class="item sylius-delete-resource" data-url="{{ path('sylius_admin_taxon_delete', { 'id': taxon.id }) ~ '?_format=json' }}" data-success-redirect-url="{{ path('sylius_admin_taxon_index') }}">
|
||||
<i class="delete icon"></i>
|
||||
{{ 'sylius.ui.delete'|trans }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui mini buttons">
|
||||
{{ buttons.create(path('sylius_admin_taxon_create_for_parent', { 'id': taxon.id }), 'sylius.ui.add'|trans) }}
|
||||
{{ buttons.edit(path('sylius_admin_taxon_update', { 'id': taxon.id }), null, null, false) }}
|
||||
{{ buttons.delete(path('sylius_admin_taxon_delete', { 'id': taxon.id }), null, null, false) }}
|
||||
</div>
|
||||
<div class="list">
|
||||
<div class="list sylius-sortable-list">
|
||||
{{ tree.render(taxon.children) }}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -27,10 +47,9 @@
|
|||
{% endfor %}
|
||||
{% endmacro %}
|
||||
|
||||
|
||||
{{ buttons.create(path('sylius_admin_taxon_create')) }}
|
||||
<div class="ui segment">
|
||||
<div id="taxons-list" class="ui list">
|
||||
<div class="ui list sylius-sortable-list">
|
||||
{{ tree.render(taxons) }}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ class TaxonRepository extends EntityRepository implements TaxonRepositoryInterfa
|
|||
->leftJoin('o.children', 'children')
|
||||
->andWhere('o.parent = :parent')
|
||||
->addOrderBy('o.root')
|
||||
->addOrderBy('o.left')
|
||||
->addOrderBy('o.position')
|
||||
->setParameter('parent', $taxon)
|
||||
;
|
||||
|
||||
|
|
@ -100,7 +100,7 @@ class TaxonRepository extends EntityRepository implements TaxonRepositoryInterfa
|
|||
->leftJoin('o.translations', 'translation')
|
||||
->where('translation.permalink = :permalink')
|
||||
->setParameter('permalink', $permalink)
|
||||
->orderBy('o.left')
|
||||
->orderBy('o.position')
|
||||
->getQuery()
|
||||
->getOneOrNullResult()
|
||||
;
|
||||
|
|
@ -131,6 +131,7 @@ class TaxonRepository extends EntityRepository implements TaxonRepositoryInterfa
|
|||
$queryBuilder = $this->createQueryBuilder('o');
|
||||
$queryBuilder
|
||||
->andWhere($queryBuilder->expr()->isNull($this->getPropertyName('parent')))
|
||||
->orderBy('o.position')
|
||||
;
|
||||
|
||||
return $queryBuilder->getQuery()->getResult();
|
||||
|
|
@ -144,7 +145,7 @@ class TaxonRepository extends EntityRepository implements TaxonRepositoryInterfa
|
|||
$queryBuilder = $this->createQueryBuilder('o');
|
||||
$queryBuilder
|
||||
->orderBy('o.root')
|
||||
->addOrderBy('o.left')
|
||||
->addOrderBy('o.position')
|
||||
;
|
||||
|
||||
return $queryBuilder->getQuery()->getResult();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace Sylius\Bundle\TaxonomyBundle\Form\Type;
|
||||
|
||||
use Sylius\Bundle\ResourceBundle\Form\Type\AbstractResourceType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
/**
|
||||
* @author Arkadiusz Krakowiak <arkadiusz.krakowiak@lakion.com>
|
||||
*/
|
||||
final class TaxonPositionType extends AbstractResourceType
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder
|
||||
->add('position', IntegerType::class, [
|
||||
'label' => 'sylius.form.taxon.position',
|
||||
])
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'sylius_taxon_position';
|
||||
}
|
||||
}
|
||||
|
|
@ -29,6 +29,7 @@
|
|||
<many-to-one field="parent" target-entity="Sylius\Component\Taxonomy\Model\TaxonInterface" inversed-by="children">
|
||||
<join-column name="parent_id" referenced-column-name="id" nullable="true" on-delete="CASCADE" />
|
||||
<gedmo:tree-parent />
|
||||
<gedmo:sortable-group />
|
||||
</many-to-one>
|
||||
|
||||
<one-to-many field="children" target-entity="Sylius\Component\Taxonomy\Model\TaxonInterface" mapped-by="parent">
|
||||
|
|
@ -36,14 +37,10 @@
|
|||
<cascade-all />
|
||||
</cascade>
|
||||
<order-by>
|
||||
<order-by-field name="left" direction="ASC" />
|
||||
<order-by-field name="position" direction="ASC" />
|
||||
</order-by>
|
||||
</one-to-many>
|
||||
|
||||
<order-by>
|
||||
<order-by-field name="left" direction="ASC" />
|
||||
</order-by>
|
||||
|
||||
<field name="code" column="code" type="string" unique="true" />
|
||||
<field name="left" column="tree_left" type="integer">
|
||||
<gedmo:tree-left />
|
||||
|
|
@ -54,6 +51,9 @@
|
|||
<field name="level" column="tree_level" type="integer">
|
||||
<gedmo:tree-level />
|
||||
</field>
|
||||
<field name="position" type="integer">
|
||||
<gedmo:sortable-position />
|
||||
</field>
|
||||
|
||||
<gedmo:tree type="nested" />
|
||||
</mapped-superclass>
|
||||
|
|
|
|||
|
|
@ -17,6 +17,11 @@
|
|||
<argument type="service" id="sylius.repository.taxon" />
|
||||
<tag name="form.type" alias="sylius_taxon_choice" />
|
||||
</service>
|
||||
<service id="sylius.form.type.taxon_position" class="Sylius\Bundle\TaxonomyBundle\Form\Type\TaxonPositionType">
|
||||
<argument>%sylius.model.taxon.class%</argument>
|
||||
<argument>%sylius.validation_groups.taxon%</argument>
|
||||
<tag name="form.type" alias="sylius_taxon_position" />
|
||||
</service>
|
||||
|
||||
<service id="sylius.factory.taxon.decorated" class="Sylius\Component\Taxonomy\Factory\TaxonFactory"
|
||||
decorates="sylius.factory.taxon" public="false">
|
||||
|
|
|
|||
|
|
@ -65,6 +65,11 @@ class Taxon implements TaxonInterface
|
|||
*/
|
||||
protected $level;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $position;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->initializeTranslationsCollection();
|
||||
|
|
@ -322,4 +327,20 @@ class Taxon implements TaxonInterface
|
|||
{
|
||||
$this->level = $level;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getPosition()
|
||||
{
|
||||
return $this->position;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setPosition($position)
|
||||
{
|
||||
$this->position = $position;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -100,4 +100,14 @@ interface TaxonInterface extends
|
|||
* @param int $level
|
||||
*/
|
||||
public function setLevel($level);
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getPosition();
|
||||
|
||||
/**
|
||||
* @param int $position
|
||||
*/
|
||||
public function setPosition($position);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -187,4 +187,10 @@ final class TaxonSpec extends ObjectBehavior
|
|||
|
||||
$this->removeChild($taxon);
|
||||
}
|
||||
|
||||
function it_has_position()
|
||||
{
|
||||
$this->setPosition(0);
|
||||
$this->getPosition()->shouldReturn(0);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue