diff --git a/README.md b/README.md
index 53299d1e..b4628208 100644
--- a/README.md
+++ b/README.md
@@ -29,6 +29,7 @@
+ [Enqueue command](#enqueue-command)
+ [Consume command](#consume-command)
* [Automatically import data with cron jobs](#automatically-import-data-with-cron-jobs)
+ * [Browsing queue items in the admin](#browsing-queue-items-in-the-admin)
- [Architecture & customization](#architecture---customization)
* [Product Importer](#product-importer)
+ [Taxons resolver](#taxons-resolver)
@@ -405,6 +406,12 @@ It will enqueue the update of all attribute options every hour and it will impor
Both enqueue and consume commands uses a [lock mechanism](https://symfony.com/doc/current/console/lockable_trait.html) which prevents to run them multiple times.
+### Browsing queue items in the admin
+
+You can examine the Akeneo import queue from the admin panel at **Catalog -> Akeneo PIM import**. You can filter and sort items and see their error message:
+
+![Akeneo queue items grid](queue_items_grid.png)
+
## Architecture & customization
This plugin has basically two main entry points:
diff --git a/features/browsing_queue_items.feature b/features/browsing_queue_items.feature
new file mode 100644
index 00000000..efa0f0ba
--- /dev/null
+++ b/features/browsing_queue_items.feature
@@ -0,0 +1,44 @@
+@browsing_queue_items
+Feature: Browsing queue items
+ In order to see the status of imported and not imported items from Akeneo
+ As an Administrator
+ I want to browse the Akeneo items queue
+
+ Background:
+ Given I am logged in as an administrator
+ And there is a not imported item with identifier "braided-hat-m" for the "Product" importer in the Akeneo queue
+ And there is a not imported item with identifier "braided-hat-l" for the "ProductAssociations" importer in the Akeneo queue
+ And there is an already imported item with identifier "braided-hat-s" for the "Product" importer in the Akeneo queue
+
+ @ui
+ Scenario: Browsing all items
+ When I browse Akeneo queue items
+ Then I should see 3 queue items in the list
+
+ @ui
+ Scenario: Browsing not imported items
+ When I browse Akeneo queue items
+ And I choose "No" as an imported filter
+ And I filter
+ Then I should see 2, not imported, queue items in the list
+
+ @ui
+ Scenario: Browsing imported items
+ When I browse Akeneo queue items
+ And I choose "Yes" as an imported filter
+ And I filter
+ Then I should see 1, imported, queue item in the list
+
+ @ui
+ Scenario: Filtering items by importer
+ When I browse Akeneo queue items
+ And I specify "Associations" as an importer filter
+ And I filter
+ Then I should see 1 queue item in the list
+
+ @ui
+ Scenario: Filtering items by identifier
+ When I browse Akeneo queue items
+ And I specify "hat-l" as an identifier filter
+ And I filter
+ Then I should see 1 queue item in the list
diff --git a/queue_items_grid.png b/queue_items_grid.png
new file mode 100644
index 00000000..4cafe34b
Binary files /dev/null and b/queue_items_grid.png differ
diff --git a/src/Menu/AdminMenuListener.php b/src/Menu/AdminMenuListener.php
new file mode 100644
index 00000000..96c8814e
--- /dev/null
+++ b/src/Menu/AdminMenuListener.php
@@ -0,0 +1,25 @@
+getMenu();
+ $catalogMenu = $menu->getChild('catalog');
+ if ($catalogMenu === null) {
+ return;
+ }
+
+ $catalogMenu
+ ->addChild('webgriffe_sylius_akeneo.queue_item', ['route' => 'webgriffe_sylius_akeneo_admin_queue_item_index'])
+ ->setLabel('webgriffe_sylius_akeneo.ui.queue_items')
+ ->setLabelAttribute('icon', 'cloud download')
+ ;
+ }
+}
diff --git a/src/Resources/config/admin_routing.yaml b/src/Resources/config/admin_routing.yaml
new file mode 100644
index 00000000..7b71fafa
--- /dev/null
+++ b/src/Resources/config/admin_routing.yaml
@@ -0,0 +1,15 @@
+webgriffe_sylius_akeneo_admin_queue_item:
+ resource: |
+ alias: webgriffe_sylius_akeneo.queue_item
+ section: admin
+ path: akeneo_queue_items
+ except: ['delete', 'update', 'create', 'show', 'bulkDelete']
+ templates: "@SyliusAdmin\\Crud"
+ redirect: update
+ grid: webgriffe_sylius_akeneo_admin_queue_item
+ vars:
+ all:
+ subheader: webgriffe_sylius_akeneo.ui.manage_akeneo_queue_items
+ index:
+ icon: 'cloud download'
+ type: sylius.resource
diff --git a/src/Resources/config/config.yaml b/src/Resources/config/config.yaml
new file mode 100644
index 00000000..4478b488
--- /dev/null
+++ b/src/Resources/config/config.yaml
@@ -0,0 +1,56 @@
+sylius_resource:
+ resources:
+ webgriffe_sylius_akeneo.queue_item:
+ classes:
+ model: Webgriffe\SyliusAkeneoPlugin\Entity\QueueItem
+ repository: Webgriffe\SyliusAkeneoPlugin\Doctrine\ORM\QueueItemRepository
+
+sylius_grid:
+ grids:
+ webgriffe_sylius_akeneo_admin_queue_item:
+ driver:
+ name: doctrine/orm
+ options:
+ class: Webgriffe\SyliusAkeneoPlugin\Entity\QueueItem
+ sorting:
+ createdAt: desc
+ fields:
+ akeneoEntity:
+ type: string
+ label: webgriffe_sylius_akeneo.ui.importer
+ sortable: ~
+ akeneoIdentifier:
+ type: string
+ label: webgriffe_sylius_akeneo.ui.identifier
+ sortable: ~
+ createdAt:
+ type: datetime
+ label: sylius.ui.created_at
+ sortable: ~
+ importedAt:
+ type: twig
+ label: webgriffe_sylius_akeneo.ui.imported
+ sortable: ~
+ options:
+ template: '@WebgriffeSyliusAkeneoPlugin\QueueItem\Grid\importedAt.html.twig'
+ errorMessage:
+ type: string
+ label: webgriffe_sylius_akeneo.ui.error_message
+ filters:
+ akeneoEntity:
+ type: string
+ label: webgriffe_sylius_akeneo.ui.importer
+ akeneoIdentifier:
+ type: string
+ label: webgriffe_sylius_akeneo.ui.identifier
+ imported:
+ type: exists
+ label: webgriffe_sylius_akeneo.ui.imported
+ options:
+ field: importedAt
+ errorMessage:
+ type: string
+ label: webgriffe_sylius_akeneo.ui.error_message
+ actions:
+ main: ~
+ item: ~
diff --git a/src/Resources/config/services.xml b/src/Resources/config/services.xml
index 300cea54..29954763 100644
--- a/src/Resources/config/services.xml
+++ b/src/Resources/config/services.xml
@@ -61,6 +61,10 @@
+
+
diff --git a/src/Resources/translations/messages.en.yaml b/src/Resources/translations/messages.en.yaml
new file mode 100644
index 00000000..7b77e3f4
--- /dev/null
+++ b/src/Resources/translations/messages.en.yaml
@@ -0,0 +1,10 @@
+webgriffe_sylius_akeneo:
+ ui:
+ queue_items: Akeneo PIM import
+ manage_akeneo_queue_items: Manage Akeneo PIM import items
+ importer: Importer type
+ identifier: Identifier
+ imported: Imported
+ imported_yes: Yes, at %date%
+ imported_no: No
+ error_message: Error message
diff --git a/src/Resources/translations/messages.it.yaml b/src/Resources/translations/messages.it.yaml
new file mode 100644
index 00000000..00f66963
--- /dev/null
+++ b/src/Resources/translations/messages.it.yaml
@@ -0,0 +1,10 @@
+webgriffe_sylius_akeneo:
+ ui:
+ queue_items: Importazione da Akeneo PIM
+ manage_akeneo_queue_items: Gestisci gli elementi di importazione da Akeneo PIM
+ importer: Tipo di import
+ identifier: Identificatore
+ imported: Importato
+ imported_yes: Si, il %date%
+ imported_no: No
+ error_message: Messaggio d'errore
diff --git a/src/Resources/views/QueueItem/Grid/importedAt.html.twig b/src/Resources/views/QueueItem/Grid/importedAt.html.twig
new file mode 100644
index 00000000..66a2cd92
--- /dev/null
+++ b/src/Resources/views/QueueItem/Grid/importedAt.html.twig
@@ -0,0 +1,11 @@
+{% if data %}
+
+
+ {{ 'webgriffe_sylius_akeneo.ui.imported_yes'|trans({'%date%': data|date('Y-m-d H:i:s')}) }}
+
+{% else %}
+
+
+ {{ 'webgriffe_sylius_akeneo.ui.imported_no'|trans }}
+
+{% endif %}
diff --git a/tests/Application/config/packages/webgriffe_sylius_akeneo_plugin.yaml b/tests/Application/config/packages/webgriffe_sylius_akeneo_plugin.yaml
index daffdc70..573f1eb4 100644
--- a/tests/Application/config/packages/webgriffe_sylius_akeneo_plugin.yaml
+++ b/tests/Application/config/packages/webgriffe_sylius_akeneo_plugin.yaml
@@ -1,3 +1,6 @@
+imports:
+ - { resource: "@WebgriffeSyliusAkeneoPlugin/Resources/config/config.yaml" }
+
webgriffe_sylius_akeneo:
api_client:
base_url: 'http://demo.akeneo.com/'
diff --git a/tests/Application/config/routes/webgriffe_sylius_akeneo_plugin.yaml b/tests/Application/config/routes/webgriffe_sylius_akeneo_plugin.yaml
new file mode 100644
index 00000000..4b6b9763
--- /dev/null
+++ b/tests/Application/config/routes/webgriffe_sylius_akeneo_plugin.yaml
@@ -0,0 +1,3 @@
+webgriffe_sylius_akeneo_plugin_admin:
+ resource: "@WebgriffeSyliusAkeneoPlugin/Resources/config/admin_routing.yaml"
+ prefix: /admin
diff --git a/tests/Behat/Context/Setup/QueueContext.php b/tests/Behat/Context/Setup/QueueContext.php
index 10258e1f..caeabc54 100644
--- a/tests/Behat/Context/Setup/QueueContext.php
+++ b/tests/Behat/Context/Setup/QueueContext.php
@@ -27,6 +27,7 @@ public function __construct(
/**
* @Given /^there is one item to import with identifier "([^"]*)" for the "([^"]*)" importer in the Akeneo queue$/
+ * @Given /^there is a not imported item with identifier "([^"]*)" for the "([^"]*)" importer in the Akeneo queue$/
*/
public function thereIsOneProductToImportWithIdentifierInTheAkeneoQueue(string $identifier, string $importer)
{
@@ -50,4 +51,18 @@ public function thereIsOneProductAssociationsToImportWithIdentifierInTheAkeneoQu
$queueItem->setCreatedAt(new \DateTime());
$this->queueItemRepository->add($queueItem);
}
+
+ /**
+ * @Given /^there is an already imported item with identifier "([^"]*)" for the "([^"]*)" importer in the Akeneo queue$/
+ */
+ public function thereIsAnAlreadyImportedItemWithIdentifierForTheImporterInTheAkeneoQueue(string $identifier, string $importer)
+ {
+ /** @var QueueItemInterface $queueItem */
+ $queueItem = $this->queueItemFactory->createNew();
+ $queueItem->setAkeneoEntity($importer);
+ $queueItem->setAkeneoIdentifier($identifier);
+ $queueItem->setCreatedAt(new \DateTime());
+ $queueItem->setImportedAt(new \DateTime());
+ $this->queueItemRepository->add($queueItem);
+ }
}
diff --git a/tests/Behat/Context/Ui/Admin/ManagingQueueItems.php b/tests/Behat/Context/Ui/Admin/ManagingQueueItems.php
new file mode 100644
index 00000000..c1f945da
--- /dev/null
+++ b/tests/Behat/Context/Ui/Admin/ManagingQueueItems.php
@@ -0,0 +1,90 @@
+indexPage = $indexPage;
+ }
+
+ /**
+ * @When /^I browse Akeneo queue items$/
+ */
+ public function iBrowseAkeneoQueueItems(): void
+ {
+ $this->indexPage->open();
+ }
+
+ /**
+ * @Then /^I should see (\d+), not imported, queue items in the list$/
+ */
+ public function iShouldSeeQueueItemsInTheList(int $numberOfItems): void
+ {
+ Assert::same($this->indexPage->countItems(), $numberOfItems);
+ foreach ($this->indexPage->getColumnFields('importedAt') as $columnField) {
+ Assert::eq($columnField, 'No');
+ }
+ }
+
+ /**
+ * @Given /^I choose "([^"]*)" as an imported filter$/
+ */
+ public function iChooseAsAnImportedFilter(string $imported): void
+ {
+ $this->indexPage->chooseImportedFilter($imported);
+ }
+
+ /**
+ * @When /^I filter$/
+ */
+ public function iFilter(): void
+ {
+ $this->indexPage->filter();
+ }
+
+ /**
+ * @Then /^I should see (\d+), imported, queue items? in the list$/
+ */
+ public function iShouldSeeImportedQueueItemInTheList(int $numberOfItems): void
+ {
+ Assert::same($this->indexPage->countItems(), $numberOfItems);
+ foreach ($this->indexPage->getColumnFields('importedAt') as $columnField) {
+ Assert::contains($columnField, 'Yes');
+ }
+ }
+
+ /**
+ * @When /^I specify "([^"]*)" as an importer filter$/
+ */
+ public function iSpecifyAsAnImporterFilter(string $importer): void
+ {
+ $this->indexPage->specifyImporterFilter($importer);
+ }
+
+ /**
+ * @Then /^I should see (\d+) queue items? in the list$/
+ */
+ public function iShouldSeeQueueItemInTheList(int $numberOfItems): void
+ {
+ Assert::same($this->indexPage->countItems(), $numberOfItems);
+ }
+
+ /**
+ * @Given /^I specify "([^"]*)" as an identifier filter$/
+ */
+ public function iSpecifyAsAnIdentifierFilter(string $identifier): void
+ {
+ $this->indexPage->specifyIdentifierFilter($identifier);
+ }
+}
diff --git a/tests/Behat/Page/Admin/QueueItem/IndexPage.php b/tests/Behat/Page/Admin/QueueItem/IndexPage.php
new file mode 100644
index 00000000..c565adf3
--- /dev/null
+++ b/tests/Behat/Page/Admin/QueueItem/IndexPage.php
@@ -0,0 +1,37 @@
+getElement('filter_imported')->selectOption($imported);
+ }
+
+ public function specifyImporterFilter(string $importer): void
+ {
+ $this->getElement('filter_importer')->setValue($importer);
+ }
+
+ public function specifyIdentifierFilter(string $identifier): void
+ {
+ $this->getElement('filter_identifier')->setValue($identifier);
+ }
+
+ protected function getDefinedElements(): array
+ {
+ return array_merge(
+ parent::getDefinedElements(),
+ [
+ 'filter_imported' => '#criteria_imported',
+ 'filter_importer' => '#criteria_akeneoEntity_value',
+ 'filter_identifier' => '#criteria_akeneoIdentifier_value',
+ ]
+ );
+ }
+}
diff --git a/tests/Behat/Page/Admin/QueueItem/IndexPageInterface.php b/tests/Behat/Page/Admin/QueueItem/IndexPageInterface.php
new file mode 100644
index 00000000..bb625e15
--- /dev/null
+++ b/tests/Behat/Page/Admin/QueueItem/IndexPageInterface.php
@@ -0,0 +1,16 @@
+
-
+
-
+
-
+
-
+
-
+
-
+
-
+
%webgriffe_sylius_akeneo.temporary_directory%
%webgriffe_sylius_akeneo.temporary_files_prefix%
-
+
+
+
+
+
+
+
+ webgriffe_sylius_akeneo_admin_queue_item_index
+
diff --git a/tests/Behat/Resources/suites.yml b/tests/Behat/Resources/suites.yml
index 8386a530..f2e8018b 100644
--- a/tests/Behat/Resources/suites.yml
+++ b/tests/Behat/Resources/suites.yml
@@ -7,13 +7,13 @@ default:
- sylius.behat.context.setup.product
- sylius.behat.context.setup.channel
- sylius.behat.context.setup.locale
- - webgriffe_sylius_akeneo.context.setup.queue
+ - webgriffe_sylius_akeneo.behat.context.setup.queue
- - webgriffe_sylius_akeneo.context.cli.consume_command
+ - webgriffe_sylius_akeneo.behat.context.cli.consume_command
- - webgriffe_sylius_akeneo.context.db.product
- - webgriffe_sylius_akeneo.context.db.queue
- - webgriffe_sylius_akeneo.context.system.filesystem
+ - webgriffe_sylius_akeneo.behat.context.db.product
+ - webgriffe_sylius_akeneo.behat.context.db.queue
+ - webgriffe_sylius_akeneo.behat.context.system.filesystem
filters:
tags: "@importing_products && @cli"
@@ -25,12 +25,12 @@ default:
- sylius.behat.context.setup.product
- sylius.behat.context.setup.product_association
- sylius.behat.context.setup.channel
- - webgriffe_sylius_akeneo.context.setup.queue
+ - webgriffe_sylius_akeneo.behat.context.setup.queue
- - webgriffe_sylius_akeneo.context.cli.consume_command
+ - webgriffe_sylius_akeneo.behat.context.cli.consume_command
- - webgriffe_sylius_akeneo.context.db.product
- - webgriffe_sylius_akeneo.context.db.queue
+ - webgriffe_sylius_akeneo.behat.context.db.product
+ - webgriffe_sylius_akeneo.behat.context.db.queue
filters:
tags: "@importing_product_associations && @cli"
@@ -41,15 +41,15 @@ default:
- sylius.behat.context.transform.date_time
- - webgriffe_sylius_akeneo.context.setup.akeneo
- - webgriffe_sylius_akeneo.context.setup.queue
+ - webgriffe_sylius_akeneo.behat.context.setup.akeneo
+ - webgriffe_sylius_akeneo.behat.context.setup.queue
- - webgriffe_sylius_akeneo.context.cli.enqueue_command
+ - webgriffe_sylius_akeneo.behat.context.cli.enqueue_command
- - webgriffe_sylius_akeneo.context.db.queue
+ - webgriffe_sylius_akeneo.behat.context.db.queue
- - webgriffe_sylius_akeneo.context.system.filesystem
- - webgriffe_sylius_akeneo.context.system.datetime
+ - webgriffe_sylius_akeneo.behat.context.system.filesystem
+ - webgriffe_sylius_akeneo.behat.context.system.datetime
filters:
tags: "@enqueuing_generic_items && @cli"
@@ -60,15 +60,15 @@ default:
- sylius.behat.context.transform.date_time
- - webgriffe_sylius_akeneo.context.setup.akeneo
- - webgriffe_sylius_akeneo.context.setup.queue
+ - webgriffe_sylius_akeneo.behat.context.setup.akeneo
+ - webgriffe_sylius_akeneo.behat.context.setup.queue
- - webgriffe_sylius_akeneo.context.cli.enqueue_command
+ - webgriffe_sylius_akeneo.behat.context.cli.enqueue_command
- - webgriffe_sylius_akeneo.context.db.queue
+ - webgriffe_sylius_akeneo.behat.context.db.queue
- - webgriffe_sylius_akeneo.context.system.filesystem
- - webgriffe_sylius_akeneo.context.system.datetime
+ - webgriffe_sylius_akeneo.behat.context.system.filesystem
+ - webgriffe_sylius_akeneo.behat.context.system.datetime
filters:
tags: "@enqueuing_products && @cli"
@@ -79,16 +79,27 @@ default:
- sylius.behat.context.transform.date_time
- - webgriffe_sylius_akeneo.context.setup.akeneo
- - webgriffe_sylius_akeneo.context.setup.queue
+ - webgriffe_sylius_akeneo.behat.context.setup.akeneo
+ - webgriffe_sylius_akeneo.behat.context.setup.queue
- - webgriffe_sylius_akeneo.context.cli.enqueue_command
+ - webgriffe_sylius_akeneo.behat.context.cli.enqueue_command
- - webgriffe_sylius_akeneo.context.db.queue
+ - webgriffe_sylius_akeneo.behat.context.db.queue
- - webgriffe_sylius_akeneo.context.system.filesystem
- - webgriffe_sylius_akeneo.context.system.datetime
+ - webgriffe_sylius_akeneo.behat.context.system.filesystem
+ - webgriffe_sylius_akeneo.behat.context.system.datetime
filters:
tags: "@enqueuing_products_associations && @cli"
+ ui_browsing_queue_items:
+ contexts:
+ - sylius.behat.context.hook.doctrine_orm
+
+ - sylius.behat.context.setup.admin_security
+ - webgriffe_sylius_akeneo.behat.context.setup.queue
+
+ - webgriffe_sylius_akeneo.behat.context.ui.admin.managing_queue_items
+
+ filters:
+ tags: "@browsing_queue_items && @ui"