diff --git a/composer.json b/composer.json index ae5ae93df1..197b65d1ff 100644 --- a/composer.json +++ b/composer.json @@ -130,6 +130,7 @@ "symfony/templating": "^6.4.0", "symfony/translation": "^6.4.0", "symfony/translation-contracts": "^2.5.2", + "symfony/ux-autocomplete": "2.x-dev", "symfony/ux-live-component": "^2.12", "symfony/ux-twig-component": "^2.11.2", "symfony/twig-bundle": "^6.4.0", diff --git a/config/bundles.php b/config/bundles.php index 1800acfb62..780e8892b8 100644 --- a/config/bundles.php +++ b/config/bundles.php @@ -63,4 +63,5 @@ return [ Symfony\UX\StimulusBundle\StimulusBundle::class => ['all' => true], Symfony\UX\LiveComponent\LiveComponentBundle::class => ['all' => true], Sylius\TwigHooks\TwigHooksBundle::class => ['all' => true], + Symfony\UX\Autocomplete\AutocompleteBundle::class => ['all' => true], ]; diff --git a/config/routes/ux_autocomplete.yaml b/config/routes/ux_autocomplete.yaml new file mode 100644 index 0000000000..da6b261a6b --- /dev/null +++ b/config/routes/ux_autocomplete.yaml @@ -0,0 +1,3 @@ +ux_autocomplete: + resource: '@AutocompleteBundle/config/routes.php' + prefix: '/autocomplete' diff --git a/package.json b/package.json index ee7c5a9ce3..b7c873ab93 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "@hotwired/stimulus": "^3.0.0", "@semantic-ui-react/css-patch": "^1.1.2", "@symfony/stimulus-bridge": "^3.2.0", + "@symfony/ux-autocomplete": "file:vendor/symfony/ux-autocomplete/assets", "@symfony/webpack-encore": "^3.1.0", "eslint": "^8.23.0", "eslint-config-airbnb-base": "^15.0.0", @@ -39,6 +40,7 @@ "eslint-plugin-import": "^2.26.0", "sass": "^1.54.8", "sass-loader": "^13.0.0", + "tom-select": "^2.2.2", "yargs": "^17.5.1" }, "engines": { diff --git a/src/Sylius/Bundle/AdminBundle/Autocompleter/ProductAttributeAutocompleter.php b/src/Sylius/Bundle/AdminBundle/Autocompleter/ProductAttributeAutocompleter.php new file mode 100644 index 0000000000..286a76902d --- /dev/null +++ b/src/Sylius/Bundle/AdminBundle/Autocompleter/ProductAttributeAutocompleter.php @@ -0,0 +1,55 @@ +productAttributeClass; + } + + public function createFilteredQueryBuilder(EntityRepository $repository, string $query): QueryBuilder + { + return $repository->createQueryBuilder('o') + ->andWhere('o.code LIKE :query') + ->setParameter('query', '%' . $query . '%') + ; + } + + public function getLabel(object $entity): string + { + return $entity->getName(); + } + + public function getValue(object $entity): mixed + { + return $entity->getCode(); + } + + public function isGranted(Security $security): bool + { + return true; + } +} diff --git a/src/Sylius/Bundle/AdminBundle/Resources/assets/bootstrap.js b/src/Sylius/Bundle/AdminBundle/Resources/assets/bootstrap.js index d4d8b947d1..f1f8fc3044 100644 --- a/src/Sylius/Bundle/AdminBundle/Resources/assets/bootstrap.js +++ b/src/Sylius/Bundle/AdminBundle/Resources/assets/bootstrap.js @@ -12,6 +12,7 @@ import LiveController from '@symfony/ux-live-component'; import '@symfony/ux-live-component/styles/live.css'; import SlugController from "./controllers/SlugController"; import TaxonSlugController from "./controllers/TaxonSlugController"; +import AutocompleteController from '@symfony/ux-autocomplete'; // Registers Stimulus controllers from controllers.json and in the controllers/ directory export const app = startStimulusApp(require.context( @@ -23,3 +24,4 @@ export const app = startStimulusApp(require.context( app.register('live', LiveController); app.register('slug', SlugController); app.register('taxon-slug', TaxonSlugController); +app.register('symfony--ux-autocomplete--autocomplete', AutocompleteController) diff --git a/src/Sylius/Bundle/AdminBundle/Resources/assets/controllers.json b/src/Sylius/Bundle/AdminBundle/Resources/assets/controllers.json index e2ce9b5cbc..8df4e2214b 100644 --- a/src/Sylius/Bundle/AdminBundle/Resources/assets/controllers.json +++ b/src/Sylius/Bundle/AdminBundle/Resources/assets/controllers.json @@ -1,4 +1,17 @@ { - "controllers": [], + "controllers": { + "@symfony/ux-autocomplete": { + "autocomplete": { + "main": "dist/controller.js", + "webpackMode": "eager", + "fetch": "eager", + "enabled": true, + "autoimport": { + "tom-select/dist/css/tom-select.default.css": false, + "tom-select/dist/css/tom-select.bootstrap5.css": true + } + } + } + }, "entrypoints": [] } diff --git a/src/Sylius/Bundle/AdminBundle/Resources/assets/styles/main.scss b/src/Sylius/Bundle/AdminBundle/Resources/assets/styles/main.scss index 0783411648..7e301a57c9 100644 --- a/src/Sylius/Bundle/AdminBundle/Resources/assets/styles/main.scss +++ b/src/Sylius/Bundle/AdminBundle/Resources/assets/styles/main.scss @@ -16,6 +16,12 @@ //@import "@tabler/core/src/scss/tabler-flags.scss"; @import "_flags.scss"; +body { + --bs-body-bg: #{$body-bg}; + --bs-tertiary-bg: #{$body-bg}; + --bs-body-color: #{$body-color}; +} + @import "alert"; @import "avatar"; @import "collapse"; diff --git a/src/Sylius/Bundle/AdminBundle/Resources/config/services/autocompleter.xml b/src/Sylius/Bundle/AdminBundle/Resources/config/services/autocompleter.xml new file mode 100644 index 0000000000..74a3e10ab2 --- /dev/null +++ b/src/Sylius/Bundle/AdminBundle/Resources/config/services/autocompleter.xml @@ -0,0 +1,21 @@ + + + + + + + + %sylius.model.product_attribute.class% + + + + diff --git a/src/Sylius/Bundle/AdminBundle/Resources/config/services/twig_component.xml b/src/Sylius/Bundle/AdminBundle/Resources/config/services/twig_component.xml index bb4db5cab3..07a6759b32 100644 --- a/src/Sylius/Bundle/AdminBundle/Resources/config/services/twig_component.xml +++ b/src/Sylius/Bundle/AdminBundle/Resources/config/services/twig_component.xml @@ -59,5 +59,11 @@ Sylius\Bundle\ProductBundle\Form\Type\ProductType + + + + + + diff --git a/src/Sylius/Bundle/AdminBundle/Resources/views/Product/Form/Sections/_attributes.html.twig b/src/Sylius/Bundle/AdminBundle/Resources/views/Product/Form/Sections/_attributes.html.twig index 49957aa0e1..95e5c8d1e5 100644 --- a/src/Sylius/Bundle/AdminBundle/Resources/views/Product/Form/Sections/_attributes.html.twig +++ b/src/Sylius/Bundle/AdminBundle/Resources/views/Product/Form/Sections/_attributes.html.twig @@ -8,6 +8,7 @@
+
diff --git a/src/Sylius/Bundle/AdminBundle/Resources/views/Product/_productAttributeAutocomplete.html.twig b/src/Sylius/Bundle/AdminBundle/Resources/views/Product/_productAttributeAutocomplete.html.twig new file mode 100644 index 0000000000..6ea9a21f7e --- /dev/null +++ b/src/Sylius/Bundle/AdminBundle/Resources/views/Product/_productAttributeAutocomplete.html.twig @@ -0,0 +1,19 @@ +
+
+ + +
+ +
diff --git a/src/Sylius/Bundle/AdminBundle/TwigComponent/Product/FormComponent.php b/src/Sylius/Bundle/AdminBundle/TwigComponent/Product/FormComponent.php index 5f4dc4e260..b7947bfadd 100644 --- a/src/Sylius/Bundle/AdminBundle/TwigComponent/Product/FormComponent.php +++ b/src/Sylius/Bundle/AdminBundle/TwigComponent/Product/FormComponent.php @@ -22,6 +22,7 @@ use Symfony\Component\Form\FormInterface; use Symfony\UX\LiveComponent\Attribute\AsLiveComponent; use Symfony\UX\LiveComponent\Attribute\LiveAction; use Symfony\UX\LiveComponent\Attribute\LiveArg; +use Symfony\UX\LiveComponent\Attribute\LiveListener; use Symfony\UX\LiveComponent\Attribute\LiveProp; use Symfony\UX\LiveComponent\DefaultActionTrait; use Symfony\UX\LiveComponent\LiveCollectionTrait; @@ -83,4 +84,18 @@ final class FormComponent $this->formValues['attributes'], ); } + + #[LiveListener('product_attribute_autocomplete:add')] + public function addAttributes(#[LiveArg] array $attributeCodes): void + { + foreach ($attributeCodes as $attributeCode) { + foreach ($this->formValues['translations'] as $localesCode => $translation) { + $this->formValues['attributes'][] = [ + 'attribute' => $attributeCode, + 'localeCode' => $localesCode, + 'value' => '', + ]; + } + } + } } diff --git a/src/Sylius/Bundle/AdminBundle/TwigComponent/Product/ProductAttributeAutocompleteComponent.php b/src/Sylius/Bundle/AdminBundle/TwigComponent/Product/ProductAttributeAutocompleteComponent.php new file mode 100644 index 0000000000..4ee97b5486 --- /dev/null +++ b/src/Sylius/Bundle/AdminBundle/TwigComponent/Product/ProductAttributeAutocompleteComponent.php @@ -0,0 +1,38 @@ +emit('product_attribute_autocomplete:add', ['attributeCodes' => explode(',', $this->attributeCodes)]); + $this->attributeCodes = ''; + $this->dispatchBrowserEvent('product_attribute_autocomplete:clear'); + } +} diff --git a/symfony.lock b/symfony.lock index d2c3476171..9e34df8aab 100644 --- a/symfony.lock +++ b/symfony.lock @@ -870,6 +870,18 @@ "templates/base.html.twig" ] }, + "symfony/ux-autocomplete": { + "version": "2.9999999", + "recipe": { + "repo": "github.com/symfony/recipes", + "branch": "main", + "version": "2.6", + "ref": "07d9602b7231ba355f484305d6cea58310c01741" + }, + "files": [ + "config/routes/ux_autocomplete.yaml" + ] + }, "symfony/ux-live-component": { "version": "2.12", "recipe": {